blob: 0da33ad50c0789c044f6593696e5a92d243712b4 [file] [log] [blame]
Mehdi Amini33a7ea42015-12-15 00:59:19 +00001//========- unittests/Support/ThreadPools.cpp - ThreadPools.h 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//===----------------------------------------------------------------------===//
9
10#include "llvm/Support/ThreadPool.h"
11
12#include "llvm/ADT/STLExtras.h"
Mehdi Amini942e52c2015-12-15 09:10:25 +000013#include "llvm/ADT/SmallVector.h"
14#include "llvm/ADT/Triple.h"
15#include "llvm/Support/Host.h"
16#include "llvm/Support/TargetSelect.h"
Mehdi Amini33a7ea42015-12-15 00:59:19 +000017
18#include "gtest/gtest.h"
19
20using namespace llvm;
Mehdi Amini33a7ea42015-12-15 00:59:19 +000021
Mehdi Amini942e52c2015-12-15 09:10:25 +000022// Fixture for the unittests, allowing to *temporarily* disable the unittests
23// on a particular platform
24class ThreadPoolTest : public testing::Test {
25 Triple Host;
26 SmallVector<Triple::ArchType, 4> UnsupportedArchs;
27 SmallVector<Triple::OSType, 4> UnsupportedOSs;
28 SmallVector<Triple::EnvironmentType, 1> UnsupportedEnvironments;
29protected:
30 // This is intended for platform as a temporary "XFAIL"
31 bool isUnsupportedOSOrEnvironment() {
32 Triple Host(Triple::normalize(sys::getProcessTriple()));
33
David Majnemer0d955d02016-08-11 22:21:41 +000034 if (find(UnsupportedEnvironments, Host.getEnvironment()) !=
35 UnsupportedEnvironments.end())
Mehdi Amini942e52c2015-12-15 09:10:25 +000036 return true;
37
David Majnemer0d955d02016-08-11 22:21:41 +000038 if (is_contained(UnsupportedOSs, Host.getOS()))
Mehdi Amini942e52c2015-12-15 09:10:25 +000039 return true;
40
David Majnemer0d955d02016-08-11 22:21:41 +000041 if (is_contained(UnsupportedArchs, Host.getArch()))
Mehdi Amini942e52c2015-12-15 09:10:25 +000042 return true;
43
44 return false;
45 }
46
47 ThreadPoolTest() {
48 // Add unsupported configuration here, example:
49 // UnsupportedArchs.push_back(Triple::x86_64);
Mehdi Amini4b8d75b2015-12-15 09:10:28 +000050
51 // See https://llvm.org/bugs/show_bug.cgi?id=25829
52 UnsupportedArchs.push_back(Triple::ppc64le);
53 UnsupportedArchs.push_back(Triple::ppc64);
Mehdi Amini942e52c2015-12-15 09:10:25 +000054 }
Mehdi Amini0129fca2015-12-19 05:12:07 +000055
56 /// Make sure this thread not progress faster than the main thread.
57 void waitForMainThread() {
Vedant Kumar3791e3d2015-12-19 09:54:27 +000058 std::unique_lock<std::mutex> LockGuard(WaitMainThreadMutex);
59 WaitMainThread.wait(LockGuard, [&] { return MainThreadReady; });
Mehdi Amini0129fca2015-12-19 05:12:07 +000060 }
Vedant Kumar2cf75332015-12-19 09:49:09 +000061
62 /// Set the readiness of the main thread.
Mehdi Aminifa4e4742015-12-19 22:56:24 +000063 void setMainThreadReady() {
64 {
65 std::unique_lock<std::mutex> LockGuard(WaitMainThreadMutex);
66 MainThreadReady = true;
67 }
Vedant Kumar2cf75332015-12-19 09:49:09 +000068 WaitMainThread.notify_all();
69 }
70
Mehdi Aminifa4e4742015-12-19 22:56:24 +000071 void SetUp() override { MainThreadReady = false; }
72
Mehdi Amini0129fca2015-12-19 05:12:07 +000073 std::condition_variable WaitMainThread;
74 std::mutex WaitMainThreadMutex;
75 bool MainThreadReady;
76
Mehdi Amini942e52c2015-12-15 09:10:25 +000077};
78
79#define CHECK_UNSUPPORTED() \
80 do { \
81 if (isUnsupportedOSOrEnvironment()) \
82 return; \
83 } while (0); \
84
85TEST_F(ThreadPoolTest, AsyncBarrier) {
86 CHECK_UNSUPPORTED();
Mehdi Amini33a7ea42015-12-15 00:59:19 +000087 // test that async & barrier work together properly.
88
89 std::atomic_int checked_in{0};
90
91 ThreadPool Pool;
92 for (size_t i = 0; i < 5; ++i) {
Malcolm Parsons17d266b2017-01-13 17:12:16 +000093 Pool.async([this, &checked_in] {
Mehdi Amini0129fca2015-12-19 05:12:07 +000094 waitForMainThread();
Mehdi Amini33a7ea42015-12-15 00:59:19 +000095 ++checked_in;
96 });
97 }
Mehdi Amini0129fca2015-12-19 05:12:07 +000098 ASSERT_EQ(0, checked_in);
Mehdi Aminifa4e4742015-12-19 22:56:24 +000099 setMainThreadReady();
Mehdi Amini33a7ea42015-12-15 00:59:19 +0000100 Pool.wait();
101 ASSERT_EQ(5, checked_in);
102}
103
Teresa Johnsonf064d622015-12-15 04:44:02 +0000104static void TestFunc(std::atomic_int &checked_in, int i) { checked_in += i; }
105
Mehdi Amini942e52c2015-12-15 09:10:25 +0000106TEST_F(ThreadPoolTest, AsyncBarrierArgs) {
107 CHECK_UNSUPPORTED();
Teresa Johnsonf064d622015-12-15 04:44:02 +0000108 // Test that async works with a function requiring multiple parameters.
109 std::atomic_int checked_in{0};
110
111 ThreadPool Pool;
112 for (size_t i = 0; i < 5; ++i) {
113 Pool.async(TestFunc, std::ref(checked_in), i);
114 }
115 Pool.wait();
116 ASSERT_EQ(10, checked_in);
117}
118
Mehdi Amini942e52c2015-12-15 09:10:25 +0000119TEST_F(ThreadPoolTest, Async) {
120 CHECK_UNSUPPORTED();
Mehdi Amini33a7ea42015-12-15 00:59:19 +0000121 ThreadPool Pool;
122 std::atomic_int i{0};
Mehdi Amini0129fca2015-12-19 05:12:07 +0000123 Pool.async([this, &i] {
124 waitForMainThread();
Mehdi Amini33a7ea42015-12-15 00:59:19 +0000125 ++i;
126 });
127 Pool.async([&i] { ++i; });
Mehdi Amini0129fca2015-12-19 05:12:07 +0000128 ASSERT_NE(2, i.load());
Mehdi Aminifa4e4742015-12-19 22:56:24 +0000129 setMainThreadReady();
Mehdi Amini33a7ea42015-12-15 00:59:19 +0000130 Pool.wait();
131 ASSERT_EQ(2, i.load());
132}
133
Davide Italiano0f0d5d82016-11-28 09:17:12 +0000134TEST_F(ThreadPoolTest, GetFuture) {
135 CHECK_UNSUPPORTED();
136 ThreadPool Pool{2};
137 std::atomic_int i{0};
138 Pool.async([this, &i] {
139 waitForMainThread();
140 ++i;
141 });
142 // Force the future using get()
143 Pool.async([&i] { ++i; }).get();
144 ASSERT_NE(2, i.load());
145 setMainThreadReady();
146 Pool.wait();
147 ASSERT_EQ(2, i.load());
148}
149
Mehdi Amini942e52c2015-12-15 09:10:25 +0000150TEST_F(ThreadPoolTest, PoolDestruction) {
151 CHECK_UNSUPPORTED();
Mehdi Amini33a7ea42015-12-15 00:59:19 +0000152 // Test that we are waiting on destruction
153 std::atomic_int checked_in{0};
Mehdi Amini33a7ea42015-12-15 00:59:19 +0000154 {
155 ThreadPool Pool;
156 for (size_t i = 0; i < 5; ++i) {
Malcolm Parsons17d266b2017-01-13 17:12:16 +0000157 Pool.async([this, &checked_in] {
Mehdi Amini0129fca2015-12-19 05:12:07 +0000158 waitForMainThread();
Mehdi Amini33a7ea42015-12-15 00:59:19 +0000159 ++checked_in;
160 });
161 }
Mehdi Amini0129fca2015-12-19 05:12:07 +0000162 ASSERT_EQ(0, checked_in);
Mehdi Aminifa4e4742015-12-19 22:56:24 +0000163 setMainThreadReady();
Mehdi Amini33a7ea42015-12-15 00:59:19 +0000164 }
165 ASSERT_EQ(5, checked_in);
166}