11adb55b1SChris Apple //===--- rtsan_context.cpp - Realtime Sanitizer -----------------*- C++ -*-===// 21adb55b1SChris Apple // 31adb55b1SChris Apple // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41adb55b1SChris Apple // See https://llvm.org/LICENSE.txt for license information. 51adb55b1SChris Apple // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61adb55b1SChris Apple // 71adb55b1SChris Apple //===----------------------------------------------------------------------===// 81adb55b1SChris Apple // 91adb55b1SChris Apple //===----------------------------------------------------------------------===// 101adb55b1SChris Apple 113477eb72SChris Apple #include "rtsan/rtsan_context.h" 123477eb72SChris Apple #include "rtsan/rtsan.h" 131adb55b1SChris Apple 143477eb72SChris Apple #include "sanitizer_common/sanitizer_allocator_internal.h" 151adb55b1SChris Apple 161adb55b1SChris Apple #include <new> 171adb55b1SChris Apple #include <pthread.h> 181adb55b1SChris Apple 19a424b792SChris Apple using namespace __sanitizer; 20*e069434aSChris Apple using namespace __rtsan; 21a424b792SChris Apple 221adb55b1SChris Apple static pthread_key_t context_key; 231adb55b1SChris Apple static pthread_once_t key_once = PTHREAD_ONCE_INIT; 241adb55b1SChris Apple 251adb55b1SChris Apple // InternalFree cannot be passed directly to pthread_key_create 261adb55b1SChris Apple // because it expects a signature with only one arg 271adb55b1SChris Apple static void InternalFreeWrapper(void *ptr) { __sanitizer::InternalFree(ptr); } 281adb55b1SChris Apple 291adb55b1SChris Apple static __rtsan::Context &GetContextForThisThreadImpl() { 306032feeeSChris Apple auto MakeThreadLocalContextKey = []() { 311adb55b1SChris Apple CHECK_EQ(pthread_key_create(&context_key, InternalFreeWrapper), 0); 321adb55b1SChris Apple }; 331adb55b1SChris Apple 346032feeeSChris Apple pthread_once(&key_once, MakeThreadLocalContextKey); 35*e069434aSChris Apple Context *current_thread_context = 36*e069434aSChris Apple static_cast<Context *>(pthread_getspecific(context_key)); 371adb55b1SChris Apple if (current_thread_context == nullptr) { 38*e069434aSChris Apple current_thread_context = 39*e069434aSChris Apple static_cast<Context *>(InternalAlloc(sizeof(Context))); 40*e069434aSChris Apple new (current_thread_context) Context(); 411adb55b1SChris Apple pthread_setspecific(context_key, current_thread_context); 421adb55b1SChris Apple } 431adb55b1SChris Apple 441adb55b1SChris Apple return *current_thread_context; 451adb55b1SChris Apple } 461adb55b1SChris Apple 471adb55b1SChris Apple __rtsan::Context::Context() = default; 481adb55b1SChris Apple 4930d56bedSChris Apple void __rtsan::Context::RealtimePush() { realtime_depth_++; } 501adb55b1SChris Apple 5130d56bedSChris Apple void __rtsan::Context::RealtimePop() { realtime_depth_--; } 521adb55b1SChris Apple 5330d56bedSChris Apple void __rtsan::Context::BypassPush() { bypass_depth_++; } 541adb55b1SChris Apple 5530d56bedSChris Apple void __rtsan::Context::BypassPop() { bypass_depth_--; } 561adb55b1SChris Apple 5730d56bedSChris Apple bool __rtsan::Context::InRealtimeContext() const { return realtime_depth_ > 0; } 581adb55b1SChris Apple 5930d56bedSChris Apple bool __rtsan::Context::IsBypassed() const { return bypass_depth_ > 0; } 601adb55b1SChris Apple 61*e069434aSChris Apple Context &__rtsan::GetContextForThisThread() { 621adb55b1SChris Apple return GetContextForThisThreadImpl(); 631adb55b1SChris Apple } 64