186abd0dcd8e478759fe409d338d11558c4cec427Jason Evans#include "test/jemalloc_test.h"
293443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
32a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evansstatic const bool config_stats =
42a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans#ifdef JEMALLOC_STATS
52a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans    true
62a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans#else
72a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans    false
82a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans#endif
92a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans    ;
102a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans
1193443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evansvoid *
120f4f1efd94d33a4bbf766d3d4e7e349fa7c0d3b9Jason Evansthd_start(void *arg)
1393443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans{
1493443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans	int err;
1593443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans	void *p;
1693443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans	uint64_t a0, a1, d0, d1;
179dcad2dfd11762ea3b542ef45a20bd8297c6f18cJason Evans	uint64_t *ap0, *ap1, *dp0, *dp1;
1893443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans	size_t sz, usize;
1993443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
2093443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans	sz = sizeof(a0);
210a5489e37da88a1a50fbf8552e0d3a7f8fd93ffcJason Evans	if ((err = mallctl("thread.allocated", &a0, &sz, NULL, 0))) {
222a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans		if (err == ENOENT)
232a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans			goto label_ENOENT;
242a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans		test_fail("%s(): Error in mallctl(): %s", __func__,
2593443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans		    strerror(err));
2693443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans	}
279dcad2dfd11762ea3b542ef45a20bd8297c6f18cJason Evans	sz = sizeof(ap0);
280a5489e37da88a1a50fbf8552e0d3a7f8fd93ffcJason Evans	if ((err = mallctl("thread.allocatedp", &ap0, &sz, NULL, 0))) {
292a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans		if (err == ENOENT)
302a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans			goto label_ENOENT;
312a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans		test_fail("%s(): Error in mallctl(): %s", __func__,
329dcad2dfd11762ea3b542ef45a20bd8297c6f18cJason Evans		    strerror(err));
339dcad2dfd11762ea3b542ef45a20bd8297c6f18cJason Evans	}
342a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	assert_u64_eq(*ap0, a0,
352a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "\"thread.allocatedp\" should provide a pointer to internal "
362a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "storage");
3793443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
3893443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans	sz = sizeof(d0);
390a5489e37da88a1a50fbf8552e0d3a7f8fd93ffcJason Evans	if ((err = mallctl("thread.deallocated", &d0, &sz, NULL, 0))) {
402a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans		if (err == ENOENT)
412a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans			goto label_ENOENT;
422a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans		test_fail("%s(): Error in mallctl(): %s", __func__,
4393443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans		    strerror(err));
4493443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans	}
459dcad2dfd11762ea3b542ef45a20bd8297c6f18cJason Evans	sz = sizeof(dp0);
460a5489e37da88a1a50fbf8552e0d3a7f8fd93ffcJason Evans	if ((err = mallctl("thread.deallocatedp", &dp0, &sz, NULL, 0))) {
472a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans		if (err == ENOENT)
482a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans			goto label_ENOENT;
492a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans		test_fail("%s(): Error in mallctl(): %s", __func__,
509dcad2dfd11762ea3b542ef45a20bd8297c6f18cJason Evans		    strerror(err));
519dcad2dfd11762ea3b542ef45a20bd8297c6f18cJason Evans	}
522a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	assert_u64_eq(*dp0, d0,
532a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "\"thread.deallocatedp\" should provide a pointer to internal "
542a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "storage");
5593443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
560a5489e37da88a1a50fbf8552e0d3a7f8fd93ffcJason Evans	p = malloc(1);
572a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	assert_ptr_not_null(p, "Unexpected malloc() error");
5893443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
5993443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans	sz = sizeof(a1);
600a5489e37da88a1a50fbf8552e0d3a7f8fd93ffcJason Evans	mallctl("thread.allocated", &a1, &sz, NULL, 0);
619dcad2dfd11762ea3b542ef45a20bd8297c6f18cJason Evans	sz = sizeof(ap1);
620a5489e37da88a1a50fbf8552e0d3a7f8fd93ffcJason Evans	mallctl("thread.allocatedp", &ap1, &sz, NULL, 0);
632a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	assert_u64_eq(*ap1, a1,
642a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "Dereferenced \"thread.allocatedp\" value should equal "
652a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "\"thread.allocated\" value");
662a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	assert_ptr_eq(ap0, ap1,
672a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "Pointer returned by \"thread.allocatedp\" should not change");
6893443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
690a5489e37da88a1a50fbf8552e0d3a7f8fd93ffcJason Evans	usize = malloc_usable_size(p);
702a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	assert_u64_le(a0 + usize, a1,
712a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "Allocated memory counter should increase by at least the amount "
722a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "explicitly allocated");
7393443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
740a5489e37da88a1a50fbf8552e0d3a7f8fd93ffcJason Evans	free(p);
7593443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
7693443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans	sz = sizeof(d1);
770a5489e37da88a1a50fbf8552e0d3a7f8fd93ffcJason Evans	mallctl("thread.deallocated", &d1, &sz, NULL, 0);
789dcad2dfd11762ea3b542ef45a20bd8297c6f18cJason Evans	sz = sizeof(dp1);
790a5489e37da88a1a50fbf8552e0d3a7f8fd93ffcJason Evans	mallctl("thread.deallocatedp", &dp1, &sz, NULL, 0);
802a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	assert_u64_eq(*dp1, d1,
812a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "Dereferenced \"thread.deallocatedp\" value should equal "
822a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "\"thread.deallocated\" value");
832a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	assert_ptr_eq(dp0, dp1,
842a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "Pointer returned by \"thread.deallocatedp\" should not change");
8593443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
862a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	assert_u64_le(d0 + usize, d1,
872a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "Deallocated memory counter should increase by at least the amount "
882a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "explicitly deallocated");
8993443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
902a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	return (NULL);
912a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evanslabel_ENOENT:
922a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	assert_false(config_stats,
932a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    "ENOENT should only be returned if stats are disabled");
942a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	test_skip("\"thread.allocated\" mallctl not available");
9593443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans	return (NULL);
9693443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans}
9793443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
982a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason EvansTEST_BEGIN(test_main_thread)
9993443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans{
10093443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
1010f4f1efd94d33a4bbf766d3d4e7e349fa7c0d3b9Jason Evans	thd_start(NULL);
1022a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans}
1032a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason EvansTEST_END
10493443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
1052a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason EvansTEST_BEGIN(test_subthread)
1062a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans{
1070f4f1efd94d33a4bbf766d3d4e7e349fa7c0d3b9Jason Evans	thd_t thd;
10893443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
1090f4f1efd94d33a4bbf766d3d4e7e349fa7c0d3b9Jason Evans	thd_create(&thd, thd_start, NULL);
1100f4f1efd94d33a4bbf766d3d4e7e349fa7c0d3b9Jason Evans	thd_join(thd, NULL);
1112a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans}
1122a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason EvansTEST_END
11393443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
1142a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evansint
1152a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evansmain(void)
1162a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans{
11793443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans
1182a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	/* Run tests multiple times to check for bad interactions. */
1192a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	return (test(
1202a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    test_main_thread,
1212a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    test_subthread,
1222a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    test_main_thread,
1232a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    test_subthread,
1242a83ed0284e92c7ba4bd4efe9df149ac724b2f26Jason Evans	    test_main_thread));
12593443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans}
126