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> 15 #include "make_test_thread.h" 16 #endif 17 18 #include "test_macros.h" 19 20 // Ensure that we initialize each variable once and only once. 21 namespace test1 { 22 static int run_count = 0; increment()23 int increment() { 24 ++run_count; 25 return 0; 26 } helper()27 void helper() { 28 static int a = increment(); 29 ((void)a); 30 } test()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 { 46 #ifndef TEST_HAS_NO_EXCEPTIONS 47 static int run_count = 0; increment()48 int increment() { 49 ++run_count; 50 throw 0; 51 } helper()52 void helper() { 53 try { 54 static int a = increment(); 55 assert(false); 56 ((void)a); 57 } catch (...) {} 58 } test()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 { zero()72 int zero() { 73 return 0; 74 } 75 one()76 int one() { 77 static int b = zero(); ((void)b); 78 return 0; 79 } 80 test()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; increment()91 int increment() { 92 ++run_count; 93 return 0; 94 } 95 helper()96 void helper() { 97 static int a = increment(); ((void)a); 98 } 99 test()100 void test() { 101 std::thread t1 = support::make_test_thread(helper); 102 std::thread t2 = support::make_test_thread(helper); 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; zero()113 int zero() { 114 ++run_count; 115 return 0; 116 } 117 one()118 int one() { 119 static int b = zero(); ((void)b); 120 return 0; 121 } 122 another_helper()123 void another_helper() { 124 static int a = one(); ((void)a); 125 } 126 helper()127 void helper() { 128 static int a = one(); ((void)a); 129 std::thread t = support::make_test_thread(another_helper); 130 t.join(); 131 } 132 test()133 void test() { 134 std::thread t = support::make_test_thread(helper); 135 t.join(); 136 assert(run_count == 1); 137 } 138 } 139 #endif /* _LIBCXXABI_HAS_NO_THREADS */ 140 main(int,char **)141int main(int, char**) 142 { 143 test1::test(); 144 test2::test(); 145 test3::test(); 146 #ifndef _LIBCXXABI_HAS_NO_THREADS 147 test4::test(); 148 test5::test(); 149 #endif 150 151 return 0; 152 } 153