1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef ZEPHYR_INCLUDE_TRACING_TRACING_MACROS_H_
7 #define ZEPHYR_INCLUDE_TRACING_TRACING_MACROS_H_
8 
9 #include <zephyr/sys/util_macro.h>
10 
11 #if !defined(CONFIG_TRACING) && !defined(__DOXYGEN__)
12 
13 #define SYS_PORT_TRACING_FUNC(type, func, ...) do { } while (false)
14 #define SYS_PORT_TRACING_FUNC_ENTER(type, func, ...) do { } while (false)
15 #define SYS_PORT_TRACING_FUNC_BLOCKING(type, func, ...) do { } while (false)
16 #define SYS_PORT_TRACING_FUNC_EXIT(type, func, ...) do { } while (false)
17 #define SYS_PORT_TRACING_OBJ_INIT(obj_type, obj, ...) do { } while (false)
18 #define SYS_PORT_TRACING_OBJ_FUNC(obj_type, func, obj, ...) do { } while (false)
19 #define SYS_PORT_TRACING_OBJ_FUNC_ENTER(obj_type, func, obj, ...) do { } while (false)
20 #define SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(obj_type, func, obj, ...) do { } while (false)
21 #define SYS_PORT_TRACING_OBJ_FUNC_EXIT(obj_type, func, obj, ...) do { } while (false)
22 
23 #define SYS_PORT_TRACING_TRACKING_FIELD(type)
24 
25 #else
26 
27 /**
28  * @brief Tracing utility macros
29  * @defgroup subsys_tracing_macros Tracing utility macros
30  * @ingroup subsys_tracing
31  * @{
32  */
33 
34 /** @cond INTERNAL_HIDDEN */
35 
36 /*
37  * Helper macros used by the extended tracing system
38  */
39 
40 #define _SYS_PORT_TRACING_TYPE_MASK(type) \
41 	sys_port_trace_type_mask_ ## type
42 #define _SYS_PORT_TRACING_FUNC(name, func) \
43 	sys_port_trace_ ## name ## _ ## func
44 #define _SYS_PORT_TRACING_FUNC_ENTER(name, func) \
45 	sys_port_trace_ ## name ## _ ## func ## _enter
46 #define _SYS_PORT_TRACING_FUNC_BLOCKING(name, func) \
47 	sys_port_trace_ ## name ## _ ## func ## _blocking
48 #define _SYS_PORT_TRACING_FUNC_EXIT(name, func) \
49 	sys_port_trace_ ## name ## _ ## func ## _exit
50 #define _SYS_PORT_TRACING_OBJ_INIT(name) \
51 	sys_port_trace_ ## name ## _init
52 #define _SYS_PORT_TRACING_OBJ_FUNC(name, func) \
53 	sys_port_trace_ ## name ## _ ## func
54 #define _SYS_PORT_TRACING_OBJ_FUNC_ENTER(name, func) \
55 	sys_port_trace_ ## name ## _ ## func ## _enter
56 #define _SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(name, func) \
57 	sys_port_trace_ ## name ## _ ## func ## _blocking
58 #define _SYS_PORT_TRACING_OBJ_FUNC_EXIT(name, func) \
59 	sys_port_trace_ ## name ## _ ## func ## _exit
60 
61 /*
62  * Helper macros for the object tracking system
63  */
64 
65 #define _SYS_PORT_TRACKING_OBJ_INIT(name) \
66 	sys_port_track_ ## name ## _init
67 #define _SYS_PORT_TRACKING_OBJ_FUNC(name, func) \
68 	sys_port_track_ ## name ## _ ## func
69 
70 /*
71  * Object trace macros part of the system for checking if certain
72  * objects should be traced or not depending on the tracing configuration.
73  */
74 #if defined(CONFIG_TRACING_THREAD)
75 	#define sys_port_trace_type_mask_k_thread(trace_call) trace_call
76 #else
77 	#define sys_port_trace_type_mask_k_thread(trace_call)
78 	#define sys_port_trace_k_thread_is_disabled 1
79 #endif
80 
81 #if defined(CONFIG_TRACING_WORK)
82 	#define sys_port_trace_type_mask_k_work(trace_call) trace_call
83 	#define sys_port_trace_type_mask_k_work_queue(trace_call) trace_call
84 	#define sys_port_trace_type_mask_k_work_delayable(trace_call) trace_call
85 	#define sys_port_trace_type_mask_k_work_poll(trace_call) trace_call
86 #else
87 	#define sys_port_trace_type_mask_k_work(trace_call)
88 	#define sys_port_trace_type_mask_k_work_queue(trace_call)
89 	#define sys_port_trace_type_mask_k_work_delayable(trace_call)
90 	#define sys_port_trace_type_mask_k_work_poll(trace_call)
91 #endif
92 
93 #if defined(CONFIG_TRACING_SEMAPHORE)
94 	#define sys_port_trace_type_mask_k_sem(trace_call) trace_call
95 #else
96 	#define sys_port_trace_type_mask_k_sem(trace_call)
97 #endif
98 
99 #if defined(CONFIG_TRACING_MUTEX)
100 	#define sys_port_trace_type_mask_k_mutex(trace_call) trace_call
101 #else
102 	#define sys_port_trace_type_mask_k_mutex(trace_call)
103 #endif
104 
105 #if defined(CONFIG_TRACING_CONDVAR)
106 	#define sys_port_trace_type_mask_k_condvar(trace_call) trace_call
107 #else
108 	#define sys_port_trace_type_mask_k_condvar(trace_call)
109 #endif
110 
111 #if defined(CONFIG_TRACING_QUEUE)
112 	#define sys_port_trace_type_mask_k_queue(trace_call) trace_call
113 #else
114 	#define sys_port_trace_type_mask_k_queue(trace_call)
115 #endif
116 
117 #if defined(CONFIG_TRACING_FIFO)
118 	#define sys_port_trace_type_mask_k_fifo(trace_call) trace_call
119 #else
120 	#define sys_port_trace_type_mask_k_fifo(trace_call)
121 #endif
122 
123 #if defined(CONFIG_TRACING_LIFO)
124 	#define sys_port_trace_type_mask_k_lifo(trace_call) trace_call
125 #else
126 	#define sys_port_trace_type_mask_k_lifo(trace_call)
127 #endif
128 
129 #if defined(CONFIG_TRACING_STACK)
130 	#define sys_port_trace_type_mask_k_stack(trace_call) trace_call
131 #else
132 	#define sys_port_trace_type_mask_k_stack(trace_call)
133 #endif
134 
135 #if defined(CONFIG_TRACING_MESSAGE_QUEUE)
136 	#define sys_port_trace_type_mask_k_msgq(trace_call) trace_call
137 #else
138 	#define sys_port_trace_type_mask_k_msgq(trace_call)
139 #endif
140 
141 #if defined(CONFIG_TRACING_MAILBOX)
142 	#define sys_port_trace_type_mask_k_mbox(trace_call) trace_call
143 #else
144 	#define sys_port_trace_type_mask_k_mbox(trace_call)
145 #endif
146 
147 #if defined(CONFIG_TRACING_PIPE)
148 	#define sys_port_trace_type_mask_k_pipe(trace_call) trace_call
149 #else
150 	#define sys_port_trace_type_mask_k_pipe(trace_call)
151 #endif
152 
153 #if defined(CONFIG_TRACING_HEAP)
154 	#define sys_port_trace_type_mask_k_heap(trace_call) trace_call
155 	#define sys_port_trace_type_mask_k_heap_sys(trace_call) trace_call
156 #else
157 	#define sys_port_trace_type_mask_k_heap(trace_call)
158 	#define sys_port_trace_type_mask_k_heap_sys(trace_call)
159 #endif
160 
161 #if defined(CONFIG_TRACING_MEMORY_SLAB)
162 	#define sys_port_trace_type_mask_k_mem_slab(trace_call) trace_call
163 #else
164 	#define sys_port_trace_type_mask_k_mem_slab(trace_call)
165 #endif
166 
167 #if defined(CONFIG_TRACING_TIMER)
168 	#define sys_port_trace_type_mask_k_timer(trace_call) trace_call
169 #else
170 	#define sys_port_trace_type_mask_k_timer(trace_call)
171 #endif
172 
173 #if defined(CONFIG_TRACING_EVENT)
174 	#define sys_port_trace_type_mask_k_event(trace_call) trace_call
175 #else
176 	#define sys_port_trace_type_mask_k_event(trace_call)
177 #endif
178 
179 #ifndef CONFIG_TRACING_POLLING
180 	#define sys_port_trace_k_poll_api_is_disabled 1
181 	#define sys_port_trace_k_work_poll_is_disabled 1
182 #endif
183 
184 #ifndef CONFIG_TRACING_PM
185 	#define sys_port_trace_pm_is_disabled 1
186 #endif
187 
188 #if defined(CONFIG_TRACING_NET_SOCKETS)
189 	#define sys_port_trace_type_mask_socket(trace_call) trace_call
190 #else
191 	#define sys_port_trace_type_mask_socket(trace_call)
192 #endif
193 
194 #if defined(CONFIG_TRACING_NET_CORE)
195 	#define sys_port_trace_type_mask_net(trace_call) trace_call
196 #else
197 	#define sys_port_trace_type_mask_net(trace_call)
198 #endif
199 
200 /*
201  * We cannot positively enumerate all traced APIs, as applications may trace
202  * arbitrary custom APIs we know nothing about. Therefore we demand that tracing
203  * of an API must be actively disabled.
204  *
205  * This contrasts with object tracing/tracking as all traceable objects are well
206  * known, see the SYS_PORT_TRACING_TYPE_MASK approach below.
207  */
208 #define _SYS_PORT_TRACE_IS_DISABLED(type) sys_port_trace_##type##_is_disabled
209 #define _SYS_PORT_TRACE_WRAP(func, ...) do { func(__VA_ARGS__); } while (false)
210 #define _SYS_PORT_TRACE_IF_NOT_DISABLED(type, func, ...)                                           \
211 	COND_CODE_1(_SYS_PORT_TRACE_IS_DISABLED(type), (),                                         \
212 		    (_SYS_PORT_TRACE_WRAP(func, __VA_ARGS__)))
213 
214 /** @endcond */
215 
216 /**
217  * @brief Checks if an object type should be traced or not.
218  *
219  * @param type Tracing event type/object
220  * @param trace_call Tracing call
221  */
222 #define SYS_PORT_TRACING_TYPE_MASK(type, trace_call) \
223 	_SYS_PORT_TRACING_TYPE_MASK(type)(trace_call)
224 
225 /**
226  * @brief Tracing macro for function calls which are not directly
227  * associated with a specific type of object.
228  *
229  * @param type Type of tracing event or object type
230  * @param func Name of the function responsible for the call. This does not need to exactly
231  * match the name of the function but should rather match what the user called in case of
232  * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name.
233  * @param ... Additional parameters relevant to the tracing call
234  */
235 #define SYS_PORT_TRACING_FUNC(type, func, ...)                                                     \
236 	_SYS_PORT_TRACE_IF_NOT_DISABLED(type, _SYS_PORT_TRACING_FUNC(type, func), __VA_ARGS__)
237 
238 /**
239  * @brief Tracing macro for the entry into a function that might or might not return
240  * a value.
241  *
242  * @param type Type of tracing event or object type
243  * @param func Name of the function responsible for the call. This does not need to exactly
244  * match the name of the function but should rather match what the user called in case of
245  * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name.
246  * @param ... Additional parameters relevant to the tracing call
247  */
248 #define SYS_PORT_TRACING_FUNC_ENTER(type, func, ...)                                               \
249 	_SYS_PORT_TRACE_IF_NOT_DISABLED(type, _SYS_PORT_TRACING_FUNC_ENTER(type, func), __VA_ARGS__)
250 
251 /**
252  * @brief Tracing macro for when a function blocks during its execution.
253  *
254  * @param type Type of tracing event or object type
255  * @param func Name of the function responsible for the call. This does not need to exactly
256  * match the name of the function but should rather match what the user called in case of
257  * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name.
258  * @param ... Additional parameters relevant to the tracing call
259  */
260 #define SYS_PORT_TRACING_FUNC_BLOCKING(type, func, ...)                                            \
261 	_SYS_PORT_TRACE_IF_NOT_DISABLED(type, _SYS_PORT_TRACING_FUNC_BLOCKING(type, func),         \
262 					__VA_ARGS__)
263 
264 /**
265  * @brief Tracing macro for when a function ends its execution. Potential return values
266  * can be given as additional arguments.
267  *
268  * @param type Type of tracing event or object type
269  * @param func Name of the function responsible for the call. This does not need to exactly
270  * match the name of the function but should rather match what the user called in case of
271  * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name.
272  * @param ... Additional parameters relevant to the tracing call
273  */
274 #define SYS_PORT_TRACING_FUNC_EXIT(type, func, ...)                                                \
275 	_SYS_PORT_TRACE_IF_NOT_DISABLED(type, _SYS_PORT_TRACING_FUNC_EXIT(type, func), __VA_ARGS__)
276 
277 /**
278  * @brief Tracing macro for the initialization of an object.
279  *
280  * @param obj_type The type of object associated with the call (k_thread, k_sem, k_mutex etc.)
281  * @param obj Object
282  */
283 #define SYS_PORT_TRACING_OBJ_INIT(obj_type, obj, ...) \
284 	do { \
285 		SYS_PORT_TRACING_TYPE_MASK(obj_type, \
286 			_SYS_PORT_TRACING_OBJ_INIT(obj_type)(obj, ##__VA_ARGS__)); \
287 		SYS_PORT_TRACING_TYPE_MASK(obj_type, \
288 			_SYS_PORT_TRACKING_OBJ_INIT(obj_type)(obj, ##__VA_ARGS__)); \
289 	} while (false)
290 
291 /**
292  * @brief Tracing macro for simple object function calls often without returns or branching.
293  *
294  * @param obj_type The type of object associated with the call (k_thread, k_sem, k_mutex etc.)
295  * @param func Name of the function responsible for the call. This does not need to exactly
296  * match the name of the function but should rather match what the user called in case of
297  * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name.
298  * @param obj Object
299  * @param ... Additional parameters relevant to the tracing call
300  */
301 #define SYS_PORT_TRACING_OBJ_FUNC(obj_type, func, obj, ...) \
302 	do { \
303 		SYS_PORT_TRACING_TYPE_MASK(obj_type, \
304 			_SYS_PORT_TRACING_OBJ_FUNC(obj_type, func)(obj, ##__VA_ARGS__)); \
305 		SYS_PORT_TRACING_TYPE_MASK(obj_type, \
306 			_SYS_PORT_TRACKING_OBJ_FUNC(obj_type, func)(obj, ##__VA_ARGS__)); \
307 	} while (false)
308 
309 /**
310  * @brief Tracing macro for the entry into a function that might or might not return
311  * a value.
312  *
313  * @param obj_type The type of object associated with the call (k_thread, k_sem, k_mutex etc.)
314  * @param func Name of the function responsible for the call. This does not need to exactly
315  * match the name of the function but should rather match what the user called in case of
316  * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name.
317  * @param obj Object
318  * @param ... Additional parameters relevant to the tracing call
319  */
320 #define SYS_PORT_TRACING_OBJ_FUNC_ENTER(obj_type, func, obj, ...) \
321 	do { \
322 		SYS_PORT_TRACING_TYPE_MASK(obj_type, \
323 			_SYS_PORT_TRACING_OBJ_FUNC_ENTER(obj_type, func)(obj, ##__VA_ARGS__)); \
324 	} while (false)
325 
326 /**
327  * @brief Tracing macro for when a function blocks during its execution.
328  *
329  * @param obj_type The type of object associated with the call (k_thread, k_sem, k_mutex etc.)
330  * @param func Name of the function responsible for the call. This does not need to exactly
331  * match the name of the function but should rather match what the user called in case of
332  * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name.
333  * @param obj Object
334  * @param timeout Timeout
335  * @param ... Additional parameters relevant to the tracing call
336  */
337 #define SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(obj_type, func, obj, timeout, ...) \
338 	do { \
339 		SYS_PORT_TRACING_TYPE_MASK(obj_type, \
340 			_SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(obj_type, func) \
341 			(obj, timeout, ##__VA_ARGS__)); \
342 	} while (false)
343 
344 /**
345  * @brief Tracing macro for when a function ends its execution. Potential return values
346  * can be given as additional arguments.
347  *
348  * @param obj_type The type of object associated with the call (k_thread, k_sem, k_mutex etc.)
349  * @param func Name of the function responsible for the call. This does not need to exactly
350  * match the name of the function but should rather match what the user called in case of
351  * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name.
352  * @param obj Object
353  * @param ... Additional parameters relevant to the tracing call
354  */
355 #define SYS_PORT_TRACING_OBJ_FUNC_EXIT(obj_type, func, obj, ...) \
356 	do { \
357 		SYS_PORT_TRACING_TYPE_MASK(obj_type, \
358 			_SYS_PORT_TRACING_OBJ_FUNC_EXIT(obj_type, func)(obj, ##__VA_ARGS__)); \
359 	} while (false)
360 
361 /**
362  * @brief Field added to kernel objects so they are tracked.
363  *
364  * @param type Type of object being tracked (k_thread, k_sem, etc.)
365  */
366 #define SYS_PORT_TRACING_TRACKING_FIELD(type) \
367 	SYS_PORT_TRACING_TYPE_MASK(type, struct type *_obj_track_next;)
368 
369 /** @} */ /* end of subsys_tracing_macros */
370 
371 #endif /* CONFIG_TRACING */
372 
373 #endif /* ZEPHYR_INCLUDE_TRACING_TRACING_MACROS_H_ */
374