Page MenuHomeFreeBSD

D33312.diff
No OneTemporary

D33312.diff

diff --git a/share/man/man3/bitstring.3 b/share/man/man3/bitstring.3
--- a/share/man/man3/bitstring.3
+++ b/share/man/man3/bitstring.3
@@ -68,14 +68,17 @@
.Nm bit_decl ,
.Nm bit_ffc ,
.Nm bit_ffs ,
+.Nm bit_ff_at ,
.Nm bit_ffc_at ,
.Nm bit_ffs_at ,
.Nm bit_ffc_area ,
.Nm bit_ffs_area ,
+.Nm bit_ff_area_at ,
.Nm bit_ffc_area_at ,
.Nm bit_ffs_area_at ,
.Nm bit_nclear ,
.Nm bit_nset ,
+.Nm bit_ntest ,
.Nm bit_set ,
.Nm bit_test ,
.Nm bitstr_size
@@ -99,6 +102,8 @@
.Ft void
.Fn bit_ffs_at "bitstr_t *name" "int start" "int nbits" "int *value"
.Ft void
+.Fn bit_ff_at "bitstr_t *name" "int start" "int nbits" "int match" "int *value"
+.Ft void
.Fn bit_ffc_area "bitstr_t *name" "int nbits" "int size" "int *value"
.Ft void
.Fn bit_ffs_area "bitstr_t *name" "int nbits" "int size" "int *value"
@@ -106,6 +111,8 @@
.Fn bit_ffc_area_at "bitstr_t *name" "int start" "int nbits" "int size" "int *value"
.Ft void
.Fn bit_ffs_area_at "bitstr_t *name" "int start" "int nbits" "int size" "int *value"
+.Ft void
+.Fn bit_ff_area_at "bitstr_t *name" "int start" "int nbits" "int size" "int match" "int *value"
.Fn bit_foreach "bitstr_t *name" "int nbits" "int var"
.Fn bit_foreach_at "bitstr_t *name" "int start" "int nbits" "int var"
.Fn bit_foreach_unset "bitstr_t *name" "int nbits" "int var"
@@ -114,6 +121,8 @@
.Fn bit_nclear "bitstr_t *name" "int start" "int stop"
.Ft void
.Fn bit_nset "bitstr_t *name" "int start" "int stop"
+.Ft int
+.Fn bit_ntest "bitstr_t *name" "int start" "int stop" "int match"
.Ft void
.Fn bit_set "bitstr_t *name" "int bit"
.Ft int
@@ -186,6 +195,18 @@
.Fa name
is set, and zero otherwise.
.Pp
+The
+.Fn bit_ntest
+function
+evaluates to non-zero if the zero-based numbered bits from
+.Fa start
+through
+.Fa stop
+in the bit string
+.Ar name
+all have the value
+.Ar match .
+.Pp
The function
.Fn bit_ffc
stores in the location referenced by
@@ -245,6 +266,25 @@
is set to \-1.
.Pp
The
+.Fn bit_ff_at
+function
+stores in the location referenced by
+.Fa value
+the zero-based number of the first bit in the array of
+.Fa nbits
+bits referenced by
+.Fa name ,
+at or after the zero-based bit index
+.Fa start
+that has value
+.Fa match .
+If no bits after
+.Fa start
+match that value, the location referenced by
+.Fa value
+is set to \-1.
+.Pp
+The
.Fn bit_ffc_area
function stores in the location referenced by
.Fa value
@@ -321,6 +361,29 @@
is set to \-1.
.Pp
The
+.Fn bit_ff_area_at
+function stores in the location referenced by
+.Fa value
+the zero-based number of the first bit beginning a sequence of bits of
+at least
+.Fa size
+bits in the array of
+.Fa nbits
+bits referenced by
+.Fa name ,
+at or after the zero-based bit index
+.Fa start
+in which all bits have the value
+.Fa match .
+If no sequence of contiguous such bits of the specified
+.Fa size
+can be found at or after
+.Fa start ,
+the location referenced by
+.Fa value
+is set to \-1.
+.Pp
+The
.Fn bit_count
function stores in the location referenced by
.Fa value
diff --git a/sys/sys/bitstring.h b/sys/sys/bitstring.h
--- a/sys/sys/bitstring.h
+++ b/sys/sys/bitstring.h
@@ -155,6 +155,34 @@
_bitstr[_bit_idx(_bit)] &= ~_bit_mask(_bit);
}
+/* Are bits in [start ... stop] in bit string all 0 or all 1? */
+static inline int
+bit_ntest(const bitstr_t *_bitstr, int _start, int _stop, int _match)
+{
+ const bitstr_t *_stopbitstr;
+ bitstr_t _mask;
+
+ _mask = (_match == 0) ? 0 : _BITSTR_MASK;
+ _stopbitstr = _bitstr + _bit_idx(_stop);
+ _bitstr += _bit_idx(_start);
+
+ if (_bitstr == _stopbitstr)
+ return (0 == ((*_bitstr ^ _mask) &
+ _bit_make_mask(_start, _stop)));
+ if (_bit_offset(_start) != 0 &&
+ 0 != ((*_bitstr++ ^ _mask) &
+ _bit_make_mask(_start, _BITSTR_BITS - 1)))
+ return (0);
+ if (_bit_offset(_stop) == _BITSTR_BITS - 1)
+ ++_stopbitstr;
+ while (_bitstr < _stopbitstr) {
+ if (*_bitstr++ != _mask)
+ return (0);
+ }
+ return (_bit_offset(_stop) == _BITSTR_BITS - 1 ||
+ 0 == ((*_stopbitstr ^ _mask) & _bit_make_mask(0, _stop)));
+}
+
/* Set bits start ... stop inclusive in bit string. */
static inline void
bit_nset(bitstr_t *_bitstr, int _start, int _stop)
@@ -167,10 +195,14 @@
if (_bitstr == _stopbitstr) {
*_bitstr |= _bit_make_mask(_start, _stop);
} else {
- *_bitstr |= _bit_make_mask(_start, _BITSTR_BITS - 1);
- while (++_bitstr < _stopbitstr)
- *_bitstr = _BITSTR_MASK;
- *_stopbitstr |= _bit_make_mask(0, _stop);
+ if (_bit_offset(_start) != 0)
+ *_bitstr++ |= _bit_make_mask(_start, _BITSTR_BITS - 1);
+ if (_bit_offset(_stop) == _BITSTR_BITS - 1)
+ ++_stopbitstr;
+ while (_bitstr < _stopbitstr)
+ *_bitstr++ = _BITSTR_MASK;
+ if (_bit_offset(_stop) != _BITSTR_BITS - 1)
+ *_stopbitstr |= _bit_make_mask(0, _stop);
}
}
@@ -186,79 +218,62 @@
if (_bitstr == _stopbitstr) {
*_bitstr &= ~_bit_make_mask(_start, _stop);
} else {
- *_bitstr &= ~_bit_make_mask(_start, _BITSTR_BITS - 1);
- while (++_bitstr < _stopbitstr)
- *_bitstr = 0;
- *_stopbitstr &= ~_bit_make_mask(0, _stop);
+ if (_bit_offset(_start) != 0)
+ *_bitstr++ &= ~_bit_make_mask(_start, _BITSTR_BITS - 1);
+ if (_bit_offset(_stop) == _BITSTR_BITS - 1)
+ ++_stopbitstr;
+ while (_bitstr < _stopbitstr)
+ *_bitstr++ = 0;
+ if (_bit_offset(_stop) != _BITSTR_BITS - 1)
+ *_stopbitstr &= ~_bit_make_mask(0, _stop);
}
}
-/* Find the first bit set in bit string at or after bit start. */
+/* Find the first '_match'-bit in bit string at or after bit start. */
static inline void
-bit_ffs_at(bitstr_t *_bitstr, int _start, int _nbits, int *_result)
+bit_ff_at(bitstr_t *_bitstr, int _start, int _nbits, int _match,
+ int *_result)
{
bitstr_t *_curbitstr;
bitstr_t *_stopbitstr;
+ bitstr_t _mask;
bitstr_t _test;
- int _value, _offset;
+ int _value;
- if (_start >= _nbits) {
+ if (_start >= _nbits || _nbits <= 0) {
*_result = -1;
return;
}
- if (_nbits > 0) {
- _curbitstr = _bitstr + _bit_idx(_start);
- _stopbitstr = _bitstr + _bit_idx(_nbits - 1);
+ _curbitstr = _bitstr + _bit_idx(_start);
+ _stopbitstr = _bitstr + _bit_idx(_nbits - 1);
+ _mask = _match ? 0 : _BITSTR_MASK;
- _test = *_curbitstr;
- if (_bit_offset(_start) != 0)
- _test &= _bit_make_mask(_start, _BITSTR_BITS - 1);
- while (_test == 0 && _curbitstr < _stopbitstr)
- _test = *(++_curbitstr);
+ _test = _mask ^ *_curbitstr;
+ if (_bit_offset(_start) != 0)
+ _test &= _bit_make_mask(_start, _BITSTR_BITS - 1);
+ while (_test == 0 && _curbitstr < _stopbitstr)
+ _test = _mask ^ *(++_curbitstr);
- _offset = ffsl(_test);
- _value = ((_curbitstr - _bitstr) * _BITSTR_BITS) + _offset - 1;
- if (_offset == 0 || _value >= _nbits)
- _value = -1;
- } else {
+ _value = ((_curbitstr - _bitstr) * _BITSTR_BITS) + ffsl(_test) - 1;
+ if (_test == 0 ||
+ (_bit_offset(_nbits) != 0 && _value >= _nbits))
_value = -1;
- }
*_result = _value;
}
+/* Find the first bit set in bit string at or after bit start. */
+static inline void
+bit_ffs_at(bitstr_t *_bitstr, int _start, int _nbits, int *_result)
+{
+ bit_ff_at(_bitstr, _start, _nbits, 1, _result);
+}
+
/* Find the first bit clear in bit string at or after bit start. */
static inline void
bit_ffc_at(bitstr_t *_bitstr, int _start, int _nbits, int *_result)
{
- bitstr_t *_curbitstr;
- bitstr_t *_stopbitstr;
- bitstr_t _test;
- int _value, _offset;
-
- if (_start >= _nbits) {
- *_result = -1;
- return;
- }
-
- if (_nbits > 0) {
- _curbitstr = _bitstr + _bit_idx(_start);
- _stopbitstr = _bitstr + _bit_idx(_nbits - 1);
-
- _test = *_curbitstr;
- if (_bit_offset(_start) != 0)
- _test |= _bit_make_mask(0, _start - 1);
- while (_test == _BITSTR_MASK && _curbitstr < _stopbitstr)
- _test = *(++_curbitstr);
-
- _offset = ffsl(~_test);
- _value = ((_curbitstr - _bitstr) * _BITSTR_BITS) + _offset - 1;
- if (_offset == 0 || _value >= _nbits)
- _value = -1;
- } else {
- _value = -1;
- }
- *_result = _value;
+ bit_ff_at(_bitstr, _start, _nbits, 0, _result);
}
/* Find the first bit set in bit string. */
@@ -275,98 +290,65 @@
bit_ffc_at(_bitstr, /*start*/0, _nbits, _result);
}
-/* Find contiguous sequence of at least size set bits at or after start */
+/* Find contiguous sequence of at least size '_match'-bits at or after start */
static inline void
-bit_ffs_area_at(bitstr_t *_bitstr, int _start, int _nbits, int _size,
- int *_result)
+bit_ff_area_at(bitstr_t *_bitstr, int _start, int _nbits, int _size,
+ int _match, int *_result)
{
- bitstr_t *_curbitstr;
- bitstr_t _test;
- int _value, _offset, _logsize, _b;
+ bitstr_t *_curbitstr, _mask, _test;
+ int _value, _last, _shft, _maxshft;
if (_start + _size > _nbits || _nbits <= 0) {
*_result = -1;
return;
}
- _logsize = fls(_size - 1);
- _value = _start;
+ _mask = _match ? _BITSTR_MASK : 0;
+ _maxshft = _bit_idx(_size - 1) == 0 ? _size : _BITSTR_BITS;
+ _value = 0;
_curbitstr = _bitstr + _bit_idx(_start);
- _test = ~*_curbitstr;
- if (_bit_offset(_start) != 0)
- _test |= _bit_make_mask(0, _start - 1);
- for (_offset = 0;; _offset -= _BITSTR_BITS, _test = ~*++_curbitstr) {
- if (_test != 0) {
- /* If leading 0s in _test can finish 0-area, stop. */
- if (_offset + _size < (int)_BITSTR_BITS &&
- (_test & _bit_make_mask(0, _offset + _size)) == 0)
- break;
- /* Shrink-left every 0-area in _test by size-1 bits. */
- _b = _logsize;
- while ((_test & (_test + 1)) != 0 && _b-- > 0)
- _test |= _test >> (((_size - 1) >> _b) + 1) / 2;
- /* Find the start of the first 0-area in _test. */
- _offset = (~_test == 0) ? (int)_BITSTR_BITS :
- ffsl(~_test) - 1;
- _value = (_curbitstr - _bitstr) * _BITSTR_BITS +
- _offset;
- /* If there's insufficient space left, give up. */
- if (_value + _size > _nbits) {
- _value = -1;
- break;
- }
+ _test = ~(_BITSTR_MASK << _bit_offset(_start));
+ for (_last = _size - 1, _test |= _mask ^ *_curbitstr;
+ !(_bit_idx(_last) == 0 &&
+ (_test & _bit_make_mask(0, _last)) == 0);
+ _last -= _BITSTR_BITS, _test = _mask ^ *++_curbitstr) {
+ if (_test == 0)
+ continue;
+ /* Shrink-left every 0-area in _test by maxshft-1 bits. */
+ for (_shft = _maxshft; _shft > 1 && (_test & (_test + 1)) != 0;
+ _shft = (_shft + 1) / 2)
+ _test |= _test >> _shft / 2;
+ /* Find the start of the first 0-area in _test. */
+ _last = ffsl(~(_test >> 1));
+ _value = (_curbitstr - _bitstr) * _BITSTR_BITS + _last;
+ /* If there's insufficient space left, give up. */
+ if (_value + _size > _nbits) {
+ _value = -1;
+ break;
}
- if (_offset + _size <= (int)_BITSTR_BITS)
+ _last += _size - 1;
+ /* If a solution is contained in _test, success! */
+ if (_bit_idx(_last) == 0)
break;
+ /* A solution here needs bits from the next word. */
}
*_result = _value;
}
+/* Find contiguous sequence of at least size set bits at or after start */
+static inline void
+bit_ffs_area_at(bitstr_t *_bitstr, int _start, int _nbits, int _size,
+ int *_result)
+{
+ bit_ff_area_at(_bitstr, _start, _nbits, _size, 1, _result);
+}
+
/* Find contiguous sequence of at least size cleared bits at or after start */
static inline void
bit_ffc_area_at(bitstr_t *_bitstr, int _start, int _nbits, int _size,
int *_result)
{
- bitstr_t *_curbitstr;
- bitstr_t _test;
- int _value, _offset, _logsize, _b;
-
- if (_start + _size > _nbits || _nbits <= 0) {
- *_result = -1;
- return;
- }
-
- _logsize = fls(_size - 1);
- _value = _start;
- _curbitstr = _bitstr + _bit_idx(_start);
- _test = *_curbitstr;
- if (_bit_offset(_start) != 0)
- _test |= _bit_make_mask(0, _start - 1);
- for (_offset = 0;; _offset -= _BITSTR_BITS, _test = *++_curbitstr) {
- if (_test != 0) {
- /* If leading 0s in _test can finish 0-area, stop. */
- if (_offset + _size < (int)_BITSTR_BITS &&
- (_test & _bit_make_mask(0, _offset + _size)) == 0)
- break;
- /* Shrink-left every 0-area in _test by size-1 bits. */
- _b = _logsize;
- while ((_test & (_test + 1)) != 0 && _b-- > 0)
- _test |= _test >> (((_size - 1) >> _b) + 1) / 2;
- /* Find the start of the first 0-area in _test. */
- _offset = (~_test == 0) ? (int)_BITSTR_BITS :
- ffsl(~_test) - 1;
- _value = (_curbitstr - _bitstr) * _BITSTR_BITS +
- _offset;
- /* If there's insufficient space left, give up. */
- if (_value + _size > _nbits) {
- _value = -1;
- break;
- }
- }
- if (_offset + _size <= (int)_BITSTR_BITS)
- break;
- }
- *_result = _value;
+ bit_ff_area_at(_bitstr, _start, _nbits, _size, 0, _result);
}
/* Find contiguous sequence of at least size set bits in bit string */
diff --git a/sys/vm/vm_reserv.c b/sys/vm/vm_reserv.c
--- a/sys/vm/vm_reserv.c
+++ b/sys/vm/vm_reserv.c
@@ -53,6 +53,7 @@
#include <sys/sbuf.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
+#include <sys/bitstring.h>
#include <sys/counter.h>
#include <sys/ktr.h>
#include <sys/vmmeter.h>
@@ -106,68 +107,12 @@
#define VM_RESERV_INDEX(object, pindex) \
(((object)->pg_color + (pindex)) & (VM_LEVEL_0_NPAGES - 1))
-/*
- * The size of a population map entry
- */
-typedef u_long popmap_t;
-
-/*
- * The number of bits in a population map entry
- */
-#define NBPOPMAP (NBBY * sizeof(popmap_t))
-
-/*
- * The number of population map entries in a reservation
- */
-#define NPOPMAP howmany(VM_LEVEL_0_NPAGES, NBPOPMAP)
-#define NPOPMAP_MAX howmany(VM_LEVEL_0_NPAGES_MAX, NBPOPMAP)
-
/*
* Number of elapsed ticks before we update the LRU queue position. Used
* to reduce contention and churn on the list.
*/
#define PARTPOPSLOP 1
-/*
- * Clear a bit in the population map.
- */
-static __inline void
-popmap_clear(popmap_t popmap[], int i)
-{
-
- popmap[i / NBPOPMAP] &= ~(1UL << (i % NBPOPMAP));
-}
-
-/*
- * Set a bit in the population map.
- */
-static __inline void
-popmap_set(popmap_t popmap[], int i)
-{
-
- popmap[i / NBPOPMAP] |= 1UL << (i % NBPOPMAP);
-}
-
-/*
- * Is a bit in the population map clear?
- */
-static __inline boolean_t
-popmap_is_clear(popmap_t popmap[], int i)
-{
-
- return ((popmap[i / NBPOPMAP] & (1UL << (i % NBPOPMAP))) == 0);
-}
-
-/*
- * Is a bit in the population map set?
- */
-static __inline boolean_t
-popmap_is_set(popmap_t popmap[], int i)
-{
-
- return ((popmap[i / NBPOPMAP] & (1UL << (i % NBPOPMAP))) != 0);
-}
-
/*
* The reservation structure
*
@@ -199,7 +144,8 @@
uint8_t domain; /* (c) NUMA domain. */
char inpartpopq; /* (d, r) */
int lasttick; /* (r) last pop update tick. */
- popmap_t popmap[NPOPMAP_MAX]; /* (r) bit vector, used pages */
+ bitstr_t bit_decl(popmap, VM_LEVEL_0_NPAGES_MAX);
+ /* (r) bit vector, used pages */
};
TAILQ_HEAD(vm_reserv_queue, vm_reserv);
@@ -415,7 +361,6 @@
static void
vm_reserv_insert(vm_reserv_t rv, vm_object_t object, vm_pindex_t pindex)
{
- int i;
vm_reserv_assert_locked(rv);
CTR6(KTR_VM,
@@ -428,9 +373,8 @@
("vm_reserv_insert: reserv %p's popcnt is corrupted", rv));
KASSERT(!rv->inpartpopq,
("vm_reserv_insert: reserv %p's inpartpopq is TRUE", rv));
- for (i = 0; i < NPOPMAP; i++)
- KASSERT(rv->popmap[i] == 0,
- ("vm_reserv_insert: reserv %p's popmap is corrupted", rv));
+ KASSERT(bit_ntest(rv->popmap, 0, VM_LEVEL_0_NPAGES - 1, 0),
+ ("vm_reserv_insert: reserv %p's popmap is corrupted", rv));
vm_reserv_object_lock(object);
rv->pindex = pindex;
rv->object = object;
@@ -455,7 +399,7 @@
__FUNCTION__, rv, rv->object, rv->popcnt, rv->inpartpopq);
KASSERT(rv->object != NULL,
("vm_reserv_depopulate: reserv %p is free", rv));
- KASSERT(popmap_is_set(rv->popmap, index),
+ KASSERT(bit_test(rv->popmap, index),
("vm_reserv_depopulate: reserv %p's popmap[%d] is clear", rv,
index));
KASSERT(rv->popcnt > 0,
@@ -469,7 +413,7 @@
rv));
rv->pages->psind = 0;
}
- popmap_clear(rv->popmap, index);
+ bit_clear(rv->popmap, index);
rv->popcnt--;
if ((unsigned)(ticks - rv->lasttick) >= PARTPOPSLOP ||
rv->popcnt == 0) {
@@ -575,7 +519,7 @@
__FUNCTION__, rv, rv->object, rv->popcnt, rv->inpartpopq);
KASSERT(rv->object != NULL,
("vm_reserv_populate: reserv %p is free", rv));
- KASSERT(popmap_is_clear(rv->popmap, index),
+ KASSERT(!bit_test(rv->popmap, index),
("vm_reserv_populate: reserv %p's popmap[%d] is set", rv,
index));
KASSERT(rv->popcnt < VM_LEVEL_0_NPAGES,
@@ -585,7 +529,7 @@
KASSERT(rv->domain < vm_ndomains,
("vm_reserv_populate: reserv %p's domain is corrupted %d",
rv, rv->domain));
- popmap_set(rv->popmap, index);
+ bit_set(rv->popmap, index);
rv->popcnt++;
if ((unsigned)(ticks - rv->lasttick) < PARTPOPSLOP &&
rv->inpartpopq && rv->popcnt != VM_LEVEL_0_NPAGES)
@@ -684,9 +628,8 @@
!vm_addr_ok(pa, size, alignment, boundary))
goto out;
/* Handle vm_page_rename(m, new_object, ...). */
- for (i = 0; i < npages; i++)
- if (popmap_is_set(rv->popmap, index + i))
- goto out;
+ if (!bit_ntest(rv->popmap, index, index + npages - 1, 0))
+ goto out;
if (!vm_domain_allocate(vmd, req, npages))
goto out;
for (i = 0; i < npages; i++)
@@ -854,7 +797,7 @@
/* Handle reclaim race. */
if (rv->object != object ||
/* Handle vm_page_rename(m, new_object, ...). */
- popmap_is_set(rv->popmap, index)) {
+ bit_test(rv->popmap, index)) {
m = NULL;
goto out;
}
@@ -948,8 +891,7 @@
static void
vm_reserv_break(vm_reserv_t rv)
{
- u_long changes;
- int bitpos, hi, i, lo;
+ int hi, lo, pos;
vm_reserv_assert_locked(rv);
CTR5(KTR_VM, "%s: rv %p object %p popcnt %d inpartpop %d",
@@ -957,39 +899,24 @@
vm_reserv_remove(rv);
rv->pages->psind = 0;
hi = lo = -1;
- for (i = 0; i <= NPOPMAP; i++) {
- /*
- * "changes" is a bitmask that marks where a new sequence of
- * 0s or 1s begins in popmap[i], with last bit in popmap[i-1]
- * considered to be 1 if and only if lo == hi. The bits of
- * popmap[-1] and popmap[NPOPMAP] are considered all 1s.
- */
- if (i == NPOPMAP)
- changes = lo != hi;
- else {
- changes = rv->popmap[i];
- changes ^= (changes << 1) | (lo == hi);
- rv->popmap[i] = 0;
- }
- while (changes != 0) {
- /*
- * If the next change marked begins a run of 0s, set
- * lo to mark that position. Otherwise set hi and
- * free pages from lo up to hi.
- */
- bitpos = ffsl(changes) - 1;
- changes ^= 1UL << bitpos;
- if (lo == hi)
- lo = NBPOPMAP * i + bitpos;
- else {
- hi = NBPOPMAP * i + bitpos;
- vm_domain_free_lock(VM_DOMAIN(rv->domain));
- vm_phys_enqueue_contig(&rv->pages[lo], hi - lo);
- vm_domain_free_unlock(VM_DOMAIN(rv->domain));
- lo = hi;
- }
+ pos = 0;
+ for (;;) {
+ bit_ff_at(rv->popmap, pos, VM_LEVEL_0_NPAGES, lo != hi, &pos);
+ if (lo == hi) {
+ if (pos == -1)
+ break;
+ lo = pos;
+ continue;
}
+ if (pos == -1)
+ pos = VM_LEVEL_0_NPAGES;
+ hi = pos;
+ vm_domain_free_lock(VM_DOMAIN(rv->domain));
+ vm_phys_enqueue_contig(&rv->pages[lo], hi - lo);
+ vm_domain_free_unlock(VM_DOMAIN(rv->domain));
+ lo = hi;
}
+ bit_nclear(rv->popmap, 0, VM_LEVEL_0_NPAGES - 1);
rv->popcnt = 0;
counter_u64_add(vm_reserv_broken, 1);
}
@@ -1068,7 +995,7 @@
#ifdef VM_PHYSSEG_SPARSE
vm_pindex_t used;
#endif
- int i, j, segind;
+ int i, segind;
/*
* Initialize the reservation array. Specifically, initialize the
@@ -1110,8 +1037,7 @@
* partially populated reservation queues.
*/
rvd->marker.popcnt = VM_LEVEL_0_NPAGES;
- for (j = 0; j < VM_LEVEL_0_NPAGES; j++)
- popmap_set(rvd->marker.popmap, j);
+ bit_nset(rvd->marker.popmap, 0, VM_LEVEL_0_NPAGES - 1);
}
for (i = 0; i < VM_RESERV_OBJ_LOCK_COUNT; i++)
@@ -1131,7 +1057,7 @@
rv = vm_reserv_from_page(m);
if (rv->object == NULL)
return (false);
- return (popmap_is_clear(rv->popmap, m - rv->pages));
+ return (!bit_test(rv->popmap, m - rv->pages));
}
/*
@@ -1238,8 +1164,6 @@
vm_reserv_find_contig(vm_reserv_t rv, int npages, int lo,
int hi, int ppn_align, int ppn_bound)
{
- u_long changes;
- int bitpos, bits_left, i, n;
vm_reserv_assert_locked(rv);
KASSERT(npages <= VM_LEVEL_0_NPAGES - 1,
@@ -1252,56 +1176,18 @@
("ppn_align is not a positive power of 2"));
KASSERT(ppn_bound != 0 && powerof2(ppn_bound),
("ppn_bound is not a positive power of 2"));
- i = lo / NBPOPMAP;
- changes = rv->popmap[i] | ((1UL << (lo % NBPOPMAP)) - 1);
- n = hi / NBPOPMAP;
- bits_left = hi % NBPOPMAP;
- hi = lo = -1;
- for (;;) {
- /*
- * "changes" is a bitmask that marks where a new sequence of
- * 0s or 1s begins in popmap[i], with last bit in popmap[i-1]
- * considered to be 1 if and only if lo == hi. The bits of
- * popmap[-1] and popmap[NPOPMAP] are considered all 1s.
- */
- changes ^= (changes << 1) | (lo == hi);
- while (changes != 0) {
- /*
- * If the next change marked begins a run of 0s, set
- * lo to mark that position. Otherwise set hi and
- * look for a satisfactory first page from lo up to hi.
- */
- bitpos = ffsl(changes) - 1;
- changes ^= 1UL << bitpos;
- if (lo == hi) {
- lo = NBPOPMAP * i + bitpos;
- continue;
- }
- hi = NBPOPMAP * i + bitpos;
- if (lo < roundup2(lo, ppn_align)) {
- /* Skip to next aligned page. */
- lo = roundup2(lo, ppn_align);
- if (lo >= VM_LEVEL_0_NPAGES)
- return (-1);
- }
- if (lo + npages > roundup2(lo, ppn_bound)) {
- /* Skip to next boundary-matching page. */
- lo = roundup2(lo, ppn_bound);
- if (lo >= VM_LEVEL_0_NPAGES)
- return (-1);
- }
- if (lo + npages <= hi)
- return (lo);
- lo = hi;
+ while (bit_ffc_area_at(rv->popmap, lo, hi, npages, &lo), lo != -1) {
+ if (lo < roundup2(lo, ppn_align)) {
+ /* Skip to next aligned page. */
+ lo = roundup2(lo, ppn_align);
+ } else if (roundup2(lo + 1, ppn_bound) >= lo + npages)
+ return (lo);
+ if (roundup2(lo + 1, ppn_bound) < lo + npages) {
+ /* Skip to next boundary-matching page. */
+ lo = roundup2(lo + 1, ppn_bound);
}
- if (++i < n)
- changes = rv->popmap[i];
- else if (i == n)
- changes = bits_left == 0 ? -1UL :
- (rv->popmap[n] | (-1UL << bits_left));
- else
- return (-1);
}
+ return (-1);
}
/*
@@ -1389,8 +1275,7 @@
vm_reserv_domain_scan_unlock(domain);
/* Allocate requested space */
rv->popcnt += npages;
- while (npages-- > 0)
- popmap_set(rv->popmap, posn + npages);
+ bit_nset(rv->popmap, posn, posn + npages - 1);
vm_reserv_reclaim(rv);
vm_reserv_unlock(rv);
m_ret = &rv->pages[posn];
diff --git a/tests/sys/sys/bitstring_test.c b/tests/sys/sys/bitstring_test.c
--- a/tests/sys/sys/bitstring_test.c
+++ b/tests/sys/sys/bitstring_test.c
@@ -352,20 +352,23 @@
memset(bitstr, 0, bitstr_size(nbits));
- bit_set(bitstr, 5);
- bit_set(bitstr, 6);
+ bit_nset(bitstr, 5, 6);
location = 0;
bit_ffs_area(bitstr, nbits, 3, &location);
ATF_REQUIRE_EQ_MSG(-1, location,
- "bit_ffs_area: found location of size 3 when only 2 bits are set");
+ "bit_ffs_area: found location of size 3 when only 2 bits are set");
+ ATF_REQUIRE_EQ_MSG(0, bit_ntest(bitstr, 5, 7, 1),
+ "bit_ntest: found location of size 3 when only 2 bits are set");
bit_set(bitstr, 7);
location = 0;
bit_ffs_area(bitstr, nbits, 3, &location);
ATF_REQUIRE_EQ_MSG(5, location,
- "bit_ffs_area: failed to find location of size 3");
+ "bit_ffs_area: failed to find location of size 3 %d", location);
+ ATF_REQUIRE_EQ_MSG(1, bit_ntest(bitstr, 5, 7, 1),
+ "bit_ntest: failed to find all 3 bits set");
bit_set(bitstr, 8);
@@ -389,9 +392,7 @@
ATF_REQUIRE_EQ_MSG(-1, location,
"bit_ffs_area_at: found invalid location");
- bit_set(bitstr, 69);
- bit_set(bitstr, 70);
- bit_set(bitstr, 71);
+ bit_nset(bitstr, 69, 71);
location = 0;
bit_ffs_area_at(bitstr, 8, nbits, 3, &location);
@@ -412,6 +413,18 @@
bit_ffs_area_at(bitstr, 72, nbits, 3, &location);
ATF_REQUIRE_EQ_MSG(-1, location,
"bit_ffs_area_at: found invalid location");
+
+ bit_nset(bitstr, 59, 67);
+
+ location = 0;
+ bit_ffs_area(bitstr, nbits, 9, &location);
+ ATF_REQUIRE_EQ_MSG(59, location,
+ "bit_ffs_area: failed to find location of size 9");
+
+ location = 0;
+ bit_ffs_area(bitstr, nbits, 10, &location);
+ ATF_REQUIRE_EQ_MSG(-1, location,
+ "bit_ffs_area: found invalid location");
}
ATF_TC_WITHOUT_HEAD(bit_ffc_area);

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 15, 12:09 AM (9 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14635566
Default Alt Text
D33312.diff (23 KB)

Event Timeline