150
|
1 //===----------------------------- test_guard.cpp -------------------------===//
|
|
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 #include "cxxabi.h"
|
|
10
|
|
11 #include <cassert>
|
|
12
|
|
13 #ifndef _LIBCXXABI_HAS_NO_THREADS
|
|
14 #include <thread>
|
207
|
15 #include "make_test_thread.h"
|
150
|
16 #endif
|
|
17
|
207
|
18 #include "test_macros.h"
|
|
19
|
150
|
20 // Ensure that we initialize each variable once and only once.
|
|
21 namespace test1 {
|
|
22 static int run_count = 0;
|
|
23 int increment() {
|
|
24 ++run_count;
|
|
25 return 0;
|
|
26 }
|
|
27 void helper() {
|
|
28 static int a = increment();
|
|
29 ((void)a);
|
|
30 }
|
|
31 void test() {
|
|
32 static int a = increment(); ((void)a);
|
|
33 assert(run_count == 1);
|
|
34 static int b = increment(); ((void)b);
|
|
35 assert(run_count == 2);
|
|
36 helper();
|
|
37 assert(run_count == 3);
|
|
38 helper();
|
|
39 assert(run_count == 3);
|
|
40 }
|
|
41 }
|
|
42
|
|
43 // When initialization fails, ensure that we try to initialize it again next
|
|
44 // time.
|
|
45 namespace test2 {
|
207
|
46 #ifndef TEST_HAS_NO_EXCEPTIONS
|
150
|
47 static int run_count = 0;
|
|
48 int increment() {
|
|
49 ++run_count;
|
|
50 throw 0;
|
|
51 }
|
|
52 void helper() {
|
|
53 try {
|
|
54 static int a = increment();
|
|
55 assert(false);
|
|
56 ((void)a);
|
|
57 } catch (...) {}
|
|
58 }
|
|
59 void test() {
|
|
60 helper();
|
|
61 assert(run_count == 1);
|
|
62 helper();
|
|
63 assert(run_count == 2);
|
|
64 }
|
|
65 #else
|
|
66 void test() {}
|
|
67 #endif
|
|
68 }
|
|
69
|
|
70 // Check that we can initialize a second value while initializing a first.
|
|
71 namespace test3 {
|
|
72 int zero() {
|
|
73 return 0;
|
|
74 }
|
|
75
|
|
76 int one() {
|
|
77 static int b = zero(); ((void)b);
|
|
78 return 0;
|
|
79 }
|
|
80
|
|
81 void test() {
|
|
82 static int a = one(); ((void)a);
|
|
83 }
|
|
84 }
|
|
85
|
|
86 #ifndef _LIBCXXABI_HAS_NO_THREADS
|
|
87 // A simple thread test of two threads racing to initialize a variable. This
|
|
88 // isn't guaranteed to catch any particular threading problems.
|
|
89 namespace test4 {
|
|
90 static int run_count = 0;
|
|
91 int increment() {
|
|
92 ++run_count;
|
|
93 return 0;
|
|
94 }
|
|
95
|
|
96 void helper() {
|
|
97 static int a = increment(); ((void)a);
|
|
98 }
|
|
99
|
|
100 void test() {
|
207
|
101 std::thread t1 = support::make_test_thread(helper);
|
|
102 std::thread t2 = support::make_test_thread(helper);
|
150
|
103 t1.join();
|
|
104 t2.join();
|
|
105 assert(run_count == 1);
|
|
106 }
|
|
107 }
|
|
108
|
|
109 // Check that we don't re-initialize a static variable even when it's
|
|
110 // encountered from two different threads.
|
|
111 namespace test5 {
|
|
112 static int run_count = 0;
|
|
113 int zero() {
|
|
114 ++run_count;
|
|
115 return 0;
|
|
116 }
|
|
117
|
|
118 int one() {
|
|
119 static int b = zero(); ((void)b);
|
|
120 return 0;
|
|
121 }
|
|
122
|
|
123 void another_helper() {
|
|
124 static int a = one(); ((void)a);
|
|
125 }
|
|
126
|
|
127 void helper() {
|
|
128 static int a = one(); ((void)a);
|
207
|
129 std::thread t = support::make_test_thread(another_helper);
|
150
|
130 t.join();
|
|
131 }
|
|
132
|
|
133 void test() {
|
207
|
134 std::thread t = support::make_test_thread(helper);
|
150
|
135 t.join();
|
|
136 assert(run_count == 1);
|
|
137 }
|
|
138 }
|
|
139 #endif /* _LIBCXXABI_HAS_NO_THREADS */
|
|
140
|
207
|
141 int main(int, char**)
|
150
|
142 {
|
|
143 test1::test();
|
|
144 test2::test();
|
|
145 test3::test();
|
|
146 #ifndef _LIBCXXABI_HAS_NO_THREADS
|
|
147 test4::test();
|
|
148 test5::test();
|
|
149 #endif
|
207
|
150
|
|
151 return 0;
|
150
|
152 }
|