Index: kcore/testbin.exe.c ================================================================== --- kcore/testbin.exe.c +++ kcore/testbin.exe.c @@ -19,15 +19,17 @@ if (kiosend(e.std, ptr, null) == kiocond_ok) { /* great, continue */ } else { return kbad_io; } + kmptr object = kmheapao(sizeof (struct object) * 16); + if (object.kind == kmkind_fail) return kbad_mem; - struct object* block = kmheapa(sizeof (struct object) * 4); - if (block == null) return kbad_mem; + /* struct object* block = kmheapa(sizeof (struct object) * 4); */ - block[1].a = 5; + struct object* block = object.ref; + block[5].a = 5; - if (kmheapf(block) != kmcond_ok) return kbad_mem; + if (kmfree(object) != kmcond_ok) return kbad_mem; return kbad_ok; } Index: kmem/heapa.fn.c ================================================================== --- kmem/heapa.fn.c +++ kmem/heapa.fn.c @@ -1,5 +1,6 @@ +#include #include #include #include #include /* heapa.c - kmheapa() "heap alloc" @@ -18,11 +19,18 @@ 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. */ - void* val; + 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 @@ -38,26 +46,27 @@ * 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, + 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 == (void*) -1) return null; + if (region.raw == (void*) -1) return null; /* worth retrieving errno? discuss */ - *((sz*)region) = len; - val = region + sizeof len; - # 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 val; + return object; } Index: kmem/kmem.md ================================================================== --- kmem/kmem.md +++ kmem/kmem.md @@ -10,10 +10,14 @@ * `kmfree(kmptr) → void` - free, downref, or ignore the pasted object as appropriate * `kmshred(kmptr) → void` - free, downref, or ignore the pasted object as appropriate. if deallocating, zero its contents * `kmstat(void*) → kmptr` - convenience function to wrap a pointer to a non-managed object in a `kmptr` struct, so it can be passed to functions that accept arbitrary objects. `kmptr p = kmstat(raw)` is equivalent to `kmptr p = { kmkind_none, raw, NULL }`. * `kmtaint(&kmptr) → void` - "taints" a `kmptr` object by setting it to be shredded when freed. this may be desirable if the object pointed to contains privileged information. + * `kmzero(void*,sz) → void` - zeroes a region of memory + * `kmozero(kmptr) → void` - zeroes an object in memory + * `kmcopy(void* dest, void* src, sz) → void` - copies one region of memory to another + * `kmdup(kmptr) → kmptr` - duplicates an object in memory, allocating it as sibling of the original ## types kmem defines the following types: Index: kmem/mem.h ================================================================== --- kmem/mem.h +++ kmem/mem.h @@ -10,15 +10,22 @@ extern "C" { #endif typedef enum kmcond { kmcond_ok, + kmcond_unnecessary, + + kmcond_fail, + kmcond_unhandled, + kmcond_mismatch, kmcond_bad_address, } kmcond; typedef enum kmkind { kmkind_none, + kmkind_fail, + kmkind_linear, kmkind_heap, kmkind_pool, kmkind_ref, kmkind_tree } kmkind; @@ -26,30 +33,50 @@ typedef enum kmshred { kmshred_yes, kmshred_no } kmshred; -typedef struct kmcell { +typedef struct kmbox { kmkind kind; sz size; kmshred shred; +} kmbox; + +typedef struct kmcell { + kmbox header; sz refs; struct kmcell* src; } kmcell; + +typedef struct kmnode { + kmbox header; + struct kmnode* origin, + * branch, + * next, + * prev; +} kmnode; typedef struct kmptr { kmkind kind; kmshred shred; void* ref; - kmcell* cell; } kmptr; /* heap functions */ void* kmheapa(sz); +kmptr kmheapao(sz); kmcond kmheapf(void*); + +/* generic functions */ + +kmcond kmfree(kmptr); +kmkind kmtell(void*); +void kmzero(void*,sz); +void kmozero(kmptr); + #ifdef __cplusplus } #endif #endif