Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions compiler-rt/lib/radsan/radsan.cpp
Original file line number Diff line number Diff line change
@@ -1,32 +1,38 @@
/**
This file is part of the RealtimeSanitizer (RADSan) project.
https://github.com/realtime-sanitizer/radsan

Copyright 2023 David Trevelyan & Alistair Barker
Subject to GNU General Public License (GPL) v3.0
*/
//===--- radsan.cpp - Realtime Sanitizer --------------*- 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 <radsan/radsan.h>
#include <radsan/radsan_context.h>
#include <radsan/radsan_interceptors.h>
#include <unistd.h>

extern "C" {
RADSAN_EXPORT void radsan_init() { radsan::initialiseInterceptors(); }

RADSAN_EXPORT void radsan_realtime_enter() {
radsan::getContextForThisThread().realtimePush();
SANITIZER_INTERFACE_ATTRIBUTE void radsan_init() {
radsan::InitializeInterceptors();
}

RADSAN_EXPORT void radsan_realtime_exit() {
radsan::getContextForThisThread().realtimePop();
SANITIZER_INTERFACE_ATTRIBUTE void radsan_realtime_enter() {
radsan::GetContextForThisThread().RealtimePush();
}

RADSAN_EXPORT void radsan_off() {
radsan::getContextForThisThread().bypassPush();
SANITIZER_INTERFACE_ATTRIBUTE void radsan_realtime_exit() {
radsan::GetContextForThisThread().RealtimePop();
}

RADSAN_EXPORT void radsan_on() {
radsan::getContextForThisThread().bypassPop();
SANITIZER_INTERFACE_ATTRIBUTE void radsan_off() {
radsan::GetContextForThisThread().BypassPush();
}

SANITIZER_INTERFACE_ATTRIBUTE void radsan_on() {
radsan::GetContextForThisThread().BypassPop();
}

} // extern "C"
33 changes: 18 additions & 15 deletions compiler-rt/lib/radsan/radsan.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
/**
This file is part of the RealtimeSanitizer (RADSan) project.
https://github.com/realtime-sanitizer/radsan

Copyright 2023 David Trevelyan & Alistair Barker
Subject to GNU General Public License (GPL) v3.0
*/
//===--- radsan.h - Realtime Sanitizer --------------*- 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
//
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===//

#pragma once

#define RADSAN_EXPORT __attribute__((visibility("default")))
#include "sanitizer_common/sanitizer_internal_defs.h"

extern "C" {

Expand All @@ -18,7 +20,7 @@ extern "C" {

@warning Do not call this method as a user.
*/
RADSAN_EXPORT void radsan_init();
SANITIZER_INTERFACE_ATTRIBUTE void radsan_init();

/** Enter real-time context.

Expand All @@ -28,7 +30,7 @@ RADSAN_EXPORT void radsan_init();

@warning Do not call this method as a user
*/
RADSAN_EXPORT void radsan_realtime_enter();
SANITIZER_INTERFACE_ATTRIBUTE void radsan_realtime_enter();

/** Exit the real-time context.

Expand All @@ -37,7 +39,7 @@ RADSAN_EXPORT void radsan_realtime_enter();

@warning Do not call this method as a user
*/
RADSAN_EXPORT void radsan_realtime_exit();
SANITIZER_INTERFACE_ATTRIBUTE void radsan_realtime_exit();

/** Disable all RADSan error reporting.

Expand All @@ -52,7 +54,7 @@ RADSAN_EXPORT void radsan_realtime_exit();

Example:

[[clang::realtime]] float process (float x)
float process (float x) [[clang::nonblocking]]
{
auto const y = 2.0f * x;

Expand All @@ -62,12 +64,13 @@ RADSAN_EXPORT void radsan_realtime_exit();
}

*/
RADSAN_EXPORT void radsan_off();
SANITIZER_INTERFACE_ATTRIBUTE void radsan_off();

/** Re-enable all RADSan error reporting.

The counterpart to `radsan_off`. See the description for `radsan_off` for
details about how to use this method.
*/
RADSAN_EXPORT void radsan_on();
}
SANITIZER_INTERFACE_ATTRIBUTE void radsan_on();

} // extern "C"
70 changes: 36 additions & 34 deletions compiler-rt/lib/radsan/radsan_context.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/**
This file is part of the RealtimeSanitizer (RADSan) project.
https://github.com/realtime-sanitizer/radsan

Copyright 2023 David Trevelyan & Alistair Barker
Subject to GNU General Public License (GPL) v3.0
*/
//===--- radsan_context.cpp - Realtime Sanitizer --------------*- 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 <radsan/radsan_context.h>

Expand All @@ -22,59 +24,59 @@ using namespace __sanitizer;

namespace detail {

static pthread_key_t key;
static pthread_once_t key_once = PTHREAD_ONCE_INIT;
void internalFree(void *ptr) { InternalFree(ptr); }
static pthread_key_t Key;
static pthread_once_t KeyOnce = PTHREAD_ONCE_INIT;
void internalFree(void *Ptr) { __sanitizer::InternalFree(Ptr); }

} // namespace detail

namespace radsan {

Context::Context() = default;

void Context::realtimePush() { realtime_depth_++; }
void Context::RealtimePush() { RealtimeDepth++; }

void Context::realtimePop() { realtime_depth_--; }
void Context::RealtimePop() { RealtimeDepth--; }

void Context::bypassPush() { bypass_depth_++; }
void Context::BypassPush() { BypassDepth++; }

void Context::bypassPop() { bypass_depth_--; }
void Context::BypassPop() { BypassDepth--; }

void Context::expectNotRealtime(const char *intercepted_function_name) {
if (inRealtimeContext() && !isBypassed()) {
bypassPush();
printDiagnostics(intercepted_function_name);
void Context::ExpectNotRealtime(const char *InterceptedFunctionName) {
if (InRealtimeContext() && !IsBypassed()) {
BypassPush();
PrintDiagnostics(InterceptedFunctionName);
exit(EXIT_FAILURE);
bypassPop();
BypassPop();
}
}

bool Context::inRealtimeContext() const { return realtime_depth_ > 0; }
bool Context::InRealtimeContext() const { return RealtimeDepth > 0; }

bool Context::isBypassed() const { return bypass_depth_ > 0; }
bool Context::IsBypassed() const { return BypassDepth > 0; }

void Context::printDiagnostics(const char *intercepted_function_name) {
void Context::PrintDiagnostics(const char *InterceptedFunctionName) {
fprintf(stderr,
"Real-time violation: intercepted call to real-time unsafe function "
"`%s` in real-time context! Stack trace:\n",
intercepted_function_name);
radsan::printStackTrace();
InterceptedFunctionName);
radsan::PrintStackTrace();
}

Context &getContextForThisThread() {
auto make_tls_key = []() {
CHECK_EQ(pthread_key_create(&detail::key, detail::internalFree), 0);
Context &GetContextForThisThread() {
auto MakeTlsKey = []() {
CHECK_EQ(pthread_key_create(&detail::Key, detail::internalFree), 0);
};

pthread_once(&detail::key_once, make_tls_key);
auto *ptr = static_cast<Context *>(pthread_getspecific(detail::key));
if (ptr == nullptr) {
ptr = static_cast<Context *>(InternalAlloc(sizeof(Context)));
new(ptr) Context();
pthread_setspecific(detail::key, ptr);
pthread_once(&detail::KeyOnce, MakeTlsKey);
Context *CurrentThreadContext = static_cast<Context *>(pthread_getspecific(detail::Key));
if (CurrentThreadContext == nullptr) {
CurrentThreadContext = static_cast<Context *>(InternalAlloc(sizeof(Context)));
new(CurrentThreadContext) Context();
pthread_setspecific(detail::Key, CurrentThreadContext);
}

return *ptr;
return *CurrentThreadContext;
}

} // namespace radsan
38 changes: 20 additions & 18 deletions compiler-rt/lib/radsan/radsan_context.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/**
This file is part of the RealtimeSanitizer (RADSan) project.
https://github.com/realtime-sanitizer/radsan

Copyright 2023 David Trevelyan & Alistair Barker
Subject to GNU General Public License (GPL) v3.0
*/
//===--- radsan_context.h - Realtime Sanitizer --------------*- 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
//
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===//

#pragma once

Expand All @@ -14,23 +16,23 @@ class Context {
public:
Context();

void realtimePush();
void realtimePop();
void RealtimePush();
void RealtimePop();

void bypassPush();
void bypassPop();
void BypassPush();
void BypassPop();

void expectNotRealtime(const char *interpreted_function_name);
void ExpectNotRealtime(const char *InterceptedFunctionName);

private:
bool inRealtimeContext() const;
bool isBypassed() const;
void printDiagnostics(const char *intercepted_function_name);
bool InRealtimeContext() const;
bool IsBypassed() const;
void PrintDiagnostics(const char *InterceptedFunctionName);

int realtime_depth_{0};
int bypass_depth_{0};
int RealtimeDepth{0};
int BypassDepth{0};
};

Context &getContextForThisThread();
Context &GetContextForThisThread();

} // namespace radsan
Loading