Fix tcache_flush (follow up cd2931a).

Also catch invalid tcache id.
This commit is contained in:
Qi Wang 2018-11-09 14:45:06 -08:00 committed by Qi Wang
parent 794e29c0ab
commit 1f56115704
3 changed files with 20 additions and 5 deletions

View File

@ -216,6 +216,9 @@ JEMALLOC_ALWAYS_INLINE tcache_t *
tcaches_get(tsd_t *tsd, unsigned ind) { tcaches_get(tsd_t *tsd, unsigned ind) {
tcaches_t *elm = &tcaches[ind]; tcaches_t *elm = &tcaches[ind];
if (unlikely(elm->tcache == NULL)) { if (unlikely(elm->tcache == NULL)) {
malloc_printf("<jemalloc>: invalid tcache id (%u).\n", ind);
abort();
} else if (unlikely(elm->tcache == TCACHES_ELM_NEED_REINIT)) {
elm->tcache = tcache_create_explicit(tsd); elm->tcache = tcache_create_explicit(tsd);
} }
return elm->tcache; return elm->tcache;

View File

@ -53,4 +53,7 @@ typedef struct tcaches_s tcaches_t;
/* Used in TSD static initializer only. Will be initialized to opt_tcache. */ /* Used in TSD static initializer only. Will be initialized to opt_tcache. */
#define TCACHE_ENABLED_ZERO_INITIALIZER false #define TCACHE_ENABLED_ZERO_INITIALIZER false
/* Used for explicit tcache only. Means flushed but not destroyed. */
#define TCACHES_ELM_NEED_REINIT ((tcache_t *)(uintptr_t)1)
#endif /* JEMALLOC_INTERNAL_TCACHE_TYPES_H */ #endif /* JEMALLOC_INTERNAL_TCACHE_TYPES_H */

View File

@ -638,24 +638,33 @@ label_return:
} }
static tcache_t * static tcache_t *
tcaches_elm_remove(tsd_t *tsd, tcaches_t *elm) { tcaches_elm_remove(tsd_t *tsd, tcaches_t *elm, bool allow_reinit) {
malloc_mutex_assert_owner(tsd_tsdn(tsd), &tcaches_mtx); malloc_mutex_assert_owner(tsd_tsdn(tsd), &tcaches_mtx);
if (elm->tcache == NULL) { if (elm->tcache == NULL) {
return NULL; return NULL;
} }
tcache_t *tcache = elm->tcache; tcache_t *tcache = elm->tcache;
elm->tcache = NULL; if (allow_reinit) {
elm->tcache = TCACHES_ELM_NEED_REINIT;
} else {
elm->tcache = NULL;
}
if (tcache == TCACHES_ELM_NEED_REINIT) {
return NULL;
}
return tcache; return tcache;
} }
void void
tcaches_flush(tsd_t *tsd, unsigned ind) { tcaches_flush(tsd_t *tsd, unsigned ind) {
malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx); malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx);
tcache_t *tcache = tcaches_elm_remove(tsd, &tcaches[ind]); tcache_t *tcache = tcaches_elm_remove(tsd, &tcaches[ind], true);
malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx); malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx);
if (tcache != NULL) { if (tcache != NULL) {
tcache_flush_cache(tsd, tcache); /* Destroy the tcache; recreate in tcaches_get() if needed. */
tcache_destroy(tsd, tcache, false);
} }
} }
@ -663,7 +672,7 @@ void
tcaches_destroy(tsd_t *tsd, unsigned ind) { tcaches_destroy(tsd_t *tsd, unsigned ind) {
malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx); malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx);
tcaches_t *elm = &tcaches[ind]; tcaches_t *elm = &tcaches[ind];
tcache_t *tcache = tcaches_elm_remove(tsd, elm); tcache_t *tcache = tcaches_elm_remove(tsd, elm, false);
elm->next = tcaches_avail; elm->next = tcaches_avail;
tcaches_avail = elm; tcaches_avail = elm;
malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx); malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx);