#include "kernel/prelude/kernel_prelude.hats" #define ATS_DYNLOADFLAG 0 staload "./frame.sats" staload "kernel/bootinfo/multiboot.sats" staload UN = "prelude/SATS/unsafe.sats" implement containing_address(address) : frame_t = @{ counter = $UN.cast{size_t}(address) / i2sz(PAGE_SIZE) } fn choose_next_area{l,k : agz}(pf : !frame_allocator_t@l, bf : !boot_info_t @ k | p : ptr l, b : ptr k) : void = let in end implement allocate_frame(pf , bf | p,b) : frame_t = if (p->current_area.length > 1) then let val area = p->current_area val frame = @{ num = p->next_free_frame.num } // last frame of current area val last_frame_area = containing_address(ptr_add(area.base_addr,area.length - i2sz(1))) in if (frame.num > last_frame_area.num) then ( // all frames of current area are used, switch to next area choose_next_area(pf, bf | p,b); allocate_frame(pf,bf | p,b) ) else if (frame.num > p->kernel_start.num && frame.num <= p->kernel_end.num) then ( // frame is used by kernel p->next_free_frame := @{num = p->kernel_end.num + 1}; allocate_frame(pf,bf | p,b) ) else if (frame.num > p->multiboot_start.num && frame.num <= p->multiboot_end.num) then ( // frame is used by multiboot info structure p->next_free_frame := @{num = p->multiboot_end.num + 1}; allocate_frame(pf,bf | p,b) ) else ( // frame is unused, increment `next_free_frame` and return it p->next_free_frame.num := succ(p->next_free_frame.num); frame ); end else @{num = i2sz(0)} // No free frames left implement deallocate_frame(p) : void = let in end