xref: /netbsd-src/external/bsd/jemalloc/dist/test/unit/counter.c (revision 7bdf38e5b7a28439665f2fdeff81e36913eef7dd)
1*7bdf38e5Schristos #include "test/jemalloc_test.h"
2*7bdf38e5Schristos 
3*7bdf38e5Schristos static const uint64_t interval = 1 << 20;
4*7bdf38e5Schristos 
5*7bdf38e5Schristos TEST_BEGIN(test_counter_accum) {
6*7bdf38e5Schristos 	uint64_t increment = interval >> 4;
7*7bdf38e5Schristos 	unsigned n = interval / increment;
8*7bdf38e5Schristos 	uint64_t accum = 0;
9*7bdf38e5Schristos 
10*7bdf38e5Schristos 	counter_accum_t c;
11*7bdf38e5Schristos 	counter_accum_init(&c, interval);
12*7bdf38e5Schristos 
13*7bdf38e5Schristos 	tsd_t *tsd = tsd_fetch();
14*7bdf38e5Schristos 	bool trigger;
15*7bdf38e5Schristos 	for (unsigned i = 0; i < n; i++) {
16*7bdf38e5Schristos 		trigger = counter_accum(tsd_tsdn(tsd), &c, increment);
17*7bdf38e5Schristos 		accum += increment;
18*7bdf38e5Schristos 		if (accum < interval) {
19*7bdf38e5Schristos 			expect_b_eq(trigger, false, "Should not trigger");
20*7bdf38e5Schristos 		} else {
21*7bdf38e5Schristos 			expect_b_eq(trigger, true, "Should have triggered");
22*7bdf38e5Schristos 		}
23*7bdf38e5Schristos 	}
24*7bdf38e5Schristos 	expect_b_eq(trigger, true, "Should have triggered");
25*7bdf38e5Schristos }
26*7bdf38e5Schristos TEST_END
27*7bdf38e5Schristos 
28*7bdf38e5Schristos void
29*7bdf38e5Schristos expect_counter_value(counter_accum_t *c, uint64_t v) {
30*7bdf38e5Schristos 	uint64_t accum = locked_read_u64_unsynchronized(&c->accumbytes);
31*7bdf38e5Schristos 	expect_u64_eq(accum, v, "Counter value mismatch");
32*7bdf38e5Schristos }
33*7bdf38e5Schristos 
34*7bdf38e5Schristos #define N_THDS (16)
35*7bdf38e5Schristos #define N_ITER_THD (1 << 12)
36*7bdf38e5Schristos #define ITER_INCREMENT (interval >> 4)
37*7bdf38e5Schristos 
38*7bdf38e5Schristos static void *
39*7bdf38e5Schristos thd_start(void *varg) {
40*7bdf38e5Schristos 	counter_accum_t *c = (counter_accum_t *)varg;
41*7bdf38e5Schristos 
42*7bdf38e5Schristos 	tsd_t *tsd = tsd_fetch();
43*7bdf38e5Schristos 	bool trigger;
44*7bdf38e5Schristos 	uintptr_t n_triggered = 0;
45*7bdf38e5Schristos 	for (unsigned i = 0; i < N_ITER_THD; i++) {
46*7bdf38e5Schristos 		trigger = counter_accum(tsd_tsdn(tsd), c, ITER_INCREMENT);
47*7bdf38e5Schristos 		n_triggered += trigger ? 1 : 0;
48*7bdf38e5Schristos 	}
49*7bdf38e5Schristos 
50*7bdf38e5Schristos 	return (void *)n_triggered;
51*7bdf38e5Schristos }
52*7bdf38e5Schristos 
53*7bdf38e5Schristos 
54*7bdf38e5Schristos TEST_BEGIN(test_counter_mt) {
55*7bdf38e5Schristos 	counter_accum_t shared_c;
56*7bdf38e5Schristos 	counter_accum_init(&shared_c, interval);
57*7bdf38e5Schristos 
58*7bdf38e5Schristos 	thd_t thds[N_THDS];
59*7bdf38e5Schristos 	unsigned i;
60*7bdf38e5Schristos 	for (i = 0; i < N_THDS; i++) {
61*7bdf38e5Schristos 		thd_create(&thds[i], thd_start, (void *)&shared_c);
62*7bdf38e5Schristos 	}
63*7bdf38e5Schristos 
64*7bdf38e5Schristos 	uint64_t sum = 0;
65*7bdf38e5Schristos 	for (i = 0; i < N_THDS; i++) {
66*7bdf38e5Schristos 		void *ret;
67*7bdf38e5Schristos 		thd_join(thds[i], &ret);
68*7bdf38e5Schristos 		sum += (uintptr_t)ret;
69*7bdf38e5Schristos 	}
70*7bdf38e5Schristos 	expect_u64_eq(sum, N_THDS * N_ITER_THD / (interval / ITER_INCREMENT),
71*7bdf38e5Schristos 	    "Incorrect number of triggers");
72*7bdf38e5Schristos }
73*7bdf38e5Schristos TEST_END
74*7bdf38e5Schristos 
75*7bdf38e5Schristos int
76*7bdf38e5Schristos main(void) {
77*7bdf38e5Schristos 	return test(
78*7bdf38e5Schristos 	    test_counter_accum,
79*7bdf38e5Schristos 	    test_counter_mt);
80*7bdf38e5Schristos }
81