taskman.inc
mxlgv_KolibriDev/src/kernel/core/taskman.inc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                              ;;
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
;;  Distributed under terms of the GNU General Public License.  ;;
;;                                                              ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

$Revision: 8093 $


GREEDY_KERNEL  = 0

struct  APP_HEADER_00_
        banner          dq ?
        version         dd ?    ;+8
        start           dd ?    ;+12
        i_end           dd ?    ;+16
        mem_size        dd ?    ;+20
        i_param         dd ?    ;+24
ends

struct  APP_HEADER_01_
        banner          dq ?
        version         dd ?    ;+8
        start           dd ?    ;+12
        i_end           dd ?    ;+16
        mem_size        dd ?    ;+20
        stack_top       dd ?    ;+24
        i_param         dd ?    ;+28
        i_icon          dd ?    ;+32
ends

struct  APP_HDR
        cmdline         rd 1    ;0x00
        path            rd 1    ;0x04
        eip             rd 1    ;0x08
        esp             rd 1    ;0x0C
        _edata          rd 1    ;0x10
        _emem           rd 1    ;0x14
        img_base        rd 1    ;0x18
        img_size        rd 1
        filename_size   rd 1
        cmdline_size    rd 1
        path_string     rd 1
ends

macro _clear_ op
{  mov ecx, op/4
        xor     eax, eax
        cld
        rep stosd
}

align 4
_strnlen:
        mov     edx, ecx
        xor     eax, eax
        repne scasb
        jne     @F
        inc     ecx
@@:
        mov     eax, edx
        sub     eax, ecx
        retn

fs_execute_from_sysdir:
        xor     ebx, ebx
fs_execute_from_sysdir_param:
        stdcall kernel_alloc, maxPathLength
        push    eax ebx
        mov     esi, ebp
        mov     edi, eax
        xor     eax, eax
        call    getFullPath
        pop     ecx ebx
        xor     edx, edx
proc fs_execute
; edx = flags
; ecx -> cmdline
; ebx -> absolute file path
; eax = string length
    locals
        cmdline         rd  1
        flags           rd  1
        slot            rd  1
        slot_base       rd  1
; app header data
        hdr_cmdline     rd  1
        hdr_path        rd  1
        hdr_eip         rd  1
        hdr_esp         rd  1
        hdr_edata       rd  1
        hdr_emem        rd  1
        file_base       rd  1
        file_size       rd  1
        filename_size   rd  1
        cmdline_size    rd  1
        path_string     rd  1
    endl

        mov     [flags], edx
        mov     [cmdline], ecx
        mov     [path_string], ebx
        mov     [filename_size], eax
        mov     esi, -ERROR_FILE_NOT_FOUND
        test    eax, eax
        jz      .err_file
        stdcall load_file, ebx
        test    eax, eax
        jz      .err_file

        mov     [file_base], eax
        mov     [file_size], ebx
        lea     ebx, [hdr_cmdline]
        call    test_app_header
        mov     esi, -0x1F
        test    eax, eax
        jz      .err_hdr

        call    lock_application_table
        call    alloc_thread_slot
        mov     esi, -0x20  ; too many processes
        test    eax, eax
        jz      .err_0

        mov     [slot], eax
        shl     eax, 8
        lea     edi, [SLOT_BASE+eax]
        mov     [slot_base], edi
; clean extended information about process
        mov     ecx, sizeof.APPDATA/4
        xor     eax, eax
        cld
        rep stosd
; write application name
        stdcall strrchr, [path_string], '/'
        lea     esi, [eax+1]    ; -> name without path
        mov     ecx, 11
        mov     edi, [slot_base]
@@:
        call    utf8to16
        call    uni2ansi_char
        cmp     al, '.'
        jz      @f
        test    al, al
        jz      @f
        stosb
        loop    @b
@@:
        mov     edi, [cmdline]
        xor     eax, eax
        test    edi, edi
        jz      @f
        mov     ecx, 65535
        call    _strnlen
        cmp     eax, 256
        jb      @f
        lea     ebx, [eax+1]
        add     [hdr_emem], ebx
