@@ -1,6 +1,8 @@ #include #include +#include +#include /* heapa.c - kmheapa() "heap alloc" * ~ lexi hale * kmheapa() allocates a pointer on the heap à la libc malloc() * see also: kmheapf() "heap free" @@ -10,51 +12,52 @@ * whether or not they're for the correct * platform - only the ones actually called * by the generated code will be linked, * linker errors are our friend here! */ -extern void* kmem_posix_mmap(void* addr, +extern void* kmem_platform_mmap(void* addr, unsigned long sz, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off); -enum posix_prot { - posix_prot_none = 0, - posix_prot_read = 1 << 0, - posix_prot_write = 1 << 1, - posix_prot_exec = 1 << 2 -}; - -enum posix_map { - posix_map_shared = 1, - posix_map_private = 2 -}; - -enum posix_flag { - posix_flag_fixed = 0x10, - posix_flag_anonymous = 0x20, - - /* platform flags */ - posix_flag_linux_hugetlb = 0x40000 -}; - void* kmheapa(sz len) { /* allocate an object on the heap and return * a pointer, or NULL if the allocation failed. */ void* val; # ifdef KFenv_posix - /* posix APIs - we've got it easy */ - val = kmem_posix_mmap(null, len, posix_prot_read | posix_prot_write, - posix_flag_anonymous, -1, 0); + /* posix APIs - we've got it easy. currently for nonlinear + * heap allocation kmheapa simply uses m(un)map and lets the + * kernel worry about it. it may ultimately be worth replacing + * this with a more sophisticated implementation, most likely + * an existing allocator like jemalloc, though i'm wary of + * including outside code - it creates a licensing mess and + * i'd prefer libk to be AGPLv3 across the board. possibility: + * include hooks for multiple allocators, allowing the user + * to select & link in her preferred allocator at compile time? */ + + /* because munmap needs to be informed of the size of + * the region it is going to unmap, we need to store + * that information in the allocated region itself. + * the user will be given a pointer that can be + * adjusted to point a field of type size_t that + * contains the size of the allocate space.*/ + + sz const region_total = len + sizeof len; + ubyte* const region = kmem_platform_mmap(null, region_total, + posix_prot_read | posix_prot_write, + posix_flag_anonymous | posix_map_shared, -1, 0); /* impl note: while per manpage fd is "ignored" * for MAP_ANONYMOUS, "some implementations" require * a value of -1 */ - if (val == (void*) -1) return null; + if (region == (void*) -1) return null; /* worth retrieving errno? discuss */ + *((sz*)region) = len; + val = region + sizeof len; + # else Knoimpl(kmheapa,KVos); # error missing implementation # endif return val; }