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