1//===-- xray_recursion_guard.h ---------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of XRay, a dynamic runtime instrumentation system.
11//
12//===----------------------------------------------------------------------===//
13#ifndef XRAY_XRAY_RECURSION_GUARD_H
14#define XRAY_XRAY_RECURSION_GUARD_H
15
16#include "sanitizer_common/sanitizer_atomic.h"
17
18namespace __xray {
19
20/// The RecursionGuard is useful for guarding against signal handlers which are
21/// also potentially calling XRay-instrumented functions. To use the
22/// RecursionGuard, you'll typically need a thread_local atomic_uint8_t:
23///
24///   thread_local atomic_uint8_t Guard{0};
25///
26///   // In a handler function:
27///   void handleArg0(int32_t F, XRayEntryType T) {
28///     RecursionGuard G(Guard);
29///     if (!G)
30///       return;  // Failed to acquire the guard.
31///     ...
32///   }
33///
34class RecursionGuard {
35  atomic_uint8_t &Running;
36  const bool Valid;
37
38public:
39  explicit inline RecursionGuard(atomic_uint8_t &R)
40      : Running(R), Valid(!atomic_exchange(&R, 1, memory_order_acq_rel)) {}
41
42  inline RecursionGuard(const RecursionGuard &) = delete;
43  inline RecursionGuard(RecursionGuard &&) = delete;
44  inline RecursionGuard &operator=(const RecursionGuard &) = delete;
45  inline RecursionGuard &operator=(RecursionGuard &&) = delete;
46
47  explicit inline operator bool() const { return Valid; }
48
49  inline ~RecursionGuard() noexcept {
50    if (Valid)
51      atomic_store(&Running, 0, memory_order_release);
52  }
53};
54
55} // namespace __xray
56
57#endif // XRAY_XRAY_RECURSION_GUARD_H
58