1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "base/atomicops.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
8*635a8641SAndroid Build Coastguard Worker #include <string.h>
9*635a8641SAndroid Build Coastguard Worker
10*635a8641SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
11*635a8641SAndroid Build Coastguard Worker
12*635a8641SAndroid Build Coastguard Worker template <class AtomicType>
TestAtomicIncrement()13*635a8641SAndroid Build Coastguard Worker static void TestAtomicIncrement() {
14*635a8641SAndroid Build Coastguard Worker // For now, we just test single threaded execution
15*635a8641SAndroid Build Coastguard Worker
16*635a8641SAndroid Build Coastguard Worker // use a guard value to make sure the NoBarrier_AtomicIncrement doesn't go
17*635a8641SAndroid Build Coastguard Worker // outside the expected address bounds. This is in particular to
18*635a8641SAndroid Build Coastguard Worker // test that some future change to the asm code doesn't cause the
19*635a8641SAndroid Build Coastguard Worker // 32-bit NoBarrier_AtomicIncrement doesn't do the wrong thing on 64-bit
20*635a8641SAndroid Build Coastguard Worker // machines.
21*635a8641SAndroid Build Coastguard Worker struct {
22*635a8641SAndroid Build Coastguard Worker AtomicType prev_word;
23*635a8641SAndroid Build Coastguard Worker AtomicType count;
24*635a8641SAndroid Build Coastguard Worker AtomicType next_word;
25*635a8641SAndroid Build Coastguard Worker } s;
26*635a8641SAndroid Build Coastguard Worker
27*635a8641SAndroid Build Coastguard Worker AtomicType prev_word_value, next_word_value;
28*635a8641SAndroid Build Coastguard Worker memset(&prev_word_value, 0xFF, sizeof(AtomicType));
29*635a8641SAndroid Build Coastguard Worker memset(&next_word_value, 0xEE, sizeof(AtomicType));
30*635a8641SAndroid Build Coastguard Worker
31*635a8641SAndroid Build Coastguard Worker s.prev_word = prev_word_value;
32*635a8641SAndroid Build Coastguard Worker s.count = 0;
33*635a8641SAndroid Build Coastguard Worker s.next_word = next_word_value;
34*635a8641SAndroid Build Coastguard Worker
35*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 1), 1);
36*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.count, 1);
37*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.prev_word, prev_word_value);
38*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.next_word, next_word_value);
39*635a8641SAndroid Build Coastguard Worker
40*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 2), 3);
41*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.count, 3);
42*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.prev_word, prev_word_value);
43*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.next_word, next_word_value);
44*635a8641SAndroid Build Coastguard Worker
45*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 3), 6);
46*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.count, 6);
47*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.prev_word, prev_word_value);
48*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.next_word, next_word_value);
49*635a8641SAndroid Build Coastguard Worker
50*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -3), 3);
51*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.count, 3);
52*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.prev_word, prev_word_value);
53*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.next_word, next_word_value);
54*635a8641SAndroid Build Coastguard Worker
55*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -2), 1);
56*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.count, 1);
57*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.prev_word, prev_word_value);
58*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.next_word, next_word_value);
59*635a8641SAndroid Build Coastguard Worker
60*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), 0);
61*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.count, 0);
62*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.prev_word, prev_word_value);
63*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.next_word, next_word_value);
64*635a8641SAndroid Build Coastguard Worker
65*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), -1);
66*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.count, -1);
67*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.prev_word, prev_word_value);
68*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.next_word, next_word_value);
69*635a8641SAndroid Build Coastguard Worker
70*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -4), -5);
71*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.count, -5);
72*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.prev_word, prev_word_value);
73*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.next_word, next_word_value);
74*635a8641SAndroid Build Coastguard Worker
75*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 5), 0);
76*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.count, 0);
77*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.prev_word, prev_word_value);
78*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(s.next_word, next_word_value);
79*635a8641SAndroid Build Coastguard Worker }
80*635a8641SAndroid Build Coastguard Worker
81*635a8641SAndroid Build Coastguard Worker
82*635a8641SAndroid Build Coastguard Worker #define NUM_BITS(T) (sizeof(T) * 8)
83*635a8641SAndroid Build Coastguard Worker
84*635a8641SAndroid Build Coastguard Worker
85*635a8641SAndroid Build Coastguard Worker template <class AtomicType>
TestCompareAndSwap()86*635a8641SAndroid Build Coastguard Worker static void TestCompareAndSwap() {
87*635a8641SAndroid Build Coastguard Worker AtomicType value = 0;
88*635a8641SAndroid Build Coastguard Worker AtomicType prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 1);
89*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(1, value);
90*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, prev);
91*635a8641SAndroid Build Coastguard Worker
92*635a8641SAndroid Build Coastguard Worker // Verify that CAS will *not* change "value" if it doesn't match the
93*635a8641SAndroid Build Coastguard Worker // expected number. CAS will always return the actual value of the
94*635a8641SAndroid Build Coastguard Worker // variable from before any change.
95*635a8641SAndroid Build Coastguard Worker AtomicType fail = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 2);
96*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(1, value);
97*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(1, fail);
98*635a8641SAndroid Build Coastguard Worker
99*635a8641SAndroid Build Coastguard Worker // Use test value that has non-zero bits in both halves, more for testing
100*635a8641SAndroid Build Coastguard Worker // 64-bit implementation on 32-bit platforms.
101*635a8641SAndroid Build Coastguard Worker const AtomicType k_test_val = (static_cast<uint64_t>(1) <<
102*635a8641SAndroid Build Coastguard Worker (NUM_BITS(AtomicType) - 2)) + 11;
103*635a8641SAndroid Build Coastguard Worker value = k_test_val;
104*635a8641SAndroid Build Coastguard Worker prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 5);
105*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(k_test_val, value);
106*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(k_test_val, prev);
107*635a8641SAndroid Build Coastguard Worker
108*635a8641SAndroid Build Coastguard Worker value = k_test_val;
109*635a8641SAndroid Build Coastguard Worker prev = base::subtle::NoBarrier_CompareAndSwap(&value, k_test_val, 5);
110*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(5, value);
111*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(k_test_val, prev);
112*635a8641SAndroid Build Coastguard Worker }
113*635a8641SAndroid Build Coastguard Worker
114*635a8641SAndroid Build Coastguard Worker
115*635a8641SAndroid Build Coastguard Worker template <class AtomicType>
TestAtomicExchange()116*635a8641SAndroid Build Coastguard Worker static void TestAtomicExchange() {
117*635a8641SAndroid Build Coastguard Worker AtomicType value = 0;
118*635a8641SAndroid Build Coastguard Worker AtomicType new_value = base::subtle::NoBarrier_AtomicExchange(&value, 1);
119*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(1, value);
120*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(0, new_value);
121*635a8641SAndroid Build Coastguard Worker
122*635a8641SAndroid Build Coastguard Worker // Use test value that has non-zero bits in both halves, more for testing
123*635a8641SAndroid Build Coastguard Worker // 64-bit implementation on 32-bit platforms.
124*635a8641SAndroid Build Coastguard Worker const AtomicType k_test_val = (static_cast<uint64_t>(1) <<
125*635a8641SAndroid Build Coastguard Worker (NUM_BITS(AtomicType) - 2)) + 11;
126*635a8641SAndroid Build Coastguard Worker value = k_test_val;
127*635a8641SAndroid Build Coastguard Worker new_value = base::subtle::NoBarrier_AtomicExchange(&value, k_test_val);
128*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(k_test_val, value);
129*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(k_test_val, new_value);
130*635a8641SAndroid Build Coastguard Worker
131*635a8641SAndroid Build Coastguard Worker value = k_test_val;
132*635a8641SAndroid Build Coastguard Worker new_value = base::subtle::NoBarrier_AtomicExchange(&value, 5);
133*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(5, value);
134*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(k_test_val, new_value);
135*635a8641SAndroid Build Coastguard Worker }
136*635a8641SAndroid Build Coastguard Worker
137*635a8641SAndroid Build Coastguard Worker
138*635a8641SAndroid Build Coastguard Worker template <class AtomicType>
TestAtomicIncrementBounds()139*635a8641SAndroid Build Coastguard Worker static void TestAtomicIncrementBounds() {
140*635a8641SAndroid Build Coastguard Worker // Test at rollover boundary between int_max and int_min
141*635a8641SAndroid Build Coastguard Worker AtomicType test_val = (static_cast<uint64_t>(1) <<
142*635a8641SAndroid Build Coastguard Worker (NUM_BITS(AtomicType) - 1));
143*635a8641SAndroid Build Coastguard Worker AtomicType value = -1 ^ test_val;
144*635a8641SAndroid Build Coastguard Worker AtomicType new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1);
145*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(test_val, value);
146*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(value, new_value);
147*635a8641SAndroid Build Coastguard Worker
148*635a8641SAndroid Build Coastguard Worker base::subtle::NoBarrier_AtomicIncrement(&value, -1);
149*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(-1 ^ test_val, value);
150*635a8641SAndroid Build Coastguard Worker
151*635a8641SAndroid Build Coastguard Worker // Test at 32-bit boundary for 64-bit atomic type.
152*635a8641SAndroid Build Coastguard Worker test_val = static_cast<uint64_t>(1) << (NUM_BITS(AtomicType) / 2);
153*635a8641SAndroid Build Coastguard Worker value = test_val - 1;
154*635a8641SAndroid Build Coastguard Worker new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1);
155*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(test_val, value);
156*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(value, new_value);
157*635a8641SAndroid Build Coastguard Worker
158*635a8641SAndroid Build Coastguard Worker base::subtle::NoBarrier_AtomicIncrement(&value, -1);
159*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(test_val - 1, value);
160*635a8641SAndroid Build Coastguard Worker }
161*635a8641SAndroid Build Coastguard Worker
162*635a8641SAndroid Build Coastguard Worker // Return an AtomicType with the value 0xa5a5a5..
163*635a8641SAndroid Build Coastguard Worker template <class AtomicType>
TestFillValue()164*635a8641SAndroid Build Coastguard Worker static AtomicType TestFillValue() {
165*635a8641SAndroid Build Coastguard Worker AtomicType val = 0;
166*635a8641SAndroid Build Coastguard Worker memset(&val, 0xa5, sizeof(AtomicType));
167*635a8641SAndroid Build Coastguard Worker return val;
168*635a8641SAndroid Build Coastguard Worker }
169*635a8641SAndroid Build Coastguard Worker
170*635a8641SAndroid Build Coastguard Worker // This is a simple sanity check that values are correct. Not testing
171*635a8641SAndroid Build Coastguard Worker // atomicity
172*635a8641SAndroid Build Coastguard Worker template <class AtomicType>
TestStore()173*635a8641SAndroid Build Coastguard Worker static void TestStore() {
174*635a8641SAndroid Build Coastguard Worker const AtomicType kVal1 = TestFillValue<AtomicType>();
175*635a8641SAndroid Build Coastguard Worker const AtomicType kVal2 = static_cast<AtomicType>(-1);
176*635a8641SAndroid Build Coastguard Worker
177*635a8641SAndroid Build Coastguard Worker AtomicType value;
178*635a8641SAndroid Build Coastguard Worker
179*635a8641SAndroid Build Coastguard Worker base::subtle::NoBarrier_Store(&value, kVal1);
180*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kVal1, value);
181*635a8641SAndroid Build Coastguard Worker base::subtle::NoBarrier_Store(&value, kVal2);
182*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kVal2, value);
183*635a8641SAndroid Build Coastguard Worker
184*635a8641SAndroid Build Coastguard Worker base::subtle::Acquire_Store(&value, kVal1);
185*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kVal1, value);
186*635a8641SAndroid Build Coastguard Worker base::subtle::Acquire_Store(&value, kVal2);
187*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kVal2, value);
188*635a8641SAndroid Build Coastguard Worker
189*635a8641SAndroid Build Coastguard Worker base::subtle::Release_Store(&value, kVal1);
190*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kVal1, value);
191*635a8641SAndroid Build Coastguard Worker base::subtle::Release_Store(&value, kVal2);
192*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kVal2, value);
193*635a8641SAndroid Build Coastguard Worker }
194*635a8641SAndroid Build Coastguard Worker
195*635a8641SAndroid Build Coastguard Worker // This is a simple sanity check that values are correct. Not testing
196*635a8641SAndroid Build Coastguard Worker // atomicity
197*635a8641SAndroid Build Coastguard Worker template <class AtomicType>
TestLoad()198*635a8641SAndroid Build Coastguard Worker static void TestLoad() {
199*635a8641SAndroid Build Coastguard Worker const AtomicType kVal1 = TestFillValue<AtomicType>();
200*635a8641SAndroid Build Coastguard Worker const AtomicType kVal2 = static_cast<AtomicType>(-1);
201*635a8641SAndroid Build Coastguard Worker
202*635a8641SAndroid Build Coastguard Worker AtomicType value;
203*635a8641SAndroid Build Coastguard Worker
204*635a8641SAndroid Build Coastguard Worker value = kVal1;
205*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kVal1, base::subtle::NoBarrier_Load(&value));
206*635a8641SAndroid Build Coastguard Worker value = kVal2;
207*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kVal2, base::subtle::NoBarrier_Load(&value));
208*635a8641SAndroid Build Coastguard Worker
209*635a8641SAndroid Build Coastguard Worker value = kVal1;
210*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kVal1, base::subtle::Acquire_Load(&value));
211*635a8641SAndroid Build Coastguard Worker value = kVal2;
212*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kVal2, base::subtle::Acquire_Load(&value));
213*635a8641SAndroid Build Coastguard Worker
214*635a8641SAndroid Build Coastguard Worker value = kVal1;
215*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kVal1, base::subtle::Release_Load(&value));
216*635a8641SAndroid Build Coastguard Worker value = kVal2;
217*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kVal2, base::subtle::Release_Load(&value));
218*635a8641SAndroid Build Coastguard Worker }
219*635a8641SAndroid Build Coastguard Worker
TEST(AtomicOpsTest,Inc)220*635a8641SAndroid Build Coastguard Worker TEST(AtomicOpsTest, Inc) {
221*635a8641SAndroid Build Coastguard Worker TestAtomicIncrement<base::subtle::Atomic32>();
222*635a8641SAndroid Build Coastguard Worker TestAtomicIncrement<base::subtle::AtomicWord>();
223*635a8641SAndroid Build Coastguard Worker }
224*635a8641SAndroid Build Coastguard Worker
TEST(AtomicOpsTest,CompareAndSwap)225*635a8641SAndroid Build Coastguard Worker TEST(AtomicOpsTest, CompareAndSwap) {
226*635a8641SAndroid Build Coastguard Worker TestCompareAndSwap<base::subtle::Atomic32>();
227*635a8641SAndroid Build Coastguard Worker TestCompareAndSwap<base::subtle::AtomicWord>();
228*635a8641SAndroid Build Coastguard Worker }
229*635a8641SAndroid Build Coastguard Worker
TEST(AtomicOpsTest,Exchange)230*635a8641SAndroid Build Coastguard Worker TEST(AtomicOpsTest, Exchange) {
231*635a8641SAndroid Build Coastguard Worker TestAtomicExchange<base::subtle::Atomic32>();
232*635a8641SAndroid Build Coastguard Worker TestAtomicExchange<base::subtle::AtomicWord>();
233*635a8641SAndroid Build Coastguard Worker }
234*635a8641SAndroid Build Coastguard Worker
TEST(AtomicOpsTest,IncrementBounds)235*635a8641SAndroid Build Coastguard Worker TEST(AtomicOpsTest, IncrementBounds) {
236*635a8641SAndroid Build Coastguard Worker TestAtomicIncrementBounds<base::subtle::Atomic32>();
237*635a8641SAndroid Build Coastguard Worker TestAtomicIncrementBounds<base::subtle::AtomicWord>();
238*635a8641SAndroid Build Coastguard Worker }
239*635a8641SAndroid Build Coastguard Worker
TEST(AtomicOpsTest,Store)240*635a8641SAndroid Build Coastguard Worker TEST(AtomicOpsTest, Store) {
241*635a8641SAndroid Build Coastguard Worker TestStore<base::subtle::Atomic32>();
242*635a8641SAndroid Build Coastguard Worker TestStore<base::subtle::AtomicWord>();
243*635a8641SAndroid Build Coastguard Worker }
244*635a8641SAndroid Build Coastguard Worker
TEST(AtomicOpsTest,Load)245*635a8641SAndroid Build Coastguard Worker TEST(AtomicOpsTest, Load) {
246*635a8641SAndroid Build Coastguard Worker TestLoad<base::subtle::Atomic32>();
247*635a8641SAndroid Build Coastguard Worker TestLoad<base::subtle::AtomicWord>();
248*635a8641SAndroid Build Coastguard Worker }
249