summaryrefslogtreecommitdiffstats
path: root/test/unit/tsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/unit/tsd.c')
-rw-r--r--test/unit/tsd.c125
1 files changed, 76 insertions, 49 deletions
diff --git a/test/unit/tsd.c b/test/unit/tsd.c
index d5f96ac..6c47913 100644
--- a/test/unit/tsd.c
+++ b/test/unit/tsd.c
@@ -1,38 +1,29 @@
#include "test/jemalloc_test.h"
-#define THREAD_DATA 0x72b65c10
-
-typedef unsigned int data_t;
-
-static bool data_cleanup_executed;
-
-malloc_tsd_types(data_, data_t)
-malloc_tsd_protos(, data_, data_t)
+static int data_cleanup_count;
void
-data_cleanup(void *arg)
-{
- data_t *data = (data_t *)arg;
-
- if (!data_cleanup_executed) {
- assert_x_eq(*data, THREAD_DATA,
+data_cleanup(int *data) {
+ if (data_cleanup_count == 0) {
+ assert_x_eq(*data, MALLOC_TSD_TEST_DATA_INIT,
"Argument passed into cleanup function should match tsd "
"value");
}
- data_cleanup_executed = true;
+ ++data_cleanup_count;
/*
* Allocate during cleanup for two rounds, in order to assure that
* jemalloc's internal tsd reinitialization happens.
*/
+ bool reincarnate = false;
switch (*data) {
- case THREAD_DATA:
+ case MALLOC_TSD_TEST_DATA_INIT:
*data = 1;
- data_tsd_set(data);
+ reincarnate = true;
break;
case 1:
*data = 2;
- data_tsd_set(data);
+ reincarnate = true;
break;
case 2:
return;
@@ -40,73 +31,109 @@ data_cleanup(void *arg)
not_reached();
}
- {
+ if (reincarnate) {
void *p = mallocx(1, 0);
assert_ptr_not_null(p, "Unexpeced mallocx() failure");
dallocx(p, 0);
}
}
-malloc_tsd_externs(data_, data_t)
-#define DATA_INIT 0x12345678
-malloc_tsd_data(, data_, data_t, DATA_INIT)
-malloc_tsd_funcs(, data_, data_t, DATA_INIT, data_cleanup)
-
static void *
-thd_start(void *arg)
-{
- data_t d = (data_t)(uintptr_t)arg;
+thd_start(void *arg) {
+ int d = (int)(uintptr_t)arg;
void *p;
- assert_x_eq(*data_tsd_get(true), DATA_INIT,
+ tsd_t *tsd = tsd_fetch();
+ assert_x_eq(tsd_test_data_get(tsd), MALLOC_TSD_TEST_DATA_INIT,
"Initial tsd get should return initialization value");
p = malloc(1);
assert_ptr_not_null(p, "Unexpected malloc() failure");
- data_tsd_set(&d);
- assert_x_eq(*data_tsd_get(true), d,
+ tsd_test_data_set(tsd, d);
+ assert_x_eq(tsd_test_data_get(tsd), d,
"After tsd set, tsd get should return value that was set");
d = 0;
- assert_x_eq(*data_tsd_get(true), (data_t)(uintptr_t)arg,
+ assert_x_eq(tsd_test_data_get(tsd), (int)(uintptr_t)arg,
"Resetting local data should have no effect on tsd");
+ tsd_test_callback_set(tsd, &data_cleanup);
+
free(p);
- return (NULL);
+ return NULL;
}
-TEST_BEGIN(test_tsd_main_thread)
-{
-
+TEST_BEGIN(test_tsd_main_thread) {
thd_start((void *)(uintptr_t)0xa5f3e329);
}
TEST_END
-TEST_BEGIN(test_tsd_sub_thread)
-{
+TEST_BEGIN(test_tsd_sub_thread) {
thd_t thd;
- data_cleanup_executed = false;
- thd_create(&thd, thd_start, (void *)THREAD_DATA);
+ data_cleanup_count = 0;
+ thd_create(&thd, thd_start, (void *)MALLOC_TSD_TEST_DATA_INIT);
thd_join(thd, NULL);
- assert_true(data_cleanup_executed,
- "Cleanup function should have executed");
+ /*
+ * We reincarnate twice in the data cleanup, so it should execute at
+ * least 3 times.
+ */
+ assert_x_ge(data_cleanup_count, 3,
+ "Cleanup function should have executed multiple times.");
}
TEST_END
-int
-main(void)
-{
+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_get(tsd),
+ "Should have tsd arena set.");
+ tsd_cleanup((void *)tsd);
+ assert_ptr_null(*tsd_arenap_get_unsafe(tsd),
+ "TSD arena should have been cleared.");
+ assert_u_eq(tsd->state, tsd_state_purgatory,
+ "TSD state should be purgatory\n");
- /* Core tsd bootstrapping must happen prior to data_tsd_boot(). */
+ 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_null(*tsd_arenap_get_unsafe(tsd),
+ "Should not have tsd arena set after reincarnation.");
+
+ free(p);
+ tsd_cleanup((void *)tsd);
+ assert_ptr_null(*tsd_arenap_get_unsafe(tsd),
+ "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
+main(void) {
+ /* Ensure tsd bootstrapped. */
if (nallocx(1, 0) == 0) {
malloc_printf("Initialization error");
- return (test_status_fail);
+ return test_status_fail;
}
- data_tsd_boot();
- return (test(
+ return test_no_reentrancy(
test_tsd_main_thread,
- test_tsd_sub_thread));
+ test_tsd_sub_thread,
+ test_tsd_reincarnation);
}