
Summary: This change extracts the recursion guard implementation from FDR Mode and updates it to do the following: - Do the atomic operation correctly to be signal-handler safe. - Make it usable in both FDR and Basic Modes. Before this change, the recursion guard relied on an unsynchronised read and write on a volatile thread-local. A signal handler could then run in between the read and the write, and then be able to run instrumented code as part of the signal handling. Using an atomic exchange instead fixes that by doing a proper mutual exclusion even in the presence of signal handling. Reviewers: kpw, eizan, jfb Reviewed By: eizan Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D47696 llvm-svn: 334064
58 lines
1.8 KiB
C++
58 lines
1.8 KiB
C++
//===-- xray_recursion_guard.h ---------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file is a part of XRay, a dynamic runtime instrumentation system.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#ifndef XRAY_XRAY_RECURSION_GUARD_H
|
|
#define XRAY_XRAY_RECURSION_GUARD_H
|
|
|
|
#include "sanitizer_common/sanitizer_atomic.h"
|
|
|
|
namespace __xray {
|
|
|
|
/// The RecursionGuard is useful for guarding against signal handlers which are
|
|
/// also potentially calling XRay-instrumented functions. To use the
|
|
/// RecursionGuard, you'll typically need a thread_local atomic_uint8_t:
|
|
///
|
|
/// thread_local atomic_uint8_t Guard{0};
|
|
///
|
|
/// // In a handler function:
|
|
/// void handleArg0(int32_t F, XRayEntryType T) {
|
|
/// RecursionGuard G(Guard);
|
|
/// if (!G)
|
|
/// return; // Failed to acquire the guard.
|
|
/// ...
|
|
/// }
|
|
///
|
|
class RecursionGuard {
|
|
atomic_uint8_t &Running;
|
|
const bool Valid;
|
|
|
|
public:
|
|
explicit inline RecursionGuard(atomic_uint8_t &R)
|
|
: Running(R), Valid(!atomic_exchange(&R, 1, memory_order_acq_rel)) {}
|
|
|
|
inline RecursionGuard(const RecursionGuard &) = delete;
|
|
inline RecursionGuard(RecursionGuard &&) = delete;
|
|
inline RecursionGuard &operator=(const RecursionGuard &) = delete;
|
|
inline RecursionGuard &operator=(RecursionGuard &&) = delete;
|
|
|
|
explicit inline operator bool() const { return Valid; }
|
|
|
|
inline ~RecursionGuard() noexcept {
|
|
if (Valid)
|
|
atomic_store(&Running, 0, memory_order_release);
|
|
}
|
|
};
|
|
|
|
} // namespace __xray
|
|
|
|
#endif // XRAY_XRAY_RECURSION_GUARD_H
|