tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestAtomics.cpp (9016B)


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