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 0 if not inside the prealloc'd block, 1 if inside */
58 static int 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 0;
63  }
64  return 1;
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 
105  /* setup the filter */
106  p = SCMalloc(sizeof(Pool));
107  if (unlikely(p == NULL)) {
109  goto error;
110  }
111 
112  memset(p,0,sizeof(Pool));
113 
114  p->max_buckets = size;
115  p->preallocated = prealloc_size;
116  p->elt_size = elt_size;
117  p->data_buffer_size = prealloc_size * elt_size;
118  p->Alloc = Alloc;
119  p->Init = Init;
120  p->InitData = InitData;
121  p->Cleanup = Cleanup;
122  p->Free = Free;
123  if (p->Init == NULL) {
124  p->Init = PoolMemset;
125  p->InitData = p;
126  }
127 
128  /* alloc the buckets and place them in the empty list */
129  uint32_t u32 = 0;
130  if (size > 0) {
131  PoolBucket *pb = SCCalloc(size, sizeof(PoolBucket));
132  if (unlikely(pb == NULL)) {
134  goto error;
135  }
136  memset(pb, 0, size * sizeof(PoolBucket));
137  p->pb_buffer = pb;
138  for (u32 = 0; u32 < size; u32++) {
139  /* populate pool */
140  pb->next = p->empty_stack;
142  p->empty_stack = pb;
143  p->empty_stack_size++;
144  pb++;
145  }
146 
147  p->data_buffer = SCCalloc(prealloc_size, elt_size);
148  /* FIXME better goto */
149  if (p->data_buffer == NULL) {
151  goto error;
152  }
153  }
154  /* prealloc the buckets and requeue them to the alloc list */
155  for (u32 = 0; u32 < prealloc_size; u32++) {
156  if (size == 0) { /* unlimited */
157  PoolBucket *pb = SCMalloc(sizeof(PoolBucket));
158  if (unlikely(pb == NULL)) {
160  goto error;
161  }
162  memset(pb, 0, sizeof(PoolBucket));
163 
164  if (p->Alloc) {
165  pb->data = p->Alloc();
166  } else {
167  pb->data = SCMalloc(p->elt_size);
168  }
169  if (pb->data == NULL) {
170  SCFree(pb);
172  goto error;
173  }
174  if (p->Init(pb->data, p->InitData) != 1) {
175  if (p->Free)
176  p->Free(pb->data);
177  else
178  SCFree(pb->data);
179  SCFree(pb);
181  goto error;
182  }
183  p->allocated++;
184 
185  pb->next = p->alloc_stack;
186  p->alloc_stack = pb;
187  p->alloc_stack_size++;
188  } else {
189  PoolBucket *pb = p->empty_stack;
190  if (pb == NULL) {
192  goto error;
193  }
194 
195  pb->data = (char *)p->data_buffer + u32 * elt_size;
196  if (p->Init(pb->data, p->InitData) != 1) {
197  pb->data = NULL;
199  goto error;
200  }
201 
202  p->empty_stack = pb->next;
203  p->empty_stack_size--;
204 
205  p->allocated++;
206 
207  pb->next = p->alloc_stack;
208  p->alloc_stack = pb;
209  p->alloc_stack_size++;
210  }
211  }
212 
213  return p;
214 
215 error:
216  if (p != NULL) {
217  PoolFree(p);
218  }
219  return NULL;
220 }
221 
222 void PoolFree(Pool *p)
223 {
224  if (p == NULL)
225  return;
226 
227  while (p->alloc_stack != NULL) {
228  PoolBucket *pb = p->alloc_stack;
229  p->alloc_stack = pb->next;
230  if (p->Cleanup)
231  p->Cleanup(pb->data);
232  if (PoolDataPreAllocated(p, pb->data) == 0) {
233  if (p->Free)
234  p->Free(pb->data);
235  else
236  SCFree(pb->data);
237  }
238  pb->data = NULL;
239  if (!(pb->flags & POOL_BUCKET_PREALLOCATED)) {
240  SCFree(pb);
241  }
242  }
243 
244  while (p->empty_stack != NULL) {
245  PoolBucket *pb = p->empty_stack;
246  p->empty_stack = pb->next;
247  if (pb->data!= NULL) {
248  if (p->Cleanup)
249  p->Cleanup(pb->data);
250  if (PoolDataPreAllocated(p, pb->data) == 0) {
251  if (p->Free)
252  p->Free(pb->data);
253  else
254  SCFree(pb->data);
255  }
256  pb->data = NULL;
257  }
258  if (!(pb->flags & POOL_BUCKET_PREALLOCATED)) {
259  SCFree(pb);
260  }
261  }
262 
263  if (p->pb_buffer)
264  SCFree(p->pb_buffer);
265  if (p->data_buffer)
266  SCFree(p->data_buffer);
267  SCFree(p);
268 }
269 
270 void PoolPrint(Pool *p)
271 {
272  printf("\n----------- Hash Table Stats ------------\n");
273  printf("Buckets: %" PRIu32 "\n", p->empty_stack_size + p->alloc_stack_size);
274  printf("-----------------------------------------\n");
275 }
276 
277 void *PoolGet(Pool *p)
278 {
279  SCEnter();
280 
281  PoolBucket *pb = p->alloc_stack;
282  if (pb != NULL) {
283  /* pull from the alloc list */
284  p->alloc_stack = pb->next;
285  p->alloc_stack_size--;
286 
287  /* put in the empty list */
288  pb->next = p->empty_stack;
289  p->empty_stack = pb;
290  p->empty_stack_size++;
291  } else {
292  if (p->max_buckets == 0 || p->allocated < p->max_buckets) {
293  void *pitem;
294  SCLogDebug("max_buckets %"PRIu32"", p->max_buckets);
295 
296  if (p->Alloc != NULL) {
297  pitem = p->Alloc();
298  } else {
299  pitem = SCMalloc(p->elt_size);
300  }
301 
302  if (pitem != NULL) {
303  if (p->Init(pitem, p->InitData) != 1) {
304  if (p->Free != NULL)
305  p->Free(pitem);
306  else
307  SCFree(pitem);
308  SCReturnPtr(NULL, "void");
309  }
310 
311  p->allocated++;
312  p->outstanding++;
313 #ifdef DEBUG
314  if (p->outstanding > p->max_outstanding)
315  p->max_outstanding = p->outstanding;
316 #endif
317  }
318 
319  SCReturnPtr(pitem, "void");
320  } else {
321  SCReturnPtr(NULL, "void");
322  }
323  }
324 
325  void *ptr = pb->data;
326  pb->data = NULL;
327  p->outstanding++;
328 #ifdef DEBUG
329  if (p->outstanding > p->max_outstanding)
330  p->max_outstanding = p->outstanding;
331 #endif
332  SCReturnPtr(ptr,"void");
333 }
334 
335 void PoolReturn(Pool *p, void *data)
336 {
337  SCEnter();
338 
339  PoolBucket *pb = p->empty_stack;
340 
341  SCLogDebug("pb %p", pb);
342 
343  if (pb == NULL) {
344  p->allocated--;
345  p->outstanding--;
346  if (p->Cleanup != NULL) {
347  p->Cleanup(data);
348  }
349  if (PoolDataPreAllocated(p, data) == 0) {
350  if (p->Free)
351  p->Free(data);
352  else
353  SCFree(data);
354  }
355 
356  SCLogDebug("tried to return data %p to the pool %p, but no more "
357  "buckets available. Just freeing the data.", data, p);
358  SCReturn;
359  }
360 
361  /* pull from the alloc list */
362  p->empty_stack = pb->next;
363  p->empty_stack_size--;
364 
365  /* put in the alloc list */
366  pb->next = p->alloc_stack;
367  p->alloc_stack = pb;
368  p->alloc_stack_size++;
369 
370  pb->data = data;
371  p->outstanding--;
372  SCReturn;
373 }
374 
376 {
377  SCLogDebug("pool %p is using %" PRIu32 " out of %" PRIu32 " items (%02.1f%%), max %" PRIu32
378  " (%02.1f%%): pool struct memory %" PRIu64 ".",
379  p, p->outstanding, p->max_buckets,
380  (float)(p->outstanding) / (float)(p->max_buckets) * 100, p->max_outstanding,
381  (float)(p->max_outstanding) / (float)(p->max_buckets) * 100,
382  (uint64_t)(p->max_buckets * sizeof(PoolBucket)));
383 }
384 
385 /*
386  * ONLY TESTS BELOW THIS COMMENT
387  */
388 
389 #ifdef UNITTESTS
390 static void *PoolTestAlloc(void)
391 {
392  void *ptr = SCMalloc(10);
393  if (unlikely(ptr == NULL))
394  return NULL;
395  return ptr;
396 }
397 static int PoolTestInitArg(void *data, void *allocdata)
398 {
399  size_t len = strlen((char *)allocdata) + 1;
400  char *str = data;
401  if (str != NULL)
402  strlcpy(str,(char *)allocdata,len);
403  return 1;
404 }
405 
406 static void PoolTestFree(void *ptr)
407 {
408  return;
409 }
410 
411 static int PoolTestInit01 (void)
412 {
413  Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL);
414  if (p == NULL)
415  return 0;
416 
417  PoolFree(p);
418  return 1;
419 }
420 
421 static int PoolTestInit02 (void)
422 {
423  int retval = 0;
424 
425  Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL);
426  if (p == NULL)
427  goto end;
428 
429  if (p->alloc_stack == NULL || p->empty_stack == NULL) {
430  printf("list(s) not properly initialized (a:%p e:%p): ",
431  p->alloc_stack, p->empty_stack);
432  retval = 0;
433  goto end;
434  }
435 
436  if (p->Alloc != PoolTestAlloc) {
437  printf("Alloc func ptr %p != %p: ",
438  p->Alloc, PoolTestAlloc);
439  retval = 0;
440  goto end;
441  }
442 
443  if (p->Cleanup != PoolTestFree) {
444  printf("Free func ptr %p != %p: ",
445  p->Cleanup, PoolTestFree);
446  retval = 0;
447  goto end;
448  }
449 
450  retval = 1;
451 end:
452  if (p != NULL)
453  PoolFree(p);
454  return retval;
455 }
456 
457 static int PoolTestInit03 (void)
458 {
459  int retval = 0;
460  void *data = NULL;
461 
462  Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL);
463  if (p == NULL)
464  goto end;
465 
466  data = PoolGet(p);
467  if (data == NULL) {
468  printf("PoolGet returned NULL: ");
469  retval = 0;
470  goto end;
471  }
472 
473  if (p->alloc_stack_size != 4) {
474  printf("p->alloc_stack_size 4 != %" PRIu32 ": ", p->alloc_stack_size);
475  retval = 0;
476  goto end;
477  }
478 
479  if (p->empty_stack_size != 6) {
480  printf("p->empty_stack_size 6 != %" PRIu32 ": ", p->empty_stack_size);
481  retval = 0;
482  goto end;
483  }
484 
485  retval = 1;
486 end:
487  if (p != NULL)
488  PoolFree(p);
489  return retval;
490 }
491 
492 static int PoolTestInit04 (void)
493 {
494  int retval = 0;
495  char *str = NULL;
496 
497  Pool *p = PoolInit(10,5,strlen("test") + 1,NULL, PoolTestInitArg,(void *)"test",PoolTestFree, NULL);
498  if (p == NULL)
499  goto end;
500 
501  str = PoolGet(p);
502  if (str == NULL) {
503  printf("PoolGet returned NULL: ");
504  retval = 0;
505  goto end;
506  }
507 
508  if (strcmp(str, "test") != 0) {
509  printf("Memory not properly initialized: ");
510  retval = 0;
511  goto end;
512  }
513 
514  if (p->alloc_stack_size != 4) {
515  printf("p->alloc_stack_size 4 != %" PRIu32 ": ", p->alloc_stack_size);
516  retval = 0;
517  goto end;
518  }
519 
520  if (p->empty_stack_size != 6) {
521  printf("p->empty_stack_size 6 != %" PRIu32 ": ", p->empty_stack_size);
522  retval = 0;
523  goto end;
524  }
525 
526  retval = 1;
527 end:
528  if (p != NULL)
529  PoolFree(p);
530  return retval;
531 }
532 
533 static int PoolTestInit05 (void)
534 {
535  int retval = 0;
536  void *data = NULL;
537 
538  Pool *p = PoolInit(10,5,10,PoolTestAlloc,NULL, NULL,PoolTestFree, NULL);
539  if (p == NULL)
540  goto end;
541 
542  data = PoolGet(p);
543  if (data == NULL) {
544  printf("PoolGet returned NULL: ");
545  retval = 0;
546  goto end;
547  }
548 
549  if (p->alloc_stack_size != 4) {
550  printf("p->alloc_stack_size 4 != %" PRIu32 ": ", p->alloc_stack_size);
551  retval = 0;
552  goto end;
553  }
554 
555  if (p->empty_stack_size != 6) {
556  printf("p->empty_stack_size 6 != %" PRIu32 ": ", p->empty_stack_size);
557  retval = 0;
558  goto end;
559  }
560 
561  PoolReturn(p, data);
562  data = NULL;
563 
564  if (p->alloc_stack_size != 5) {
565  printf("p->alloc_stack_size 5 != %" PRIu32 ": ", p->alloc_stack_size);
566  retval = 0;
567  goto end;
568  }
569 
570  if (p->empty_stack_size != 5) {
571  printf("p->empty_stack_size 5 != %" PRIu32 ": ", p->empty_stack_size);
572  retval = 0;
573  goto end;
574  }
575 
576  retval = 1;
577 end:
578  if (p != NULL)
579  PoolFree(p);
580  return retval;
581 }
582 
583 static int PoolTestInit06 (void)
584 {
585  int retval = 0;
586  void *data = NULL;
587  void *data2 = NULL;
588 
589  Pool *p = PoolInit(1,0,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL);
590  if (p == NULL)
591  goto end;
592 
593  if (p->allocated != 0) {
594  printf("p->allocated 0 != %" PRIu32 ": ", p->allocated);
595  retval = 0;
596  goto end;
597  }
598 
599  data = PoolGet(p);
600  if (data == NULL) {
601  printf("PoolGet returned NULL: ");
602  retval = 0;
603  goto end;
604  }
605 
606  if (p->allocated != 1) {
607  printf("p->allocated 1 != %" PRIu32 ": ", p->allocated);
608  retval = 0;
609  goto end;
610  }
611 
612  data2 = PoolGet(p);
613  if (data2 != NULL) {
614  printf("PoolGet returned %p, expected NULL: ", data2);
615  retval = 0;
616  goto end;
617  }
618 
619  PoolReturn(p,data);
620  data = NULL;
621 
622  if (p->allocated != 1) {
623  printf("p->allocated 1 != %" PRIu32 ": ", p->allocated);
624  retval = 0;
625  goto end;
626  }
627 
628  if (p->alloc_stack_size != 1) {
629  printf("p->alloc_stack_size 1 != %" PRIu32 ": ", p->alloc_stack_size);
630  retval = 0;
631  goto end;
632  }
633 
634  retval = 1;
635 end:
636  if (p != NULL)
637  PoolFree(p);
638  return retval;
639 }
640 
641 /** \test pool with unlimited size */
642 static int PoolTestInit07 (void)
643 {
644  int retval = 0;
645  void *data = NULL;
646  void *data2 = NULL;
647 
648  Pool *p = PoolInit(0,1,10,PoolTestAlloc,NULL,NULL,PoolTestFree, NULL);
649  if (p == NULL)
650  goto end;
651 
652  if (p->max_buckets != 0) {
653  printf("p->max_buckets 0 != %" PRIu32 ": ", p->max_buckets);
654  retval = 0;
655  goto end;
656  }
657 
658  if (p->allocated != 1) {
659  printf("p->allocated 1 != %" PRIu32 ": ", p->allocated);
660  retval = 0;
661  goto end;
662  }
663 
664  data = PoolGet(p);
665  if (data == NULL) {
666  printf("PoolGet returned NULL: ");
667  retval = 0;
668  goto end;
669  }
670 
671  if (p->allocated != 1) {
672  printf("(2) p->allocated 1 != %" PRIu32 ": ", p->allocated);
673  retval = 0;
674  goto end;
675  }
676 
677  data2 = PoolGet(p);
678  if (data2 == NULL) {
679  printf("PoolGet returned NULL: ");
680  retval = 0;
681  goto end;
682  }
683 
684  if (p->allocated != 2) {
685  printf("(3) p->allocated 2 != %" PRIu32 ": ", p->allocated);
686  retval = 0;
687  goto end;
688  }
689 
690  PoolReturn(p,data);
691  data = NULL;
692 
693  if (p->allocated != 2) {
694  printf("(4) p->allocated 2 != %" PRIu32 ": ", p->allocated);
695  retval = 0;
696  goto end;
697  }
698 
699  if (p->alloc_stack_size != 1) {
700  printf("p->alloc_stack_size 1 != %" PRIu32 ": ", p->alloc_stack_size);
701  retval = 0;
702  goto end;
703  }
704 
705  PoolReturn(p,data2);
706  data2 = NULL;
707 
708  if (p->allocated != 1) {
709  printf("(5) p->allocated 1 != %" PRIu32 ": ", p->allocated);
710  retval = 0;
711  goto end;
712  }
713 
714  retval = 1;
715 end:
716  if (p != NULL)
717  PoolFree(p);
718  return retval;
719 }
720 #endif /* UNITTESTS */
721 
723 {
724 #ifdef UNITTESTS
725  UtRegisterTest("PoolTestInit01", PoolTestInit01);
726  UtRegisterTest("PoolTestInit02", PoolTestInit02);
727  UtRegisterTest("PoolTestInit03", PoolTestInit03);
728  UtRegisterTest("PoolTestInit04", PoolTestInit04);
729  UtRegisterTest("PoolTestInit05", PoolTestInit05);
730  UtRegisterTest("PoolTestInit06", PoolTestInit06);
731  UtRegisterTest("PoolTestInit07", PoolTestInit07);
732 
734 #endif /* UNITTESTS */
735 }
736 
737 
738 /**
739  * @}
740  */
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:722
SC_EINVAL
@ SC_EINVAL
Definition: util-error.h:32
PoolPrintSaturation
void PoolPrintSaturation(Pool *p)
Definition: util-pool.c:375
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:31
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:222
SC_OK
@ SC_OK
Definition: util-error.h:29
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:335
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:280
PoolGet
void * PoolGet(Pool *p)
Definition: util-pool.c:277
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:270