suricata
util-pool.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \defgroup utilpool Pool
20  *
21  * ::Pool are an effective way to maintain a set of ready to use
22  * structures.
23  *
24  * To create a ::Pool, you need to use PoolInit(). You can
25  * get an item from the ::Pool by using PoolGet(). When you're
26  * done with it call PoolReturn().
27  * To destroy the ::Pool, call PoolFree(), it will free all used
28  * memory.
29  *
30  * @{
31  */
32 
33 /**
34  * \file
35  *
36  * \author Victor Julien <victor@inliniac.net>
37  *
38  * Pool utility functions
39  */
40 
41 #include "suricata-common.h"
42 #include "util-pool.h"
43 #include "util-pool-thread.h"
44 #include "util-unittest.h"
45 #include "util-debug.h"
46 
47 static int PoolMemset(void *pitem, void *initdata)
48 {
49  Pool *p = (Pool *) initdata;
50 
51  memset(pitem, 0, p->elt_size);
52  return 1;
53 }
54 
55 /**
56  * \brief Check if data is preallocated
57  * \retval false if not inside the prealloc'd block, true if inside */
58 static bool PoolDataPreAllocated(Pool *p, void *data)
59 {
60  ptrdiff_t delta = data - p->data_buffer;
61  if ((delta < 0) || (delta > p->data_buffer_size)) {
62  return false;
63  }
64  return true;
65 }
66 
67 /** \brief Init a Pool
68  *
69  * PoolInit() creates a ::Pool. The Alloc function must only do
70  * allocation stuff. The Cleanup function must not try to free
71  * the PoolBucket::data. This is done by the ::Pool management
72  * system.
73  *
74  * \param size
75  * \param prealloc_size
76  * \param elt_size Memory size of an element
77  * \param Alloc An allocation function or NULL to use a standard SCMalloc
78  * \param Init An init function or NULL to use a standard memset to 0
79  * \param InitData Init data
80  * \param Cleanup a free function or NULL if no special treatment is needed
81  * \param Free free func
82  * \retval the allocated Pool
83  */
84 Pool *PoolInit(uint32_t size, uint32_t prealloc_size, uint32_t elt_size,
85  void *(*Alloc)(void), int (*Init)(void *, void *), void *InitData,
86  void (*Cleanup)(void *), void (*Free)(void *))
87 {
88  sc_errno = SC_OK;
89 
90  Pool *p = NULL;
91 
92  if (size != 0 && prealloc_size > size) {
94  goto error;
95  }
96  if (size != 0 && elt_size == 0) {
98  goto error;
99  }
100  if (elt_size && Free) {
102  goto error;
103  }
104  if (elt_size == 0 && Alloc == NULL) {
106  goto error;
107  }
108 
109  /* setup the filter */
110  p = SCMalloc(sizeof(Pool));
111  if (unlikely(p == NULL)) {
113  goto error;
114  }
115 
116  memset(p,0,sizeof(Pool));
117 
118  p->max_buckets = size;
119  p->preallocated = prealloc_size;
120  p->elt_size = elt_size;
121  p->data_buffer_size = prealloc_size * elt_size;
122  p->Alloc = Alloc;
123  p->Init = Init;
124  p->InitData = InitData;
125  p->Cleanup = Cleanup;
126  p->Free = Free;
127  if (p->Init == NULL) {
128  p->Init = PoolMemset;
129  p->InitData = p;
130  }
131 
132  /* alloc the buckets and place them in the empty list */
133  uint32_t u32 = 0;
134  if (size > 0) {
135  PoolBucket *pb = SCCalloc(size, sizeof(PoolBucket));
136  if (unlikely(pb == NULL)) {
138  goto error;
139  }
140  memset(pb, 0, size * sizeof(PoolBucket));
141  p->pb_buffer = pb;
142  for (u32 = 0; u32 < size; u32++) {
143  /* populate pool */
144  pb->next = p->empty_stack;
146  p->empty_stack = pb;
147  p->empty_stack_size++;
148  pb++;
149  }
150 
151  p->data_buffer = SCCalloc(prealloc_size, elt_size);
152  /* FIXME better goto */
153  if (p->data_buffer == NULL) {
155  goto error;
156  }
157  }
158  /* prealloc the buckets and requeue them to the alloc list */
159  for (u32 = 0; u32 < prealloc_size; u32++) {
160  if (size == 0) { /* unlimited */
161  PoolBucket *pb = SCMalloc(sizeof(PoolBucket));
162  if (unlikely(pb == NULL)) {
164  goto error;
165  }
166  memset(pb, 0, sizeof(PoolBucket));
167 
168  if (p->Alloc) {
169  pb->data = p->Alloc();
170  } else {
171  pb->data = SCMalloc(p->elt_size);
172  }
173  if (pb->data == NULL) {
174  SCFree(pb);
176  goto error;
177  }
178  if (p->Init(pb->data, p->InitData) != 1) {
179  if (p->Free)
180  p->Free(pb->data);
181  else
182  SCFree(pb->data);
183  SCFree(pb);
185  goto error;
186  }
187  p->allocated++;
188 
189  pb->next = p->alloc_stack;
190  p->alloc_stack = pb;
191  p->alloc_stack_size++;
192  } else {
193  PoolBucket *pb = p->empty_stack;
194  if (pb == NULL) {
196  goto error;
197  }
198 
199  pb->data = (char *)p->data_buffer + u32 * elt_size;
200  if (p->Init(pb->data, p->InitData) != 1) {
201  pb->data = NULL;
203  goto error;
204  }
205 
206  p->empty_stack = pb->next;
207  p->empty_stack_size--;
208 
209  p->allocated++;
210 
211  pb->next = p->alloc_stack;
212  p->alloc_stack = pb;
213  p->alloc_stack_size++;
214  }
215  }
216 
217  return p;
218 
219 error:
220  if (p != NULL) {
221  PoolFree(p);
222  }
223  return NULL;
224 }
225 
226 void PoolFree(Pool *p)
227 {
228  if (p == NULL)
229  return;
230 
231  while (p->alloc_stack != NULL) {
232  PoolBucket *pb = p->alloc_stack;
233  p->alloc_stack = pb->next;
234  if (p->Cleanup)
235  p->Cleanup(pb->data);
236  if (!PoolDataPreAllocated(p, pb->data)) {
237  if (p->Free)
238  p->Free(pb->data);
239  else
240  SCFree(pb->data);
241  }
242  pb->data = NULL;
243  if (!(pb->flags & POOL_BUCKET_PREALLOCATED)) {
244  SCFree(pb);
245  }
246  }
247 
248  while (p->empty_stack != NULL) {
249  PoolBucket *pb = p->empty_stack;
250  p->empty_stack = pb->next;
251  if (pb->data!= NULL) {
252  if (p->Cleanup)
253  p->Cleanup(pb->data);
254  if (!PoolDataPreAllocated(p, pb->data)) {
255  if (p->Free)
256  p->Free(pb->data);
257  else
258  SCFree(pb->data);
259  }
260  pb->data = NULL;
261  }
262  if (!(pb->flags & POOL_BUCKET_PREALLOCATED)) {
263  SCFree(pb);
264  }
265  }
266 
267  if (p->pb_buffer)
268  SCFree(p->pb_buffer);
269  if (p->data_buffer)
270  SCFree(p->data_buffer);
271  SCFree(p);
272 }
273 
274 void PoolPrint(Pool *p)
275 {
276  printf("\n----------- Hash Table Stats ------------\n");
277  printf("Buckets: %" PRIu32 "\n", p->empty_stack_size + p->alloc_stack_size);
278  printf("-----------------------------------------\n");
279 }
280 
281 void *PoolGet(Pool *p)
282 {
283  SCEnter();
284 
285  PoolBucket *pb = p->alloc_stack;
286  if (pb != NULL) {
287  /* pull from the alloc list */
288  p->alloc_stack = pb->next;
289  p->alloc_stack_size--;
290 
291  /* put in the empty list */
292  pb->next = p->empty_stack;
293  p->empty_stack = pb;
294  p->empty_stack_size++;
295  } else {
296  if (p->max_buckets == 0 || p->allocated < p->max_buckets) {
297  void *pitem;
298  SCLogDebug("max_buckets %"PRIu32"", p->max_buckets);
299 
300  if (p->Alloc != NULL) {
301  pitem = p->Alloc();
302  } else {
303  pitem = SCMalloc(p->elt_size);
304  }
305 
306  if (pitem != NULL) {
307  if (p->Init(pitem, p->InitData) != 1) {
308  if (p->Free != NULL)
309  p->Free(pitem);
310  else
311  SCFree(pitem);
312  SCReturnPtr(NULL, "void");
313  }
314 
315  p->allocated++;
316  p->outstanding++;
317 #ifdef DEBUG
318  if (p->outstanding > p->max_outstanding)
319  p->max_outstanding = p->outstanding;
320 #endif
321  }
322 
323  SCReturnPtr(pitem, "void");
324  } else {
325  SCReturnPtr(NULL, "void");
326  }
327  }
328 
329  void *ptr = pb->data;
330  pb->data = NULL;
331  p->outstanding++;
332 #ifdef DEBUG
333  if (p->outstanding > p->max_outstanding)
334  p->max_outstanding = p->outstanding;
335 #endif
336  SCReturnPtr(ptr,"void");
337 }
338 
339 void PoolReturn(Pool *p, void *data)
340 {
341  SCEnter();
342 
343  PoolBucket *pb = p->empty_stack;
344 
345  SCLogDebug("pb %p", pb);
346 
347  if (pb == NULL) {
348  p->allocated--;
349  p->outstanding--;
350  if (p->Cleanup != NULL) {
351  p->Cleanup(data);
352  }
353  if (!PoolDataPreAllocated(p, data)) {
354  if (p->Free)
355  p->Free(data);
356  else
357  SCFree(data);
358  }
359 
360  SCLogDebug("tried to return data %p to the pool %p, but no more "
361  "buckets available. Just freeing the data.", data, p);
362  SCReturn;
363  }
364 
365  /* pull from the alloc list */
366  p->empty_stack = pb->next;
367  p->empty_stack_size--;
368 
369  /* put in the alloc list */
370  pb->next = p->alloc_stack;
371  p->alloc_stack = pb;
372  p->alloc_stack_size++;
373 
374  pb->data = data;
375  p->outstanding--;
376  SCReturn;
377 }
378 
380 {
381  if (p->max_buckets > 0) {
382  SCLogDebug("pool %p is using %" PRIu32 " out of %" PRIu32 " items (%02.1f%%), max %" PRIu32
383  " (%02.1f%%): pool struct memory %" PRIu64 ".",
384  p, p->outstanding, p->max_buckets,
385  (float)(p->outstanding) / (float)(p->max_buckets) * 100, p->max_outstanding,
386  (float)(p->max_outstanding) / (float)(p->max_buckets) * 100,
387  (uint64_t)(p->max_buckets * sizeof(PoolBucket)));
388  }
389 }
390 
391 /*
392  * ONLY TESTS BELOW THIS COMMENT
393  */
394 
395 #ifdef UNITTESTS
396 static void *PoolTestAlloc(void)
397 {
398  void *ptr = SCMalloc(10);
399  if (unlikely(ptr == NULL))
400  return NULL;
401  return ptr;
402 }
403 static int PoolTestInitArg(void *data, void *allocdata)
404 {
405  size_t len = strlen((char *)allocdata) + 1;
406  char *str = data;
407  if (str != NULL)
408  strlcpy(str,(char *)allocdata,len);
409  return 1;
410 }
411 
412 static void PoolTestFree(void *ptr)
413 {
414  return;
415 }
416 
417 static int PoolTestInit01 (void)
418 {
419  Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL);
420  if (p == NULL)
421  return 0;
422 
423  PoolFree(p);
424  return 1;
425 }
426 
427 static int PoolTestInit02 (void)
428 {
429  int retval = 0;
430 
431  Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL);
432  if (p == NULL)
433  goto end;
434 
435  if (p->alloc_stack == NULL || p->empty_stack == NULL) {
436  printf("list(s) not properly initialized (a:%p e:%p): ",
437  p->alloc_stack, p->empty_stack);
438  retval = 0;
439  goto end;
440  }
441 
442  if (p->Alloc != PoolTestAlloc) {
443  printf("Alloc func ptr %p != %p: ",
444  p->Alloc, PoolTestAlloc);
445  retval = 0;
446  goto end;
447  }
448 
449  if (p->Cleanup != PoolTestFree) {
450  printf("Free func ptr %p != %p: ",
451  p->Cleanup, PoolTestFree);
452  retval = 0;
453  goto end;
454  }
455 
456  retval = 1;
457 end:
458  if (p != NULL)
459  PoolFree(p);
460  return retval;
461 }
462 
463 static int PoolTestInit03 (void)
464 {
465  int retval = 0;
466  void *data = NULL;
467 
468  Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL);
469  if (p == NULL)
470  goto end;
471 
472  data = PoolGet(p);
473  if (data == NULL) {
474  printf("PoolGet returned NULL: ");
475  retval = 0;
476  goto end;
477  }
478 
479  if (p->alloc_stack_size != 4) {
480  printf("p->alloc_stack_size 4 != %" PRIu32 ": ", p->alloc_stack_size);
481  retval = 0;
482  goto end;
483  }
484 
485  if (p->empty_stack_size != 6) {
486  printf("p->empty_stack_size 6 != %" PRIu32 ": ", p->empty_stack_size);
487  retval = 0;
488  goto end;
489  }
490 
491  retval = 1;
492 end:
493  if (p != NULL)
494  PoolFree(p);
495  return retval;
496 }
497 
498 static int PoolTestInit04 (void)
499 {
500  int retval = 0;
501  char *str = NULL;
502 
503  Pool *p = PoolInit(10,5,strlen("test") + 1,NULL, PoolTestInitArg,(void *)"test",PoolTestFree, NULL);
504  if (p == NULL)
505  goto end;
506 
507  str = PoolGet(p);
508  if (str == NULL) {
509  printf("PoolGet returned NULL: ");
510  retval = 0;
511  goto end;
512  }
513 
514  if (strcmp(str, "test") != 0) {
515  printf("Memory not properly initialized: ");
516  retval = 0;
517  goto end;
518  }
519 
520  if (p->alloc_stack_size != 4) {
521  printf("p->alloc_stack_size 4 != %" PRIu32 ": ", p->alloc_stack_size);
522  retval = 0;
523  goto end;
524  }
525 
526  if (p->empty_stack_size != 6) {
527  printf("p->empty_stack_size 6 != %" PRIu32 ": ", p->empty_stack_size);
528  retval = 0;
529  goto end;
530  }
531 
532  retval = 1;
533 end:
534  if (p != NULL)
535  PoolFree(p);
536  return retval;
537 }
538 
539 static int PoolTestInit05 (void)
540 {
541  int retval = 0;
542  void *data = NULL;
543 
544  Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL, NULL,PoolTestFree, NULL);
545  if (p == NULL)
546  goto end;
547 
548  data = PoolGet(p);
549  if (data == NULL) {
550  printf("PoolGet returned NULL: ");
551  retval = 0;
552  goto end;
553  }
554 
555  if (p->alloc_stack_size != 4) {
556  printf("p->alloc_stack_size 4 != %" PRIu32 ": ", p->alloc_stack_size);
557  retval = 0;
558  goto end;
559  }
560 
561  if (p->empty_stack_size != 6) {
562  printf("p->empty_stack_size 6 != %" PRIu32 ": ", p->empty_stack_size);
563  retval = 0;
564  goto end;
565  }
566 
567  PoolReturn(p, data);
568  data = NULL;
569 
570  if (p->alloc_stack_size != 5) {
571  printf("p->alloc_stack_size 5 != %" PRIu32 ": ", p->alloc_stack_size);
572  retval = 0;
573  goto end;
574  }
575 
576  if (p->empty_stack_size != 5) {
577  printf("p->empty_stack_size 5 != %" PRIu32 ": ", p->empty_stack_size);
578  retval = 0;
579  goto end;
580  }
581 
582  retval = 1;
583 end:
584  if (p != NULL)
585  PoolFree(p);
586  return retval;
587 }
588 
589 static int PoolTestInit06 (void)
590 {
591  int retval = 0;
592  void *data = NULL;
593  void *data2 = NULL;
594 
595  Pool *p = PoolInit(1,0,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL);
596  if (p == NULL)
597  goto end;
598 
599  if (p->allocated != 0) {
600  printf("p->allocated 0 != %" PRIu32 ": ", p->allocated);
601  retval = 0;
602  goto end;
603  }
604 
605  data = PoolGet(p);
606  if (data == NULL) {
607  printf("PoolGet returned NULL: ");
608  retval = 0;
609  goto end;
610  }
611 
612  if (p->allocated != 1) {
613  printf("p->allocated 1 != %" PRIu32 ": ", p->allocated);
614  retval = 0;
615  goto end;
616  }
617 
618  data2 = PoolGet(p);
619  if (data2 != NULL) {
620  printf("PoolGet returned %p, expected NULL: ", data2);
621  retval = 0;
622  goto end;
623  }
624 
625  PoolReturn(p,data);
626  data = NULL;
627 
628  if (p->allocated != 1) {
629  printf("p->allocated 1 != %" PRIu32 ": ", p->allocated);
630  retval = 0;
631  goto end;
632  }
633 
634  if (p->alloc_stack_size != 1) {
635  printf("p->alloc_stack_size 1 != %" PRIu32 ": ", p->alloc_stack_size);
636  retval = 0;
637  goto end;
638  }
639 
640  retval = 1;
641 end:
642  if (p != NULL)
643  PoolFree(p);
644  return retval;
645 }
646 
647 /** \test pool with unlimited size */
648 static int PoolTestInit07 (void)
649 {
650  int retval = 0;
651  void *data = NULL;
652  void *data2 = NULL;
653 
654  Pool *p = PoolInit(0,1,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL);
655  if (p == NULL)
656  goto end;
657 
658  if (p->max_buckets != 0) {
659  printf("p->max_buckets 0 != %" PRIu32 ": ", p->max_buckets);
660  retval = 0;
661  goto end;
662  }
663 
664  if (p->allocated != 1) {
665  printf("p->allocated 1 != %" PRIu32 ": ", p->allocated);
666  retval = 0;
667  goto end;
668  }
669 
670  data = PoolGet(p);
671  if (data == NULL) {
672  printf("PoolGet returned NULL: ");
673  retval = 0;
674  goto end;
675  }
676 
677  if (p->allocated != 1) {
678  printf("(2) p->allocated 1 != %" PRIu32 ": ", p->allocated);
679  retval = 0;
680  goto end;
681  }
682 
683  data2 = PoolGet(p);
684  if (data2 == NULL) {
685  printf("PoolGet returned NULL: ");
686  retval = 0;
687  goto end;
688  }
689 
690  if (p->allocated != 2) {
691  printf("(3) p->allocated 2 != %" PRIu32 ": ", p->allocated);
692  retval = 0;
693  goto end;
694  }
695 
696  PoolReturn(p,data);
697  data = NULL;
698 
699  if (p->allocated != 2) {
700  printf("(4) p->allocated 2 != %" PRIu32 ": ", p->allocated);
701  retval = 0;
702  goto end;
703  }
704 
705  if (p->alloc_stack_size != 1) {
706  printf("p->alloc_stack_size 1 != %" PRIu32 ": ", p->alloc_stack_size);
707  retval = 0;
708  goto end;
709  }
710 
711  PoolReturn(p,data2);
712  data2 = NULL;
713 
714  if (p->allocated != 1) {
715  printf("(5) p->allocated 1 != %" PRIu32 ": ", p->allocated);
716  retval = 0;
717  goto end;
718  }
719 
720  retval = 1;
721 end:
722  if (p != NULL)
723  PoolFree(p);
724  return retval;
725 }
726 #endif /* UNITTESTS */
727 
729 {
730 #ifdef UNITTESTS
731  UtRegisterTest("PoolTestInit01", PoolTestInit01);
732  UtRegisterTest("PoolTestInit02", PoolTestInit02);
733  UtRegisterTest("PoolTestInit03", PoolTestInit03);
734  UtRegisterTest("PoolTestInit04", PoolTestInit04);
735  UtRegisterTest("PoolTestInit05", PoolTestInit05);
736  UtRegisterTest("PoolTestInit06", PoolTestInit06);
737  UtRegisterTest("PoolTestInit07", PoolTestInit07);
738 
740 #endif /* UNITTESTS */
741 }
742 
743 
744 /**
745  * @}
746  */
len
uint8_t len
Definition: app-layer-dnp3.h:2
Pool_::pb_buffer
PoolBucket * pb_buffer
Definition: util-pool.h:58
Pool_::Free
void(* Free)(void *)
Definition: util-pool.h:64
Pool_::Init
int(* Init)(void *, void *)
Definition: util-pool.h:61
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
POOL_BUCKET_PREALLOCATED
#define POOL_BUCKET_PREALLOCATED
Definition: util-pool.h:33
util-pool-thread.h
PoolRegisterTests
void PoolRegisterTests(void)
Definition: util-pool.c:728
SC_EINVAL
@ SC_EINVAL
Definition: util-error.h:30
PoolPrintSaturation
void PoolPrintSaturation(Pool *p)
Definition: util-pool.c:379
Pool_::alloc_stack
PoolBucket * alloc_stack
Definition: util-pool.h:51
Pool_
Definition: util-pool.h:43
Pool_::Cleanup
void(* Cleanup)(void *)
Definition: util-pool.h:63
util-unittest.h
SC_ENOMEM
@ SC_ENOMEM
Definition: util-error.h:29
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
util-debug.h
Pool_::empty_stack_size
uint32_t empty_stack_size
Definition: util-pool.h:54
PoolBucket_::next
struct PoolBucket_ * next
Definition: util-pool.h:39
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
Pool_::outstanding
uint32_t outstanding
Definition: util-pool.h:67
PoolBucket_::data
void * data
Definition: util-pool.h:37
SCReturn
#define SCReturn
Definition: util-debug.h:273
PoolFree
void PoolFree(Pool *p)
Definition: util-pool.c:226
SC_OK
@ SC_OK
Definition: util-error.h:27
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:287
PoolBucket_
Definition: util-pool.h:36
PoolReturn
void PoolReturn(Pool *p, void *data)
Definition: util-pool.c:339
Pool_::max_buckets
uint32_t max_buckets
Definition: util-pool.h:44
PoolThreadRegisterTests
void PoolThreadRegisterTests(void)
Definition: util-pool-thread.c:401
suricata-common.h
Pool_::Alloc
void *(* Alloc)(void)
Definition: util-pool.h:60
Pool_::preallocated
uint32_t preallocated
Definition: util-pool.h:45
Pool_::allocated
uint32_t allocated
Definition: util-pool.h:46
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:286
PoolGet
void * PoolGet(Pool *p)
Definition: util-pool.c:281
Pool_::data_buffer_size
int data_buffer_size
Definition: util-pool.h:56
Pool_::empty_stack
PoolBucket * empty_stack
Definition: util-pool.h:53
SCFree
#define SCFree(p)
Definition: util-mem.h:61
sc_errno
thread_local SCError sc_errno
Definition: util-error.c:31
PoolBucket_::flags
uint8_t flags
Definition: util-pool.h:38
Pool_::elt_size
uint32_t elt_size
Definition: util-pool.h:66
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
util-pool.h
PoolInit
Pool * PoolInit(uint32_t size, uint32_t prealloc_size, uint32_t elt_size, void *(*Alloc)(void), int(*Init)(void *, void *), void *InitData, void(*Cleanup)(void *), void(*Free)(void *))
Init a Pool.
Definition: util-pool.c:84
Pool_::InitData
void * InitData
Definition: util-pool.h:62
Pool_::alloc_stack_size
uint32_t alloc_stack_size
Definition: util-pool.h:49
Pool_::data_buffer
void * data_buffer
Definition: util-pool.h:57
PoolPrint
void PoolPrint(Pool *p)
Definition: util-pool.c:274