blob: 5c56068da77aeb5eddfd311e70b28d35a16e89d7 [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, 2005 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
38#ifndef included_clib_bitmap_h
39#define included_clib_bitmap_h
40
Dave Barach310f7fe2016-08-05 14:36:27 -040041/** \file
42 Bitmaps built as vectors of machine words
Dave Barachc3799992016-08-15 11:12:27 -040043*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070044
45#include <vppinfra/vec.h>
46#include <vppinfra/random.h>
47#include <vppinfra/error.h>
48#include <vppinfra/bitops.h> /* for count_set_bits */
49
Damjan Marion0b140722016-06-14 00:36:09 +020050typedef uword clib_bitmap_t;
51
Dave Barach310f7fe2016-08-05 14:36:27 -040052/** predicate function; is an entire bitmap empty?
53 @param ai - pointer to a bitmap
54 @returns 1 if the entire bitmap is zero, 0 otherwise
55*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070056always_inline uword
57clib_bitmap_is_zero (uword * ai)
58{
59 uword i;
60 for (i = 0; i < vec_len (ai); i++)
61 if (ai[i] != 0)
62 return 0;
63 return 1;
64}
65
Dave Barach310f7fe2016-08-05 14:36:27 -040066/** predicate function; are two bitmaps equal?
67 @param a - pointer to a bitmap
68 @param b - pointer to a bitmap
69 @returns 1 if the bitmaps are equal, 0 otherwise
70*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070071always_inline uword
72clib_bitmap_is_equal (uword * a, uword * b)
73{
74 uword i;
75 if (vec_len (a) != vec_len (b))
76 return 0;
77 for (i = 0; i < vec_len (a); i++)
78 if (a[i] != b[i])
79 return 0;
80 return 1;
81}
82
Dave Barach310f7fe2016-08-05 14:36:27 -040083/** Duplicate a bitmap
Chris Luked4024f52016-09-06 09:32:36 -040084 @param v - pointer to a bitmap
Dave Barach310f7fe2016-08-05 14:36:27 -040085 @returns a duplicate of the bitmap
86*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070087#define clib_bitmap_dup(v) vec_dup(v)
88
Dave Barach310f7fe2016-08-05 14:36:27 -040089/** Free a bitmap
90 @param v - pointer to the bitmap to free
91*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070092#define clib_bitmap_free(v) vec_free(v)
93
Dave Barach310f7fe2016-08-05 14:36:27 -040094/** Number of bytes in a bitmap
95 @param v - pointer to the bitmap
96*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070097#define clib_bitmap_bytes(v) vec_bytes(v)
98
Dave Barach310f7fe2016-08-05 14:36:27 -040099/** Clear a bitmap
100 @param v - pointer to the bitmap to clear
101*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700102#define clib_bitmap_zero(v) vec_zero(v)
103
Dave Barach310f7fe2016-08-05 14:36:27 -0400104/** Allocate a bitmap with the supplied number of bits
105 @param [out] v - the resulting bitmap
106 @param n_bits - the required number of bits
107*/
108
Ed Warnickecb9cada2015-12-08 15:45:58 -0700109#define clib_bitmap_alloc(v,n_bits) \
110 v = vec_new (uword, ((n_bits) + BITS (uword) - 1) / BITS (uword))
111
112#define clib_bitmap_vec_validate(v,i) vec_validate_aligned((v),(i),sizeof(uword))
113
114/* Make sure that a bitmap is at least n_bits in size */
115#define clib_bitmap_validate(v,n_bits) \
116 clib_bitmap_vec_validate ((v), ((n_bits) - 1) / BITS (uword))
117
118/* low-level routine to remove trailing zeros from a bitmap */
119always_inline uword *
120_clib_bitmap_remove_trailing_zeros (uword * a)
121{
122 word i;
123 if (a)
124 {
125 for (i = _vec_len (a) - 1; i >= 0; i--)
126 if (a[i] != 0)
127 break;
128 _vec_len (a) = i + 1;
129 }
130 return a;
131}
132
Dave Barach310f7fe2016-08-05 14:36:27 -0400133/** Sets the ith bit of a bitmap to new_value.
Dave Barachc3799992016-08-15 11:12:27 -0400134 No sanity checking. Be careful.
Dave Barach310f7fe2016-08-05 14:36:27 -0400135 @param a - pointer to the bitmap
136 @param i - the bit position to interrogate
137 @param new_value - new value for the bit
138 @returns the old value of the bit
139*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700140always_inline uword
141clib_bitmap_set_no_check (uword * a, uword i, uword new_value)
142{
143 uword i0 = i / BITS (a[0]);
144 uword i1 = i % BITS (a[0]);
145 uword bit = (uword) 1 << i1;
146 uword ai, old_value;
147
148 /* Removed ASSERT since uword * a may not be a vector. */
149 /* ASSERT (i0 < vec_len (a)); */
150
151 ai = a[i0];
152 old_value = (ai & bit) != 0;
Dave Barachc3799992016-08-15 11:12:27 -0400153 ai &= ~bit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700154 ai |= ((uword) (new_value != 0)) << i1;
155 a[i0] = ai;
156 return old_value;
157}
158
Dave Barach310f7fe2016-08-05 14:36:27 -0400159/** Sets the ith bit of a bitmap to new_value
160 Removes trailing zeros from the bitmap
Chris Luked4024f52016-09-06 09:32:36 -0400161 @param ai - pointer to the bitmap
Dave Barach310f7fe2016-08-05 14:36:27 -0400162 @param i - the bit position to interrogate
Chris Luked4024f52016-09-06 09:32:36 -0400163 @param value - new value for the bit
Dave Barach310f7fe2016-08-05 14:36:27 -0400164 @returns the old value of the bit
165*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700166always_inline uword *
167clib_bitmap_set (uword * ai, uword i, uword value)
168{
169 uword i0 = i / BITS (ai[0]);
170 uword i1 = i % BITS (ai[0]);
171 uword a;
172
173 /* Check for writing a zero to beyond end of bitmap. */
174 if (value == 0 && i0 >= vec_len (ai))
175 return ai; /* Implied trailing zeros. */
176
177 clib_bitmap_vec_validate (ai, i0);
178
179 a = ai[i0];
180 a &= ~((uword) 1 << i1);
181 a |= ((uword) (value != 0)) << i1;
182 ai[i0] = a;
183
184 /* If bits have been cleared, test for zero. */
185 if (a == 0)
186 ai = _clib_bitmap_remove_trailing_zeros (ai);
187
188 return ai;
189}
190
Dave Barach310f7fe2016-08-05 14:36:27 -0400191/** Gets the ith bit value from a bitmap
192 @param ai - pointer to the bitmap
193 @param i - the bit position to interrogate
194 @returns the indicated bit value
195*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196always_inline uword
197clib_bitmap_get (uword * ai, uword i)
198{
199 uword i0 = i / BITS (ai[0]);
200 uword i1 = i % BITS (ai[0]);
201 return i0 < vec_len (ai) && 0 != ((ai[i0] >> i1) & 1);
202}
203
Dave Barach310f7fe2016-08-05 14:36:27 -0400204/** Gets the ith bit value from a bitmap
205 Does not sanity-check the bit position. Be careful.
206 @param ai - pointer to the bitmap
207 @param i - the bit position to interrogate
208 @returns the indicated bit value, or garbage if the bit position is
209 out of range.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700210*/
211always_inline uword
212clib_bitmap_get_no_check (uword * ai, uword i)
213{
214 uword i0 = i / BITS (ai[0]);
215 uword i1 = i % BITS (ai[0]);
216 return 0 != ((ai[i0] >> i1) & 1);
217}
218
Ed Warnickecb9cada2015-12-08 15:45:58 -0700219always_inline uword
220clib_bitmap_get_multiple_no_check (uword * ai, uword i, uword n_bits)
221{
222 uword i0 = i / BITS (ai[0]);
223 uword i1 = i % BITS (ai[0]);
224 ASSERT (i1 + n_bits <= BITS (uword));
225 return 0 != ((ai[i0] >> i1) & pow2_mask (n_bits));
226}
227
Dave Barach310f7fe2016-08-05 14:36:27 -0400228/** Gets the ith through ith + n_bits bit values from a bitmap
229 @param bitmap - pointer to the bitmap
230 @param i - the first bit position to retrieve
231 @param n_bits - the number of bit positions to retrieve
232 @returns the indicated range of bits
233*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700234always_inline uword
235clib_bitmap_get_multiple (uword * bitmap, uword i, uword n_bits)
236{
237 uword i0, i1, result;
238 uword l = vec_len (bitmap);
239
Dave Barachf9c231e2016-08-05 10:10:18 -0400240 ASSERT (n_bits <= BITS (result));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241
242 i0 = i / BITS (bitmap[0]);
243 i1 = i % BITS (bitmap[0]);
244
245 /* Check first word. */
246 result = 0;
247 if (i0 < l)
248 {
249 result |= (bitmap[i0] >> i1);
250 if (n_bits < BITS (bitmap[0]))
251 result &= (((uword) 1 << n_bits) - 1);
252 }
253
254 /* Check for overlap into next word. */
255 i0++;
256 if (i1 + n_bits > BITS (bitmap[0]) && i0 < l)
257 {
258 n_bits -= BITS (bitmap[0]) - i1;
Dave Barachc3799992016-08-15 11:12:27 -0400259 result |=
260 (bitmap[i0] & (((uword) 1 << n_bits) - 1)) << (BITS (bitmap[0]) - i1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700261 }
262
263 return result;
264}
265
Dave Barach310f7fe2016-08-05 14:36:27 -0400266/** sets the ith through ith + n_bits bits in a bitmap
267 @param bitmap - pointer to the bitmap
268 @param i - the first bit position to retrieve
269 @param value - the values to set
270 @param n_bits - the number of bit positions to set
271 @returns a pointer to the updated bitmap, which may expand and move
272*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700273
Ed Warnickecb9cada2015-12-08 15:45:58 -0700274always_inline uword *
275clib_bitmap_set_multiple (uword * bitmap, uword i, uword value, uword n_bits)
276{
277 uword i0, i1, l, t, m;
278
Dave Barachf9c231e2016-08-05 10:10:18 -0400279 ASSERT (n_bits <= BITS (value));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700280
281 i0 = i / BITS (bitmap[0]);
282 i1 = i % BITS (bitmap[0]);
283
284 /* Allocate bitmap. */
285 clib_bitmap_vec_validate (bitmap, (i + n_bits) / BITS (bitmap[0]));
286 l = vec_len (bitmap);
287
288 m = ~0;
289 if (n_bits < BITS (value))
290 m = (((uword) 1 << n_bits) - 1);
291 value &= m;
292
293 /* Insert into first word. */
294 t = bitmap[i0];
295 t &= ~(m << i1);
296 t |= value << i1;
297 bitmap[i0] = t;
298
299 /* Insert into second word. */
300 i0++;
301 if (i1 + n_bits > BITS (bitmap[0]) && i0 < l)
302 {
303 t = BITS (bitmap[0]) - i1;
304 value >>= t;
305 n_bits -= t;
306 t = bitmap[i0];
307 m = ((uword) 1 << n_bits) - 1;
308 t &= ~m;
309 t |= value;
310 bitmap[i0] = t;
311 }
312
313 return bitmap;
314}
315
Ed Warnickecb9cada2015-12-08 15:45:58 -0700316always_inline uword *
Korian Edeline40e6bdf2018-08-08 11:30:30 +0200317clib_bitmap_set_region (uword * bitmap, uword i, uword value, uword n_bits)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700318{
319 uword a0, a1, b0;
320 uword i_end, mask;
321
322 a0 = i / BITS (bitmap[0]);
323 a1 = i % BITS (bitmap[0]);
324
325 i_end = i + n_bits;
326 b0 = i_end / BITS (bitmap[0]);
327
328 clib_bitmap_vec_validate (bitmap, b0);
329
330 /* First word. */
331 mask = n_bits < BITS (bitmap[0]) ? pow2_mask (n_bits) : ~0;
332 mask <<= a1;
333
334 if (value)
335 bitmap[a0] |= mask;
336 else
337 bitmap[a0] &= ~mask;
338
339 for (a0++; a0 < b0; a0++)
340 bitmap[a0] = value ? ~0 : 0;
341
342 if (a0 == b0)
343 {
344 word n_bits_left = n_bits - (BITS (bitmap[0]) - a1);
345 mask = pow2_mask (n_bits_left);
346 if (value)
347 bitmap[a0] |= mask;
348 else
349 bitmap[a0] &= ~mask;
350 }
351
352 return bitmap;
353}
354
Dave Barach310f7fe2016-08-05 14:36:27 -0400355/** Macro to iterate across set bits in a bitmap
356
357 @param i - the current set bit
358 @param ai - the bitmap
359 @param body - the expression to evaluate for each set bit
360*/
Damjan Marionf0ca1e82020-12-13 23:26:56 +0100361#define clib_bitmap_foreach(i,ai) \
362 if (ai) \
363 for (i = clib_bitmap_first_set (ai); \
364 i != ~0; \
365 i = clib_bitmap_next_set (ai, i + 1))
366
367#define clib_bitmap_foreach_old(i,ai,body) \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700368do { \
369 uword __bitmap_i, __bitmap_ai, __bitmap_len, __bitmap_first_set; \
370 __bitmap_len = vec_len ((ai)); \
371 for (__bitmap_i = 0; __bitmap_i < __bitmap_len; __bitmap_i++) \
372 { \
373 __bitmap_ai = (ai)[__bitmap_i]; \
374 while (__bitmap_ai != 0) \
375 { \
376 __bitmap_first_set = first_set (__bitmap_ai); \
377 (i) = (__bitmap_i * BITS ((ai)[0]) \
378 + min_log2 (__bitmap_first_set)); \
379 do { body; } while (0); \
380 __bitmap_ai ^= __bitmap_first_set; \
381 } \
382 } \
383} while (0)
384
Ed Warnickecb9cada2015-12-08 15:45:58 -0700385
Dave Barach310f7fe2016-08-05 14:36:27 -0400386/** Return the lowest numbered set bit in a bitmap
387 @param ai - pointer to the bitmap
388 @returns lowest numbered set bit, or ~0 if the entire bitmap is zero
389*/
Dave Barachc3799992016-08-15 11:12:27 -0400390always_inline uword
391clib_bitmap_first_set (uword * ai)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700392{
Damjan Marion32ab9542018-06-26 01:29:55 +0200393 uword i = 0;
394#if uword_bits == 64
Damjan Marion13c98a22018-06-26 16:05:43 +0200395#if defined(CLIB_HAVE_VEC256)
Damjan Marion32ab9542018-06-26 01:29:55 +0200396 while (i + 7 < vec_len (ai))
397 {
398 u64x4 v;
399 v = u64x4_load_unaligned (ai + i) | u64x4_load_unaligned (ai + i + 4);
400 if (!u64x4_is_all_zero (v))
401 break;
402 i += 8;
403 }
Damjan Marion13c98a22018-06-26 16:05:43 +0200404#elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE)
Damjan Marion32ab9542018-06-26 01:29:55 +0200405 while (i + 3 < vec_len (ai))
406 {
407 u64x2 v;
408 v = u64x2_load_unaligned (ai + i) | u64x2_load_unaligned (ai + i + 2);
409 if (!u64x2_is_all_zero (v))
410 break;
411 i += 4;
412 }
413#endif
414#endif
415 for (; i < vec_len (ai); i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700416 {
417 uword x = ai[i];
418 if (x != 0)
419 return i * BITS (ai[0]) + log2_first_set (x);
420 }
421 return ~0;
422}
423
Dave Barach310f7fe2016-08-05 14:36:27 -0400424/** Return the higest numbered set bit in a bitmap
425 @param ai - pointer to the bitmap
426 @returns lowest numbered set bit, or ~0 if the entire bitmap is zero
427*/
Dave Barachc3799992016-08-15 11:12:27 -0400428always_inline uword
429clib_bitmap_last_set (uword * ai)
Damjan Marion0247b462016-06-08 01:37:11 +0200430{
431 uword i;
432
Dave Barachc3799992016-08-15 11:12:27 -0400433 for (i = vec_len (ai); i > 0; i--)
Damjan Marion0247b462016-06-08 01:37:11 +0200434 {
Damjan Marionec175102016-06-30 01:02:17 +0200435 uword x = ai[i - 1];
Damjan Marion0247b462016-06-08 01:37:11 +0200436 if (x != 0)
437 {
438 uword first_bit;
Damjan Marion11056002018-05-10 13:40:44 +0200439 first_bit = count_leading_zeros (x);
Damjan Marionec175102016-06-30 01:02:17 +0200440 return (i) * BITS (ai[0]) - first_bit - 1;
Damjan Marion0247b462016-06-08 01:37:11 +0200441 }
442 }
443 return ~0;
444}
445
Dave Barach310f7fe2016-08-05 14:36:27 -0400446/** Return the lowest numbered clear bit in a bitmap
447 @param ai - pointer to the bitmap
448 @returns lowest numbered clear bit
449*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700450always_inline uword
451clib_bitmap_first_clear (uword * ai)
452{
453 uword i;
454 for (i = 0; i < vec_len (ai); i++)
455 {
456 uword x = ~ai[i];
457 if (x != 0)
458 return i * BITS (ai[0]) + log2_first_set (x);
459 }
460 return i * BITS (ai[0]);
461}
462
Dave Barach310f7fe2016-08-05 14:36:27 -0400463/** Return the number of set bits in a bitmap
464 @param ai - pointer to the bitmap
465 @returns the number of set bits in the bitmap
466*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700467always_inline uword
468clib_bitmap_count_set_bits (uword * ai)
469{
470 uword i;
471 uword n_set = 0;
472 for (i = 0; i < vec_len (ai); i++)
473 n_set += count_set_bits (ai[i]);
474 return n_set;
475}
476
Dave Barach310f7fe2016-08-05 14:36:27 -0400477/** Logical operator across two bitmaps
478
479 @param ai - pointer to the destination bitmap
480 @param bi - pointer to the source bitmap
481 @returns ai = ai and bi. ai is modified, bi is not modified
482*/
Dave Barachc3799992016-08-15 11:12:27 -0400483always_inline uword *clib_bitmap_and (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400484
485/** Logical operator across two bitmaps
486
487 @param ai - pointer to the destination bitmap
488 @param bi - pointer to the source bitmap
489 @returns ai = ai & ~bi. ai is modified, bi is not modified
490*/
Dave Barachc3799992016-08-15 11:12:27 -0400491always_inline uword *clib_bitmap_andnot (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400492
493/** Logical operator across two bitmaps
494
495 @param ai - pointer to the destination bitmap
496 @param bi - pointer to the source bitmap
497 @returns ai = ai & ~bi. ai is modified, bi is not modified
498*/
Dave Barachc3799992016-08-15 11:12:27 -0400499always_inline uword *clib_bitmap_or (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400500/** Logical operator across two bitmaps
501
502 @param ai - pointer to the destination bitmap
503 @param bi - pointer to the source bitmap
504 @returns ai = ai or bi. ai is modified, bi is not modified
505*/
Dave Barachc3799992016-08-15 11:12:27 -0400506always_inline uword *clib_bitmap_or (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400507
508/** Logical operator across two bitmaps
509
510 @param ai - pointer to the destination bitmap
511 @param bi - pointer to the source bitmap
512 @returns ai = ai xor bi. ai is modified, bi is not modified
513*/
Dave Barachc3799992016-08-15 11:12:27 -0400514always_inline uword *clib_bitmap_xor (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400515
Ed Warnickecb9cada2015-12-08 15:45:58 -0700516/* ALU function definition macro for functions taking two bitmaps. */
517#define _(name, body, check_zero) \
518always_inline uword * \
519clib_bitmap_##name (uword * ai, uword * bi) \
520{ \
521 uword i, a, b, bi_len, n_trailing_zeros; \
522 \
523 n_trailing_zeros = 0; \
524 bi_len = vec_len (bi); \
525 if (bi_len > 0) \
526 clib_bitmap_vec_validate (ai, bi_len - 1); \
527 for (i = 0; i < vec_len (ai); i++) \
528 { \
529 a = ai[i]; \
530 b = i < bi_len ? bi[i] : 0; \
531 do { body; } while (0); \
532 ai[i] = a; \
533 if (check_zero) \
534 n_trailing_zeros = a ? 0 : (n_trailing_zeros + 1); \
535 } \
536 if (check_zero) \
537 _vec_len (ai) -= n_trailing_zeros; \
538 return ai; \
539}
540
541/* ALU functions: */
Florin Corasfcd23682018-06-29 03:22:44 -0700542/* *INDENT-OFF* */
Dave Barachc3799992016-08-15 11:12:27 -0400543_(and, a = a & b, 1)
Florin Corasfcd23682018-06-29 03:22:44 -0700544_(andnot, a = a & ~b, 1)
545_(or, a = a | b, 0)
546_(xor, a = a ^ b, 1)
547/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700548#undef _
Dave Barach310f7fe2016-08-05 14:36:27 -0400549/** Logical operator across two bitmaps which duplicates the first bitmap
550
551 @param ai - pointer to the destination bitmap
552 @param bi - pointer to the source bitmap
553 @returns aiDup = ai and bi. Neither ai nor bi are modified
554*/
Florin Corasfcd23682018-06-29 03:22:44 -0700555always_inline uword *clib_bitmap_dup_and (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400556
557/** Logical operator across two bitmaps which duplicates the first bitmap
558
559 @param ai - pointer to the destination bitmap
560 @param bi - pointer to the source bitmap
561 @returns aiDup = ai & ~bi. Neither ai nor bi are modified
562*/
Florin Corasfcd23682018-06-29 03:22:44 -0700563always_inline uword *clib_bitmap_dup_andnot (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400564
565/** Logical operator across two bitmaps which duplicates the first bitmap
566
567 @param ai - pointer to the destination bitmap
568 @param bi - pointer to the source bitmap
569 @returns aiDup = ai or bi. Neither ai nor bi are modified
570*/
Florin Corasfcd23682018-06-29 03:22:44 -0700571always_inline uword *clib_bitmap_dup_or (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400572
573/** Logical operator across two bitmaps which duplicates the first bitmap
574
575 @param ai - pointer to the destination bitmap
576 @param bi - pointer to the source bitmap
577 @returns aiDup = ai xor bi. Neither ai nor bi are modified
578*/
Florin Corasfcd23682018-06-29 03:22:44 -0700579always_inline uword *clib_bitmap_dup_xor (uword * ai, uword * bi);
Dave Barach310f7fe2016-08-05 14:36:27 -0400580
Ed Warnickecb9cada2015-12-08 15:45:58 -0700581#define _(name) \
582 always_inline uword * \
583 clib_bitmap_dup_##name (uword * ai, uword * bi) \
584{ return clib_bitmap_##name (clib_bitmap_dup (ai), bi); }
585
Florin Corasfcd23682018-06-29 03:22:44 -0700586/* *INDENT-OFF* */
Dave Barachc3799992016-08-15 11:12:27 -0400587_(and);
588_(andnot);
589_(or);
590_(xor);
Florin Corasfcd23682018-06-29 03:22:44 -0700591/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700592#undef _
593
Florin Corasfcd23682018-06-29 03:22:44 -0700594/* ALU function definition macro for functions taking one bitmap and an
595 * immediate. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700596#define _(name, body, check_zero) \
597always_inline uword * \
598clib_bitmap_##name (uword * ai, uword i) \
599{ \
600 uword i0 = i / BITS (ai[0]); \
601 uword i1 = i % BITS (ai[0]); \
602 uword a, b; \
603 clib_bitmap_vec_validate (ai, i0); \
604 a = ai[i0]; \
605 b = (uword) 1 << i1; \
606 do { body; } while (0); \
607 ai[i0] = a; \
608 if (check_zero && a == 0) \
609 ai = _clib_bitmap_remove_trailing_zeros (ai); \
610 return ai; \
611}
612
613/* ALU functions immediate: */
Florin Corasfcd23682018-06-29 03:22:44 -0700614/* *INDENT-OFF* */
Dave Barachc3799992016-08-15 11:12:27 -0400615_(andi, a = a & b, 1)
Florin Corasfcd23682018-06-29 03:22:44 -0700616_(andnoti, a = a & ~b, 1)
617_(ori, a = a | b, 0)
618_(xori, a = a ^ b, 1)
619/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700620#undef _
Florin Corasfcd23682018-06-29 03:22:44 -0700621
622/* ALU function definition macro for functions taking one bitmap and an
623 * immediate. No tail trimming */
624#define _(name, body) \
625always_inline uword * \
626clib_bitmap_##name##_notrim (uword * ai, uword i) \
627{ \
628 uword i0 = i / BITS (ai[0]); \
629 uword i1 = i % BITS (ai[0]); \
630 uword a, b; \
631 clib_bitmap_vec_validate (ai, i0); \
632 a = ai[i0]; \
633 b = (uword) 1 << i1; \
634 do { body; } while (0); \
635 ai[i0] = a; \
636 return ai; \
637}
638
639/* ALU functions immediate: */
640/* *INDENT-OFF* */
641_(andi, a = a & b)
642_(andnoti, a = a & ~b)
643_(ori, a = a | b)
644_(xori, a = a ^ b)
645#undef _
646/* *INDENT-ON* */
647
Dave Barach310f7fe2016-08-05 14:36:27 -0400648/** Return a random bitmap of the requested length
649 @param ai - pointer to the destination bitmap
650 @param n_bits - number of bits to allocate
Chris Luked4024f52016-09-06 09:32:36 -0400651 @param [in,out] seed - pointer to the random number seed
Dave Barach310f7fe2016-08-05 14:36:27 -0400652 @returns a reasonably random bitmap based. See random.h.
653*/
Florin Corasfcd23682018-06-29 03:22:44 -0700654always_inline uword *
655clib_bitmap_random (uword * ai, uword n_bits, u32 * seed)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700656{
657 vec_reset_length (ai);
658
659 if (n_bits > 0)
660 {
661 uword i = n_bits - 1;
662 uword i0, i1;
663 uword log2_rand_max;
664
665 log2_rand_max = min_log2 (random_u32_max ());
666
667 i0 = i / BITS (ai[0]);
668 i1 = i % BITS (ai[0]);
669
670 clib_bitmap_vec_validate (ai, i0);
671 for (i = 0; i <= i0; i++)
672 {
673 uword n;
674 for (n = 0; n < BITS (ai[i]); n += log2_rand_max)
675 ai[i] |= random_u32 (seed) << n;
676 }
677 if (i1 + 1 < BITS (ai[0]))
678 ai[i0] &= (((uword) 1 << (i1 + 1)) - 1);
679 }
680 return ai;
681}
682
Dave Barach310f7fe2016-08-05 14:36:27 -0400683/** Return the next set bit in a bitmap starting at bit i
684 @param ai - pointer to the bitmap
685 @param i - first bit position to test
Dave Barachc3799992016-08-15 11:12:27 -0400686 @returns first set bit position at or after i,
Dave Barach310f7fe2016-08-05 14:36:27 -0400687 ~0 if no further set bits are found
688*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700689always_inline uword
690clib_bitmap_next_set (uword * ai, uword i)
691{
692 uword i0 = i / BITS (ai[0]);
693 uword i1 = i % BITS (ai[0]);
694 uword t;
Dave Barachc3799992016-08-15 11:12:27 -0400695
Ed Warnickecb9cada2015-12-08 15:45:58 -0700696 if (i0 < vec_len (ai))
697 {
698 t = (ai[i0] >> i1) << i1;
699 if (t)
700 return log2_first_set (t) + i0 * BITS (ai[0]);
701
702 for (i0++; i0 < vec_len (ai); i0++)
703 {
704 t = ai[i0];
705 if (t)
706 return log2_first_set (t) + i0 * BITS (ai[0]);
707 }
708 }
709
710 return ~0;
711}
712
Dave Barach310f7fe2016-08-05 14:36:27 -0400713/** Return the next clear bit in a bitmap starting at bit i
714 @param ai - pointer to the bitmap
715 @param i - first bit position to test
716 @returns first clear bit position at or after i
717*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700718always_inline uword
719clib_bitmap_next_clear (uword * ai, uword i)
720{
721 uword i0 = i / BITS (ai[0]);
722 uword i1 = i % BITS (ai[0]);
723 uword t;
Dave Barachc3799992016-08-15 11:12:27 -0400724
Ed Warnickecb9cada2015-12-08 15:45:58 -0700725 if (i0 < vec_len (ai))
726 {
727 t = (~ai[i0] >> i1) << i1;
728 if (t)
729 return log2_first_set (t) + i0 * BITS (ai[0]);
730
731 for (i0++; i0 < vec_len (ai); i0++)
732 {
Dave Barachc3799992016-08-15 11:12:27 -0400733 t = ~ai[i0];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700734 if (t)
735 return log2_first_set (t) + i0 * BITS (ai[0]);
736 }
John Loef8db362018-07-04 16:27:59 -0400737
738 /* no clear bit left in bitmap, return bit just beyond bitmap */
Dave Barach37b44542020-04-27 18:38:36 -0400739 return (i0 * BITS (ai[0])) + 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700740 }
741 return i;
742}
743
Yi Hee4a9eb72018-07-17 14:18:41 +0800744/** unformat an any sized hexadecimal bitmask into a bitmap
745
746 uword * bitmap;
747 rv = unformat ("%U", unformat_bitmap_mask, &bitmap);
748
749 Standard unformat_function_t arguments
750
751 @param input - pointer an unformat_input_t
752 @param va - varargs list comprising a single uword **
753 @returns 1 on success, 0 on failure
754*/
755static inline uword
756unformat_bitmap_mask (unformat_input_t * input, va_list * va)
757{
758 u8 *v = 0; /* hexadecimal vector */
759 uword **bitmap_return = va_arg (*va, uword **);
760 uword *bitmap = 0;
761
762 if (unformat (input, "%U", unformat_hex_string, &v))
763 {
764 int i, s = vec_len (v) - 1; /* 's' for significance or shift */
765
766 /* v[0] holds the most significant byte */
767 for (i = 0; s >= 0; i++, s--)
768 bitmap = clib_bitmap_set_multiple (bitmap,
769 s * BITS (v[i]), v[i],
770 BITS (v[i]));
771
772 vec_free (v);
773 *bitmap_return = bitmap;
774 return 1;
775 }
776
777 return 0;
778}
779
Dave Barachc3799992016-08-15 11:12:27 -0400780/** unformat a list of bit ranges into a bitmap (eg "0-3,5-7,11" )
Dave Barach310f7fe2016-08-05 14:36:27 -0400781
782 uword * bitmap;
783 rv = unformat ("%U", unformat_bitmap_list, &bitmap);
784
785 Standard unformat_function_t arguments
786
Dave Barachc3799992016-08-15 11:12:27 -0400787 @param input - pointer an unformat_input_t
Dave Barach310f7fe2016-08-05 14:36:27 -0400788 @param va - varargs list comprising a single uword **
789 @returns 1 on success, 0 on failure
790*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700791static inline uword
Dave Barachc3799992016-08-15 11:12:27 -0400792unformat_bitmap_list (unformat_input_t * input, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700793{
Dave Barachc3799992016-08-15 11:12:27 -0400794 uword **bitmap_return = va_arg (*va, uword **);
795 uword *bitmap = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700796
Dave Barachc3799992016-08-15 11:12:27 -0400797 u32 a, b;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700798
799 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
800 {
801 int i;
802 if (unformat (input, "%u-%u,", &a, &b))
Dave Barachc3799992016-08-15 11:12:27 -0400803 ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700804 else if (unformat (input, "%u,", &a))
Dave Barachc3799992016-08-15 11:12:27 -0400805 b = a;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700806 else if (unformat (input, "%u-%u", &a, &b))
Dave Barachc3799992016-08-15 11:12:27 -0400807 ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700808 else if (unformat (input, "%u", &a))
Dave Barachc3799992016-08-15 11:12:27 -0400809 b = a;
Damjan Marion75d1f242016-01-19 14:06:32 +0100810 else if (bitmap)
Dave Barachc3799992016-08-15 11:12:27 -0400811 {
812 unformat_put_input (input);
Damjan Marion75d1f242016-01-19 14:06:32 +0100813 break;
814 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700815 else
Dave Barachc3799992016-08-15 11:12:27 -0400816 goto error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700817
Damjan Marion14a44d32016-02-05 23:33:21 +0100818 if (b < a)
Dave Barachc3799992016-08-15 11:12:27 -0400819 goto error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700820
821 for (i = a; i <= b; i++)
Dave Barachc3799992016-08-15 11:12:27 -0400822 bitmap = clib_bitmap_set (bitmap, i, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700823 }
824 *bitmap_return = bitmap;
825 return 1;
826error:
Dave Barachc3799992016-08-15 11:12:27 -0400827 clib_bitmap_free (bitmap);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700828 return 0;
829}
830
Dave Barach310f7fe2016-08-05 14:36:27 -0400831/** Format a bitmap as a string of hex bytes
832
833 uword * bitmap;
834 s = format ("%U", format_bitmap_hex, bitmap);
835
836 Standard format_function_t arguments
837
838 @param s - string under construction
839 @param args - varargs list comprising a single uword *
840 @returns string under construction
841*/
Damjan Marion14a44d32016-02-05 23:33:21 +0100842static inline u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400843format_bitmap_hex (u8 * s, va_list * args)
Damjan Marion14a44d32016-02-05 23:33:21 +0100844{
Dave Barachc3799992016-08-15 11:12:27 -0400845 uword *bitmap = va_arg (*args, uword *);
Damjan Marion14a44d32016-02-05 23:33:21 +0100846 int i, is_trailing_zero = 1;
847
848 if (!bitmap)
Dave Barachc3799992016-08-15 11:12:27 -0400849 return format (s, "0");
Damjan Marion14a44d32016-02-05 23:33:21 +0100850
851 i = vec_bytes (bitmap) * 2;
852
853 while (i > 0)
854 {
Dave Barachc3799992016-08-15 11:12:27 -0400855 u8 x = clib_bitmap_get_multiple (bitmap, --i * 4, 4);
Damjan Marion14a44d32016-02-05 23:33:21 +0100856
857 if (x && is_trailing_zero)
Dave Barachc3799992016-08-15 11:12:27 -0400858 is_trailing_zero = 0;
Damjan Marion14a44d32016-02-05 23:33:21 +0100859
860 if (x || !is_trailing_zero)
Dave Barachc3799992016-08-15 11:12:27 -0400861 s = format (s, "%x", x);
Damjan Marion14a44d32016-02-05 23:33:21 +0100862 }
863 return s;
864}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700865#endif /* included_clib_bitmap_h */
Dave Barachc3799992016-08-15 11:12:27 -0400866
867/*
868 * fd.io coding-style-patch-verification: ON
869 *
870 * Local Variables:
871 * eval: (c-set-style "gnu")
872 * End:
873 */