Heap: add heap_freeSpace(), a new function.
[bertos.git] / bertos / struct / heap.c
index dc8ceaab8e03df4cc2916ecaba936027277153d8..1e4d60530336c7ae0f86e8cf891e7eeb44ccf63a 100644 (file)
 
 #include "heap.h"
 
-#include <cfg/macros.h>           // IS_POW2()
-#include <cfg/debug.h>            // ASSERT()
-
-#include <string.h>           // memset()
-
-/* NOTE: struct size must be a 2's power! */
-typedef struct _MemChunk
-{
-       struct _MemChunk *next;
-       size_t size;
-} MemChunk;
-
-STATIC_ASSERT(IS_POW2(sizeof(MemChunk)));
+#include <cfg/debug.h> // ASSERT()
+#include <string.h>    // memset()
 
 #define FREE_FILL_CODE     0xDEAD
 #define ALLOC_FILL_CODE    0xBEEF
 
+
+/*
+ * This function prototype is deprecated, will change in:
+ * void heap_init(struct Heap* h, heap_buf_t* memory, size_t size)
+ * in the nex BeRTOS release.
+ */
 void heap_init(struct Heap* h, void* memory, size_t size)
 {
-#ifdef _DEBUG
+       #ifdef _DEBUG
        memset(memory, FREE_FILL_CODE, size);
-#endif
+       #endif
+
+       ASSERT2(((size_t)memory % alignof(heap_buf_t)) == 0,
+       "memory buffer is unaligned, please use the HEAP_DEFINE_BUF() macro to declare heap buffers!\n");
 
        /* Initialize heap with a single big chunk */
        h->FreeList = (MemChunk *)memory;
@@ -129,9 +127,9 @@ void heap_freemem(struct Heap* h, void *mem, size_t size)
        if (!size)
                size = sizeof(MemChunk);
 
-       /* Special case: first chunk in the free list */
+       /* Special cases: first chunk in the free list or memory completely full */
        ASSERT((uint8_t*)mem != (uint8_t*)h->FreeList);
-       if (((uint8_t *)mem) < ((uint8_t *)h->FreeList))
+       if (((uint8_t *)mem) < ((uint8_t *)h->FreeList) || !h->FreeList)
        {
                /* Insert memory block before the current free list head */
                prev = (MemChunk *)mem;
@@ -186,6 +184,25 @@ void heap_freemem(struct Heap* h, void *mem, size_t size)
        }
 }
 
+/**
+ * Returns the number of free bytes in a heap.
+ * \param h the heap to check.
+ *
+ * \note The returned value is the sum of all free memory regions 
+ *       in the heap.
+ *       Those regions are likely to be *not* contiguous,
+ *       so a successive allocation may fail even if the
+ *       requested amount of memory is lower than the current free space.
+ */
+size_t heap_freeSpace(struct Heap *h)
+{
+       size_t free_mem = 0;
+       for (MemChunck *chunk = h->FreeList; hunk; chunk = chunk->next)
+               free_mem += chunck->size;
+
+       return free_mem;
+}
+
 #if CONFIG_HEAP_MALLOC
 
 void *heap_malloc(struct Heap* h, size_t size)