1a0698ed9Schristos #include "test/jemalloc_test.h" 2a0698ed9Schristos 3a0698ed9Schristos static void 4a0698ed9Schristos mallctl_thread_name_get_impl(const char *thread_name_expected, const char *func, 5a0698ed9Schristos int line) { 6a0698ed9Schristos const char *thread_name_old; 7a0698ed9Schristos size_t sz; 8a0698ed9Schristos 9a0698ed9Schristos sz = sizeof(thread_name_old); 10*7bdf38e5Schristos expect_d_eq(mallctl("thread.prof.name", (void *)&thread_name_old, &sz, 11a0698ed9Schristos NULL, 0), 0, 12a0698ed9Schristos "%s():%d: Unexpected mallctl failure reading thread.prof.name", 13a0698ed9Schristos func, line); 14*7bdf38e5Schristos expect_str_eq(thread_name_old, thread_name_expected, 15a0698ed9Schristos "%s():%d: Unexpected thread.prof.name value", func, line); 16a0698ed9Schristos } 17a0698ed9Schristos #define mallctl_thread_name_get(a) \ 18a0698ed9Schristos mallctl_thread_name_get_impl(a, __func__, __LINE__) 19a0698ed9Schristos 20a0698ed9Schristos static void 21a0698ed9Schristos mallctl_thread_name_set_impl(const char *thread_name, const char *func, 22a0698ed9Schristos int line) { 23*7bdf38e5Schristos expect_d_eq(mallctl("thread.prof.name", NULL, NULL, 24a0698ed9Schristos (void *)&thread_name, sizeof(thread_name)), 0, 25*7bdf38e5Schristos "%s():%d: Unexpected mallctl failure writing thread.prof.name", 26a0698ed9Schristos func, line); 27a0698ed9Schristos mallctl_thread_name_get_impl(thread_name, func, line); 28a0698ed9Schristos } 29a0698ed9Schristos #define mallctl_thread_name_set(a) \ 30a0698ed9Schristos mallctl_thread_name_set_impl(a, __func__, __LINE__) 31a0698ed9Schristos 32a0698ed9Schristos TEST_BEGIN(test_prof_thread_name_validation) { 33a0698ed9Schristos const char *thread_name; 34a0698ed9Schristos 35a0698ed9Schristos test_skip_if(!config_prof); 36*7bdf38e5Schristos test_skip_if(opt_prof_sys_thread_name); 37a0698ed9Schristos 38a0698ed9Schristos mallctl_thread_name_get(""); 39a0698ed9Schristos mallctl_thread_name_set("hi there"); 40a0698ed9Schristos 41a0698ed9Schristos /* NULL input shouldn't be allowed. */ 42a0698ed9Schristos thread_name = NULL; 43*7bdf38e5Schristos expect_d_eq(mallctl("thread.prof.name", NULL, NULL, 44a0698ed9Schristos (void *)&thread_name, sizeof(thread_name)), EFAULT, 45a0698ed9Schristos "Unexpected mallctl result writing \"%s\" to thread.prof.name", 46a0698ed9Schristos thread_name); 47a0698ed9Schristos 48a0698ed9Schristos /* '\n' shouldn't be allowed. */ 49a0698ed9Schristos thread_name = "hi\nthere"; 50*7bdf38e5Schristos expect_d_eq(mallctl("thread.prof.name", NULL, NULL, 51a0698ed9Schristos (void *)&thread_name, sizeof(thread_name)), EFAULT, 52a0698ed9Schristos "Unexpected mallctl result writing \"%s\" to thread.prof.name", 53a0698ed9Schristos thread_name); 54a0698ed9Schristos 55a0698ed9Schristos /* Simultaneous read/write shouldn't be allowed. */ 56a0698ed9Schristos { 57a0698ed9Schristos const char *thread_name_old; 58a0698ed9Schristos size_t sz; 59a0698ed9Schristos 60a0698ed9Schristos sz = sizeof(thread_name_old); 61*7bdf38e5Schristos expect_d_eq(mallctl("thread.prof.name", 62a0698ed9Schristos (void *)&thread_name_old, &sz, (void *)&thread_name, 63a0698ed9Schristos sizeof(thread_name)), EPERM, 64a0698ed9Schristos "Unexpected mallctl result writing \"%s\" to " 65a0698ed9Schristos "thread.prof.name", thread_name); 66a0698ed9Schristos } 67a0698ed9Schristos 68a0698ed9Schristos mallctl_thread_name_set(""); 69a0698ed9Schristos } 70a0698ed9Schristos TEST_END 71a0698ed9Schristos 72a0698ed9Schristos #define NTHREADS 4 73a0698ed9Schristos #define NRESET 25 74a0698ed9Schristos static void * 75a0698ed9Schristos thd_start(void *varg) { 76a0698ed9Schristos unsigned thd_ind = *(unsigned *)varg; 77a0698ed9Schristos char thread_name[16] = ""; 78a0698ed9Schristos unsigned i; 79a0698ed9Schristos 80a0698ed9Schristos malloc_snprintf(thread_name, sizeof(thread_name), "thread %u", thd_ind); 81a0698ed9Schristos 82a0698ed9Schristos mallctl_thread_name_get(""); 83a0698ed9Schristos mallctl_thread_name_set(thread_name); 84a0698ed9Schristos 85a0698ed9Schristos for (i = 0; i < NRESET; i++) { 86*7bdf38e5Schristos expect_d_eq(mallctl("prof.reset", NULL, NULL, NULL, 0), 0, 87a0698ed9Schristos "Unexpected error while resetting heap profile data"); 88a0698ed9Schristos mallctl_thread_name_get(thread_name); 89a0698ed9Schristos } 90a0698ed9Schristos 91a0698ed9Schristos mallctl_thread_name_set(thread_name); 92a0698ed9Schristos mallctl_thread_name_set(""); 93a0698ed9Schristos 94a0698ed9Schristos return NULL; 95a0698ed9Schristos } 96a0698ed9Schristos 97a0698ed9Schristos TEST_BEGIN(test_prof_thread_name_threaded) { 98*7bdf38e5Schristos test_skip_if(!config_prof); 99*7bdf38e5Schristos test_skip_if(opt_prof_sys_thread_name); 100*7bdf38e5Schristos 101a0698ed9Schristos thd_t thds[NTHREADS]; 102a0698ed9Schristos unsigned thd_args[NTHREADS]; 103a0698ed9Schristos unsigned i; 104a0698ed9Schristos 105a0698ed9Schristos for (i = 0; i < NTHREADS; i++) { 106a0698ed9Schristos thd_args[i] = i; 107a0698ed9Schristos thd_create(&thds[i], thd_start, (void *)&thd_args[i]); 108a0698ed9Schristos } 109a0698ed9Schristos for (i = 0; i < NTHREADS; i++) { 110a0698ed9Schristos thd_join(thds[i], NULL); 111a0698ed9Schristos } 112a0698ed9Schristos } 113a0698ed9Schristos TEST_END 114a0698ed9Schristos #undef NTHREADS 115a0698ed9Schristos #undef NRESET 116a0698ed9Schristos 117a0698ed9Schristos int 118a0698ed9Schristos main(void) { 119a0698ed9Schristos return test( 120a0698ed9Schristos test_prof_thread_name_validation, 121a0698ed9Schristos test_prof_thread_name_threaded); 122a0698ed9Schristos } 123