diff --git a/source/server/vnode/inc/vnodeMemAllocator.h b/source/server/vnode/inc/vnodeMemAllocator.h index 9b3d27776d..eabccc689e 100644 --- a/source/server/vnode/inc/vnodeMemAllocator.h +++ b/source/server/vnode/inc/vnodeMemAllocator.h @@ -16,12 +16,39 @@ #ifndef _TD_VNODE_MEM_ALLOCATOR_H_ #define _TD_VNODE_MEM_ALLOCATOR_H_ -#include "amalloc.h" +#include "os.h" #ifdef __cplusplus extern "C" { #endif +typedef struct SVMANode SVMANode; +typedef struct SVnodeMemAllocator SVnodeMemAllocator; + +SVnodeMemAllocator *VMACreate(size_t size /* base size */, size_t ssize /* step size */, + size_t threshold /* threshold size when full*/); +void VMADestroy(SVnodeMemAllocator *pvma); +void VMAReset(SVnodeMemAllocator *pvma); +void * VMAMalloc(SVnodeMemAllocator *pvma, size_t size); +void VMAFree(SVnodeMemAllocator *pvma, void *ptr); +bool VMAIsFull(SVnodeMemAllocator *pvma); + +// ------------------ FOR TEST ONLY ------------------ +struct SVMANode { + struct SVMANode *prev; + size_t tsize; + size_t used; + char data[]; +}; + +struct SVnodeMemAllocator { + bool full; // if allocator is full + size_t threshold; // threshold; + size_t ssize; // step size to allocate + SVMANode *inuse; // inuse node to allocate + SVMANode node; // basic node to use +}; + #ifdef __cplusplus } #endif diff --git a/source/server/vnode/src/vnodeMemAllocator.c b/source/server/vnode/src/vnodeMemAllocator.c index 6dea4a4e57..29909df491 100644 --- a/source/server/vnode/src/vnodeMemAllocator.c +++ b/source/server/vnode/src/vnodeMemAllocator.c @@ -11,4 +11,114 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - */ \ No newline at end of file + */ + +#include "vnodeMemAllocator.h" + +#define VMA_IS_FULL(pvma) \ + (((pvma)->inuse != &((pvma)->node)) || ((pvma)->inuse->tsize - (pvma)->inuse->used < (pvma)->threshold)) + +static SVMANode *VMANodeNew(size_t size); +static void VMANodeFree(SVMANode *node); + +SVnodeMemAllocator *VMACreate(size_t size, size_t ssize, size_t threshold) { + SVnodeMemAllocator *pvma = NULL; + + if (size < threshold) { + return NULL; + } + + pvma = (SVnodeMemAllocator *)malloc(sizeof(*pvma) + size); + if (pvma) { + pvma->full = false; + pvma->threshold = threshold; + pvma->ssize = ssize; + pvma->inuse = &(pvma->node); + + pvma->inuse->prev = NULL; + pvma->inuse->tsize = size; + pvma->inuse->used = 0; + } + + return pvma; +} + +void VMADestroy(SVnodeMemAllocator *pvma) { + if (pvma) { + VMAReset(pvma); + free(pvma); + } +} + +void VMAReset(SVnodeMemAllocator *pvma) { + while (pvma->inuse != &(pvma->node)) { + SVMANode *node = pvma->inuse; + pvma->inuse = node->prev; + VMANodeFree(node); + } + + pvma->inuse->used = 0; + pvma->full = false; +} + +void *VMAMalloc(SVnodeMemAllocator *pvma, size_t size) { + void * ptr = NULL; + size_t tsize = size + sizeof(size_t); + + if (pvma->inuse->tsize - pvma->inuse->used < tsize) { + SVMANode *pNode = VMANodeNew(MAX(pvma->ssize, tsize)); + if (pNode == NULL) { + return NULL; + } + + pNode->prev = pvma->inuse; + pvma->inuse = pNode; + } + + ptr = pvma->inuse->data + pvma->inuse->used; + pvma->inuse->used += tsize; + *(size_t *)ptr = size; + ptr = POINTER_SHIFT(ptr, sizeof(size_t)); + + pvma->full = VMA_IS_FULL(pvma); + + return ptr; +} + +void VMAFree(SVnodeMemAllocator *pvma, void *ptr) { + if (ptr) { + size_t size = *(size_t *)POINTER_SHIFT(ptr, -sizeof(size_t)); + if (POINTER_SHIFT(ptr, size) == pvma->inuse->data + pvma->inuse->used) { + pvma->inuse->used -= (size + sizeof(size_t)); + + if ((pvma->inuse->used == 0) && (pvma->inuse != &(pvma->node))) { + SVMANode *node = pvma->inuse; + pvma->inuse = node->prev; + VMANodeFree(node); + } + + pvma->full = VMA_IS_FULL(pvma); + } + } +} + +bool VMAIsFull(SVnodeMemAllocator *pvma) { return pvma->full; } + +static SVMANode *VMANodeNew(size_t size) { + SVMANode *node = NULL; + + node = (SVMANode *)malloc(sizeof(*node) + size); + if (node) { + node->prev = NULL; + node->tsize = size; + node->used = 0; + } + + return node; +} + +static void VMANodeFree(SVMANode *node) { + if (node) { + free(node); + } +} \ No newline at end of file