mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-04 22:49:32 +03:00
use free field for expiration instead of used
This commit is contained in:
parent
60c4a0fe56
commit
4f809aadb7
3 changed files with 49 additions and 35 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue