libk  heapf.fn.c at [12a51d9c50]

File mod/kmem/heapf.fn.c artifact a8a4c98c3a part of check-in 12a51d9c50


#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.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;
}