forked from KolibriOS/kolibrios
d5c0fed779
git-svn-id: svn://kolibrios.org@2 a494cfbc-eb01-0410-851d-a64ba20cac60
978 lines
25 KiB
PHP
978 lines
25 KiB
PHP
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
|