From 535444eb2a13e0f94f9b0811000d8298496b15ee Mon Sep 17 00:00:00 2001 From: nub31 Date: Mon, 3 Feb 2025 22:31:23 +0100 Subject: [PATCH] alloc/free working (not merging) --- input/baseline/alloc.asm | 153 +++++++++++++++++++++++++++++---------- 1 file changed, 115 insertions(+), 38 deletions(-) diff --git a/input/baseline/alloc.asm b/input/baseline/alloc.asm index be65199..080190c 100644 --- a/input/baseline/alloc.asm +++ b/input/baseline/alloc.asm @@ -6,52 +6,120 @@ section .bss section .text alloc: - add rdi, 16 ; add space for metadata - mov rax, [free_list_head] ; load head of free list - xor r8, r8 ; last block + add rdi, 16 ; reserve 16 bytes for metadata + mov rsi, [free_list_head] + xor r8, r8 .loop: - test rax, rax ; end of list? - jz .new_block ; yes? allocate new block - cmp [rax], rdi ; does object fit in block and have space for metadata? - jge .found_block ; yes? use this block - mov r8, rax - mov rax, [rax + 8] ; load next free block - jb .loop ; no? go to next block -.found_block: - sub qword [rax], rdi ; reduce the available size of the block - cmp qword [rax], 0 ; no space left in block? - jg .done_remove_free_block ; no? do not remove block from free list - mov rsi, [rax + 8] ; yes? remove block from free list - test r8, r8 ; is current head of list? - jz .remove_free_head ; yes? remove head - mov [r8 + 8], rsi ; set prev.next to this.next - jmp .done_remove_free_block -.remove_free_head: - mov [free_list_head], rsi -.done_remove_free_block: - mov rsi, [rax] ; load size of block excluding the newly allocated object - lea rax, [rax + rsi + 16] ; address of allocated block - sub rdi, 16 - mov [rax], rdi ; save size - mov rsi, [alloc_list_head] ; load head of allocated blocks - mov [rax + 8], rsi ; move head to be next item after this block - mov [alloc_list_head], rax ; set new head to this block - lea rax, [rax + 16] ; skip metadata for return value - ret + test rsi, rsi ; allocate new block if end of list is reached + jz .new_block + mov rdx, [rsi] + cmp rdx, rdi ; is there enough space for allocation? + ja .use_block ; yes? allocate + add rdx, 16 + cmp rdx, rdi ; no? is there enough space if we include metadata + je .use_block ; if we include metadata, the sizes has to match exactly, or partial metadata will persist + mov r8, rsi ; r8 contains the node from the last iteration + mov rsi, [rsi + 8] ; next node + jmp .loop .new_block: push rdi push r8 - mov rdi, 4096 ; page size - call sys_mmap ; allocate a page - mov qword [rax], 4080 ; set size of block to block size - metadata - mov rsi, [free_list_head] - mov qword [rax + 8], rsi ; move head to be the next item after this block - mov [free_list_head], rax ; set new head to this block + add rdi, 16 + mov rsi, 4096 + call max + push rax + mov rdi, rax + call sys_mmap + pop rsi + sub rsi, 16 + mov qword [rax], rsi ; update metadata to page size - metadata + push rax + mov rdi, rax + call insert_into_free + pop rsi pop r8 pop rdi - jmp .found_block +.use_block: + cmp [rsi], rdi ; check if the block will be empty after allocation + ja .unlink_done ; if not, do not unlink + test r8, r8 ; r8 is null if node is also head + jz .unlink_head + mov rdx, [rsi + 8] ; load next node + mov [r8 + 8], rdx ; link next node to last node's next + jmp .unlink_done +.unlink_head: + mov rdx, [free_list_head] ; load head + mov rdx, [rdx + 8] ; load head.next + mov [free_list_head], rdx ; mov head.next into head +.unlink_done: + sub [rsi], rdi ; reduce available space of block by the allocated space + mov rdx, [rsi] ; load the available space excluding the newly allocated space + lea rax, [rsi + rdx + 16] ; load the address of the newly allocated space + sub rdi, 16 + mov [rax], rdi ; update metadata to allocation size - metadata + mov rdx, [alloc_list_head] + mov [rax + 8], rdx ; move head to nex item in this alloc + mov [alloc_list_head], rax ; update head to point to this node + lea rax, [rax + 16] ; skip past metadata for return value + ret free: + lea rdi, [rdi - 16] ; adjust for metadata + mov rsi, [alloc_list_head] + xor r8, r8 +.loop: + test rsi, rsi + jz .not_found + cmp rdi, rsi + je .found + mov r8, rsi + mov rsi, [rsi + 8] ; next node + jmp .loop +.not_found: + mov rax, 60 + mov rdi, 1 + syscall +.found: + test r8, r8 ; r8 is null if node is also head + jz .unlink_head + mov rdx, [rsi + 8] ; load next node + mov [r8 + 8], rdx ; link next node to last node's next + jmp .unlink_done +.unlink_head: + mov rdx, [alloc_list_head] ; load head + mov rdx, [rdx + 8] ; load head.next + mov [alloc_list_head], rdx ; mov head.next into head +.unlink_done: + mov rdi, rsi + call insert_into_free + ret + +insert_into_free: + mov rsi, [free_list_head] ; load head + test rsi, rsi ; is list empty + jz .insert_head ; if empty, insert at head + cmp rdi, rsi ; is input smaller then head + jl .insert_head ; if smaller, insert at head + xor r8, r8 ; r9 will track the previous node +.loop: + test rsi, rsi + jz .insert_end ; if at end of list, insert at end + cmp rdi, [rsi + 8] ; compare input to next node + jg .next ; if larger, skip to next node + mov [rsi + 8], rdi ; if smaller, insert at this position + mov [rdi + 8], rdx + ret +.next: + mov r8, rsi ; update r8 to current node + mov rsi, [rsi + 8] ; update rsi to next node + jmp .loop +.insert_head: + mov rdx, [free_list_head] + mov [rdi + 8], rdx + mov [free_list_head], rdi + ret +.insert_end: + mov [r8 + 8], rdi ; update last node's next to point at rdi ret sys_mmap: @@ -81,3 +149,12 @@ sys_munmap: mov rax, 60 mov rdi, 1 syscall + +max: + cmp rdi, rsi + jae .left + mov rax, rsi + ret +.left: + mov rax, rdi + ret