It's better and easier for us to just have threads contend against each other in the tests if it's more than the maximum supported number of hardware threads available. Specifically, the recoverable test fails on Android because the GTEST_SKIP in a called function, and it only properly works from the TEST_* harness function. Android tests run on cuttlefish, which can be a single core with two hyperthreads. Reviewed By: fmayer Differential Revision: https://reviews.llvm.org/D143221
66 lines
2.0 KiB
C++
66 lines
2.0 KiB
C++
//===-- 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 <atomic> and <thread> are extremely expensive for
|
|
// non-opt builds of clang.
|
|
#include <atomic>
|
|
#include <cstdlib>
|
|
#include <thread>
|
|
#include <vector>
|
|
|
|
void asyncTask(gwp_asan::GuardedPoolAllocator *GPA,
|
|
std::atomic<bool> *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<volatile char *>(
|
|
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<char *>(Ptr));
|
|
}
|
|
}
|
|
|
|
void runThreadContentionTest(unsigned NumThreads, unsigned NumIterations,
|
|
gwp_asan::GuardedPoolAllocator *GPA) {
|
|
std::atomic<bool> StartingGun{false};
|
|
std::vector<std::thread> Threads;
|
|
|
|
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);
|
|
}
|