0,0 → 1,977 |
if ~defined memmanager_inc |
memmanager_inc_fix: |
memmanager_inc fix memmanager_inc_fix |
;for testing in applications |
if defined B32 |
iskernel=1 |
else |
iskernel=0 |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; Memory allocator for MenuetOS kernel |
;; Andrey Halyavin, halyavin@land.ru 2005 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; heap block structure - |
;; you can handle several ranges of |
;; pages simultaneosly. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
.heap_linear_address equ 0 |
.heap_block_size equ 4 |
.heap_physical_address equ 8 |
.heap_reserved equ 12 |
.heap_block_info equ 16 |
max_heaps equ 8 |
.range_info equ 36 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; memory manager data |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_heap_block_ rd .heap_block_info*max_heaps/4 |
MEM_heap_block=MEM_heap_block_+second_base_address |
MEM_heap_count_ rd 1 |
MEM_heap_count=MEM_heap_count_+second_base_address |
if iskernel = 0 |
MEM_general_mutex rd 1 |
MEM_call_count rd 1 |
MEM_mutex_pid rd 1 |
MEM_mutex_count rd 1 |
else |
MEM_cli_count_ rd 1 |
MEM_cli_count=MEM_cli_count_+second_base_address |
MEM_cli_prev_ rd 1 |
MEM_cli_prev=MEM_cli_prev_+second_base_address |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Init |
;;Initialize memory manager structures. |
;;Must be called first. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Init: |
push eax |
xor eax,eax |
if iskernel = 0 |
mov [MEM_heap_count],eax |
mov [MEM_general_mutex],eax |
mov [MEM_call_count],eax |
mov [MEM_mutex_pid],eax |
mov [MEM_mutex_count],eax |
else |
mov [MEM_cli_prev],eax ;init value = 0 |
dec eax |
mov [MEM_cli_count],eax ;init value = -1 |
end if |
pop eax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;change_task |
;;procedure for changing tasks. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if iskernel = 0 |
change_task: |
push eax |
push ebx |
mov eax,5 |
xor ebx,ebx |
inc ebx |
int 0x40 |
pop ebx |
pop eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_get_pid |
;;determine current pid |
;;result: |
;; eax - pid |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if iskernel = 0 |
MEM_get_pid: |
push ebx |
push ecx |
sub esp,1024 |
mov eax,9 |
mov ebx,esp |
mov ecx,-1 |
int 0x40 |
mov eax,[esp+30] |
add esp,1024 |
pop ecx |
pop ebx |
ret |
else |
; pid_address dd 0x3000 |
;MEM_get_pid: |
; mov eax,[pid_address] |
; mov eax,[eax] |
; ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Heap_Lock |
;;Wait until all operations with heap will be finished. |
;;Between MEM_Heap_Lock and MEM_Heap_UnLock operations |
;;with heap are forbidden. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Heap_Lock: |
if iskernel = 0 |
push eax |
inc dword [MEM_call_count] |
MEM_Heap_Lock_wait: |
mov eax,1 |
xchg [MEM_general_mutex],eax |
test eax,eax |
jz MEM_Heap_Lock_end |
call MEM_get_pid |
cmp [MEM_mutex_pid],eax |
jz MEM_Heap_Lock_end1 |
call change_task |
jmp MEM_Heap_Lock_wait |
MEM_Heap_Lock_end1: |
inc dword [MEM_mutex_count] |
pop eax |
ret |
MEM_Heap_Lock_end: |
call MEM_get_pid |
mov [MEM_mutex_pid],eax |
mov dword [MEM_mutex_count],1 |
pop eax |
ret |
else |
pushfd |
cli |
inc dword [MEM_cli_count] |
jz MEM_Heap_First_Lock |
add esp,4 |
ret |
MEM_Heap_First_Lock: ;save interrupt flag |
shr dword [esp],9 |
and dword [esp],1 |
pop dword [MEM_cli_prev] |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Heap_UnLock |
;;After this routine operations with heap are allowed. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Heap_UnLock: |
if iskernel = 0 |
push eax |
xor eax,eax |
dec dword [MEM_mutex_count] |
jnz MEM_Heap_UnLock_No_Wait1 |
dec dword [MEM_call_count] |
mov [MEM_mutex_pid],eax |
mov [MEM_general_mutex],eax;release mutex BEFORE task switching |
jz MEM_Heap_UnLock_No_Wait |
call change_task ;someone want to use heap - switch tasks |
MEM_Heap_UnLock_No_Wait: |
pop eax |
ret |
MEM_Heap_UnLock_No_Wait1: |
dec dword [MEM_call_count] |
jz MEM_Heap_UnLock_No_Wait2 |
call change_task |
MEM_Heap_UnLock_No_Wait2: |
pop eax |
ret |
else |
dec dword [MEM_cli_count] |
js MEM_Heap_UnLock_last |
ret |
MEM_Heap_UnLock_last: |
cmp dword [MEM_cli_prev],0 ;restore saved interrupt flag |
jz MEM_Heap_UnLock_No_sti |
sti |
MEM_Heap_UnLock_No_sti: |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Add_Heap |
;;Add new range to memory manager. |
;;eax - linear address |
;;ebx - size in pages |
;;ecx - physical address |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Add_Heap: |
push edx |
call MEM_Heap_Lock |
mov edx,[MEM_heap_count] |
cmp edx,max_heaps |
jz MEM_Add_Heap_Error |
inc dword [MEM_heap_count] |
shl edx,4 |
mov [MEM_heap_block+edx+.heap_linear_address],eax |
mov [MEM_heap_block+edx+.heap_block_size],ebx |
shl dword [MEM_heap_block+edx+.heap_block_size],12 |
mov [MEM_heap_block+edx+.heap_physical_address],ecx |
lea edx,[4*ebx+.range_info+4095] ;calculate space for page info table |
and edx,0xFFFFF000 |
mov [eax],eax |
add [eax],edx ;first 4 bytes - pointer to first free page |
;clean page info area |
push edi |
lea edi,[eax+4] |
mov ecx,edx |
shr ecx,2 |
push eax |
xor eax,eax |
rep stosd |
pop eax |
pop edi |
;create free pages list. |
mov ecx,[eax] |
shl ebx,12 |
add eax,ebx ;eax - address after block |
MEM_Add_Heap_loop: |
add ecx,4096 |
mov [ecx-4096],ecx ;set forward pointer |
cmp ecx,eax |
jnz MEM_Add_Heap_loop |
mov dword [ecx-4096],0 ;set end of list |
MEM_Add_Heap_ret: |
call MEM_Heap_UnLock |
pop edx |
ret |
MEM_Add_Heap_Error: |
xor eax,eax |
jmp MEM_Add_Heap_ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Physical_Address |
;;Translate linear address to physical address |
;;Parameters: |
;; eax - linear address |
;;Result: |
;; eax - physical address |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Physical_Address |
MEM_Get_Physical_Address: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Physical_Address_loop: |
sub eax,[MEM_heap_block+ecx+.heap_linear_address] |
jl MEM_Get_Physical_Address_next |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jge MEM_Get_Physical_Address_next |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
jmp MEM_Get_Physical_Address_loopend |
MEM_Get_Physical_Address_next: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
sub ecx,16 |
jns MEM_Get_Physical_Address_loop |
xor eax,eax ;address not found |
MEM_Get_Physical_Address_loopend: |
call MEM_Heap_UnLock |
pop ecx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Linear_Address |
;;Translate physical address to linear address. |
;;Parameters: |
;; eax - physical address |
;;Result: |
;; eax - linear address |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Linear_Address |
MEM_Get_Linear_Address: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Linear_Address_loop: |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
jl MEM_Get_Linear_Address_Next |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jge MEM_Get_Linear_Address_Next |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
call MEM_Heap_UnLock |
pop ecx |
ret |
MEM_Get_Linear_Address_Next: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
sub ecx,16 |
jns MEM_Get_Linear_Address_loop |
call MEM_Heap_UnLock |
pop ecx |
xor eax,eax ;address not found |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Page |
;;Allocate and add reference to page |
;;Result: |
;; eax<>0 - physical address of page |
;; eax=0 - not enough memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Page |
MEM_Alloc_Page: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Alloc_Page_loop: |
push ecx |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
cmp dword [ecx],0 |
jz MEM_Alloc_Page_loopend |
mov eax,[ecx] |
push dword [eax] |
pop dword [ecx] |
sub eax,ecx |
push eax |
shr eax,10 |
mov word [ecx+.range_info+eax],1 |
pop eax |
pop ecx |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
jmp MEM_Alloc_Page_ret |
MEM_Alloc_Page_loopend: |
pop ecx |
sub ecx,16 |
jns MEM_Alloc_Page_loop |
xor eax,eax |
MEM_Alloc_Page_ret: |
call MEM_Heap_UnLock |
pop ecx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Page_Linear |
;;Allocate and add reference to page |
;;Result: |
;; eax<>0 - linear address of page |
;; eax=0 - not enough memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Page_Linear |
MEM_Alloc_Page_Linear: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Alloc_Page_Linear_loop: |
push ecx |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
cmp dword [ecx],0 |
jz MEM_Alloc_Page_Linear_loopend |
mov eax,[ecx] |
push dword [eax] |
pop dword [ecx] |
push eax |
sub eax,ecx |
shr eax,10 |
mov word [ecx+.range_info+eax],1 |
pop eax |
pop ecx |
jmp MEM_Alloc_Page_Linear_ret |
MEM_Alloc_Page_Linear_loopend: |
pop ecx |
sub ecx,16 |
jns MEM_Alloc_Page_Linear_loop |
xor eax,eax |
MEM_Alloc_Page_Linear_ret: |
call MEM_Heap_UnLock |
pop ecx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Page |
;;Remove reference and free page if number of |
;;references is equal to 0 |
;;Parameters: |
;; eax - physical address of page |
;;Result: |
;; eax - 1 success |
;; eax - 0 failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Page |
MEM_Free_Page: |
test eax,eax |
jz MEM_Free_Page_Zero |
test eax,0xFFF |
jnz MEM_Free_Page_Not_Aligned |
push ebx |
push ecx |
push edx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Free_Page_Heap_loop: |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
js MEM_Free_Page_Heap_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Free_Page_Heap_loopend |
MEM_Free_Page_Heap_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
sub ecx,16 |
jns MEM_Free_Page_Heap_loop |
xor eax,eax |
inc eax |
jmp MEM_Free_Page_ret |
MEM_Free_Page_Heap_loopend: |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
mov ebx,eax |
add eax,ecx |
shr ebx,10 |
mov edx,[ecx+.range_info+ebx] |
test edx,0x80000000 |
jnz MEM_Free_Page_Bucket |
test dx,dx |
jz MEM_Free_Page_Error |
dec word [ecx+.range_info+ebx] |
jnz MEM_Free_Page_OK |
MEM_Free_Page_Bucket: |
push dword [ecx] |
mov [ecx],eax |
pop dword [eax] |
mov dword [ecx+.range_info+ebx],0 |
MEM_Free_Page_OK: |
mov eax,1 |
MEM_Free_Page_ret: |
call MEM_Heap_UnLock |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Free_Page_Error: |
xor eax,eax |
jmp MEM_Free_Page_ret |
MEM_Free_Page_Zero: |
inc eax |
ret |
MEM_Free_Page_Not_Aligned: |
xor eax,eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Page_Linear |
;;Remove reference and free page if number of |
;;references is equal to 0 |
;;Parameters: |
;; eax - linear address of page |
;;Result: |
;; eax - 1 success |
;; eax - 0 failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Page_Linear |
MEM_Free_Page_Linear: |
test eax,eax |
jz MEM_Free_Page_Linear_Zero |
test eax,0xFFF |
jnz MEM_Free_Page_Linear_Not_Aligned |
push ebx |
push ecx |
push edx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
|
MEM_Free_Page_Linear_Heap_loop: |
sub eax,[MEM_heap_block+ecx+.heap_linear_address] |
js MEM_Free_Page_Linear_Heap_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Free_Page_Linear_Heap_loopend |
MEM_Free_Page_Linear_Heap_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
sub ecx,16 |
jns MEM_Free_Page_Linear_Heap_loop |
xor eax,eax |
inc eax |
jmp MEM_Free_Page_Linear_ret |
|
MEM_Free_Page_Linear_Heap_loopend: |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
mov ebx,eax |
add eax,ecx |
shr ebx,10 |
mov edx,[ecx+.range_info+ebx] |
test edx,0x80000000 |
jnz MEM_Free_Page_Linear_Bucket |
test dx,dx |
jz MEM_Free_Page_Linear_Error |
dec word [ecx+.range_info+ebx] |
jnz MEM_Free_Page_Linear_OK |
MEM_Free_Page_Linear_Bucket: |
mov edx,[ecx] |
mov [eax],edx |
mov dword [eax+4],0 |
mov [ecx],eax |
test edx,edx |
jz MEM_Free_Page_No_Next |
mov [edx+4],eax |
MEM_Free_Page_No_Next: |
mov dword [ecx+.range_info+ebx],0 |
MEM_Free_Page_Linear_OK: |
xor eax, eax |
inc eax |
MEM_Free_Page_Linear_ret: |
call MEM_Heap_UnLock |
pop edx |
pop ecx |
pop ebx |
ret |
|
MEM_Free_Page_Linear_Error: |
xor eax,eax |
jmp MEM_Free_Page_Linear_ret |
|
MEM_Free_Page_Linear_Zero: |
inc eax |
ret |
|
MEM_Free_Page_Linear_Not_Aligned: |
xor eax,eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Pages |
;;Allocates set of pages. |
;;Parameters: |
;; eax - number of pages |
;; ebx - buffer for physical addresses |
;;Result: |
;; eax - number of allocated pages |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Pages |
MEM_Alloc_Pages: |
push eax |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Alloc_Pages_ret |
MEM_Alloc_Pages_loop: |
call MEM_Alloc_Page |
test eax,eax |
jz MEM_Alloc_Pages_ret |
mov [ebx],eax |
add ebx,4 |
dec ecx |
jnz MEM_Alloc_Pages_loop |
MEM_Alloc_Pages_ret: |
sub [esp+8],ecx |
pop ecx |
pop ebx |
pop eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Pages_Linear |
;;Allocates set of pages. |
;;Parameters: |
;; eax - number of pages |
;; ebx - buffer for linear addresses |
;;Result: |
;; eax - number of allocated pages |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Pages_Linear |
MEM_Alloc_Pages_Linear: |
push eax |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Alloc_Pages_Linear_ret |
MEM_Alloc_Pages_Linear_loop: |
call MEM_Alloc_Page_Linear |
test eax,eax |
jz MEM_Alloc_Pages_Linear_ret |
mov [ebx],eax |
add ebx,4 |
dec ecx |
jnz MEM_Alloc_Pages_Linear_loop |
MEM_Alloc_Pages_Linear_ret: |
sub [esp+8],ecx |
pop ecx |
pop ebx |
pop eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Pages |
;;Parameters: |
;; eax - number of pages |
;; ebx - array of addresses |
;;Result: |
;; eax=1 - succcess |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Pages |
MEM_Free_Pages: |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Free_Pages_ret |
MEM_Free_Pages_loop: |
mov eax,[ebx] |
call MEM_Free_Page |
add ebx,4 |
test eax,eax |
jz MEM_Free_Pages_ret |
dec ecx |
jnz MEM_Free_Pages_loop |
MEM_Free_Pages_ret: |
pop ecx |
pop ebx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Pages_Linear |
;;Parameters: |
;; eax - number of pages |
;; ebx - array of addresses |
;;Result: |
;; eax=1 - succcess |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Pages_Linear |
MEM_Free_Pages_Linear: |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Free_Pages_Linear_ret |
MEM_Free_Pages_Linear_loop: |
mov eax,[ebx] |
call MEM_Free_Page_Linear |
add ebx,4 |
test eax,eax |
jz MEM_Free_Pages_Linear_ret |
dec ecx |
jnz MEM_Free_Pages_Linear_loop |
MEM_Free_Pages_Linear_ret: |
pop ecx |
pop ebx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Heap_Number |
;;Calculate number of heap which pointer belongs to. |
;;Parameter: |
;; eax - address |
;;Result: |
;; ecx - number of heap*16. |
;; eax=0 if address not found. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Heap_Number |
MEM_Get_Heap_Number: |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Heap_loop: |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
jl MEM_Get_Heap_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Get_Heap_loopend |
MEM_Get_Heap_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
sub ecx,16 |
jns MEM_Get_Heap_loop |
call MEM_Heap_UnLock |
xor eax,eax |
ret |
MEM_Get_Heap_loopend: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
call MEM_Heap_UnLock |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Heap_Number_Linear |
;;Calculate number of heap which pointer belongs to. |
;;Parameter: |
;; eax - address |
;;Result: |
;; ecx - number of heap*16. |
;; eax=0 if address not found. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Heap_Number_Linear |
MEM_Get_Heap_Number_Linear: |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Heap_Linear_loop: |
sub eax,[MEM_heap_block+ecx+.heap_linear_address] |
jl MEM_Get_Heap_Linear_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Get_Heap_Linear_loopend |
MEM_Get_Heap_Linear_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
sub ecx,16 |
jns MEM_Get_Heap_Linear_loop |
call MEM_Heap_UnLock |
xor eax,eax |
ret |
MEM_Get_Heap_Linear_loopend: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
call MEM_Heap_UnLock |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc |
;;Allocate small region. |
;;Parameters: |
;; eax - size (0<eax<=4096) |
;;Result: |
;; eax - linear address |
;; eax=0 - not enough memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc |
MEM_Alloc: |
;find chain |
test eax,eax |
jng MEM_Alloc_Wrong_Size |
cmp eax,4096 |
jg MEM_Alloc_Wrong_Size |
push ebx |
push ecx |
push edx |
push esi |
dec eax |
shr eax,4 |
xor edx,edx |
MEM_Alloc_Find_Size: |
add edx,4 |
shr eax,1 |
jnz MEM_Alloc_Find_Size |
MEM_Alloc_Size_Found: |
mov ecx,edx |
shr ecx,2 |
add ecx,4 |
mov eax,1 |
shl eax,cl |
mov esi,eax |
;esi - block size |
;edx - offset |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Alloc_Find_Heap: |
mov eax,[MEM_heap_block+ecx+.heap_linear_address] |
cmp dword [eax+edx],0 |
jnz MEM_Alloc_Use_Existing |
sub ecx,16 |
jns MEM_Alloc_Find_Heap |
;create new bucket page |
call MEM_Alloc_Page_Linear |
call MEM_Get_Heap_Number_Linear |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
mov [ecx+edx],eax |
lea ebx,[eax+4096] |
MEM_Alloc_List_loop: |
mov [eax],eax |
mov [eax+4],eax |
add [eax],esi |
sub [eax+4],esi |
add eax,esi |
cmp eax,ebx |
jnz MEM_Alloc_List_loop |
sub ebx,esi |
mov dword [ebx],0 |
sub eax,4096 |
mov dword [eax+4],0 |
mov eax,ecx |
|
MEM_Alloc_Use_Existing: |
mov ebx,eax |
mov eax,[eax+edx] |
mov ecx,[eax] |
mov [ebx+edx],ecx |
test ecx,ecx |
jz MEM_Alloc_Became_Empty |
mov dword [ecx+4],0 |
MEM_Alloc_Became_Empty: |
mov ecx,eax |
sub ecx,ebx |
shr ecx,10 |
and ecx,0xFFFFFFFC |
inc byte [ebx+.range_info+ecx+2] |
shr edx,2 |
add edx,128 |
dec edx |
mov [ebx+.range_info+ecx+3],dl |
|
MEM_Alloc_ret: |
call MEM_Heap_UnLock |
pop esi |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Alloc_Wrong_Size: |
xor eax,eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free |
;;Parameters: |
;; eax - linear address |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free |
MEM_Free: |
test eax,eax |
jz MEM_Free_Zero |
push ebx |
push ecx |
push edx |
push esi |
push edi |
push ebp |
call MEM_Heap_Lock |
call MEM_Get_Heap_Number_Linear |
test eax,eax |
jz MEM_Free_ret |
mov edx,eax |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
sub edx,ecx |
shr edx,10 |
and edx,0xFFFFFFFC |
mov ebx,[ecx+.range_info+edx] |
mov esi,ebx |
shr esi,24 |
sub esi,128 |
mov edi,[ecx+4+4*esi] |
mov [eax],edi |
mov dword [eax+4],0 |
test edi,edi |
jz MEM_Free_Empty_List |
mov [edi+4],eax |
MEM_Free_Empty_List: |
mov [ecx+4+4*esi],eax |
sub ebx,0x10000 |
mov [ecx+.range_info+edx],ebx |
test ebx,0xFF0000 |
jnz MEM_Free_ret |
;delete empty blocks on the page |
lea edx,[esi+5] |
and eax,0xFFFFF000 |
mov edi,eax |
mov eax,1 |
xchg ecx,edx |
shl eax,cl |
mov ecx,edx |
mov edx,eax |
;edx - size of block |
;edi - start of page |
mov eax,edi |
lea ebx,[eax+4096] |
MEM_Free_Block_loop: |
cmp dword [eax+4],0 |
jnz MEM_Free_Block_Not_First |
mov ebp,dword [eax] |
mov [ecx+4+4*esi],ebp |
test ebp,ebp |
jz MEM_Free_Block_Last |
mov dword [ebp+4],0 |
MEM_Free_Block_Last: |
jmp MEM_Free_Block_loop_end |
MEM_Free_Block_Not_First: |
mov ebp,dword [eax] |
push ebp |
mov ebp,dword [eax+4] |
pop dword [ebp] |
mov ebp,dword [eax] |
test ebp,ebp |
jz MEM_Free_Block_loop_end |
push dword [eax+4] |
pop dword [ebp+4] |
; jmp MEM_Free_Block_loop_end |
MEM_Free_Block_loop_end: |
add eax,edx |
cmp eax,ebx |
jnz MEM_Free_Block_loop |
mov eax,edi |
call MEM_Free_Page_Linear |
MEM_Free_ret: |
call MEM_Heap_UnLock |
pop ebp |
pop edi |
pop esi |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Free_Zero: |
inc eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Add_Reference |
;; eax - physical address of page |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Add_Reference |
MEM_Add_Reference: |
push ebx |
push ecx |
call MEM_Heap_Lock |
call MEM_Get_Heap_Number |
test eax,eax |
jz MEM_Add_Reference_ret |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
shr eax,10 |
and eax,0xFFFFFFFC |
test dword [ecx+eax+.range_info],0x80000000 |
jnz MEM_Add_Reference_failed |
inc dword [ecx+eax+.range_info] |
MEM_Add_Reference_ret: |
call MEM_Heap_UnLock |
pop ecx |
pop ebx |
ret |
MEM_Add_Reference_failed: |
xor eax,eax |
jmp MEM_Add_Reference_ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Add_Reference_Linear |
;; eax - linear address of page |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Add_Reference_Linear |
MEM_Add_Reference_Linear: |
push ebx |
push ecx |
call MEM_Heap_Lock |
call MEM_Get_Heap_Number_Linear |
test eax,eax |
jz MEM_Add_Reference_Linear_ret |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
sub eax,ecx |
shr eax,10 |
and eax,0xFFFFFFFC |
test dword [ecx+eax+.range_info],0x80000000 |
jnz MEM_Add_Reference_Linear_failed |
inc dword [ecx+eax+.range_info] |
mov eax,1 |
MEM_Add_Reference_Linear_ret: |
call MEM_Heap_UnLock |
pop ecx |
pop ebx |
ret |
MEM_Add_Reference_Linear_failed: |
xor eax,eax |
jmp MEM_Add_Reference_Linear_ret |
end if |
end if ;memmanager.inc |