@@:
        mov     [cmdline_size], eax
        stdcall create_process, [hdr_emem]
        mov     esi, -30    ; no memory
        test    eax, eax
        jz      .err_hdr

        mov     ebx, [sys_proc+LHEAD.prev]
        __list_add eax, ebx, sys_proc
        mov     ebx, [hdr_emem]
        mov     [eax+PROC.mem_used], ebx
        mov     ebx, [slot_base]
        mov     [ebx+APPDATA.process], eax
        lea     edx, [ebx+APPDATA.list]
        lea     ecx, [eax+PROC.thr_list]
        list_add_tail edx, ecx
        mov     eax, [cmdline_size]
        add     eax, sizeof.APP_HDR
        stdcall kernel_alloc, eax
        mov     [ebx+APPDATA.exec_params], eax
        mov     edi, eax
        lea     esi, [hdr_cmdline]
        mov     ecx, sizeof.APP_HDR/4
        rep movsd
        mov     ecx, [cmdline_size]
        mov     esi, [cmdline]
        rep movsb
        lea     eax, [hdr_cmdline]
        stdcall set_app_params , [slot], eax, [flags]
        mov     eax, [process_number]   ;set result
        call    unlock_application_table
        ret

.err_0:
        call    unlock_application_table
.err_hdr:
        stdcall kernel_free, [file_base]
.err_file:
        stdcall kernel_free, [path_string]
        mov     eax, esi
        ret
endp

align 4
test_app_header:
       virtual at eax
         APP_HEADER_00 APP_HEADER_00_
       end virtual
       virtual at eax
         APP_HEADER_01 APP_HEADER_01_
       end virtual

        cmp     dword [eax], 'MENU'
        jne     .fail
        cmp     word [eax+4], 'ET'
        jne     .fail

        cmp     [eax+6], word '00'
        jne     .check_01_header

        mov     ecx, [APP_HEADER_00.start]
        mov     [ebx+APP_HDR.eip], ecx
        mov     edx, [APP_HEADER_00.mem_size]
        mov     [ebx+APP_HDR._emem], edx
        shr     edx, 1
        sub     edx, 0x10
        mov     [ebx+APP_HDR.esp], edx
        mov     ecx, [APP_HEADER_00.i_param]
        mov     [ebx+APP_HDR.cmdline], ecx
        mov     [ebx+APP_HDR.path], 0
        mov     edx, [APP_HEADER_00.i_end]
        mov     [ebx+APP_HDR._edata], edx
        ret

 .check_01_header:

        cmp     [eax+6], word '01'
        je      @f
        cmp     [eax+6], word '02'
        jne     .fail
@@:
        mov     ecx, [APP_HEADER_01.start]
        mov     [ebx+0x08], ecx
        mov     edx, [APP_HEADER_01.mem_size]

; \begin{diamond}[20.08.2006]
; sanity check (functions 19,58 load app_i_end bytes and that must
; fit in allocated memory to prevent kernel faults)
        cmp     edx, [APP_HEADER_01.i_end]
        jb      .fail
; \end{diamond}[20.08.2006]

        mov     [ebx+APP_HDR._emem], edx
        mov     ecx, [APP_HEADER_01.stack_top]
        mov     [ebx+APP_HDR.esp], ecx
        mov     edx, [APP_HEADER_01.i_param]
        mov     [ebx+APP_HDR.cmdline], edx
        mov     ecx, [APP_HEADER_01.i_icon]
        mov     [ebx+APP_HDR.path], ecx
        mov     edx, [APP_HEADER_01.i_end]
        mov     [ebx+APP_HDR._edata], edx
        ret
.fail:
        xor     eax, eax
        ret

align 4
alloc_thread_slot:
;input:
;  none
;result:
;  eax=[new_thread_slot]<>0 - ok
;      0 - failed.
;This function find least empty slot.
;It doesn't increase [TASK_COUNT]!


        mov     edx, thr_slot_map
        pushfd
        cli
.l1:
        bsf     eax, [edx]
        jnz     .found
        add     edx, 4
        cmp     edx, thr_slot_map+32
        jb      .l1

        popfd
        xor     eax, eax
        ret
.found:
        btr     [edx], eax
        sub     edx, thr_slot_map
        lea     eax, [eax+edx*8]
        popfd
        ret

