Changeset View
Changeset View
Standalone View
Standalone View
head/sys/vm/vm_reserv.c
Show First 20 Lines • Show All 1,024 Lines • ▼ Show 20 Lines | |||||
* population count and map are reset to their initial state. | * population count and map are reset to their initial state. | ||||
* | * | ||||
* The given reservation must not be in the partially populated reservation | * The given reservation must not be in the partially populated reservation | ||||
* queue. The free page queue lock must be held. | * queue. The free page queue lock must be held. | ||||
*/ | */ | ||||
static void | static void | ||||
vm_reserv_break(vm_reserv_t rv) | vm_reserv_break(vm_reserv_t rv) | ||||
{ | { | ||||
int begin_zeroes, hi, i, lo; | u_long changes; | ||||
int bitpos, hi, i, lo; | |||||
vm_reserv_assert_locked(rv); | vm_reserv_assert_locked(rv); | ||||
CTR5(KTR_VM, "%s: rv %p object %p popcnt %d inpartpop %d", | CTR5(KTR_VM, "%s: rv %p object %p popcnt %d inpartpop %d", | ||||
__FUNCTION__, rv, rv->object, rv->popcnt, rv->inpartpopq); | __FUNCTION__, rv, rv->object, rv->popcnt, rv->inpartpopq); | ||||
vm_reserv_remove(rv); | vm_reserv_remove(rv); | ||||
rv->pages->psind = 0; | rv->pages->psind = 0; | ||||
i = hi = 0; | hi = lo = -1; | ||||
do { | for (i = 0; i <= NPOPMAP; i++) { | ||||
/* Find the next 0 bit. Any previous 0 bits are < "hi". */ | /* | ||||
lo = ffsl(~(((1UL << hi) - 1) | rv->popmap[i])); | * "changes" is a bitmask that marks where a new sequence of | ||||
if (lo == 0) { | * 0s or 1s begins in popmap[i], with last bit in popmap[i-1] | ||||
/* Redundantly clears bits < "hi". */ | * 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; | rv->popmap[i] = 0; | ||||
rv->popcnt -= NBPOPMAP - hi; | |||||
while (++i < NPOPMAP) { | |||||
lo = ffsl(~rv->popmap[i]); | |||||
if (lo == 0) { | |||||
rv->popmap[i] = 0; | |||||
rv->popcnt -= NBPOPMAP; | |||||
} else | |||||
break; | |||||
} | } | ||||
if (i == NPOPMAP) | while (changes != 0) { | ||||
break; | /* | ||||
hi = 0; | * If the next change marked begins a run of 0s, set | ||||
} | * lo to mark that position. Otherwise set hi and | ||||
KASSERT(lo > 0, ("vm_reserv_break: lo is %d", lo)); | * free pages from lo up to hi. | ||||
/* Convert from ffsl() to ordinary bit numbering. */ | */ | ||||
lo--; | bitpos = ffsl(changes) - 1; | ||||
if (lo > 0) { | changes ^= 1UL << bitpos; | ||||
/* Redundantly clears bits < "hi". */ | if (lo == hi) | ||||
rv->popmap[i] &= ~((1UL << lo) - 1); | lo = NBPOPMAP * i + bitpos; | ||||
rv->popcnt -= lo - hi; | else { | ||||
} | hi = NBPOPMAP * i + bitpos; | ||||
begin_zeroes = NBPOPMAP * i + lo; | |||||
/* Find the next 1 bit. */ | |||||
do | |||||
hi = ffsl(rv->popmap[i]); | |||||
while (hi == 0 && ++i < NPOPMAP); | |||||
if (i != NPOPMAP) | |||||
/* Convert from ffsl() to ordinary bit numbering. */ | |||||
hi--; | |||||
vm_domain_free_lock(VM_DOMAIN(rv->domain)); | vm_domain_free_lock(VM_DOMAIN(rv->domain)); | ||||
vm_phys_free_contig(&rv->pages[begin_zeroes], NBPOPMAP * i + | vm_phys_free_contig(&rv->pages[lo], hi - lo); | ||||
hi - begin_zeroes); | |||||
vm_domain_free_unlock(VM_DOMAIN(rv->domain)); | vm_domain_free_unlock(VM_DOMAIN(rv->domain)); | ||||
} while (i < NPOPMAP); | lo = hi; | ||||
KASSERT(rv->popcnt == 0, | } | ||||
("vm_reserv_break: reserv %p's popcnt is corrupted", rv)); | } | ||||
} | |||||
rv->popcnt = 0; | |||||
counter_u64_add(vm_reserv_broken, 1); | counter_u64_add(vm_reserv_broken, 1); | ||||
} | } | ||||
/* | /* | ||||
* Breaks all reservations belonging to the given object. | * Breaks all reservations belonging to the given object. | ||||
*/ | */ | ||||
void | void | ||||
vm_reserv_break_all(vm_object_t object) | vm_reserv_break_all(vm_object_t object) | ||||
▲ Show 20 Lines • Show All 419 Lines • Show Last 20 Lines |