1 // RUN: %clangxx_xray -g -std=c++11 %s -o %t
2 // RUN: rm xray-log.fdr-reinit* || true
3 // RUN: XRAY_OPTIONS="verbosity=1" %run %t
4 // RUN: rm xray-log.fdr-reinit* || true
5 #include "xray/xray_log_interface.h"
6 #include <atomic>
7 #include <cassert>
8 #include <cstddef>
9 #include <thread>
10 
11 volatile uint64_t var = 0;
12 
13 std::atomic_flag keep_going = ATOMIC_FLAG_INIT;
14 
15 [[clang::xray_always_instrument]] void __attribute__((noinline)) func() {
16   ++var;
17 }
18 
19 int main(int argc, char *argv[]) {
20   // Start a thread that will just keep calling the function, to spam calls to
21   // the function call handler.
22   keep_going.test_and_set(std::memory_order_acquire);
23   std::thread t([] {
24     while (keep_going.test_and_set(std::memory_order_acquire))
25       func();
26   });
27 
28   static constexpr char kConfig[] =
29       "buffer_size=1024:buffer_max=10:no_file_flush=true";
30 
31   // Then we initialize the FDR mode implementation.
32   assert(__xray_log_select_mode("xray-fdr") ==
33          XRayLogRegisterStatus::XRAY_REGISTRATION_OK);
34   auto init_status = __xray_log_init_mode("xray-fdr", kConfig);
35   assert(init_status == XRayLogInitStatus::XRAY_LOG_INITIALIZED);
36 
37   // Now we patch the instrumentation points.
38   __xray_patch();
39 
40   // Spin for a bit, calling func() enough times.
41   for (auto i = 0; i < 1 << 20; ++i)
42     func();
43 
44   // Then immediately finalize the implementation.
45   auto finalize_status = __xray_log_finalize();
46   assert(finalize_status == XRayLogInitStatus::XRAY_LOG_FINALIZED);
47 
48   // Once we're here, we should then flush.
49   auto flush_status = __xray_log_flushLog();
50   assert(flush_status == XRayLogFlushStatus::XRAY_LOG_FLUSHED);
51 
52   for (auto trial = 0; trial < 3; trial++) {
53     // Without doing anything else, we should re-initialize.
54     init_status = __xray_log_init_mode("xray-fdr", kConfig);
55     assert(init_status == XRayLogInitStatus::XRAY_LOG_INITIALIZED);
56 
57     // Then we spin for a bit again calling func() enough times.
58     for (auto i = 0; i < 1 << 20; ++i)
59       func();
60 
61     // Then immediately finalize the implementation.
62     finalize_status = __xray_log_finalize();
63     assert(finalize_status == XRayLogInitStatus::XRAY_LOG_FINALIZED);
64 
65     // Once we're here, we should then flush.
66     flush_status = __xray_log_flushLog();
67     assert(flush_status == XRayLogFlushStatus::XRAY_LOG_FLUSHED);
68   }
69 
70   // Finally, we should signal the sibling thread to stop.
71   keep_going.clear(std::memory_order_release);
72 
73   // Then join.
74   t.join();
75 }
76