//===-- thread_contention.cpp -----------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "gwp_asan/tests/harness.h" // Note: Compilation of and are extremely expensive for // non-opt builds of clang. #include #include #include #include void asyncTask(gwp_asan::GuardedPoolAllocator *GPA, std::atomic *StartingGun, unsigned NumIterations) { while (!*StartingGun) { // Wait for starting gun. } // Get ourselves a new allocation. for (unsigned i = 0; i < NumIterations; ++i) { volatile char *Ptr = reinterpret_cast( GPA->allocate(GPA->getAllocatorState()->maximumAllocationSize())); // Do any other threads have access to this page? EXPECT_EQ(*Ptr, 0); // Mark the page as from malloc. Wait to see if another thread also takes // this page. *Ptr = 'A'; std::this_thread::sleep_for(std::chrono::nanoseconds(10000)); // Check we still own the page. EXPECT_EQ(*Ptr, 'A'); // And now release it. *Ptr = 0; GPA->deallocate(const_cast(Ptr)); } } void runThreadContentionTest(unsigned NumThreads, unsigned NumIterations, gwp_asan::GuardedPoolAllocator *GPA) { std::atomic StartingGun{false}; std::vector Threads; if (std::thread::hardware_concurrency() < NumThreads) { NumThreads = std::thread::hardware_concurrency(); } for (unsigned i = 0; i < NumThreads; ++i) { Threads.emplace_back(asyncTask, GPA, &StartingGun, NumIterations); } StartingGun = true; for (auto &T : Threads) T.join(); } TEST_F(CustomGuardedPoolAllocator, ThreadContention) { unsigned NumThreads = 4; unsigned NumIterations = 10000; InitNumSlots(NumThreads); runThreadContentionTest(NumThreads, NumIterations, &GPA); }