blob: 56e6634461e16d37179bac12b5fd089d2f6967c6 [file] [log] [blame]
/**
* \addtogroup exampleapps
* @{
*/
/**
* \file
* Memory block allocation routines.
* \author Adam Dunkels <adam@sics.se>
*
* The memory block allocation routines provide a simple yet powerful
* set of functions for managing a set of memory blocks of fixed
* size. A set of memory blocks is statically declared with the
* MEMB() macro. Memory blocks are allocated from the declared
* memory by the memb_alloc() function, and are deallocated with the
* memb_free() function.
*
* \note Because of namespace clashes only one MEMB() can be
* declared per C module, and the name scope of a MEMB() memory
* block is local to each C module.
*
* The following example shows how to declare and use a memory block
* called "cmem" which has 8 chunks of memory with each memory chunk
* being 20 bytes large.
*
\code
MEMB(cmem, 20, 8);
int main(int argc, char *argv[]) {
char *ptr;
memb_init(&cmem);
ptr = memb_alloc(&cmem);
if(ptr != NULL) {
do_something(ptr);
} else {
printf("Could not allocate memory.\n");
}
if(memb_free(ptr) == 0) {
printf("Deallocation succeeded.\n");
}
}
\endcode
*
*/
#include <string.h>
#include "memb.h"
/*------------------------------------------------------------------------------*/
/**
* Initialize a memory block that was declared with MEMB().
*
* \param m A memory block previosly declared with MEMB().
*/
/*------------------------------------------------------------------------------*/
void
memb_init(struct memb_blocks *m)
{
memset(m->mem, (m->size + 1) * m->num, 0);
}
/*------------------------------------------------------------------------------*/
/**
* Allocate a memory block from a block of memory declared with MEMB().
*
* \param m A memory block previosly declared with MEMB().
*/
/*------------------------------------------------------------------------------*/
char *
memb_alloc(struct memb_blocks *m)
{
int i;
char *ptr;
ptr = m->mem;
for(i = 0; i < m->num; ++i) {
if(*ptr == 0) {
/* If this block was unused, we increase the reference count to
indicate that it now is used and return a pointer to the
first byte following the reference counter. */
++*ptr;
return ptr + 1;
}
ptr += m->size + 1;
}
/* No free block was found, so we return NULL to indicate failure to
allocate block. */
return NULL;
}
/*------------------------------------------------------------------------------*/
/**
* Deallocate a memory block from a memory block previously declared
* with MEMB().
*
* \param m m A memory block previosly declared with MEMB().
*
* \param ptr A pointer to the memory block that is to be deallocated.
*
* \return The new reference count for the memory block (should be 0
* if successfully deallocated) or -1 if the pointer "ptr" did not
* point to a legal memory block.
*/
/*------------------------------------------------------------------------------*/
char
memb_free(struct memb_blocks *m, char *ptr)
{
int i;
char *ptr2;
/* Walk through the list of blocks and try to find the block to
which the pointer "ptr" points to. */
ptr2 = m->mem;
for(i = 0; i < m->num; ++i) {
if(ptr2 == ptr - 1) {
/* We've found to block to which "ptr" points so we decrease the
reference count and return the new value of it. */
return --*ptr2;
}
ptr2 += m->size + 1;
}
return -1;
}
/*------------------------------------------------------------------------------*/
/**
* Increase the reference count for a memory chunk.
*
* \note No sanity checks are currently made.
*
* \param m m A memory block previosly declared with MEMB().
*
* \param ptr A pointer to the memory chunk for which the reference
* count should be increased.
*
* \return The new reference count.
*/
/*------------------------------------------------------------------------------*/
char
memb_ref(struct memb_blocks *m, char *ptr)
{
return ++*(ptr - 1);
}
/*------------------------------------------------------------------------------*/