xref: /aosp_15_r20/external/pigweed/pw_trace_tokenized/public/pw_trace_tokenized/trace_callback.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 //==============================================================================
15 //
16 // The file provides the API for working with callbacks and sinks for the
17 // tokenized trace module.
18 
19 #pragma once
20 
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <string.h>
24 
25 #include "pw_span/span.h"
26 #include "pw_status/status.h"
27 #include "pw_trace_tokenized/config.h"
28 #include "pw_trace_tokenized/trace_tokenized.h"
29 
30 PW_EXTERN_C_START
31 // The pw_trace_EventCallback is called before the sample is encoded or sent
32 // to the sinks. Bits in the return argument can be set to change the behaviour
33 // of tracing.
34 //    - PW_TRACE_EVENT_RETURN_FLAGS_SKIP_EVENT can optionally be set true to
35 //    skip this sample.
36 //    - PW_TRACE_EVENT_RETURN_FLAGS_DISABLE_AFTER_PROCESSING can be set true to
37 //      disable tracing after this sample.
38 //
39 // When registering the callback the parameter 'called_on_every_event' is used
40 // to indicate if the callback should be called even when tracing is disabled.
41 // This behaviour is useful to implment a tracing behaviour, where tracing can
42 // turn on when a specific event occurs.
43 //
44 // If a handle pointer is provided it will be set to a value, which can be later
45 // used to unregister the callback.
46 //
47 // The user_data pointer is provider for use by the application, it can be used
48 // to allow a single function callback to be registered multiple times but act
49 // differently by providing it with different context objects as pointers.
50 //
51 // NOTE: Since callbacks are called within the trace event lock, they should not
52 // register/unregister sinks or callbacks or trigger other trace events.
53 typedef enum {
54   PW_TRACE_CALL_ONLY_WHEN_ENABLED = 0,
55   PW_TRACE_CALL_ON_EVERY_EVENT = 1,
56 } pw_trace_ShouldCallOnEveryEvent;
57 
58 enum {
59   PW_TRACE_EVENT_RETURN_FLAGS_NONE = 0,
60   PW_TRACE_EVENT_RETURN_FLAGS_SKIP_EVENT = 1 << 0,
61   PW_TRACE_EVENT_RETURN_FLAGS_DISABLE_AFTER_PROCESSING = 1 << 1
62 };
63 typedef uint32_t pw_trace_TraceEventReturnFlags;
64 
65 typedef size_t pw_trace_EventCallbackHandle;
66 typedef pw_trace_TraceEventReturnFlags (*pw_trace_EventCallback)(
67     void* user_data, pw_trace_tokenized_TraceEvent* event);
68 
69 pw_Status pw_trace_RegisterEventCallback(
70     pw_trace_EventCallback callback,
71     pw_trace_ShouldCallOnEveryEvent called_on_every_event,
72     void* user_data,
73     pw_trace_EventCallbackHandle* handle);
74 
75 // pw_trace_UnregisterEventCallback will cause the callback to not receive any
76 // more events.
77 pw_Status pw_trace_UnregisterEventCallback(pw_trace_EventCallbackHandle handle);
78 
79 // pw_trace_Sink* is called after the trace event is encoded.
80 // Trace will internally handle locking, so every Start event will have a
81 // matching End event before another sequence is started.
82 // The number of bytes sent to AddBytes will be the number provided at the
83 // start, allowing buffers to allocate the required amount at the start when
84 // necessary.
85 //
86 // If OkStatus() is not returned from Start, the events bytes will be skipped.
87 //
88 // NOTE: Called while tracing is locked (which might be a critical section
89 // depending on application), so quick/simple operations only. One trace event
90 // might result in multiple callbacks if the data is split up.
91 //
92 // If a handle pointer is provided it will be set to a value, which can be later
93 // used to unregister the callback.
94 //
95 // The user_data pointer is provider for use by the application, it can be used
96 // to allow a single function callback to be registered multiple times but act
97 // differently by providing it with different user_data values.
98 //
99 // NOTE: Since callbacks are called within the trace event lock, they should not
100 // register/unregister sinks or callbacks or trigger other trace events.
101 typedef void (*pw_trace_SinkStartBlock)(void* user_data, size_t size);
102 typedef void (*pw_trace_SinkAddBytes)(void* user_data,
103                                       const void* bytes,
104                                       size_t size);
105 typedef void (*pw_trace_SinkEndBlock)(void* user_data);
106 typedef size_t pw_trace_SinkHandle;
107 pw_Status pw_trace_RegisterSink(pw_trace_SinkStartBlock start_func,
108                                 pw_trace_SinkAddBytes add_bytes_func,
109                                 pw_trace_SinkEndBlock end_block_func,
110                                 void* user_data,
111                                 pw_trace_SinkHandle* handle);
112 
113 // pw_trace_UnregisterSink will cause the sink to stop receiving trace data.
114 pw_Status pw_trace_UnregisterSink(pw_trace_SinkHandle handle);
115 
116 PW_EXTERN_C_END
117 
118 #ifdef __cplusplus
119 namespace pw {
120 namespace trace {
121 
122 // C++ API to the tokenized trace callback system
123 // Example: pw::trace::GetTraceCallbacks().UnregisterAllSinks();
124 class Callbacks {
125  public:
126   enum CallOnEveryEvent {
127     kCallOnlyWhenEnabled = PW_TRACE_CALL_ONLY_WHEN_ENABLED,
128     kCallOnEveryEvent = PW_TRACE_CALL_ON_EVERY_EVENT,
129   };
130   using SinkStartBlock = pw_trace_SinkStartBlock;
131   using SinkAddBytes = pw_trace_SinkAddBytes;
132   using SinkEndBlock = pw_trace_SinkEndBlock;
133   using SinkHandle = pw_trace_SinkHandle;
134   struct SinkCallbacks {
135     void* user_data;
136     SinkStartBlock start_block;
137     SinkAddBytes add_bytes;
138     SinkEndBlock end_block;
139   };
140   using EventCallback = pw_trace_EventCallback;
141   using EventCallbackHandle = pw_trace_EventCallbackHandle;
142   using TraceEvent = pw_trace_tokenized_TraceEvent;
143   struct EventCallbacks {
144     void* user_data;
145     EventCallback callback;
146     CallOnEveryEvent called_on_every_event;
147   };
148 
149   pw::Status RegisterSink(SinkStartBlock start_func,
150                           SinkAddBytes add_bytes_func,
151                           SinkEndBlock end_block_func,
152                           void* user_data = nullptr,
153                           SinkHandle* handle = nullptr);
154   pw::Status UnregisterSink(SinkHandle handle);
155   pw::Status UnregisterAllSinks();
156   SinkCallbacks* GetSink(SinkHandle handle);
157   void CallSinks(span<const std::byte> header, span<const std::byte> data);
158 
159   pw::Status RegisterEventCallback(
160       EventCallback callback,
161       CallOnEveryEvent called_on_every_event = kCallOnlyWhenEnabled,
162       void* user_data = nullptr,
163       EventCallbackHandle* handle = nullptr);
164   pw::Status UnregisterEventCallback(EventCallbackHandle handle);
165   pw::Status UnregisterAllEventCallbacks();
166   EventCallbacks* GetEventCallback(EventCallbackHandle handle);
167   pw_trace_TraceEventReturnFlags CallEventCallbacks(
168       CallOnEveryEvent called_on_every_event, TraceEvent* event);
GetCalledOnEveryEventCount()169   size_t GetCalledOnEveryEventCount() const {
170     return called_on_every_event_count_;
171   }
172 
173  private:
174   EventCallbacks event_callbacks_[PW_TRACE_CONFIG_MAX_EVENT_CALLBACKS];
175   SinkCallbacks sink_callbacks_[PW_TRACE_CONFIG_MAX_SINKS];
176   size_t called_on_every_event_count_ = 0;
177 
IsSinkFree(pw_trace_SinkHandle handle)178   bool IsSinkFree(pw_trace_SinkHandle handle) {
179     return sink_callbacks_[handle].start_block == nullptr &&
180            sink_callbacks_[handle].add_bytes == nullptr &&
181            sink_callbacks_[handle].end_block == nullptr;
182   }
183 };
184 
185 // Returns a reference of the tokenized trace callbacks
186 Callbacks& GetCallbacks();
187 
188 // This is a convenience class to register the callback when the object is
189 // created. For example if the callback should always be registered this can be
190 // created as a global object to avoid needing to call register directly.
191 class RegisterCallbackWhenCreated {
192  public:
193   RegisterCallbackWhenCreated(
194       Callbacks& callbacks,
195       Callbacks::EventCallback event_callback,
196       Callbacks::CallOnEveryEvent called_on_every_event =
197           Callbacks::kCallOnlyWhenEnabled,
198       void* user_data = nullptr)
callbacks_(callbacks)199       : callbacks_(callbacks) {
200     callbacks_
201         .RegisterEventCallback(event_callback, called_on_every_event, user_data)
202         .IgnoreError();  // TODO: b/242598609 - Handle Status properly
203   }
204   RegisterCallbackWhenCreated(Callbacks& callbacks,
205                               Callbacks::SinkStartBlock sink_start,
206                               Callbacks::SinkAddBytes sink_add_bytes,
207                               Callbacks::SinkEndBlock sink_end,
208                               void* user_data = nullptr)
callbacks_(callbacks)209       : callbacks_(callbacks) {
210     callbacks_.RegisterSink(sink_start, sink_add_bytes, sink_end, user_data)
211         .IgnoreError();  // TODO: b/242598609 - Handle Status properly
212   }
213 
214  private:
215   Callbacks& callbacks_;
216 };
217 
218 }  // namespace trace
219 }  // namespace pw
220 #endif  // __cplusplus
221