@@ -54,8 +54,6 @@
#define MLX5_SHMAT_FLAGS 0
#endif
-#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG)
-
#ifndef HPAGE_SIZE
#define HPAGE_SIZE (2UL * 1024 * 1024)
#endif
@@ -1,4 +1,5 @@
publish_internal_headers(util
+ bitmap.h
cl_qmap.h
compiler.h
interval_set.h
@@ -9,6 +10,7 @@ publish_internal_headers(util
)
set(C_FILES
+ bitmap.c
cl_map.c
interval_set.c
node_name_map.c
new file mode 100644
@@ -0,0 +1,180 @@
+/* GPLv2 or OpenIB.org BSD (MIT) See COPYING file */
+
+#include "bitmap.h"
+
+#define BMP_WORD_INDEX(n) (BITS_TO_LONGS((n) + 1) - 1)
+#define BMP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
+#define BMP_LAST_WORD_MASK(end) (~BMP_FIRST_WORD_MASK(end))
+
+static unsigned long __word_ffs(const unsigned long *word)
+{
+ unsigned long i;
+
+ for (i = 0; i < BITS_PER_LONG; i++) {
+ if (bitmap_test_bit(word, i))
+ return i;
+ }
+
+ return i;
+}
+
+static unsigned long word_ffs(const unsigned long *word,
+ unsigned long bmp_index, unsigned long end)
+{
+ unsigned long set_bit;
+
+ set_bit = __word_ffs(word);
+ set_bit += bmp_index * BITS_PER_LONG;
+ if (set_bit >= end)
+ return end;
+
+ return set_bit;
+}
+
+/*
+ * Finds the first set bit in the bitmap starting from
+ * 'start' bit until ('end'-1) bit.
+ *
+ * Returns the set bit index if found, otherwise returns 'end'.
+ */
+unsigned long bitmap_find_first_bit(const unsigned long *bmp,
+ unsigned long start, unsigned long end)
+{
+ unsigned long mask;
+ unsigned long first_word;
+ unsigned long curr_idx = BMP_WORD_INDEX(start);
+ unsigned long end_idx = BMP_WORD_INDEX(end);
+
+ assert(start <= end);
+
+ mask = BMP_FIRST_WORD_MASK(start);
+
+ first_word = bmp[curr_idx] & mask;
+ if (first_word)
+ return word_ffs(&first_word, curr_idx, end);
+
+ for (curr_idx++; curr_idx <= end_idx; curr_idx++) {
+ if (!bmp[curr_idx])
+ continue;
+
+ return word_ffs(&bmp[curr_idx], curr_idx, end);
+ }
+
+ return end;
+}
+
+/*
+ * Zeroes bitmap bits in the following range: [start,end-1]
+ */
+void bitmap_zero_region(unsigned long *bmp, unsigned long start,
+ unsigned long end)
+{
+ unsigned long start_mask;
+ unsigned long last_mask;
+ unsigned long curr_idx = BMP_WORD_INDEX(start);
+ unsigned long end_idx = BMP_WORD_INDEX(end);
+
+ assert(start <= end);
+
+ start_mask = BMP_FIRST_WORD_MASK(start);
+ last_mask = BMP_LAST_WORD_MASK(end);
+
+ if (curr_idx == end_idx) {
+ bmp[curr_idx] &= ~(start_mask & last_mask);
+ return;
+ }
+
+ bmp[curr_idx] &= ~start_mask;
+
+ for (curr_idx++; curr_idx < end_idx; curr_idx++)
+ bmp[curr_idx] = 0;
+
+ bmp[curr_idx] &= ~last_mask;
+}
+
+/*
+ * Sets bitmap bits in the following range: [start,end-1]
+ */
+void bitmap_fill_region(unsigned long *bmp, unsigned long start,
+ unsigned long end)
+{
+ unsigned long start_mask;
+ unsigned long last_mask;
+ unsigned long curr_idx = BMP_WORD_INDEX(start);
+ unsigned long end_idx = BMP_WORD_INDEX(end);
+
+ assert(start <= end);
+
+ start_mask = BMP_FIRST_WORD_MASK(start);
+ last_mask = BMP_LAST_WORD_MASK(end);
+
+ if (curr_idx == end_idx) {
+ bmp[curr_idx] |= (start_mask & last_mask);
+ return;
+ }
+
+ bmp[curr_idx] |= start_mask;
+
+ for (curr_idx++; curr_idx < end_idx; curr_idx++)
+ bmp[curr_idx] = ULONG_MAX;
+
+ bmp[curr_idx] |= last_mask;
+}
+
+/*
+ * Checks whether the contiguous region of region_size bits starting from
+ * start is free.
+ *
+ * Returns true if the said region is free, otherwise returns false.
+ */
+static bool bitmap_is_free_region(unsigned long *bmp, unsigned long start,
+ unsigned long region_size)
+{
+ unsigned long curr_idx;
+ unsigned long last_idx;
+ unsigned long last_mask;
+ unsigned long start_mask;
+
+ curr_idx = BMP_WORD_INDEX(start);
+ start_mask = BMP_FIRST_WORD_MASK(start);
+ last_idx = BMP_WORD_INDEX(start + region_size);
+ last_mask = BMP_LAST_WORD_MASK(start + region_size);
+
+ if (curr_idx == last_idx)
+ return !(bmp[curr_idx] & start_mask & last_mask);
+
+ if (bmp[curr_idx] & start_mask)
+ return false;
+
+ for (curr_idx++; curr_idx < last_idx; curr_idx++) {
+ if (bmp[curr_idx])
+ return false;
+ }
+
+ return !(bmp[curr_idx] & last_mask);
+}
+
+/*
+ * Finds a contiguous region with the size of region_size
+ * in the bitmap that is not set.
+ *
+ * Returns first index of such region if found,
+ * otherwise returns nbits.
+ */
+unsigned long bitmap_find_free_region(unsigned long *bmp,
+ unsigned long nbits,
+ unsigned long region_size)
+{
+ unsigned long start;
+
+ for (start = 0; start + region_size <= nbits; start++) {
+ if (bitmap_test_bit(bmp, start))
+ continue;
+
+ if (bitmap_is_free_region(bmp, start, region_size))
+ return start;
+ }
+
+ return nbits;
+}
+
new file mode 100644
@@ -0,0 +1,120 @@
+/* GPLv2 or OpenIB.org BSD (MIT) See COPYING file */
+
+#ifndef UTIL_BITMAP_H
+#define UTIL_BITMAP_H
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <limits.h>
+#include <string.h>
+#include <assert.h>
+
+#include "util.h"
+
+#define BMP_DECLARE(name, nbits) \
+ unsigned long (name)[BITS_TO_LONGS((nbits))]
+
+unsigned long bitmap_find_first_bit(const unsigned long *bmp,
+ unsigned long start, unsigned long end);
+
+void bitmap_zero_region(unsigned long *bmp, unsigned long start,
+ unsigned long end);
+
+void bitmap_fill_region(unsigned long *bmp, unsigned long start,
+ unsigned long end);
+
+unsigned long bitmap_find_free_region(unsigned long *bmp,
+ unsigned long nbits,
+ unsigned long region_size);
+
+static inline void bitmap_fill(unsigned long *bmp, unsigned long nbits)
+{
+ unsigned long size = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+
+ memset(bmp, 0xff, size);
+}
+
+static inline void bitmap_zero(unsigned long *bmp, unsigned long nbits)
+{
+ unsigned long size = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+
+ memset(bmp, 0, size);
+}
+
+static inline bool bitmap_empty(const unsigned long *bmp, unsigned long nbits)
+{
+ unsigned long i;
+ unsigned long mask = ULONG_MAX;
+
+ assert(nbits);
+
+ for (i = 0; i < BITS_TO_LONGS(nbits) - 1; i++) {
+ if (bmp[i] != 0)
+ return false;
+ }
+
+ if (nbits % BITS_PER_LONG)
+ mask = (1UL << (nbits % BITS_PER_LONG)) - 1;
+
+ return (bmp[i] & mask) ? false : true;
+}
+
+static inline bool bitmap_full(const unsigned long *bmp, unsigned long nbits)
+{
+ unsigned long i;
+ unsigned long mask = ULONG_MAX;
+
+ assert(nbits);
+
+ for (i = 0; i < BITS_TO_LONGS(nbits) - 1; i++) {
+ if (bmp[i] != -1UL)
+ return false;
+ }
+
+ if (nbits % BITS_PER_LONG)
+ mask = (1UL << (nbits % BITS_PER_LONG)) - 1;
+
+ return ((bmp[i] & mask) ^ (mask)) ? false : true;
+}
+
+static inline void bitmap_set_bit(unsigned long *bmp, unsigned long idx)
+{
+ bmp[(idx / BITS_PER_LONG)] |= (1UL << (idx % BITS_PER_LONG));
+}
+
+static inline void bitmap_clear_bit(unsigned long *bmp, unsigned long idx)
+{
+ bmp[(idx / BITS_PER_LONG)] &= ~(1UL << (idx % BITS_PER_LONG));
+}
+
+static inline bool bitmap_test_bit(const unsigned long *bmp, unsigned long idx)
+{
+ return !!(bmp[(idx / BITS_PER_LONG)] &
+ (1UL << (idx % BITS_PER_LONG)));
+}
+
+static inline unsigned long *bitmap_alloc0(unsigned long size)
+{
+ unsigned long *bmp;
+
+ bmp = calloc(BITS_TO_LONGS(size), sizeof(long));
+ if (!bmp)
+ return NULL;
+
+ return bmp;
+}
+
+static inline unsigned long *bitmap_alloc1(unsigned long size)
+{
+ unsigned long *bmp;
+
+ bmp = bitmap_alloc0(size);
+ if (!bmp)
+ return NULL;
+
+ bitmap_fill(bmp, size);
+
+ return bmp;
+}
+
+#endif
@@ -28,6 +28,7 @@ static inline bool __good_snprintf(size_t len, int rc)
#define BITS_PER_LONG (8 * sizeof(long))
#define BITS_PER_LONG_LONG (8 * sizeof(long long))
+#define BITS_TO_LONGS(nr) (((nr) + BITS_PER_LONG - 1) / BITS_PER_LONG)
#define GENMASK(h, l) \
(((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))