pool: realize a block allocation for preallocated item.

This patch required a evolution of Pool API as it is needed to
proceed to alloc or init separetely. The PoolInit has been changed
with a new Init function parameter.
pull/49/merge
Eric Leblond 14 years ago committed by Victor Julien
parent cd76c7e5fb
commit fa079c1da0

@ -98,15 +98,15 @@ FileContainer *AppLayerGetFilesFromFlow(Flow *f, uint8_t direction) {
}
/** \brief Alloc a AppLayerParserResultElmt func for the pool */
static void *AlpResultElmtPoolAlloc(void *null)
static void *AlpResultElmtPoolAlloc()
{
AppLayerParserResultElmt *e = (AppLayerParserResultElmt *)SCMalloc
(sizeof(AppLayerParserResultElmt));
AppLayerParserResultElmt *e = NULL;
e = (AppLayerParserResultElmt *)SCMalloc
(sizeof(AppLayerParserResultElmt));
if (e == NULL)
return NULL;
memset(e, 0, sizeof(AppLayerParserResultElmt));
#ifdef DEBUG
al_result_pool_elmts++;
SCLogDebug("al_result_pool_elmts %"PRIu32"", al_result_pool_elmts);
@ -122,7 +122,6 @@ static void AlpResultElmtPoolFree(void *e)
if (re->data_ptr != NULL)
SCFree(re->data_ptr);
}
SCFree(re);
#ifdef DEBUG
al_result_pool_elmts--;
@ -1335,7 +1334,9 @@ void RegisterAppLayerParsers(void)
/** setup result pool
* \todo Per thread pool */
al_result_pool = PoolInit(1000,250,AlpResultElmtPoolAlloc,NULL,AlpResultElmtPoolFree);
al_result_pool = PoolInit(1000, 250,
sizeof(AppLayerParserResultElmt),
AlpResultElmtPoolAlloc, NULL, NULL, AlpResultElmtPoolFree);
RegisterHTPParsers();
RegisterSSLParsers();

