xref: /llvm-project/llvm/unittests/Support/ManagedStatic.cpp (revision 89e6a288674c9fae33aeb5448c7b1fe782b2bf53)
1 //===- llvm/unittest/Support/ManagedStatic.cpp - ManagedStatic tests ------===//
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 "llvm/Support/ManagedStatic.h"
10 #include "llvm/Config/config.h"
11 #include "llvm/Config/llvm-config.h" // for LLVM_ENABLE_THREADS
12 #include "llvm/Support/Allocator.h"
13 #include "gtest/gtest.h"
14 #ifdef HAVE_PTHREAD_H
15 #include <pthread.h>
16 #endif
17 
18 #include "gtest/gtest.h"
19 
20 using namespace llvm;
21 
22 namespace {
23 
24 #if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H) && \
25   !__has_feature(memory_sanitizer)
26 namespace test1 {
27   llvm::ManagedStatic<int> ms;
28   void *helper(void*) {
29     *ms;
30     return nullptr;
31   }
32 
33   // Valgrind's leak checker complains glibc's stack allocation.
34   // To appease valgrind, we provide our own stack for each thread.
35   void *allocate_stack(pthread_attr_t &a, size_t n = 65536) {
36     void *stack = safe_malloc(n);
37     pthread_attr_init(&a);
38 #if defined(__linux__)
39     pthread_attr_setstack(&a, stack, n);
40 #endif
41     return stack;
42   }
43 }
44 
45 TEST(Initialize, MultipleThreads) {
46   // Run this test under tsan: http://code.google.com/p/data-race-test/
47 
48   pthread_attr_t a1, a2;
49   void *p1 = test1::allocate_stack(a1);
50   void *p2 = test1::allocate_stack(a2);
51 
52   pthread_t t1, t2;
53   pthread_create(&t1, &a1, test1::helper, nullptr);
54   pthread_create(&t2, &a2, test1::helper, nullptr);
55   pthread_join(t1, nullptr);
56   pthread_join(t2, nullptr);
57   free(p1);
58   free(p2);
59 }
60 #endif
61 
62 namespace NestedStatics {
63 static ManagedStatic<int> Ms1;
64 struct Nest {
65   Nest() {
66     ++(*Ms1);
67   }
68 
69   ~Nest() {
70     assert(Ms1.isConstructed());
71     ++(*Ms1);
72   }
73 };
74 static ManagedStatic<Nest> Ms2;
75 
76 TEST(ManagedStaticTest, NestedStatics) {
77   EXPECT_FALSE(Ms1.isConstructed());
78   EXPECT_FALSE(Ms2.isConstructed());
79 
80   *Ms2;
81   EXPECT_TRUE(Ms1.isConstructed());
82   EXPECT_TRUE(Ms2.isConstructed());
83 }
84 } // namespace NestedStatics
85 
86 namespace CustomCreatorDeletor {
87 struct CustomCreate {
88   static void *call() {
89     void *Mem = safe_malloc(sizeof(int));
90     *((int *)Mem) = 42;
91     return Mem;
92   }
93 };
94 struct CustomDelete {
95   static void call(void *P) { std::free(P); }
96 };
97 static ManagedStatic<int, CustomCreate, CustomDelete> Custom;
98 TEST(ManagedStaticTest, CustomCreatorDeletor) {
99   EXPECT_EQ(42, *Custom);
100 }
101 } // namespace CustomCreatorDeletor
102 
103 } // anonymous namespace
104