llvm-project

Форк
0
/
guard_test_basic.pass.cpp 
164 строки · 4.3 Кб
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
10

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
17

18
#define TESTING_CXA_GUARD
19
#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
#endif
28

29
using namespace __cxxabiv1;
30

31
template <class GuardType, class Impl>
32
struct Tests {
33
private:
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

46
public:
47
  // Test the post conditions on cxa_guard_acquire, cxa_guard_abort, and
48
  // cxa_guard_release. Specifically, that they leave the first byte with
49
  // 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

99
struct 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

111
private:
112
  bool is_locked = false;
113
};
114
NopMutex global_nop_mutex = {};
115

116
struct NopCondVar {
117
  bool broadcast() { return false; }
118
  bool wait(NopMutex&) { return false; }
119
};
120
NopCondVar global_nop_cond = {};
121

122
void NopFutexWait(int*, int) { assert(false); }
123
void NopFutexWake(int*) { assert(false); }
124
uint32_t MockGetThreadID() { return 0; }
125

126
int 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
#else
132
    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
#endif
138
  }
139
  {
140
#if (defined(__APPLE__) || defined(__linux__))  && !defined(TEST_HAS_NO_THREADS)
141
    assert(PlatformThreadID);
142
#endif
143
    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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.