mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-05 06:59: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;
|
size_t diff;
|
||||||
if mi_likely(page->block_offset_adj != 0) {
|
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 {
|
else {
|
||||||
diff = (uint8_t*)p - _mi_page_start(segment, page, NULL);
|
diff = (uint8_t*)p - _mi_page_start(segment, page, NULL);
|
||||||
|
|
13
src/page.c
13
src/page.c
|
@ -676,16 +676,17 @@ 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));
|
mi_assert_expensive(!page->is_zero_init || mi_mem_is_zero(page_start, page_size));
|
||||||
}
|
}
|
||||||
#endif
|
#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));
|
page->block_size_shift = (uint8_t)(mi_ctz((uintptr_t)block_size));
|
||||||
}
|
}
|
||||||
const ptrdiff_t start_offset = (uint8_t*)page_start - (uint8_t*)page;
|
if (block_size > 0) {
|
||||||
const ptrdiff_t start_adjust = start_offset % block_size;
|
const ptrdiff_t start_offset = (uint8_t*)page_start - (uint8_t*)page;
|
||||||
if (start_offset >= 0 && (start_adjust % 8) == 0 && (start_adjust/8) < 255) {
|
const ptrdiff_t start_adjust = start_offset % block_size;
|
||||||
page->block_offset_adj = (uint8_t)((start_adjust/8) + 1);
|
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->capacity == 0);
|
||||||
mi_assert_internal(page->free == NULL);
|
mi_assert_internal(page->free == NULL);
|
||||||
mi_assert_internal(page->used == 0);
|
mi_assert_internal(page->used == 0);
|
||||||
|
|
|
@ -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);
|
mi_assert_internal(!page->segment_in_use);
|
||||||
if (!segment->allow_purge) return;
|
if (!segment->allow_purge) return;
|
||||||
mi_assert_internal(page->used == 0);
|
mi_assert_internal(page->used == 0);
|
||||||
|
mi_assert_internal(page->free == NULL);
|
||||||
mi_assert_expensive(!mi_pages_purge_contains(page, tld));
|
mi_assert_expensive(!mi_pages_purge_contains(page, tld));
|
||||||
size_t psize;
|
size_t psize;
|
||||||
void* start = mi_segment_raw_page_start(segment, page, &psize);
|
void* start = mi_segment_raw_page_start(segment, page, &psize);
|
||||||
const bool needs_recommit = _mi_os_purge(start, psize, tld->stats);
|
const bool needs_recommit = _mi_os_purge(start, psize, tld->stats);
|
||||||
if (needs_recommit) { page->is_committed = false; }
|
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) {
|
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!
|
if (!ok) return false; // failed to commit!
|
||||||
page->is_committed = true;
|
page->is_committed = true;
|
||||||
page->used = 0;
|
page->used = 0;
|
||||||
|
page->free = NULL;
|
||||||
page->is_zero_init = is_zero;
|
page->is_zero_init = is_zero;
|
||||||
if (gsize > 0) {
|
if (gsize > 0) {
|
||||||
mi_segment_protect_range(start + psize, gsize, true);
|
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
|
The free page queue
|
||||||
----------------------------------------------------------- */
|
----------------------------------------------------------- */
|
||||||
|
|
||||||
// we re-use the `used` field for the expiration counter. Since this is a
|
// we re-use the `free` field for the expiration counter. Since this is a
|
||||||
// a 32-bit field while the clock is always 64-bit we need to guard
|
// 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
|
// 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)
|
// 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) {
|
static uint32_t mi_page_get_expire( mi_page_t* page ) {
|
||||||
mi_assert_internal(page->used == 0);
|
return (uint32_t)((uintptr_t)page->free);
|
||||||
uint32_t expire = (uint32_t)_mi_clock_now() + mi_option_get(mi_option_purge_delay);
|
|
||||||
page->used = expire;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
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);
|
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_page_queue_t* pq = &tld->pages_purge;
|
||||||
mi_assert_internal(pq!=NULL);
|
mi_assert_internal(pq!=NULL);
|
||||||
mi_assert_internal(!page->segment_in_use);
|
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));
|
mi_assert_internal(mi_pages_purge_contains(page, tld));
|
||||||
if (page->prev != NULL) page->prev->next = page->next;
|
if (page->prev != NULL) page->prev->next = page->next;
|
||||||
if (page->next != NULL) page->next->prev = page->prev;
|
if (page->next != NULL) page->next->prev = page->prev;
|
||||||
if (page == pq->last) pq->last = page->prev;
|
if (page == pq->last) pq->last = page->prev;
|
||||||
if (page == pq->first) pq->first = page->next;
|
if (page == pq->first) pq->first = page->next;
|
||||||
page->next = page->prev = NULL;
|
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) {
|
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