diff options
author | David Goldblatt <davidgoldblatt@fb.com> | 2017-04-01 02:59:45 (GMT) |
---|---|---|
committer | David Goldblatt <davidtgoldblatt@gmail.com> | 2017-04-07 21:10:27 (GMT) |
commit | b407a65401bca5828760c8fd5e940e91475a2b3e (patch) | |
tree | a1bbd2e2fccd51153f126a228a07491259b44730 /test/src/test.c | |
parent | 0a0fcd3e6a0816f0a56fa852416d0ece861c0abb (diff) | |
download | jemalloc-b407a65401bca5828760c8fd5e940e91475a2b3e.zip jemalloc-b407a65401bca5828760c8fd5e940e91475a2b3e.tar.gz jemalloc-b407a65401bca5828760c8fd5e940e91475a2b3e.tar.bz2 |
Add basic reentrancy-checking support, and allow arena_new to reenter.
This checks whether or not we're reentrant using thread-local data, and, if we
are, moves certain internal allocations to use arena 0 (which should be properly
initialized after bootstrapping).
The immediate thing this allows is spinning up threads in arena_new, which will
enable spinning up background threads there.
Diffstat (limited to 'test/src/test.c')
-rw-r--r-- | test/src/test.c | 76 |
1 files changed, 52 insertions, 24 deletions
diff --git a/test/src/test.c b/test/src/test.c index fe6dc60..01a4d73 100644 --- a/test/src/test.c +++ b/test/src/test.c @@ -10,31 +10,56 @@ static const char * test_name = ""; /* Reentrancy testing helpers. */ #define NUM_REENTRANT_ALLOCS 20 -static bool reentrant = false; -static bool hook_ran = false; -static void *to_free[NUM_REENTRANT_ALLOCS]; +typedef enum { + non_reentrant = 0, + libc_reentrant = 1, + arena_new_reentrant = 2 +} reentrancy_t; +static reentrancy_t reentrancy; + +static bool libc_hook_ran = false; +static bool arena_new_hook_ran = false; + +static const char * +reentrancy_t_str(reentrancy_t r) { + switch (r) { + case non_reentrant: + return "non-reentrant"; + case libc_reentrant: + return "libc-reentrant"; + case arena_new_reentrant: + return "arena_new-reentrant"; + default: + unreachable(); + } +} static void -reentrancy_hook() { - hook_ran = true; - hooks_libc_hook = NULL; +do_hook(bool *hook_ran, void (**hook)()) { + *hook_ran = true; + *hook = NULL; - void *to_free_local[NUM_REENTRANT_ALLOCS]; size_t alloc_size = 1; for (int i = 0; i < NUM_REENTRANT_ALLOCS; i++) { - to_free[i] = malloc(alloc_size); - to_free_local[i] = malloc(alloc_size); + free(malloc(alloc_size)); alloc_size *= 2; } - for (int i = 0; i < NUM_REENTRANT_ALLOCS; i++) { - free(to_free_local[i]); - } +} + +static void +libc_reentrancy_hook() { + do_hook(&libc_hook_ran, &hooks_libc_hook); +} + +static void +arena_new_reentrancy_hook() { + do_hook(&arena_new_hook_ran, &hooks_arena_new_hook); } /* Actual test infrastructure. */ bool test_is_reentrant() { - return reentrant; + return reentrancy != non_reentrant; } JEMALLOC_FORMAT_PRINTF(1, 2) @@ -81,9 +106,8 @@ p_test_init(const char *name) { void p_test_fini(void) { test_counts[test_status]++; - malloc_printf("%s: %s (%s)\n", test_name, - test_status_string(test_status), - reentrant ? "reentrant" : "non-reentrant"); + malloc_printf("%s (%s): %s\n", test_name, reentrancy_t_str(reentrancy), + test_status_string(test_status)); } static test_status_t @@ -106,24 +130,28 @@ p_test_impl(bool do_malloc_init, bool do_reentrant, test_t *t, va_list ap) { ret = test_status_pass; for (; t != NULL; t = va_arg(ap, test_t *)) { /* Non-reentrant run. */ - reentrant = false; + reentrancy = non_reentrant; + hooks_arena_new_hook = hooks_libc_hook = NULL; t(); if (test_status > ret) { ret = test_status; } /* Reentrant run. */ if (do_reentrant) { - reentrant = true; - hooks_libc_hook = &reentrancy_hook; + reentrancy = libc_reentrant; + hooks_arena_new_hook = NULL; + hooks_libc_hook = &libc_reentrancy_hook; t(); if (test_status > ret) { ret = test_status; } - if (hook_ran) { - hook_ran = false; - for (int i = 0; i < NUM_REENTRANT_ALLOCS; i++) { - free(to_free[i]); - } + + reentrancy = arena_new_reentrant; + hooks_libc_hook = NULL; + hooks_arena_new_hook = &arena_new_reentrancy_hook; + t(); + if (test_status > ret) { + ret = test_status; } } } |