use free field for expiration instead of used

This commit is contained in:
Daan Leijen 2024-03-24 08:29:56 -07:00
parent 60c4a0fe56
commit 4f809aadb7
3 changed files with 49 additions and 35 deletions

View file

@ -57,7 +57,7 @@ mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* p
size_t diff;
if mi_likely(page->block_offset_adj != 0) {
diff = (uint8_t*)p - (uint8_t*)page - 8 * (page->block_offset_adj - 1);
diff = (uint8_t*)p - (uint8_t*)page - (8*(page->block_offset_adj - 1));
}
else {
diff = (uint8_t*)p - _mi_page_start(segment, page, NULL);

View file

@ -676,15 +676,16 @@ static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi
mi_assert_expensive(!page->is_zero_init || mi_mem_is_zero(page_start, page_size));
}
#endif
if (_mi_is_power_of_two(block_size) && block_size > 0) {
if (block_size > 0 && _mi_is_power_of_two(block_size)) {
page->block_size_shift = (uint8_t)(mi_ctz((uintptr_t)block_size));
}
if (block_size > 0) {
const ptrdiff_t start_offset = (uint8_t*)page_start - (uint8_t*)page;
const ptrdiff_t start_adjust = start_offset % block_size;
if (start_offset >= 0 && (start_adjust % 8) == 0 && (start_adjust/8) < 255) {
page->block_offset_adj = (uint8_t)((start_adjust/8) + 1);
}
}
mi_assert_internal(page->capacity == 0);
mi_assert_internal(page->free == NULL);

View file

@ -237,12 +237,12 @@ static void mi_page_purge(mi_segment_t* segment, mi_page_t* page, mi_segments_tl
mi_assert_internal(!page->segment_in_use);
if (!segment->allow_purge) return;
mi_assert_internal(page->used == 0);
mi_assert_internal(page->free == NULL);
mi_assert_expensive(!mi_pages_purge_contains(page, tld));
size_t psize;
void* start = mi_segment_raw_page_start(segment, page, &psize);
const bool needs_recommit = _mi_os_purge(start, psize, tld->stats);
if (needs_recommit) { page->is_committed = false; }
page->used = 0;
}
static bool mi_page_ensure_committed(mi_segment_t* segment, mi_page_t* page, mi_segments_tld_t* tld) {
@ -258,6 +258,7 @@ static bool mi_page_ensure_committed(mi_segment_t* segment, mi_page_t* page, mi_
if (!ok) return false; // failed to commit!
page->is_committed = true;
page->used = 0;
page->free = NULL;
page->is_zero_init = is_zero;
if (gsize > 0) {
mi_segment_protect_range(start + psize, gsize, true);
@ -270,18 +271,30 @@ static bool mi_page_ensure_committed(mi_segment_t* segment, mi_page_t* page, mi_
The free page queue
----------------------------------------------------------- */
// we re-use the `used` field for the expiration counter. Since this is a
// a 32-bit field while the clock is always 64-bit we need to guard
// against overflow, we use substraction to check for expiry which work
// we re-use the `free` field for the expiration counter. Since this is a
// a pointer size field while the clock is always 64-bit we need to guard
// against overflow, we use substraction to check for expiry which works
// as long as the reset delay is under (2^30 - 1) milliseconds (~12 days)
static void mi_page_purge_set_expire(mi_page_t* page) {
mi_assert_internal(page->used == 0);
uint32_t expire = (uint32_t)_mi_clock_now() + mi_option_get(mi_option_purge_delay);
page->used = expire;
static uint32_t mi_page_get_expire( mi_page_t* page ) {
return (uint32_t)((uintptr_t)page->free);
}
static void mi_page_set_expire( mi_page_t* page, uint32_t expire ) {
page->free = (mi_block_t*)((uintptr_t)expire);
}
static void mi_page_purge_set_expire(mi_page_t* page) {
mi_assert_internal(mi_page_get_expire(page)==0);
uint32_t expire = (uint32_t)_mi_clock_now() + mi_option_get(mi_option_purge_delay);
mi_page_set_expire(page, expire);
}
// we re-use the `free` field for the expiration counter. Since this is a
// a pointer size field while the clock is always 64-bit we need to guard
// against overflow, we use substraction to check for expiry which work
// as long as the reset delay is under (2^30 - 1) milliseconds (~12 days)
static bool mi_page_purge_is_expired(mi_page_t* page, mi_msecs_t now) {
int32_t expire = (int32_t)(page->used);
int32_t expire = (int32_t)mi_page_get_expire(page);
return (((int32_t)now - expire) >= 0);
}
@ -320,14 +333,14 @@ static void mi_page_purge_remove(mi_page_t* page, mi_segments_tld_t* tld) {
mi_page_queue_t* pq = &tld->pages_purge;
mi_assert_internal(pq!=NULL);
mi_assert_internal(!page->segment_in_use);
mi_assert_internal(page->used != 0);
mi_assert_internal(mi_page_get_expire(page) != 0);
mi_assert_internal(mi_pages_purge_contains(page, tld));
if (page->prev != NULL) page->prev->next = page->next;
if (page->next != NULL) page->next->prev = page->prev;
if (page == pq->last) pq->last = page->prev;
if (page == pq->first) pq->first = page->next;
page->next = page->prev = NULL;
page->used = 0;
mi_page_set_expire(page,0);
}
static void mi_segment_remove_all_purges(mi_segment_t* segment, bool force_purge, mi_segments_tld_t* tld) {