;; 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 ? .vmflag 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: _vmm_segfree ;; ;; In: ;; EAX - Segment address _vmm_segfree: ;mov ecx, eax ;add ecx, VmSegment.seglist.next ;mov edx, [pVmmFreeSegHead] ;or edx, edx ;jz @f ;mov [eax + VmSegment.seglist.next], edx ;mov [edx + VmSegment.seglist.prev], ecx ;@@: ; mov [pVmmFreeSegHead], eax ; mov [eax + VmSegment.seglist.prev], ecx ; ; inc [iVmmFreeSegCount] ret ; ; ;; Function: _vmm_segalloc ;_vmm_segalloc: ; mov eax, [pVmmFreeSegHead] ; or eax, eax ; jz @f ; ; dec [iVmmFreeSegCount] ;@@: ; 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 mov [eax + Vmem.base], ecx if CONFIG_TRACE_VMEM push esi push edi push ebx mov esi, eax mov edi, edx mov ebx, ecx mov eax, esi mov edx, edi mov ecx, ebx pop ebx pop edi pop esi end if 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: ret ;;; MARK: variables aVmemStaticSegs db STATIC_SEG_COUNT*sizeof.VmSegment dup(0) pVmemFreeSegHead dd 0 iVmemFreeSegCount dd 0 if CONFIG_TRACE_VMM 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