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