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
19using namespace __sanitizer;
20using namespace __rtsan;
21
22static pthread_key_t context_key;
23static 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
27static void InternalFreeWrapper(void *ptr) { __sanitizer::InternalFree(p: ptr); }
28
29static __rtsan::Context &GetContextForThisThreadImpl() {
30 auto MakeThreadLocalContextKey = []() {
31 CHECK_EQ(pthread_key_create(&context_key, InternalFreeWrapper), 0);
32 };
33
34 pthread_once(once_control: &key_once, init_routine: MakeThreadLocalContextKey);
35 Context *current_thread_context =
36 static_cast<Context *>(pthread_getspecific(key: context_key));
37 if (current_thread_context == nullptr) {
38 current_thread_context =
39 static_cast<Context *>(InternalAlloc(size: sizeof(Context)));
40 new (current_thread_context) Context();
41 pthread_setspecific(key: context_key, pointer: current_thread_context);
42 }
43
44 return *current_thread_context;
45}
46
47__rtsan::Context::Context() = default;
48
49void __rtsan::Context::RealtimePush() { realtime_depth_++; }
50
51void __rtsan::Context::RealtimePop() { realtime_depth_--; }
52
53void __rtsan::Context::BypassPush() { bypass_depth_++; }
54
55void __rtsan::Context::BypassPop() { bypass_depth_--; }
56
57bool __rtsan::Context::InRealtimeContext() const { return realtime_depth_ > 0; }
58
59bool __rtsan::Context::IsBypassed() const { return bypass_depth_ > 0; }
60
61Context &__rtsan::GetContextForThisThread() {
62 return GetContextForThisThreadImpl();
63}
64