1 // Copyright 2020 The Pigweed Authors
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
7 // https://www.apache.org/licenses/LICENSE-2.0
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
14 //==============================================================================
16 // The file provides the API for working with callbacks and sinks for the
17 // tokenized trace module.
27 #include "pw_status/status.h"
28 #include "pw_trace_tokenized/config.h"
29 #include "pw_trace_tokenized/trace_tokenized.h"
32 // The pw_trace_EventCallback is called before the sample is encoded or sent
33 // to the sinks. Bits in the return argument can be set to change the behaviour
35 // - PW_TRACE_EVENT_RETURN_FLAGS_SKIP_EVENT can optionally be set true to
37 // - PW_TRACE_EVENT_RETURN_FLAGS_DISABLE_AFTER_PROCESSING can be set true to
38 // disable tracing after this sample.
40 // When registering the callback the parameter 'called_on_every_event' is used
41 // to indicate if the callback should be called even when tracing is disabled.
42 // This behaviour is useful to implment a tracing behaviour, where tracing can
43 // turn on when a specific event occurs.
45 // If a handle pointer is provided it will be set to a value, which can be later
46 // used to unregister the callback.
48 // The user_data pointer is provider for use by the application, it can be used
49 // to allow a single function callback to be registered multiple times but act
50 // differently by providing it with different context objects as pointers.
52 // NOTE: Since callbacks are called within the trace event lock, they should not
53 // register/unregister sinks or callbacks or trigger other trace events.
55 PW_TRACE_CALL_ONLY_WHEN_ENABLED = 0,
56 PW_TRACE_CALL_ON_EVERY_EVENT = 1,
57 } pw_trace_ShouldCallOnEveryEvent;
60 PW_TRACE_EVENT_RETURN_FLAGS_NONE = 0,
61 PW_TRACE_EVENT_RETURN_FLAGS_SKIP_EVENT = 1 << 0,
62 PW_TRACE_EVENT_RETURN_FLAGS_DISABLE_AFTER_PROCESSING = 1 << 1
64 typedef uint32_t pw_trace_TraceEventReturnFlags;
66 typedef size_t pw_trace_EventCallbackHandle;
67 typedef pw_trace_TraceEventReturnFlags (*pw_trace_EventCallback)(
70 pw_trace_EventType event_type,
75 pw_Status pw_trace_RegisterEventCallback(
76 pw_trace_EventCallback callback,
77 pw_trace_ShouldCallOnEveryEvent called_on_every_event,
79 pw_trace_EventCallbackHandle* handle);
81 // pw_trace_UnregisterEventCallback will cause the callback to not receive any
83 pw_Status pw_trace_UnregisterEventCallback(pw_trace_EventCallbackHandle handle);
85 // pw_trace_Sink* is called after the trace event is encoded.
86 // Trace will internally handle locking, so every Start event will have a
87 // matching End event before another sequence is started.
88 // The number of bytes sent to AddBytes will be the number provided at the
89 // start, allowing buffers to allocate the required amount at the start when
92 // If OkStatus() is not returned from Start, the events bytes will be skipped.
94 // NOTE: Called while tracing is locked (which might be a critical section
95 // depending on application), so quick/simple operations only. One trace event
96 // might result in multiple callbacks if the data is split up.
98 // If a handle pointer is provided it will be set to a value, which can be later
99 // used to unregister the callback.
101 // The user_data pointer is provider for use by the application, it can be used
102 // to allow a single function callback to be registered multiple times but act
103 // differently by providing it with different user_data values.
105 // NOTE: Since callbacks are called within the trace event lock, they should not
106 // register/unregister sinks or callbacks or trigger other trace events.
107 typedef void (*pw_trace_SinkStartBlock)(void* user_data, size_t size);
108 typedef void (*pw_trace_SinkAddBytes)(void* user_data,
111 typedef void (*pw_trace_SinkEndBlock)(void* user_data);
112 typedef size_t pw_trace_SinkHandle;
113 pw_Status pw_trace_RegisterSink(pw_trace_SinkStartBlock start_func,
114 pw_trace_SinkAddBytes add_bytes_func,
115 pw_trace_SinkEndBlock end_block_func,
117 pw_trace_SinkHandle* handle);
119 // pw_trace_UnregisterSink will cause the sink to stop receiving trace data.
120 pw_Status pw_trace_UnregisterSink(pw_trace_SinkHandle handle);
128 class CallbacksImpl {
130 enum CallOnEveryEvent {
131 kCallOnlyWhenEnabled = PW_TRACE_CALL_ONLY_WHEN_ENABLED,
132 kCallOnEveryEvent = PW_TRACE_CALL_ON_EVERY_EVENT,
134 using SinkStartBlock = pw_trace_SinkStartBlock;
135 using SinkAddBytes = pw_trace_SinkAddBytes;
136 using SinkEndBlock = pw_trace_SinkEndBlock;
137 using SinkHandle = pw_trace_SinkHandle;
138 struct SinkCallbacks {
140 SinkStartBlock start_block;
141 SinkAddBytes add_bytes;
142 SinkEndBlock end_block;
144 using EventCallback = pw_trace_EventCallback;
145 using EventCallbackHandle = pw_trace_EventCallbackHandle;
146 struct EventCallbacks {
148 EventCallback callback;
149 CallOnEveryEvent called_on_every_event;
152 pw::Status RegisterSink(SinkStartBlock start_func,
153 SinkAddBytes add_bytes_func,
154 SinkEndBlock end_block_func,
155 void* user_data = nullptr,
156 SinkHandle* handle = nullptr);
157 pw::Status UnregisterSink(SinkHandle handle);
158 pw::Status UnregisterAllSinks();
159 SinkCallbacks* GetSink(SinkHandle handle);
160 void CallSinks(std::span<const std::byte> header,
161 std::span<const std::byte> data);
163 pw::Status RegisterEventCallback(
164 EventCallback callback,
165 CallOnEveryEvent called_on_every_event = kCallOnlyWhenEnabled,
166 void* user_data = nullptr,
167 EventCallbackHandle* handle = nullptr);
168 pw::Status UnregisterEventCallback(EventCallbackHandle handle);
169 pw::Status UnregisterAllEventCallbacks();
170 EventCallbacks* GetEventCallback(EventCallbackHandle handle);
171 pw_trace_TraceEventReturnFlags CallEventCallbacks(
172 CallOnEveryEvent called_on_every_event,
174 EventType event_type,
178 size_t GetCalledOnEveryEventCount() const {
179 return called_on_every_event_count_;
183 EventCallbacks event_callbacks_[PW_TRACE_CONFIG_MAX_EVENT_CALLBACKS];
184 SinkCallbacks sink_callbacks_[PW_TRACE_CONFIG_MAX_SINKS];
185 size_t called_on_every_event_count_ = 0;
187 bool IsSinkFree(pw_trace_SinkHandle handle) {
188 return sink_callbacks_[handle].start_block == nullptr &&
189 sink_callbacks_[handle].add_bytes == nullptr &&
190 sink_callbacks_[handle].end_block == nullptr;
194 // A singleton object of the CallbacksImpl class which can be used to
195 // interface with trace using the C++ API.
196 // Example: pw::trace::Callbacks::Instance().UnregisterAllSinks();
199 static CallbacksImpl& Instance() { return instance_; };
202 static CallbacksImpl instance_;
205 // This is a convenience class to register the callback when the object is
206 // created. For example if the callback should always be registered this can be
207 // created as a global object to avoid needing to call register directly.
208 class RegisterCallbackWhenCreated {
210 RegisterCallbackWhenCreated(
211 CallbacksImpl::EventCallback event_callback,
212 CallbacksImpl::CallOnEveryEvent called_on_every_event =
213 CallbacksImpl::kCallOnlyWhenEnabled,
214 void* user_data = nullptr) {
215 Callbacks::Instance().RegisterEventCallback(
216 event_callback, called_on_every_event, user_data);
218 RegisterCallbackWhenCreated(CallbacksImpl::SinkStartBlock sink_start,
219 CallbacksImpl::SinkAddBytes sink_add_bytes,
220 CallbacksImpl::SinkEndBlock sink_end,
221 void* user_data = nullptr) {
222 Callbacks::Instance().RegisterSink(
223 sink_start, sink_add_bytes, sink_end, user_data);
229 #endif // __cplusplus