1 //===- unittests/Threading.cpp - Thread 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/Threading.h" 10 #include "llvm/Support/thread.h" 11 #include "gtest/gtest.h" 12 13 #include <atomic> 14 #include <condition_variable> 15 16 using namespace llvm; 17 18 namespace { 19 20 TEST(Threading, PhysicalConcurrency) { 21 auto Num = heavyweight_hardware_concurrency(); 22 // Since Num is unsigned this will also catch us trying to 23 // return -1. 24 ASSERT_LE(Num.compute_thread_count(), 25 hardware_concurrency().compute_thread_count()); 26 } 27 28 #if LLVM_ENABLE_THREADS 29 30 class Notification { 31 public: 32 void notify() { 33 { 34 std::lock_guard<std::mutex> Lock(M); 35 Notified = true; 36 // Broadcast with the lock held, so it's safe to destroy the Notification 37 // after wait() returns. 38 CV.notify_all(); 39 } 40 } 41 42 bool wait() { 43 std::unique_lock<std::mutex> Lock(M); 44 using steady_clock = std::chrono::steady_clock; 45 auto Deadline = steady_clock::now() + 46 std::chrono::duration_cast<steady_clock::duration>( 47 std::chrono::duration<double>(5)); 48 return CV.wait_until(Lock, Deadline, [this] { return Notified; }); 49 } 50 51 private: 52 bool Notified = false; 53 mutable std::condition_variable CV; 54 mutable std::mutex M; 55 }; 56 57 TEST(Threading, RunOnThreadSyncAsync) { 58 Notification ThreadStarted, ThreadAdvanced, ThreadFinished; 59 60 auto ThreadFunc = [&] { 61 ThreadStarted.notify(); 62 ASSERT_TRUE(ThreadAdvanced.wait()); 63 ThreadFinished.notify(); 64 }; 65 66 llvm::thread Thread(ThreadFunc); 67 Thread.detach(); 68 ASSERT_TRUE(ThreadStarted.wait()); 69 ThreadAdvanced.notify(); 70 ASSERT_TRUE(ThreadFinished.wait()); 71 } 72 73 TEST(Threading, RunOnThreadSync) { 74 std::atomic_bool Executed(false); 75 llvm::thread Thread( 76 [](void *Arg) { *static_cast<std::atomic_bool *>(Arg) = true; }, 77 &Executed); 78 Thread.join(); 79 ASSERT_EQ(Executed, true); 80 } 81 82 #if defined(__APPLE__) 83 TEST(Threading, AppleStackSize) { 84 llvm::thread Thread([] { 85 volatile unsigned char Var[8 * 1024 * 1024 - 1024]; 86 Var[0] = 0xff; 87 ASSERT_EQ(Var[0], 0xff); 88 }); 89 Thread.join(); 90 } 91 #endif 92 #endif 93 94 } // end anon namespace 95