Nick Lewycky | fe85611 | 2011-11-14 20:50:16 +0000 | [diff] [blame] | 1 | //===- llvm/unittest/Support/ManagedStatic.cpp - ManagedStatic tests ------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
Serge Pavlov | 76d8cce | 2018-02-20 05:41:26 +0000 | [diff] [blame] | 9 | |
| 10 | #include "llvm/Support/Allocator.h" |
Nick Lewycky | fe85611 | 2011-11-14 20:50:16 +0000 | [diff] [blame] | 11 | #include "llvm/Support/ManagedStatic.h" |
Nick Lewycky | e5dc755 | 2011-11-14 22:10:23 +0000 | [diff] [blame] | 12 | #include "llvm/Config/config.h" |
| 13 | #ifdef HAVE_PTHREAD_H |
Nick Lewycky | fe85611 | 2011-11-14 20:50:16 +0000 | [diff] [blame] | 14 | #include <pthread.h> |
Nick Lewycky | e5dc755 | 2011-11-14 22:10:23 +0000 | [diff] [blame] | 15 | #endif |
Nick Lewycky | fe85611 | 2011-11-14 20:50:16 +0000 | [diff] [blame] | 16 | |
| 17 | #include "gtest/gtest.h" |
| 18 | |
| 19 | using namespace llvm; |
| 20 | |
| 21 | namespace { |
| 22 | |
Duncan Sands | b33790d | 2013-05-14 13:29:16 +0000 | [diff] [blame] | 23 | #if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H) && \ |
| 24 | !__has_feature(memory_sanitizer) |
Nick Lewycky | fe85611 | 2011-11-14 20:50:16 +0000 | [diff] [blame] | 25 | namespace test1 { |
| 26 | llvm::ManagedStatic<int> ms; |
| 27 | void *helper(void*) { |
| 28 | *ms; |
Craig Topper | 66f09ad | 2014-06-08 22:29:17 +0000 | [diff] [blame] | 29 | return nullptr; |
Nick Lewycky | fe85611 | 2011-11-14 20:50:16 +0000 | [diff] [blame] | 30 | } |
NAKAMURA Takumi | 2998dcb | 2013-01-24 14:44:02 +0000 | [diff] [blame] | 31 | |
| 32 | // Valgrind's leak checker complains glibc's stack allocation. |
| 33 | // To appease valgrind, we provide our own stack for each thread. |
| 34 | void *allocate_stack(pthread_attr_t &a, size_t n = 65536) { |
Serge Pavlov | 76d8cce | 2018-02-20 05:41:26 +0000 | [diff] [blame] | 35 | void *stack = safe_malloc(n); |
NAKAMURA Takumi | 2998dcb | 2013-01-24 14:44:02 +0000 | [diff] [blame] | 36 | pthread_attr_init(&a); |
NAKAMURA Takumi | cbc86bc | 2013-01-24 15:29:27 +0000 | [diff] [blame] | 37 | #if defined(__linux__) |
NAKAMURA Takumi | 2998dcb | 2013-01-24 14:44:02 +0000 | [diff] [blame] | 38 | pthread_attr_setstack(&a, stack, n); |
NAKAMURA Takumi | cbc86bc | 2013-01-24 15:29:27 +0000 | [diff] [blame] | 39 | #endif |
NAKAMURA Takumi | 2998dcb | 2013-01-24 14:44:02 +0000 | [diff] [blame] | 40 | return stack; |
| 41 | } |
Nick Lewycky | fe85611 | 2011-11-14 20:50:16 +0000 | [diff] [blame] | 42 | } |
| 43 | |
| 44 | TEST(Initialize, MultipleThreads) { |
| 45 | // Run this test under tsan: http://code.google.com/p/data-race-test/ |
| 46 | |
NAKAMURA Takumi | 2998dcb | 2013-01-24 14:44:02 +0000 | [diff] [blame] | 47 | pthread_attr_t a1, a2; |
| 48 | void *p1 = test1::allocate_stack(a1); |
| 49 | void *p2 = test1::allocate_stack(a2); |
| 50 | |
Nick Lewycky | fe85611 | 2011-11-14 20:50:16 +0000 | [diff] [blame] | 51 | pthread_t t1, t2; |
Craig Topper | 66f09ad | 2014-06-08 22:29:17 +0000 | [diff] [blame] | 52 | pthread_create(&t1, &a1, test1::helper, nullptr); |
| 53 | pthread_create(&t2, &a2, test1::helper, nullptr); |
| 54 | pthread_join(t1, nullptr); |
| 55 | pthread_join(t2, nullptr); |
NAKAMURA Takumi | 2998dcb | 2013-01-24 14:44:02 +0000 | [diff] [blame] | 56 | free(p1); |
| 57 | free(p2); |
Nick Lewycky | fe85611 | 2011-11-14 20:50:16 +0000 | [diff] [blame] | 58 | } |
Nick Lewycky | e5dc755 | 2011-11-14 22:10:23 +0000 | [diff] [blame] | 59 | #endif |
Nick Lewycky | fe85611 | 2011-11-14 20:50:16 +0000 | [diff] [blame] | 60 | |
Benjamin Kramer | 1533eda | 2017-05-29 14:05:26 +0000 | [diff] [blame] | 61 | namespace NestedStatics { |
| 62 | static ManagedStatic<int> Ms1; |
| 63 | struct Nest { |
| 64 | Nest() { |
| 65 | ++(*Ms1); |
| 66 | } |
| 67 | |
| 68 | ~Nest() { |
| 69 | assert(Ms1.isConstructed()); |
| 70 | ++(*Ms1); |
| 71 | } |
| 72 | }; |
| 73 | static ManagedStatic<Nest> Ms2; |
| 74 | |
| 75 | TEST(ManagedStaticTest, NestedStatics) { |
| 76 | EXPECT_FALSE(Ms1.isConstructed()); |
| 77 | EXPECT_FALSE(Ms2.isConstructed()); |
| 78 | |
| 79 | *Ms2; |
| 80 | EXPECT_TRUE(Ms1.isConstructed()); |
| 81 | EXPECT_TRUE(Ms2.isConstructed()); |
Benjamin Kramer | 1533eda | 2017-05-29 14:05:26 +0000 | [diff] [blame] | 82 | } |
| 83 | } // namespace NestedStatics |
| 84 | |
| 85 | namespace CustomCreatorDeletor { |
Benjamin Kramer | 74de080 | 2017-05-29 20:56:27 +0000 | [diff] [blame] | 86 | struct CustomCreate { |
| 87 | static void *call() { |
Serge Pavlov | 76d8cce | 2018-02-20 05:41:26 +0000 | [diff] [blame] | 88 | void *Mem = safe_malloc(sizeof(int)); |
Benjamin Kramer | 74de080 | 2017-05-29 20:56:27 +0000 | [diff] [blame] | 89 | *((int *)Mem) = 42; |
| 90 | return Mem; |
| 91 | } |
| 92 | }; |
| 93 | struct CustomDelete { |
| 94 | static void call(void *P) { std::free(P); } |
| 95 | }; |
| 96 | static ManagedStatic<int, CustomCreate, CustomDelete> Custom; |
Benjamin Kramer | 1533eda | 2017-05-29 14:05:26 +0000 | [diff] [blame] | 97 | TEST(ManagedStaticTest, CustomCreatorDeletor) { |
| 98 | EXPECT_EQ(42, *Custom); |
Benjamin Kramer | 1533eda | 2017-05-29 14:05:26 +0000 | [diff] [blame] | 99 | } |
| 100 | } // namespace CustomCreatorDeletor |
| 101 | |
Nick Lewycky | fe85611 | 2011-11-14 20:50:16 +0000 | [diff] [blame] | 102 | } // anonymous namespace |