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