../../xray_profile_collector.h
../../xray_profiler_flags.cc
../../xray_profiler_flags.h
+ ../../xray_recursion_guard.h
../../xray_segmented_array.h
../../xray_trampoline_powerpc64.cc
../../xray_tsc.h
#include "sanitizer_common/sanitizer_allocator_internal.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "xray/xray_records.h"
+#include "xray_recursion_guard.h"
#include "xray_basic_flags.h"
#include "xray_basic_logging.h"
#include "xray_defs.h"
BasicLoggingOptions GlobalOptions;
-thread_local volatile bool RecursionGuard = false;
+thread_local atomic_uint8_t Guard{0};
static uint64_t thresholdTicks() XRAY_NEVER_INSTRUMENT {
static uint64_t TicksPerSec = probeRequiredCPUFeatures()
// Use a simple recursion guard, to handle cases where we're already logging
// and for one reason or another, this function gets called again in the same
// thread.
- if (RecursionGuard)
+ RecursionGuard G(Guard);
+ if (!G)
return;
- RecursionGuard = true;
- auto ExitGuard = at_scope_exit([] { RecursionGuard = false; });
uint8_t CPU = 0;
uint64_t TSC = ReadTSC(CPU);
// Then we write the "we have an argument" record.
InMemoryRawLog(FuncId, Type, ReadTSC);
- if (RecursionGuard)
+ RecursionGuard G(Guard);
+ if (!G)
return;
- RecursionGuard = true;
- auto ExitGuard = at_scope_exit([] { RecursionGuard = false; });
// And from here on write the arg payload.
XRayArgPayload R;
#include "sanitizer_common/sanitizer_common.h"
#include "xray/xray_interface.h"
#include "xray/xray_records.h"
+#include "xray_recursion_guard.h"
#include "xray_buffer_queue.h"
#include "xray_defs.h"
#include "xray_fdr_flags.h"
return TLD;
}
-namespace {
-
-class RecursionGuard {
- volatile bool &Running;
- const bool Valid;
-
-public:
- explicit RecursionGuard(volatile bool &R) : Running(R), Valid(!R) {
- if (Valid)
- Running = true;
- }
-
- RecursionGuard(const RecursionGuard &) = delete;
- RecursionGuard(RecursionGuard &&) = delete;
- RecursionGuard &operator=(const RecursionGuard &) = delete;
- RecursionGuard &operator=(RecursionGuard &&) = delete;
-
- explicit operator bool() const { return Valid; }
-
- ~RecursionGuard() noexcept {
- if (Valid)
- Running = false;
- }
-};
-
-} // namespace
-
static void writeNewBufferPreamble(tid_t Tid,
timespec TS) XRAY_NEVER_INSTRUMENT {
static constexpr int InitRecordsCount = 2;
}
}
-thread_local volatile bool Running = false;
+thread_local atomic_uint8_t Running{0};
/// Here's where the meat of the processing happens. The writer captures
/// function entry, exit and tail exit points with a time and will create
// handleArg0 to happen at any given time.
RecursionGuard Guard{Running};
if (!Guard) {
- DCHECK(Running == true && "RecursionGuard is buggy!");
+ DCHECK(atomic_load_relaxed(&Running) && "RecursionGuard is buggy!");
return;
}
--- /dev/null
+//===-- 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