You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
4.1 KiB
C
153 lines
4.1 KiB
C
19 years ago
|
/**
|
||
|
* \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);
|
||
|
}
|
||
|
/*------------------------------------------------------------------------------*/
|
||
|
|
||
|
|
||
|
|
||
|
|