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