1 //===-- thread_contention.cpp -----------------------------------*- C++ -*-===// 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 "gwp_asan/tests/harness.h" 10 11 // Note: Compilation of <atomic> and <thread> are extremely expensive for 12 // non-opt builds of clang. 13 #include <atomic> 14 #include <cstdlib> 15 #include <thread> 16 #include <vector> 17 18 void asyncTask(gwp_asan::GuardedPoolAllocator *GPA, 19 std::atomic<bool> *StartingGun, unsigned NumIterations) { 20 while (!*StartingGun) { 21 // Wait for starting gun. 22 } 23 24 // Get ourselves a new allocation. 25 for (unsigned i = 0; i < NumIterations; ++i) { 26 volatile char *Ptr = reinterpret_cast<volatile char *>( 27 GPA->allocate(GPA->maximumAllocationSize())); 28 // Do any other threads have access to this page? 29 EXPECT_EQ(*Ptr, 0); 30 31 // Mark the page as from malloc. Wait to see if another thread also takes 32 // this page. 33 *Ptr = 'A'; 34 std::this_thread::sleep_for(std::chrono::nanoseconds(10000)); 35 36 // Check we still own the page. 37 EXPECT_EQ(*Ptr, 'A'); 38 39 // And now release it. 40 *Ptr = 0; 41 GPA->deallocate(const_cast<char *>(Ptr)); 42 } 43 } 44 45 void runThreadContentionTest(unsigned NumThreads, unsigned NumIterations, 46 gwp_asan::GuardedPoolAllocator *GPA) { 47 48 std::atomic<bool> StartingGun{false}; 49 std::vector<std::thread> Threads; 50 if (std::thread::hardware_concurrency() < NumThreads) { 51 NumThreads = std::thread::hardware_concurrency(); 52 } 53 54 for (unsigned i = 0; i < NumThreads; ++i) { 55 Threads.emplace_back(asyncTask, GPA, &StartingGun, NumIterations); 56 } 57 58 StartingGun = true; 59 60 for (auto &T : Threads) 61 T.join(); 62 } 63 64 TEST_F(CustomGuardedPoolAllocator, ThreadContention) { 65 unsigned NumThreads = 4; 66 unsigned NumIterations = 10000; 67 InitNumSlots(NumThreads); 68 runThreadContentionTest(NumThreads, NumIterations, &GPA); 69 } 70