@ -303,28 +303,16 @@ DefragFragReset(Frag *frag)
/**
* \brief Allocate a new frag for use in a pool.
*/
static void *
DefragFragNew(void *arg)
static int
DefragFragInit(void *data, void *initdata)
{
DefragContext *dc = arg;
Frag *frag;
DefragContext *dc = initdata;
Frag *frag = data;
frag = SCCalloc(1, sizeof(*frag));
if (frag == NULL)
return NULL;
memset(frag, 0, sizeof(*frag));
frag->dc = dc;
return (void *)frag;
}
/**
* \brief Free a frag when released from a pool.
*/
static void
DefragFragFree(void *arg)
{
Frag *frag = arg;
SCFree(frag);
return 1;
}
/**
@ -369,23 +357,20 @@ DefragTrackerReset(DefragTracker *tracker)
*
* \retval A new DefragTracker if successfull, NULL on failure.
*/
static void *
DefragTrackerNew(void *arg)
static int
DefragTrackerInit(void *data, void *initdata)
{
DefragContext *dc = arg;
DefragTracker *tracker;
DefragContext *dc = initdata;
DefragTracker *tracker = data;
tracker = SCCalloc(1, sizeof(*tracker));
if (tracker == NULL)
return NULL;
memset(tracker, 0, sizeof(*tracker));
if (SCMutexInit(&tracker->lock, NULL) != 0) {
SCFree(tracker);
return NULL;
return 0;
}
tracker->dc = dc;
TAILQ_INIT(&tracker->frags);
return (void *)tracker;
return 1;
}
/**
@ -399,7 +384,6 @@ DefragTrackerFree(void *arg)
SCMutexDestroy(&tracker->lock);
DefragTrackerFreeFrags(tracker);
SCFree(tracker);
}
/**
@ -437,7 +421,8 @@ DefragContextNew(void)
tracker_pool_size = DEFAULT_DEFRAG_HASH_SIZE;
}
dc->tracker_pool = PoolInit(tracker_pool_size, tracker_pool_size,
DefragTrackerNew, dc, DefragTrackerFree);
sizeof(DefragTracker),
NULL, DefragTrackerInit, dc, DefragTrackerFree);
if (dc->tracker_pool == NULL) {
SCLogError(SC_ERR_MEM_ALLOC,
"Defrag: Failed to initialize tracker pool.");
@ -456,7 +441,8 @@ DefragContextNew(void)
}
intmax_t frag_pool_prealloc = frag_pool_size / 2;
dc->frag_pool = PoolInit(frag_pool_size, frag_pool_prealloc,
DefragFragNew, dc, DefragFragFree);
sizeof(Frag),
NULL, DefragFragInit, dc, NULL);
if (dc->frag_pool == NULL) {
SCLogError(SC_ERR_MEM_ALLOC,
"Defrag: Failed to initialize fragment pool.");

@ -153,16 +153,24 @@ int StreamTcpReassembleCheckMemcap(uint32_t size) {
}
/** \brief alloc a tcp segment pool entry */
void *TcpSegmentPoolAlloc(void *payload_len) {
if (StreamTcpReassembleCheckMemcap((uint32_t)sizeof(TcpSegment) +
*((uint16_t *) payload_len)) == 0)
void *TcpSegmentPoolAlloc()
{
if (StreamTcpReassembleCheckMemcap((uint32_t)sizeof(TcpSegment)) == 0)
{
return NULL;
}
TcpSegment *seg = SCMalloc(sizeof (TcpSegment));
TcpSegment *seg = NULL;
seg = SCMalloc(sizeof (TcpSegment));
if (seg == NULL)
return NULL;
return seg;
}
int TcpSegmentPoolInit(void *data, void *payload_len)
{
TcpSegment *seg = (TcpSegment *) data;
memset(seg, 0, sizeof (TcpSegment));
@ -172,7 +180,7 @@ void *TcpSegmentPoolAlloc(void *payload_len) {
seg->payload = SCMalloc(seg->payload_len);
if (seg->payload == NULL) {
SCFree(seg);
return NULL;
return 0;
}
#ifdef DEBUG
@ -184,7 +192,7 @@ void *TcpSegmentPoolAlloc(void *payload_len) {
#endif
StreamTcpReassembleIncrMemuse((uint32_t)seg->pool_size + sizeof(TcpSegment));
return seg;
return 1;
}
/** \brief free a tcp segment pool entry */
@ -205,7 +213,6 @@ void TcpSegmentPoolFree(void *ptr) {
#endif
SCFree(seg->payload);
SCFree(seg);
return;
}
@ -276,8 +283,9 @@ int StreamTcpReassembleInit(char quiet)
SCMutexLock(&segment_pool_mutex[u16]);
segment_pool[u16] = PoolInit(segment_pool_poolsizes[u16],
segment_pool_poolsizes_prealloc[u16],
TcpSegmentPoolAlloc, (void *) &
segment_pool_pktsizes[u16],
sizeof (TcpSegment),
TcpSegmentPoolAlloc, TcpSegmentPoolInit,
(void *) &segment_pool_pktsizes[u16],
TcpSegmentPoolFree);
SCMutexUnlock(&segment_pool_mutex[u16]);
}

@ -244,23 +244,28 @@ void StreamTcpSessionPktFree (Packet *p)
}
/** \brief Stream alloc function for the Pool
* \param null NULL ptr (value of null is ignored)
* \retval ptr void ptr to TcpSession structure with all vars set to 0/NULL
*/
void *StreamTcpSessionPoolAlloc(void *null)
void *StreamTcpSessionPoolAlloc()
{
void *ptr = NULL;
if (StreamTcpCheckMemcap((uint32_t)sizeof(TcpSession)) == 0)
return NULL;
void *ptr = SCMalloc(sizeof(TcpSession));
ptr = SCMalloc(sizeof(TcpSession));
if (ptr == NULL)
return NULL;
memset(ptr, 0, sizeof(TcpSession));
return ptr;
}
int StreamTcpSessionPoolInit(void *data, void* initdata)
{
memset(data, 0, sizeof(TcpSession));
StreamTcpIncrMemuse((uint64_t)sizeof(TcpSession));
return ptr;
return 1;
}
/** \brief Pool free function
@ -302,10 +307,7 @@ void StreamTcpSessionPoolFree(void *s)
}
ssn->toclient_smsg_head = NULL;
SCFree(ssn);
StreamTcpDecrMemuse((uint64_t)sizeof(TcpSession));
}
/** \brief To initialize the stream global configuration data
@ -488,7 +490,9 @@ void StreamTcpInitConfig(char quiet)
SCMutexLock(&ssn_pool_mutex);
ssn_pool = PoolInit(stream_config.max_sessions,
stream_config.prealloc_sessions,
StreamTcpSessionPoolAlloc, NULL,
sizeof(TcpSession),
StreamTcpSessionPoolAlloc,
StreamTcpSessionPoolInit, NULL,
StreamTcpSessionPoolFree);
if (ssn_pool == NULL) {
SCLogError(SC_ERR_POOL_INIT, "ssn_pool is not initialized");
@ -7513,7 +7517,7 @@ static int StreamTcpTest28(void)
}
if (StreamTcpCheckMemcap((memuse + stream_config.memcap)) != 0) {
printf("failed in validating the memcap");
printf("failed in validating the overflowed memcap");
goto end;
}

@ -44,12 +44,9 @@ static uint16_t toclient_min_chunk_len = 2560;
static Pool *stream_msg_pool = NULL;
static SCMutex stream_msg_pool_mutex = PTHREAD_MUTEX_INITIALIZER;
void *StreamMsgAlloc(void *null) {
StreamMsg *s = SCMalloc(sizeof(StreamMsg));
if (s == NULL)
return NULL;
memset(s, 0, sizeof(StreamMsg));
int StreamMsgInit(void *data, void *initdata)
{
memset(data, 0, sizeof(StreamMsg));
#ifdef DEBUG
SCMutexLock(&stream_pool_memuse_mutex);
@ -57,16 +54,7 @@ void *StreamMsgAlloc(void *null) {
stream_pool_memcnt ++;
SCMutexUnlock(&stream_pool_memuse_mutex);
#endif
return s;
}
void StreamMsgFree(void *ptr) {
if (ptr == NULL)
return;
StreamMsg *s = (StreamMsg *)ptr;
SCFree(s);
return;
return 1;
}
static void StreamMsgEnqueue (StreamMsgQueue *q, StreamMsg *s) {
@ -159,7 +147,7 @@ void StreamMsgQueuesInit(void) {
SCMutexInit(&stream_pool_memuse_mutex, NULL);
#endif
SCMutexLock(&stream_msg_pool_mutex);
stream_msg_pool = PoolInit(0,250,StreamMsgAlloc,NULL,StreamMsgFree);
stream_msg_pool = PoolInit(0,250,sizeof(StreamMsg),NULL,StreamMsgInit,NULL,NULL);
if (stream_msg_pool == NULL)
exit(EXIT_FAILURE); /* XXX */
SCMutexUnlock(&stream_msg_pool_mutex);

@ -28,14 +28,40 @@
#include "util-unittest.h"
#include "util-debug.h"
Pool *PoolInit(uint32_t size, uint32_t prealloc_size, void *(*Alloc)(void *), void *AllocData, void (*Free)(void *))
static int PoolMemset(void *pitem, void *initdata)
{
Pool *p = NULL;
Pool *p = (Pool *) initdata;
if (Alloc == NULL) {
//printf("ERROR: PoolInit no Hash function\n");
goto error;
memset(pitem, 0, p->elt_size);
return 1;
}
/**
* \brief Check if data is preallocated
* \retval 0 or -1 if not inside */
static int PoolDataPreAllocated(Pool *p, void *data)
{
int delta = data - p->data_buffer;
if ((delta < 0) || (delta > p->data_buffer_size)) {
return 0;
}
return 1;
}
/** \brief Init a Pool
*
* \param size
* \param prealloc_size
* \param elt_size Memory size of an element
* \param Alloc An allocation function or NULL to use a standard SCMalloc
* \param Init An init function or NULL to use a standard memset to 0
* \param InitData Init data
* \Param Free a free function or NULL if no special treatment is needed
* \retval the allocated Pool
*/
Pool *PoolInit(uint32_t size, uint32_t prealloc_size, uint32_t elt_size, void *(*Alloc)(), int (*Init)(void *, void *), void *InitData, void (*Free)(void *))
{
Pool *p = NULL;
if (size != 0 && prealloc_size > size)
goto error;
@ -48,9 +74,17 @@ Pool *PoolInit(uint32_t size, uint32_t prealloc_size, void *(*Alloc)(void *), vo
memset(p,0,sizeof(Pool));
p->max_buckets = size;
p->preallocated = prealloc_size;
p->elt_size = elt_size;
p->data_buffer_size = prealloc_size * elt_size;
p->Alloc = Alloc;
p->AllocData = AllocData;
p->Free = Free;
p->Init = Init;
p->InitData = InitData;
p->Free = Free;
if (p->Init == NULL) {
p->Init = PoolMemset;
p->InitData = p;
}
/* alloc the buckets and place them in the empty list */
uint32_t u32 = 0;
@ -70,6 +104,10 @@ Pool *PoolInit(uint32_t size, uint32_t prealloc_size, void *(*Alloc)(void *), vo
}
}
p->data_buffer = SCCalloc(prealloc_size, elt_size);
/* FIXME better goto */
if (p->data_buffer == NULL)
goto error;
/* prealloc the buckets and requeue them to the alloc list */
for (u32 = 0; u32 < prealloc_size; u32++) {
if (size == 0) { /* unlimited */
@ -79,7 +117,15 @@ Pool *PoolInit(uint32_t size, uint32_t prealloc_size, void *(*Alloc)(void *), vo
memset(pb, 0, sizeof(PoolBucket));
pb->data = p->Alloc(p->AllocData);
if (p->Alloc) {
pb->data = p->Alloc();
} else {
pb->data = SCMalloc(p->elt_size);
}
if (pb->data == NULL)
goto error;
if (p->Init(pb->data, p->InitData) != 1)
goto error;
p->allocated++;
pb->next = p->alloc_list;
@ -93,7 +139,9 @@ Pool *PoolInit(uint32_t size, uint32_t prealloc_size, void *(*Alloc)(void *), vo
p->empty_list = pb->next;
p->empty_list_size--;
pb->data = p->Alloc(p->AllocData);
pb->data = (char *)p->data_buffer + u32 * elt_size;
if (p->Init(pb->data, p->InitData) != 1)
goto error;
p->allocated++;
pb->next = p->alloc_list;
@ -111,6 +159,7 @@ error:
return NULL;
}
void PoolFree(Pool *p) {
if (p == NULL)
return;
@ -118,7 +167,11 @@ void PoolFree(Pool *p) {
while (p->alloc_list != NULL) {
PoolBucket *pb = p->alloc_list;
p->alloc_list = pb->next;
p->Free(pb->data);
if (p->Free)
p->Free(pb->data);
if (PoolDataPreAllocated(p, pb->data) == 0) {
SCFree(pb->data);
}
pb->data = NULL;
if (! pb->flags & POOL_BUCKET_PREALLOCATED) {
SCFree(pb);
@ -129,7 +182,11 @@ void PoolFree(Pool *p) {
PoolBucket *pb = p->empty_list;
p->empty_list = pb->next;
if (pb->data!= NULL) {
p->Free(pb->data);
if (p->Free)
p->Free(pb->data);
if (PoolDataPreAllocated(p, pb->data) == 0) {
SCFree(pb->data);
}
pb->data = NULL;
}
if (! pb->flags & POOL_BUCKET_PREALLOCATED) {
@ -139,6 +196,8 @@ void PoolFree(Pool *p) {
if (p->pb_buffer)
SCFree(p->pb_buffer);
if (p->data_buffer)
SCFree(p->data_buffer);
SCFree(p);
}
@ -163,6 +222,7 @@ void *PoolGet(Pool *p) {
p->empty_list_size++;
} else {
if (p->max_buckets == 0 || p->allocated < p->max_buckets) {
void *pitem;
SCLogDebug("max_buckets %"PRIu32"", p->max_buckets);
p->allocated++;
@ -170,7 +230,16 @@ void *PoolGet(Pool *p) {
if (p->outstanding > p->max_outstanding)
p->max_outstanding = p->outstanding;
SCReturnPtr(p->Alloc(p->AllocData), "void");
if (p->Alloc != NULL) {
pitem = p->Alloc();
} else {
pitem = SCMalloc(p->elt_size);
}
if (pitem != NULL) {
if (p->Init(pitem, p->InitData) != 1)
SCReturnPtr(NULL, "void");
}
SCReturnPtr(pitem, "void");
} else {
SCReturnPtr(NULL, "void");
}
@ -194,8 +263,11 @@ void PoolReturn(Pool *p, void *data) {
if (pb == NULL) {
p->allocated--;
p->outstanding--;
if (p->Free != NULL)
if (p->Free != NULL) {
p->Free(data);
}
if (PoolDataPreAllocated(p, data) == 0)
SCFree(data);
SCLogDebug("tried to return data %p to the pool %p, but no more "
"buckets available. Just freeing the data.", data, p);
@ -224,25 +296,25 @@ void PoolPrintSaturation(Pool *p) {
* ONLY TESTS BELOW THIS COMMENT
*/
void *PoolTestAlloc(void *allocdata) {
void *PoolTestAlloc() {
void *ptr = SCMalloc(10);
return ptr;
}
void *PoolTestAllocArg(void *allocdata) {
int PoolTestInitArg(void *data, void *allocdata) {
size_t len = strlen((char *)allocdata) + 1;
char *str = SCMalloc(len);
char *str = data;
if (str != NULL)
strlcpy(str,(char *)allocdata,len);
return (void *)str;
return 1;
}
void PoolTestFree(void *ptr) {
SCFree(ptr);
return;
}
#ifdef UNITTESTS
static int PoolTestInit01 (void) {
Pool *p = PoolInit(10,5,PoolTestAlloc,NULL,PoolTestFree);
Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL,NULL,PoolTestFree);
if (p == NULL)
return 0;
@ -253,7 +325,7 @@ static int PoolTestInit01 (void) {
static int PoolTestInit02 (void) {
int retval = 0;
Pool *p = PoolInit(10,5,PoolTestAlloc,NULL,PoolTestFree);
Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL,NULL,PoolTestFree);
if (p == NULL)
goto end;
@ -289,7 +361,7 @@ static int PoolTestInit03 (void) {
int retval = 0;
void *data = NULL;
Pool *p = PoolInit(10,5,PoolTestAlloc,NULL,PoolTestFree);
Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL,NULL,PoolTestFree);
if (p == NULL)
goto end;
@ -314,8 +386,6 @@ static int PoolTestInit03 (void) {
retval = 1;
end:
if (data != NULL)
SCFree(data);
if (p != NULL)
PoolFree(p);
return retval;
@ -325,7 +395,7 @@ static int PoolTestInit04 (void) {
int retval = 0;
char *str = NULL;
Pool *p = PoolInit(10,5,PoolTestAllocArg,(void *)"test",PoolTestFree);
Pool *p = PoolInit(10,5,strlen("test") + 1,NULL, PoolTestInitArg,(void *)"test",PoolTestFree);
if (p == NULL)
goto end;
@ -356,8 +426,6 @@ static int PoolTestInit04 (void) {
retval = 1;
end:
if (str != NULL)
SCFree(str);
if (p != NULL)
PoolFree(p);
return retval;
@ -367,7 +435,7 @@ static int PoolTestInit05 (void) {
int retval = 0;
void *data = NULL;
Pool *p = PoolInit(10,5,PoolTestAlloc,NULL,PoolTestFree);
Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL, NULL,PoolTestFree);
if (p == NULL)
goto end;
@ -407,8 +475,6 @@ static int PoolTestInit05 (void) {
retval = 1;
end:
if (data != NULL)
SCFree(data);
if (p != NULL)
PoolFree(p);
return retval;
@ -419,7 +485,7 @@ static int PoolTestInit06 (void) {
void *data = NULL;
void *data2 = NULL;
Pool *p = PoolInit(1,0,PoolTestAlloc,NULL,PoolTestFree);
Pool *p = PoolInit(1,0,10,PoolTestAlloc,NULL,NULL,PoolTestFree);
if (p == NULL)
goto end;
@ -466,10 +532,6 @@ static int PoolTestInit06 (void) {
retval = 1;
end:
if (data != NULL)
SCFree(data);
if (data2 != NULL)
SCFree(data2);
if (p != NULL)
PoolFree(p);
return retval;
@ -481,7 +543,7 @@ static int PoolTestInit07 (void) {
void *data = NULL;
void *data2 = NULL;
Pool *p = PoolInit(0,1,PoolTestAlloc,NULL,PoolTestFree);
Pool *p = PoolInit(0,1,10,PoolTestAlloc,NULL,NULL,PoolTestFree);
if (p == NULL)
goto end;
@ -549,10 +611,6 @@ static int PoolTestInit07 (void) {
retval = 1;
end:
if (data != NULL)
SCFree(data);
if (data2 != NULL)
SCFree(data2);
if (p != NULL)
PoolFree(p);
return retval;

@ -36,6 +36,7 @@ typedef struct PoolBucket_ {
/* pool structure */
typedef struct Pool_ {
uint32_t max_buckets;
uint32_t preallocated;
uint32_t allocated;
PoolBucket *alloc_list;
@ -46,17 +47,20 @@ typedef struct Pool_ {
PoolBucket *pb_buffer;
void *data_buffer;
int data_buffer_size;
void *(*Alloc)(void *);
void *AllocData;
void *(*Alloc)();
int (*Init)(void *, void *);
void *InitData;
void (*Free)(void *);
uint32_t elt_size;
uint32_t outstanding;
uint32_t max_outstanding;
} Pool;
/* prototypes */
Pool* PoolInit(uint32_t, uint32_t, void *(*Alloc)(void *), void *, void (*Free)(void *));
Pool* PoolInit(uint32_t, uint32_t, uint32_t, void *(*Alloc)(), int (*Init)(void *, void *), void *, void (*Free)(void *));
void PoolFree(Pool *);
void PoolPrint(Pool *);
void PoolPrintSaturation(Pool *p);

Loading…
Cancel
Save