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