+/**
+ * Set bits in a range to zero or one
+ * @param bitset the bitset
+ * @param from first bit to set
+ * @param to last bit (the first bit which is not set anymore)
+ * @param val wether to set to 1 or 0
+ */
+static inline void rbitset_set_range(unsigned *bitset, unsigned from,
+ unsigned to, bool val)
+{
+ /*
+ * A small example (for cleaning bits in the same unit).
+ * from = 7
+ * to = 19
+ * do_set = 0
+ * result: xxxxxxx000000000000xxxxxxxxxxxxx
+ * from_unit_mask: 00000001111111111111111111111111
+ * to_unit_mask: 11111111111111111110000000000000
+ * scale: 01234567890123456789012345678901
+ * 1 2 3
+ */
+
+ unsigned from_bit = from % BITS_PER_ELEM;
+ unsigned from_pos = from / BITS_PER_ELEM;
+ unsigned from_unit_mask = ~((1 << from_bit) - 1);
+
+ unsigned to_bit = to % BITS_PER_ELEM;
+ unsigned to_pos = to / BITS_PER_ELEM;
+ unsigned to_unit_mask = (1 << to_bit) - 1;
+
+ assert(from < to);
+
+ /* do we want to set the bits in the range? */
+ if (val) {
+ if (from_pos == to_pos) {
+ BITSET_ELEM(bitset, from_pos) |= from_unit_mask & to_unit_mask;
+ } else {
+ unsigned i;
+ BITSET_ELEM(bitset, from_pos) |= from_unit_mask;
+ BITSET_ELEM(bitset, to_pos) |= to_unit_mask;
+ for (i = from_pos + 1; i < to_pos; ++i)
+ BITSET_ELEM(bitset, i) = ~0u;
+ }
+ } else {
+ /* ... or clear them? */
+ if (from_pos == to_pos) {
+ BITSET_ELEM(bitset, from_pos) &= ~(from_unit_mask & to_unit_mask);
+ } else {
+ unsigned i;
+ BITSET_ELEM(bitset, from_pos) &= ~from_unit_mask;
+ BITSET_ELEM(bitset, to_pos) &= ~to_unit_mask;
+ for (i = from_pos + 1; i < to_pos; ++i)
+ BITSET_ELEM(bitset, i) = 0;
+ }
+ }
+}
+