diff options
Diffstat (limited to 'framework/src/suricata/src/util-pool.c')
-rw-r--r-- | framework/src/suricata/src/util-pool.c | 737 |
1 files changed, 0 insertions, 737 deletions
diff --git a/framework/src/suricata/src/util-pool.c b/framework/src/suricata/src/util-pool.c deleted file mode 100644 index 6f405252..00000000 --- a/framework/src/suricata/src/util-pool.c +++ /dev/null @@ -1,737 +0,0 @@ -/* Copyright (C) 2007-2010 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \defgroup utilpool Pool - * - * ::Pool are an effective way to maintain a set of ready to use - * structures. - * - * To create a ::Pool, you need to use PoolInit(). You can - * get an item from the ::Pool by using PoolGet(). When you're - * done with it call PoolReturn(). - * To destroy the ::Pool, call PoolFree(), it will free all used - * memory. - * - * @{ - */ - -/** - * \file - * - * \author Victor Julien <victor@inliniac.net> - * - * Pool utility functions - */ - -#include "suricata-common.h" -#include "util-pool.h" -#include "util-pool-thread.h" -#include "util-unittest.h" -#include "util-debug.h" - -static int PoolMemset(void *pitem, void *initdata) -{ - Pool *p = (Pool *) initdata; - - 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 - * - * PoolInit() creates a ::Pool. The Alloc function must only do - * allocation stuff. The Cleanup function must not try to free - * the PoolBucket::data. This is done by the ::Pool management - * system. - * - * \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 Cleanup a free function or NULL if no special treatment is needed - * \param Free free func - * \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 (*Cleanup)(void *), void (*Free)(void *)) -{ - Pool *p = NULL; - - if (size != 0 && prealloc_size > size) { - SCLogError(SC_ERR_POOL_INIT, "size error"); - goto error; - } - if (size != 0 && elt_size == 0) { - SCLogError(SC_ERR_POOL_INIT, "size != 0 && elt_size == 0"); - goto error; - } - if (elt_size && Free) { - SCLogError(SC_ERR_POOL_INIT, "elt_size && Free"); - goto error; - } - - /* setup the filter */ - p = SCMalloc(sizeof(Pool)); - if (unlikely(p == NULL)) { - SCLogError(SC_ERR_POOL_INIT, "alloc error"); - 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->Init = Init; - p->InitData = InitData; - p->Cleanup = Cleanup; - 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; - if (size > 0) { - PoolBucket *pb = SCCalloc(size, sizeof(PoolBucket)); - if (unlikely(pb == NULL)) { - SCLogError(SC_ERR_POOL_INIT, "alloc error"); - goto error; - } - p->pb_buffer = pb; - memset(pb, 0, size * sizeof(PoolBucket)); - for (u32 = 0; u32 < size; u32++) { - /* populate pool */ - pb->next = p->empty_stack; - pb->flags |= POOL_BUCKET_PREALLOCATED; - p->empty_stack = pb; - p->empty_stack_size++; - pb++; - } - } - - if (size > 0) { - p->data_buffer = SCCalloc(prealloc_size, elt_size); - /* FIXME better goto */ - if (p->data_buffer == NULL) { - SCLogError(SC_ERR_POOL_INIT, "alloc error"); - goto error; - } - } - /* prealloc the buckets and requeue them to the alloc list */ - for (u32 = 0; u32 < prealloc_size; u32++) { - if (size == 0) { /* unlimited */ - PoolBucket *pb = SCMalloc(sizeof(PoolBucket)); - if (unlikely(pb == NULL)) { - SCLogError(SC_ERR_POOL_INIT, "alloc error"); - goto error; - } - - memset(pb, 0, sizeof(PoolBucket)); - - if (p->Alloc) { - pb->data = p->Alloc(); - } else { - pb->data = SCMalloc(p->elt_size); - } - if (pb->data == NULL) { - SCLogError(SC_ERR_POOL_INIT, "alloc error"); - SCFree(pb); - goto error; - } - if (p->Init(pb->data, p->InitData) != 1) { - SCLogError(SC_ERR_POOL_INIT, "init error"); - if (p->Cleanup) - p->Cleanup(pb->data); - if (p->Free) - p->Free(pb->data); - else - SCFree(pb->data); - SCFree(pb); - goto error; - } - p->allocated++; - - pb->next = p->alloc_stack; - p->alloc_stack = pb; - p->alloc_stack_size++; - } else { - PoolBucket *pb = p->empty_stack; - if (pb == NULL) { - SCLogError(SC_ERR_POOL_INIT, "alloc error"); - goto error; - } - - pb->data = (char *)p->data_buffer + u32 * elt_size; - if (p->Init(pb->data, p->InitData) != 1) { - SCLogError(SC_ERR_POOL_INIT, "init error"); - if (p->Cleanup) - p->Cleanup(pb->data); - goto error; - } - - p->empty_stack = pb->next; - p->empty_stack_size--; - - p->allocated++; - - pb->next = p->alloc_stack; - p->alloc_stack = pb; - p->alloc_stack_size++; - } - } - - return p; - -error: - if (p != NULL) { - PoolFree(p); - } - return NULL; -} - - -void PoolFree(Pool *p) -{ - if (p == NULL) - return; - - while (p->alloc_stack != NULL) { - PoolBucket *pb = p->alloc_stack; - p->alloc_stack = pb->next; - if (p->Cleanup) - p->Cleanup(pb->data); - if (PoolDataPreAllocated(p, pb->data) == 0) { - if (p->Free) - p->Free(pb->data); - else - SCFree(pb->data); - } - pb->data = NULL; - if (! pb->flags & POOL_BUCKET_PREALLOCATED) { - SCFree(pb); - } - } - - while (p->empty_stack != NULL) { - PoolBucket *pb = p->empty_stack; - p->empty_stack = pb->next; - if (pb->data!= NULL) { - if (p->Cleanup) - p->Cleanup(pb->data); - if (PoolDataPreAllocated(p, pb->data) == 0) { - if (p->Free) - p->Free(pb->data); - else - SCFree(pb->data); - } - pb->data = NULL; - } - if (! pb->flags & POOL_BUCKET_PREALLOCATED) { - SCFree(pb); - } - } - - if (p->pb_buffer) - SCFree(p->pb_buffer); - if (p->data_buffer) - SCFree(p->data_buffer); - SCFree(p); -} - -void PoolPrint(Pool *p) -{ - printf("\n----------- Hash Table Stats ------------\n"); - printf("Buckets: %" PRIu32 "\n", p->empty_stack_size + p->alloc_stack_size); - printf("-----------------------------------------\n"); -} - -void *PoolGet(Pool *p) -{ - SCEnter(); - - PoolBucket *pb = p->alloc_stack; - if (pb != NULL) { - /* pull from the alloc list */ - p->alloc_stack = pb->next; - p->alloc_stack_size--; - - /* put in the empty list */ - pb->next = p->empty_stack; - p->empty_stack = pb; - p->empty_stack_size++; - } else { - if (p->max_buckets == 0 || p->allocated < p->max_buckets) { - void *pitem; - SCLogDebug("max_buckets %"PRIu32"", p->max_buckets); - - if (p->Alloc != NULL) { - pitem = p->Alloc(); - } else { - pitem = SCMalloc(p->elt_size); - } - - if (pitem != NULL) { - if (p->Init(pitem, p->InitData) != 1) { - if (p->Cleanup) - p->Cleanup(pitem); - if (p->Free != NULL) - p->Free(pitem); - else - SCFree(pitem); - SCReturnPtr(NULL, "void"); - } - - p->allocated++; - - p->outstanding++; - if (p->outstanding > p->max_outstanding) - p->max_outstanding = p->outstanding; - } - - SCReturnPtr(pitem, "void"); - } else { - SCReturnPtr(NULL, "void"); - } - } - - void *ptr = pb->data; - pb->data = NULL; - p->outstanding++; - if (p->outstanding > p->max_outstanding) - p->max_outstanding = p->outstanding; - SCReturnPtr(ptr,"void"); -} - -void PoolReturn(Pool *p, void *data) -{ - SCEnter(); - - PoolBucket *pb = p->empty_stack; - - SCLogDebug("pb %p", pb); - - if (pb == NULL) { - p->allocated--; - p->outstanding--; - if (p->Cleanup != NULL) { - p->Cleanup(data); - } - if (PoolDataPreAllocated(p, data) == 0) { - if (p->Free) - p->Free(data); - else - SCFree(data); - } - - SCLogDebug("tried to return data %p to the pool %p, but no more " - "buckets available. Just freeing the data.", data, p); - SCReturn; - } - - /* pull from the alloc list */ - p->empty_stack = pb->next; - p->empty_stack_size--; - - /* put in the alloc list */ - pb->next = p->alloc_stack; - p->alloc_stack = pb; - p->alloc_stack_size++; - - pb->data = data; - p->outstanding--; - SCReturn; -} - -void PoolPrintSaturation(Pool *p) -{ - SCLogDebug("pool %p is using %"PRIu32" out of %"PRIu32" items (%02.1f%%), max %"PRIu32" (%02.1f%%): pool struct memory %"PRIu64".", p, p->outstanding, p->max_buckets, (float)(p->outstanding/(float)(p->max_buckets))*100, p->max_outstanding, (float)(p->max_outstanding/(float)(p->max_buckets))*100, (uint64_t)(p->max_buckets * sizeof(PoolBucket))); -} - -/* - * ONLY TESTS BELOW THIS COMMENT - */ - -void *PoolTestAlloc() -{ - void *ptr = SCMalloc(10); - if (unlikely(ptr == NULL)) - return NULL; - return ptr; -} -int PoolTestInitArg(void *data, void *allocdata) -{ - size_t len = strlen((char *)allocdata) + 1; - char *str = data; - if (str != NULL) - strlcpy(str,(char *)allocdata,len); - return 1; -} - -void PoolTestFree(void *ptr) -{ - return; -} - -#ifdef UNITTESTS -static int PoolTestInit01 (void) -{ - Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL); - if (p == NULL) - return 0; - - PoolFree(p); - return 1; -} - -static int PoolTestInit02 (void) -{ - int retval = 0; - - Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL); - if (p == NULL) - goto end; - - if (p->alloc_stack == NULL || p->empty_stack == NULL) { - printf("list(s) not properly initialized (a:%p e:%p): ", - p->alloc_stack, p->empty_stack); - retval = 0; - goto end; - } - - if (p->Alloc != PoolTestAlloc) { - printf("Alloc func ptr %p != %p: ", - p->Alloc, PoolTestAlloc); - retval = 0; - goto end; - } - - if (p->Cleanup != PoolTestFree) { - printf("Free func ptr %p != %p: ", - p->Cleanup, PoolTestFree); - retval = 0; - goto end; - } - - retval = 1; -end: - if (p != NULL) - PoolFree(p); - return retval; -} - -static int PoolTestInit03 (void) -{ - int retval = 0; - void *data = NULL; - - Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL); - if (p == NULL) - goto end; - - data = PoolGet(p); - if (data == NULL) { - printf("PoolGet returned NULL: "); - retval = 0; - goto end; - } - - if (p->alloc_stack_size != 4) { - printf("p->alloc_stack_size 4 != %" PRIu32 ": ", p->alloc_stack_size); - retval = 0; - goto end; - } - - if (p->empty_stack_size != 6) { - printf("p->empty_stack_size 6 != %" PRIu32 ": ", p->empty_stack_size); - retval = 0; - goto end; - } - - retval = 1; -end: - if (p != NULL) - PoolFree(p); - return retval; -} - -static int PoolTestInit04 (void) -{ - int retval = 0; - char *str = NULL; - - Pool *p = PoolInit(10,5,strlen("test") + 1,NULL, PoolTestInitArg,(void *)"test",PoolTestFree, NULL); - if (p == NULL) - goto end; - - str = PoolGet(p); - if (str == NULL) { - printf("PoolGet returned NULL: "); - retval = 0; - goto end; - } - - if (strcmp(str, "test") != 0) { - printf("Memory not properly initialized: "); - retval = 0; - goto end; - } - - if (p->alloc_stack_size != 4) { - printf("p->alloc_stack_size 4 != %" PRIu32 ": ", p->alloc_stack_size); - retval = 0; - goto end; - } - - if (p->empty_stack_size != 6) { - printf("p->empty_stack_size 6 != %" PRIu32 ": ", p->empty_stack_size); - retval = 0; - goto end; - } - - retval = 1; -end: - if (p != NULL) - PoolFree(p); - return retval; -} - -static int PoolTestInit05 (void) -{ - int retval = 0; - void *data = NULL; - - Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL, NULL,PoolTestFree, NULL); - if (p == NULL) - goto end; - - data = PoolGet(p); - if (data == NULL) { - printf("PoolGet returned NULL: "); - retval = 0; - goto end; - } - - if (p->alloc_stack_size != 4) { - printf("p->alloc_stack_size 4 != %" PRIu32 ": ", p->alloc_stack_size); - retval = 0; - goto end; - } - - if (p->empty_stack_size != 6) { - printf("p->empty_stack_size 6 != %" PRIu32 ": ", p->empty_stack_size); - retval = 0; - goto end; - } - - PoolReturn(p, data); - data = NULL; - - if (p->alloc_stack_size != 5) { - printf("p->alloc_stack_size 5 != %" PRIu32 ": ", p->alloc_stack_size); - retval = 0; - goto end; - } - - if (p->empty_stack_size != 5) { - printf("p->empty_stack_size 5 != %" PRIu32 ": ", p->empty_stack_size); - retval = 0; - goto end; - } - - retval = 1; -end: - if (p != NULL) - PoolFree(p); - return retval; -} - -static int PoolTestInit06 (void) -{ - int retval = 0; - void *data = NULL; - void *data2 = NULL; - - Pool *p = PoolInit(1,0,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL); - if (p == NULL) - goto end; - - if (p->allocated != 0) { - printf("p->allocated 0 != %" PRIu32 ": ", p->allocated); - retval = 0; - goto end; - } - - data = PoolGet(p); - if (data == NULL) { - printf("PoolGet returned NULL: "); - retval = 0; - goto end; - } - - if (p->allocated != 1) { - printf("p->allocated 1 != %" PRIu32 ": ", p->allocated); - retval = 0; - goto end; - } - - data2 = PoolGet(p); - if (data2 != NULL) { - printf("PoolGet returned %p, expected NULL: ", data2); - retval = 0; - goto end; - } - - PoolReturn(p,data); - data = NULL; - - if (p->allocated != 1) { - printf("p->allocated 1 != %" PRIu32 ": ", p->allocated); - retval = 0; - goto end; - } - - if (p->alloc_stack_size != 1) { - printf("p->alloc_stack_size 1 != %" PRIu32 ": ", p->alloc_stack_size); - retval = 0; - goto end; - } - - retval = 1; -end: - if (p != NULL) - PoolFree(p); - return retval; -} - -/** \test pool with unlimited size */ -static int PoolTestInit07 (void) -{ - int retval = 0; - void *data = NULL; - void *data2 = NULL; - - Pool *p = PoolInit(0,1,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL); - if (p == NULL) - goto end; - - if (p->max_buckets != 0) { - printf("p->max_buckets 0 != %" PRIu32 ": ", p->max_buckets); - retval = 0; - goto end; - } - - if (p->allocated != 1) { - printf("p->allocated 1 != %" PRIu32 ": ", p->allocated); - retval = 0; - goto end; - } - - data = PoolGet(p); - if (data == NULL) { - printf("PoolGet returned NULL: "); - retval = 0; - goto end; - } - - if (p->allocated != 1) { - printf("(2) p->allocated 1 != %" PRIu32 ": ", p->allocated); - retval = 0; - goto end; - } - - data2 = PoolGet(p); - if (data2 == NULL) { - printf("PoolGet returned NULL: "); - retval = 0; - goto end; - } - - if (p->allocated != 2) { - printf("(3) p->allocated 2 != %" PRIu32 ": ", p->allocated); - retval = 0; - goto end; - } - - PoolReturn(p,data); - data = NULL; - - if (p->allocated != 2) { - printf("(4) p->allocated 2 != %" PRIu32 ": ", p->allocated); - retval = 0; - goto end; - } - - if (p->alloc_stack_size != 1) { - printf("p->alloc_stack_size 1 != %" PRIu32 ": ", p->alloc_stack_size); - retval = 0; - goto end; - } - - PoolReturn(p,data2); - data2 = NULL; - - if (p->allocated != 1) { - printf("(5) p->allocated 1 != %" PRIu32 ": ", p->allocated); - retval = 0; - goto end; - } - - retval = 1; -end: - if (p != NULL) - PoolFree(p); - return retval; -} -#endif /* UNITTESTS */ - -void PoolRegisterTests(void) -{ -#ifdef UNITTESTS - UtRegisterTest("PoolTestInit01", PoolTestInit01, 1); - UtRegisterTest("PoolTestInit02", PoolTestInit02, 1); - UtRegisterTest("PoolTestInit03", PoolTestInit03, 1); - UtRegisterTest("PoolTestInit04", PoolTestInit04, 1); - UtRegisterTest("PoolTestInit05", PoolTestInit05, 1); - UtRegisterTest("PoolTestInit06", PoolTestInit06, 1); - UtRegisterTest("PoolTestInit07", PoolTestInit07, 1); - - PoolThreadRegisterTests(); -#endif /* UNITTESTS */ -} - - -/** - * @} - */ |