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