mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-05 15:09:31 +03:00
improve encoding of padding canary and buffer overflow detection
This commit is contained in:
parent
40f1e1e07b
commit
aa68b8cbc7
6 changed files with 78 additions and 66 deletions
|
@ -519,30 +519,37 @@ static inline uintptr_t mi_rotr(uintptr_t x, uintptr_t shift) {
|
||||||
return ((x >> shift) | (x << (MI_INTPTR_BITS - shift)));
|
return ((x >> shift) | (x << (MI_INTPTR_BITS - shift)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline mi_block_t* mi_block_nextx( const void* null, const mi_block_t* block, uintptr_t key1, uintptr_t key2 ) {
|
static inline void* mi_ptr_decode(const void* null, const mi_encoded_t x, const uintptr_t* keys) {
|
||||||
|
void* p = (void*)(mi_rotr(x - keys[0], keys[0]) ^ keys[1]);
|
||||||
|
return (mi_unlikely(p==null) ? NULL : p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline mi_encoded_t mi_ptr_encode(const void* null, const void* p, const uintptr_t* keys) {
|
||||||
|
uintptr_t x = (uintptr_t)(mi_unlikely(p==NULL) ? null : p);
|
||||||
|
return mi_rotl(x ^ keys[1], keys[0]) + keys[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline mi_block_t* mi_block_nextx( const void* null, const mi_block_t* block, const uintptr_t* keys ) {
|
||||||
#ifdef MI_ENCODE_FREELIST
|
#ifdef MI_ENCODE_FREELIST
|
||||||
mi_block_t* b = (mi_block_t*)(mi_rotr(block->next - key1, key1) ^ key2);
|
return (mi_block_t*)mi_ptr_decode(null, block->next, keys);
|
||||||
if (mi_unlikely((void*)b==null)) { b = NULL; }
|
|
||||||
return b;
|
|
||||||
#else
|
#else
|
||||||
UNUSED(key1); UNUSED(key2); UNUSED(null);
|
UNUSED(keys); UNUSED(null);
|
||||||
return (mi_block_t*)block->next;
|
return (mi_block_t*)block->next;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mi_block_set_nextx(const void* null, mi_block_t* block, const mi_block_t* next, uintptr_t key1, uintptr_t key2) {
|
static inline void mi_block_set_nextx(const void* null, mi_block_t* block, const mi_block_t* next, const uintptr_t* keys) {
|
||||||
#ifdef MI_ENCODE_FREELIST
|
#ifdef MI_ENCODE_FREELIST
|
||||||
if (mi_unlikely(next==NULL)) { next = (mi_block_t*)null; }
|
block->next = mi_ptr_encode(null, next, keys);
|
||||||
block->next = mi_rotl((uintptr_t)next ^ key2, key1) + key1;
|
|
||||||
#else
|
#else
|
||||||
UNUSED(key1); UNUSED(key2); UNUSED(null);
|
UNUSED(keys); UNUSED(null);
|
||||||
block->next = (mi_encoded_t)next;
|
block->next = (mi_encoded_t)next;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline mi_block_t* mi_block_next(const mi_page_t* page, const mi_block_t* block) {
|
static inline mi_block_t* mi_block_next(const mi_page_t* page, const mi_block_t* block) {
|
||||||
#ifdef MI_ENCODE_FREELIST
|
#ifdef MI_ENCODE_FREELIST
|
||||||
mi_block_t* next = mi_block_nextx(page,block,page->key[0],page->key[1]);
|
mi_block_t* next = mi_block_nextx(page,block,page->keys);
|
||||||
// check for free list corruption: is `next` at least in the same page?
|
// check for free list corruption: is `next` at least in the same page?
|
||||||
// TODO: check if `next` is `page->block_size` aligned?
|
// TODO: check if `next` is `page->block_size` aligned?
|
||||||
if (mi_unlikely(next!=NULL && !mi_is_in_same_page(block, next))) {
|
if (mi_unlikely(next!=NULL && !mi_is_in_same_page(block, next))) {
|
||||||
|
@ -552,16 +559,16 @@ static inline mi_block_t* mi_block_next(const mi_page_t* page, const mi_block_t*
|
||||||
return next;
|
return next;
|
||||||
#else
|
#else
|
||||||
UNUSED(page);
|
UNUSED(page);
|
||||||
return mi_block_nextx(page,block,0,0);
|
return mi_block_nextx(page,block,NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mi_block_set_next(const mi_page_t* page, mi_block_t* block, const mi_block_t* next) {
|
static inline void mi_block_set_next(const mi_page_t* page, mi_block_t* block, const mi_block_t* next) {
|
||||||
#ifdef MI_ENCODE_FREELIST
|
#ifdef MI_ENCODE_FREELIST
|
||||||
mi_block_set_nextx(page,block,next, page->key[0], page->key[1]);
|
mi_block_set_nextx(page,block,next, page->keys);
|
||||||
#else
|
#else
|
||||||
UNUSED(page);
|
UNUSED(page);
|
||||||
mi_block_set_nextx(page,block, next,0,0);
|
mi_block_set_nextx(page,block,next,NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,25 +48,24 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Reserve extra padding at the end of each block to be more resilient against heap block overflows.
|
||||||
|
// The padding can detect byte-precise buffer overflow on free.
|
||||||
|
#if !defined(MI_PADDING) && (MI_DEBUG>=1)
|
||||||
|
#define MI_PADDING 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Encoded free lists allow detection of corrupted free lists
|
// Encoded free lists allow detection of corrupted free lists
|
||||||
// and can detect buffer overflows, modify after free, and double `free`s.
|
// and can detect buffer overflows, modify after free, and double `free`s.
|
||||||
#if (MI_SECURE>=3 || MI_DEBUG>=1)
|
#if (MI_SECURE>=3 || MI_DEBUG>=1 || defined(MI_PADDING))
|
||||||
#define MI_ENCODE_FREELIST 1
|
#define MI_ENCODE_FREELIST 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Reserve extra padding at the end of each block to be more resilient against heap block overflows.
|
|
||||||
// If free lists are encoded, the padding can detect byte-precise buffer overflow on free.
|
|
||||||
#if (!defined(MI_PADDING) && (MI_SECURE>=3 || MI_DEBUG>=1))
|
|
||||||
#define MI_PADDING
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// Platform specific values
|
// Platform specific values
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// Size of a pointer.
|
// Size of a pointer.
|
||||||
// We assume that `sizeof(void*)==sizeof(intptr_t)`
|
// We assume that `sizeof(void*)==sizeof(intptr_t)`
|
||||||
|
@ -218,7 +217,7 @@ typedef struct mi_page_s {
|
||||||
|
|
||||||
mi_block_t* free; // list of available free blocks (`malloc` allocates from this list)
|
mi_block_t* free; // list of available free blocks (`malloc` allocates from this list)
|
||||||
#ifdef MI_ENCODE_FREELIST
|
#ifdef MI_ENCODE_FREELIST
|
||||||
uintptr_t key[2]; // two random keys to encode the free lists (see `_mi_block_next`)
|
uintptr_t keys[2]; // two random keys to encode the free lists (see `_mi_block_next`)
|
||||||
#endif
|
#endif
|
||||||
uint32_t used; // number of blocks in use (including blocks in `local_free` and `thread_free`)
|
uint32_t used; // number of blocks in use (including blocks in `local_free` and `thread_free`)
|
||||||
uint32_t xblock_size; // size available in each block (always `>0`)
|
uint32_t xblock_size; // size available in each block (always `>0`)
|
||||||
|
@ -306,8 +305,8 @@ typedef struct mi_random_cxt_s {
|
||||||
// In debug mode there is a padding stucture at the end of the blocks to check for buffer overflows
|
// In debug mode there is a padding stucture at the end of the blocks to check for buffer overflows
|
||||||
#if defined(MI_PADDING)
|
#if defined(MI_PADDING)
|
||||||
typedef struct mi_padding_s {
|
typedef struct mi_padding_s {
|
||||||
uint32_t block; // (encoded) lower 32 bits of the block address. (to check validity of the block)
|
uint32_t canary; // encoded block value to check validity of the padding (in case of overflow)
|
||||||
uint32_t delta; // (encoded) padding bytes before the block. (mi_usable_size(p) - decode(delta) == exact allocated bytes)
|
uint32_t delta; // padding bytes before the block. (mi_usable_size(p) - delta == exact allocated bytes)
|
||||||
} mi_padding_t;
|
} mi_padding_t;
|
||||||
#define MI_PADDING_SIZE (sizeof(mi_padding_t))
|
#define MI_PADDING_SIZE (sizeof(mi_padding_t))
|
||||||
#define MI_PADDING_WSIZE ((MI_PADDING_SIZE + MI_INTPTR_SIZE - 1) / MI_INTPTR_SIZE)
|
#define MI_PADDING_WSIZE ((MI_PADDING_SIZE + MI_INTPTR_SIZE - 1) / MI_INTPTR_SIZE)
|
||||||
|
@ -327,7 +326,7 @@ struct mi_heap_s {
|
||||||
volatile _Atomic(mi_block_t*) thread_delayed_free;
|
volatile _Atomic(mi_block_t*) thread_delayed_free;
|
||||||
uintptr_t thread_id; // thread this heap belongs too
|
uintptr_t thread_id; // thread this heap belongs too
|
||||||
uintptr_t cookie; // random cookie to verify pointers (see `_mi_ptr_cookie`)
|
uintptr_t cookie; // random cookie to verify pointers (see `_mi_ptr_cookie`)
|
||||||
uintptr_t key[2]; // two random keys used to encode the `thread_delayed_free` list
|
uintptr_t keys[2]; // two random keys used to encode the `thread_delayed_free` list
|
||||||
mi_random_ctx_t random; // random number context used for secure allocation
|
mi_random_ctx_t random; // random number context used for secure allocation
|
||||||
size_t page_count; // total number of pages in the `pages` queues.
|
size_t page_count; // total number of pages in the `pages` queues.
|
||||||
bool no_reclaim; // `true` if this heap should not reclaim abandoned pages
|
bool no_reclaim; // `true` if this heap should not reclaim abandoned pages
|
||||||
|
|
54
src/alloc.c
54
src/alloc.c
|
@ -48,10 +48,11 @@ extern inline void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t siz
|
||||||
mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + mi_page_usable_block_size(page));
|
mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + mi_page_usable_block_size(page));
|
||||||
ptrdiff_t delta = ((uint8_t*)padding - (uint8_t*)block - (size - MI_PADDING_SIZE));
|
ptrdiff_t delta = ((uint8_t*)padding - (uint8_t*)block - (size - MI_PADDING_SIZE));
|
||||||
mi_assert_internal(delta >= 0 && mi_page_usable_block_size(page) >= (size - MI_PADDING_SIZE + delta));
|
mi_assert_internal(delta >= 0 && mi_page_usable_block_size(page) >= (size - MI_PADDING_SIZE + delta));
|
||||||
padding->block = (uint32_t)(((uintptr_t)block >> MI_INTPTR_SHIFT) ^ page->key[0]);
|
padding->canary = (uint32_t)(mi_ptr_encode(page,block,page->keys));
|
||||||
padding->delta = (uint32_t)(delta ^ page->key[1]);
|
padding->delta = (uint32_t)(delta);
|
||||||
uint8_t* fill = (uint8_t*)padding - delta;
|
uint8_t* fill = (uint8_t*)padding - delta;
|
||||||
for (ptrdiff_t i = 0; i < delta; i++) { fill[i] = MI_DEBUG_PADDING; }
|
const size_t maxpad = (delta > MI_MAX_ALIGN_SIZE ? MI_MAX_ALIGN_SIZE : delta); // set at most N initial padding bytes
|
||||||
|
for (size_t i = 0; i < maxpad; i++) { fill[i] = MI_DEBUG_PADDING; }
|
||||||
#endif
|
#endif
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
@ -175,7 +176,7 @@ static mi_decl_noinline bool mi_check_is_double_freex(const mi_page_t* page, con
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block_t* block) {
|
static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block_t* block) {
|
||||||
mi_block_t* n = mi_block_nextx(page, block, page->key[0], page->key[1]); // pretend it is freed, and get the decoded first field
|
mi_block_t* n = mi_block_nextx(page, block, page->keys); // pretend it is freed, and get the decoded first field
|
||||||
if (((uintptr_t)n & (MI_INTPTR_SIZE-1))==0 && // quick check: aligned pointer?
|
if (((uintptr_t)n & (MI_INTPTR_SIZE-1))==0 && // quick check: aligned pointer?
|
||||||
(n==NULL || mi_is_in_same_page(block, n))) // quick check: in same page or NULL?
|
(n==NULL || mi_is_in_same_page(block, n))) // quick check: in same page or NULL?
|
||||||
{
|
{
|
||||||
|
@ -198,33 +199,35 @@ static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(MI_PADDING) && defined(MI_ENCODE_FREELIST)
|
#if defined(MI_PADDING) && defined(MI_ENCODE_FREELIST)
|
||||||
static mi_padding_t mi_page_decode_padding(const mi_page_t* page, const mi_block_t* block, size_t* bsize) {
|
static bool mi_page_decode_padding(const mi_page_t* page, const mi_block_t* block, size_t* delta, size_t* bsize) {
|
||||||
*bsize = mi_page_usable_block_size(page);
|
*bsize = mi_page_usable_block_size(page);
|
||||||
const mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + *bsize);
|
const mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + *bsize);
|
||||||
mi_padding_t pad;
|
*delta = padding->delta;
|
||||||
pad.block = padding->block ^ (uint32_t)page->key[0];
|
return ((uint32_t)mi_ptr_encode(page,block,page->keys) == padding->canary && *delta <= *bsize);
|
||||||
pad.delta = padding->delta ^ (uint32_t)page->key[1];
|
|
||||||
return pad;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the exact usable size of a block.
|
// Return the exact usable size of a block.
|
||||||
static size_t mi_page_usable_size_of(const mi_page_t* page, const mi_block_t* block) {
|
static size_t mi_page_usable_size_of(const mi_page_t* page, const mi_block_t* block) {
|
||||||
size_t bsize;
|
size_t bsize;
|
||||||
mi_padding_t pad = mi_page_decode_padding(page, block, &bsize);
|
size_t delta;
|
||||||
return bsize - pad.delta;
|
bool ok = mi_page_decode_padding(page, block, &delta, &bsize);
|
||||||
|
mi_assert_internal(ok); mi_assert_internal(delta <= bsize);
|
||||||
|
return (ok ? bsize - delta : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mi_verify_padding(const mi_page_t* page, const mi_block_t* block, size_t* size, size_t* wrong) {
|
static bool mi_verify_padding(const mi_page_t* page, const mi_block_t* block, size_t* size, size_t* wrong) {
|
||||||
size_t bsize;
|
size_t bsize;
|
||||||
const mi_padding_t pad = mi_page_decode_padding(page, block, &bsize);
|
size_t delta;
|
||||||
|
bool ok = mi_page_decode_padding(page, block, &delta, &bsize);
|
||||||
*size = *wrong = bsize;
|
*size = *wrong = bsize;
|
||||||
if ((uint32_t)((uintptr_t)block >> MI_INTPTR_SHIFT) != pad.block) return false;
|
if (!ok) return false;
|
||||||
if (pad.delta > bsize) return false; // can be equal for zero-sized allocation!
|
mi_assert_internal(bsize >= delta);
|
||||||
*size = bsize - pad.delta;
|
*size = bsize - delta;
|
||||||
uint8_t* fill = (uint8_t*)block + bsize - pad.delta;
|
uint8_t* fill = (uint8_t*)block + bsize - delta;
|
||||||
for (uint32_t i = 0; i < pad.delta; i++) {
|
const size_t maxpad = (delta > MI_MAX_ALIGN_SIZE ? MI_MAX_ALIGN_SIZE : delta); // check at most the first N padding bytes
|
||||||
|
for (size_t i = 0; i < maxpad; i++) {
|
||||||
if (fill[i] != MI_DEBUG_PADDING) {
|
if (fill[i] != MI_DEBUG_PADDING) {
|
||||||
*wrong = bsize - pad.delta + i;
|
*wrong = bsize - delta + i;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,13 +248,16 @@ static void mi_check_padding(const mi_page_t* page, const mi_block_t* block) {
|
||||||
// so it will later not trigger an overflow error in `mi_free_block`.
|
// so it will later not trigger an overflow error in `mi_free_block`.
|
||||||
static void mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size) {
|
static void mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size) {
|
||||||
size_t bsize;
|
size_t bsize;
|
||||||
mi_padding_t pad = mi_page_decode_padding(page, block, &bsize);
|
size_t delta;
|
||||||
if ((bsize - pad.delta) >= min_size) return;
|
bool ok = mi_page_decode_padding(page, block, &delta, &bsize);
|
||||||
|
mi_assert_internal(ok);
|
||||||
|
if (!ok || (bsize - delta) >= min_size) return; // usually already enough space
|
||||||
mi_assert_internal(bsize >= min_size);
|
mi_assert_internal(bsize >= min_size);
|
||||||
ptrdiff_t delta = (bsize - min_size);
|
if (bsize < min_size) return; // should never happen
|
||||||
mi_assert_internal(delta >= 0 && delta < (ptrdiff_t)bsize);
|
size_t new_delta = (bsize - min_size);
|
||||||
|
mi_assert_internal(new_delta < bsize);
|
||||||
mi_padding_t* padding = (mi_padding_t*)((uint8_t*)block + bsize);
|
mi_padding_t* padding = (mi_padding_t*)((uint8_t*)block + bsize);
|
||||||
padding->delta = (uint32_t)(delta ^ page->key[1]);
|
padding->delta = (uint32_t)new_delta;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void mi_check_padding(const mi_page_t* page, const mi_block_t* block) {
|
static void mi_check_padding(const mi_page_t* page, const mi_block_t* block) {
|
||||||
|
@ -348,7 +354,7 @@ static mi_decl_noinline void _mi_free_block_mt(mi_page_t* page, mi_block_t* bloc
|
||||||
mi_block_t* dfree;
|
mi_block_t* dfree;
|
||||||
do {
|
do {
|
||||||
dfree = mi_atomic_read_ptr_relaxed(mi_block_t,&heap->thread_delayed_free);
|
dfree = mi_atomic_read_ptr_relaxed(mi_block_t,&heap->thread_delayed_free);
|
||||||
mi_block_set_nextx(heap,block,dfree, heap->key[0], heap->key[1]);
|
mi_block_set_nextx(heap,block,dfree, heap->keys);
|
||||||
} while (!mi_atomic_cas_ptr_weak(mi_block_t,&heap->thread_delayed_free, block, dfree));
|
} while (!mi_atomic_cas_ptr_weak(mi_block_t,&heap->thread_delayed_free, block, dfree));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -194,9 +194,9 @@ mi_heap_t* mi_heap_new(void) {
|
||||||
heap->tld = bheap->tld;
|
heap->tld = bheap->tld;
|
||||||
heap->thread_id = _mi_thread_id();
|
heap->thread_id = _mi_thread_id();
|
||||||
_mi_random_split(&bheap->random, &heap->random);
|
_mi_random_split(&bheap->random, &heap->random);
|
||||||
heap->cookie = _mi_heap_random_next(heap) | 1;
|
heap->cookie = _mi_heap_random_next(heap) | 1;
|
||||||
heap->key[0] = _mi_heap_random_next(heap);
|
heap->keys[0] = _mi_heap_random_next(heap);
|
||||||
heap->key[1] = _mi_heap_random_next(heap);
|
heap->keys[1] = _mi_heap_random_next(heap);
|
||||||
heap->no_reclaim = true; // don't reclaim abandoned pages or otherwise destroy is unsafe
|
heap->no_reclaim = true; // don't reclaim abandoned pages or otherwise destroy is unsafe
|
||||||
return heap;
|
return heap;
|
||||||
}
|
}
|
||||||
|
|
12
src/init.c
12
src/init.c
|
@ -173,9 +173,9 @@ static bool _mi_heap_init(void) {
|
||||||
memcpy(heap, &_mi_heap_empty, sizeof(*heap));
|
memcpy(heap, &_mi_heap_empty, sizeof(*heap));
|
||||||
heap->thread_id = _mi_thread_id();
|
heap->thread_id = _mi_thread_id();
|
||||||
_mi_random_init(&heap->random);
|
_mi_random_init(&heap->random);
|
||||||
heap->cookie = _mi_heap_random_next(heap) | 1;
|
heap->cookie = _mi_heap_random_next(heap) | 1;
|
||||||
heap->key[0] = _mi_heap_random_next(heap);
|
heap->keys[0] = _mi_heap_random_next(heap);
|
||||||
heap->key[1] = _mi_heap_random_next(heap);
|
heap->keys[1] = _mi_heap_random_next(heap);
|
||||||
heap->tld = tld;
|
heap->tld = tld;
|
||||||
tld->heap_backing = heap;
|
tld->heap_backing = heap;
|
||||||
tld->segments.stats = &tld->stats;
|
tld->segments.stats = &tld->stats;
|
||||||
|
@ -418,9 +418,9 @@ void mi_process_init(void) mi_attr_noexcept {
|
||||||
_mi_verbose_message("process init: 0x%zx\n", _mi_heap_main.thread_id);
|
_mi_verbose_message("process init: 0x%zx\n", _mi_heap_main.thread_id);
|
||||||
_mi_random_init(&_mi_heap_main.random);
|
_mi_random_init(&_mi_heap_main.random);
|
||||||
#ifndef __APPLE__ // TODO: fix this? cannot update cookie if allocation already happened..
|
#ifndef __APPLE__ // TODO: fix this? cannot update cookie if allocation already happened..
|
||||||
_mi_heap_main.cookie = _mi_heap_random_next(&_mi_heap_main);
|
_mi_heap_main.cookie = _mi_heap_random_next(&_mi_heap_main);
|
||||||
_mi_heap_main.key[0] = _mi_heap_random_next(&_mi_heap_main);
|
_mi_heap_main.keys[0] = _mi_heap_random_next(&_mi_heap_main);
|
||||||
_mi_heap_main.key[1] = _mi_heap_random_next(&_mi_heap_main);
|
_mi_heap_main.keys[1] = _mi_heap_random_next(&_mi_heap_main);
|
||||||
#endif
|
#endif
|
||||||
mi_process_setup_auto_thread_done();
|
mi_process_setup_auto_thread_done();
|
||||||
_mi_os_init();
|
_mi_os_init();
|
||||||
|
|
14
src/page.c
14
src/page.c
|
@ -281,7 +281,7 @@ void _mi_heap_delayed_free(mi_heap_t* heap) {
|
||||||
|
|
||||||
// and free them all
|
// and free them all
|
||||||
while(block != NULL) {
|
while(block != NULL) {
|
||||||
mi_block_t* next = mi_block_nextx(heap,block, heap->key[0], heap->key[1]);
|
mi_block_t* next = mi_block_nextx(heap,block, heap->keys);
|
||||||
// use internal free instead of regular one to keep stats etc correct
|
// use internal free instead of regular one to keep stats etc correct
|
||||||
if (!_mi_free_delayed_block(block)) {
|
if (!_mi_free_delayed_block(block)) {
|
||||||
// we might already start delayed freeing while another thread has not yet
|
// we might already start delayed freeing while another thread has not yet
|
||||||
|
@ -289,7 +289,7 @@ void _mi_heap_delayed_free(mi_heap_t* heap) {
|
||||||
mi_block_t* dfree;
|
mi_block_t* dfree;
|
||||||
do {
|
do {
|
||||||
dfree = mi_atomic_read_ptr_relaxed(mi_block_t,&heap->thread_delayed_free);
|
dfree = mi_atomic_read_ptr_relaxed(mi_block_t,&heap->thread_delayed_free);
|
||||||
mi_block_set_nextx(heap, block, dfree, heap->key[0], heap->key[1]);
|
mi_block_set_nextx(heap, block, dfree, heap->keys);
|
||||||
} while (!mi_atomic_cas_ptr_weak(mi_block_t,&heap->thread_delayed_free, block, dfree));
|
} while (!mi_atomic_cas_ptr_weak(mi_block_t,&heap->thread_delayed_free, block, dfree));
|
||||||
}
|
}
|
||||||
block = next;
|
block = next;
|
||||||
|
@ -348,7 +348,7 @@ void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq) {
|
||||||
|
|
||||||
#if MI_DEBUG>1
|
#if MI_DEBUG>1
|
||||||
// check there are no references left..
|
// check there are no references left..
|
||||||
for (mi_block_t* block = (mi_block_t*)pheap->thread_delayed_free; block != NULL; block = mi_block_nextx(pheap, block, pheap->key[0], pheap->key[1])) {
|
for (mi_block_t* block = (mi_block_t*)pheap->thread_delayed_free; block != NULL; block = mi_block_nextx(pheap, block, pheap->keys)) {
|
||||||
mi_assert_internal(_mi_ptr_page(block) != page);
|
mi_assert_internal(_mi_ptr_page(block) != page);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -609,8 +609,8 @@ static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi
|
||||||
mi_assert_internal(page_size / block_size < (1L<<16));
|
mi_assert_internal(page_size / block_size < (1L<<16));
|
||||||
page->reserved = (uint16_t)(page_size / block_size);
|
page->reserved = (uint16_t)(page_size / block_size);
|
||||||
#ifdef MI_ENCODE_FREELIST
|
#ifdef MI_ENCODE_FREELIST
|
||||||
page->key[0] = _mi_heap_random_next(heap);
|
page->keys[0] = _mi_heap_random_next(heap);
|
||||||
page->key[1] = _mi_heap_random_next(heap);
|
page->keys[1] = _mi_heap_random_next(heap);
|
||||||
#endif
|
#endif
|
||||||
page->is_zero = page->is_zero_init;
|
page->is_zero = page->is_zero_init;
|
||||||
|
|
||||||
|
@ -623,8 +623,8 @@ static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi
|
||||||
mi_assert_internal(page->retire_expire == 0);
|
mi_assert_internal(page->retire_expire == 0);
|
||||||
mi_assert_internal(!mi_page_has_aligned(page));
|
mi_assert_internal(!mi_page_has_aligned(page));
|
||||||
#if (MI_ENCODE_FREELIST)
|
#if (MI_ENCODE_FREELIST)
|
||||||
mi_assert_internal(page->key[0] != 0);
|
mi_assert_internal(page->keys[0] != 0);
|
||||||
mi_assert_internal(page->key[1] != 0);
|
mi_assert_internal(page->keys[1] != 0);
|
||||||
#endif
|
#endif
|
||||||
mi_assert_expensive(mi_page_is_valid_init(page));
|
mi_assert_expensive(mi_page_is_valid_init(page));
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue