/// The log initialization routine provided by the implementation, always
/// provided with the following parameters:
///
- /// - buffer size
- /// - maximum number of buffers
+ /// - buffer size (unused)
+ /// - maximum number of buffers (unused)
/// - a pointer to an argument struct that the implementation MUST handle
/// - the size of the argument struct
///
} // extern "C"
-namespace __xray {
-
-/// DEPRECATED: Use __xray_log_init_mode(...) instead, and provide flag
-/// configuration strings to set the options instead.
-/// Options used by the LLVM XRay FDR logging implementation.
-struct FDRLoggingOptions {
- bool ReportErrors = false;
- int Fd = -1;
-};
-
-/// DEPRECATED: Use __xray_log_init_mode(...) instead, and provide flag
-/// configuration strings to set the options instead.
-/// Options used by the LLVM XRay Basic (Naive) logging implementation.
-struct BasicLoggingOptions {
- int DurationFilterMicros = 0;
- size_t MaxStackDepth = 0;
- size_t ThreadBufferSize = 0;
-};
-
-} // namespace __xray
-
#endif // XRAY_XRAY_LOG_INTERFACE_H
add_xray_unittest(XRayBufferQueueTest SOURCES
buffer_queue_test.cc xray_unit_test_main.cc)
-add_xray_unittest(XRayFDRLoggingTest SOURCES
- fdr_logging_test.cc xray_unit_test_main.cc)
add_xray_unittest(XRayAllocatorTest SOURCES
allocator_test.cc xray_unit_test_main.cc)
add_xray_unittest(XRaySegmentedArrayTest SOURCES
+++ /dev/null
-//===-- fdr_logging_test.cc -----------------------------------------------===//
-//
-// 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 function call tracing system.
-//
-//===----------------------------------------------------------------------===//
-#include "sanitizer_common/sanitizer_common.h"
-#include "xray_fdr_logging.h"
-#include "gtest/gtest.h"
-
-#include <array>
-#include <fcntl.h>
-#include <iostream>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <system_error>
-#include <thread>
-#include <unistd.h>
-
-#include "xray/xray_records.h"
-
-namespace __xray {
-namespace {
-
-constexpr auto kBufferSize = 16384;
-constexpr auto kBufferMax = 10;
-
-struct ScopedFileCloserAndDeleter {
- explicit ScopedFileCloserAndDeleter(int Fd, const char *Filename)
- : Fd(Fd), Filename(Filename) {}
-
- ~ScopedFileCloserAndDeleter() {
- if (Map)
- munmap(Map, Size);
- if (Fd) {
- close(Fd);
- unlink(Filename);
- }
- }
-
- void registerMap(void *M, size_t S) {
- Map = M;
- Size = S;
- }
-
- int Fd;
- const char *Filename;
- void *Map = nullptr;
- size_t Size = 0;
-};
-
-TEST(FDRLoggingTest, Simple) {
- FDRLoggingOptions Options;
- Options.ReportErrors = true;
- char TmpFilename[] = "fdr-logging-test.XXXXXX";
- Options.Fd = mkstemp(TmpFilename);
- ASSERT_NE(Options.Fd, -1);
- ASSERT_EQ(fdrLoggingInit(kBufferSize, kBufferMax, &Options,
- sizeof(FDRLoggingOptions)),
- XRayLogInitStatus::XRAY_LOG_INITIALIZED);
- fdrLoggingHandleArg0(1, XRayEntryType::ENTRY);
- fdrLoggingHandleArg0(1, XRayEntryType::EXIT);
- ASSERT_EQ(fdrLoggingFinalize(), XRayLogInitStatus::XRAY_LOG_FINALIZED);
- ASSERT_EQ(fdrLoggingFlush(), XRayLogFlushStatus::XRAY_LOG_FLUSHED);
-
- // To do this properly, we have to close the file descriptor then re-open the
- // file for reading this time.
- ASSERT_EQ(close(Options.Fd), 0);
- int Fd = open(TmpFilename, O_RDONLY);
- ASSERT_NE(-1, Fd);
- ScopedFileCloserAndDeleter Guard(Fd, TmpFilename);
- auto Size = lseek(Fd, 0, SEEK_END);
- ASSERT_NE(Size, 0);
- // Map the file contents.
- void *Map = mmap(NULL, Size, PROT_READ, MAP_PRIVATE, Fd, 0);
- const char *Contents = static_cast<const char *>(Map);
- Guard.registerMap(Map, Size);
- ASSERT_NE(Contents, nullptr);
-
- XRayFileHeader H;
- memcpy(&H, Contents, sizeof(XRayFileHeader));
- ASSERT_EQ(H.Version, 3);
- ASSERT_EQ(H.Type, FileTypes::FDR_LOG);
-
- // We require one buffer at least to have the "extents" metadata record,
- // followed by the NewBuffer record.
- MetadataRecord MDR0, MDR1;
- memcpy(&MDR0, Contents + sizeof(XRayFileHeader), sizeof(MetadataRecord));
- memcpy(&MDR1, Contents + sizeof(XRayFileHeader) + sizeof(MetadataRecord),
- sizeof(MetadataRecord));
- ASSERT_EQ(MDR0.RecordKind,
- uint8_t(MetadataRecord::RecordKinds::BufferExtents));
- ASSERT_EQ(MDR1.RecordKind, uint8_t(MetadataRecord::RecordKinds::NewBuffer));
-}
-
-TEST(FDRLoggingTest, Multiple) {
- FDRLoggingOptions Options;
- char TmpFilename[] = "fdr-logging-test.XXXXXX";
- Options.Fd = mkstemp(TmpFilename);
- ASSERT_NE(Options.Fd, -1);
- ASSERT_EQ(fdrLoggingInit(kBufferSize, kBufferMax, &Options,
- sizeof(FDRLoggingOptions)),
- XRayLogInitStatus::XRAY_LOG_INITIALIZED);
- for (uint64_t I = 0; I < 100; ++I) {
- fdrLoggingHandleArg0(1, XRayEntryType::ENTRY);
- fdrLoggingHandleArg0(1, XRayEntryType::EXIT);
- }
- ASSERT_EQ(fdrLoggingFinalize(), XRayLogInitStatus::XRAY_LOG_FINALIZED);
- ASSERT_EQ(fdrLoggingFlush(), XRayLogFlushStatus::XRAY_LOG_FLUSHED);
-
- // To do this properly, we have to close the file descriptor then re-open the
- // file for reading this time.
- ASSERT_EQ(close(Options.Fd), 0);
- int Fd = open(TmpFilename, O_RDONLY);
- ASSERT_NE(-1, Fd);
- ScopedFileCloserAndDeleter Guard(Fd, TmpFilename);
- auto Size = lseek(Fd, 0, SEEK_END);
- ASSERT_NE(Size, 0);
- // Map the file contents.
- void *Map = mmap(NULL, Size, PROT_READ, MAP_PRIVATE, Fd, 0);
- const char *Contents = static_cast<const char *>(Map);
- Guard.registerMap(Map, Size);
- ASSERT_NE(Contents, nullptr);
-
- XRayFileHeader H;
- memcpy(&H, Contents, sizeof(XRayFileHeader));
- ASSERT_EQ(H.Version, 3);
- ASSERT_EQ(H.Type, FileTypes::FDR_LOG);
-
- MetadataRecord MDR0, MDR1;
- memcpy(&MDR0, Contents + sizeof(XRayFileHeader), sizeof(MetadataRecord));
- memcpy(&MDR1, Contents + sizeof(XRayFileHeader) + sizeof(MetadataRecord),
- sizeof(MetadataRecord));
- ASSERT_EQ(MDR0.RecordKind,
- uint8_t(MetadataRecord::RecordKinds::BufferExtents));
- ASSERT_EQ(MDR1.RecordKind, uint8_t(MetadataRecord::RecordKinds::NewBuffer));
-}
-
-TEST(FDRLoggingTest, MultiThreadedCycling) {
- FDRLoggingOptions Options;
- char TmpFilename[] = "fdr-logging-test.XXXXXX";
- Options.Fd = mkstemp(TmpFilename);
- ASSERT_NE(Options.Fd, -1);
- ASSERT_EQ(fdrLoggingInit(kBufferSize, 1, &Options, sizeof(FDRLoggingOptions)),
- XRayLogInitStatus::XRAY_LOG_INITIALIZED);
-
- // Now we want to create one thread, do some logging, then create another one,
- // in succession and making sure that we're able to get thread records from
- // the latest thread (effectively being able to recycle buffers).
- std::array<tid_t, 2> Threads;
- for (uint64_t I = 0; I < 2; ++I) {
- std::thread t{[I, &Threads] {
- fdrLoggingHandleArg0(I + 1, XRayEntryType::ENTRY);
- fdrLoggingHandleArg0(I + 1, XRayEntryType::EXIT);
- Threads[I] = GetTid();
- }};
- t.join();
- }
- ASSERT_EQ(fdrLoggingFinalize(), XRayLogInitStatus::XRAY_LOG_FINALIZED);
- ASSERT_EQ(fdrLoggingFlush(), XRayLogFlushStatus::XRAY_LOG_FLUSHED);
-
- // To do this properly, we have to close the file descriptor then re-open the
- // file for reading this time.
- ASSERT_EQ(close(Options.Fd), 0);
- int Fd = open(TmpFilename, O_RDONLY);
- ASSERT_NE(-1, Fd);
- ScopedFileCloserAndDeleter Guard(Fd, TmpFilename);
- auto Size = lseek(Fd, 0, SEEK_END);
- ASSERT_NE(Size, 0);
- // Map the file contents.
- void *Map = mmap(NULL, Size, PROT_READ, MAP_PRIVATE, Fd, 0);
- const char *Contents = static_cast<const char *>(Map);
- Guard.registerMap(Map, Size);
- ASSERT_NE(Contents, nullptr);
-
- XRayFileHeader H;
- memcpy(&H, Contents, sizeof(XRayFileHeader));
- ASSERT_EQ(H.Version, 3);
- ASSERT_EQ(H.Type, FileTypes::FDR_LOG);
-
- MetadataRecord MDR0, MDR1;
- memcpy(&MDR0, Contents + sizeof(XRayFileHeader), sizeof(MetadataRecord));
- memcpy(&MDR1, Contents + sizeof(XRayFileHeader) + sizeof(MetadataRecord),
- sizeof(MetadataRecord));
- ASSERT_EQ(MDR0.RecordKind,
- uint8_t(MetadataRecord::RecordKinds::BufferExtents));
- ASSERT_EQ(MDR1.RecordKind, uint8_t(MetadataRecord::RecordKinds::NewBuffer));
- int32_t Latest = 0;
- memcpy(&Latest, MDR1.Data, sizeof(int32_t));
- ASSERT_EQ(Latest, static_cast<int32_t>(Threads[1]));
-}
-
-} // namespace
-} // namespace __xray
static atomic_uint8_t BasicInitialized{0};
-BasicLoggingOptions GlobalOptions;
+struct BasicLoggingOptions {
+ int DurationFilterMicros = 0;
+ size_t MaxStackDepth = 0;
+ size_t ThreadBufferSize = 0;
+};
+
+struct BasicLoggingOptions GlobalOptions;
thread_local atomic_uint8_t Guard{0};
fsync(TLD.Fd);
}
-XRayLogInitStatus basicLoggingInit(size_t BufferSize, size_t BufferMax,
- void *Options,
+XRayLogInitStatus basicLoggingInit(UNUSED size_t BufferSize,
+ UNUSED size_t BufferMax, void *Options,
size_t OptionsSize) XRAY_NEVER_INSTRUMENT {
uint8_t Expected = 0;
if (!atomic_compare_exchange_strong(&BasicInitialized, &Expected, 1,
"using emulation instead.\n");
});
- if (BufferSize == 0 && BufferMax == 0 && Options != nullptr) {
- FlagParser P;
- BasicFlags F;
- F.setDefaults();
- registerXRayBasicFlags(&P, &F);
- P.ParseString(useCompilerDefinedBasicFlags());
- auto *EnvOpts = GetEnv("XRAY_BASIC_OPTIONS");
- if (EnvOpts == nullptr)
- EnvOpts = "";
-
- P.ParseString(EnvOpts);
-
- // If XRAY_BASIC_OPTIONS was not defined, then we use the deprecated options
- // set through XRAY_OPTIONS instead.
- if (internal_strlen(EnvOpts) == 0) {
- F.func_duration_threshold_us =
- flags()->xray_naive_log_func_duration_threshold_us;
- F.max_stack_depth = flags()->xray_naive_log_max_stack_depth;
- F.thread_buffer_size = flags()->xray_naive_log_thread_buffer_size;
- }
-
- P.ParseString(static_cast<const char *>(Options));
- GlobalOptions.ThreadBufferSize = F.thread_buffer_size;
- GlobalOptions.DurationFilterMicros = F.func_duration_threshold_us;
- GlobalOptions.MaxStackDepth = F.max_stack_depth;
- *basicFlags() = F;
- } else if (OptionsSize != sizeof(BasicLoggingOptions)) {
- Report("Invalid options size, potential ABI mismatch; expected %d got %d",
- sizeof(BasicLoggingOptions), OptionsSize);
- return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED;
- } else {
- if (Verbosity())
- Report("XRay Basic: struct-based init is deprecated, please use "
- "string-based configuration instead.\n");
- GlobalOptions = *reinterpret_cast<BasicLoggingOptions *>(Options);
+ FlagParser P;
+ BasicFlags F;
+ F.setDefaults();
+ registerXRayBasicFlags(&P, &F);
+ P.ParseString(useCompilerDefinedBasicFlags());
+ auto *EnvOpts = GetEnv("XRAY_BASIC_OPTIONS");
+ if (EnvOpts == nullptr)
+ EnvOpts = "";
+
+ P.ParseString(EnvOpts);
+
+ // If XRAY_BASIC_OPTIONS was not defined, then we use the deprecated options
+ // set through XRAY_OPTIONS instead.
+ if (internal_strlen(EnvOpts) == 0) {
+ F.func_duration_threshold_us =
+ flags()->xray_naive_log_func_duration_threshold_us;
+ F.max_stack_depth = flags()->xray_naive_log_max_stack_depth;
+ F.thread_buffer_size = flags()->xray_naive_log_thread_buffer_size;
}
+ P.ParseString(static_cast<const char *>(Options));
+ GlobalOptions.ThreadBufferSize = F.thread_buffer_size;
+ GlobalOptions.DurationFilterMicros = F.func_duration_threshold_us;
+ GlobalOptions.MaxStackDepth = F.max_stack_depth;
+ *basicFlags() = F;
+
atomic_store(&ThresholdTicks,
atomic_load(&TicksPerSec, memory_order_acquire) *
GlobalOptions.DurationFilterMicros / 1000000,
static atomic_sint32_t LogFlushStatus = {
XRayLogFlushStatus::XRAY_LOG_NOT_FLUSHING};
-static FDRLoggingOptions FDROptions;
-
-static SpinMutex FDROptionsMutex;
-
// This function will initialize the thread-local data structure used by the FDR
// logging implementation and return a reference to it. The implementation
// details require a bit of care to maintain.
// (fixed-sized) and let the tools reading the buffers deal with the data
// afterwards.
//
- int Fd = -1;
- {
- // FIXME: Remove this section of the code, when we remove the struct-based
- // configuration API.
- SpinMutexLock Guard(&FDROptionsMutex);
- Fd = FDROptions.Fd;
- }
- if (Fd == -1)
- Fd = getLogFD();
+ int Fd = getLogFD();
if (Fd == -1) {
auto Result = XRayLogFlushStatus::XRAY_LOG_NOT_FLUSHING;
atomic_store(&LogFlushStatus, Result, memory_order_release);
endBufferIfFull();
}
-XRayLogInitStatus fdrLoggingInit(size_t BufferSize, size_t BufferMax,
- void *Options,
+XRayLogInitStatus fdrLoggingInit(UNUSED size_t BufferSize,
+ UNUSED size_t BufferMax, void *Options,
size_t OptionsSize) XRAY_NEVER_INSTRUMENT {
if (Options == nullptr)
return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED;
return static_cast<XRayLogInitStatus>(CurrentStatus);
}
- // Because of __xray_log_init_mode(...) which guarantees that this will be
- // called with BufferSize == 0 and BufferMax == 0 we parse the configuration
- // provided in the Options pointer as a string instead.
- if (BufferSize == 0 && BufferMax == 0) {
- if (Verbosity())
- Report("Initializing FDR mode with options: %s\n",
- static_cast<const char *>(Options));
-
- // TODO: Factor out the flags specific to the FDR mode implementation. For
- // now, use the global/single definition of the flags, since the FDR mode
- // flags are already defined there.
- FlagParser FDRParser;
- FDRFlags FDRFlags;
- registerXRayFDRFlags(&FDRParser, &FDRFlags);
- FDRFlags.setDefaults();
-
- // Override first from the general XRAY_DEFAULT_OPTIONS compiler-provided
- // options until we migrate everyone to use the XRAY_FDR_OPTIONS
- // compiler-provided options.
- FDRParser.ParseString(useCompilerDefinedFlags());
- FDRParser.ParseString(useCompilerDefinedFDRFlags());
- auto *EnvOpts = GetEnv("XRAY_FDR_OPTIONS");
- if (EnvOpts == nullptr)
- EnvOpts = "";
- FDRParser.ParseString(EnvOpts);
-
- // FIXME: Remove this when we fully remove the deprecated flags.
- if (internal_strlen(EnvOpts) == 0) {
- FDRFlags.func_duration_threshold_us =
- flags()->xray_fdr_log_func_duration_threshold_us;
- FDRFlags.grace_period_ms = flags()->xray_fdr_log_grace_period_ms;
- }
-
- // The provided options should always override the compiler-provided and
- // environment-variable defined options.
- FDRParser.ParseString(static_cast<const char *>(Options));
- *fdrFlags() = FDRFlags;
- BufferSize = FDRFlags.buffer_size;
- BufferMax = FDRFlags.buffer_max;
- SpinMutexLock Guard(&FDROptionsMutex);
- FDROptions.Fd = -1;
- FDROptions.ReportErrors = true;
- } else if (OptionsSize != sizeof(FDRLoggingOptions)) {
- // FIXME: This is deprecated, and should really be removed.
- // At this point we use the flag parser specific to the FDR mode
- // implementation.
- if (Verbosity())
- Report("Cannot initialize FDR logging; wrong size for options: %d\n",
- OptionsSize);
- return static_cast<XRayLogInitStatus>(
- atomic_load(&LoggingStatus, memory_order_acquire));
- } else {
- if (Verbosity())
- Report("XRay FDR: struct-based init is deprecated, please use "
- "string-based configuration instead.\n");
- SpinMutexLock Guard(&FDROptionsMutex);
- internal_memcpy(&FDROptions, Options, OptionsSize);
+ if (Verbosity())
+ Report("Initializing FDR mode with options: %s\n",
+ static_cast<const char *>(Options));
+
+ // TODO: Factor out the flags specific to the FDR mode implementation. For
+ // now, use the global/single definition of the flags, since the FDR mode
+ // flags are already defined there.
+ FlagParser FDRParser;
+ FDRFlags FDRFlags;
+ registerXRayFDRFlags(&FDRParser, &FDRFlags);
+ FDRFlags.setDefaults();
+
+ // Override first from the general XRAY_DEFAULT_OPTIONS compiler-provided
+ // options until we migrate everyone to use the XRAY_FDR_OPTIONS
+ // compiler-provided options.
+ FDRParser.ParseString(useCompilerDefinedFlags());
+ FDRParser.ParseString(useCompilerDefinedFDRFlags());
+ auto *EnvOpts = GetEnv("XRAY_FDR_OPTIONS");
+ if (EnvOpts == nullptr)
+ EnvOpts = "";
+ FDRParser.ParseString(EnvOpts);
+
+ // FIXME: Remove this when we fully remove the deprecated flags.
+ if (internal_strlen(EnvOpts) == 0) {
+ FDRFlags.func_duration_threshold_us =
+ flags()->xray_fdr_log_func_duration_threshold_us;
+ FDRFlags.grace_period_ms = flags()->xray_fdr_log_grace_period_ms;
}
+ // The provided options should always override the compiler-provided and
+ // environment-variable defined options.
+ FDRParser.ParseString(static_cast<const char *>(Options));
+ *fdrFlags() = FDRFlags;
+ BufferSize = FDRFlags.buffer_size;
+ BufferMax = FDRFlags.buffer_max;
+
bool Success = false;
if (BQ != nullptr) {
}
XRayLogInitStatus
-profilingLoggingInit(size_t BufferSize, size_t BufferMax, void *Options,
- size_t OptionsSize) XRAY_NEVER_INSTRUMENT {
- if (BufferSize != 0 || BufferMax != 0) {
- if (Verbosity())
- Report("__xray_log_init() being used, and is unsupported. Use "
- "__xray_log_init_mode(...) instead. Bailing out.");
- return XRayLogInitStatus::XRAY_LOG_UNINITIALIZED;
- }
-
+profilingLoggingInit(UNUSED size_t BufferSize, UNUSED size_t BufferMax,
+ void *Options, size_t OptionsSize) XRAY_NEVER_INSTRUMENT {
s32 CurrentStatus = XRayLogInitStatus::XRAY_LOG_UNINITIALIZED;
if (!atomic_compare_exchange_strong(&ProfilerLogStatus, &CurrentStatus,
XRayLogInitStatus::XRAY_LOG_INITIALIZING,
void __attribute__((noinline)) fArg(int) { }
int main(int argc, char *argv[]) {
- using namespace __xray;
std::cout << "Logging before init." << std::endl;
// CHECK: Logging before init.
assert(__xray_log_select_mode("xray-fdr") ==
#include "xray/xray_log_interface.h"
#include <cassert>
-constexpr auto kBufferSize = 16384;
-constexpr auto kBufferMax = 10;
-
[[clang::xray_always_instrument]] void __attribute__((noinline)) fn() { }
int main(int argc, char *argv[]) {
- using namespace __xray;
FDRLoggingOptions Opts;
- auto status = __xray_log_init(kBufferSize, kBufferMax, &Opts, sizeof(Opts));
+ auto status = __xray_log_init_mode("xray-fdr", "");
assert(status == XRayLogInitStatus::XRAY_LOG_INITIALIZED);
__xray_patch();
#include <cassert>
#include <thread>
-constexpr auto kBufferSize = 16384;
-constexpr auto kBufferMax = 10;
-
std::atomic<uint64_t> var{0};
[[clang::xray_always_instrument]] void __attribute__((noinline)) f1() {
}
int main(int argc, char *argv[]) {
- using namespace __xray;
- FDRLoggingOptions Options;
__xray_patch();
- assert(__xray_log_init(kBufferSize, kBufferMax, &Options,
- sizeof(FDRLoggingOptions)) ==
+ assert(__xray_log_init_mode("xray-fdr", "") ==
XRayLogInitStatus::XRAY_LOG_INITIALIZED);
std::atomic_thread_fence(std::memory_order_acq_rel);
std::string current_mode = __xray_log_get_current_mode();
assert(current_mode == "xray-profiling");
assert(__xray_patch() == XRayPatchingStatus::SUCCESS);
- assert(__xray_log_init(0, 0, nullptr, 0) ==
+ assert(__xray_log_init_mode("xray-profiling", "") ==
XRayLogInitStatus::XRAY_LOG_INITIALIZED);
std::thread t0([] { f0(); });
std::thread t1([] { f0(); });