xref: /netbsd-src/external/bsd/jemalloc/dist/test/integration/allocated.c (revision 7bdf38e5b7a28439665f2fdeff81e36913eef7dd)
1a0698ed9Schristos #include "test/jemalloc_test.h"
2a0698ed9Schristos 
3a0698ed9Schristos static const bool config_stats =
4a0698ed9Schristos #ifdef JEMALLOC_STATS
5a0698ed9Schristos     true
6a0698ed9Schristos #else
7a0698ed9Schristos     false
8a0698ed9Schristos #endif
9a0698ed9Schristos     ;
10a0698ed9Schristos 
11a0698ed9Schristos void *
12a0698ed9Schristos thd_start(void *arg) {
13a0698ed9Schristos 	int err;
14a0698ed9Schristos 	void *p;
15a0698ed9Schristos 	uint64_t a0, a1, d0, d1;
16a0698ed9Schristos 	uint64_t *ap0, *ap1, *dp0, *dp1;
17a0698ed9Schristos 	size_t sz, usize;
18a0698ed9Schristos 
19a0698ed9Schristos 	sz = sizeof(a0);
20a0698ed9Schristos 	if ((err = mallctl("thread.allocated", (void *)&a0, &sz, NULL, 0))) {
21a0698ed9Schristos 		if (err == ENOENT) {
22a0698ed9Schristos 			goto label_ENOENT;
23a0698ed9Schristos 		}
24a0698ed9Schristos 		test_fail("%s(): Error in mallctl(): %s", __func__,
25a0698ed9Schristos 		    strerror(err));
26a0698ed9Schristos 	}
27a0698ed9Schristos 	sz = sizeof(ap0);
28a0698ed9Schristos 	if ((err = mallctl("thread.allocatedp", (void *)&ap0, &sz, NULL, 0))) {
29a0698ed9Schristos 		if (err == ENOENT) {
30a0698ed9Schristos 			goto label_ENOENT;
31a0698ed9Schristos 		}
32a0698ed9Schristos 		test_fail("%s(): Error in mallctl(): %s", __func__,
33a0698ed9Schristos 		    strerror(err));
34a0698ed9Schristos 	}
35*7bdf38e5Schristos 	expect_u64_eq(*ap0, a0,
36a0698ed9Schristos 	    "\"thread.allocatedp\" should provide a pointer to internal "
37a0698ed9Schristos 	    "storage");
38a0698ed9Schristos 
39a0698ed9Schristos 	sz = sizeof(d0);
40a0698ed9Schristos 	if ((err = mallctl("thread.deallocated", (void *)&d0, &sz, NULL, 0))) {
41a0698ed9Schristos 		if (err == ENOENT) {
42a0698ed9Schristos 			goto label_ENOENT;
43a0698ed9Schristos 		}
44a0698ed9Schristos 		test_fail("%s(): Error in mallctl(): %s", __func__,
45a0698ed9Schristos 		    strerror(err));
46a0698ed9Schristos 	}
47a0698ed9Schristos 	sz = sizeof(dp0);
48a0698ed9Schristos 	if ((err = mallctl("thread.deallocatedp", (void *)&dp0, &sz, NULL,
49a0698ed9Schristos 	    0))) {
50a0698ed9Schristos 		if (err == ENOENT) {
51a0698ed9Schristos 			goto label_ENOENT;
52a0698ed9Schristos 		}
53a0698ed9Schristos 		test_fail("%s(): Error in mallctl(): %s", __func__,
54a0698ed9Schristos 		    strerror(err));
55a0698ed9Schristos 	}
56*7bdf38e5Schristos 	expect_u64_eq(*dp0, d0,
57a0698ed9Schristos 	    "\"thread.deallocatedp\" should provide a pointer to internal "
58a0698ed9Schristos 	    "storage");
59a0698ed9Schristos 
60a0698ed9Schristos 	p = malloc(1);
61*7bdf38e5Schristos 	expect_ptr_not_null(p, "Unexpected malloc() error");
62a0698ed9Schristos 
63a0698ed9Schristos 	sz = sizeof(a1);
64a0698ed9Schristos 	mallctl("thread.allocated", (void *)&a1, &sz, NULL, 0);
65a0698ed9Schristos 	sz = sizeof(ap1);
66a0698ed9Schristos 	mallctl("thread.allocatedp", (void *)&ap1, &sz, NULL, 0);
67*7bdf38e5Schristos 	expect_u64_eq(*ap1, a1,
68a0698ed9Schristos 	    "Dereferenced \"thread.allocatedp\" value should equal "
69a0698ed9Schristos 	    "\"thread.allocated\" value");
70*7bdf38e5Schristos 	expect_ptr_eq(ap0, ap1,
71a0698ed9Schristos 	    "Pointer returned by \"thread.allocatedp\" should not change");
72a0698ed9Schristos 
73*7bdf38e5Schristos 	usize = TEST_MALLOC_SIZE(p);
74*7bdf38e5Schristos 	expect_u64_le(a0 + usize, a1,
75a0698ed9Schristos 	    "Allocated memory counter should increase by at least the amount "
76a0698ed9Schristos 	    "explicitly allocated");
77a0698ed9Schristos 
78a0698ed9Schristos 	free(p);
79a0698ed9Schristos 
80a0698ed9Schristos 	sz = sizeof(d1);
81a0698ed9Schristos 	mallctl("thread.deallocated", (void *)&d1, &sz, NULL, 0);
82a0698ed9Schristos 	sz = sizeof(dp1);
83a0698ed9Schristos 	mallctl("thread.deallocatedp", (void *)&dp1, &sz, NULL, 0);
84*7bdf38e5Schristos 	expect_u64_eq(*dp1, d1,
85a0698ed9Schristos 	    "Dereferenced \"thread.deallocatedp\" value should equal "
86a0698ed9Schristos 	    "\"thread.deallocated\" value");
87*7bdf38e5Schristos 	expect_ptr_eq(dp0, dp1,
88a0698ed9Schristos 	    "Pointer returned by \"thread.deallocatedp\" should not change");
89a0698ed9Schristos 
90*7bdf38e5Schristos 	expect_u64_le(d0 + usize, d1,
91a0698ed9Schristos 	    "Deallocated memory counter should increase by at least the amount "
92a0698ed9Schristos 	    "explicitly deallocated");
93a0698ed9Schristos 
94a0698ed9Schristos 	return NULL;
95a0698ed9Schristos label_ENOENT:
96*7bdf38e5Schristos 	expect_false(config_stats,
97a0698ed9Schristos 	    "ENOENT should only be returned if stats are disabled");
98a0698ed9Schristos 	test_skip("\"thread.allocated\" mallctl not available");
99a0698ed9Schristos 	return NULL;
100a0698ed9Schristos }
101a0698ed9Schristos 
102a0698ed9Schristos TEST_BEGIN(test_main_thread) {
103a0698ed9Schristos 	thd_start(NULL);
104a0698ed9Schristos }
105a0698ed9Schristos TEST_END
106a0698ed9Schristos 
107a0698ed9Schristos TEST_BEGIN(test_subthread) {
108a0698ed9Schristos 	thd_t thd;
109a0698ed9Schristos 
110a0698ed9Schristos 	thd_create(&thd, thd_start, NULL);
111a0698ed9Schristos 	thd_join(thd, NULL);
112a0698ed9Schristos }
113a0698ed9Schristos TEST_END
114a0698ed9Schristos 
115a0698ed9Schristos int
116a0698ed9Schristos main(void) {
117a0698ed9Schristos 	/* Run tests multiple times to check for bad interactions. */
118a0698ed9Schristos 	return test(
119a0698ed9Schristos 	    test_main_thread,
120a0698ed9Schristos 	    test_subthread,
121a0698ed9Schristos 	    test_main_thread,
122a0698ed9Schristos 	    test_subthread,
123a0698ed9Schristos 	    test_main_thread);
124a0698ed9Schristos }
125