+++ /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* kheap_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 kheap_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;
-}