diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index d4f2b8b0be8b..a7c898bd2308 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -98,12 +98,18 @@ FileContainer *AppLayerGetFilesFromFlow(Flow *f, uint8_t direction) { } /** \brief Alloc a AppLayerParserResultElmt func for the pool */ -static void *AlpResultElmtPoolAlloc(void *null) +static void *AlpResultElmtPoolAlloc(void *null, void *data) { - AppLayerParserResultElmt *e = (AppLayerParserResultElmt *)SCMalloc - (sizeof(AppLayerParserResultElmt)); - if (e == NULL) - return NULL; + AppLayerParserResultElmt *e = NULL; + + if (data == NULL) { + e = (AppLayerParserResultElmt *)SCMalloc + (sizeof(AppLayerParserResultElmt)); + if (e == NULL) + return NULL; + } else { + e = data; + } memset(e, 0, sizeof(AppLayerParserResultElmt)); @@ -1314,7 +1320,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,AlpResultElmtPoolFree); RegisterHTPParsers(); RegisterSSLParsers(); diff --git a/src/defrag.c b/src/defrag.c index 99a320a8489a..760be3e54236 100644 --- a/src/defrag.c +++ b/src/defrag.c @@ -303,14 +303,18 @@ DefragFragReset(Frag *frag) * \brief Allocate a new frag for use in a pool. */ static void * -DefragFragNew(void *arg) +DefragFragNew(void *arg, void *data) { DefragContext *dc = arg; - Frag *frag; + Frag *frag = NULL; - frag = SCCalloc(1, sizeof(*frag)); - if (frag == NULL) - return NULL; + if (data == NULL) { + frag = SCCalloc(1, sizeof(*frag)); + if (frag == NULL) + return NULL; + } else { + frag = data; + } frag->dc = dc; return (void *)frag; @@ -369,14 +373,18 @@ DefragTrackerReset(DefragTracker *tracker) * \retval A new DefragTracker if successfull, NULL on failure. */ static void * -DefragTrackerNew(void *arg) +DefragTrackerNew(void *arg, void *data) { DefragContext *dc = arg; DefragTracker *tracker; - tracker = SCCalloc(1, sizeof(*tracker)); - if (tracker == NULL) - return NULL; + if (data == NULL) { + tracker = SCCalloc(1, sizeof(*tracker)); + if (tracker == NULL) + return NULL; + } else { + tracker = data; + } if (SCMutexInit(&tracker->lock, NULL) != 0) { SCFree(tracker); return NULL; @@ -436,6 +444,7 @@ DefragContextNew(void) tracker_pool_size = DEFAULT_DEFRAG_HASH_SIZE; } dc->tracker_pool = PoolInit(tracker_pool_size, tracker_pool_size, + sizeof(DefragTracker), DefragTrackerNew, dc, DefragTrackerFree); if (dc->tracker_pool == NULL) { SCLogError(SC_ERR_MEM_ALLOC, @@ -452,6 +461,7 @@ DefragContextNew(void) int frag_pool_size = 0xffff; int frag_pool_prealloc = frag_pool_size / 4; dc->frag_pool = PoolInit(frag_pool_size, frag_pool_prealloc, + sizeof(Frag), DefragFragNew, dc, DefragFragFree); if (dc->frag_pool == NULL) { SCLogError(SC_ERR_MEM_ALLOC, diff --git a/src/stream-tcp-reassemble.c b/src/stream-tcp-reassemble.c index abea41caf200..3829a311fc4c 100644 --- a/src/stream-tcp-reassemble.c +++ b/src/stream-tcp-reassemble.c @@ -153,16 +153,22 @@ int StreamTcpReassembleCheckMemcap(uint32_t size) { } /** \brief alloc a tcp segment pool entry */ -void *TcpSegmentPoolAlloc(void *payload_len) { +void *TcpSegmentPoolAlloc(void *payload_len, void* data) { if (StreamTcpReassembleCheckMemcap((uint32_t)sizeof(TcpSegment) + *((uint16_t *) payload_len)) == 0) { return NULL; } - TcpSegment *seg = SCMalloc(sizeof (TcpSegment)); - if (seg == NULL) - return NULL; + TcpSegment *seg = NULL; + + if (data == NULL) { + seg = SCMalloc(sizeof (TcpSegment)); + if (seg == NULL) + return NULL; + } else { + seg = data; + } memset(seg, 0, sizeof (TcpSegment)); @@ -276,6 +282,7 @@ int StreamTcpReassembleInit(char quiet) SCMutexLock(&segment_pool_mutex[u16]); segment_pool[u16] = PoolInit(segment_pool_poolsizes[u16], segment_pool_poolsizes_prealloc[u16], + sizeof (TcpSegment), TcpSegmentPoolAlloc, (void *) & segment_pool_pktsizes[u16], TcpSegmentPoolFree); diff --git a/src/stream-tcp.c b/src/stream-tcp.c index 5e4c010a11b4..1a3d096721ef 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -245,16 +245,23 @@ void StreamTcpSessionPktFree (Packet *p) /** \brief Stream alloc function for the Pool * \param null NULL ptr (value of null is ignored) + * \param data Pointer to potentially pre-allocated data * \retval ptr void ptr to TcpSession structure with all vars set to 0/NULL */ -void *StreamTcpSessionPoolAlloc(void *null) +void *StreamTcpSessionPoolAlloc(void *null, void* data) { - if (StreamTcpCheckMemcap((uint32_t)sizeof(TcpSession)) == 0) - return NULL; + void *ptr = NULL; - void *ptr = SCMalloc(sizeof(TcpSession)); - if (ptr == NULL) - return NULL; + if (data == NULL) { + if (StreamTcpCheckMemcap((uint32_t)sizeof(TcpSession)) == 0) + return NULL; + + ptr = SCMalloc(sizeof(TcpSession)); + if (ptr == NULL) + return NULL; + } else { + ptr = data; + } memset(ptr, 0, sizeof(TcpSession)); @@ -488,6 +495,7 @@ void StreamTcpInitConfig(char quiet) SCMutexLock(&ssn_pool_mutex); ssn_pool = PoolInit(stream_config.max_sessions, stream_config.prealloc_sessions, + sizeof(TcpSession), StreamTcpSessionPoolAlloc, NULL, StreamTcpSessionPoolFree); if (ssn_pool == NULL) { diff --git a/src/stream.c b/src/stream.c index bda9ad3c4fe2..5f0d796d007c 100644 --- a/src/stream.c +++ b/src/stream.c @@ -44,10 +44,16 @@ 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; +void *StreamMsgAlloc(void *null, void *data) { + StreamMsg *s; + + if (data == NULL) { + s = SCMalloc(sizeof(StreamMsg)); + if (s == NULL) + return NULL; + } else { + s = data; + } memset(s, 0, sizeof(StreamMsg)); @@ -159,7 +165,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),StreamMsgAlloc,NULL,StreamMsgFree); 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 f325cdcde70c..68c08831e3c7 100644 --- a/src/util-pool.c +++ b/src/util-pool.c @@ -28,7 +28,7 @@ #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 *)) +Pool *PoolInit(uint32_t size, uint32_t prealloc_size, uint32_t elt_size, void *(*Alloc)(void *, void*), void *AllocData, void (*Free)(void *)) { Pool *p = NULL; @@ -48,24 +48,34 @@ 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->Alloc = Alloc; p->AllocData = AllocData; p->Free = Free; /* alloc the buckets and place them in the empty list */ uint32_t u32 = 0; - for (u32 = 0; u32 < size; u32++) { - /* populate pool */ - PoolBucket *pb = SCMalloc(sizeof(PoolBucket)); + if (size > 0) { + PoolBucket *pb = SCCalloc(size, sizeof(PoolBucket)); + p->pb_buffer = pb; if (pb == NULL) goto error; - - memset(pb, 0, sizeof(PoolBucket)); - pb->next = p->empty_list; - p->empty_list = pb; - p->empty_list_size++; + memset(pb, 0, size * sizeof(PoolBucket)); + for (u32 = 0; u32 < size; u32++) { + /* populate pool */ + pb->next = p->empty_list; + pb->flags |= POOL_BUCKET_PREALLOCATED; + p->empty_list = pb; + p->empty_list_size++; + pb++; + } } + 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 */ @@ -75,7 +85,7 @@ Pool *PoolInit(uint32_t size, uint32_t prealloc_size, void *(*Alloc)(void *), vo memset(pb, 0, sizeof(PoolBucket)); - pb->data = p->Alloc(p->AllocData); + pb->data = p->Alloc(p->AllocData, NULL); p->allocated++; pb->next = p->alloc_list; @@ -89,7 +99,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; + pb->flags |= POOL_BUCKET_PREALLOCATED_DATA; + p->Alloc(p->AllocData, pb->data); p->allocated++; pb->next = p->alloc_list; @@ -107,6 +119,7 @@ Pool *PoolInit(uint32_t size, uint32_t prealloc_size, void *(*Alloc)(void *), vo return NULL; } + void PoolFree(Pool *p) { if (p == NULL) return; @@ -114,21 +127,30 @@ void PoolFree(Pool *p) { while (p->alloc_list != NULL) { PoolBucket *pb = p->alloc_list; p->alloc_list = pb->next; - p->Free(pb->data); + if (! pb->flags & POOL_BUCKET_PREALLOCATED_DATA) { + p->Free(pb->data); + } pb->data = NULL; - SCFree(pb); + if (! pb->flags & POOL_BUCKET_PREALLOCATED) { + SCFree(pb); + } } while (p->empty_list != NULL) { PoolBucket *pb = p->empty_list; p->empty_list = pb->next; - if (pb->data!= NULL) { - p->Free(pb->data); + if (pb->data!= NULL) { + if (! pb->flags & POOL_BUCKET_PREALLOCATED_DATA) { + p->Free(pb->data); + } pb->data = NULL; } - SCFree(pb); + if (! pb->flags & POOL_BUCKET_PREALLOCATED) { + SCFree(pb); + } } + SCFree(p->pb_buffer); SCFree(p); } @@ -160,7 +182,7 @@ void *PoolGet(Pool *p) { if (p->outstanding > p->max_outstanding) p->max_outstanding = p->outstanding; - SCReturnPtr(p->Alloc(p->AllocData), "void"); + SCReturnPtr(p->Alloc(p->AllocData, NULL), "void"); } else { SCReturnPtr(NULL, "void"); } diff --git a/src/util-pool.h b/src/util-pool.h index b1abb996371d..eb1a4da17989 100644 --- a/src/util-pool.h +++ b/src/util-pool.h @@ -24,15 +24,20 @@ #ifndef __UTIL_POOL_H__ #define __UTIL_POOL_H__ +#define POOL_BUCKET_PREALLOCATED 1 << 0 +#define POOL_BUCKET_PREALLOCATED_DATA 1 << 1 + /* pool bucket structure */ typedef struct PoolBucket_ { void *data; + uint8_t flags; struct PoolBucket_ *next; } PoolBucket; /* pool structure */ typedef struct Pool_ { uint32_t max_buckets; + uint32_t preallocated; uint32_t allocated; PoolBucket *alloc_list; @@ -41,16 +46,20 @@ typedef struct Pool_ { PoolBucket *empty_list; uint32_t empty_list_size; - void *(*Alloc)(void *); + PoolBucket *pb_buffer; + void *data_buffer; + + void *(*Alloc)(void *, void *); void *AllocData; 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)(void *, void *), void *, void (*Free)(void *)); void PoolFree(Pool *); void PoolPrint(Pool *); void PoolPrintSaturation(Pool *p);