finish vma
This commit is contained in:
parent
f762d03791
commit
a7e15c32c1
|
@ -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
|
||||
|
|
|
@ -12,3 +12,113 @@
|
|||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue