finish vma
This commit is contained in:
parent
f762d03791
commit
a7e15c32c1
|
@ -16,12 +16,39 @@
|
||||||
#ifndef _TD_VNODE_MEM_ALLOCATOR_H_
|
#ifndef _TD_VNODE_MEM_ALLOCATOR_H_
|
||||||
#define _TD_VNODE_MEM_ALLOCATOR_H_
|
#define _TD_VNODE_MEM_ALLOCATOR_H_
|
||||||
|
|
||||||
#include "amalloc.h"
|
#include "os.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,4 +11,114 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* 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/>.
|
* 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