brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.3 KiB · dca906a Raw
165 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// UNSUPPORTED: c++0310 11// Necessary because we include a private header of libc++abi, which12// only understands _LIBCXXABI_HAS_NO_THREADS.13#include "test_macros.h"14#ifdef TEST_HAS_NO_THREADS15# define _LIBCXXABI_HAS_NO_THREADS16#endif17 18#define TESTING_CXA_GUARD19#include "../src/cxa_guard_impl.h"20#include <cassert>21#include <type_traits>22 23#if defined(__clang__)24#  pragma clang diagnostic ignored "-Wtautological-pointer-compare"25#elif defined(__GNUC__)26#  pragma GCC diagnostic ignored "-Waddress"27#endif28 29using namespace __cxxabiv1;30 31template <class GuardType, class Impl>32struct Tests {33private:34  Tests() : g{}, impl(&g) {}35  GuardType g;36  Impl impl;37 38  uint8_t first_byte() {39    uint8_t first;40    std::memcpy(&first, &g, 1);41    return first;42  }43 44  void reset() { g = {}; }45 46public:47  // Test the post conditions on cxa_guard_acquire, cxa_guard_abort, and48  // cxa_guard_release. Specifically, that they leave the first byte with49  // the value 0 or 1 as specified by the ARM or Itanium specification.50  static void test() {51    Tests tests;52    tests.test_acquire();53    tests.test_abort();54    tests.test_release();55  }56 57  void test_acquire() {58    {59      reset();60      assert(first_byte() == 0);61      assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);62      assert(first_byte() == 0);63    }64    {65      reset();66      assert(first_byte() == 0);67      assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);68      impl.cxa_guard_release();69      assert(first_byte() == 1);70      assert(impl.cxa_guard_acquire() == INIT_IS_DONE);71    }72  }73 74  void test_release() {75    {76      reset();77      assert(first_byte() == 0);78      assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);79      assert(first_byte() == 0);80      impl.cxa_guard_release();81      assert(first_byte() == 1);82    }83  }84 85  void test_abort() {86    {87      reset();88      assert(first_byte() == 0);89      assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);90      assert(first_byte() == 0);91      impl.cxa_guard_abort();92      assert(first_byte() == 0);93      assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);94      assert(first_byte() == 0);95    }96  }97};98 99struct NopMutex {100  bool lock() {101    assert(!is_locked);102    is_locked = true;103    return false;104  }105  bool unlock() {106    assert(is_locked);107    is_locked = false;108    return false;109  }110 111private:112  bool is_locked = false;113};114NopMutex global_nop_mutex = {};115 116struct NopCondVar {117  bool broadcast() { return false; }118  bool wait(NopMutex&) { return false; }119};120NopCondVar global_nop_cond = {};121 122void NopFutexWait(int*, int) { assert(false); }123void NopFutexWake(int*) { assert(false); }124uint32_t MockGetThreadID() { return 0; }125 126int main(int, char**) {127  {128#if defined(TEST_HAS_NO_THREADS)129    static_assert(CurrentImplementation == Implementation::NoThreads, "");130    static_assert(std::is_same<SelectedImplementation, NoThreadsGuard>::value, "");131#else132    static_assert(CurrentImplementation == Implementation::GlobalMutex, "");133    static_assert(std::is_same<SelectedImplementation,134                               GlobalMutexGuard<LibcppMutex, LibcppCondVar, GlobalStatic<LibcppMutex>::instance,135                                                GlobalStatic<LibcppCondVar>::instance>>::value,136                  "");137#endif138  }139  {140#if (defined(__APPLE__) || defined(__linux__))  && !defined(TEST_HAS_NO_THREADS)141    assert(PlatformThreadID);142#endif143    if (PlatformThreadID != nullptr) {144      assert(PlatformThreadID() != 0);145      assert(PlatformThreadID() == PlatformThreadID());146    }147  }148  {149    Tests<uint32_t, NoThreadsGuard>::test();150    Tests<uint64_t, NoThreadsGuard>::test();151  }152  {153    using MutexImpl = GlobalMutexGuard<NopMutex, NopCondVar, global_nop_mutex, global_nop_cond, MockGetThreadID>;154    Tests<uint32_t, MutexImpl>::test();155    Tests<uint64_t, MutexImpl>::test();156  }157  {158    using FutexImpl = FutexGuard<&NopFutexWait, &NopFutexWake, &MockGetThreadID>;159    Tests<uint32_t, FutexImpl>::test();160    Tests<uint64_t, FutexImpl>::test();161  }162 163  return 0;164}165