From af8dc3b80a498bcf8437cc939dc152cf45090789 Mon Sep 17 00:00:00 2001 From: "Evgeny Grechnikov (Diamond)" Date: Tue, 8 Dec 2009 23:36:12 +0000 Subject: [PATCH] make dll a per-process object git-svn-id: svn://kolibrios.org@1311 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/trunk/const.inc | 2 - kernel/trunk/core/dll.inc | 101 ++++++++++++++++++++++++++-------- kernel/trunk/core/memory.inc | 10 ++-- kernel/trunk/core/sys32.inc | 4 +- kernel/trunk/core/taskman.inc | 32 +++++++---- kernel/trunk/kernel32.inc | 3 +- 6 files changed, 107 insertions(+), 45 deletions(-) diff --git a/kernel/trunk/const.inc b/kernel/trunk/const.inc index 8fbebc2b76..ee1e18b5ab 100644 --- a/kernel/trunk/const.inc +++ b/kernel/trunk/const.inc @@ -531,8 +531,6 @@ struc DLLDESCR struc HDLL { - .magic dd ? ; HDLL - .destroy dd ? ;internal destructor .fd dd ? ;next object in list .bk dd ? ;prev object in list .pid dd ? ;owner id diff --git a/kernel/trunk/core/dll.inc b/kernel/trunk/core/dll.inc index b702ca28f4..3285243aed 100644 --- a/kernel/trunk/core/dll.inc +++ b/kernel/trunk/core/dll.inc @@ -1064,14 +1064,14 @@ proc load_library stdcall, file_name:dword ; ignore timestamp mov esi, [CURRENT_TASK] shl esi, 8 - lea ebx, [esi+SLOT_BASE+APP_OBJ_OFFSET] - mov esi, [ebx+APPOBJ.fd] lea edi, [fullname] + mov ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr] + test ebx, ebx + jz .not_in_process + mov esi, [ebx+HDLL.fd] .scan_in_process: cmp esi, ebx jz .not_in_process - cmp dword [esi+APPOBJ.magic], 'HDLL' - jnz .next_in_process mov eax, [esi+HDLL.parent] add eax, DLLDESCR.name stdcall strncmp, eax, edi, -1 @@ -1087,7 +1087,7 @@ proc load_library stdcall, file_name:dword add eax, [esi+HDLL.base] ret .next_in_process: - mov esi, [esi+APPOBJ.fd] + mov esi, [esi+HDLL.fd] jmp .scan_in_process .not_in_process: @@ -1335,15 +1335,25 @@ proc load_library stdcall, file_name:dword jz .fail_and_dereference @@: mov [img_base], eax + mov eax, HDLL.sizeof + call malloc + test eax, eax + jz .fail_and_free_user mov ebx, [CURRENT_TASK] shl ebx, 5 - mov ebx, [CURRENT_TASK+ebx+TASKDATA.pid] - mov eax, HDLL.sizeof - call create_kernel_object + mov edx, [CURRENT_TASK+ebx+TASKDATA.pid] + mov [eax+HDLL.pid], edx + push eax + call init_dlls_in_thread + pop ebx test eax, eax - jz .fail_and_free_user - mov [eax+APPOBJ.magic], 'HDLL' - mov [eax+APPOBJ.destroy], destroy_hdll + jz .fail_and_free_user + mov edx, [eax+HDLL.fd] + mov [ebx+HDLL.fd], edx + mov [ebx+HDLL.bk], eax + mov [eax+HDLL.fd], ebx + mov [edx+HDLL.bk], ebx + mov eax, ebx mov ebx, [img_base] mov [eax+HDLL.base], ebx mov [eax+HDLL.size], edi @@ -1374,7 +1384,6 @@ proc load_library stdcall, file_name:dword jb .map_pages_loop ; if real user-mode base is not equal to preferred base, relocate image - mov ebx, [img_base] sub ebx, [esi+DLLDESCR.defaultbase] jz @f stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx @@ -1403,6 +1412,37 @@ proc load_library stdcall, file_name:dword ret endp +; initialize [APPDATA.dlls_list_ptr] for given thread +; DLL is per-process object, so APPDATA.dlls_list_ptr must be +; kept in sync for all threads of one process. +; out: eax = APPDATA.dlls_list_ptr if all is OK, +; NULL if memory allocation failed +init_dlls_in_thread: + mov ebx, [current_slot] + mov eax, [ebx+APPDATA.dlls_list_ptr] + test eax, eax + jnz .ret + push [ebx+APPDATA.dir_table] + mov eax, 8 + call malloc + pop edx + test eax, eax + jz .ret + mov [eax], eax + mov [eax+4], eax + mov ecx, [TASK_COUNT] + mov ebx, SLOT_BASE+256 +.set: + cmp [ebx+APPDATA.dir_table], edx + jnz @f + mov [ebx+APPDATA.dlls_list_ptr], eax +@@: + add ebx, 256 + dec ecx + jnz .set +.ret: + ret + ; in: eax = number of references to delete, esi -> DLLDESCR struc dereference_dll: sub [esi+DLLDESCR.refcount], eax @@ -1419,7 +1459,7 @@ dereference_dll: ret destroy_hdll: - push ebx esi edi + push ebx ecx esi edi push eax mov ebx, [eax+HDLL.base] mov esi, [eax+HDLL.parent] @@ -1428,21 +1468,17 @@ destroy_hdll: ; However, destroy_hdll can be called in the context of OS thread when ; cleaning up objects created by the application which is destroyed. ; So remember current cr3 and set it to page table of target. - mov eax, [eax+HDLL.pid] - call pid_to_slot - shl eax, 8 - add eax, SLOT_BASE - mov ecx, [eax+APPDATA.dir_table] + mov eax, [ecx+APPDATA.dir_table] ; Because we cheat with cr3, disable interrupts: task switch would restore ; page table from APPDATA of current thread. ; Also set [current_slot] because it is used by user_free. pushf cli push [current_slot] - mov [current_slot], eax - mov eax, cr3 - push eax - mov cr3, ecx + mov [current_slot], ecx + mov ecx, cr3 + push ecx + mov cr3, eax push ebx ; argument for user_free mov eax, ebx shr ebx, 12 @@ -1482,8 +1518,25 @@ destroy_hdll: mov eax, [eax+HDLL.refcount] call dereference_dll pop eax - call destroy_kernel_object - pop edi esi ebx + mov edx, [eax+HDLL.bk] + mov ebx, [eax+HDLL.fd] + mov [ebx+HDLL.bk], edx + mov [edx+HDLL.fd], ebx + call free + pop edi esi ecx ebx + ret + +; ecx -> APPDATA for slot, esi = dlls_list_ptr +destroy_all_hdlls: + test esi, esi + jz .ret +.loop: + mov eax, [esi+HDLL.fd] + cmp eax, esi + jz free + call destroy_hdll + jmp .loop +.ret: ret align 4 diff --git a/kernel/trunk/core/memory.inc b/kernel/trunk/core/memory.inc index eca93fa4fb..4b4f1cd120 100644 --- a/kernel/trunk/core/memory.inc +++ b/kernel/trunk/core/memory.inc @@ -639,19 +639,19 @@ end if and ebx, not 0xFFF mov eax, [CURRENT_TASK] shl eax, 8 - lea eax, [SLOT_BASE+eax+APP_OBJ_OFFSET] - mov esi, [eax+APPOBJ.fd] + mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr] + test eax, eax + jz .fail + mov esi, [eax+HDLL.fd] .scan_hdll: cmp esi, eax jz .fail - cmp [esi+APPOBJ.magic], 'HDLL' - jnz .scan_hdll.next mov edx, ebx sub edx, [esi+HDLL.base] cmp edx, [esi+HDLL.size] jb .fault_in_hdll .scan_hdll.next: - mov esi, [esi+APPOBJ.fd] + mov esi, [esi+HDLL.fd] jmp .scan_hdll .fault_in_hdll: ; allocate new page, map it as rw and copy data diff --git a/kernel/trunk/core/sys32.inc b/kernel/trunk/core/sys32.inc index 26d1197233..70bfea382e 100644 --- a/kernel/trunk/core/sys32.inc +++ b/kernel/trunk/core/sys32.inc @@ -508,10 +508,10 @@ term9: pop esi jmp @B @@: + mov eax, [.slot] shl eax, 8 - mov eax,[SLOT_BASE+eax+APPDATA.dir_table] - stdcall destroy_app_space, eax + stdcall destroy_app_space, [SLOT_BASE+eax+APPDATA.dir_table], [SLOT_BASE+eax+APPDATA.dlls_list_ptr] mov esi, [.slot] cmp [fpu_owner],esi ; if user fpu last -> fpu user = 1 diff --git a/kernel/trunk/core/taskman.inc b/kernel/trunk/core/taskman.inc index b7a232f375..1e1b734b2c 100644 --- a/kernel/trunk/core/taskman.inc +++ b/kernel/trunk/core/taskman.inc @@ -486,7 +486,7 @@ end if dec [pg_data.pg_mutex] cmp [dir_addr], 0 je @f - stdcall destroy_app_space, [dir_addr] + stdcall destroy_app_space, [dir_addr], 0 @@: xor eax, eax ret @@ -523,12 +523,10 @@ proc destroy_page_table stdcall, pg_tab:dword endp align 4 -proc destroy_app_space stdcall, pg_dir:dword - - mov ebx, pg_data.pg_mutex - call wait_mutex ;ebx +proc destroy_app_space stdcall, pg_dir:dword, dlls_list:dword xor edx,edx + push edx mov eax,0x2 mov ebx, [pg_dir] .loop: @@ -538,8 +536,10 @@ proc destroy_app_space stdcall, pg_dir:dword cmp byte [CURRENT_TASK+ecx+0xa],9 ;if process running? jz @f ;skip empty slots shl ecx,3 - cmp [SLOT_BASE+ecx+0xB8],ebx ;compare page directory addresses + add ecx,SLOT_BASE + cmp [ecx+APPDATA.dir_table],ebx ;compare page directory addresses jnz @f + mov [ebp-4],ecx inc edx ;thread found @@: inc eax @@ -548,13 +548,19 @@ proc destroy_app_space stdcall, pg_dir:dword ;edx = number of threads ;our process is zombi so it isn't counted + pop ecx cmp edx,1 - jg .exit + jg .ret ;if there isn't threads then clear memory. + mov esi, [dlls_list] + call destroy_all_hdlls + + mov ebx, pg_data.pg_mutex + call wait_mutex ;ebx mov eax, [pg_dir] and eax, not 0xFFF - stdcall map_page,[tmp_task_pdir],eax,dword PG_SW + stdcall map_page,[tmp_task_pdir],eax,PG_SW mov esi, [tmp_task_pdir] mov edi, (OS_BASE shr 20)/4 .destroy: @@ -562,7 +568,7 @@ proc destroy_app_space stdcall, pg_dir:dword test eax, 1 jz .next and eax, not 0xFFF - stdcall map_page,[tmp_task_ptab],eax,dword PG_SW + stdcall map_page,[tmp_task_ptab],eax,PG_SW stdcall destroy_page_table, [tmp_task_ptab] mov eax, [esi] call free_page @@ -574,9 +580,10 @@ proc destroy_app_space stdcall, pg_dir:dword mov eax, [pg_dir] call free_page .exit: - stdcall map_page,[tmp_task_ptab],dword 0,dword PG_UNMAP - stdcall map_page,[tmp_task_pdir],dword 0,dword PG_UNMAP + stdcall map_page,[tmp_task_ptab],0,PG_UNMAP + stdcall map_page,[tmp_task_pdir],0,PG_UNMAP dec [pg_data.pg_mutex] +.ret: ret endp @@ -908,6 +915,9 @@ proc new_sys_threads mov ecx,[ebx+APPDATA.dir_table] mov [edx+APPDATA.dir_table],ecx ;copy page directory + mov eax,[ebx+APPDATA.dlls_list_ptr] + mov [edx+APPDATA.dlls_list_ptr],eax + mov eax, [ebx+APPDATA.tls_base] test eax, eax jz @F diff --git a/kernel/trunk/kernel32.inc b/kernel/trunk/kernel32.inc index e26c68947a..195c722d4d 100644 --- a/kernel/trunk/kernel32.inc +++ b/kernel/trunk/kernel32.inc @@ -142,7 +142,8 @@ struc APPDATA .wait_test dd ? ;+96 +++ .wait_param dd ? ;+100 +++ .tls_base dd ? ;+104 - db 20 dup(?) ;+108 + .dlls_list_ptr dd ? ;+108 + db 16 dup(?) ;+112 .wnd_shape dd ? ;+128 .wnd_shape_scale dd ? ;+132