mbed OS5

Fork of UIPEthernet by Zoltan Hudak

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mempool.cpp Source File

mempool.cpp

00001 /*
00002  mempool.cpp - sleek implementation of a memory pool
00003  Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
00004  All rights reserved.
00005 
00006  This program is free software: you can redistribute it and/or modify
00007  it under the terms of the GNU General Public License as published by
00008  the Free Software Foundation, either version 3 of the License, or
00009  (at your option) any later version.
00010 
00011  This program is distributed in the hope that it will be useful,
00012  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  GNU General Public License for more details.
00015 
00016  You should have received a copy of the GNU General Public License
00017  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018  */
00019 #include "mempool.h"
00020 #include <string.h>
00021 
00022 #define POOLOFFSET  1
00023 
00024 struct memblock myMemoryPool::    blocks[MEMPOOL_NUM_MEMBLOCKS + 1];
00025 
00026 /**
00027  * @brief
00028  * @note
00029  * @param
00030  * @retval
00031  */
00032 void myMemoryPool::init(void) {
00033     memset(&blocks[0], 0, sizeof(blocks));
00034     blocks[POOLSTART].begin = MEMPOOL_STARTADDRESS;
00035     blocks[POOLSTART].size = 0;
00036     blocks[POOLSTART].nextblock = NOBLOCK;
00037 }
00038 
00039 /**
00040  * @brief
00041  * @note
00042  * @param
00043  * @retval
00044  */
00045 memhandle myMemoryPool::allocBlock(memaddress size) {
00046     memblock*   best = NULL;
00047     memhandle   cur = POOLSTART;
00048     memblock*   block = &blocks[POOLSTART];
00049     memaddress  bestsize = MEMPOOL_SIZE + 1;
00050 
00051     do {
00052         memhandle   next = block->nextblock;
00053         memaddress  freesize = (next == NOBLOCK ? blocks[POOLSTART].begin + MEMPOOL_SIZE : blocks[next].begin) -
00054             block->begin -
00055             block->size;
00056         if (freesize == size) {
00057             best = &blocks[cur];
00058             goto found;
00059         }
00060 
00061         if (freesize > size && freesize < bestsize) {
00062             bestsize = freesize;
00063             best = &blocks[cur];
00064         }
00065 
00066         if (next == NOBLOCK) {
00067             if (best)
00068                 goto found;
00069             else
00070                 goto collect;
00071         }
00072 
00073         block = &blocks[next];
00074         cur = next;
00075     } while (true);
00076 
00077 collect:
00078     {
00079         cur = POOLSTART;
00080         block = &blocks[POOLSTART];
00081 
00082         memhandle   next;
00083         while ((next = block->nextblock) != NOBLOCK) {
00084             memaddress      dest = block->begin + block->size;
00085             memblock*       nextblock = &blocks[next];
00086             memaddress*     src = &nextblock->begin;
00087             if (dest != *src)
00088             {
00089 #ifdef MEMPOOL_MEMBLOCK_MV
00090                 MEMPOOL_MEMBLOCK_MV(dest, *src, nextblock->size);
00091 #endif
00092                 *src = dest;
00093             }
00094 
00095             block = nextblock;
00096         }
00097 
00098         if (blocks[POOLSTART].begin + MEMPOOL_SIZE - block->begin - block->size >= size)
00099             best = block;
00100         else
00101             goto notfound;
00102     }
00103 
00104 found:
00105     {
00106         block = &blocks[POOLOFFSET];
00107         for (cur = POOLOFFSET; cur < MEMPOOL_NUM_MEMBLOCKS + POOLOFFSET; cur++) {
00108             if (block->size) {
00109                 block++;
00110                 continue;
00111             }
00112 
00113             memaddress  address = best->begin + best->size;
00114 #ifdef MEMBLOCK_ALLOC
00115             MEMBLOCK_ALLOC(address, size);
00116 #endif
00117             block->begin = address;
00118             block->size = size;
00119             block->nextblock = best->nextblock;
00120             best->nextblock = cur;
00121             return cur;
00122         }
00123     }
00124 
00125 notfound:
00126     return NOBLOCK;
00127 }
00128 
00129 /**
00130  * @brief
00131  * @note
00132  * @param
00133  * @retval
00134  */
00135 void myMemoryPool::freeBlock(memhandle handle) {
00136     if (handle == NOBLOCK)
00137         return;
00138 
00139     memblock*   b = &blocks[POOLSTART];
00140 
00141     do {
00142         memhandle   next = b->nextblock;
00143         if (next == handle) {
00144             memblock*   f = &blocks[next];
00145 #ifdef MEMBLOCK_FREE
00146             MEMBLOCK_FREE(f->begin, f->size);
00147 #endif
00148             b->nextblock = f->nextblock;
00149             f->size = 0;
00150             f->nextblock = NOBLOCK;
00151             return;
00152         }
00153 
00154         if (next == NOBLOCK)
00155             return;
00156         b = &blocks[next];
00157     } while (true);
00158 }
00159 
00160 /**
00161  * @brief
00162  * @note
00163  * @param
00164  * @retval
00165  */
00166 void myMemoryPool::resizeBlock(memhandle handle, memaddress position) {
00167     memblock*   block = &blocks[handle];
00168     block->begin += position;
00169     block->size -= position;
00170 }
00171 
00172 /**
00173  * @brief
00174  * @note
00175  * @param
00176  * @retval
00177  */
00178 void myMemoryPool::resizeBlock(memhandle handle, memaddress position, memaddress size) {
00179     memblock*   block = &blocks[handle];
00180     block->begin += position;
00181     block->size = size;
00182 }
00183 
00184 /**
00185  * @brief
00186  * @note
00187  * @param
00188  * @retval
00189  */
00190 memaddress myMemoryPool::blockSize(memhandle handle) {
00191     return blocks[handle].size;
00192 }