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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 Copyright (c) 2001, 2002, 2003, 2005 Eliot Dresselhaus
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:
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
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.
38 #ifndef included_clib_bitmap_h
39 #define included_clib_bitmap_h
42 Bitmaps built as vectors of machine words
45 #include <vppinfra/vec.h>
46 #include <vppinfra/random.h>
47 #include <vppinfra/error.h>
48 #include <vppinfra/bitops.h> /* for count_set_bits */
50 typedef uword clib_bitmap_t;
52 /** 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
57 clib_bitmap_is_zero (uword * ai)
60 for (i = 0; i < vec_len (ai); i++)
66 /** 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
72 clib_bitmap_is_equal (uword * a, uword * b)
75 if (vec_len (a) != vec_len (b))
77 for (i = 0; i < vec_len (a); i++)
83 /** Duplicate a bitmap
84 @param v - pointer to a bitmap
85 @returns a duplicate of the bitmap
87 #define clib_bitmap_dup(v) vec_dup(v)
90 @param v - pointer to the bitmap to free
92 #define clib_bitmap_free(v) vec_free(v)
94 /** Number of bytes in a bitmap
95 @param v - pointer to the bitmap
97 #define clib_bitmap_bytes(v) vec_bytes(v)
100 @param v - pointer to the bitmap to clear
102 #define clib_bitmap_zero(v) vec_zero(v)
104 /** 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
109 #define clib_bitmap_alloc(v,n_bits) \
110 v = vec_new (uword, ((n_bits) + BITS (uword) - 1) / BITS (uword))
112 #define clib_bitmap_vec_validate(v,i) vec_validate_aligned((v),(i),sizeof(uword))
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))
118 /* low-level routine to remove trailing zeros from a bitmap */
119 always_inline uword *
120 _clib_bitmap_remove_trailing_zeros (uword * a)
125 for (i = _vec_len (a) - 1; i >= 0; i--)
128 _vec_len (a) = i + 1;
133 /** Sets the ith bit of a bitmap to new_value.
134 No sanity checking. Be careful.
135 @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
141 clib_bitmap_set_no_check (uword * a, uword i, uword new_value)
143 uword i0 = i / BITS (a[0]);
144 uword i1 = i % BITS (a[0]);
145 uword bit = (uword) 1 << i1;
148 /* Removed ASSERT since uword * a may not be a vector. */
149 /* ASSERT (i0 < vec_len (a)); */
152 old_value = (ai & bit) != 0;
154 ai |= ((uword) (new_value != 0)) << i1;
159 /** Sets the ith bit of a bitmap to new_value
160 Removes trailing zeros from the bitmap
161 @param ai - pointer to the bitmap
162 @param i - the bit position to interrogate
163 @param value - new value for the bit
164 @returns the old value of the bit
166 always_inline uword *
167 clib_bitmap_set (uword * ai, uword i, uword value)
169 uword i0 = i / BITS (ai[0]);
170 uword i1 = i % BITS (ai[0]);
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. */
177 clib_bitmap_vec_validate (ai, i0);
180 a &= ~((uword) 1 << i1);
181 a |= ((uword) (value != 0)) << i1;
184 /* If bits have been cleared, test for zero. */
186 ai = _clib_bitmap_remove_trailing_zeros (ai);
191 /** 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
197 clib_bitmap_get (uword * ai, uword i)
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);
204 /** 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
212 clib_bitmap_get_no_check (uword * ai, uword i)
214 uword i0 = i / BITS (ai[0]);
215 uword i1 = i % BITS (ai[0]);
216 return 0 != ((ai[i0] >> i1) & 1);
220 clib_bitmap_get_multiple_no_check (uword * ai, uword i, uword n_bits)
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));
228 /** 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
235 clib_bitmap_get_multiple (uword * bitmap, uword i, uword n_bits)
237 uword i0, i1, result;
238 uword l = vec_len (bitmap);
240 ASSERT (n_bits <= BITS (result));
242 i0 = i / BITS (bitmap[0]);
243 i1 = i % BITS (bitmap[0]);
245 /* Check first word. */
249 result |= (bitmap[i0] >> i1);
250 if (n_bits < BITS (bitmap[0]))
251 result &= (((uword) 1 << n_bits) - 1);
254 /* Check for overlap into next word. */
256 if (i1 + n_bits > BITS (bitmap[0]) && i0 < l)
258 n_bits -= BITS (bitmap[0]) - i1;
260 (bitmap[i0] & (((uword) 1 << n_bits) - 1)) << (BITS (bitmap[0]) - i1);
266 /** 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
274 always_inline uword *
275 clib_bitmap_set_multiple (uword * bitmap, uword i, uword value, uword n_bits)
277 uword i0, i1, l, t, m;
279 ASSERT (n_bits <= BITS (value));
281 i0 = i / BITS (bitmap[0]);
282 i1 = i % BITS (bitmap[0]);
284 /* Allocate bitmap. */
285 clib_bitmap_vec_validate (bitmap, (i + n_bits) / BITS (bitmap[0]));
286 l = vec_len (bitmap);
289 if (n_bits < BITS (value))
290 m = (((uword) 1 << n_bits) - 1);
293 /* Insert into first word. */
299 /* Insert into second word. */
301 if (i1 + n_bits > BITS (bitmap[0]) && i0 < l)
303 t = BITS (bitmap[0]) - i1;
307 m = ((uword) 1 << n_bits) - 1;
316 always_inline uword *
317 clib_bitmap_set_region (uword * bitmap, uword i, uword value, uword n_bits)
322 a0 = i / BITS (bitmap[0]);
323 a1 = i % BITS (bitmap[0]);
326 b0 = i_end / BITS (bitmap[0]);
328 clib_bitmap_vec_validate (bitmap, b0);
331 mask = n_bits < BITS (bitmap[0]) ? pow2_mask (n_bits) : ~0;
339 for (a0++; a0 < b0; a0++)
340 bitmap[a0] = value ? ~0 : 0;
344 word n_bits_left = n_bits - (BITS (bitmap[0]) - a1);
345 mask = pow2_mask (n_bits_left);
355 /** Macro to iterate across set bits in a bitmap
357 @param i - the current set bit
358 @param ai - the bitmap
359 @param body - the expression to evaluate for each set bit
361 #define clib_bitmap_foreach(i,ai) \
363 for (i = clib_bitmap_first_set (ai); \
365 i = clib_bitmap_next_set (ai, i + 1))
367 #define clib_bitmap_foreach_old(i,ai,body) \
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++) \
373 __bitmap_ai = (ai)[__bitmap_i]; \
374 while (__bitmap_ai != 0) \
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; \
386 /** 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
391 clib_bitmap_first_set (uword * ai)
395 #if defined(CLIB_HAVE_VEC256)
396 while (i + 7 < vec_len (ai))
399 v = u64x4_load_unaligned (ai + i) | u64x4_load_unaligned (ai + i + 4);
400 if (!u64x4_is_all_zero (v))
404 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE)
405 while (i + 3 < vec_len (ai))
408 v = u64x2_load_unaligned (ai + i) | u64x2_load_unaligned (ai + i + 2);
409 if (!u64x2_is_all_zero (v))
415 for (; i < vec_len (ai); i++)
419 return i * BITS (ai[0]) + log2_first_set (x);
424 /** 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
429 clib_bitmap_last_set (uword * ai)
433 for (i = vec_len (ai); i > 0; i--)
439 first_bit = count_leading_zeros (x);
440 return (i) * BITS (ai[0]) - first_bit - 1;
446 /** Return the lowest numbered clear bit in a bitmap
447 @param ai - pointer to the bitmap
448 @returns lowest numbered clear bit
451 clib_bitmap_first_clear (uword * ai)
454 for (i = 0; i < vec_len (ai); i++)
458 return i * BITS (ai[0]) + log2_first_set (x);
460 return i * BITS (ai[0]);
463 /** 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
468 clib_bitmap_count_set_bits (uword * ai)
472 for (i = 0; i < vec_len (ai); i++)
473 n_set += count_set_bits (ai[i]);
477 /** Logical operator across two bitmaps
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
483 always_inline uword *clib_bitmap_and (uword * ai, uword * bi);
485 /** Logical operator across two bitmaps
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
491 always_inline uword *clib_bitmap_andnot (uword * ai, uword * bi);
493 /** Logical operator across two bitmaps
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
499 always_inline uword *clib_bitmap_or (uword * ai, uword * bi);
500 /** Logical operator across two bitmaps
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
506 always_inline uword *clib_bitmap_or (uword * ai, uword * bi);
508 /** Logical operator across two bitmaps
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
514 always_inline uword *clib_bitmap_xor (uword * ai, uword * bi);
516 /* ALU function definition macro for functions taking two bitmaps. */
517 #define _(name, body, check_zero) \
518 always_inline uword * \
519 clib_bitmap_##name (uword * ai, uword * bi) \
521 uword i, a, b, bi_len, n_trailing_zeros; \
523 n_trailing_zeros = 0; \
524 bi_len = vec_len (bi); \
526 clib_bitmap_vec_validate (ai, bi_len - 1); \
527 for (i = 0; i < vec_len (ai); i++) \
530 b = i < bi_len ? bi[i] : 0; \
531 do { body; } while (0); \
534 n_trailing_zeros = a ? 0 : (n_trailing_zeros + 1); \
537 _vec_len (ai) -= n_trailing_zeros; \
544 _(andnot, a = a & ~b, 1)
549 /** Logical operator across two bitmaps which duplicates the first bitmap
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
555 always_inline uword *clib_bitmap_dup_and (uword * ai, uword * bi);
557 /** Logical operator across two bitmaps which duplicates the first bitmap
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
563 always_inline uword *clib_bitmap_dup_andnot (uword * ai, uword * bi);
565 /** Logical operator across two bitmaps which duplicates the first bitmap
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
571 always_inline uword *clib_bitmap_dup_or (uword * ai, uword * bi);
573 /** Logical operator across two bitmaps which duplicates the first bitmap
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
579 always_inline uword *clib_bitmap_dup_xor (uword * ai, uword * bi);
582 always_inline uword * \
583 clib_bitmap_dup_##name (uword * ai, uword * bi) \
584 { return clib_bitmap_##name (clib_bitmap_dup (ai), bi); }
594 /* ALU function definition macro for functions taking one bitmap and an
596 #define _(name, body, check_zero) \
597 always_inline uword * \
598 clib_bitmap_##name (uword * ai, uword i) \
600 uword i0 = i / BITS (ai[0]); \
601 uword i1 = i % BITS (ai[0]); \
603 clib_bitmap_vec_validate (ai, i0); \
605 b = (uword) 1 << i1; \
606 do { body; } while (0); \
608 if (check_zero && a == 0) \
609 ai = _clib_bitmap_remove_trailing_zeros (ai); \
613 /* ALU functions immediate: */
615 _(andi, a = a & b, 1)
616 _(andnoti, a = a & ~b, 1)
618 _(xori, a = a ^ b, 1)
622 /* ALU function definition macro for functions taking one bitmap and an
623 * immediate. No tail trimming */
624 #define _(name, body) \
625 always_inline uword * \
626 clib_bitmap_##name##_notrim (uword * ai, uword i) \
628 uword i0 = i / BITS (ai[0]); \
629 uword i1 = i % BITS (ai[0]); \
631 clib_bitmap_vec_validate (ai, i0); \
633 b = (uword) 1 << i1; \
634 do { body; } while (0); \
639 /* ALU functions immediate: */
642 _(andnoti, a = a & ~b)
648 /** 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
651 @param [in,out] seed - pointer to the random number seed
652 @returns a reasonably random bitmap based. See random.h.
654 always_inline uword *
655 clib_bitmap_random (uword * ai, uword n_bits, u32 * seed)
657 vec_reset_length (ai);
661 uword i = n_bits - 1;
665 log2_rand_max = min_log2 (random_u32_max ());
667 i0 = i / BITS (ai[0]);
668 i1 = i % BITS (ai[0]);
670 clib_bitmap_vec_validate (ai, i0);
671 for (i = 0; i <= i0; i++)
674 for (n = 0; n < BITS (ai[i]); n += log2_rand_max)
675 ai[i] |= random_u32 (seed) << n;
677 if (i1 + 1 < BITS (ai[0]))
678 ai[i0] &= (((uword) 1 << (i1 + 1)) - 1);
683 /** 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
686 @returns first set bit position at or after i,
687 ~0 if no further set bits are found
690 clib_bitmap_next_set (uword * ai, uword i)
692 uword i0 = i / BITS (ai[0]);
693 uword i1 = i % BITS (ai[0]);
696 if (i0 < vec_len (ai))
698 t = (ai[i0] >> i1) << i1;
700 return log2_first_set (t) + i0 * BITS (ai[0]);
702 for (i0++; i0 < vec_len (ai); i0++)
706 return log2_first_set (t) + i0 * BITS (ai[0]);
713 /** 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
719 clib_bitmap_next_clear (uword * ai, uword i)
721 uword i0 = i / BITS (ai[0]);
722 uword i1 = i % BITS (ai[0]);
725 if (i0 < vec_len (ai))
727 t = (~ai[i0] >> i1) << i1;
729 return log2_first_set (t) + i0 * BITS (ai[0]);
731 for (i0++; i0 < vec_len (ai); i0++)
735 return log2_first_set (t) + i0 * BITS (ai[0]);
738 /* no clear bit left in bitmap, return bit just beyond bitmap */
739 return (i0 * BITS (ai[0])) + 1;
744 /** unformat an any sized hexadecimal bitmask into a bitmap
747 rv = unformat ("%U", unformat_bitmap_mask, &bitmap);
749 Standard unformat_function_t arguments
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
756 unformat_bitmap_mask (unformat_input_t * input, va_list * va)
758 u8 *v = 0; /* hexadecimal vector */
759 uword **bitmap_return = va_arg (*va, uword **);
762 if (unformat (input, "%U", unformat_hex_string, &v))
764 int i, s = vec_len (v) - 1; /* 's' for significance or shift */
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],
773 *bitmap_return = bitmap;
780 /** unformat a list of bit ranges into a bitmap (eg "0-3,5-7,11" )
783 rv = unformat ("%U", unformat_bitmap_list, &bitmap);
785 Standard unformat_function_t arguments
787 @param input - pointer an unformat_input_t
788 @param va - varargs list comprising a single uword **
789 @returns 1 on success, 0 on failure
792 unformat_bitmap_list (unformat_input_t * input, va_list * va)
794 uword **bitmap_return = va_arg (*va, uword **);
799 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
802 if (unformat (input, "%u-%u,", &a, &b))
804 else if (unformat (input, "%u,", &a))
806 else if (unformat (input, "%u-%u", &a, &b))
808 else if (unformat (input, "%u", &a))
812 unformat_put_input (input);
821 for (i = a; i <= b; i++)
822 bitmap = clib_bitmap_set (bitmap, i, 1);
824 *bitmap_return = bitmap;
827 clib_bitmap_free (bitmap);
831 /** Format a bitmap as a string of hex bytes
834 s = format ("%U", format_bitmap_hex, bitmap);
836 Standard format_function_t arguments
838 @param s - string under construction
839 @param args - varargs list comprising a single uword *
840 @returns string under construction
843 format_bitmap_hex (u8 * s, va_list * args)
845 uword *bitmap = va_arg (*args, uword *);
846 int i, is_trailing_zero = 1;
849 return format (s, "0");
851 i = vec_bytes (bitmap) * 2;
855 u8 x = clib_bitmap_get_multiple (bitmap, --i * 4, 4);
857 if (x && is_trailing_zero)
858 is_trailing_zero = 0;
860 if (x || !is_trailing_zero)
861 s = format (s, "%x", x);
865 #endif /* included_clib_bitmap_h */
868 * fd.io coding-style-patch-verification: ON
871 * eval: (c-set-style "gnu")