align 4
proc create_process stdcall, app_size:dword
       locals
         process     dd ?
         app_tabs    dd ?
       endl

        push    ebx
        push    esi
        push    edi

        xor     eax, eax
        mov     [process], eax

        mov     eax, [app_size]
        add     eax, 0x3FFFFF
        shr     eax, 22
        mov     [app_tabs], eax

        stdcall kernel_alloc, 0x2000
        test    eax, eax
        jz      .fail
        mov     [process], eax

        lea     edi, [eax+PROC.heap_lock]
        mov     ecx, (PROC.ht_free-PROC.heap_lock)/4

        list_init eax
        add     eax, PROC.thr_list
        list_init eax

        xor     eax, eax
        cld
        rep stosd

        mov     [edi], dword (PROC.pdt_0 - PROC.htab)/4 - 3
        mov     [edi+4], dword 3           ;reserve handles for stdin stdout and stderr
        mov     ecx, (PROC.pdt_0 - PROC.htab)/4
        add     edi, 8
        inc     eax
@@:
        stosd
        inc     eax
        cmp     eax, ecx
        jbe     @B

        mov     eax, edi
        call    get_pg_addr
        mov     [edi-4096+PROC.pdt_0_phys], eax

        mov     ecx, (OS_BASE shr 20)/4
        xor     eax, eax
        rep stosd

        mov     ecx, (OS_BASE shr 20)/4
        mov     esi, sys_proc+PROC.pdt_0+(OS_BASE shr 20)
        rep movsd

        mov     eax, [edi-8192+PROC.pdt_0_phys]
        or      eax, PG_SWR
        mov     [edi-4096+(page_tabs shr 20)], eax

        lea     edx, [edi-4096]
        mov     esi, [app_tabs]

.alloc_page_dir:
        call    alloc_page
        test    eax, eax
        jz      .fail
        or      eax, PG_UWR
        mov     [edx], eax

        mov     edi, [tmp_task_ptab]
        stdcall map_page, edi, eax, PG_SWR
        mov     ecx, 1024
        xor     eax, eax
        rep stosd

        add     edx, 4
        dec     esi
        jnz     .alloc_page_dir

        stdcall map_page, [tmp_task_ptab], 0, PG_UNMAP
        mov     eax, [process]

        pop     edi
        pop     esi
        pop     ebx
        ret
.fail:
        mov     ecx, [process]
        jcxz    @F

        call    destroy_process
@@:
        xor     eax, eax
        pop     edi
        pop     esi
        pop     ebx
        ret
endp

align 4
proc destroy_page_table stdcall, pg_tab:dword

        push    esi

        mov     esi, [pg_tab]
        mov     ecx, 1024
.free:
        mov     eax, [esi]
        test    eax, 1
        jz      .next
        test    eax, 2
        jz      .next
        test    eax, 1 shl 9
        jnz     .next                     ;skip shared pages
        call    free_page
.next:
        add     esi, 4
        dec     ecx
        jnz     .free
        pop     esi
        ret
endp

align 4
destroy_process: ;fastcall ecx= ptr to process

        lea     eax, [ecx+PROC.thr_list]
        cmp     eax, [eax+LHEAD.next]
        jne     .exit

align 4
.internal:
        push    ecx

        mov     esi, ecx
        list_del esi

        mov     esi, [esi+PROC.dlls_list_ptr]
        call    destroy_all_hdlls

        mov     esi, [esp]
        add     esi, PROC.pdt_0
        mov     edi, (0x80000000 shr 20)/4
.destroy:
        mov     eax, [esi]
        test    eax, 1
        jz      .next
        and     eax, not 0xFFF
        stdcall map_page, [tmp_task_ptab], eax, PG_SWR
        stdcall destroy_page_table, [tmp_task_ptab]
        mov     eax, [esi]
        call    free_page
.next:
        add     esi, 4
        dec     edi
        jnz     .destroy

        call    kernel_free     ;ecx still in stack
        stdcall map_page, [tmp_task_ptab], 0, PG_UNMAP
.exit:
        ret

align 4
get_pid:
        mov     eax, [TASK_BASE]
        mov     eax, [eax+TASKDATA.pid]
        ret

pid_to_slot:
;Input:
;  eax - pid of process
;Output:
;  eax - slot of process or 0 if process don't exists
;Search process by PID.
        push    ebx
        push    ecx
        mov     ebx, [TASK_COUNT]
        shl     ebx, 5
        mov     ecx, 2*32

.loop:
;ecx=offset of current process info entry
;ebx=maximum permitted offset
        cmp     byte [CURRENT_TASK+ecx+0xa], 9
        jz      .endloop ;skip empty slots
        cmp     [CURRENT_TASK+ecx+0x4], eax;check PID
        jz      .pid_found
.endloop:
        add     ecx, 32
        cmp     ecx, ebx
        jle     .loop

        pop     ecx
        pop     ebx
        xor     eax, eax
        ret

.pid_found:
        shr     ecx, 5
        mov     eax, ecx ;convert offset to index of slot
        pop     ecx
        pop     ebx
        ret

check_region:
;input:
;  esi - start of buffer
;  edx - size of buffer
;result:
;  eax = 1 region lays in app memory
;  eax = 0 region don't lays in app memory

        mov     eax, 1
        ret
if 0
        mov     eax, [CURRENT_TASK]
;     jmp  check_process_region
;-----------------------------------------------------------------------------
;check_process_region:
;input:
;  eax - slot
;  esi - start of buffer
;  edx - size of buffer
;result:
;  eax = 1 region lays in app memory
;  eax = 0 region don't lays in app memory

        test    edx, edx
        jle     .ok
        shl     eax, 5
        cmp     word [CURRENT_TASK+eax+0xa], 0
        jnz     .failed
        shl     eax, 3
        mov     eax, [SLOT_BASE+eax+0xb8]
        test    eax, eax
        jz      .failed

        mov     eax, 1
        ret
.ok:
        mov     eax, 1
        ret
.failed:
        xor     eax, eax
        ret
end if

align 4
proc read_process_memory
;Input:
;  eax - process slot
;  ecx - buffer address
;  edx - buffer size
;  esi - start address in other process
;Output:
;  eax - number of bytes read.
       locals
         slot   dd ?
         buff   dd ?
         r_count    dd ?
         offset dd ?
         tmp_r_cnt  dd ?
       endl

        mov     [slot], eax
        mov     [buff], ecx
        and     [r_count], 0
        mov     [tmp_r_cnt], edx
        mov     [offset], esi

        pushad
.read_mem:
        mov     edx, [offset]
        mov     ebx, [tmp_r_cnt]

        mov     ecx, 0x400000
        and     edx, 0x3FFFFF
        sub     ecx, edx
        cmp     ecx, ebx
        jbe     @f
        mov     ecx, ebx
@@:
        cmp     ecx, 0x8000
        jna     @F
        mov     ecx, 0x8000
@@:
        mov     ebx, [offset]

        push    ecx
        stdcall map_memEx, [proc_mem_map], \
                [slot], ebx, ecx, PG_READ
        pop     ecx

        mov     esi, [offset]
        and     esi, 0xfff
        sub     eax, esi
        jbe     .ret
        cmp     ecx, eax
        jbe     @f
        mov     ecx, eax
        mov     [tmp_r_cnt], eax
@@:
        add     esi, [proc_mem_map]
        mov     edi, [buff]
        mov     edx, ecx
        rep movsb
        add     [r_count], edx

        add     [offset], edx
        sub     [tmp_r_cnt], edx
        jnz     .read_mem
.ret:
        popad
        mov     eax, [r_count]
        ret
endp

align 4
proc write_process_memory
;Input:
;  eax - process slot
;  ecx - buffer address
;  edx - buffer size
;  esi - start address in other process
;Output:
;  eax - number of bytes written

       locals
         slot   dd ?
         buff   dd ?
         w_count    dd ?
         offset dd ?
         tmp_w_cnt  dd ?
       endl

        mov     [slot], eax
        mov     [buff], ecx
        and     [w_count], 0
        mov     [tmp_w_cnt], edx
        mov     [offset], esi

        pushad
.read_mem:
        mov     edx, [offset]
        mov     ebx, [tmp_w_cnt]

        mov     ecx, 0x400000
        and     edx, 0x3FFFFF
        sub     ecx, edx
        cmp     ecx, ebx
        jbe     @f
        mov     ecx, ebx
