diff --git a/kernel/trunk/blkdev/rdsave.inc b/kernel/trunk/blkdev/rdsave.inc index 621eebb857..7c016cccaa 100644 --- a/kernel/trunk/blkdev/rdsave.inc +++ b/kernel/trunk/blkdev/rdsave.inc @@ -24,7 +24,7 @@ sysfn_saveramdisk: ; 18.6 = SAVE FLOPPY IMAGE (HD version only) mov ebx, saverd_fileinfo mov [saverd_fileinfo.name], ecx pushad - call file_system_lfn ;in ebx + call file_system_lfn_protected ;in ebx popad mov [esp+32], eax ret diff --git a/kernel/trunk/boot/rdload.inc b/kernel/trunk/boot/rdload.inc index f4e86efb48..5794cb4849 100644 --- a/kernel/trunk/boot/rdload.inc +++ b/kernel/trunk/boot/rdload.inc @@ -103,7 +103,7 @@ endg read_image: mov ebx, read_image_fsinfo pushad - call file_system_lfn + call file_system_lfn_protected popad ret diff --git a/kernel/trunk/core/dll.inc b/kernel/trunk/core/dll.inc index 6c5165352e..c9772e42af 100644 --- a/kernel/trunk/core/dll.inc +++ b/kernel/trunk/core/dll.inc @@ -369,7 +369,7 @@ proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\ pushad lea ebx, [cmd] - call file_system_lfn + call file_system_lfn_protected popad ret endp diff --git a/kernel/trunk/core/sys32.inc b/kernel/trunk/core/sys32.inc index 0e9e962eb7..11b3a76ef5 100644 --- a/kernel/trunk/core/sys32.inc +++ b/kernel/trunk/core/sys32.inc @@ -707,3 +707,78 @@ restore .slot ; mov esi,boot_sched_2 ; call boot_log ; ret + +; Three following procedures are used to guarantee that +; some part of kernel code will not be terminated from outside +; while it is running. +; Note: they do not protect a thread from terminating due to errors inside +; the thread; accessing a nonexisting memory would still terminate it. + +; First two procedures must be used in pair by thread-to-be-protected +; to signal the beginning and the end of an important part. +; It is OK to have nested areas. + +; The last procedure must be used by outside wanna-be-terminators; +; if it is safe to terminate the given thread immediately, it returns eax=1; +; otherwise, it returns eax=0 and notifies the target thread that it should +; terminate itself when leaving a critical area (the last critical area if +; they are nested). + +; Implementation. Those procedures use one dword in APPDATA for the thread, +; APPDATA.terminate_protection. +; * The upper bit is 1 during normal operations and 0 when terminate is requested. +; * Other bits form a number = depth of critical regions, +; plus 1 if the upper bit is 1. +; * When this dword goes to zero, the thread should be destructed, +; and the procedure in which it happened becomes responsible for destruction. + +; Enter critical area. Called by thread which wants to be protected. +proc protect_from_terminate + mov edx, [current_slot] +; Atomically increment depth of critical areas and get the old value. + mov eax, 1 + lock xadd [edx+APPDATA.terminate_protection], eax +; If the old value was zero, somebody has started to terminate us, +; so we are destructing and cannot do anything protected. +; Otherwise, return to the caller. + test eax, eax + jz @f + ret +@@: +; Wait for somebody to finish us. + call change_task + jmp @b +endp + +; Leave critical area. Called by thread which wants to be protected. +proc unprotect_from_terminate + mov edx, [current_slot] +; Atomically decrement depth of critical areas. + lock dec [edx+APPDATA.terminate_protection] +; If the result of decrement is zero, somebody has requested termination, +; but at that moment we were inside a critical area; terminate now. + jz sys_end +; Otherwise, return to the caller. + ret +endp + +; Request termination of thread identified by edx = SLOT_BASE + slot*256. +; Called by anyone. +proc request_terminate + xor eax, eax ; set return value +; Atomically clear the upper bit. If it was already zero, then +; somebody has requested termination before us, so just exit. + lock btr [edx+APPDATA.terminate_protection], 31 + jnc .unsafe +; Atomically decrement depth of critical areas. + lock dec [edx+APPDATA.terminate_protection] +; If the result of decrement is nonzero, the target thread is inside a +; critical area; leave termination to leaving that area. + jnz .unsafe +; Otherwise, it is safe to kill the target now and the caller is responsible +; for this. Return eax=1. + inc eax +.unsafe: + ret +endp + diff --git a/kernel/trunk/core/syscall.inc b/kernel/trunk/core/syscall.inc index 8c1c206da7..650406be40 100644 --- a/kernel/trunk/core/syscall.inc +++ b/kernel/trunk/core/syscall.inc @@ -190,7 +190,7 @@ iglobal dd syscall_move_window ; 67-Window move or resize dd f68 ; 68-Some internal services dd sys_debug_services ; 69-Debug - dd file_system_lfn ; 70-Common file system interface, version 2 + dd file_system_lfn_protected; 70-Common file system interface, version 2 dd syscall_window_settings ; 71-Window settings dd sys_sendwindowmsg ; 72-Send window message dd blit_32 ; 73-blitter; diff --git a/kernel/trunk/core/taskman.inc b/kernel/trunk/core/taskman.inc index 9da5d9c080..b4dce8219c 100644 --- a/kernel/trunk/core/taskman.inc +++ b/kernel/trunk/core/taskman.inc @@ -1023,6 +1023,7 @@ proc set_app_params stdcall,slot:dword, params:dword,\ 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+256+APPDATA.io_map] diff --git a/kernel/trunk/fs/fs_lfn.inc b/kernel/trunk/fs/fs_lfn.inc index e806af3e06..5f773a7e64 100644 --- a/kernel/trunk/fs/fs_lfn.inc +++ b/kernel/trunk/fs/fs_lfn.inc @@ -103,6 +103,17 @@ fs_additional_handlers: dd 0 endg + +file_system_lfn_protected: + pushad + call protect_from_terminate + call file_system_lfn + call unprotect_from_terminate + popad + mov [image_of_eax], eax + mov [image_of_ebx], ebx + ret + file_system_lfn: ; in: ebx->fileinfo block ; operation codes: diff --git a/kernel/trunk/kernel.asm b/kernel/trunk/kernel.asm index b9fdab572f..7e947e945f 100644 --- a/kernel/trunk/kernel.asm +++ b/kernel/trunk/kernel.asm @@ -612,6 +612,52 @@ no_mode_0x12: mov [mem_BACKGROUND], 4 mov [img_background], static_background_data +; SET UP OS TASK + + mov esi, boot_setostask + call boot_log + + xor eax, eax + mov dword [SLOT_BASE+APPDATA.fpu_state], fpu_data + mov dword [SLOT_BASE+APPDATA.exc_handler], eax + mov dword [SLOT_BASE+APPDATA.except_mask], eax + + ; name for OS/IDLE process + + mov dword [SLOT_BASE+256+APPDATA.app_name], dword 'OS/I' + mov dword [SLOT_BASE+256+APPDATA.app_name+4], dword 'DLE ' + mov edi, [os_stack_seg] + mov dword [SLOT_BASE+256+APPDATA.pl0_stack], edi + add edi, 0x2000-512 + mov dword [SLOT_BASE+256+APPDATA.fpu_state], edi + mov dword [SLOT_BASE+256+APPDATA.saved_esp0], edi; just for case + mov dword [SLOT_BASE+256+APPDATA.terminate_protection], 80000001h + + mov esi, fpu_data + mov ecx, 512/4 + cld + rep movsd + + mov dword [SLOT_BASE+256+APPDATA.exc_handler], eax + mov dword [SLOT_BASE+256+APPDATA.except_mask], eax + + mov ebx, SLOT_BASE+256+APP_OBJ_OFFSET + mov dword [SLOT_BASE+256+APPDATA.fd_obj], ebx + mov dword [SLOT_BASE+256+APPDATA.bk_obj], ebx + + mov dword [SLOT_BASE+256+APPDATA.cur_dir], sysdir_path + mov dword [SLOT_BASE+256+APPDATA.tls_base], eax + + ; task list + mov dword [TASK_DATA+TASKDATA.mem_start], eax; process base address + inc eax + mov dword [CURRENT_TASK], eax + mov dword [TASK_COUNT], eax + mov [current_slot], SLOT_BASE+256 + mov [TASK_BASE], dword TASK_DATA + mov byte[TASK_DATA+TASKDATA.wnd_number], al ; on screen number + mov dword [TASK_DATA+TASKDATA.pid], eax ; process id number + mov [SLOT_BASE + 256 + APPDATA.dir_table], sys_pgdir - OS_BASE stdcall kernel_alloc, 0x10000/8 @@ -752,7 +798,6 @@ end if mov [pci_access_enabled], 1 - ; SET PRELIMINARY WINDOW STACK AND POSITIONS mov esi, boot_windefs @@ -772,52 +817,6 @@ end if call boot_log call reserve_irqs_ports -; SET UP OS TASK - - mov esi, boot_setostask - call boot_log - - xor eax, eax - mov dword [SLOT_BASE+APPDATA.fpu_state], fpu_data - mov dword [SLOT_BASE+APPDATA.exc_handler], eax - mov dword [SLOT_BASE+APPDATA.except_mask], eax - - ; name for OS/IDLE process - - mov dword [SLOT_BASE+256+APPDATA.app_name], dword 'OS/I' - mov dword [SLOT_BASE+256+APPDATA.app_name+4], dword 'DLE ' - mov edi, [os_stack_seg] - mov dword [SLOT_BASE+256+APPDATA.pl0_stack], edi - add edi, 0x2000-512 - mov dword [SLOT_BASE+256+APPDATA.fpu_state], edi - mov dword [SLOT_BASE+256+APPDATA.saved_esp0], edi; just for case - ; [SLOT_BASE+256+APPDATA.io_map] was set earlier - - mov esi, fpu_data - mov ecx, 512/4 - cld - rep movsd - - mov dword [SLOT_BASE+256+APPDATA.exc_handler], eax - mov dword [SLOT_BASE+256+APPDATA.except_mask], eax - - mov ebx, SLOT_BASE+256+APP_OBJ_OFFSET - mov dword [SLOT_BASE+256+APPDATA.fd_obj], ebx - mov dword [SLOT_BASE+256+APPDATA.bk_obj], ebx - - mov dword [SLOT_BASE+256+APPDATA.cur_dir], sysdir_path - mov dword [SLOT_BASE+256+APPDATA.tls_base], eax - - ; task list - mov dword [TASK_DATA+TASKDATA.mem_start], eax; process base address - inc eax - mov dword [CURRENT_TASK], eax - mov dword [TASK_COUNT], eax - mov [current_slot], SLOT_BASE+256 - mov [TASK_BASE], dword TASK_DATA - mov byte[TASK_DATA+TASKDATA.wnd_number], al ; on screen number - mov dword [TASK_DATA+TASKDATA.pid], eax ; process id number - call init_display mov eax, [def_cursor] mov [SLOT_BASE+APPDATA.cursor], eax @@ -931,8 +930,8 @@ end if call fs_execute_from_sysdir ; cmp eax,2 ; continue if a process has been loaded - sub eax, 2 - jz first_app_found + test eax, eax + jns first_app_found mov esi, boot_failed call boot_log @@ -2110,6 +2109,12 @@ sysfn_terminate: ; 18.2 = TERMINATE add ecx, CURRENT_TASK+TASKDATA.state cmp byte [ecx], 9 jz noprocessterminate + push ecx edx + lea edx, [(ecx-(CURRENT_TASK and 1FFFFFFFh)-TASKDATA.state)*8+SLOT_BASE] + call request_terminate + pop edx ecx + test eax, eax + jz noprocessterminate ;-------------------------------------- cmp [_display.select_cursor], 0 je .restore_end @@ -3489,7 +3494,14 @@ nobackgr: ;-------------------------------------- align 4 markz: + push ecx edx + lea edx, [(edx-(TASK_DATA and 1FFFFFFFh))*8+SLOT_BASE] + call request_terminate + pop edx ecx + test eax, eax + jz @f mov [edx+TASKDATA.state], byte 3 +@@: add edx, 0x20 loop markz ;-------------------------------------- diff --git a/kernel/trunk/kernel32.inc b/kernel/trunk/kernel32.inc index b2271e7f9f..7920a91769 100644 --- a/kernel/trunk/kernel32.inc +++ b/kernel/trunk/kernel32.inc @@ -137,7 +137,7 @@ struct APPDATA ipc_size dd ? event_mask dd ? debugger_slot dd ? - dd ? + terminate_protection dd ? keyboard_mode db ? rb 3 dir_table dd ?