blob: 45265b31cbcb3132a5daad6eae761b699f15b122 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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*/
Chris Luke8e5b0412016-07-26 13:06:10 -040037/** @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 */
Ed Warnickecb9cada2015-12-08 15:45:58 -070043
44#ifndef included_pool_h
45#define included_pool_h
46
47#include <vppinfra/bitmap.h>
48#include <vppinfra/error.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070049
Ed Warnickecb9cada2015-12-08 15:45:58 -070050
Dave Barachc3799992016-08-15 11:12:27 -040051typedef struct
52{
Chris Luke8e5b0412016-07-26 13:06:10 -040053 /** Bitmap of indices of free objects. */
Dave Barachc3799992016-08-15 11:12:27 -040054 uword *free_bitmap;
Ed Warnickecb9cada2015-12-08 15:45:58 -070055
Chris Luke8e5b0412016-07-26 13:06:10 -040056 /** Vector of free indices. One element for each set bit in bitmap. */
Dave Barachc3799992016-08-15 11:12:27 -040057 u32 *free_indices;
Dave Barachb7f1faa2017-08-29 11:43:37 -040058
59 /* The following fields are set for fixed-size, preallocated pools */
60
61 /** Maximum size of the pool, in elements */
62 u32 max_elts;
63
Ed Warnickecb9cada2015-12-08 15:45:58 -070064} pool_header_t;
65
Chris Luke8e5b0412016-07-26 13:06:10 -040066/** Align pool header so that pointers are naturally aligned. */
Damjan Marioneb63cae2022-02-25 00:19:26 +010067#define pool_aligned_header_bytes \
68 round_pow2 (sizeof (pool_header_t), sizeof (void *))
Ed Warnickecb9cada2015-12-08 15:45:58 -070069
Chris Luke8e5b0412016-07-26 13:06:10 -040070/** Get pool header from user pool pointer */
Dave Barachc3799992016-08-15 11:12:27 -040071always_inline pool_header_t *
72pool_header (void *v)
73{
Damjan Mariona4a28f02022-03-17 15:46:25 +010074 return vec_header (v);
Dave Barachc3799992016-08-15 11:12:27 -040075}
Ed Warnickecb9cada2015-12-08 15:45:58 -070076
Dave Barachb7f1faa2017-08-29 11:43:37 -040077extern void _pool_init_fixed (void **, u32, u32);
78extern void fpool_free (void *);
79
80/** initialize a fixed-size, preallocated pool */
81#define pool_init_fixed(pool,max_elts) \
82{ \
83 _pool_init_fixed((void **)&(pool),sizeof(pool[0]),max_elts); \
84}
85
Chris Luke8e5b0412016-07-26 13:06:10 -040086/** Validate a pool */
Dave Barachc3799992016-08-15 11:12:27 -040087always_inline void
88pool_validate (void *v)
Ed Warnickecb9cada2015-12-08 15:45:58 -070089{
Dave Barachc3799992016-08-15 11:12:27 -040090 pool_header_t *p = pool_header (v);
Ed Warnickecb9cada2015-12-08 15:45:58 -070091 uword i, n_free_bitmap;
92
Dave Barachc3799992016-08-15 11:12:27 -040093 if (!v)
Ed Warnickecb9cada2015-12-08 15:45:58 -070094 return;
95
96 n_free_bitmap = clib_bitmap_count_set_bits (p->free_bitmap);
97 ASSERT (n_free_bitmap == vec_len (p->free_indices));
98 for (i = 0; i < vec_len (p->free_indices); i++)
99 ASSERT (clib_bitmap_get (p->free_bitmap, p->free_indices[i]) == 1);
100}
101
Dave Barachc3799992016-08-15 11:12:27 -0400102always_inline void
103pool_header_validate_index (void *v, uword index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700104{
Dave Barachc3799992016-08-15 11:12:27 -0400105 pool_header_t *p = pool_header (v);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700106
107 if (v)
108 vec_validate (p->free_bitmap, index / BITS (uword));
109}
110
111#define pool_validate_index(v,i) \
112do { \
113 uword __pool_validate_index = (i); \
114 vec_validate_ha ((v), __pool_validate_index, \
Dave Barachb7f1faa2017-08-29 11:43:37 -0400115 pool_aligned_header_bytes, /* align */ 0); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700116 pool_header_validate_index ((v), __pool_validate_index); \
117} while (0)
118
Chris Luke8e5b0412016-07-26 13:06:10 -0400119/** Number of active elements in a pool.
120 * @return Number of active elements in a pool
121 */
Dave Barachc3799992016-08-15 11:12:27 -0400122always_inline uword
123pool_elts (void *v)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700124{
125 uword ret = vec_len (v);
126 if (v)
127 ret -= vec_len (pool_header (v)->free_indices);
128 return ret;
129}
130
Chris Luke8e5b0412016-07-26 13:06:10 -0400131/** Number of elements in pool vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700132
Chris Luke8e5b0412016-07-26 13:06:10 -0400133 @note You probably want to call pool_elts() instead.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700134*/
135#define pool_len(p) vec_len(p)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700136
Chris Luke8e5b0412016-07-26 13:06:10 -0400137/** Number of elements in pool vector (usable as an lvalue)
138
139 @note You probably don't want to use this macro.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700140*/
141#define _pool_len(p) _vec_len(p)
142
Chris Luke8e5b0412016-07-26 13:06:10 -0400143/** Memory usage of pool header. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700144always_inline uword
Dave Barachc3799992016-08-15 11:12:27 -0400145pool_header_bytes (void *v)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700146{
Dave Barachc3799992016-08-15 11:12:27 -0400147 pool_header_t *p = pool_header (v);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700148
Dave Barachc3799992016-08-15 11:12:27 -0400149 if (!v)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700150 return 0;
151
152 return vec_bytes (p->free_bitmap) + vec_bytes (p->free_indices);
153}
154
Chris Luke8e5b0412016-07-26 13:06:10 -0400155/** Memory usage of pool. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700156#define pool_bytes(P) (vec_bytes (P) + pool_header_bytes (P))
157
Chris Luke8e5b0412016-07-26 13:06:10 -0400158/** Local variable naming macro. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700159#define _pool_var(v) _pool_##v
160
Florin Coras400d4592022-03-09 13:34:12 -0800161/** Number of elements that can fit into pool with current allocation */
Damjan Marion5c45d1c2022-03-17 15:32:56 +0100162#define pool_max_len(P) vec_max_len (P)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700163
Florin Coras400d4592022-03-09 13:34:12 -0800164/** Number of free elements in pool */
165#define pool_free_elts(P) \
166 ({ \
167 pool_header_t *_pool_var (p) = pool_header (P); \
168 uword n_free = 0; \
169 if (P) \
170 { \
171 n_free += vec_len (_pool_var (p)->free_indices); \
172 /* Fixed-size pools have max_elts set non-zero */ \
173 if (_pool_var (p)->max_elts == 0) \
174 n_free += pool_max_len (P) - vec_len (P); \
175 } \
176 n_free; \
177 })
Ed Warnickecb9cada2015-12-08 15:45:58 -0700178
Chris Luke8e5b0412016-07-26 13:06:10 -0400179/** Allocate an object E from a pool P (general version).
Ed Warnickecb9cada2015-12-08 15:45:58 -0700180
Chris Luke8e5b0412016-07-26 13:06:10 -0400181 First search free list. If nothing is free extend vector of objects.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700182*/
Damjan Marion3cfd5292022-03-18 15:48:12 +0100183#define _pool_get_aligned_internal(P, E, A, Z) \
184 do \
185 { \
186 pool_header_t *_pool_var (p) = pool_header (P); \
187 uword _pool_var (l); \
188 \
189 STATIC_ASSERT (A == 0 || ((A % sizeof (P[0])) == 0) || \
190 ((sizeof (P[0]) % A) == 0), \
191 "Pool aligned alloc of incorrectly sized object"); \
192 _pool_var (l) = 0; \
193 if (P) \
194 _pool_var (l) = vec_len (_pool_var (p)->free_indices); \
195 \
196 if (_pool_var (l) > 0) \
197 { \
198 /* Return free element from free list. */ \
199 uword _pool_var (i) = \
200 _pool_var (p)->free_indices[_pool_var (l) - 1]; \
201 (E) = (P) + _pool_var (i); \
202 _pool_var (p)->free_bitmap = clib_bitmap_andnoti_notrim ( \
203 _pool_var (p)->free_bitmap, _pool_var (i)); \
204 _vec_len (_pool_var (p)->free_indices) = _pool_var (l) - 1; \
205 CLIB_MEM_UNPOISON ((E), sizeof ((E)[0])); \
206 } \
207 else \
208 { \
209 /* fixed-size, preallocated pools cannot expand */ \
210 if ((P) && _pool_var (p)->max_elts) \
211 { \
212 clib_warning ("can't expand fixed-size pool"); \
213 os_out_of_memory (); \
214 } \
215 /* Nothing on free list, make a new element and return it. */ \
216 P = _vec_resize (P, /* length_increment */ 1, \
217 /* new size */ (vec_len (P) + 1) * sizeof (P[0]), \
218 pool_aligned_header_bytes, /* align */ (A)); \
219 E = vec_end (P) - 1; \
220 } \
221 if (Z) \
222 memset (E, 0, sizeof (*E)); \
223 } \
224 while (0)
Dave Baracha690fdb2020-01-21 12:34:55 -0500225
Dave Barachbf3443b2018-10-18 15:37:49 -0400226/** Allocate an object E from a pool P with alignment A */
227#define pool_get_aligned(P,E,A) _pool_get_aligned_internal(P,E,A,0)
228
229/** Allocate an object E from a pool P with alignment A and zero it */
230#define pool_get_aligned_zero(P,E,A) _pool_get_aligned_internal(P,E,A,1)
231
Chris Luke8e5b0412016-07-26 13:06:10 -0400232/** Allocate an object E from a pool P (unspecified alignment). */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700233#define pool_get(P,E) pool_get_aligned(P,E,0)
234
Dave Barachbf3443b2018-10-18 15:37:49 -0400235/** Allocate an object E from a pool P and zero it */
236#define pool_get_zero(P,E) pool_get_aligned_zero(P,E,0)
237
Damjan Marion66d4cb52022-03-17 18:59:46 +0100238always_inline int
239_pool_get_will_expand (void *p, uword elt_size)
240{
241 pool_header_t *ph;
242 uword len;
Dave Barach614ac5d2017-02-06 09:28:03 -0500243
Damjan Marion66d4cb52022-03-17 18:59:46 +0100244 if (p == 0)
245 return 1;
Stanislav Zaikin09abed62021-11-04 09:32:32 +0100246
Damjan Marion66d4cb52022-03-17 18:59:46 +0100247 ph = pool_header (p);
248
249 if (ph->max_elts)
250 len = ph->max_elts;
251 else
252 len = vec_len (ph->free_indices);
253
254 /* Free elements, certainly won't expand */
255 if (len > 0)
256 return 0;
257
258 return _vec_resize_will_expand (p, 1, elt_size);
259}
260
261#define pool_get_will_expand(P) _pool_get_will_expand (P, sizeof ((P)[0]))
262
263always_inline int
264_pool_put_will_expand (void *p, uword index, uword elt_size)
265{
266 pool_header_t *ph = pool_header (p);
267
268 if (clib_bitmap_will_expand (ph->free_bitmap, index))
269 return 1;
270
271 if (vec_resize_will_expand (ph->free_indices, 1))
272 return 1;
273
274 return 0;
275}
276
277#define pool_put_will_expand(P, E) _pool_put_will_expand (P, (E) - (P), sizeof ((P)[0])
Dave Barach614ac5d2017-02-06 09:28:03 -0500278
Chris Luke8e5b0412016-07-26 13:06:10 -0400279/** Use free bitmap to query whether given element is free. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700280#define pool_is_free(P,E) \
281({ \
282 pool_header_t * _pool_var (p) = pool_header (P); \
283 uword _pool_var (i) = (E) - (P); \
Florin Corasfcd23682018-06-29 03:22:44 -0700284 (_pool_var (i) < vec_len (P)) ? clib_bitmap_get (_pool_var (p)->free_bitmap, _pool_i) : 1; \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700285})
Dave Barachc3799992016-08-15 11:12:27 -0400286
Chris Luke8e5b0412016-07-26 13:06:10 -0400287/** Use free bitmap to query whether given index is free */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700288#define pool_is_free_index(P,I) pool_is_free((P),(P)+(I))
289
Chris Luke8e5b0412016-07-26 13:06:10 -0400290/** Free an object E in pool P. */
Dave Barach4de5f9b2021-06-02 18:18:18 -0400291#define pool_put(P, E) \
292 do \
293 { \
294 typeof (P) _pool_var (p__) = (P); \
295 typeof (E) _pool_var (e__) = (E); \
296 pool_header_t *_pool_var (p) = pool_header (_pool_var (p__)); \
297 uword _pool_var (l) = _pool_var (e__) - _pool_var (p__); \
298 if (_pool_var (p)->max_elts == 0) \
299 ASSERT (vec_is_member (_pool_var (p__), _pool_var (e__))); \
300 ASSERT (!pool_is_free (_pool_var (p__), _pool_var (e__))); \
301 \
302 /* Add element to free bitmap and to free list. */ \
303 _pool_var (p)->free_bitmap = \
304 clib_bitmap_ori_notrim (_pool_var (p)->free_bitmap, _pool_var (l)); \
305 \
306 /* Preallocated pool? */ \
307 if (_pool_var (p)->max_elts) \
308 { \
309 ASSERT (_pool_var (l) < _pool_var (p)->max_elts); \
310 _pool_var (p) \
311 ->free_indices[_vec_len (_pool_var (p)->free_indices)] = \
312 _pool_var (l); \
313 _vec_len (_pool_var (p)->free_indices) += 1; \
314 } \
315 else \
316 vec_add1 (_pool_var (p)->free_indices, _pool_var (l)); \
317 \
318 CLIB_MEM_POISON (_pool_var (e__), sizeof (_pool_var (e__)[0])); \
319 } \
320 while (0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700321
Chris Luke8e5b0412016-07-26 13:06:10 -0400322/** Free pool element with given index. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700323#define pool_put_index(p,i) \
324do { \
325 typeof (p) _e = (p) + (i); \
326 pool_put (p, _e); \
327} while (0)
328
Chris Luke8e5b0412016-07-26 13:06:10 -0400329/** Allocate N more free elements to pool (general version). */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700330#define pool_alloc_aligned(P,N,A) \
331do { \
332 pool_header_t * _p; \
Dave Barachb7f1faa2017-08-29 11:43:37 -0400333 \
334 if ((P)) \
335 { \
336 _p = pool_header (P); \
337 if (_p->max_elts) \
338 { \
339 clib_warning ("Can't expand fixed-size pool"); \
340 os_out_of_memory(); \
341 } \
342 } \
343 \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700344 (P) = _vec_resize ((P), 0, (vec_len (P) + (N)) * sizeof (P[0]), \
345 pool_aligned_header_bytes, \
346 (A)); \
347 _p = pool_header (P); \
348 vec_resize (_p->free_indices, (N)); \
349 _vec_len (_p->free_indices) -= (N); \
350} while (0)
351
Chris Luke8e5b0412016-07-26 13:06:10 -0400352/** Allocate N more free elements to pool (unspecified alignment). */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700353#define pool_alloc(P,N) pool_alloc_aligned(P,N,0)
354
Florin Coras8be6c402018-11-27 17:11:37 -0800355/**
356 * Return copy of pool with alignment
357 *
358 * @param P pool to copy
359 * @param A alignment (may be zero)
360 * @return copy of pool
361 */
Benoît Ganne563ec992021-11-19 13:39:10 +0100362#define pool_dup_aligned(P, A) \
363 ({ \
364 typeof (P) _pool_var (new) = 0; \
365 pool_header_t *_pool_var (ph), *_pool_var (new_ph); \
366 u32 _pool_var (n) = pool_len (P); \
367 if ((P)) \
368 { \
369 _pool_var (new) = _vec_resize (_pool_var (new), _pool_var (n), \
370 _pool_var (n) * sizeof ((P)[0]), \
371 pool_aligned_header_bytes, (A)); \
372 CLIB_MEM_OVERFLOW_PUSH ((P), _pool_var (n) * sizeof ((P)[0])); \
373 clib_memcpy_fast (_pool_var (new), (P), \
374 _pool_var (n) * sizeof ((P)[0])); \
375 CLIB_MEM_OVERFLOW_POP (); \
376 _pool_var (ph) = pool_header (P); \
377 _pool_var (new_ph) = pool_header (_pool_var (new)); \
378 _pool_var (new_ph)->free_bitmap = \
379 clib_bitmap_dup (_pool_var (ph)->free_bitmap); \
380 _pool_var (new_ph)->free_indices = \
381 vec_dup (_pool_var (ph)->free_indices); \
382 _pool_var (new_ph)->max_elts = _pool_var (ph)->max_elts; \
383 } \
384 _pool_var (new); \
385 })
Florin Coras8be6c402018-11-27 17:11:37 -0800386
387/**
388 * Return copy of pool without alignment
389 *
390 * @param P pool to copy
391 * @return copy of pool
392 */
Florin Coras47c40e22018-11-26 17:01:36 -0800393#define pool_dup(P) pool_dup_aligned(P,0)
Florin Coras8be6c402018-11-27 17:11:37 -0800394
Chris Luke8e5b0412016-07-26 13:06:10 -0400395/** Low-level free pool operator (do not call directly). */
Dave Barachc3799992016-08-15 11:12:27 -0400396always_inline void *
397_pool_free (void *v)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700398{
Dave Barachc3799992016-08-15 11:12:27 -0400399 pool_header_t *p = pool_header (v);
400 if (!v)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700401 return v;
402 clib_bitmap_free (p->free_bitmap);
Dave Barachb7f1faa2017-08-29 11:43:37 -0400403
Damjan Marion86bbdf92022-03-18 12:28:35 +0100404 vec_free (p->free_indices);
Damjan Marion05563c92022-03-17 18:29:32 +0100405 vec_free (v);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700406 return 0;
407}
408
Damjan Marion62c25ab2020-12-12 23:32:12 +0100409static_always_inline uword
410pool_get_first_index (void *pool)
411{
412 pool_header_t *h = pool_header (pool);
413 return clib_bitmap_first_clear (h->free_bitmap);
414}
415
416static_always_inline uword
417pool_get_next_index (void *pool, uword last)
418{
419 pool_header_t *h = pool_header (pool);
420 return clib_bitmap_next_clear (h->free_bitmap, last + 1);
421}
422
Chris Luke8e5b0412016-07-26 13:06:10 -0400423/** Free a pool. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700424#define pool_free(p) (p) = _pool_free(p)
425
Chris Luke8e5b0412016-07-26 13:06:10 -0400426/** Optimized iteration through pool.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700427
428 @param LO pointer to first element in chunk
429 @param HI pointer to last element in chunk
430 @param POOL pool to iterate across
431 @param BODY operation to perform
432
Dave Barachc3799992016-08-15 11:12:27 -0400433 Optimized version which assumes that BODY is smart enough to
Ed Warnickecb9cada2015-12-08 15:45:58 -0700434 process multiple (LOW,HI) chunks. See also pool_foreach().
435 */
436#define pool_foreach_region(LO,HI,POOL,BODY) \
437do { \
438 uword _pool_var (i), _pool_var (lo), _pool_var (hi), _pool_var (len); \
439 uword _pool_var (bl), * _pool_var (b); \
440 pool_header_t * _pool_var (p); \
441 \
442 _pool_var (p) = pool_header (POOL); \
443 _pool_var (b) = (POOL) ? _pool_var (p)->free_bitmap : 0; \
444 _pool_var (bl) = vec_len (_pool_var (b)); \
445 _pool_var (len) = vec_len (POOL); \
446 _pool_var (lo) = 0; \
447 \
448 for (_pool_var (i) = 0; \
449 _pool_var (i) <= _pool_var (bl); \
450 _pool_var (i)++) \
451 { \
452 uword _pool_var (m), _pool_var (f); \
453 _pool_var (m) = (_pool_var (i) < _pool_var (bl) \
454 ? _pool_var (b) [_pool_var (i)] \
455 : 1); \
456 while (_pool_var (m) != 0) \
457 { \
458 _pool_var (f) = first_set (_pool_var (m)); \
459 _pool_var (hi) = (_pool_var (i) * BITS (_pool_var (b)[0]) \
460 + min_log2 (_pool_var (f))); \
461 _pool_var (hi) = (_pool_var (i) < _pool_var (bl) \
462 ? _pool_var (hi) : _pool_var (len)); \
463 _pool_var (m) ^= _pool_var (f); \
464 if (_pool_var (hi) > _pool_var (lo)) \
465 { \
466 (LO) = _pool_var (lo); \
467 (HI) = _pool_var (hi); \
468 do { BODY; } while (0); \
469 } \
470 _pool_var (lo) = _pool_var (hi) + 1; \
471 } \
472 } \
473} while (0)
474
Chris Luke8e5b0412016-07-26 13:06:10 -0400475/** Iterate through pool.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700476
Chris Luke8e5b0412016-07-26 13:06:10 -0400477 @param VAR A variable of same type as pool vector to be used as an
478 iterator.
479 @param POOL The pool to iterate across.
480 @param BODY The operation to perform, typically a code block. See
481 the example below.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700482
Chris Luke8e5b0412016-07-26 13:06:10 -0400483 This macro will call @c BODY with each active pool element.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700484
485 It is a bad idea to allocate or free pool element from within
Chris Luke8e5b0412016-07-26 13:06:10 -0400486 @c pool_foreach. Build a vector of indices and dispose of them later.
Neale Ranns87df12d2017-02-18 08:16:41 -0800487 Or call pool_flush.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700488
Chris Luke8e5b0412016-07-26 13:06:10 -0400489
490 @par Example
491 @code{.c}
492 proc_t *procs; // a pool of processes.
493 proc_t *proc; // pointer to one process; used as the iterator.
494
495 pool_foreach (proc, procs, ({
496 if (proc->state != PROC_STATE_RUNNING)
497 continue;
498
499 // check a running proc in some way
500 ...
501 }));
502 @endcode
503
504 @warning Because @c pool_foreach is a macro, syntax errors can be
505 difficult to find inside @c BODY, let alone actual code bugs. One
506 can temporarily split a complex @c pool_foreach into a trivial
507 @c pool_foreach which builds a vector of active indices, and a
508 vec_foreach() (or plain for-loop) to walk the active index vector.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700509 */
Damjan Marion62c25ab2020-12-12 23:32:12 +0100510
Damjan Marionb2c31b62020-12-13 21:47:40 +0100511#define pool_foreach(VAR,POOL) \
Damjan Marion62c25ab2020-12-12 23:32:12 +0100512 if (POOL) \
513 for (VAR = POOL + pool_get_first_index (POOL); \
514 VAR < vec_end (POOL); \
515 VAR = POOL + pool_get_next_index (POOL, VAR - POOL))
516
Chris Luke8e5b0412016-07-26 13:06:10 -0400517/** Returns pointer to element at given index.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700518
Chris Luke8e5b0412016-07-26 13:06:10 -0400519 ASSERTs that the supplied index is valid.
520 Even though one can write correct code of the form
521 @code
522 p = pool_base + index;
523 @endcode
Dave Barachc3799992016-08-15 11:12:27 -0400524 use of @c pool_elt_at_index is strongly suggested.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700525 */
526#define pool_elt_at_index(p,i) \
527({ \
528 typeof (p) _e = (p) + (i); \
529 ASSERT (! pool_is_free (p, _e)); \
530 _e; \
531})
532
Chris Luke8e5b0412016-07-26 13:06:10 -0400533/** Return next occupied pool index after @c i, useful for safe iteration. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700534#define pool_next_index(P,I) \
535({ \
536 pool_header_t * _pool_var (p) = pool_header (P); \
537 uword _pool_var (rv) = (I) + 1; \
538 \
539 _pool_var(rv) = \
540 (_pool_var (rv) < vec_len (P) ? \
541 clib_bitmap_next_clear (_pool_var (p)->free_bitmap, _pool_var(rv)) \
542 : ~0); \
John Lo7f358b32018-04-28 01:19:24 -0400543 _pool_var(rv) = \
544 (_pool_var (rv) < vec_len (P) ? \
545 _pool_var (rv) : ~0); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700546 _pool_var(rv); \
547})
548
Damjan Marionb2c31b62020-12-13 21:47:40 +0100549#define pool_foreach_index(i,v) \
Damjan Marion62c25ab2020-12-12 23:32:12 +0100550 if (v) \
551 for (i = pool_get_first_index (v); \
552 i < vec_len (v); \
553 i = pool_get_next_index (v, i)) \
554
Neale Ranns87df12d2017-02-18 08:16:41 -0800555/**
Paul Vinciguerraec11b132018-09-24 05:25:00 -0700556 * @brief Remove all elements from a pool in a safe way
Neale Ranns87df12d2017-02-18 08:16:41 -0800557 *
558 * @param VAR each element in the pool
559 * @param POOL The pool to flush
560 * @param BODY The actions to perform on each element before it is returned to
561 * the pool. i.e. before it is 'freed'
562 */
563#define pool_flush(VAR, POOL, BODY) \
564{ \
565 uword *_pool_var(ii), *_pool_var(dv) = NULL; \
566 \
Damjan Marionb2c31b62020-12-13 21:47:40 +0100567 pool_foreach((VAR), (POOL)) \
568 { \
Neale Ranns87df12d2017-02-18 08:16:41 -0800569 vec_add1(_pool_var(dv), (VAR) - (POOL)); \
Damjan Marionb2c31b62020-12-13 21:47:40 +0100570 } \
Neale Ranns87df12d2017-02-18 08:16:41 -0800571 vec_foreach(_pool_var(ii), _pool_var(dv)) \
572 { \
573 (VAR) = pool_elt_at_index((POOL), *_pool_var(ii)); \
574 do { BODY; } while (0); \
575 pool_put((POOL), (VAR)); \
576 } \
577 vec_free(_pool_var(dv)); \
578}
579
Ed Warnickecb9cada2015-12-08 15:45:58 -0700580#endif /* included_pool_h */
Dave Barachc3799992016-08-15 11:12:27 -0400581
582/*
583 * fd.io coding-style-patch-verification: ON
584 *
585 * Local Variables:
586 * eval: (c-set-style "gnu")
587 * End:
588 */