Do proper cleanup for tsd_state_reincarnated.
Also enable arena_bind under non-nominal state, as the cleanup will be handled correctly now.
This commit is contained in:
parent
51d3682950
commit
d3cda3423c
@ -74,7 +74,8 @@ tsd_##n##_get(tsd_t *tsd) { \
|
|||||||
} \
|
} \
|
||||||
JEMALLOC_ALWAYS_INLINE void \
|
JEMALLOC_ALWAYS_INLINE void \
|
||||||
tsd_##n##_set(tsd_t *tsd, t n) { \
|
tsd_##n##_set(tsd_t *tsd, t n) { \
|
||||||
assert(tsd->state == tsd_state_nominal); \
|
assert(tsd->state == tsd_state_nominal || \
|
||||||
|
tsd->state == tsd_state_reincarnated); \
|
||||||
tsd->n = n; \
|
tsd->n = n; \
|
||||||
}
|
}
|
||||||
#define MALLOC_TSD_getset_no(n, t)
|
#define MALLOC_TSD_getset_no(n, t)
|
||||||
|
@ -422,13 +422,7 @@ arena_init(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
arena_bind(tsd_t *tsd, unsigned ind, bool internal) {
|
arena_bind(tsd_t *tsd, unsigned ind, bool internal) {
|
||||||
arena_t *arena;
|
arena_t *arena = arena_get(tsd_tsdn(tsd), ind, false);
|
||||||
|
|
||||||
if (!tsd_nominal(tsd)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
arena = arena_get(tsd_tsdn(tsd), ind, false);
|
|
||||||
arena_nthreads_inc(arena, internal);
|
arena_nthreads_inc(arena, internal);
|
||||||
|
|
||||||
if (internal) {
|
if (internal) {
|
||||||
@ -455,6 +449,7 @@ arena_unbind(tsd_t *tsd, unsigned ind, bool internal) {
|
|||||||
|
|
||||||
arena = arena_get(tsd_tsdn(tsd), ind, false);
|
arena = arena_get(tsd_tsdn(tsd), ind, false);
|
||||||
arena_nthreads_dec(arena, internal);
|
arena_nthreads_dec(arena, internal);
|
||||||
|
|
||||||
if (internal) {
|
if (internal) {
|
||||||
tsd_iarena_set(tsd, NULL);
|
tsd_iarena_set(tsd, NULL);
|
||||||
} else {
|
} else {
|
||||||
|
15
src/tsd.c
15
src/tsd.c
@ -86,6 +86,12 @@ tsd_cleanup(void *arg) {
|
|||||||
/* Do nothing. */
|
/* Do nothing. */
|
||||||
break;
|
break;
|
||||||
case tsd_state_nominal:
|
case tsd_state_nominal:
|
||||||
|
case tsd_state_reincarnated:
|
||||||
|
/*
|
||||||
|
* Reincarnated means another destructor deallocated memory
|
||||||
|
* after this destructor was called. Reset state to
|
||||||
|
* tsd_state_purgatory and request another callback.
|
||||||
|
*/
|
||||||
#define MALLOC_TSD_cleanup_yes(n, t) \
|
#define MALLOC_TSD_cleanup_yes(n, t) \
|
||||||
n##_cleanup(tsd);
|
n##_cleanup(tsd);
|
||||||
#define MALLOC_TSD_cleanup_no(n, t)
|
#define MALLOC_TSD_cleanup_no(n, t)
|
||||||
@ -106,15 +112,6 @@ MALLOC_TSD
|
|||||||
* nothing, and do not request another callback.
|
* nothing, and do not request another callback.
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
case tsd_state_reincarnated:
|
|
||||||
/*
|
|
||||||
* Another destructor deallocated memory after this destructor
|
|
||||||
* was called. Reset state to tsd_state_purgatory and request
|
|
||||||
* another callback.
|
|
||||||
*/
|
|
||||||
tsd->state = tsd_state_purgatory;
|
|
||||||
tsd_set(tsd);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
not_reached();
|
not_reached();
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,44 @@ TEST_BEGIN(test_tsd_sub_thread) {
|
|||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
|
static void *
|
||||||
|
thd_start_reincarnated(void *arg) {
|
||||||
|
tsd_t *tsd = tsd_fetch();
|
||||||
|
assert(tsd);
|
||||||
|
|
||||||
|
void *p = malloc(1);
|
||||||
|
assert_ptr_not_null(p, "Unexpected malloc() failure");
|
||||||
|
|
||||||
|
/* Manually trigger reincarnation. */
|
||||||
|
assert_ptr_not_null(tsd->arena, "Should have tsd arena set.");
|
||||||
|
tsd_cleanup((void *)tsd);
|
||||||
|
assert_ptr_null(tsd->arena, "TSD arena should have been cleared.");
|
||||||
|
assert_u_eq(tsd->state, tsd_state_purgatory,
|
||||||
|
"TSD state should be purgatory\n");
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
assert_u_eq(tsd->state, tsd_state_reincarnated,
|
||||||
|
"TSD state should be reincarnated\n");
|
||||||
|
p = mallocx(1, MALLOCX_TCACHE_NONE);
|
||||||
|
assert_ptr_not_null(p, "Unexpected malloc() failure");
|
||||||
|
assert_ptr_not_null(tsd->arena,
|
||||||
|
"Should have tsd arena set after reincarnation.");
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
tsd_cleanup((void *)tsd);
|
||||||
|
assert_ptr_null(tsd->arena,
|
||||||
|
"TSD arena should have been cleared after 2nd cleanup.");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_BEGIN(test_tsd_reincarnation) {
|
||||||
|
thd_t thd;
|
||||||
|
thd_create(&thd, thd_start_reincarnated, NULL);
|
||||||
|
thd_join(thd, NULL);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
int
|
int
|
||||||
main(void) {
|
main(void) {
|
||||||
/* Core tsd bootstrapping must happen prior to data_tsd_boot(). */
|
/* Core tsd bootstrapping must happen prior to data_tsd_boot(). */
|
||||||
@ -101,5 +139,6 @@ main(void) {
|
|||||||
|
|
||||||
return test(
|
return test(
|
||||||
test_tsd_main_thread,
|
test_tsd_main_thread,
|
||||||
test_tsd_sub_thread);
|
test_tsd_sub_thread,
|
||||||
|
test_tsd_reincarnation);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user