1 //===--- rtsan_context.cpp - Realtime Sanitizer -----------------*- 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 //===----------------------------------------------------------------------===// 10 11 #include "rtsan/rtsan_context.h" 12 #include "rtsan/rtsan.h" 13 14 #include "sanitizer_common/sanitizer_allocator_internal.h" 15 16 #include <new> 17 #include <pthread.h> 18 19 using namespace __sanitizer; 20 using namespace __rtsan; 21 22 static pthread_key_t context_key; 23 static pthread_once_t key_once = PTHREAD_ONCE_INIT; 24 25 // InternalFree cannot be passed directly to pthread_key_create 26 // because it expects a signature with only one arg 27 static void InternalFreeWrapper(void *ptr) { __sanitizer::InternalFree(ptr); } 28 29 static __rtsan::Context &GetContextForThisThreadImpl() { 30 auto MakeThreadLocalContextKey = []() { 31 CHECK_EQ(pthread_key_create(&context_key, InternalFreeWrapper), 0); 32 }; 33 34 pthread_once(&key_once, MakeThreadLocalContextKey); 35 Context *current_thread_context = 36 static_cast<Context *>(pthread_getspecific(context_key)); 37 if (current_thread_context == nullptr) { 38 current_thread_context = 39 static_cast<Context *>(InternalAlloc(sizeof(Context))); 40 new (current_thread_context) Context(); 41 pthread_setspecific(context_key, current_thread_context); 42 } 43 44 return *current_thread_context; 45 } 46 47 __rtsan::Context::Context() = default; 48 49 void __rtsan::Context::RealtimePush() { realtime_depth_++; } 50 51 void __rtsan::Context::RealtimePop() { realtime_depth_--; } 52 53 void __rtsan::Context::BypassPush() { bypass_depth_++; } 54 55 void __rtsan::Context::BypassPop() { bypass_depth_--; } 56 57 bool __rtsan::Context::InRealtimeContext() const { return realtime_depth_ > 0; } 58 59 bool __rtsan::Context::IsBypassed() const { return bypass_depth_ > 0; } 60 61 Context &__rtsan::GetContextForThisThread() { 62 return GetContextForThisThreadImpl(); 63 } 64