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