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