xref: /aosp_15_r20/external/libcxxabi/test/guard_test_basic.pass.cpp (revision c05d8e5dc3e10f6ce4317e8bc22cc4a25f55fa94)
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