16d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov//===-- sanitizer_thread_registry_test.cc ---------------------------------===// 26d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// 36d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// The LLVM Compiler Infrastructure 46d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// 56d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// This file is distributed under the University of Illinois Open Source 66d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// License. See LICENSE.TXT for details. 76d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// 86d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov//===----------------------------------------------------------------------===// 96d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// 106d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// This file is a part of shared sanitizer runtime. 116d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov// 126d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov//===----------------------------------------------------------------------===// 136d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include "sanitizer_common/sanitizer_thread_registry.h" 142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_pthread_wrappers.h" 162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 176d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include "gtest/gtest.h" 186d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 196d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include <vector> 206d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 216d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovnamespace __sanitizer { 226d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 236d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic BlockingMutex tctx_allocator_lock(LINKER_INITIALIZED); 246d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic LowLevelAllocator tctx_allocator; 256d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 266d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovtemplate<typename TCTX> 276d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic ThreadContextBase *GetThreadContext(u32 tid) { 286d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov BlockingMutexLock l(&tctx_allocator_lock); 2953177247698bfba075f2d5b255a447fc3ced6976Peter Collingbourne return new(tctx_allocator) TCTX(tid); 306d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 316d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 326d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic const u32 kMaxRegistryThreads = 1000; 336d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic const u32 kRegistryQuarantine = 2; 346d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 356d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic void CheckThreadQuantity(ThreadRegistry *registry, uptr exp_total, 366d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr exp_running, uptr exp_alive) { 376d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr total, running, alive; 386d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->GetNumberOfThreads(&total, &running, &alive); 396d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov EXPECT_EQ(exp_total, total); 406d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov EXPECT_EQ(exp_running, running); 416d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov EXPECT_EQ(exp_alive, alive); 426d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 436d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 44827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonovstatic bool is_detached(u32 tid) { 456d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return (tid % 2 == 0); 466d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 476d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 48827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonovstatic uptr get_uid(u32 tid) { 496d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return tid * 2; 506d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 516d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 526d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic bool HasName(ThreadContextBase *tctx, void *arg) { 536d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov char *name = (char*)arg; 542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return (0 == internal_strcmp(tctx->name, name)); 556d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 566d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 576d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic bool HasUid(ThreadContextBase *tctx, void *arg) { 586d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr uid = (uptr)arg; 596d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return (tctx->user_id == uid); 606d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 616d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 626d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic void MarkUidAsPresent(ThreadContextBase *tctx, void *arg) { 636d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov bool *arr = (bool*)arg; 646d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov arr[tctx->tid] = true; 656d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 666d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 676d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic void TestRegistry(ThreadRegistry *registry, bool has_quarantine) { 686d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Create and start a main thread. 69827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov EXPECT_EQ(0U, registry->CreateThread(get_uid(0), true, -1, 0)); 706d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->StartThread(0, 0, 0); 716d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Create a bunch of threads. 72827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov for (u32 i = 1; i <= 10; i++) { 736d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov EXPECT_EQ(i, registry->CreateThread(get_uid(i), is_detached(i), 0, 0)); 746d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 756d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CheckThreadQuantity(registry, 11, 1, 11); 766d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Start some of them. 77827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov for (u32 i = 1; i <= 5; i++) { 786d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->StartThread(i, 0, 0); 796d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 806d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CheckThreadQuantity(registry, 11, 6, 11); 816d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Finish, create and start more threads. 82827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov for (u32 i = 1; i <= 5; i++) { 836d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->FinishThread(i); 846d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov if (!is_detached(i)) 856d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->JoinThread(i, 0); 866d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 87827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov for (u32 i = 6; i <= 10; i++) { 886d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->StartThread(i, 0, 0); 896d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 90827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov std::vector<u32> new_tids; 91827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov for (u32 i = 11; i <= 15; i++) { 926d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov new_tids.push_back( 936d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->CreateThread(get_uid(i), is_detached(i), 0, 0)); 946d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 95827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov ASSERT_LE(kRegistryQuarantine, 5U); 96827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov u32 exp_total = 16 - (has_quarantine ? 5 - kRegistryQuarantine : 0); 976d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CheckThreadQuantity(registry, exp_total, 6, 11); 986d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Test SetThreadName and FindThread. 996d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->SetThreadName(6, "six"); 1006d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->SetThreadName(7, "seven"); 101827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov EXPECT_EQ(7U, registry->FindThread(HasName, (void*)"seven")); 102827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov EXPECT_EQ(ThreadRegistry::kUnknownTid, 103827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov registry->FindThread(HasName, (void*)"none")); 104827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov EXPECT_EQ(0U, registry->FindThread(HasUid, (void*)get_uid(0))); 105827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov EXPECT_EQ(10U, registry->FindThread(HasUid, (void*)get_uid(10))); 106827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov EXPECT_EQ(ThreadRegistry::kUnknownTid, 107827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov registry->FindThread(HasUid, (void*)0x1234)); 1086d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Detach and finish and join remaining threads. 109827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov for (u32 i = 6; i <= 10; i++) { 1106d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->DetachThread(i); 1116d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->FinishThread(i); 1126d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 113827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov for (u32 i = 0; i < new_tids.size(); i++) { 114827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov u32 tid = new_tids[i]; 1156d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->StartThread(tid, 0, 0); 1166d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->DetachThread(tid); 1176d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->FinishThread(tid); 1186d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1196d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov CheckThreadQuantity(registry, exp_total, 1, 1); 1206d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Test methods that require the caller to hold a ThreadRegistryLock. 1216d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov bool has_tid[16]; 1226d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov internal_memset(&has_tid[0], 0, sizeof(has_tid)); 1236d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov { 1246d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadRegistryLock l(registry); 1256d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->RunCallbackForEachThreadLocked(MarkUidAsPresent, &has_tid[0]); 1266d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 127827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov for (u32 i = 0; i < exp_total; i++) { 1286d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov EXPECT_TRUE(has_tid[i]); 1296d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1306d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov { 1316d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadRegistryLock l(registry); 1326d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->CheckLocked(); 1336d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadContextBase *main_thread = registry->GetThreadLocked(0); 1346d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov EXPECT_EQ(main_thread, registry->FindThreadContextLocked( 1356d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov HasUid, (void*)get_uid(0))); 1366d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 137827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov EXPECT_EQ(11U, registry->GetMaxAliveThreads()); 1386d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1396d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1406d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovTEST(SanitizerCommon, ThreadRegistryTest) { 1416d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadRegistry quarantine_registry(GetThreadContext<ThreadContextBase>, 1426d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov kMaxRegistryThreads, 1436d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov kRegistryQuarantine); 1446d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov TestRegistry(&quarantine_registry, true); 1456d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1466d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadRegistry no_quarantine_registry(GetThreadContext<ThreadContextBase>, 1476d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov kMaxRegistryThreads, 1486d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov kMaxRegistryThreads); 1496d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov TestRegistry(&no_quarantine_registry, false); 1506d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1516d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1526d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic const int kThreadsPerShard = 20; 1536d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic const int kNumShards = 25; 1546d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1556d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic int num_created[kNumShards + 1]; 1566d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic int num_started[kNumShards + 1]; 1576d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic int num_joined[kNumShards + 1]; 1586d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1596d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovnamespace { 1606d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1616d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstruct RunThreadArgs { 1626d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadRegistry *registry; 1636d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr shard; // started from 1. 1646d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov}; 1656d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1666d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovclass TestThreadContext : public ThreadContextBase { 1676d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov public: 1686d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov explicit TestThreadContext(int tid) : ThreadContextBase(tid) {} 1696d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void OnJoined(void *arg) { 1706d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr shard = (uptr)arg; 1716d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov num_joined[shard]++; 1726d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1736d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void OnStarted(void *arg) { 1746d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr shard = (uptr)arg; 1756d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov num_started[shard]++; 1766d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1776d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov void OnCreated(void *arg) { 1786d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov uptr shard = (uptr)arg; 1796d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov num_created[shard]++; 1806d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 1816d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov}; 1826d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1836d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} // namespace 1846d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 1856d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovvoid *RunThread(void *arg) { 1866d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov RunThreadArgs *args = static_cast<RunThreadArgs*>(arg); 1876d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov std::vector<int> tids; 1886d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov for (int i = 0; i < kThreadsPerShard; i++) 1896d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov tids.push_back( 1906d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov args->registry->CreateThread(0, false, 0, (void*)args->shard)); 1916d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov for (int i = 0; i < kThreadsPerShard; i++) 1926d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov args->registry->StartThread(tids[i], 0, (void*)args->shard); 1936d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov for (int i = 0; i < kThreadsPerShard; i++) 1946d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov args->registry->FinishThread(tids[i]); 1956d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov for (int i = 0; i < kThreadsPerShard; i++) 1966d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov args->registry->JoinThread(tids[i], (void*)args->shard); 1976d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov return 0; 1986d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 1996d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 2006d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatic void ThreadedTestRegistry(ThreadRegistry *registry) { 2016d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Create and start a main thread. 202827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov EXPECT_EQ(0U, registry->CreateThread(0, true, -1, 0)); 2036d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov registry->StartThread(0, 0, 0); 2046d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov pthread_t threads[kNumShards]; 2056d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov RunThreadArgs args[kNumShards]; 2066d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov for (int i = 0; i < kNumShards; i++) { 2076d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov args[i].registry = registry; 2086d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov args[i].shard = i + 1; 2092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PTHREAD_CREATE(&threads[i], 0, RunThread, &args[i]); 2106d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 2116d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov for (int i = 0; i < kNumShards; i++) { 2122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PTHREAD_JOIN(threads[i], 0); 2136d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 2146d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // Check that each thread created/started/joined correct amount 2156d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // of "threads" in thread_registry. 2166d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov EXPECT_EQ(1, num_created[0]); 2176d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov EXPECT_EQ(1, num_started[0]); 2186d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov EXPECT_EQ(0, num_joined[0]); 2196d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov for (int i = 1; i <= kNumShards; i++) { 2206d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov EXPECT_EQ(kThreadsPerShard, num_created[i]); 2216d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov EXPECT_EQ(kThreadsPerShard, num_started[i]); 2226d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov EXPECT_EQ(kThreadsPerShard, num_joined[i]); 2236d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov } 2246d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 2256d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 2266d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovTEST(SanitizerCommon, ThreadRegistryThreadedTest) { 2276d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadRegistry registry(GetThreadContext<TestThreadContext>, 2286d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov kThreadsPerShard * kNumShards + 1, 10); 2296d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov ThreadedTestRegistry(®istry); 2306d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} 2316d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov 2326d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov} // namespace __sanitizer 233