[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / libcxxabi / test / guard_test_basic.pass.cpp
blob6b15dd042a38db1fc3c1dd175fcdd5b68c1331be
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // UNSUPPORTED: c++03
11 // Necessary because we include a private header of libc++abi, which
12 // only understands _LIBCXXABI_HAS_NO_THREADS.
13 #include "test_macros.h"
14 #ifdef TEST_HAS_NO_THREADS
15 # define _LIBCXXABI_HAS_NO_THREADS
16 #endif
18 #define TESTING_CXA_GUARD
19 #include "../src/cxa_guard_impl.h"
20 #include <cassert>
22 #if defined(__clang__)
23 # pragma clang diagnostic ignored "-Wtautological-pointer-compare"
24 #elif defined(__GNUC__)
25 # pragma GCC diagnostic ignored "-Waddress"
26 #endif
28 using namespace __cxxabiv1;
30 template <class GuardType, class Impl>
31 struct Tests {
32 private:
33 Tests() : g{}, impl(&g) {}
34 GuardType g;
35 Impl impl;
37 uint8_t first_byte() {
38 uint8_t first;
39 std::memcpy(&first, &g, 1);
40 return first;
43 void reset() { g = {}; }
45 public:
46 // Test the post conditions on cxa_guard_acquire, cxa_guard_abort, and
47 // cxa_guard_release. Specifically, that they leave the first byte with
48 // the value 0 or 1 as specified by the ARM or Itanium specification.
49 static void test() {
50 Tests tests;
51 tests.test_acquire();
52 tests.test_abort();
53 tests.test_release();
56 void test_acquire() {
58 reset();
59 assert(first_byte() == 0);
60 assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
61 assert(first_byte() == 0);
64 reset();
65 assert(first_byte() == 0);
66 assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
67 impl.cxa_guard_release();
68 assert(first_byte() == 1);
69 assert(impl.cxa_guard_acquire() == INIT_IS_DONE);
73 void test_release() {
75 reset();
76 assert(first_byte() == 0);
77 assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
78 assert(first_byte() == 0);
79 impl.cxa_guard_release();
80 assert(first_byte() == 1);
84 void test_abort() {
86 reset();
87 assert(first_byte() == 0);
88 assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
89 assert(first_byte() == 0);
90 impl.cxa_guard_abort();
91 assert(first_byte() == 0);
92 assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
93 assert(first_byte() == 0);
98 struct NopMutex {
99 bool lock() {
100 assert(!is_locked);
101 is_locked = true;
102 return false;
104 bool unlock() {
105 assert(is_locked);
106 is_locked = false;
107 return false;
110 private:
111 bool is_locked = false;
113 NopMutex global_nop_mutex = {};
115 struct NopCondVar {
116 bool broadcast() { return false; }
117 bool wait(NopMutex&) { return false; }
119 NopCondVar global_nop_cond = {};
121 void NopFutexWait(int*, int) { assert(false); }
122 void NopFutexWake(int*) { assert(false); }
123 uint32_t MockGetThreadID() { return 0; }
125 int main(int, char**) {
127 #if defined(TEST_HAS_NO_THREADS)
128 static_assert(CurrentImplementation == Implementation::NoThreads, "");
129 static_assert(std::is_same<SelectedImplementation, NoThreadsGuard>::value, "");
130 #else
131 static_assert(CurrentImplementation == Implementation::GlobalMutex, "");
132 static_assert(std::is_same<SelectedImplementation,
133 GlobalMutexGuard<LibcppMutex, LibcppCondVar, GlobalStatic<LibcppMutex>::instance,
134 GlobalStatic<LibcppCondVar>::instance>>::value,
135 "");
136 #endif
139 #if (defined(__APPLE__) || defined(__linux__)) && !defined(TEST_HAS_NO_THREADS)
140 assert(PlatformThreadID);
141 #endif
142 if (PlatformThreadID != nullptr) {
143 assert(PlatformThreadID() != 0);
144 assert(PlatformThreadID() == PlatformThreadID());
148 Tests<uint32_t, NoThreadsGuard>::test();
149 Tests<uint64_t, NoThreadsGuard>::test();
152 using MutexImpl = GlobalMutexGuard<NopMutex, NopCondVar, global_nop_mutex, global_nop_cond, MockGetThreadID>;
153 Tests<uint32_t, MutexImpl>::test();
154 Tests<uint64_t, MutexImpl>::test();
157 using FutexImpl = FutexGuard<&NopFutexWait, &NopFutexWake, &MockGetThreadID>;
158 Tests<uint32_t, FutexImpl>::test();
159 Tests<uint64_t, FutexImpl>::test();
162 return 0;