1#include "test/jemalloc_test.h" 2 3#ifdef JEMALLOC_PROF 4const char *malloc_conf = "prof:true,prof_active:false"; 5#endif 6 7static void 8mallctl_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 25static void 26mallctl_thread_name_set_impl(const char *thread_name, const char *func, 27 int line) 28{ 29 assert_d_eq(mallctl("thread.prof.name", NULL, NULL, 30 (void *)&thread_name, 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 38TEST_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, 50 (void *)&thread_name, 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, 57 (void *)&thread_name, 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", 68 (void *)&thread_name_old, &sz, (void *)&thread_name, 69 sizeof(thread_name)), EPERM, 70 "Unexpected mallctl result writing \"%s\" to " 71 "thread.prof.name", thread_name); 72 } 73 74 mallctl_thread_name_set(""); 75} 76TEST_END 77 78#define NTHREADS 4 79#define NRESET 25 80static void * 81thd_start(void *varg) 82{ 83 unsigned thd_ind = *(unsigned *)varg; 84 char thread_name[16] = ""; 85 unsigned i; 86 87 malloc_snprintf(thread_name, sizeof(thread_name), "thread %u", thd_ind); 88 89 mallctl_thread_name_get(""); 90 mallctl_thread_name_set(thread_name); 91 92 for (i = 0; i < NRESET; i++) { 93 assert_d_eq(mallctl("prof.reset", NULL, NULL, NULL, 0), 0, 94 "Unexpected error while resetting heap profile data"); 95 mallctl_thread_name_get(thread_name); 96 } 97 98 mallctl_thread_name_set(thread_name); 99 mallctl_thread_name_set(""); 100 101 return (NULL); 102} 103 104TEST_BEGIN(test_prof_thread_name_threaded) 105{ 106 thd_t thds[NTHREADS]; 107 unsigned thd_args[NTHREADS]; 108 unsigned i; 109 110 test_skip_if(!config_prof); 111 112 for (i = 0; i < NTHREADS; i++) { 113 thd_args[i] = i; 114 thd_create(&thds[i], thd_start, (void *)&thd_args[i]); 115 } 116 for (i = 0; i < NTHREADS; i++) 117 thd_join(thds[i], NULL); 118} 119TEST_END 120#undef NTHREADS 121#undef NRESET 122 123int 124main(void) 125{ 126 return (test( 127 test_prof_thread_name_validation, 128 test_prof_thread_name_threaded)); 129} 130