;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $Revision$ MEM_LIST_OFFSET equ 8 FREE_BLOCK equ 4 USED_BLOCK equ 8 DONT_FREE_BLOCK equ 10h ;;;;;;;;;;;;;; USER ;;;;;;;;;;;;;;;;; HEAP_TOP equ 0x7FC00000 align 4 _init_user_heap: init_heap: mov ebx,[current_slot] mov eax, [ebx+APPDATA.heap_top] test eax, eax jz @F sub eax,[ebx+APPDATA.heap_base] sub eax, 4096 ret @@: mov edx, [ebx+APPDATA.mem_size] add edx, 4095 and edx, not 4095 mov [ebx+APPDATA.mem_size], edx mov eax, HEAP_TOP mov [ebx+APPDATA.heap_base], edx mov [ebx+APPDATA.heap_top], eax sub eax, edx shr edx, 10 mov ecx, eax sub eax, 4096 or ecx, FREE_BLOCK mov [page_tabs+edx], ecx ret align 4 _UserAlloc: proc user_alloc stdcall, alloc_size:dword push ebx push esi push edi mov ecx, [alloc_size] add ecx, (4095+4096) and ecx, not 4095 mov ebx, [current_slot] mov esi, dword [ebx+APPDATA.heap_base] ; heap_base mov edi, dword [ebx+APPDATA.heap_top] ; heap_top l_0: cmp esi, edi jae m_exit mov ebx, esi shr ebx, 12 mov eax, [page_tabs+ebx*4] test al, FREE_BLOCK jz test_used and eax, 0xFFFFF000 cmp eax, ecx ;alloc_size jb m_next jz @f lea edx, [esi+ecx] sub eax, ecx or al, FREE_BLOCK shr edx, 12 mov [page_tabs+edx*4], eax @@: or ecx, USED_BLOCK mov [page_tabs+ebx*4], ecx shr ecx, 12 inc ebx dec ecx jz .no @@: mov dword [page_tabs+ebx*4], 2 inc ebx dec ecx jnz @B .no: mov edx, [current_slot] mov ebx, [alloc_size] add ebx, 0xFFF and ebx, not 0xFFF add ebx, [edx+APPDATA.mem_size] call update_mem_size lea eax, [esi+4096] pop edi pop esi pop ebx ret test_used: test al, USED_BLOCK jz m_exit and eax, 0xFFFFF000 m_next: add esi, eax jmp l_0 m_exit: xor eax, eax pop edi pop esi pop ebx ret endp align 4 _UserFree: proc user_free stdcall, base:dword push esi mov esi, [base] test esi, esi jz .exit push ebx xor ebx, ebx shr esi, 12 mov eax, [page_tabs+(esi-1)*4] test al, USED_BLOCK jz .cantfree test al, DONT_FREE_BLOCK jnz .cantfree push edi and eax, not 4095 mov edi, eax or al, FREE_BLOCK mov [page_tabs+(esi-1)*4], eax sub edi, 4096 mov ebx, edi shr edi, 12 jz .released .release: xor ecx, ecx xchg ecx, [page_tabs+esi*4] test cl, 1 jz @F call @frame_free@4 mov eax, esi shl eax, 12 invlpg [eax] @@: inc esi dec edi jnz .release .released: mov edx, [current_slot] mov esi, dword [edx+APPDATA.heap_base] mov edi, dword [edx+APPDATA.heap_top] sub ebx, [edx+APPDATA.mem_size] neg ebx call update_mem_size call user_normalize pop edi pop ebx pop esi ret .exit: xor eax, eax inc eax pop esi ret .cantfree: xor eax, eax pop ebx pop esi ret endp user_normalize: ; in: esi=heap_base, edi=heap_top ; out: eax=0 <=> OK ; destroys: ebx,edx,esi,edi shr esi, 12 shr edi, 12 @@: mov eax, [page_tabs+esi*4] test al, USED_BLOCK jz .test_free shr eax, 12 add esi, eax jmp @B .test_free: test al, FREE_BLOCK jz .err mov edx, eax shr edx, 12 add edx, esi cmp edx, edi jae .exit mov ebx, [page_tabs+edx*4] test bl, USED_BLOCK jz .next_free shr ebx, 12 add edx, ebx mov esi, edx jmp @B .next_free: test bl, FREE_BLOCK jz .err and dword [page_tabs+edx*4], 0 add eax, ebx and eax, not 4095 or eax, FREE_BLOCK mov [page_tabs+esi*4], eax jmp @B .exit: xor eax, eax inc eax ret .err: xor eax, eax ret user_realloc: ; in: eax = pointer, ebx = new size ; out: eax = new pointer or NULL test eax, eax jnz @f ; realloc(NULL,sz) - same as malloc(sz) push ebx call user_alloc ret @@: push ecx edx lea ecx, [eax - 0x1000] shr ecx, 12 mov edx, [page_tabs+ecx*4] test dl, USED_BLOCK jnz @f ; attempt to realloc invalid pointer .ret0: pop edx ecx xor eax, eax ret @@: test dl, DONT_FREE_BLOCK jnz .ret0 add ebx, 0x1FFF shr edx, 12 shr ebx, 12 ; edx = allocated size, ebx = new size add edx, ecx add ebx, ecx cmp edx, ebx jb .realloc_add ; release part of allocated memory push ecx .loop: cmp edx, ebx jz .release_done dec edx xor ecx, ecx xchg ecx, [page_tabs+edx*4] test al, 1 jz .loop push edx call @frame_free@4 pop edx mov eax, edx shl eax, 12 invlpg [eax] jmp .loop .release_done: pop ecx sub ebx, ecx cmp ebx, 1 jnz .nofreeall mov eax, [page_tabs+ecx*4] and eax, not 0xFFF mov edx, [current_slot] mov ebx, [APPDATA.mem_size+edx] sub ebx, eax add ebx, 0x1000 or al, FREE_BLOCK mov [page_tabs+ecx*4], eax push esi edi mov esi, [APPDATA.heap_base+edx] mov edi, [APPDATA.heap_top+edx] call update_mem_size call user_normalize pop edi esi jmp .ret0 ; all freed .nofreeall: sub edx, ecx shl ebx, 12 or ebx, USED_BLOCK xchg [page_tabs+ecx*4], ebx shr ebx, 12 sub ebx, edx push ebx ecx edx mov edx, [current_slot] shl ebx, 12 sub ebx, [APPDATA.mem_size+edx] neg ebx call update_mem_size pop edx ecx ebx lea eax, [ecx+1] shl eax, 12 push eax add ecx, edx lea edx, [ecx+ebx] shl ebx, 12 jz .ret push esi mov esi, [current_slot] mov esi, [APPDATA.heap_top+esi] shr esi, 12 @@: cmp edx, esi jae .merge_done mov eax, [page_tabs+edx*4] test al, USED_BLOCK jnz .merge_done and dword [page_tabs+edx*4], 0 shr eax, 12 add edx, eax shl eax, 12 add ebx, eax jmp @b .merge_done: pop esi or ebx, FREE_BLOCK mov [page_tabs+ecx*4], ebx .ret: pop eax edx ecx ret .realloc_add: ; get some additional memory mov eax, [current_slot] mov eax, [APPDATA.heap_top+eax] shr eax, 12 cmp edx, eax jae .cant_inplace mov eax, [page_tabs+edx*4] test al, FREE_BLOCK jz .cant_inplace shr eax, 12 add eax, edx sub eax, ebx jb .cant_inplace jz @f shl eax, 12 or al, FREE_BLOCK mov [page_tabs+ebx*4], eax @@: mov eax, ebx sub eax, ecx shl eax, 12 or al, USED_BLOCK mov [page_tabs+ecx*4], eax lea eax, [ecx+1] shl eax, 12 push eax push edi lea edi, [page_tabs+edx*4] mov eax, 2 sub ebx, edx mov ecx, ebx cld rep stosd pop edi mov edx, [current_slot] shl ebx, 12 add ebx, [APPDATA.mem_size+edx] call update_mem_size pop eax edx ecx ret .cant_inplace: push esi edi mov eax, [current_slot] mov esi, [APPDATA.heap_base+eax] mov edi, [APPDATA.heap_top+eax] shr esi, 12 shr edi, 12 sub ebx, ecx .find_place: cmp esi, edi jae .place_not_found mov eax, [page_tabs+esi*4] test al, FREE_BLOCK jz .next_place shr eax, 12 cmp eax, ebx jae .place_found add esi, eax jmp .find_place .next_place: shr eax, 12 add esi, eax jmp .find_place .place_not_found: pop edi esi jmp .ret0 .place_found: sub eax, ebx jz @f push esi add esi, ebx shl eax, 12 or al, FREE_BLOCK mov [page_tabs+esi*4], eax pop esi @@: mov eax, ebx shl eax, 12 or al, USED_BLOCK mov [page_tabs+esi*4], eax inc esi mov eax, esi shl eax, 12 push eax mov eax, [page_tabs+ecx*4] and eax, not 0xFFF or al, FREE_BLOCK sub edx, ecx mov [page_tabs+ecx*4], eax inc ecx dec ebx dec edx jz .no @@: xor eax, eax xchg eax, [page_tabs+ecx*4] mov [page_tabs+esi*4], eax mov eax, ecx shl eax, 12 invlpg [eax] inc esi inc ecx dec ebx dec edx jnz @b .no: push ebx mov edx, [current_slot] shl ebx, 12 add ebx, [APPDATA.mem_size+edx] call update_mem_size pop ebx @@: mov dword [page_tabs+esi*4], 2 inc esi dec ebx jnz @b pop eax edi esi edx ecx ret if 0 align 4 proc alloc_dll pushf cli bsf eax, [dll_map] jnz .find popf xor eax, eax ret .find: btr [dll_map], eax popf shl eax, 5 add eax, dll_tab ret endp align 4 proc alloc_service pushf cli bsf eax, [srv_map] jnz .find popf xor eax, eax ret .find: btr [srv_map], eax popf shl eax,0x02 lea eax,[srv_tab+eax+eax*8] ;srv_tab+eax*36 ret endp end if