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