blob: d4e8d090d871a32c39f2d420b035eafc21c1f258 [file] [log] [blame]
adamdunkelsa2f3c422004-09-12 20:24:53 +00001/*
2 * Copyright (c) 2004, Swedish Institute of Computer Science.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * This file is part of the Contiki operating system.
30 *
31 * Author: Adam Dunkels <adam@sics.se>
32 *
33 * $Id: memb.c,v 1.5 2004/09/12 20:24:55 adamdunkels Exp $
34 */
adamdunkels25adfdf2003-10-14 11:14:54 +000035/**
adamdunkels01f657c2004-03-18 21:07:00 +000036 * \defgroup memb Memory block management functions
adamdunkels25adfdf2003-10-14 11:14:54 +000037 *
38 * The memory block allocation routines provide a simple yet powerful
39 * set of functions for managing a set of memory blocks of fixed
40 * size. A set of memory blocks is statically declared with the
41 * MEMB() macro. Memory blocks are allocated from the declared
42 * memory by the memb_alloc() function, and are deallocated with the
43 * memb_free() function.
44 *
45 * \note Because of namespace clashes only one MEMB() can be
46 * declared per C module, and the name scope of a MEMB() memory
47 * block is local to each C module.
48 *
49 * The following example shows how to declare and use a memory block
50 * called "cmem" which has 8 chunks of memory with each memory chunk
51 * being 20 bytes large.
52 *
53 \code
adamdunkels01f657c2004-03-18 21:07:00 +000054 #include "memb.h"
55
adamdunkels25adfdf2003-10-14 11:14:54 +000056 MEMB(cmem, 20, 8);
57
58 int main(int argc, char *argv[]) {
59 char *ptr;
60
61 memb_init(&cmem);
62
63 ptr = memb_alloc(&cmem);
64
65 if(ptr != NULL) {
66 do_something(ptr);
67 } else {
68 printf("Could not allocate memory.\n");
69 }
70
adamdunkels01f657c2004-03-18 21:07:00 +000071 if(memb_free(&cmem, ptr) == 0) {
adamdunkels25adfdf2003-10-14 11:14:54 +000072 printf("Deallocation succeeded.\n");
73 }
74 }
75 \endcode
adamdunkels01f657c2004-03-18 21:07:00 +000076 *
77 * @{
adamdunkels25adfdf2003-10-14 11:14:54 +000078 */
79
adamdunkels01f657c2004-03-18 21:07:00 +000080 /**
81 * \file
82 * Memory block allocation routines.
83 * \author Adam Dunkels <adam@sics.se>
84 */
adamdunkels25adfdf2003-10-14 11:14:54 +000085#include <string.h>
86
87#include "memb.h"
88
89/*------------------------------------------------------------------------------*/
90/**
91 * Initialize a memory block that was declared with MEMB().
92 *
93 * \param m A memory block previosly declared with MEMB().
94 */
95/*------------------------------------------------------------------------------*/
96void
97memb_init(struct memb_blocks *m)
98{
adamdunkels9e15ad72004-02-16 20:48:13 +000099 memset(m->mem, 0, (m->size + 1) * m->num);
adamdunkels25adfdf2003-10-14 11:14:54 +0000100}
101/*------------------------------------------------------------------------------*/
102/**
103 * Allocate a memory block from a block of memory declared with MEMB().
104 *
105 * \param m A memory block previosly declared with MEMB().
106 */
107/*------------------------------------------------------------------------------*/
108char *
109memb_alloc(struct memb_blocks *m)
110{
111 int i;
112 char *ptr;
113
114 ptr = m->mem;
115 for(i = 0; i < m->num; ++i) {
116 if(*ptr == 0) {
117 /* If this block was unused, we increase the reference count to
118 indicate that it now is used and return a pointer to the
119 first byte following the reference counter. */
120 ++*ptr;
121 return ptr + 1;
122 }
123 ptr += m->size + 1;
124 }
125
126 /* No free block was found, so we return NULL to indicate failure to
127 allocate block. */
128 return NULL;
129}
130/*------------------------------------------------------------------------------*/
131/**
132 * Deallocate a memory block from a memory block previously declared
133 * with MEMB().
134 *
135 * \param m m A memory block previosly declared with MEMB().
136 *
137 * \param ptr A pointer to the memory block that is to be deallocated.
138 *
139 * \return The new reference count for the memory block (should be 0
140 * if successfully deallocated) or -1 if the pointer "ptr" did not
141 * point to a legal memory block.
142 */
143/*------------------------------------------------------------------------------*/
144char
adamdunkels01f657c2004-03-18 21:07:00 +0000145memb_free(struct memb_blocks *m, void *ptr)
adamdunkels25adfdf2003-10-14 11:14:54 +0000146{
147 int i;
148 char *ptr2;
149
150 /* Walk through the list of blocks and try to find the block to
151 which the pointer "ptr" points to. */
152 ptr2 = m->mem;
153 for(i = 0; i < m->num; ++i) {
154
adamdunkels01f657c2004-03-18 21:07:00 +0000155 if(ptr2 == (char *)ptr - 1) {
adamdunkels25adfdf2003-10-14 11:14:54 +0000156 /* We've found to block to which "ptr" points so we decrease the
157 reference count and return the new value of it. */
158 return --*ptr2;
159 }
160 ptr2 += m->size + 1;
161 }
162 return -1;
163}
164/*------------------------------------------------------------------------------*/
165/**
166 * Increase the reference count for a memory chunk.
167 *
168 * \note No sanity checks are currently made.
169 *
170 * \param m m A memory block previosly declared with MEMB().
171 *
172 * \param ptr A pointer to the memory chunk for which the reference
173 * count should be increased.
174 *
175 * \return The new reference count.
176 */
177/*------------------------------------------------------------------------------*/
178char
179memb_ref(struct memb_blocks *m, char *ptr)
180{
181 return ++*(ptr - 1);
182}
183/*------------------------------------------------------------------------------*/
184
adamdunkels01f657c2004-03-18 21:07:00 +0000185/** @} */