}
/** \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);
if (re->data_ptr != NULL)
SCFree(re->data_ptr);
}
- SCFree(re);
#ifdef DEBUG
al_result_pool_elmts--;
/** 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();
/**
* \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;
}
/**
*
* \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;
}
/**
SCMutexDestroy(&tracker->lock);
DefragTrackerFreeFrags(tracker);
- SCFree(tracker);
}
/**
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.");
}
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.");
}
/** \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));
seg->payload = SCMalloc(seg->payload_len);
if (seg->payload == NULL) {
SCFree(seg);
- return NULL;
+ return 0;
}
#ifdef DEBUG
#endif
StreamTcpReassembleIncrMemuse((uint32_t)seg->pool_size + sizeof(TcpSegment));
- return seg;
+ return 1;
}
/** \brief free a tcp segment pool entry */
#endif
SCFree(seg->payload);
- SCFree(seg);
return;
}
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]);
}
}
/** \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
}
ssn->toclient_smsg_head = NULL;
- SCFree(ssn);
-
StreamTcpDecrMemuse((uint64_t)sizeof(TcpSession));
-
}
/** \brief To initialize the stream global configuration data
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");
}
if (StreamTcpCheckMemcap((memuse + stream_config.memcap)) != 0) {
- printf("failed in validating the memcap");
+ printf("failed in validating the overflowed memcap");
goto end;
}
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);
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) {
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);
#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;
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;
}
}
+ 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 */
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;
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;
return NULL;
}
+
void PoolFree(Pool *p) {
if (p == NULL)
return;
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);
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) {
if (p->pb_buffer)
SCFree(p->pb_buffer);
+ if (p->data_buffer)
+ SCFree(p->data_buffer);
SCFree(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++;
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");
}
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);
* 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;
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;
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;
retval = 1;
end:
- if (data != NULL)
- SCFree(data);
if (p != NULL)
PoolFree(p);
return retval;
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;
retval = 1;
end:
- if (str != NULL)
- SCFree(str);
if (p != NULL)
PoolFree(p);
return retval;
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;
retval = 1;
end:
- if (data != NULL)
- SCFree(data);
if (p != NULL)
PoolFree(p);
return retval;
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;
retval = 1;
end:
- if (data != NULL)
- SCFree(data);
- if (data2 != NULL)
- SCFree(data2);
if (p != NULL)
PoolFree(p);
return retval;
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;
retval = 1;
end:
- if (data != NULL)
- SCFree(data);
- if (data2 != NULL)
- SCFree(data2);
if (p != NULL)
PoolFree(p);
return retval;
/* pool structure */
typedef struct Pool_ {
uint32_t max_buckets;
+ uint32_t preallocated;
uint32_t allocated;
PoolBucket *alloc_list;
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);