make dll a per-process object

git-svn-id: svn://kolibrios.org@1311 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Evgeny Grechnikov (Diamond) 2009-12-08 23:36:12 +00:00
parent 6b29296f2c
commit af8dc3b80a
6 changed files with 107 additions and 45 deletions

View File

@ -531,8 +531,6 @@ struc DLLDESCR
struc HDLL struc HDLL
{ {
.magic dd ? ; HDLL
.destroy dd ? ;internal destructor
.fd dd ? ;next object in list .fd dd ? ;next object in list
.bk dd ? ;prev object in list .bk dd ? ;prev object in list
.pid dd ? ;owner id .pid dd ? ;owner id

View File

@ -1064,14 +1064,14 @@ proc load_library stdcall, file_name:dword
; ignore timestamp ; ignore timestamp
mov esi, [CURRENT_TASK] mov esi, [CURRENT_TASK]
shl esi, 8 shl esi, 8
lea ebx, [esi+SLOT_BASE+APP_OBJ_OFFSET]
mov esi, [ebx+APPOBJ.fd]
lea edi, [fullname] 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: .scan_in_process:
cmp esi, ebx cmp esi, ebx
jz .not_in_process jz .not_in_process
cmp dword [esi+APPOBJ.magic], 'HDLL'
jnz .next_in_process
mov eax, [esi+HDLL.parent] mov eax, [esi+HDLL.parent]
add eax, DLLDESCR.name add eax, DLLDESCR.name
stdcall strncmp, eax, edi, -1 stdcall strncmp, eax, edi, -1
@ -1087,7 +1087,7 @@ proc load_library stdcall, file_name:dword
add eax, [esi+HDLL.base] add eax, [esi+HDLL.base]
ret ret
.next_in_process: .next_in_process:
mov esi, [esi+APPOBJ.fd] mov esi, [esi+HDLL.fd]
jmp .scan_in_process jmp .scan_in_process
.not_in_process: .not_in_process:
@ -1335,15 +1335,25 @@ proc load_library stdcall, file_name:dword
jz .fail_and_dereference jz .fail_and_dereference
@@: @@:
mov [img_base], eax mov [img_base], eax
mov eax, HDLL.sizeof
call malloc
test eax, eax
jz .fail_and_free_user
mov ebx, [CURRENT_TASK] mov ebx, [CURRENT_TASK]
shl ebx, 5 shl ebx, 5
mov ebx, [CURRENT_TASK+ebx+TASKDATA.pid] mov edx, [CURRENT_TASK+ebx+TASKDATA.pid]
mov eax, HDLL.sizeof mov [eax+HDLL.pid], edx
call create_kernel_object push eax
call init_dlls_in_thread
pop ebx
test eax, eax test eax, eax
jz .fail_and_free_user jz .fail_and_free_user
mov [eax+APPOBJ.magic], 'HDLL' mov edx, [eax+HDLL.fd]
mov [eax+APPOBJ.destroy], destroy_hdll 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 ebx, [img_base]
mov [eax+HDLL.base], ebx mov [eax+HDLL.base], ebx
mov [eax+HDLL.size], edi mov [eax+HDLL.size], edi
@ -1374,7 +1384,6 @@ proc load_library stdcall, file_name:dword
jb .map_pages_loop jb .map_pages_loop
; if real user-mode base is not equal to preferred base, relocate image ; if real user-mode base is not equal to preferred base, relocate image
mov ebx, [img_base]
sub ebx, [esi+DLLDESCR.defaultbase] sub ebx, [esi+DLLDESCR.defaultbase]
jz @f jz @f
stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx
@ -1403,6 +1412,37 @@ proc load_library stdcall, file_name:dword
ret ret
endp 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 ; in: eax = number of references to delete, esi -> DLLDESCR struc
dereference_dll: dereference_dll:
sub [esi+DLLDESCR.refcount], eax sub [esi+DLLDESCR.refcount], eax
@ -1419,7 +1459,7 @@ dereference_dll:
ret ret
destroy_hdll: destroy_hdll:
push ebx esi edi push ebx ecx esi edi
push eax push eax
mov ebx, [eax+HDLL.base] mov ebx, [eax+HDLL.base]
mov esi, [eax+HDLL.parent] mov esi, [eax+HDLL.parent]
@ -1428,21 +1468,17 @@ destroy_hdll:
; However, destroy_hdll can be called in the context of OS thread when ; However, destroy_hdll can be called in the context of OS thread when
; cleaning up objects created by the application which is destroyed. ; cleaning up objects created by the application which is destroyed.
; So remember current cr3 and set it to page table of target. ; So remember current cr3 and set it to page table of target.
mov eax, [eax+HDLL.pid] mov eax, [ecx+APPDATA.dir_table]
call pid_to_slot
shl eax, 8
add eax, SLOT_BASE
mov ecx, [eax+APPDATA.dir_table]
; Because we cheat with cr3, disable interrupts: task switch would restore ; Because we cheat with cr3, disable interrupts: task switch would restore
; page table from APPDATA of current thread. ; page table from APPDATA of current thread.
; Also set [current_slot] because it is used by user_free. ; Also set [current_slot] because it is used by user_free.
pushf pushf
cli cli
push [current_slot] push [current_slot]
mov [current_slot], eax mov [current_slot], ecx
mov eax, cr3 mov ecx, cr3
push eax push ecx
mov cr3, ecx mov cr3, eax
push ebx ; argument for user_free push ebx ; argument for user_free
mov eax, ebx mov eax, ebx
shr ebx, 12 shr ebx, 12
@ -1482,8 +1518,25 @@ destroy_hdll:
mov eax, [eax+HDLL.refcount] mov eax, [eax+HDLL.refcount]
call dereference_dll call dereference_dll
pop eax pop eax
call destroy_kernel_object mov edx, [eax+HDLL.bk]
pop edi esi ebx 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 ret
align 4 align 4

View File

@ -639,19 +639,19 @@ end if
and ebx, not 0xFFF and ebx, not 0xFFF
mov eax, [CURRENT_TASK] mov eax, [CURRENT_TASK]
shl eax, 8 shl eax, 8
lea eax, [SLOT_BASE+eax+APP_OBJ_OFFSET] mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
mov esi, [eax+APPOBJ.fd] test eax, eax
jz .fail
mov esi, [eax+HDLL.fd]
.scan_hdll: .scan_hdll:
cmp esi, eax cmp esi, eax
jz .fail jz .fail
cmp [esi+APPOBJ.magic], 'HDLL'
jnz .scan_hdll.next
mov edx, ebx mov edx, ebx
sub edx, [esi+HDLL.base] sub edx, [esi+HDLL.base]
cmp edx, [esi+HDLL.size] cmp edx, [esi+HDLL.size]
jb .fault_in_hdll jb .fault_in_hdll
.scan_hdll.next: .scan_hdll.next:
mov esi, [esi+APPOBJ.fd] mov esi, [esi+HDLL.fd]
jmp .scan_hdll jmp .scan_hdll
.fault_in_hdll: .fault_in_hdll:
; allocate new page, map it as rw and copy data ; allocate new page, map it as rw and copy data

View File

@ -508,10 +508,10 @@ term9:
pop esi pop esi
jmp @B jmp @B
@@: @@:
mov eax, [.slot] mov eax, [.slot]
shl eax, 8 shl eax, 8
mov eax,[SLOT_BASE+eax+APPDATA.dir_table] stdcall destroy_app_space, [SLOT_BASE+eax+APPDATA.dir_table], [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
stdcall destroy_app_space, eax
mov esi, [.slot] mov esi, [.slot]
cmp [fpu_owner],esi ; if user fpu last -> fpu user = 1 cmp [fpu_owner],esi ; if user fpu last -> fpu user = 1

View File

@ -486,7 +486,7 @@ end if
dec [pg_data.pg_mutex] dec [pg_data.pg_mutex]
cmp [dir_addr], 0 cmp [dir_addr], 0
je @f je @f
stdcall destroy_app_space, [dir_addr] stdcall destroy_app_space, [dir_addr], 0
@@: @@:
xor eax, eax xor eax, eax
ret ret
@ -523,12 +523,10 @@ proc destroy_page_table stdcall, pg_tab:dword
endp endp
align 4 align 4
proc destroy_app_space stdcall, pg_dir:dword proc destroy_app_space stdcall, pg_dir:dword, dlls_list:dword
mov ebx, pg_data.pg_mutex
call wait_mutex ;ebx
xor edx,edx xor edx,edx
push edx
mov eax,0x2 mov eax,0x2
mov ebx, [pg_dir] mov ebx, [pg_dir]
.loop: .loop:
@ -538,8 +536,10 @@ proc destroy_app_space stdcall, pg_dir:dword
cmp byte [CURRENT_TASK+ecx+0xa],9 ;if process running? cmp byte [CURRENT_TASK+ecx+0xa],9 ;if process running?
jz @f ;skip empty slots jz @f ;skip empty slots
shl ecx,3 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 jnz @f
mov [ebp-4],ecx
inc edx ;thread found inc edx ;thread found
@@: @@:
inc eax inc eax
@ -548,13 +548,19 @@ proc destroy_app_space stdcall, pg_dir:dword
;edx = number of threads ;edx = number of threads
;our process is zombi so it isn't counted ;our process is zombi so it isn't counted
pop ecx
cmp edx,1 cmp edx,1
jg .exit jg .ret
;if there isn't threads then clear memory. ;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] mov eax, [pg_dir]
and eax, not 0xFFF 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 esi, [tmp_task_pdir]
mov edi, (OS_BASE shr 20)/4 mov edi, (OS_BASE shr 20)/4
.destroy: .destroy:
@ -562,7 +568,7 @@ proc destroy_app_space stdcall, pg_dir:dword
test eax, 1 test eax, 1
jz .next jz .next
and eax, not 0xFFF 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] stdcall destroy_page_table, [tmp_task_ptab]
mov eax, [esi] mov eax, [esi]
call free_page call free_page
@ -574,9 +580,10 @@ proc destroy_app_space stdcall, pg_dir:dword
mov eax, [pg_dir] mov eax, [pg_dir]
call free_page call free_page
.exit: .exit:
stdcall map_page,[tmp_task_ptab],dword 0,dword PG_UNMAP stdcall map_page,[tmp_task_ptab],0,PG_UNMAP
stdcall map_page,[tmp_task_pdir],dword 0,dword PG_UNMAP stdcall map_page,[tmp_task_pdir],0,PG_UNMAP
dec [pg_data.pg_mutex] dec [pg_data.pg_mutex]
.ret:
ret ret
endp endp
@ -908,6 +915,9 @@ proc new_sys_threads
mov ecx,[ebx+APPDATA.dir_table] mov ecx,[ebx+APPDATA.dir_table]
mov [edx+APPDATA.dir_table],ecx ;copy page directory 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] mov eax, [ebx+APPDATA.tls_base]
test eax, eax test eax, eax
jz @F jz @F

View File

@ -142,7 +142,8 @@ struc APPDATA
.wait_test dd ? ;+96 +++ .wait_test dd ? ;+96 +++
.wait_param dd ? ;+100 +++ .wait_param dd ? ;+100 +++
.tls_base dd ? ;+104 .tls_base dd ? ;+104
db 20 dup(?) ;+108 .dlls_list_ptr dd ? ;+108
db 16 dup(?) ;+112
.wnd_shape dd ? ;+128 .wnd_shape dd ? ;+128
.wnd_shape_scale dd ? ;+132 .wnd_shape_scale dd ? ;+132