if ~defined memmanager_inc memmanager_inc_fix: memmanager_inc fix memmanager_inc_fix ;for testing in applications ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; uglobal MEM_heap_block rd .heap_block_info*max_heaps/4 MEM_heap_count rd 1 MEM_cli_count rd 1 MEM_cli_prev rd 1 MEM_FreeSpace rd 1 ; MEM_AllSpace rd 1 endg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;MEM_Init ;;Initialize memory manager structures. ;;Must be called first. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MEM_Init: push eax xor eax,eax mov [MEM_cli_prev],eax ;init value = 0 dec eax mov [MEM_cli_count],eax ;init value = -1 pop eax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;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: 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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;MEM_Heap_UnLock ;;After this routine operations with heap are allowed. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MEM_Heap_UnLock: 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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;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 push edi mov edi,edx shr edi,12 sub edi,ebx ;edi=-free space sub [MEM_FreeSpace],edi ; sub [MEM_AllSpace],edi mov [eax],eax add [eax],edx ;first 4 bytes - pointer to first free page ;clean page info area 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] dec [MEM_FreeSpace] 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 dec [MEM_FreeSpace] 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) | (used MEM_Free_Page_Linear) 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 inc [MEM_FreeSpace] 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_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_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_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_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