/* Allocating a page at a time, we should do first fit. */
for (size_t i = 0; i < HUGEPAGE_PAGES; i++) {
expect_true(hpdata_consistent(&hpdata), "");
expect_zu_eq(HUGEPAGE_PAGES - i,
hpdata_longest_free_range_get(&hpdata), "");
void *alloc = hpdata_reserve_alloc(&hpdata, PAGE);
expect_ptr_eq((char *)HPDATA_ADDR + i * PAGE, alloc, "");
expect_true(hpdata_consistent(&hpdata), "");
}
expect_true(hpdata_consistent(&hpdata), "");
expect_zu_eq(0, hpdata_longest_free_range_get(&hpdata), "");
/*
* Build up a bigger free-range, 2 pages at a time, until we've got 6
* adjacent free pages total. Pages 8-13 should be unreserved after
* this.
*/
hpdata_unreserve(&hpdata, (char *)HPDATA_ADDR + 10 * PAGE, 2 * PAGE);
expect_true(hpdata_consistent(&hpdata), "");
expect_zu_eq(2, hpdata_longest_free_range_get(&hpdata), "");
/*
* Leave page 14 reserved, but free page 15 (this test the case where
* unreserving combines two ranges).
*/
hpdata_unreserve(&hpdata, (char *)HPDATA_ADDR + 15 * PAGE, PAGE);
/*
* Longest free range shouldn't change; we've got a free range of size
* 6, then a reserved page, then another free range.
*/
expect_true(hpdata_consistent(&hpdata), "");
expect_zu_eq(6, hpdata_longest_free_range_get(&hpdata), "");
/* After freeing page 14, the two ranges get combined. */
hpdata_unreserve(&hpdata, (char *)HPDATA_ADDR + 14 * PAGE, PAGE);
expect_true(hpdata_consistent(&hpdata), "");
expect_zu_eq(8, hpdata_longest_free_range_get(&hpdata), "");
}
TEST_END
/*
* We only test intervening dalloc's not intervening allocs; the latter are
* disallowed as a purging precondition (because they interfere with purging
* across a retained extent, saving a purge call).
*/
TEST_BEGIN(test_purge_intervening_dalloc) {
hpdata_t hpdata;
hpdata_init(&hpdata, HPDATA_ADDR, HPDATA_AGE);
/* Allocate the first 3/4 of the pages. */
void *alloc = hpdata_reserve_alloc(&hpdata, 3 * HUGEPAGE_PAGES / 4 * PAGE);
expect_ptr_eq(alloc, HPDATA_ADDR, "");
/* Free the first 1/4 and the third 1/4 of the pages. */
hpdata_unreserve(&hpdata, alloc, HUGEPAGE_PAGES / 4 * PAGE);
hpdata_unreserve(&hpdata,
(void *)((uintptr_t)alloc + 2 * HUGEPAGE_PAGES / 4 * PAGE),
HUGEPAGE_PAGES / 4 * PAGE);
/* Free the first and third quarter. */
hpdata_unreserve(&hpdata, HPDATA_ADDR, HUGEPAGE_PAGES / 4 * PAGE);
hpdata_unreserve(&hpdata,
(void *)((uintptr_t)alloc + 2 * HUGEPAGE_PAGES / 4 * PAGE),
HUGEPAGE_PAGES / 4 * PAGE);
/*
* Purge again. The second quarter is retained, so we can safely
* re-purge it. We expect a single purge of 3/4 of the hugepage,
* purging half its pages.
*/
to_purge_dirty = hpdata_purge_begin(&hpdata, &purge_state);
expect_zu_eq(HUGEPAGE_PAGES / 2, to_purge_dirty, "");