From: Eric Leblond Date: Wed, 29 Aug 2012 10:27:26 +0000 (+0200) Subject: pool: realize a block allocation for preallocated item. X-Git-Tag: suricata-1.4beta1~34 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fa079c1da0c7cef3d3346e0130407a3231d0ec29;p=thirdparty%2Fsuricata.git 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. --- diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index e5ac4694b8..c18c0617cf 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -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(); diff --git a/src/defrag.c b/src/defrag.c index 816e365c3b..d26dfd57a7 100644 --- a/src/defrag.c +++ b/src/defrag.c @@ -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."); diff --git a/src/stream-tcp-reassemble.c b/src/stream-tcp-reassemble.c index cebea4a6a6..cba5154371 100644 --- a/src/stream-tcp-reassemble.c +++ b/src/stream-tcp-reassemble.c @@ -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]); } diff --git a/src/stream-tcp.c b/src/stream-tcp.c index 5e4c010a11..c2aa295d2c 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -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; } diff --git a/src/stream.c b/src/stream.c index bda9ad3c4f..2781111d4c 100644 --- a/src/stream.c +++ b/src/stream.c @@ -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); diff --git a/src/util-pool.c b/src/util-pool.c index 68529b7ba4..2708426439 100644 --- a/src/util-pool.c +++ b/src/util-pool.c @@ -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; diff --git a/src/util-pool.h b/src/util-pool.h index 67c6b0663c..3e8ae2e6c8 100644 --- a/src/util-pool.h +++ b/src/util-pool.h @@ -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);