1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
| #include "test/jemalloc_test.h"
|
| #define TEST_STRUCT(p, t) \
| struct p##_test_s { \
| t accum0; \
| t x; \
| t s; \
| }; \
| typedef struct p##_test_s p##_test_t;
|
| #define TEST_BODY(p, t, tc, ta, FMT) do { \
| const p##_test_t tests[] = { \
| {(t)-1, (t)-1, (t)-2}, \
| {(t)-1, (t) 0, (t)-2}, \
| {(t)-1, (t) 1, (t)-2}, \
| \
| {(t) 0, (t)-1, (t)-2}, \
| {(t) 0, (t) 0, (t)-2}, \
| {(t) 0, (t) 1, (t)-2}, \
| \
| {(t) 1, (t)-1, (t)-2}, \
| {(t) 1, (t) 0, (t)-2}, \
| {(t) 1, (t) 1, (t)-2}, \
| \
| {(t)0, (t)-(1 << 22), (t)-2}, \
| {(t)0, (t)(1 << 22), (t)-2}, \
| {(t)(1 << 22), (t)-(1 << 22), (t)-2}, \
| {(t)(1 << 22), (t)(1 << 22), (t)-2} \
| }; \
| unsigned i; \
| \
| for (i = 0; i < sizeof(tests)/sizeof(p##_test_t); i++) { \
| bool err; \
| t accum = tests[i].accum0; \
| assert_##ta##_eq(atomic_read_##p(&accum), \
| tests[i].accum0, \
| "Erroneous read, i=%u", i); \
| \
| assert_##ta##_eq(atomic_add_##p(&accum, tests[i].x), \
| (t)((tc)tests[i].accum0 + (tc)tests[i].x), \
| "i=%u, accum=%"FMT", x=%"FMT, \
| i, tests[i].accum0, tests[i].x); \
| assert_##ta##_eq(atomic_read_##p(&accum), accum, \
| "Erroneous add, i=%u", i); \
| \
| accum = tests[i].accum0; \
| assert_##ta##_eq(atomic_sub_##p(&accum, tests[i].x), \
| (t)((tc)tests[i].accum0 - (tc)tests[i].x), \
| "i=%u, accum=%"FMT", x=%"FMT, \
| i, tests[i].accum0, tests[i].x); \
| assert_##ta##_eq(atomic_read_##p(&accum), accum, \
| "Erroneous sub, i=%u", i); \
| \
| accum = tests[i].accum0; \
| err = atomic_cas_##p(&accum, tests[i].x, tests[i].s); \
| assert_b_eq(err, tests[i].accum0 != tests[i].x, \
| "Erroneous cas success/failure result"); \
| assert_##ta##_eq(accum, err ? tests[i].accum0 : \
| tests[i].s, "Erroneous cas effect, i=%u", i); \
| \
| accum = tests[i].accum0; \
| atomic_write_##p(&accum, tests[i].s); \
| assert_##ta##_eq(accum, tests[i].s, \
| "Erroneous write, i=%u", i); \
| } \
| } while (0)
|
| TEST_STRUCT(uint64, uint64_t)
| TEST_BEGIN(test_atomic_uint64)
| {
|
| #if !(LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)
| test_skip("64-bit atomic operations not supported");
| #else
| TEST_BODY(uint64, uint64_t, uint64_t, u64, FMTx64);
| #endif
| }
| TEST_END
|
| TEST_STRUCT(uint32, uint32_t)
| TEST_BEGIN(test_atomic_uint32)
| {
|
| TEST_BODY(uint32, uint32_t, uint32_t, u32, "#"FMTx32);
| }
| TEST_END
|
| TEST_STRUCT(p, void *)
| TEST_BEGIN(test_atomic_p)
| {
|
| TEST_BODY(p, void *, uintptr_t, ptr, "p");
| }
| TEST_END
|
| TEST_STRUCT(z, size_t)
| TEST_BEGIN(test_atomic_z)
| {
|
| TEST_BODY(z, size_t, size_t, zu, "#zx");
| }
| TEST_END
|
| TEST_STRUCT(u, unsigned)
| TEST_BEGIN(test_atomic_u)
| {
|
| TEST_BODY(u, unsigned, unsigned, u, "#x");
| }
| TEST_END
|
| int
| main(void)
| {
|
| return (test(
| test_atomic_uint64,
| test_atomic_uint32,
| test_atomic_p,
| test_atomic_z,
| test_atomic_u));
| }
|
|