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