@@:
        cmp     ecx, 0x8000
        jna     @F
        mov     ecx, 0x8000
@@:
        mov     ebx, [offset]
        push    ecx
        stdcall map_memEx, [proc_mem_map], \
                [slot], ebx, ecx, PG_SWR
        pop     ecx

        mov     edi, [offset]
        and     edi, 0xfff
        sub     eax, edi
        jbe     .ret
        cmp     ecx, eax
        jbe     @f
        mov     ecx, eax
        mov     [tmp_w_cnt], eax
@@:
        add     edi, [proc_mem_map]
        mov     esi, [buff]
        mov     edx, ecx
        rep movsb

        add     [w_count], edx
        add     [offset], edx
        sub     [tmp_w_cnt], edx
        jnz     .read_mem
.ret:
        popad
        mov     eax, [w_count]
        ret
endp

;ebx = 1 - kernel thread
;ecx=thread entry point
;edx=thread stack pointer
;creation flags  0x01 - debugged
;                0x02 - kernel

align 4
proc new_sys_threads
       locals
         slot          dd ?
         flags         dd ?
         app_cmdline   dd ? ;0x00
         app_path      dd ? ;0x04
         app_eip       dd ? ;0x08
         app_esp       dd ? ;0x0C
         app_mem       dd ? ;0x10
       endl

        shl     ebx, 1
        mov     [flags], ebx

        xor     eax, eax
        mov     [app_eip], ecx
        mov     [app_cmdline], eax
        mov     [app_esp], edx
        mov     [app_path], eax

        call    lock_application_table

        call    alloc_thread_slot
        test    eax, eax
        jz      .failed

        mov     [slot], eax

        mov     esi, [current_slot]
        mov     ebx, esi      ;ebx=esi - pointer to extended information about current thread

        mov     edi, eax
        shl     edi, 8
        add     edi, SLOT_BASE
        mov     edx, edi      ;edx=edi - pointer to extended infomation about new thread
        mov     ecx, sizeof.APPDATA/4
        xor     eax, eax
        cld
        rep stosd             ;clean extended information about new thread
        mov     esi, ebx
        mov     edi, edx
        mov     ecx, 11
        rep movsb             ;copy process name


        mov     eax, [ebx+APPDATA.tls_base]
        test    eax, eax
        jz      @F

        push    edx
        stdcall user_alloc, 4096
        pop     edx
        test    eax, eax
        jz      .failed1;eax=0
@@:
        mov     [edx+APPDATA.tls_base], eax

        mov     eax, [ebx+APPDATA.process]
        mov     [edx+APPDATA.process], eax

        lea     ebx, [edx+APPDATA.list]
        lea     ecx, [eax+PROC.thr_list]
        list_add_tail ebx, ecx               ;add thread to process child's list

        lea     eax, [app_cmdline]
        stdcall set_app_params , [slot], eax, [flags]

        mov     eax, [process_number]           ;set result
        call    unlock_application_table
        ret
.failed:
        xor     eax, eax
.failed1:
        call    unlock_application_table
        dec     eax     ;-1
        ret
endp

proc map_process_image stdcall, img_size:dword, file_base:dword, file_size:dword

        mov     edx, [img_size]
        mov     esi, [file_base]
        mov     ecx, [file_size]
        add     edx, 4095
        add     ecx, 4095
        shr     edx, 12        ; total pages
        shr     ecx, 12        ; image pages

        mov     edi, page_tabs
        shr     esi, 10
        add     esi, edi

.map_image:
        lodsd
        and     eax, -4096
        or      eax, PG_UWR
        stosd
        dec     edx
        loop    .map_image

        test    edx, edx
        jz      .done
.map_bss:
        call    alloc_page
        test    eax, eax
        jz      .fail

        or      eax, PG_UWR
        stosd
        dec     edx
        jnz     .map_bss

        mov     edi, [file_size]
        mov     ecx, [img_size]
        add     edi, 4095
        and     edi, -4096
        add     ecx, 4095
        and     ecx, -4096
        sub     ecx, edi
        shr     ecx, 2
        xor     eax, eax
        rep stosd
.done:
.fail:
        ret
endp

