5 Commits

Author SHA1 Message Date
Farid Zakaria
b859093d28 Limit TSD bootstrap hook to tests 2026-07-06 18:26:40 -04:00
Farid Zakaria
54f22c83d8 Initialize TSD tcache before enabling it 2026-07-06 18:26:40 -04:00
Farid Zakaria
36f2017777 Keep TSD bootstrap reentrant until data init completes 2026-07-06 18:26:40 -04:00
Farid Zakaria
95c2588191 Add TSD bootstrap reentrancy test 2026-07-06 18:26:40 -04:00
Farid Zakaria
7c34a482c1 Add TSD reentrant stress test 2026-07-06 18:26:40 -04:00
4 changed files with 87 additions and 6 deletions

View File

@@ -4,6 +4,9 @@
extern JEMALLOC_EXPORT void (*test_hooks_arena_new_hook)(void);
extern JEMALLOC_EXPORT void (*test_hooks_libc_hook)(void);
extern JEMALLOC_EXPORT void (*test_hooks_safety_check_abort)(const char *);
#if defined(JEMALLOC_JET) || defined(JEMALLOC_UNIT_TEST)
extern JEMALLOC_EXPORT void (*test_hooks_tsd_bootstrap_hook)(void);
#endif
#if defined(JEMALLOC_JET) || defined(JEMALLOC_UNIT_TEST)
# define JEMALLOC_TEST_HOOK(fn, hook) \

View File

@@ -1044,21 +1044,28 @@ tcache_create_explicit(tsd_t *tsd) {
bool
tsd_tcache_enabled_data_init(tsd_t *tsd) {
/* Called upon tsd initialization. */
tsd_tcache_enabled_set(tsd, opt_tcache);
/*
* tcache is not available yet, but we need to set up its tcache_nbins
* in advance.
*/
tcache_default_settings_init(tsd_tcache_slowp_get(tsd));
tsd_slow_update(tsd);
#if defined(JEMALLOC_JET) || defined(JEMALLOC_UNIT_TEST)
if (test_hooks_tsd_bootstrap_hook != NULL) {
test_hooks_tsd_bootstrap_hook();
}
#endif
bool err = false;
if (opt_tcache) {
/* Trigger tcache init. */
return tsd_tcache_data_init(
/* Initialize the bins before advertising the tcache. */
err = tsd_tcache_data_init(
tsd, NULL, tcache_get_default_ncached_max());
}
return false;
tsd_tcache_enabled_set(tsd, opt_tcache && !err);
tsd_slow_update(tsd);
return err;
}
void

View File

@@ -13,3 +13,8 @@ void (*test_hooks_libc_hook)(void) = NULL;
JEMALLOC_EXPORT
void (*test_hooks_safety_check_abort)(const char *) = NULL;
#if defined(JEMALLOC_JET) || defined(JEMALLOC_UNIT_TEST)
JEMALLOC_EXPORT
void (*test_hooks_tsd_bootstrap_hook)(void) = NULL;
#endif

View File

@@ -130,6 +130,71 @@ TEST_BEGIN(test_tsd_reincarnation) {
}
TEST_END
static bool tsd_bootstrap_reentrant_hook_ran;
static unsigned tsd_bootstrap_reentrant_hook_runs;
static void
tsd_bootstrap_reentrant_hook(void) {
tsd_bootstrap_reentrant_hook_ran = true;
tsd_bootstrap_reentrant_hook_runs++;
test_hooks_tsd_bootstrap_hook = NULL;
void *p = malloc(16);
expect_ptr_not_null(p, "Unexpected recursive malloc() failure");
free(p);
}
static void *
thd_start_reentrant_tsd_bootstrap(void *arg) {
(void)arg;
test_hooks_tsd_bootstrap_hook = tsd_bootstrap_reentrant_hook;
void *p = malloc(1);
expect_ptr_not_null(p, "Unexpected malloc() failure");
free(p);
test_hooks_tsd_bootstrap_hook = NULL;
expect_true(tsd_bootstrap_reentrant_hook_ran,
"TSD bootstrap hook should have executed");
return NULL;
}
static void *
thd_start_reentrant_tsd_bootstrap_minimal(void *arg) {
(void)arg;
tsd_t *tsd = tsd_fetch_min();
expect_u_eq(tsd_state_get(tsd), tsd_state_minimal_initialized,
"TSD should be minimal initialized");
test_hooks_tsd_bootstrap_hook = tsd_bootstrap_reentrant_hook;
void *p = malloc(1);
expect_ptr_not_null(p, "Unexpected malloc() failure");
free(p);
test_hooks_tsd_bootstrap_hook = NULL;
expect_true(tsd_bootstrap_reentrant_hook_ran,
"TSD bootstrap hook should have executed");
return NULL;
}
TEST_BEGIN(test_tsd_reentrant_bootstrap) {
thd_t thd;
tsd_bootstrap_reentrant_hook_ran = false;
tsd_bootstrap_reentrant_hook_runs = 0;
thd_create(&thd, thd_start_reentrant_tsd_bootstrap, NULL);
thd_join(thd, NULL);
tsd_bootstrap_reentrant_hook_ran = false;
thd_create(&thd, thd_start_reentrant_tsd_bootstrap_minimal, NULL);
thd_join(thd, NULL);
expect_u_eq(tsd_bootstrap_reentrant_hook_runs, 2,
"TSD bootstrap hook should have executed once per case");
}
TEST_END
static void *
thd_start_dalloc_only(void *arg) {
void **ptrs = (void **)arg;
@@ -194,5 +259,6 @@ main(void) {
}
return test_no_reentrancy(test_tsd_main_thread, test_tsd_sub_thread,
test_tsd_sub_thread_dalloc_only, test_tsd_reincarnation);
test_tsd_sub_thread_dalloc_only, test_tsd_reincarnation,
test_tsd_reentrant_bootstrap);
}