in freelist.go [175:220]
func (f *freelist) AllocRegionsWith(order *allocOrder, n uint, fn func(region)) {
if n == 0 {
return
}
var (
last int // last region to allocate from
L = len(f.regions)
N = n // number of pages to be allocated from 'last' region
)
if N > f.avail {
// not enough space -> return early
return
}
// Collect indices of regions to be allocated from.
for i, end, next := order.iter(L); i != end; i = next(i) {
count := uint(f.regions[i].count)
if count >= N {
last = i
break
}
N -= count
}
// Compute region split on last region to be allocated from.
selected := f.regions[last]
allocated, leftover := order.allocFromRegion(selected, uint32(N))
invariant.Check(allocated.count == uint32(N), "allocation mismatch")
invariant.Check(allocated.count+leftover.count == selected.count, "region split page count mismatch")
// Implicitely update last allocated region to match the allocation size
// and report all regions allocated.
f.regions[last] = allocated
for i, end := order.reportRange(last, L); i != end; i++ {
fn(f.regions[i])
}
// update free regions
f.regions[last] = leftover
start, end := order.keepRange(last, L, leftover.count != 0)
f.regions = f.regions[start:end]
f.avail -= n
}