;; File: vmem.inc ;; ;; General purpose resource allocator. ;; Based on and on ;;; MARK: macros and structs VM_BESTFIT = (1 shl 0) VM_INSTANTFIT = (1 shl 1) VM_NEXTFIT = (1 shl 2) VM_SLEEP = (1 shl 3) VM_NOSLEEP = (1 shl 4) VM_BOOTSTRAP = (1 shl 5) STATIC_SEG_COUNT = 64 FREELISTS_N = 4 * 8 HASHTABLE_N = 16 SEGMENT_ALLOCATED = 0 SEGMENT_FREE = 1 SEGMENT_SPAN = 2 macro GET_LIST reg, N { bsr reg, reg xor reg, 31 add reg, -N sub reg, 1 } struc VmSegment { .type db ? .imported db ? .base dd ? .size dd ? .spanlist ListEntry .seglist ListEntry } DEFN VmSegment ;; Struc: Vmem struc Vmem { .name db 16 dup(0) .base dd ? .size dd ? .quantum dd ? .alloc dd ? .free dd ? .source dd ? .flags dd ? .freelist dd FREELISTS_N dup(0) .hashtable dd HASHTABLE_N dup(0) .spanlist ListHead 0 } DEFN Vmem ;;; MARK: private functions ;; Function: _murmur32 ;; ;; In: ;; EAX - Address ;; ;; Out: ;; EAX - Hash ;; _murmur32: ; hash ← hash XOR (hash >> 16) mov ecx, eax shr ecx, 16 xor eax, ecx ; hash ← hash × 0x85ebca6b mov ecx, 0x85ebca6b mul ecx ; hash ← hash XOR (hash >> 13) mov ecx, eax shr ecx, 13 xor eax, ecx ; hash ← hash × 0xc2b2ae35 mov ecx, 0xc2b2ae35 mul ecx ; hash ← hash XOR (hash >> 16) mov ecx, eax shr ecx, 16 xor eax, ecx ret ;; Function: _hash_table_addr ;; ;; In: ;; EAX - Vmem ;; EDX - ADDR __hash_table_addr: push ebp mov ebp, esp push esi mov esi, eax mov eax, edx call _murmur32 and eax, HASHTABLE_N-1 ; x % y (y is a power of two) shl eax, 2 mov edx, esi add edx, Vmem.hashtable add edx, eax mov eax, [edx] pop esi leave ret ;; Function: _vmem_segfree ;; ;; In: ;; EAX - Segment address ;; _vmem_segfree: ; XXX: lock add eax, VmSegment.seglist mov edx, pVmemFreeSegHead xchg eax, edx call list_insert_head inc [iVmemFreeSegCount] ; XXX: unlock ret ;; Function: _vmem_segalloc ;; ;; Out: ;; EAX - Pointer to object on success, 0 on error _vmem_segalloc: push ebp mov ebp, esp ; XXX: lock mov eax, [pVmemFreeSegHead] or eax, eax jz .end push ebx mov ebx, eax call list_remove sub ebx, VmSegment.seglist dec [iVmemFreeSegCount] pop ebx .end: ; XXX: unlock leave ret ;;; MARK: public functions ;; Function: vmem_create ;; ;; Creates a new arena whose initial span is [Base, Base + Size). ;; ;; In: ;; EAX - Pointer to a object. ;; EDX - String. ;; ECX - Base. ;; ESP[4] - Size in bytes. ;; ESP[8] - Quantum. ;; ESP[12] - Alloc function. ;; ESP[16] - Free function. ;; ESP[20] - Source. ;; ESP[24] - Flags. ( or ) vmem_create: push ebp mov ebp, esp sub esp, 8 push esi push edi mov [ebp - 8], eax mov [ebp - 4], ecx ; zero Vmem object cld mov edi, eax xor eax, eax mov ecx, sizeof.Vmem shr 2 cld rep stosd ; copy name mov esi, edx mov edx, [ebp - 8] xor cl, cl @@: lodsb or al, al jz @f mov [edx], al inc edx inc cl cmp cl, 15 jl @b @@: mov edi, [ebp - 8] mov ecx, [ebp - 4] mov [edi + Vmem.base], ecx ; copy other from stack to struct mov ecx, 28 shr 2 mov esi, ebp add esi, 8 mov edi, [ebp - 8] add edi, Vmem.size rep movsd mov eax, [ebp - 8] mov edx, [ebp - 4] or edx, edx jnz @f mov ecx, [eax + Vmem.size] or ecx, ecx jz @f push dword [eax + Vmem.flags] call vmem_add add esp, 4 @@: if CONFIG_TRACE_VMEM mov esi, [ebp - 8] mov edx, [esi + Vmem.base] mov ecx, [esi + Vmem.size] add ecx, edx TRACE szTraceVmemCreate, esi, edx, ecx end if pop edi pop esi leave ret ;; Function: vmem_destroy ;; ;; Destroys an arena ;; ;; In: ;; EAX - Pointer to a object. vmem_destroy: ret ;; Function: vmem_alloc ;; ;; Allocates n-bytes from arena. ;; ;; In: ;; EAX - Pointer to a object. ;; EDX - Size in bytes. ;; ECX - Flags ;; ;; Out: ;; EAX - Allocated address on succes, 0 on failure. vmem_alloc: ret ;; Function: vmem_free ;; ;; Free n-bytes at address to arena ;; ;; In: ;; EAX - Pointer to a object. ;; EDX - Address. ;; ECX - Size in bytes. vmem_free: ret ;; Function: vmem_xalloc ;; ;; In: ;; EAX - Pointer to a object. ;; EDX - Size in bytes. ;; ECX - Alignment boundary. ;; ESP[4] - Phase. ;; ESP[8] - Nocross. ;; ESP[12] - Min address. ;; ESP[16] - Max address. ;; ESP[20] - Flags. (, , , , ) ;; ;; Out: ;; EAX - Allocated address on succes, 0 on failure. vmem_xalloc: ret ;; Function: vmem_xfree ;; ;; Frees n-bytes at address. ;; ;; In: ;; EAX - Pointer to object. ;; EDX - Address. ;; ECX - Size in bytes. vmem_xfree: ret ;; Function: vmem_add ;; ;; Adds a span [Address, Address + Size) to an arena. ;; ;; In: ;; EAX - Pointer to object. ;; EDX - Address. ;; ECX - Size in bytes. ;; ESP[4] - Flags. ( or ) ;; ;; Out: ;; EAX - Return Address on success, 0 on failure. vmem_add: push ebp mov ebp, esp push esi push edi push ebx mov esi, eax mov edi, ebx mov ebx, ecx pop ebx pop edi pop esi leave ret ;; Function: vmem_bootstrap ;; ;; Initialize static segments ;; vmem_bootstrap: push ebp mov ebp, esp if CONFIG_TRACE_VMEM TRACE szTraceVmemBootstrap end if push ebx xor ebx, ebx @@: mov eax, aVmemStaticSegs add eax, ebx call _vmem_segfree add ebx, sizeof.VmSegment cmp ebx, STATIC_SEG_COUNT*sizeof.VmSegment jl @b pop ebx leave ret ;;; MARK: variables aVmemStaticSegs db STATIC_SEG_COUNT*sizeof.VmSegment dup(0) pVmemFreeSegHead dd 0 iVmemFreeSegCount dd 0 if CONFIG_TRACE_VMM szTraceVmemBootstrap db "Trace(VMEM): Bootstrap vmem", 0 szTraceVmemCreate db "Trace(VMEM): Create %s [%x, %x)", 0 szTraceVmemAdd db "Trace(VMEM): %s: Add span [%x, %x)", 0 szTraceVmemDestroy db "Trace(VMEM): Destroy %s", 0 end if