mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-23 13:13:06 +00:00
Move hpdata bitmap logic out of the psset.
This commit is contained in:
committed by
David Goldblatt
parent
ca30b5db2b
commit
089f8fa442
96
src/hpdata.c
96
src/hpdata.c
@@ -16,3 +16,99 @@ hpdata_age_comp(const hpdata_t *a, const hpdata_t *b) {
|
||||
}
|
||||
|
||||
ph_gen(, hpdata_age_heap_, hpdata_age_heap_t, hpdata_t, ph_link, hpdata_age_comp)
|
||||
|
||||
|
||||
void
|
||||
hpdata_init(hpdata_t *hpdata, void *addr, uint64_t age) {
|
||||
hpdata_addr_set(hpdata, addr);
|
||||
hpdata_age_set(hpdata, age);
|
||||
hpdata_huge_set(hpdata, false);
|
||||
hpdata_nfree_set(hpdata, HUGEPAGE_PAGES);
|
||||
hpdata_longest_free_range_set(hpdata, HUGEPAGE_PAGES);
|
||||
fb_init(hpdata->active_pages, HUGEPAGE_PAGES);
|
||||
}
|
||||
|
||||
size_t
|
||||
hpdata_reserve_alloc(hpdata_t *hpdata, size_t npages) {
|
||||
assert(npages <= hpdata_longest_free_range_get(hpdata));
|
||||
|
||||
size_t result;
|
||||
|
||||
size_t start = 0;
|
||||
/*
|
||||
* These are dead stores, but the compiler will issue warnings on them
|
||||
* since it can't tell statically that found is always true below.
|
||||
*/
|
||||
size_t begin = 0;
|
||||
size_t len = 0;
|
||||
|
||||
size_t largest_unchosen_range = 0;
|
||||
while (true) {
|
||||
bool found = fb_urange_iter(hpdata->active_pages,
|
||||
HUGEPAGE_PAGES, start, &begin, &len);
|
||||
/*
|
||||
* A precondition to this function is that hpdata must be able
|
||||
* to serve the allocation.
|
||||
*/
|
||||
assert(found);
|
||||
if (len >= npages) {
|
||||
/*
|
||||
* We use first-fit within the page slabs; this gives
|
||||
* bounded worst-case fragmentation within a slab. It's
|
||||
* not necessarily right; we could experiment with
|
||||
* various other options.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
if (len > largest_unchosen_range) {
|
||||
largest_unchosen_range = len;
|
||||
}
|
||||
start = begin + len;
|
||||
}
|
||||
/* We found a range; remember it. */
|
||||
result = begin;
|
||||
fb_set_range(hpdata->active_pages, HUGEPAGE_PAGES, begin, npages);
|
||||
hpdata_nfree_set(hpdata, hpdata_nfree_get(hpdata) - npages);
|
||||
|
||||
/*
|
||||
* We might have shrunk the longest free range. We have to keep
|
||||
* scanning until the end of the hpdata to be sure.
|
||||
*
|
||||
* TODO: As an optimization, we should only do this when the range we
|
||||
* just allocated from was equal to the longest free range size.
|
||||
*/
|
||||
start = begin + npages;
|
||||
while (start < HUGEPAGE_PAGES) {
|
||||
bool found = fb_urange_iter(hpdata->active_pages,
|
||||
HUGEPAGE_PAGES, start, &begin, &len);
|
||||
if (!found) {
|
||||
break;
|
||||
}
|
||||
if (len > largest_unchosen_range) {
|
||||
largest_unchosen_range = len;
|
||||
}
|
||||
start = begin + len;
|
||||
}
|
||||
hpdata_longest_free_range_set(hpdata, largest_unchosen_range);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
hpdata_unreserve(hpdata_t *hpdata, size_t begin, size_t npages) {
|
||||
size_t old_longest_range = hpdata_longest_free_range_get(hpdata);
|
||||
|
||||
fb_unset_range(hpdata->active_pages, HUGEPAGE_PAGES, begin, npages);
|
||||
/* We might have just created a new, larger range. */
|
||||
size_t new_begin = (fb_fls(hpdata->active_pages, HUGEPAGE_PAGES,
|
||||
begin) + 1);
|
||||
size_t new_end = fb_ffs(hpdata->active_pages, HUGEPAGE_PAGES,
|
||||
begin + npages - 1);
|
||||
size_t new_range_len = new_end - new_begin;
|
||||
|
||||
if (new_range_len > old_longest_range) {
|
||||
hpdata_longest_free_range_set(hpdata, new_range_len);
|
||||
}
|
||||
|
||||
hpdata_nfree_set(hpdata, hpdata_nfree_get(hpdata) + npages);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user