FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
pool.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  Copyright (c) 2001, 2002, 2003, 2004 Eliot Dresselhaus
17 
18  Permission is hereby granted, free of charge, to any person obtaining
19  a copy of this software and associated documentation files (the
20  "Software"), to deal in the Software without restriction, including
21  without limitation the rights to use, copy, modify, merge, publish,
22  distribute, sublicense, and/or sell copies of the Software, and to
23  permit persons to whom the Software is furnished to do so, subject to
24  the following conditions:
25 
26  The above copyright notice and this permission notice shall be
27  included in all copies or substantial portions of the Software.
28 
29  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37 /** @file
38  * @brief Fixed length block allocator.
39  Pools are built from clib vectors and bitmaps. Use pools when
40  repeatedly allocating and freeing fixed-size data. Pools are
41  fast, and avoid memory fragmentation.
42  */
43 
44 #ifndef included_pool_h
45 #define included_pool_h
46 
47 #include <vppinfra/bitmap.h>
48 #include <vppinfra/error.h>
49 
50 
51 typedef struct
52 {
53  /** Bitmap of indices of free objects. */
55 
56  /** Vector of free indices. One element for each set bit in bitmap. */
58 
59  /* The following fields are set for fixed-size, preallocated pools */
60 
61  /** Maximum size of the pool, in elements */
63 
64  /** mmap segment info: base + length */
67 
69 
70 /** Align pool header so that pointers are naturally aligned. */
71 #define pool_aligned_header_bytes \
72  vec_aligned_header_bytes (sizeof (pool_header_t), sizeof (void *))
73 
74 /** Get pool header from user pool pointer */
76 pool_header (void *v)
77 {
78  return vec_aligned_header (v, sizeof (pool_header_t), sizeof (void *));
79 }
80 
81 extern void _pool_init_fixed (void **, u32, u32);
82 extern void fpool_free (void *);
83 
84 /** initialize a fixed-size, preallocated pool */
85 #define pool_init_fixed(pool,max_elts) \
86 { \
87  _pool_init_fixed((void **)&(pool),sizeof(pool[0]),max_elts); \
88 }
89 
90 /** Validate a pool */
91 always_inline void
92 pool_validate (void *v)
93 {
94  pool_header_t *p = pool_header (v);
95  uword i, n_free_bitmap;
96 
97  if (!v)
98  return;
99 
100  n_free_bitmap = clib_bitmap_count_set_bits (p->free_bitmap);
101  ASSERT (n_free_bitmap == vec_len (p->free_indices));
102  for (i = 0; i < vec_len (p->free_indices); i++)
104 }
105 
106 always_inline void
108 {
109  pool_header_t *p = pool_header (v);
110 
111  if (v)
113 }
114 
115 #define pool_validate_index(v,i) \
116 do { \
117  uword __pool_validate_index = (i); \
118  vec_validate_ha ((v), __pool_validate_index, \
119  pool_aligned_header_bytes, /* align */ 0); \
120  pool_header_validate_index ((v), __pool_validate_index); \
121 } while (0)
122 
123 /** Number of active elements in a pool.
124  * @return Number of active elements in a pool
125  */
127 pool_elts (void *v)
128 {
129  uword ret = vec_len (v);
130  if (v)
131  ret -= vec_len (pool_header (v)->free_indices);
132  return ret;
133 }
134 
135 /** Number of elements in pool vector.
136 
137  @note You probably want to call pool_elts() instead.
138 */
139 #define pool_len(p) vec_len(p)
140 
141 /** Number of elements in pool vector (usable as an lvalue)
142 
143  @note You probably don't want to use this macro.
144 */
145 #define _pool_len(p) _vec_len(p)
146 
147 /** Memory usage of pool header. */
150 {
151  pool_header_t *p = pool_header (v);
152 
153  if (!v)
154  return 0;
155 
156  return vec_bytes (p->free_bitmap) + vec_bytes (p->free_indices);
157 }
158 
159 /** Memory usage of pool. */
160 #define pool_bytes(P) (vec_bytes (P) + pool_header_bytes (P))
161 
162 /** Local variable naming macro. */
163 #define _pool_var(v) _pool_##v
164 
165 /** Queries whether pool has at least N_FREE free elements. */
167 pool_free_elts (void *v)
168 {
169  pool_header_t *p = pool_header (v);
170  uword n_free = 0;
171 
172  if (v)
173  {
174  n_free += vec_len (p->free_indices);
175 
176  /*
177  * Space left at end of vector?
178  * Fixed-size pools have max_elts set non-zero,
179  */
180  if (p->max_elts == 0)
181  n_free += vec_capacity (v, sizeof (p[0])) - vec_len (v);
182  }
183 
184  return n_free;
185 }
186 
187 /** Allocate an object E from a pool P (general version).
188 
189  First search free list. If nothing is free extend vector of objects.
190 */
191 #define _pool_get_aligned_internal_numa(P,E,A,Z,N) \
192 do { \
193  pool_header_t * _pool_var (p) = pool_header (P); \
194  uword _pool_var (l); \
195  \
196  STATIC_ASSERT(A==0 || ((A % sizeof(P[0]))==0) \
197  || ((sizeof(P[0]) % A) == 0), \
198  "Pool aligned alloc of incorrectly sized object"); \
199  _pool_var (l) = 0; \
200  if (P) \
201  _pool_var (l) = vec_len (_pool_var (p)->free_indices); \
202  \
203  if (_pool_var (l) > 0) \
204  { \
205  /* Return free element from free list. */ \
206  uword _pool_var (i) = \
207  _pool_var (p)->free_indices[_pool_var (l) - 1]; \
208  (E) = (P) + _pool_var (i); \
209  _pool_var (p)->free_bitmap = \
210  clib_bitmap_andnoti_notrim (_pool_var (p)->free_bitmap, \
211  _pool_var (i)); \
212  _vec_len (_pool_var (p)->free_indices) = _pool_var (l) - 1; \
213  CLIB_MEM_UNPOISON((E), sizeof((E)[0])); \
214  } \
215  else \
216  { \
217  /* fixed-size, preallocated pools cannot expand */ \
218  if ((P) && _pool_var(p)->max_elts) \
219  { \
220  clib_warning ("can't expand fixed-size pool"); \
221  os_out_of_memory(); \
222  } \
223  /* Nothing on free list, make a new element and return it. */ \
224  P = _vec_resize_numa (P, \
225  /* length_increment */ 1, \
226  /* new size */ (vec_len (P) + 1) * sizeof (P[0]), \
227  pool_aligned_header_bytes, \
228  /* align */ (A), \
229  /* numa */ (N)); \
230  E = vec_end (P) - 1; \
231  } \
232  if (Z) \
233  memset(E, 0, sizeof(*E)); \
234 } while (0)
235 
236 #define pool_get_aligned_zero_numa(P,E,A,Z,S) \
237  _pool_get_aligned_internal_numa(P,E,A,Z,S)
238 
239 #define pool_get_aligned_numa(P,E,A,S) \
240  _pool_get_aligned_internal_numa(P,E,A,0/*zero*/,S)
241 
242 #define pool_get_numa(P,E,S) \
243  _pool_get_aligned_internal_numa(P,E,0/*align*/,0/*zero*/,S)
244 
245 #define _pool_get_aligned_internal(P,E,A,Z) \
246  _pool_get_aligned_internal_numa(P,E,A,Z,VEC_NUMA_UNSPECIFIED)
247 
248 /** Allocate an object E from a pool P with alignment A */
249 #define pool_get_aligned(P,E,A) _pool_get_aligned_internal(P,E,A,0)
250 
251 /** Allocate an object E from a pool P with alignment A and zero it */
252 #define pool_get_aligned_zero(P,E,A) _pool_get_aligned_internal(P,E,A,1)
253 
254 /** Allocate an object E from a pool P (unspecified alignment). */
255 #define pool_get(P,E) pool_get_aligned(P,E,0)
256 
257 /** Allocate an object E from a pool P and zero it */
258 #define pool_get_zero(P,E) pool_get_aligned_zero(P,E,0)
259 
260 /** See if pool_get will expand the pool or not */
261 #define pool_get_aligned_will_expand(P,YESNO,A) \
262 do { \
263  pool_header_t * _pool_var (p) = pool_header (P); \
264  uword _pool_var (l); \
265  \
266  _pool_var (l) = 0; \
267  if (P) \
268  { \
269  if (_pool_var (p)->max_elts) \
270  _pool_var (l) = _pool_var (p)->max_elts; \
271  else \
272  _pool_var (l) = vec_len (_pool_var (p)->free_indices); \
273  } \
274  \
275  /* Free elements, certainly won't expand */ \
276  if (_pool_var (l) > 0) \
277  YESNO=0; \
278  else \
279  { \
280  /* Nothing on free list, make a new element and return it. */ \
281  YESNO = _vec_resize_will_expand \
282  (P, \
283  /* length_increment */ 1, \
284  /* new size */ (vec_len (P) + 1) * sizeof (P[0]), \
285  pool_aligned_header_bytes, \
286  /* align */ (A)); \
287  } \
288 } while (0)
289 
290 /** Tell the caller if pool get will expand the pool */
291 #define pool_get_will_expand(P,YESNO) pool_get_aligned_will_expand(P,YESNO,0)
292 
293 /** Use free bitmap to query whether given element is free. */
294 #define pool_is_free(P,E) \
295 ({ \
296  pool_header_t * _pool_var (p) = pool_header (P); \
297  uword _pool_var (i) = (E) - (P); \
298  (_pool_var (i) < vec_len (P)) ? clib_bitmap_get (_pool_var (p)->free_bitmap, _pool_i) : 1; \
299 })
300 
301 /** Use free bitmap to query whether given index is free */
302 #define pool_is_free_index(P,I) pool_is_free((P),(P)+(I))
303 
304 /** Free an object E in pool P. */
305 #define pool_put(P, E) \
306  do \
307  { \
308  typeof (P) _pool_var (p__) = (P); \
309  typeof (E) _pool_var (e__) = (E); \
310  pool_header_t *_pool_var (p) = pool_header (_pool_var (p__)); \
311  uword _pool_var (l) = _pool_var (e__) - _pool_var (p__); \
312  if (_pool_var (p)->max_elts == 0) \
313  ASSERT (vec_is_member (_pool_var (p__), _pool_var (e__))); \
314  ASSERT (!pool_is_free (_pool_var (p__), _pool_var (e__))); \
315  \
316  /* Add element to free bitmap and to free list. */ \
317  _pool_var (p)->free_bitmap = \
318  clib_bitmap_ori_notrim (_pool_var (p)->free_bitmap, _pool_var (l)); \
319  \
320  /* Preallocated pool? */ \
321  if (_pool_var (p)->max_elts) \
322  { \
323  ASSERT (_pool_var (l) < _pool_var (p)->max_elts); \
324  _pool_var (p) \
325  ->free_indices[_vec_len (_pool_var (p)->free_indices)] = \
326  _pool_var (l); \
327  _vec_len (_pool_var (p)->free_indices) += 1; \
328  } \
329  else \
330  vec_add1 (_pool_var (p)->free_indices, _pool_var (l)); \
331  \
332  CLIB_MEM_POISON (_pool_var (e__), sizeof (_pool_var (e__)[0])); \
333  } \
334  while (0)
335 
336 /** Free pool element with given index. */
337 #define pool_put_index(p,i) \
338 do { \
339  typeof (p) _e = (p) + (i); \
340  pool_put (p, _e); \
341 } while (0)
342 
343 /** Allocate N more free elements to pool (general version). */
344 #define pool_alloc_aligned(P,N,A) \
345 do { \
346  pool_header_t * _p; \
347  \
348  if ((P)) \
349  { \
350  _p = pool_header (P); \
351  if (_p->max_elts) \
352  { \
353  clib_warning ("Can't expand fixed-size pool"); \
354  os_out_of_memory(); \
355  } \
356  } \
357  \
358  (P) = _vec_resize ((P), 0, (vec_len (P) + (N)) * sizeof (P[0]), \
359  pool_aligned_header_bytes, \
360  (A)); \
361  _p = pool_header (P); \
362  vec_resize (_p->free_indices, (N)); \
363  _vec_len (_p->free_indices) -= (N); \
364 } while (0)
365 
366 /** Allocate N more free elements to pool (unspecified alignment). */
367 #define pool_alloc(P,N) pool_alloc_aligned(P,N,0)
368 
369 /**
370  * Return copy of pool with alignment
371  *
372  * @param P pool to copy
373  * @param A alignment (may be zero)
374  * @return copy of pool
375  */
376 #define pool_dup_aligned(P,A) \
377 ({ \
378  typeof (P) _pool_var (new) = 0; \
379  pool_header_t * _pool_var (ph), * _pool_var (new_ph); \
380  u32 _pool_var (n) = pool_len (P); \
381  if ((P)) \
382  { \
383  _pool_var (new) = _vec_resize (_pool_var (new), _pool_var (n), \
384  _pool_var (n) * sizeof ((P)[0]), \
385  pool_aligned_header_bytes, (A)); \
386  clib_memcpy_fast (_pool_var (new), (P), \
387  _pool_var (n) * sizeof ((P)[0])); \
388  _pool_var (ph) = pool_header (P); \
389  _pool_var (new_ph) = pool_header (_pool_var (new)); \
390  _pool_var (new_ph)->free_bitmap = \
391  clib_bitmap_dup (_pool_var (ph)->free_bitmap); \
392  _pool_var (new_ph)->free_indices = \
393  vec_dup (_pool_var (ph)->free_indices); \
394  _pool_var (new_ph)->max_elts = _pool_var (ph)->max_elts; \
395  } \
396  _pool_var (new); \
397 })
398 
399 /**
400  * Return copy of pool without alignment
401  *
402  * @param P pool to copy
403  * @return copy of pool
404  */
405 #define pool_dup(P) pool_dup_aligned(P,0)
406 
407 /** Low-level free pool operator (do not call directly). */
408 always_inline void *
409 _pool_free (void *v)
410 {
411  pool_header_t *p = pool_header (v);
412  if (!v)
413  return v;
415 
416  if (p->max_elts)
417  {
418  int rv;
419 
420  rv = munmap (p->mmap_base, p->mmap_size);
421  if (rv)
422  clib_unix_warning ("munmap");
423  }
424  else
425  {
426  vec_free (p->free_indices);
428  }
429  return 0;
430 }
431 
434 {
435  pool_header_t *h = pool_header (pool);
436  return clib_bitmap_first_clear (h->free_bitmap);
437 }
438 
441 {
442  pool_header_t *h = pool_header (pool);
443  return clib_bitmap_next_clear (h->free_bitmap, last + 1);
444 }
445 
446 /** Free a pool. */
447 #define pool_free(p) (p) = _pool_free(p)
448 
449 /** Optimized iteration through pool.
450 
451  @param LO pointer to first element in chunk
452  @param HI pointer to last element in chunk
453  @param POOL pool to iterate across
454  @param BODY operation to perform
455 
456  Optimized version which assumes that BODY is smart enough to
457  process multiple (LOW,HI) chunks. See also pool_foreach().
458  */
459 #define pool_foreach_region(LO,HI,POOL,BODY) \
460 do { \
461  uword _pool_var (i), _pool_var (lo), _pool_var (hi), _pool_var (len); \
462  uword _pool_var (bl), * _pool_var (b); \
463  pool_header_t * _pool_var (p); \
464  \
465  _pool_var (p) = pool_header (POOL); \
466  _pool_var (b) = (POOL) ? _pool_var (p)->free_bitmap : 0; \
467  _pool_var (bl) = vec_len (_pool_var (b)); \
468  _pool_var (len) = vec_len (POOL); \
469  _pool_var (lo) = 0; \
470  \
471  for (_pool_var (i) = 0; \
472  _pool_var (i) <= _pool_var (bl); \
473  _pool_var (i)++) \
474  { \
475  uword _pool_var (m), _pool_var (f); \
476  _pool_var (m) = (_pool_var (i) < _pool_var (bl) \
477  ? _pool_var (b) [_pool_var (i)] \
478  : 1); \
479  while (_pool_var (m) != 0) \
480  { \
481  _pool_var (f) = first_set (_pool_var (m)); \
482  _pool_var (hi) = (_pool_var (i) * BITS (_pool_var (b)[0]) \
483  + min_log2 (_pool_var (f))); \
484  _pool_var (hi) = (_pool_var (i) < _pool_var (bl) \
485  ? _pool_var (hi) : _pool_var (len)); \
486  _pool_var (m) ^= _pool_var (f); \
487  if (_pool_var (hi) > _pool_var (lo)) \
488  { \
489  (LO) = _pool_var (lo); \
490  (HI) = _pool_var (hi); \
491  do { BODY; } while (0); \
492  } \
493  _pool_var (lo) = _pool_var (hi) + 1; \
494  } \
495  } \
496 } while (0)
497 
498 /** Iterate through pool.
499 
500  @param VAR A variable of same type as pool vector to be used as an
501  iterator.
502  @param POOL The pool to iterate across.
503  @param BODY The operation to perform, typically a code block. See
504  the example below.
505 
506  This macro will call @c BODY with each active pool element.
507 
508  It is a bad idea to allocate or free pool element from within
509  @c pool_foreach. Build a vector of indices and dispose of them later.
510  Or call pool_flush.
511 
512 
513  @par Example
514  @code{.c}
515  proc_t *procs; // a pool of processes.
516  proc_t *proc; // pointer to one process; used as the iterator.
517 
518  pool_foreach (proc, procs, ({
519  if (proc->state != PROC_STATE_RUNNING)
520  continue;
521 
522  // check a running proc in some way
523  ...
524  }));
525  @endcode
526 
527  @warning Because @c pool_foreach is a macro, syntax errors can be
528  difficult to find inside @c BODY, let alone actual code bugs. One
529  can temporarily split a complex @c pool_foreach into a trivial
530  @c pool_foreach which builds a vector of active indices, and a
531  vec_foreach() (or plain for-loop) to walk the active index vector.
532  */
533 
534 #define pool_foreach(VAR,POOL) \
535  if (POOL) \
536  for (VAR = POOL + pool_get_first_index (POOL); \
537  VAR < vec_end (POOL); \
538  VAR = POOL + pool_get_next_index (POOL, VAR - POOL))
539 
540 /** Returns pointer to element at given index.
541 
542  ASSERTs that the supplied index is valid.
543  Even though one can write correct code of the form
544  @code
545  p = pool_base + index;
546  @endcode
547  use of @c pool_elt_at_index is strongly suggested.
548  */
549 #define pool_elt_at_index(p,i) \
550 ({ \
551  typeof (p) _e = (p) + (i); \
552  ASSERT (! pool_is_free (p, _e)); \
553  _e; \
554 })
555 
556 /** Return next occupied pool index after @c i, useful for safe iteration. */
557 #define pool_next_index(P,I) \
558 ({ \
559  pool_header_t * _pool_var (p) = pool_header (P); \
560  uword _pool_var (rv) = (I) + 1; \
561  \
562  _pool_var(rv) = \
563  (_pool_var (rv) < vec_len (P) ? \
564  clib_bitmap_next_clear (_pool_var (p)->free_bitmap, _pool_var(rv)) \
565  : ~0); \
566  _pool_var(rv) = \
567  (_pool_var (rv) < vec_len (P) ? \
568  _pool_var (rv) : ~0); \
569  _pool_var(rv); \
570 })
571 
572 #define pool_foreach_index(i,v) \
573  if (v) \
574  for (i = pool_get_first_index (v); \
575  i < vec_len (v); \
576  i = pool_get_next_index (v, i)) \
577 
578 /**
579  * @brief Remove all elements from a pool in a safe way
580  *
581  * @param VAR each element in the pool
582  * @param POOL The pool to flush
583  * @param BODY The actions to perform on each element before it is returned to
584  * the pool. i.e. before it is 'freed'
585  */
586 #define pool_flush(VAR, POOL, BODY) \
587 { \
588  uword *_pool_var(ii), *_pool_var(dv) = NULL; \
589  \
590  pool_foreach((VAR), (POOL)) \
591  { \
592  vec_add1(_pool_var(dv), (VAR) - (POOL)); \
593  } \
594  vec_foreach(_pool_var(ii), _pool_var(dv)) \
595  { \
596  (VAR) = pool_elt_at_index((POOL), *_pool_var(ii)); \
597  do { BODY; } while (0); \
598  pool_put((POOL), (VAR)); \
599  } \
600  vec_free(_pool_var(dv)); \
601 }
602 
603 #endif /* included_pool_h */
604 
605 /*
606  * fd.io coding-style-patch-verification: ON
607  *
608  * Local Variables:
609  * eval: (c-set-style "gnu")
610  * End:
611  */
pool_header_t::free_bitmap
uword * free_bitmap
Bitmap of indices of free objects.
Definition: pool.h:54
bitmap.h
fpool_free
void fpool_free(void *)
vec_aligned_header
static void * vec_aligned_header(void *v, uword header_bytes, uword align)
Definition: vec_bootstrap.h:116
vec_capacity
#define vec_capacity(v, b)
Total number of bytes that can fit in vector with current allocation.
Definition: vec_bootstrap.h:165
pool_header_t::mmap_base
u8 * mmap_base
mmap segment info: base + length
Definition: pool.h:65
clib_bitmap_first_clear
static uword clib_bitmap_first_clear(uword *ai)
Return the lowest numbered clear bit in a bitmap.
Definition: bitmap.h:432
h
h
Definition: flowhash_template.h:372
clib_unix_warning
#define clib_unix_warning(format, args...)
Definition: error.h:68
pool_validate
static void pool_validate(void *v)
Validate a pool.
Definition: pool.h:92
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
clib_bitmap_get
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
error.h
clib_bitmap_count_set_bits
static uword clib_bitmap_count_set_bits(uword *ai)
Return the number of set bits in a bitmap.
Definition: bitmap.h:449
pool_header_t::mmap_size
u64 mmap_size
Definition: pool.h:66
BITS
#define BITS(x)
Definition: clib.h:69
static_always_inline
#define static_always_inline
Definition: clib.h:112
clib_bitmap_free
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
uword
u64 uword
Definition: types.h:112
last
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
pool_header_validate_index
static void pool_header_validate_index(void *v, uword index)
Definition: pool.h:107
vec_validate
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment)
Definition: vec.h:523
pool_free_elts
static uword pool_free_elts(void *v)
Queries whether pool has at least N_FREE free elements.
Definition: pool.h:167
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
index
u32 index
Definition: flow_types.api:221
always_inline
#define always_inline
Definition: rdma_mlx5dv.h:23
pool_get_first_index
static_always_inline uword pool_get_first_index(void *pool)
Definition: pool.h:433
u64
unsigned long u64
Definition: types.h:89
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
n_free
u32 n_free
Definition: interface_output.c:1096
u32
unsigned int u32
Definition: types.h:88
pool_aligned_header_bytes
#define pool_aligned_header_bytes
Align pool header so that pointers are naturally aligned.
Definition: pool.h:71
pool_elts
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127
pool_header_t
Definition: pool.h:51
pool_header
static pool_header_t * pool_header(void *v)
Get pool header from user pool pointer.
Definition: pool.h:76
u8
unsigned char u8
Definition: types.h:56
pool_get_next_index
static_always_inline uword pool_get_next_index(void *pool, uword last)
Definition: pool.h:440
vec_free_h
#define vec_free_h(V, H)
Free vector's memory (general version)
Definition: vec.h:382
pool_header_bytes
static uword pool_header_bytes(void *v)
Memory usage of pool header.
Definition: pool.h:149
i
int i
Definition: flowhash_template.h:376
rv
int __clib_unused rv
Definition: application.c:491
pool_header_t::max_elts
u32 max_elts
Maximum size of the pool, in elements.
Definition: pool.h:62
pool_header_t::free_indices
u32 * free_indices
Vector of free indices.
Definition: pool.h:57
vec_bytes
#define vec_bytes(v)
Number of data bytes in vector.
Definition: vec_bootstrap.h:161