xref: /freebsd/contrib/llvm-project/compiler-rt/include/xray/xray_log_interface.h (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===-- xray_log_interface.h ----------------------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file is a part of XRay, a function call tracing system.
10*0b57cec5SDimitry Andric //
11*0b57cec5SDimitry Andric // APIs for installing a new logging implementation.
12*0b57cec5SDimitry Andric //
13*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
14*0b57cec5SDimitry Andric ///
15*0b57cec5SDimitry Andric /// XRay allows users to implement their own logging handlers and install them
16*0b57cec5SDimitry Andric /// to replace the default runtime-controllable implementation that comes with
17*0b57cec5SDimitry Andric /// compiler-rt/xray. The "flight data recorder" (FDR) mode implementation uses
18*0b57cec5SDimitry Andric /// this API to install itself in an XRay-enabled binary. See
19*0b57cec5SDimitry Andric /// compiler-rt/lib/xray_fdr_logging.{h,cc} for details of that implementation.
20*0b57cec5SDimitry Andric ///
21*0b57cec5SDimitry Andric /// The high-level usage pattern for these APIs look like the following:
22*0b57cec5SDimitry Andric ///
23*0b57cec5SDimitry Andric ///   // We choose the mode which we'd like to install, and check whether this
24*0b57cec5SDimitry Andric ///   // has succeeded. Each mode will have their own set of flags they will
25*0b57cec5SDimitry Andric ///   // support, outside of the global XRay configuration options that are
26*0b57cec5SDimitry Andric ///   // defined in the XRAY_OPTIONS environment variable.
27*0b57cec5SDimitry Andric ///   auto select_status = __xray_log_select_mode("xray-fdr");
28*0b57cec5SDimitry Andric ///   if (select_status != XRayLogRegisterStatus::XRAY_REGISTRATION_OK) {
29*0b57cec5SDimitry Andric ///     // This failed, we should not proceed with attempting to initialise
30*0b57cec5SDimitry Andric ///     // the currently selected mode.
31*0b57cec5SDimitry Andric ///     return;
32*0b57cec5SDimitry Andric ///   }
33*0b57cec5SDimitry Andric ///
34*0b57cec5SDimitry Andric ///   // Once that's done, we can now attempt to configure the implementation.
35*0b57cec5SDimitry Andric ///   // To do this, we provide the string flags configuration for the mode.
36*0b57cec5SDimitry Andric ///   auto config_status = __xray_log_init_mode(
37*0b57cec5SDimitry Andric ///       "xray-fdr", "verbosity=1 some_flag=1 another_flag=2");
38*0b57cec5SDimitry Andric ///   if (config_status != XRayLogInitStatus::XRAY_LOG_INITIALIZED) {
39*0b57cec5SDimitry Andric ///     // deal with the error here, if there is one.
40*0b57cec5SDimitry Andric ///   }
41*0b57cec5SDimitry Andric ///
42*0b57cec5SDimitry Andric ///   // When the log implementation has had the chance to initialize, we can
43*0b57cec5SDimitry Andric ///   // now patch the instrumentation points. Note that we could have patched
44*0b57cec5SDimitry Andric ///   // the instrumentation points first, but there's no strict ordering to
45*0b57cec5SDimitry Andric ///   // these operations.
46*0b57cec5SDimitry Andric ///   auto patch_status = __xray_patch();
47*0b57cec5SDimitry Andric ///   if (patch_status != XRayPatchingStatus::SUCCESS) {
48*0b57cec5SDimitry Andric ///     // deal with the error here, if it is an error.
49*0b57cec5SDimitry Andric ///   }
50*0b57cec5SDimitry Andric ///
51*0b57cec5SDimitry Andric ///   // If we want to stop the implementation, we can then finalize it (before
52*0b57cec5SDimitry Andric ///   // optionally flushing the log).
53*0b57cec5SDimitry Andric ///   auto fin_status = __xray_log_finalize();
54*0b57cec5SDimitry Andric ///   if (fin_status != XRayLogInitStatus::XRAY_LOG_FINALIZED) {
55*0b57cec5SDimitry Andric ///     // deal with the error here, if it is an error.
56*0b57cec5SDimitry Andric ///   }
57*0b57cec5SDimitry Andric ///
58*0b57cec5SDimitry Andric ///   // We can optionally wait before flushing the log to give other threads a
59*0b57cec5SDimitry Andric ///   // chance to see that the implementation is already finalized. Also, at
60*0b57cec5SDimitry Andric ///   // this point we can optionally unpatch the instrumentation points to
61*0b57cec5SDimitry Andric ///   // reduce overheads at runtime.
62*0b57cec5SDimitry Andric ///   auto unpatch_status = __xray_unpatch();
63*0b57cec5SDimitry Andric ///   if (unpatch_status != XRayPatchingStatus::SUCCESS) {
64*0b57cec5SDimitry Andric ///     // deal with the error here, if it is an error.
65*0b57cec5SDimitry Andric ///   }
66*0b57cec5SDimitry Andric ///
67*0b57cec5SDimitry Andric ///   // If there are logs or data to be flushed somewhere, we can do so only
68*0b57cec5SDimitry Andric ///   // after we've finalized the log. Some implementations may not actually
69*0b57cec5SDimitry Andric ///   // have anything to log (it might keep the data in memory, or periodically
70*0b57cec5SDimitry Andric ///   // be logging the data anyway).
71*0b57cec5SDimitry Andric ///   auto flush_status = __xray_log_flushLog();
72*0b57cec5SDimitry Andric ///   if (flush_status != XRayLogFlushStatus::XRAY_LOG_FLUSHED) {
73*0b57cec5SDimitry Andric ///     // deal with the error here, if it is an error.
74*0b57cec5SDimitry Andric ///   }
75*0b57cec5SDimitry Andric ///
76*0b57cec5SDimitry Andric ///   // Alternatively, we can go through the buffers ourselves without
77*0b57cec5SDimitry Andric ///   // relying on the implementations' flushing semantics (if the
78*0b57cec5SDimitry Andric ///   // implementation supports exporting this data directly).
79*0b57cec5SDimitry Andric ///   auto MyBufferProcessor = +[](const char* mode, XRayBuffer buffer) {
80*0b57cec5SDimitry Andric ///     // Check the "mode" to see if it's something we know how to handle...
81*0b57cec5SDimitry Andric ///     // and/or do something with an XRayBuffer instance.
82*0b57cec5SDimitry Andric ///   };
83*0b57cec5SDimitry Andric ///   auto process_status = __xray_log_process_buffers(MyBufferProcessor);
84*0b57cec5SDimitry Andric ///   if (process_status != XRayLogFlushStatus::XRAY_LOG_FLUSHED) {
85*0b57cec5SDimitry Andric ///     // deal with the error here, if it is an error.
86*0b57cec5SDimitry Andric ///   }
87*0b57cec5SDimitry Andric ///
88*0b57cec5SDimitry Andric /// NOTE: Before calling __xray_patch() again, consider re-initializing the
89*0b57cec5SDimitry Andric /// implementation first. Some implementations might stay in an "off" state when
90*0b57cec5SDimitry Andric /// they are finalized, while some might be in an invalid/unknown state.
91*0b57cec5SDimitry Andric ///
92*0b57cec5SDimitry Andric #ifndef XRAY_XRAY_LOG_INTERFACE_H
93*0b57cec5SDimitry Andric #define XRAY_XRAY_LOG_INTERFACE_H
94*0b57cec5SDimitry Andric 
95*0b57cec5SDimitry Andric #include "xray/xray_interface.h"
96*0b57cec5SDimitry Andric #include <stddef.h>
97*0b57cec5SDimitry Andric 
98*0b57cec5SDimitry Andric extern "C" {
99*0b57cec5SDimitry Andric 
100*0b57cec5SDimitry Andric /// This enum defines the valid states in which the logging implementation can
101*0b57cec5SDimitry Andric /// be at.
102*0b57cec5SDimitry Andric enum XRayLogInitStatus {
103*0b57cec5SDimitry Andric   /// The default state is uninitialized, and in case there were errors in the
104*0b57cec5SDimitry Andric   /// initialization, the implementation MUST return XRAY_LOG_UNINITIALIZED.
105*0b57cec5SDimitry Andric   XRAY_LOG_UNINITIALIZED = 0,
106*0b57cec5SDimitry Andric 
107*0b57cec5SDimitry Andric   /// Some implementations support multi-stage init (or asynchronous init), and
108*0b57cec5SDimitry Andric   /// may return XRAY_LOG_INITIALIZING to signal callers of the API that
109*0b57cec5SDimitry Andric   /// there's an ongoing initialization routine running. This allows
110*0b57cec5SDimitry Andric   /// implementations to support concurrent threads attempting to initialize,
111*0b57cec5SDimitry Andric   /// while only signalling success in one.
112*0b57cec5SDimitry Andric   XRAY_LOG_INITIALIZING = 1,
113*0b57cec5SDimitry Andric 
114*0b57cec5SDimitry Andric   /// When an implementation is done initializing, it MUST return
115*0b57cec5SDimitry Andric   /// XRAY_LOG_INITIALIZED. When users call `__xray_patch()`, they are
116*0b57cec5SDimitry Andric   /// guaranteed that the implementation installed with
117*0b57cec5SDimitry Andric   /// `__xray_set_log_impl(...)` has been initialized.
118*0b57cec5SDimitry Andric   XRAY_LOG_INITIALIZED = 2,
119*0b57cec5SDimitry Andric 
120*0b57cec5SDimitry Andric   /// Some implementations might support multi-stage finalization (or
121*0b57cec5SDimitry Andric   /// asynchronous finalization), and may return XRAY_LOG_FINALIZING to signal
122*0b57cec5SDimitry Andric   /// callers of the API that there's an ongoing finalization routine running.
123*0b57cec5SDimitry Andric   /// This allows implementations to support concurrent threads attempting to
124*0b57cec5SDimitry Andric   /// finalize, while only signalling success/completion in one.
125*0b57cec5SDimitry Andric   XRAY_LOG_FINALIZING = 3,
126*0b57cec5SDimitry Andric 
127*0b57cec5SDimitry Andric   /// When an implementation is done finalizing, it MUST return
128*0b57cec5SDimitry Andric   /// XRAY_LOG_FINALIZED. It is up to the implementation to determine what the
129*0b57cec5SDimitry Andric   /// semantics of a finalized implementation is. Some implementations might
130*0b57cec5SDimitry Andric   /// allow re-initialization once the log is finalized, while some might always
131*0b57cec5SDimitry Andric   /// be on (and that finalization is a no-op).
132*0b57cec5SDimitry Andric   XRAY_LOG_FINALIZED = 4,
133*0b57cec5SDimitry Andric };
134*0b57cec5SDimitry Andric 
135*0b57cec5SDimitry Andric /// This enum allows an implementation to signal log flushing operations via
136*0b57cec5SDimitry Andric /// `__xray_log_flushLog()`, and the state of flushing the log.
137*0b57cec5SDimitry Andric enum XRayLogFlushStatus {
138*0b57cec5SDimitry Andric   XRAY_LOG_NOT_FLUSHING = 0,
139*0b57cec5SDimitry Andric   XRAY_LOG_FLUSHING = 1,
140*0b57cec5SDimitry Andric   XRAY_LOG_FLUSHED = 2,
141*0b57cec5SDimitry Andric };
142*0b57cec5SDimitry Andric 
143*0b57cec5SDimitry Andric /// This enum indicates the installation state of a logging implementation, when
144*0b57cec5SDimitry Andric /// associating a mode to a particular logging implementation through
145*0b57cec5SDimitry Andric /// `__xray_log_register_impl(...)` or through `__xray_log_select_mode(...`.
146*0b57cec5SDimitry Andric enum XRayLogRegisterStatus {
147*0b57cec5SDimitry Andric   XRAY_REGISTRATION_OK = 0,
148*0b57cec5SDimitry Andric   XRAY_DUPLICATE_MODE = 1,
149*0b57cec5SDimitry Andric   XRAY_MODE_NOT_FOUND = 2,
150*0b57cec5SDimitry Andric   XRAY_INCOMPLETE_IMPL = 3,
151*0b57cec5SDimitry Andric };
152*0b57cec5SDimitry Andric 
153*0b57cec5SDimitry Andric /// A valid XRay logging implementation MUST provide all of the function
154*0b57cec5SDimitry Andric /// pointers in XRayLogImpl when being installed through `__xray_set_log_impl`.
155*0b57cec5SDimitry Andric /// To be precise, ALL the functions pointers MUST NOT be nullptr.
156*0b57cec5SDimitry Andric struct XRayLogImpl {
157*0b57cec5SDimitry Andric   /// The log initialization routine provided by the implementation, always
158*0b57cec5SDimitry Andric   /// provided with the following parameters:
159*0b57cec5SDimitry Andric   ///
160*0b57cec5SDimitry Andric   ///   - buffer size (unused)
161*0b57cec5SDimitry Andric   ///   - maximum number of buffers (unused)
162*0b57cec5SDimitry Andric   ///   - a pointer to an argument struct that the implementation MUST handle
163*0b57cec5SDimitry Andric   ///   - the size of the argument struct
164*0b57cec5SDimitry Andric   ///
165*0b57cec5SDimitry Andric   /// See XRayLogInitStatus for details on what the implementation MUST return
166*0b57cec5SDimitry Andric   /// when called.
167*0b57cec5SDimitry Andric   ///
168*0b57cec5SDimitry Andric   /// If the implementation needs to install handlers aside from the 0-argument
169*0b57cec5SDimitry Andric   /// function call handler, it MUST do so in this initialization handler.
170*0b57cec5SDimitry Andric   ///
171*0b57cec5SDimitry Andric   /// See xray_interface.h for available handler installation routines.
172*0b57cec5SDimitry Andric   XRayLogInitStatus (*log_init)(size_t, size_t, void *, size_t);
173*0b57cec5SDimitry Andric 
174*0b57cec5SDimitry Andric   /// The log finalization routine provided by the implementation.
175*0b57cec5SDimitry Andric   ///
176*0b57cec5SDimitry Andric   /// See XRayLogInitStatus for details on what the implementation MUST return
177*0b57cec5SDimitry Andric   /// when called.
178*0b57cec5SDimitry Andric   XRayLogInitStatus (*log_finalize)();
179*0b57cec5SDimitry Andric 
180*0b57cec5SDimitry Andric   /// The 0-argument function call handler. XRay logging implementations MUST
181*0b57cec5SDimitry Andric   /// always have a handler for function entry and exit events. In case the
182*0b57cec5SDimitry Andric   /// implementation wants to support arg1 (or other future extensions to XRay
183*0b57cec5SDimitry Andric   /// logging) those MUST be installed by the installed 'log_init' handler.
184*0b57cec5SDimitry Andric   ///
185*0b57cec5SDimitry Andric   /// Because we didn't want to change the ABI of this struct, the arg1 handler
186*0b57cec5SDimitry Andric   /// may be silently overwritten during initialization as well.
187*0b57cec5SDimitry Andric   void (*handle_arg0)(int32_t, XRayEntryType);
188*0b57cec5SDimitry Andric 
189*0b57cec5SDimitry Andric   /// The log implementation provided routine for when __xray_log_flushLog() is
190*0b57cec5SDimitry Andric   /// called.
191*0b57cec5SDimitry Andric   ///
192*0b57cec5SDimitry Andric   /// See XRayLogFlushStatus for details on what the implementation MUST return
193*0b57cec5SDimitry Andric   /// when called.
194*0b57cec5SDimitry Andric   XRayLogFlushStatus (*flush_log)();
195*0b57cec5SDimitry Andric };
196*0b57cec5SDimitry Andric 
197*0b57cec5SDimitry Andric /// DEPRECATED: Use the mode registration workflow instead with
198*0b57cec5SDimitry Andric /// __xray_log_register_mode(...) and __xray_log_select_mode(...). See the
199*0b57cec5SDimitry Andric /// documentation for those function.
200*0b57cec5SDimitry Andric ///
201*0b57cec5SDimitry Andric /// This function installs a new logging implementation that XRay will use. In
202*0b57cec5SDimitry Andric /// case there are any nullptr members in Impl, XRay will *uninstall any
203*0b57cec5SDimitry Andric /// existing implementations*. It does NOT patch the instrumentation points.
204*0b57cec5SDimitry Andric ///
205*0b57cec5SDimitry Andric /// NOTE: This function does NOT attempt to finalize the currently installed
206*0b57cec5SDimitry Andric /// implementation. Use with caution.
207*0b57cec5SDimitry Andric ///
208*0b57cec5SDimitry Andric /// It is guaranteed safe to call this function in the following states:
209*0b57cec5SDimitry Andric ///
210*0b57cec5SDimitry Andric ///   - When the implementation is UNINITIALIZED.
211*0b57cec5SDimitry Andric ///   - When the implementation is FINALIZED.
212*0b57cec5SDimitry Andric ///   - When there is no current implementation installed.
213*0b57cec5SDimitry Andric ///
214*0b57cec5SDimitry Andric /// It is logging implementation defined what happens when this function is
215*0b57cec5SDimitry Andric /// called while in any other states.
216*0b57cec5SDimitry Andric void __xray_set_log_impl(XRayLogImpl Impl);
217*0b57cec5SDimitry Andric 
218*0b57cec5SDimitry Andric /// This function registers a logging implementation against a "mode"
219*0b57cec5SDimitry Andric /// identifier. This allows multiple modes to be registered, and chosen at
220*0b57cec5SDimitry Andric /// runtime using the same mode identifier through
221*0b57cec5SDimitry Andric /// `__xray_log_select_mode(...)`.
222*0b57cec5SDimitry Andric ///
223*0b57cec5SDimitry Andric /// We treat the Mode identifier as a null-terminated byte string, as the
224*0b57cec5SDimitry Andric /// identifier used when retrieving the log impl.
225*0b57cec5SDimitry Andric ///
226*0b57cec5SDimitry Andric /// Returns:
227*0b57cec5SDimitry Andric ///   - XRAY_REGISTRATION_OK on success.
228*0b57cec5SDimitry Andric ///   - XRAY_DUPLICATE_MODE when an implementation is already associated with
229*0b57cec5SDimitry Andric ///     the provided Mode; does not update the already-registered
230*0b57cec5SDimitry Andric ///     implementation.
231*0b57cec5SDimitry Andric XRayLogRegisterStatus __xray_log_register_mode(const char *Mode,
232*0b57cec5SDimitry Andric                                                XRayLogImpl Impl);
233*0b57cec5SDimitry Andric 
234*0b57cec5SDimitry Andric /// This function selects the implementation associated with Mode that has been
235*0b57cec5SDimitry Andric /// registered through __xray_log_register_mode(...) and installs that
236*0b57cec5SDimitry Andric /// implementation (as if through calling __xray_set_log_impl(...)). The same
237*0b57cec5SDimitry Andric /// caveats apply to __xray_log_select_mode(...) as with
238*0b57cec5SDimitry Andric /// __xray_log_set_log_impl(...).
239*0b57cec5SDimitry Andric ///
240*0b57cec5SDimitry Andric /// Returns:
241*0b57cec5SDimitry Andric ///   - XRAY_REGISTRATION_OK on success.
242*0b57cec5SDimitry Andric ///   - XRAY_MODE_NOT_FOUND if there is no implementation associated with Mode;
243*0b57cec5SDimitry Andric ///     does not update the currently installed implementation.
244*0b57cec5SDimitry Andric XRayLogRegisterStatus __xray_log_select_mode(const char *Mode);
245*0b57cec5SDimitry Andric 
246*0b57cec5SDimitry Andric /// Returns an identifier for the currently selected XRay mode chosen through
247*0b57cec5SDimitry Andric /// the __xray_log_select_mode(...) function call. Returns nullptr if there is
248*0b57cec5SDimitry Andric /// no currently installed mode.
249*0b57cec5SDimitry Andric const char *__xray_log_get_current_mode();
250*0b57cec5SDimitry Andric 
251*0b57cec5SDimitry Andric /// This function removes the currently installed implementation. It will also
252*0b57cec5SDimitry Andric /// uninstall any handlers that have been previously installed. It does NOT
253*0b57cec5SDimitry Andric /// unpatch the instrumentation points.
254*0b57cec5SDimitry Andric ///
255*0b57cec5SDimitry Andric /// NOTE: This function does NOT attempt to finalize the currently installed
256*0b57cec5SDimitry Andric /// implementation. Use with caution.
257*0b57cec5SDimitry Andric ///
258*0b57cec5SDimitry Andric /// It is guaranteed safe to call this function in the following states:
259*0b57cec5SDimitry Andric ///
260*0b57cec5SDimitry Andric ///   - When the implementation is UNINITIALIZED.
261*0b57cec5SDimitry Andric ///   - When the implementation is FINALIZED.
262*0b57cec5SDimitry Andric ///   - When there is no current implementation installed.
263*0b57cec5SDimitry Andric ///
264*0b57cec5SDimitry Andric /// It is logging implementation defined what happens when this function is
265*0b57cec5SDimitry Andric /// called while in any other states.
266*0b57cec5SDimitry Andric void __xray_remove_log_impl();
267*0b57cec5SDimitry Andric 
268*0b57cec5SDimitry Andric /// DEPRECATED: Use __xray_log_init_mode() instead, and provide all the options
269*0b57cec5SDimitry Andric /// in string form.
270*0b57cec5SDimitry Andric /// Invokes the installed implementation initialization routine. See
271*0b57cec5SDimitry Andric /// XRayLogInitStatus for what the return values mean.
272*0b57cec5SDimitry Andric XRayLogInitStatus __xray_log_init(size_t BufferSize, size_t MaxBuffers,
273*0b57cec5SDimitry Andric                                   void *Args, size_t ArgsSize);
274*0b57cec5SDimitry Andric 
275*0b57cec5SDimitry Andric /// Invokes the installed initialization routine, which *must* support the
276*0b57cec5SDimitry Andric /// string based form.
277*0b57cec5SDimitry Andric ///
278*0b57cec5SDimitry Andric /// NOTE: When this API is used, we still invoke the installed initialization
279*0b57cec5SDimitry Andric /// routine, but we will call it with the following convention to signal that we
280*0b57cec5SDimitry Andric /// are using the string form:
281*0b57cec5SDimitry Andric ///
282*0b57cec5SDimitry Andric /// - BufferSize = 0
283*0b57cec5SDimitry Andric /// - MaxBuffers = 0
284*0b57cec5SDimitry Andric /// - ArgsSize = 0
285*0b57cec5SDimitry Andric /// - Args will be the pointer to the character buffer representing the
286*0b57cec5SDimitry Andric ///   configuration.
287*0b57cec5SDimitry Andric ///
288*0b57cec5SDimitry Andric /// FIXME: Updating the XRayLogImpl struct is an ABI breaking change. When we
289*0b57cec5SDimitry Andric /// are ready to make a breaking change, we should clean this up appropriately.
290*0b57cec5SDimitry Andric XRayLogInitStatus __xray_log_init_mode(const char *Mode, const char *Config);
291*0b57cec5SDimitry Andric 
292*0b57cec5SDimitry Andric /// Like __xray_log_init_mode(...) this version allows for providing
293*0b57cec5SDimitry Andric /// configurations that might have non-null-terminated strings. This will
294*0b57cec5SDimitry Andric /// operate similarly to __xray_log_init_mode, with the exception that
295*0b57cec5SDimitry Andric /// |ArgsSize| will be what |ConfigSize| is.
296*0b57cec5SDimitry Andric XRayLogInitStatus __xray_log_init_mode_bin(const char *Mode, const char *Config,
297*0b57cec5SDimitry Andric                                            size_t ConfigSize);
298*0b57cec5SDimitry Andric 
299*0b57cec5SDimitry Andric /// Invokes the installed implementation finalization routine. See
300*0b57cec5SDimitry Andric /// XRayLogInitStatus for what the return values mean.
301*0b57cec5SDimitry Andric XRayLogInitStatus __xray_log_finalize();
302*0b57cec5SDimitry Andric 
303*0b57cec5SDimitry Andric /// Invokes the install implementation log flushing routine. See
304*0b57cec5SDimitry Andric /// XRayLogFlushStatus for what the return values mean.
305*0b57cec5SDimitry Andric XRayLogFlushStatus __xray_log_flushLog();
306*0b57cec5SDimitry Andric 
307*0b57cec5SDimitry Andric /// An XRayBuffer represents a section of memory which can be treated by log
308*0b57cec5SDimitry Andric /// processing functions as bytes stored in the logging implementation's
309*0b57cec5SDimitry Andric /// buffers.
310*0b57cec5SDimitry Andric struct XRayBuffer {
311*0b57cec5SDimitry Andric   const void *Data;
312*0b57cec5SDimitry Andric   size_t Size;
313*0b57cec5SDimitry Andric };
314*0b57cec5SDimitry Andric 
315*0b57cec5SDimitry Andric /// Registers an iterator function which takes an XRayBuffer argument, then
316*0b57cec5SDimitry Andric /// returns another XRayBuffer function representing the next buffer. When the
317*0b57cec5SDimitry Andric /// Iterator function returns an empty XRayBuffer (Data = nullptr, Size = 0),
318*0b57cec5SDimitry Andric /// this signifies the end of the buffers.
319*0b57cec5SDimitry Andric ///
320*0b57cec5SDimitry Andric /// The first invocation of this Iterator function will always take an empty
321*0b57cec5SDimitry Andric /// XRayBuffer (Data = nullptr, Size = 0).
322*0b57cec5SDimitry Andric void __xray_log_set_buffer_iterator(XRayBuffer (*Iterator)(XRayBuffer));
323*0b57cec5SDimitry Andric 
324*0b57cec5SDimitry Andric /// Removes the currently registered buffer iterator function.
325*0b57cec5SDimitry Andric void __xray_log_remove_buffer_iterator();
326*0b57cec5SDimitry Andric 
327*0b57cec5SDimitry Andric /// Invokes the provided handler to process data maintained by the logging
328*0b57cec5SDimitry Andric /// handler. This API will be provided raw access to the data available in
329*0b57cec5SDimitry Andric /// memory from the logging implementation. The callback function must:
330*0b57cec5SDimitry Andric ///
331*0b57cec5SDimitry Andric /// 1) Not modify the data, to avoid running into undefined behaviour.
332*0b57cec5SDimitry Andric ///
333*0b57cec5SDimitry Andric /// 2) Either know the data layout, or treat the data as raw bytes for later
334*0b57cec5SDimitry Andric ///    interpretation.
335*0b57cec5SDimitry Andric ///
336*0b57cec5SDimitry Andric /// This API is best used in place of the `__xray_log_flushLog()` implementation
337*0b57cec5SDimitry Andric /// above to enable the caller to provide an alternative means of extracting the
338*0b57cec5SDimitry Andric /// data from the XRay implementation.
339*0b57cec5SDimitry Andric ///
340*0b57cec5SDimitry Andric /// Implementations MUST then provide:
341*0b57cec5SDimitry Andric ///
342*0b57cec5SDimitry Andric /// 1) A function that will return an XRayBuffer. Functions that return an
343*0b57cec5SDimitry Andric ///    "empty" XRayBuffer signifies that there are no more buffers to be
344*0b57cec5SDimitry Andric ///    processed. This function should be registered through the
345*0b57cec5SDimitry Andric ///    `__xray_log_set_buffer_iterator(...)` function.
346*0b57cec5SDimitry Andric ///
347*0b57cec5SDimitry Andric /// 2) Its own means of converting data it holds in memory into an XRayBuffer
348*0b57cec5SDimitry Andric ///    structure.
349*0b57cec5SDimitry Andric ///
350*0b57cec5SDimitry Andric /// See XRayLogFlushStatus for what the return values mean.
351*0b57cec5SDimitry Andric ///
352*0b57cec5SDimitry Andric XRayLogFlushStatus __xray_log_process_buffers(void (*Processor)(const char *,
353*0b57cec5SDimitry Andric                                                                 XRayBuffer));
354*0b57cec5SDimitry Andric 
355*0b57cec5SDimitry Andric } // extern "C"
356*0b57cec5SDimitry Andric 
357*0b57cec5SDimitry Andric #endif // XRAY_XRAY_LOG_INTERFACE_H
358