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