align 4
common_app_entry:
        mov     ebp, [current_slot]
        mov     ebp, [ebp+APPDATA.exec_params]
        test    ebp, ebp
        jz      .exit
        stdcall map_process_image, [ebp+APP_HDR._emem],\
                [ebp+APP_HDR.img_base], [ebp+APP_HDR.img_size]
        mov     esi, [ebp+APP_HDR.path_string]
        mov     edi, [ebp+APP_HDR.path]
        mov     ecx, [ebp+APP_HDR.filename_size]
        cmp     ecx, 1023
        jc      @f
        mov     ecx, 1022
@@:
        push    esi
        test    edi, edi
        jz      @f
        mov     al, '/'
        stosb
        rep movsb
        mov     byte [edi], 0
@@:
        call    kernel_free
        mov     edi, [ebp+APP_HDR.cmdline]
        test    edi, edi
        jz      .check_tls_header
        lea     esi, [ebp+sizeof.APP_HDR]
        mov     ecx, [ebp+APP_HDR.cmdline_size]
        cmp     ecx, 256
        jb      .copy_cmdline
        mov     edi, [ebp+APP_HDR._emem]
        add     edi, 4095
        and     edi, -4096
        sub     edi, ecx
        dec     edi
        cmp     word [6], '00'
        jne     @f
        mov     [APP_HEADER_00_.i_param], edi
        jmp     .copy_cmdline
@@:
        mov     [APP_HEADER_01_.i_param], edi
.copy_cmdline:
        rep movsb
        mov     byte [edi], 0
.check_tls_header:
        cmp     word [6], '02'
        jne     .cleanup
        call    init_heap
        stdcall user_alloc, 4096
        mov     edx, [current_slot]
        mov     [edx+APPDATA.tls_base], eax
        mov     [tls_data_l+2], ax
        shr     eax, 16
        mov     [tls_data_l+4], al
        mov     [tls_data_l+7], ah
        mov     dx, app_tls
        mov     fs, dx
.cleanup:
        stdcall free_kernel_space, [ebp+APP_HDR.img_base]
        stdcall kernel_free, ebp
        mov     ebx, [current_slot]
        cmp     [ebx+APPDATA.debugger_slot], 0
        je      .exit
        mov     eax, [TASK_BASE]
        mov     [eax+TASKDATA.state], 1
        call    change_task
.exit:
        popad
        iretd

EFL_IF      = 0x0200
EFL_IOPL1   = 0x1000
EFL_IOPL2   = 0x2000
EFL_IOPL3   = 0x3000

align 4
proc set_app_params stdcall,slot:dword, params:dword, flags:dword

       locals
         pl0_stack dd ?
       endl

        mov     eax, [xsave_area_size]
        add     eax, RING0_STACK_SIZE
        stdcall kernel_alloc, eax
        mov     [pl0_stack], eax

        lea     edi, [eax+RING0_STACK_SIZE]

        mov     eax, [slot]
        mov     ebx, eax

        shl     eax, 8
        mov     [eax+SLOT_BASE+APPDATA.fpu_state], edi
        mov     [eax+SLOT_BASE+APPDATA.exc_handler], 0
        mov     [eax+SLOT_BASE+APPDATA.except_mask], 0
        mov     [eax+SLOT_BASE+APPDATA.terminate_protection], 80000001h

