mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-06 23:39:31 +03:00
improve performance of mi_free_collect_mt by specializing mi_page_unown
This commit is contained in:
parent
9b7914fd3f
commit
bc7fe059a6
1 changed files with 31 additions and 2 deletions
33
src/free.c
33
src/free.c
|
@ -201,7 +201,7 @@ void mi_free(void* p) mi_attr_noexcept
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// Multi-threaded Free (`_mt`)
|
// Multi-threaded Free (`_mt`)
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
static bool mi_page_unown_from_free(mi_page_t* page, mi_block_t* mt_free);
|
||||||
|
|
||||||
static void mi_decl_noinline mi_free_try_collect_mt(mi_page_t* page, mi_block_t* mt_free) mi_attr_noexcept {
|
static void mi_decl_noinline mi_free_try_collect_mt(mi_page_t* page, mi_block_t* mt_free) mi_attr_noexcept {
|
||||||
mi_assert_internal(mi_page_is_owned(page));
|
mi_assert_internal(mi_page_is_owned(page));
|
||||||
|
@ -269,7 +269,36 @@ static void mi_decl_noinline mi_free_try_collect_mt(mi_page_t* page, mi_block_t*
|
||||||
|
|
||||||
|
|
||||||
// not reclaimed or free'd, unown again
|
// not reclaimed or free'd, unown again
|
||||||
_mi_page_unown(page);
|
// _mi_page_unown(page);
|
||||||
|
mi_page_unown_from_free(page, mt_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// release ownership of a page. This may free the page if all (other) blocks were concurrently
|
||||||
|
// freed in the meantime. Returns true if the page was freed.
|
||||||
|
// This is a specialized version of `mi_page_unown` to (try to) avoid calling `mi_page_free_collect` again.
|
||||||
|
static bool mi_page_unown_from_free(mi_page_t* page, mi_block_t* mt_free) {
|
||||||
|
mi_assert_internal(mi_page_is_owned(page));
|
||||||
|
mi_assert_internal(mi_page_is_abandoned(page));
|
||||||
|
mi_assert_internal(mt_free != NULL);
|
||||||
|
mi_assert_internal(page->used > 1);
|
||||||
|
mi_thread_free_t tf_expect = mi_tf_create(mt_free, true);
|
||||||
|
mi_thread_free_t tf_new = mi_tf_create(mt_free, false);
|
||||||
|
while mi_unlikely(!mi_atomic_cas_weak_acq_rel(&page->xthread_free, &tf_expect, tf_new)) {
|
||||||
|
mi_assert_internal(mi_tf_is_owned(tf_expect));
|
||||||
|
while (mi_tf_block(tf_expect) != NULL) {
|
||||||
|
_mi_page_free_collect(page,false); // update used
|
||||||
|
if (mi_page_all_free(page)) { // it may become free just before unowning it
|
||||||
|
_mi_arenas_page_unabandon(page);
|
||||||
|
_mi_arenas_page_free(page);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
tf_expect = mi_atomic_load_relaxed(&page->xthread_free);
|
||||||
|
}
|
||||||
|
mi_assert_internal(mi_tf_block(tf_expect)==NULL);
|
||||||
|
tf_new = mi_tf_create(NULL, false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue