|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "mozilla/Assertions.h" |
|
6 #include "mozilla/Atomics.h" |
|
7 |
|
8 #include <stdint.h> |
|
9 |
|
10 using mozilla::Atomic; |
|
11 using mozilla::MemoryOrdering; |
|
12 using mozilla::Relaxed; |
|
13 using mozilla::ReleaseAcquire; |
|
14 using mozilla::SequentiallyConsistent; |
|
15 |
|
16 template <typename T, MemoryOrdering Order> |
|
17 static void |
|
18 TestTypeWithOrdering() |
|
19 { |
|
20 Atomic<T, Order> atomic(5); |
|
21 MOZ_RELEASE_ASSERT(atomic == 5, "Atomic variable did not initialize"); |
|
22 |
|
23 // Test atomic increment |
|
24 MOZ_RELEASE_ASSERT(++atomic == T(6), "Atomic increment did not work"); |
|
25 MOZ_RELEASE_ASSERT(atomic++ == T(6), "Atomic post-increment did not work"); |
|
26 MOZ_RELEASE_ASSERT(atomic == T(7), "Atomic post-increment did not work"); |
|
27 |
|
28 // Test atomic decrement |
|
29 MOZ_RELEASE_ASSERT(--atomic == 6, "Atomic decrement did not work"); |
|
30 MOZ_RELEASE_ASSERT(atomic-- == 6, "Atomic post-decrement did not work"); |
|
31 MOZ_RELEASE_ASSERT(atomic == 5, "Atomic post-decrement did not work"); |
|
32 |
|
33 // Test other arithmetic. |
|
34 T result; |
|
35 result = (atomic += T(5)); |
|
36 MOZ_RELEASE_ASSERT(atomic == T(10), "Atomic += did not work"); |
|
37 MOZ_RELEASE_ASSERT(result == T(10), "Atomic += returned the wrong value"); |
|
38 result = (atomic -= T(3)); |
|
39 MOZ_RELEASE_ASSERT(atomic == T(7), "Atomic -= did not work"); |
|
40 MOZ_RELEASE_ASSERT(result == T(7), "Atomic -= returned the wrong value"); |
|
41 |
|
42 // Test assignment |
|
43 result = (atomic = T(5)); |
|
44 MOZ_RELEASE_ASSERT(atomic == T(5), "Atomic assignment failed"); |
|
45 MOZ_RELEASE_ASSERT(result == T(5), "Atomic assignment returned the wrong value"); |
|
46 |
|
47 // Test logical operations. |
|
48 result = (atomic ^= T(2)); |
|
49 MOZ_RELEASE_ASSERT(atomic == T(7), "Atomic ^= did not work"); |
|
50 MOZ_RELEASE_ASSERT(result == T(7), "Atomic ^= returned the wrong value"); |
|
51 result = (atomic ^= T(4)); |
|
52 MOZ_RELEASE_ASSERT(atomic == T(3), "Atomic ^= did not work"); |
|
53 MOZ_RELEASE_ASSERT(result == T(3), "Atomic ^= returned the wrong value"); |
|
54 result = (atomic |= T(8)); |
|
55 MOZ_RELEASE_ASSERT(atomic == T(11), "Atomic |= did not work"); |
|
56 MOZ_RELEASE_ASSERT(result == T(11), "Atomic |= returned the wrong value"); |
|
57 result = (atomic |= T(8)); |
|
58 MOZ_RELEASE_ASSERT(atomic == T(11), "Atomic |= did not work"); |
|
59 MOZ_RELEASE_ASSERT(result == T(11), "Atomic |= returned the wrong value"); |
|
60 result = (atomic &= T(12)); |
|
61 MOZ_RELEASE_ASSERT(atomic == T(8), "Atomic &= did not work"); |
|
62 MOZ_RELEASE_ASSERT(result == T(8), "Atomic &= returned the wrong value"); |
|
63 |
|
64 // Test exchange. |
|
65 atomic = T(30); |
|
66 result = atomic.exchange(42); |
|
67 MOZ_RELEASE_ASSERT(atomic == T(42), "Atomic exchange did not work"); |
|
68 MOZ_RELEASE_ASSERT(result == T(30), "Atomic exchange returned the wrong value"); |
|
69 |
|
70 // Test CAS. |
|
71 atomic = T(1); |
|
72 bool boolResult = atomic.compareExchange(0, 2); |
|
73 MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); |
|
74 MOZ_RELEASE_ASSERT(atomic == T(1), "CAS shouldn't have done anything."); |
|
75 |
|
76 boolResult = atomic.compareExchange(1, 42); |
|
77 MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); |
|
78 MOZ_RELEASE_ASSERT(atomic == T(42), "CAS should have changed atomic's value."); |
|
79 } |
|
80 |
|
81 template<typename T, MemoryOrdering Order> |
|
82 static void |
|
83 TestPointerWithOrdering() |
|
84 { |
|
85 T array1[10]; |
|
86 Atomic<T*, Order> atomic(array1); |
|
87 MOZ_RELEASE_ASSERT(atomic == array1, "Atomic variable did not initialize"); |
|
88 |
|
89 // Test atomic increment |
|
90 MOZ_RELEASE_ASSERT(++atomic == array1 + 1, "Atomic increment did not work"); |
|
91 MOZ_RELEASE_ASSERT(atomic++ == array1 + 1, "Atomic post-increment did not work"); |
|
92 MOZ_RELEASE_ASSERT(atomic == array1 + 2, "Atomic post-increment did not work"); |
|
93 |
|
94 // Test atomic decrement |
|
95 MOZ_RELEASE_ASSERT(--atomic == array1 + 1, "Atomic decrement did not work"); |
|
96 MOZ_RELEASE_ASSERT(atomic-- == array1 + 1, "Atomic post-decrement did not work"); |
|
97 MOZ_RELEASE_ASSERT(atomic == array1, "Atomic post-decrement did not work"); |
|
98 |
|
99 // Test other arithmetic operations |
|
100 T* result; |
|
101 result = (atomic += 2); |
|
102 MOZ_RELEASE_ASSERT(atomic == array1 + 2, "Atomic += did not work"); |
|
103 MOZ_RELEASE_ASSERT(result == array1 + 2, "Atomic += returned the wrong value"); |
|
104 result = (atomic -= 1); |
|
105 MOZ_RELEASE_ASSERT(atomic == array1 + 1, "Atomic -= did not work"); |
|
106 MOZ_RELEASE_ASSERT(result == array1 + 1, "Atomic -= returned the wrong value"); |
|
107 |
|
108 // Test stores |
|
109 result = (atomic = array1); |
|
110 MOZ_RELEASE_ASSERT(atomic == array1, "Atomic assignment did not work"); |
|
111 MOZ_RELEASE_ASSERT(result == array1, "Atomic assignment returned the wrong value"); |
|
112 |
|
113 // Test exchange |
|
114 atomic = array1 + 2; |
|
115 result = atomic.exchange(array1); |
|
116 MOZ_RELEASE_ASSERT(atomic == array1, "Atomic exchange did not work"); |
|
117 MOZ_RELEASE_ASSERT(result == array1 + 2, "Atomic exchange returned the wrong value"); |
|
118 |
|
119 atomic = array1; |
|
120 bool boolResult = atomic.compareExchange(array1 + 1, array1 + 2); |
|
121 MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); |
|
122 MOZ_RELEASE_ASSERT(atomic == array1, "CAS shouldn't have done anything."); |
|
123 |
|
124 boolResult = atomic.compareExchange(array1, array1 + 3); |
|
125 MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); |
|
126 MOZ_RELEASE_ASSERT(atomic == array1 + 3, "CAS should have changed atomic's value."); |
|
127 } |
|
128 |
|
129 enum EnumType { |
|
130 EnumType_0 = 0, |
|
131 EnumType_1 = 1, |
|
132 EnumType_2 = 2, |
|
133 EnumType_3 = 3 |
|
134 }; |
|
135 |
|
136 template<MemoryOrdering Order> |
|
137 static void |
|
138 TestEnumWithOrdering() |
|
139 { |
|
140 Atomic<EnumType, Order> atomic(EnumType_2); |
|
141 MOZ_RELEASE_ASSERT(atomic == EnumType_2, "Atomic variable did not initialize"); |
|
142 |
|
143 // Test assignment |
|
144 EnumType result; |
|
145 result = (atomic = EnumType_3); |
|
146 MOZ_RELEASE_ASSERT(atomic == EnumType_3, "Atomic assignment failed"); |
|
147 MOZ_RELEASE_ASSERT(result == EnumType_3, "Atomic assignment returned the wrong value"); |
|
148 |
|
149 // Test exchange. |
|
150 atomic = EnumType_1; |
|
151 result = atomic.exchange(EnumType_2); |
|
152 MOZ_RELEASE_ASSERT(atomic == EnumType_2, "Atomic exchange did not work"); |
|
153 MOZ_RELEASE_ASSERT(result == EnumType_1, "Atomic exchange returned the wrong value"); |
|
154 |
|
155 // Test CAS. |
|
156 atomic = EnumType_1; |
|
157 bool boolResult = atomic.compareExchange(EnumType_0, EnumType_2); |
|
158 MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); |
|
159 MOZ_RELEASE_ASSERT(atomic == EnumType_1, "CAS shouldn't have done anything."); |
|
160 |
|
161 boolResult = atomic.compareExchange(EnumType_1, EnumType_3); |
|
162 MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); |
|
163 MOZ_RELEASE_ASSERT(atomic == EnumType_3, "CAS should have changed atomic's value."); |
|
164 } |
|
165 |
|
166 template <MemoryOrdering Order> |
|
167 static void |
|
168 TestBoolWithOrdering() |
|
169 { |
|
170 Atomic<bool, Order> atomic(false); |
|
171 MOZ_RELEASE_ASSERT(atomic == false, "Atomic variable did not initialize"); |
|
172 |
|
173 // Test assignment |
|
174 bool result; |
|
175 result = (atomic = true); |
|
176 MOZ_RELEASE_ASSERT(atomic == true, "Atomic assignment failed"); |
|
177 MOZ_RELEASE_ASSERT(result == true, "Atomic assignment returned the wrong value"); |
|
178 |
|
179 // Test exchange. |
|
180 atomic = false; |
|
181 result = atomic.exchange(true); |
|
182 MOZ_RELEASE_ASSERT(atomic == true, "Atomic exchange did not work"); |
|
183 MOZ_RELEASE_ASSERT(result == false, "Atomic exchange returned the wrong value"); |
|
184 |
|
185 // Test CAS. |
|
186 atomic = false; |
|
187 bool boolResult = atomic.compareExchange(true, false); |
|
188 MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); |
|
189 MOZ_RELEASE_ASSERT(atomic == false, "CAS shouldn't have done anything."); |
|
190 |
|
191 boolResult = atomic.compareExchange(false, true); |
|
192 MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); |
|
193 MOZ_RELEASE_ASSERT(atomic == true, "CAS should have changed atomic's value."); |
|
194 } |
|
195 |
|
196 template <typename T> |
|
197 static void |
|
198 TestType() |
|
199 { |
|
200 TestTypeWithOrdering<T, SequentiallyConsistent>(); |
|
201 TestTypeWithOrdering<T, ReleaseAcquire>(); |
|
202 TestTypeWithOrdering<T, Relaxed>(); |
|
203 } |
|
204 |
|
205 template<typename T> |
|
206 static void |
|
207 TestPointer() |
|
208 { |
|
209 TestPointerWithOrdering<T, SequentiallyConsistent>(); |
|
210 TestPointerWithOrdering<T, ReleaseAcquire>(); |
|
211 TestPointerWithOrdering<T, Relaxed>(); |
|
212 } |
|
213 |
|
214 static void |
|
215 TestEnum() |
|
216 { |
|
217 TestEnumWithOrdering<SequentiallyConsistent>(); |
|
218 TestEnumWithOrdering<ReleaseAcquire>(); |
|
219 TestEnumWithOrdering<Relaxed>(); |
|
220 } |
|
221 |
|
222 static void |
|
223 TestBool() |
|
224 { |
|
225 TestBoolWithOrdering<SequentiallyConsistent>(); |
|
226 TestBoolWithOrdering<ReleaseAcquire>(); |
|
227 TestBoolWithOrdering<Relaxed>(); |
|
228 } |
|
229 |
|
230 int main() |
|
231 { |
|
232 TestType<uint32_t>(); |
|
233 TestType<int32_t>(); |
|
234 TestType<intptr_t>(); |
|
235 TestType<uintptr_t>(); |
|
236 TestPointer<int>(); |
|
237 TestPointer<float>(); |
|
238 TestPointer<uint16_t*>(); |
|
239 TestPointer<uint32_t*>(); |
|
240 TestEnum(); |
|
241 TestBool(); |
|
242 } |