1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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
18 #define TESTING_CXA_GUARD
19 #include "../src/cxa_guard_impl.h"
22 #if defined(__clang__)
23 # pragma clang diagnostic ignored "-Wtautological-pointer-compare"
24 #elif defined(__GNUC__)
25 # pragma GCC diagnostic ignored "-Waddress"
28 using namespace __cxxabiv1
;
30 template <class GuardType
, class Impl
>
33 Tests() : g
{}, impl(&g
) {}
37 uint8_t first_byte() {
39 std::memcpy(&first
, &g
, 1);
43 void reset() { g
= {}; }
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.
59 assert(first_byte() == 0);
60 assert(impl
.cxa_guard_acquire() == INIT_IS_PENDING
);
61 assert(first_byte() == 0);
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
);
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);
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);
111 bool is_locked
= false;
113 NopMutex global_nop_mutex
= {};
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
, "");
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
,
139 #if (defined(__APPLE__) || defined(__linux__)) && !defined(TEST_HAS_NO_THREADS)
140 assert(PlatformThreadID
);
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();