#include <k/mem.h>
#include <k/core.h>
#include <k/def.h>
#include <k/type.h>
/* heapf.c - kmheapf() "heap free"
* ~ lexi hale <lexi@hale.su>
* kmheapf() frees a region on the heap à la libc free()
* see also: kmheapa() "heap alloc"
*/
/* arch specific headers */
#ifdef KFenv_posix
# include <posix/posix.h>
#endif
/* we define all our platform functions here, whether or not
* they're for the correct platform - only the ones that are
* called by the preprocessed form of the code will actually
* be linked, linker errors are our friend here! */
extern int kmem_platform_munmap(void* addr, unsigned long sz);
kmcond kmheapf(void* ptr) {
/* take an object allocated on the heap and free it,
* returning kmcond_ok on success or an appropriate
* value on failure. */
struct kmbox* header = (kmbox*)
(((ubyte*)ptr) - sizeof (kmbox));
sz const total = header -> size + sizeof (kmbox);
if (header -> kind != kmkind_heap) return kmcond_mismatch;
# ifdef KFenv_posix
/* currently allocation is handled on posix by naive use
* of MAP_ANONYMOUS. munmap needs to be told the size of
* the region to unmap (free), which kmheapa() stores at
* (ptr - sizeof sz). see kmheap.c for details. */
k_platform_syscall_arg args[] = { (sz)header, total };
struct k_platform_syscall_answer r = k_platform_syscall
(k_platform_syscall_munmap, Kmsz(args), args);
if(r.error==0) {
/* we don't need to bother recovering the error
* code, there's only one possible munmap error */
return kmcond_bad_address;
}
# else
Knoimpl(kmheapf,KVos);
# error missing implementation
# endif
return kmcond_ok;
}