--- /dev/null
+#include <config.h>
+#include <corax/types.h>
+#include <corax/errno.h>
+#include <mutex.h>
+#include <unistd.h>
+#include <kheap.h>
+#include <string.h>
+
+#define FLAG_USED (1 << 0)
+
+struct heap_node {
+ struct heap_node *next;
+ size_t size;
+ size_t flags;
+};
+
+int kheap_init(kheap_t *heap, size_t size)
+{
+ struct heap_node *obj;
+ int ret_val;
+
+ ret_val = -EINVAL;
+
+ if(heap) {
+ heap->h_base = sbrk(0);
+ heap->h_brk = sbrk((ssize_t)size);
+
+ if(heap->h_base != (void*)-1 && heap->h_brk != (void*)-1) {
+ heap->h_size = (size_t)heap->h_brk - (size_t)heap->h_base;
+ heap->h_lock = 0;
+
+ obj = (struct heap_node*)heap->h_base;
+ obj->next = NULL;
+ obj->size = heap->h_size - sizeof(*obj);
+ obj->flags = 0;
+
+ heap->h_free = heap->h_size - sizeof(*obj);
+
+ ret_val = 0;
+ } else {
+ ret_val = -ENOMEM;
+ }
+ }
+
+ return(ret_val);
+}
+
+static int _kheap_grow(kheap_t *heap, const size_t size)
+{
+ struct heap_node *last;
+ struct heap_node *new;
+ int ret_val;
+ size_t new_size;
+
+ ret_val = -ENOMEM;
+
+ /* old brk is the start of the new heap object */
+ new = (struct heap_node*)heap->h_brk;
+ /* attempt to grow the heap */
+ heap->h_brk = sbrk((ssize_t)size);
+
+ new_size = (size_t)heap->h_brk - (size_t)new;
+
+ if(new_size > sizeof(*new)) {
+ /* find the last node */
+ for(last = (struct heap_node*)heap->h_base;
+ last->next; last = last->next);
+
+ new->next = NULL;
+ new->size = new_size - sizeof(*new);
+ new->flags = 0;
+
+ last->next = new;
+ heap->h_size += new_size;
+ heap->h_free += new->size;
+ ret_val = 0;
+ }
+
+ return(ret_val);
+}
+
+void* heap_alloc(kheap_t *heap, size_t size)
+{
+ struct heap_node *cur;
+ void *ret_val;
+ int err;
+
+ ret_val = NULL;
+ err = 0;
+
+ spinlock_lock(&(heap->h_lock));
+
+ if(heap->h_free < size) {
+ err = _kheap_grow(heap, size);
+ }
+
+ if(!err) {
+ for(cur = (struct heap_node*)heap->h_base;
+ cur; cur = cur->next) {
+ if(cur->flags & FLAG_USED) {
+ continue;
+ }
+
+ if(cur->size < size) {
+ continue;
+ }
+
+ /* get a pointer to the available memory */
+ ret_val = (void*)(cur + 1);
+
+ cur->flags |= FLAG_USED;
+
+ /* split the heap node, if possible */
+ if(cur->size > (size + sizeof(struct heap_node))) {
+ struct heap_node *new;
+
+ new = (struct heap_node*)(ret_val + size);
+ new->size = cur->size - size - sizeof(*new);
+ new->next = cur->next;
+ new->flags = 0;
+
+ cur->size = size;
+ cur->next = new;
+
+ heap->h_free -= sizeof(*new);
+ }
+
+ memset(ret_val, 0, size);
+ heap->h_free -= size;
+
+ break;
+ }
+ }
+
+ spinlock_unlock(&(heap->h_lock));
+
+ return(ret_val);
+}
+
+void heap_free(kheap_t *heap, void *ptr)
+{
+ struct heap_node *cur;
+
+ spinlock_lock(&(heap->h_lock));
+
+ for(cur = (struct heap_node*)heap->h_base;
+ cur;
+ cur = cur->next) {
+ void *base;
+
+ base = (void*)(cur + 1);
+
+ if(base <= ptr && (base + cur->size) > ptr) {
+ if(!(cur->flags & FLAG_USED)) {
+ /* double free */
+ } else {
+ cur->flags ^= FLAG_USED;
+ heap->h_free += cur->size;
+ }
+
+ break;
+ }
+ }
+
+ spinlock_unlock(&(heap->h_lock));
+
+ return;
+}