#include #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" */ /* we define all platform functions here, * 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_platform_mmap(void* addr, unsigned long sz, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off); void* kmheapa(sz len) { /* allocate an object on the heap and return * a pointer, or NULL if the allocation failed. */ union { void* raw; ubyte* byte; kmbox* header; } region; /* we need to allocate space for the header and * for the actual object */ sz region_size = sizeof(kmbox) + len; # ifdef KFenv_posix /* 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.*/ region.byte = kmem_platform_mmap(null, region_size, 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 (region.raw == (void*) -1) return null; /* worth retrieving errno? discuss */ # else Knoimpl(kmheapa,KVos); # error missing implementation # endif void* const object = (region.byte + sizeof (kmbox)); region.header -> kind = kmkind_heap; region.header -> size = len; return object; }