;set default io permission map
        mov     ecx, [SLOT_BASE+sizeof.APPDATA+APPDATA.io_map]
        mov     [eax+SLOT_BASE+APPDATA.io_map], ecx
        mov     ecx, [SLOT_BASE+sizeof.APPDATA+APPDATA.io_map+4]
        mov     [eax+SLOT_BASE+APPDATA.io_map+4], ecx

        mov     esi, fpu_data
        mov     ecx, [xsave_area_size]
        add     ecx, 3
        shr     ecx, 2
        rep movsd

        cmp     [TASK_COUNT], ebx
        adc     dword [TASK_COUNT], 0   ; update number of processes
        shl     ebx, 8
        lea     edx, [ebx+SLOT_BASE+APP_EV_OFFSET]
        mov     [SLOT_BASE+APPDATA.fd_ev+ebx], edx
        mov     [SLOT_BASE+APPDATA.bk_ev+ebx], edx

        add     edx, APP_OBJ_OFFSET-APP_EV_OFFSET
        mov     [SLOT_BASE+APPDATA.fd_obj+ebx], edx
        mov     [SLOT_BASE+APPDATA.bk_obj+ebx], edx

        mov     ecx, [def_cursor]
        mov     [SLOT_BASE+APPDATA.cursor+ebx], ecx
        mov     eax, [pl0_stack]
        mov     [SLOT_BASE+APPDATA.pl0_stack+ebx], eax
        add     eax, RING0_STACK_SIZE
        mov     [SLOT_BASE+APPDATA.saved_esp0+ebx], eax

        push    ebx
        stdcall kernel_alloc, maxPathLength
        pop     ebx
        mov     esi, [current_slot]
        mov     esi, [esi+APPDATA.cur_dir]
        mov     ecx, maxPathLength/4
        mov     edi, eax
        mov     [ebx+SLOT_BASE+APPDATA.cur_dir], eax
        rep movsd

        shr     ebx, 3
        mov     dword [CURRENT_TASK+ebx+0x10], 0

        mov     ebx, [slot]
        mov     eax, ebx
        shl     ebx, 5
        lea     ecx, [draw_data+ebx];ecx - pointer to draw data

; set window state to 'normal' (non-minimized/maximized/rolled-up) state
        mov     [ebx+window_data+WDATA.fl_wstate], WSTATE_NORMAL
        mov     [ebx+window_data+WDATA.fl_redraw], 1
        add     ebx, CURRENT_TASK     ;ebx - pointer to information about process
        mov     [ebx+TASKDATA.wnd_number], al;set window number on screen = process slot

        mov     [ebx+TASKDATA.event_mask], dword 1+2+4;set default event flags (see 40 function)

        inc     dword [process_number]
        mov     eax, [process_number]
        mov     [ebx+4], eax    ;set PID

;set draw data to full screen
        xor     eax, eax
        mov     [ecx+0], dword eax
        mov     [ecx+4], dword eax
        mov     eax, [screen_workarea.right]
        mov     [ecx+8], eax
        mov     eax, [screen_workarea.bottom]
        mov     [ecx+12], eax

        mov     ebx, [pl0_stack]
        mov     esi, [params]
        lea     ecx, [ebx+REG_EIP]
        xor     eax, eax

        mov     [ebx+REG_RET], dword common_app_entry
        mov     [ebx+REG_EDI], eax
        mov     [ebx+REG_ESI], eax
        mov     [ebx+REG_EBP], eax
        mov     [ebx+REG_ESP], ecx;ebx+REG_EIP
        mov     [ebx+REG_EBX], eax
        mov     [ebx+REG_EDX], eax
        mov     [ebx+REG_ECX], eax
        mov     [ebx+REG_EAX], eax

        mov     eax, [esi+APP_HDR.eip]
        mov     [ebx+REG_EIP], eax
        mov     [ebx+REG_CS], dword app_code
        mov     ecx, USER_PRIORITY

        test    byte [flags], 2
        jz      @F

        mov     [ebx+REG_CS], dword os_code ; kernel thread
        mov     ecx, MAX_PRIORITY
@@:
        mov     [ebx+REG_EFLAGS], dword EFL_IOPL1+EFL_IF

        mov     eax, [esi+APP_HDR.esp]
        mov     [ebx+REG_APP_ESP], eax
        mov     [ebx+REG_SS], dword app_data

        lea     edx, [ebx+REG_RET]
        mov     ebx, [slot]
        shl     ebx, 5
        mov     [ebx*8+SLOT_BASE+APPDATA.saved_esp], edx

        xor     edx, edx; process state - running
; set if debuggee
        test    byte [flags], 1
        jz      .no_debug
        mov     eax, [CURRENT_TASK]
        mov     [SLOT_BASE+ebx*8+APPDATA.debugger_slot], eax
.no_debug:
        mov     [CURRENT_TASK+ebx+TASKDATA.state], dl
        lea     edx, [SLOT_BASE+ebx*8]
        call    scheduler_add_thread
        ret
endp

align 4
get_stack_base:
        mov     eax, [current_slot]
        mov     eax, [eax+APPDATA.pl0_stack]
        ret


include "debug.inc"
