diff --git a/fox32os.def b/fox32os.def index 1da9a31..2f5515e 100644 --- a/fox32os.def +++ b/fox32os.def @@ -13,3 +13,4 @@ end_current_task: jmp [0x00000838] ; memory jump table allocate_memory: jmp [0x00000840] +free_memory: jmp [0x00000844] diff --git a/kernel/allocator.asm b/kernel/allocator.asm index 17a9282..6343438 100644 --- a/kernel/allocator.asm +++ b/kernel/allocator.asm @@ -1,35 +1,191 @@ ; memory allocator routines -; this is a very basic memory allocator, it doesn't even allow freeing -; TODO: make this better -const MEMORY_TOP: 0x02000000 +; block header fields: +; data.32 size - size of block, NOT INCLUDING THE HEADER +; data.32 prev - pointer to previous free block, or zero +; data.32 next - pointer to next free block, or zero + +const HEADER_SIZE: 12 +const MEMORY_TOP: 0x02000000 + +initialize_allocator: + push r0 + push r1 + + mov [free_list_head], kernel_bottom + + ; set the free block size to MEMORY_TOP - [free_list_head] + mov r0, [free_list_head] + mov r1, MEMORY_TOP + sub r1, r0 + mov [r0], r1 + + ; mark this as the only free block + add r0, 4 + mov [r0], 0 + add r0, 4 + mov [r0], 0 + + pop r1 + pop r0 + ret ; allocate a block of memory ; inputs: ; r0: size in bytes ; outputs: -; r0: pointer to allocated block (or zero if no blocks free) +; r0: pointer to allocated block (or zero if no blocks free of requested size) allocate_memory: + push r1 + push r10 + push r11 + + mov [block], [free_list_head] + + ; r10: real_size = requested size + header size + mov r10, r0 + add r10, HEADER_SIZE +allocate_memory_while_block: + mov r0, [block] + call block_get_size + cmp r0, r10 + ifgteq jmp allocate_memory_good_block + + ; block = block->next + mov r0, [block] + call block_get_next + mov [block], r0 + + cmp [block], 0 + ifnz jmp allocate_memory_while_block + ; if we reach this point, no good blocks were found + mov r0, 0 + + pop r11 + pop r10 + pop r1 + ret +allocate_memory_good_block: + mov r11, r10 + add r11, HEADER_SIZE + add r11, 16 + mov r0, [block] + call block_get_size + cmp r0, r11 + ifgt jmp allocate_memory_good_block_carve + + ; next = block->next + ; prev = block->prev + mov r0, [block] + call block_get_next + mov [next], r0 + mov r0, [block] + call block_get_prev + mov [prev], r0 + + cmp [next], 0 + ifnz call allocate_memory_good_block_set_nextprev + + cmp [prev], 0 + ifnz jmp allocate_memory_good_block_set_prevnext + mov [free_list_head], [next] +allocate_memory_good_block_ret: + mov r0, [block] + add r0, HEADER_SIZE + + pop r11 + pop r10 + pop r1 + ret +allocate_memory_good_block_carve: + ; block->size -= real_size + mov r0, [block] + call block_get_size + sub r0, r10 + mov r1, r0 + mov r0, [block] + call block_set_size + + ; block += block->size + mov r0, [block] + call block_get_size + add [block], r0 + + ; block->size = real_size + mov r0, [block] + mov r1, r10 + call block_set_size + + jmp allocate_memory_good_block_ret +allocate_memory_good_block_set_nextprev: + ; next->prev = prev + mov r0, [next] + mov r1, [prev] + call block_set_prev + ret +allocate_memory_good_block_set_prevnext: + ; prev->next = next + mov r0, [prev] + mov r1, [next] + call block_set_next + jmp allocate_memory_good_block_ret +block: data.32 0 +next: data.32 0 +prev: data.32 0 +block_get_size: + mov r0, [r0] + ret +block_set_size: + mov [r0], r1 + ret +block_get_prev: + add r0, 4 + mov r0, [r0] + ret +block_set_prev: + add r0, 4 + mov [r0], r1 + ret +block_get_next: + add r0, 8 + mov r0, [r0] + ret +block_set_next: + add r0, 8 + mov [r0], r1 + ret + +; free a block of memory +; inputs: +; r0: pointer to allocated block +; outputs: +; none +free_memory: + push r0 push r1 push r2 - mov r1, MEMORY_TOP - mov r2, [free_base] - sub r1, r2 - cmp r1, r0 - iflteq jmp allocate_memory_full - mov r1, [free_base] - add [free_base], r0 - mov r0, r1 - - pop r2 - pop r1 - ret -allocate_memory_full: - mov r0, 0 + ; point to the header + sub r0, HEADER_SIZE + mov r2, r0 + + ; add it to the free list + mov r1, 0 + call block_set_prev + mov r0, r2 + mov r1, [free_list_head] + call block_set_next + + cmp [free_list_head], 0 + ifnz mov r1, r0 + ifnz mov r0, [free_list_head] + ifnz call block_set_prev + + mov [free_list_head], r2 pop r2 pop r1 + pop r0 ret -free_base: data.32 kernel_bottom +free_list_head: data.32 kernel_bottom diff --git a/kernel/main.asm b/kernel/main.asm index cbb2053..97ca2bf 100644 --- a/kernel/main.asm +++ b/kernel/main.asm @@ -31,6 +31,7 @@ jump_table: ; memory jump table org.pad 0x00000840 data.32 allocate_memory + data.32 free_memory ; initialization code entry: @@ -38,7 +39,10 @@ entry: mov r0, BACKGROUND_COLOR call fill_background -draw_startup_text: + ; initialize the memory allocator + call initialize_allocator + + ; draw the startup text mov r0, startup_str mov r1, 16 mov r2, 464