1*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2*c05d8e5dSAndroid Build Coastguard Worker //
3*c05d8e5dSAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*c05d8e5dSAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*c05d8e5dSAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*c05d8e5dSAndroid Build Coastguard Worker //
7*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*c05d8e5dSAndroid Build Coastguard Worker //
9*c05d8e5dSAndroid Build Coastguard Worker // UNSUPPORTED: c++98, c++03
10*c05d8e5dSAndroid Build Coastguard Worker
11*c05d8e5dSAndroid Build Coastguard Worker #define TESTING_CXA_GUARD
12*c05d8e5dSAndroid Build Coastguard Worker #include "../src/cxa_guard_impl.h"
13*c05d8e5dSAndroid Build Coastguard Worker
14*c05d8e5dSAndroid Build Coastguard Worker using namespace __cxxabiv1;
15*c05d8e5dSAndroid Build Coastguard Worker
16*c05d8e5dSAndroid Build Coastguard Worker template <class GuardType, class Impl>
17*c05d8e5dSAndroid Build Coastguard Worker struct Tests {
18*c05d8e5dSAndroid Build Coastguard Worker private:
TestsTests19*c05d8e5dSAndroid Build Coastguard Worker Tests() : g{}, impl(&g) {}
20*c05d8e5dSAndroid Build Coastguard Worker GuardType g;
21*c05d8e5dSAndroid Build Coastguard Worker Impl impl;
22*c05d8e5dSAndroid Build Coastguard Worker
first_byteTests23*c05d8e5dSAndroid Build Coastguard Worker uint8_t first_byte() {
24*c05d8e5dSAndroid Build Coastguard Worker uint8_t first;
25*c05d8e5dSAndroid Build Coastguard Worker std::memcpy(&first, &g, 1);
26*c05d8e5dSAndroid Build Coastguard Worker return first;
27*c05d8e5dSAndroid Build Coastguard Worker }
28*c05d8e5dSAndroid Build Coastguard Worker
resetTests29*c05d8e5dSAndroid Build Coastguard Worker void reset() { g = {}; }
30*c05d8e5dSAndroid Build Coastguard Worker
31*c05d8e5dSAndroid Build Coastguard Worker public:
32*c05d8e5dSAndroid Build Coastguard Worker // Test the post conditions on cxa_guard_acquire, cxa_guard_abort, and
33*c05d8e5dSAndroid Build Coastguard Worker // cxa_guard_release. Specifically, that they leave the first byte with
34*c05d8e5dSAndroid Build Coastguard Worker // the value 0 or 1 as specified by the ARM or Itanium specification.
testTests35*c05d8e5dSAndroid Build Coastguard Worker static void test() {
36*c05d8e5dSAndroid Build Coastguard Worker Tests tests;
37*c05d8e5dSAndroid Build Coastguard Worker tests.test_acquire();
38*c05d8e5dSAndroid Build Coastguard Worker tests.test_abort();
39*c05d8e5dSAndroid Build Coastguard Worker tests.test_release();
40*c05d8e5dSAndroid Build Coastguard Worker }
41*c05d8e5dSAndroid Build Coastguard Worker
test_acquireTests42*c05d8e5dSAndroid Build Coastguard Worker void test_acquire() {
43*c05d8e5dSAndroid Build Coastguard Worker {
44*c05d8e5dSAndroid Build Coastguard Worker reset();
45*c05d8e5dSAndroid Build Coastguard Worker assert(first_byte() == 0);
46*c05d8e5dSAndroid Build Coastguard Worker assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
47*c05d8e5dSAndroid Build Coastguard Worker assert(first_byte() == 0);
48*c05d8e5dSAndroid Build Coastguard Worker }
49*c05d8e5dSAndroid Build Coastguard Worker {
50*c05d8e5dSAndroid Build Coastguard Worker reset();
51*c05d8e5dSAndroid Build Coastguard Worker assert(first_byte() == 0);
52*c05d8e5dSAndroid Build Coastguard Worker assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
53*c05d8e5dSAndroid Build Coastguard Worker impl.cxa_guard_release();
54*c05d8e5dSAndroid Build Coastguard Worker assert(first_byte() == 1);
55*c05d8e5dSAndroid Build Coastguard Worker assert(impl.cxa_guard_acquire() == INIT_IS_DONE);
56*c05d8e5dSAndroid Build Coastguard Worker }
57*c05d8e5dSAndroid Build Coastguard Worker }
58*c05d8e5dSAndroid Build Coastguard Worker
test_releaseTests59*c05d8e5dSAndroid Build Coastguard Worker void test_release() {
60*c05d8e5dSAndroid Build Coastguard Worker {
61*c05d8e5dSAndroid Build Coastguard Worker reset();
62*c05d8e5dSAndroid Build Coastguard Worker assert(first_byte() == 0);
63*c05d8e5dSAndroid Build Coastguard Worker assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
64*c05d8e5dSAndroid Build Coastguard Worker assert(first_byte() == 0);
65*c05d8e5dSAndroid Build Coastguard Worker impl.cxa_guard_release();
66*c05d8e5dSAndroid Build Coastguard Worker assert(first_byte() == 1);
67*c05d8e5dSAndroid Build Coastguard Worker }
68*c05d8e5dSAndroid Build Coastguard Worker }
69*c05d8e5dSAndroid Build Coastguard Worker
test_abortTests70*c05d8e5dSAndroid Build Coastguard Worker void test_abort() {
71*c05d8e5dSAndroid Build Coastguard Worker {
72*c05d8e5dSAndroid Build Coastguard Worker reset();
73*c05d8e5dSAndroid Build Coastguard Worker assert(first_byte() == 0);
74*c05d8e5dSAndroid Build Coastguard Worker assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
75*c05d8e5dSAndroid Build Coastguard Worker assert(first_byte() == 0);
76*c05d8e5dSAndroid Build Coastguard Worker impl.cxa_guard_abort();
77*c05d8e5dSAndroid Build Coastguard Worker assert(first_byte() == 0);
78*c05d8e5dSAndroid Build Coastguard Worker assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
79*c05d8e5dSAndroid Build Coastguard Worker assert(first_byte() == 0);
80*c05d8e5dSAndroid Build Coastguard Worker }
81*c05d8e5dSAndroid Build Coastguard Worker }
82*c05d8e5dSAndroid Build Coastguard Worker };
83*c05d8e5dSAndroid Build Coastguard Worker
84*c05d8e5dSAndroid Build Coastguard Worker struct NopMutex {
lockNopMutex85*c05d8e5dSAndroid Build Coastguard Worker bool lock() {
86*c05d8e5dSAndroid Build Coastguard Worker assert(!is_locked);
87*c05d8e5dSAndroid Build Coastguard Worker is_locked = true;
88*c05d8e5dSAndroid Build Coastguard Worker return false;
89*c05d8e5dSAndroid Build Coastguard Worker }
unlockNopMutex90*c05d8e5dSAndroid Build Coastguard Worker bool unlock() {
91*c05d8e5dSAndroid Build Coastguard Worker assert(is_locked);
92*c05d8e5dSAndroid Build Coastguard Worker is_locked = false;
93*c05d8e5dSAndroid Build Coastguard Worker return false;
94*c05d8e5dSAndroid Build Coastguard Worker }
95*c05d8e5dSAndroid Build Coastguard Worker
96*c05d8e5dSAndroid Build Coastguard Worker private:
97*c05d8e5dSAndroid Build Coastguard Worker bool is_locked = false;
98*c05d8e5dSAndroid Build Coastguard Worker };
99*c05d8e5dSAndroid Build Coastguard Worker static NopMutex global_nop_mutex = {};
100*c05d8e5dSAndroid Build Coastguard Worker
101*c05d8e5dSAndroid Build Coastguard Worker struct NopCondVar {
broadcastNopCondVar102*c05d8e5dSAndroid Build Coastguard Worker bool broadcast() { return false; }
waitNopCondVar103*c05d8e5dSAndroid Build Coastguard Worker bool wait(NopMutex&) { return false; }
104*c05d8e5dSAndroid Build Coastguard Worker };
105*c05d8e5dSAndroid Build Coastguard Worker static NopCondVar global_nop_cond = {};
106*c05d8e5dSAndroid Build Coastguard Worker
NopFutexWait(int *,int)107*c05d8e5dSAndroid Build Coastguard Worker void NopFutexWait(int*, int) { assert(false); }
NopFutexWake(int *)108*c05d8e5dSAndroid Build Coastguard Worker void NopFutexWake(int*) { assert(false); }
MockGetThreadID()109*c05d8e5dSAndroid Build Coastguard Worker uint32_t MockGetThreadID() { return 0; }
110*c05d8e5dSAndroid Build Coastguard Worker
main()111*c05d8e5dSAndroid Build Coastguard Worker int main() {
112*c05d8e5dSAndroid Build Coastguard Worker {
113*c05d8e5dSAndroid Build Coastguard Worker #if defined(_LIBCXXABI_HAS_NO_THREADS)
114*c05d8e5dSAndroid Build Coastguard Worker static_assert(CurrentImplementation == Implementation::NoThreads, "");
115*c05d8e5dSAndroid Build Coastguard Worker static_assert(
116*c05d8e5dSAndroid Build Coastguard Worker std::is_same<SelectedImplementation, InitByteNoThreads>::value, "");
117*c05d8e5dSAndroid Build Coastguard Worker #else
118*c05d8e5dSAndroid Build Coastguard Worker static_assert(CurrentImplementation == Implementation::GlobalLock, "");
119*c05d8e5dSAndroid Build Coastguard Worker static_assert(
120*c05d8e5dSAndroid Build Coastguard Worker std::is_same<
121*c05d8e5dSAndroid Build Coastguard Worker SelectedImplementation,
122*c05d8e5dSAndroid Build Coastguard Worker InitByteGlobalMutex<LibcppMutex, LibcppCondVar,
123*c05d8e5dSAndroid Build Coastguard Worker GlobalStatic<LibcppMutex>::instance,
124*c05d8e5dSAndroid Build Coastguard Worker GlobalStatic<LibcppCondVar>::instance>>::value,
125*c05d8e5dSAndroid Build Coastguard Worker "");
126*c05d8e5dSAndroid Build Coastguard Worker #endif
127*c05d8e5dSAndroid Build Coastguard Worker }
128*c05d8e5dSAndroid Build Coastguard Worker {
129*c05d8e5dSAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__linux__)
130*c05d8e5dSAndroid Build Coastguard Worker assert(PlatformThreadID);
131*c05d8e5dSAndroid Build Coastguard Worker #endif
132*c05d8e5dSAndroid Build Coastguard Worker if (PlatformSupportsThreadID()) {
133*c05d8e5dSAndroid Build Coastguard Worker assert(PlatformThreadID() != 0);
134*c05d8e5dSAndroid Build Coastguard Worker assert(PlatformThreadID() == PlatformThreadID());
135*c05d8e5dSAndroid Build Coastguard Worker }
136*c05d8e5dSAndroid Build Coastguard Worker }
137*c05d8e5dSAndroid Build Coastguard Worker {
138*c05d8e5dSAndroid Build Coastguard Worker Tests<uint32_t, InitByteNoThreads>::test();
139*c05d8e5dSAndroid Build Coastguard Worker Tests<uint64_t, InitByteNoThreads>::test();
140*c05d8e5dSAndroid Build Coastguard Worker }
141*c05d8e5dSAndroid Build Coastguard Worker {
142*c05d8e5dSAndroid Build Coastguard Worker using MutexImpl =
143*c05d8e5dSAndroid Build Coastguard Worker InitByteGlobalMutex<NopMutex, NopCondVar, global_nop_mutex,
144*c05d8e5dSAndroid Build Coastguard Worker global_nop_cond, MockGetThreadID>;
145*c05d8e5dSAndroid Build Coastguard Worker Tests<uint32_t, MutexImpl>::test();
146*c05d8e5dSAndroid Build Coastguard Worker Tests<uint64_t, MutexImpl>::test();
147*c05d8e5dSAndroid Build Coastguard Worker }
148*c05d8e5dSAndroid Build Coastguard Worker {
149*c05d8e5dSAndroid Build Coastguard Worker using FutexImpl =
150*c05d8e5dSAndroid Build Coastguard Worker InitByteFutex<&NopFutexWait, &NopFutexWake, &MockGetThreadID>;
151*c05d8e5dSAndroid Build Coastguard Worker Tests<uint32_t, FutexImpl>::test();
152*c05d8e5dSAndroid Build Coastguard Worker Tests<uint64_t, FutexImpl>::test();
153*c05d8e5dSAndroid Build Coastguard Worker }
154*c05d8e5dSAndroid Build Coastguard Worker }
155