trace: simplify trace point registration
[dpdk.git] / lib / librte_eal / include / rte_trace_point.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2020 Marvell International Ltd.
3  */
4
5 #ifndef _RTE_TRACE_POINT_H_
6 #define _RTE_TRACE_POINT_H_
7
8 /**
9  * @file
10  *
11  * RTE Tracepoint API
12  *
13  * This file provides the tracepoint API to RTE applications.
14  *
15  * @warning
16  * @b EXPERIMENTAL: this API may change without prior notice
17  */
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22
23 #include <stdbool.h>
24 #include <stdio.h>
25
26 #include <rte_branch_prediction.h>
27 #include <rte_common.h>
28 #include <rte_compat.h>
29 #include <rte_cycles.h>
30 #include <rte_per_lcore.h>
31 #include <rte_string_fns.h>
32 #include <rte_uuid.h>
33
34 /** The tracepoint object. */
35 typedef uint64_t rte_trace_point_t;
36
37 /**
38  * Macro to define the tracepoint arguments in RTE_TRACE_POINT macro.
39
40  * @see RTE_TRACE_POINT, RTE_TRACE_POINT_FP
41  */
42 #define RTE_TRACE_POINT_ARGS
43
44 /** @internal Helper macro to support RTE_TRACE_POINT and RTE_TRACE_POINT_FP */
45 #define __RTE_TRACE_POINT(_mode, _tp, _args, ...) \
46 extern rte_trace_point_t __##_tp; \
47 static __rte_always_inline void \
48 _tp _args \
49 { \
50         __rte_trace_point_emit_header_##_mode(&__##_tp); \
51         __VA_ARGS__ \
52 }
53
54 /**
55  * Create a tracepoint.
56  *
57  * A tracepoint is defined by specifying:
58  * - its input arguments: they are the C function style parameters to define
59  *   the arguments of tracepoint function. These input arguments are embedded
60  *   using the RTE_TRACE_POINT_ARGS macro.
61  * - its output event fields: they are the sources of event fields that form
62  *   the payload of any event that the execution of the tracepoint macro emits
63  *   for this particular tracepoint. The application uses
64  *   rte_trace_point_emit_* macros to emit the output event fields.
65  *
66  * @param tp
67  *   Tracepoint object. Before using the tracepoint, an application needs to
68  *   define the tracepoint using RTE_TRACE_POINT_REGISTER macro.
69  * @param args
70  *   C function style input arguments to define the arguments to tracepoint
71  *   function.
72  * @param ...
73  *   Define the payload of trace function. The payload will be formed using
74  *   rte_trace_point_emit_* macros. Use ";" delimiter between two payloads.
75  *
76  * @see RTE_TRACE_POINT_ARGS, RTE_TRACE_POINT_REGISTER, rte_trace_point_emit_*
77  */
78 #define RTE_TRACE_POINT(tp, args, ...) \
79         __RTE_TRACE_POINT(generic, tp, args, __VA_ARGS__)
80
81 /**
82  * Create a tracepoint for fast path.
83  *
84  * Similar to RTE_TRACE_POINT, except that it is removed at compilation time
85  * unless the RTE_ENABLE_TRACE_FP configuration parameter is set.
86  *
87  * @param tp
88  *   Tracepoint object. Before using the tracepoint, an application needs to
89  *   define the tracepoint using RTE_TRACE_POINT_REGISTER macro.
90  * @param args
91  *   C function style input arguments to define the arguments to tracepoint.
92  *   function.
93  * @param ...
94  *   Define the payload of trace function. The payload will be formed using
95  *   rte_trace_point_emit_* macros, Use ";" delimiter between two payloads.
96  *
97  * @see RTE_TRACE_POINT
98  */
99 #define RTE_TRACE_POINT_FP(tp, args, ...) \
100         __RTE_TRACE_POINT(fp, tp, args, __VA_ARGS__)
101
102 #ifdef __DOXYGEN__
103
104 /**
105  * Register a tracepoint.
106  *
107  * @param trace
108  *   The tracepoint object created using RTE_TRACE_POINT_REGISTER.
109  * @param name
110  *   The name of the tracepoint object.
111  * @return
112  *   - 0: Successfully registered the tracepoint.
113  *   - <0: Failure to register the tracepoint.
114  */
115 #define RTE_TRACE_POINT_REGISTER(trace, name)
116
117 /** Tracepoint function payload for uint64_t datatype */
118 #define rte_trace_point_emit_u64(val)
119 /** Tracepoint function payload for int64_t datatype */
120 #define rte_trace_point_emit_i64(val)
121 /** Tracepoint function payload for uint32_t datatype */
122 #define rte_trace_point_emit_u32(val)
123 /** Tracepoint function payload for int32_t datatype */
124 #define rte_trace_point_emit_i32(val)
125 /** Tracepoint function payload for uint16_t datatype */
126 #define rte_trace_point_emit_u16(val)
127 /** Tracepoint function payload for int16_t datatype */
128 #define rte_trace_point_emit_i16(val)
129 /** Tracepoint function payload for uint8_t datatype */
130 #define rte_trace_point_emit_u8(val)
131 /** Tracepoint function payload for int8_t datatype */
132 #define rte_trace_point_emit_i8(val)
133 /** Tracepoint function payload for int datatype */
134 #define rte_trace_point_emit_int(val)
135 /** Tracepoint function payload for long datatype */
136 #define rte_trace_point_emit_long(val)
137 /** Tracepoint function payload for size_t datatype */
138 #define rte_trace_point_emit_size_t(val)
139 /** Tracepoint function payload for float datatype */
140 #define rte_trace_point_emit_float(val)
141 /** Tracepoint function payload for double datatype */
142 #define rte_trace_point_emit_double(val)
143 /** Tracepoint function payload for pointer datatype */
144 #define rte_trace_point_emit_ptr(val)
145 /** Tracepoint function payload for string datatype */
146 #define rte_trace_point_emit_string(val)
147
148 #endif /* __DOXYGEN__ */
149
150 /** @internal Macro to define maximum emit length of string datatype. */
151 #define __RTE_TRACE_EMIT_STRING_LEN_MAX 32
152 /** @internal Macro to define event header size. */
153 #define __RTE_TRACE_EVENT_HEADER_SZ sizeof(uint64_t)
154
155 /**
156  * Enable recording events of the given tracepoint in the trace buffer.
157  *
158  * @param tp
159  *   The tracepoint object to enable.
160  * @return
161  *   - 0: Success.
162  *   - (-ERANGE): Trace object is not registered.
163  */
164 __rte_experimental
165 int rte_trace_point_enable(rte_trace_point_t *tp);
166
167 /**
168  * Disable recording events of the given tracepoint in the trace buffer.
169  *
170  * @param tp
171  *   The tracepoint object to disable.
172  * @return
173  *   - 0: Success.
174  *   - (-ERANGE): Trace object is not registered.
175  */
176 __rte_experimental
177 int rte_trace_point_disable(rte_trace_point_t *tp);
178
179 /**
180  * Test if recording events from the given tracepoint is enabled.
181  *
182  * @param tp
183  *    The tracepoint object.
184  * @return
185  *    true if tracepoint is enabled, false otherwise.
186  */
187 __rte_experimental
188 bool rte_trace_point_is_enabled(rte_trace_point_t *tp);
189
190 /**
191  * Lookup a tracepoint object from its name.
192  *
193  * @param name
194  *   The name of the tracepoint.
195  * @return
196  *   The tracepoint object or NULL if not found.
197  */
198 __rte_experimental
199 rte_trace_point_t *rte_trace_point_lookup(const char *name);
200
201 /**
202  * @internal
203  *
204  * Test if the tracepoint fast path compile-time option is enabled.
205  *
206  * @return
207  *   true if tracepoint fast path enabled, false otherwise.
208  */
209 __rte_experimental
210 static __rte_always_inline bool
211 __rte_trace_point_fp_is_enabled(void)
212 {
213 #ifdef RTE_ENABLE_TRACE_FP
214         return true;
215 #else
216         return false;
217 #endif
218 }
219
220 /**
221  * @internal
222  *
223  * Allocate trace memory buffer per thread.
224  *
225  */
226 __rte_experimental
227 void __rte_trace_mem_per_thread_alloc(void);
228
229 /**
230  * @internal
231  *
232  * Helper function to emit field.
233  *
234  * @param sz
235  *   The tracepoint size.
236  * @param field
237  *   The name of the trace event.
238  * @param type
239  *   The datatype of the trace event as string.
240  * @return
241  *   - 0: Success.
242  *   - <0: Failure.
243  */
244 __rte_experimental
245 void __rte_trace_point_emit_field(size_t sz, const char *field,
246         const char *type);
247
248 /**
249  * @internal
250  *
251  * Helper function to register a dynamic tracepoint.
252  * Use RTE_TRACE_POINT_REGISTER macro for tracepoint registration.
253  *
254  * @param trace
255  *   The tracepoint object created using RTE_TRACE_POINT_REGISTER.
256  * @param name
257  *   The name of the tracepoint object.
258  * @param register_fn
259  *   Trace registration function.
260  * @return
261  *   - 0: Successfully registered the tracepoint.
262  *   - <0: Failure to register the tracepoint.
263  */
264 __rte_experimental
265 int __rte_trace_point_register(rte_trace_point_t *trace, const char *name,
266         void (*register_fn)(void));
267
268 #ifndef __DOXYGEN__
269
270 #ifndef _RTE_TRACE_POINT_REGISTER_H_
271 #ifdef ALLOW_EXPERIMENTAL_API
272
273 #define __RTE_TRACE_EVENT_HEADER_ID_SHIFT (48)
274
275 #define __RTE_TRACE_FIELD_SIZE_SHIFT 0
276 #define __RTE_TRACE_FIELD_SIZE_MASK (0xffffULL << __RTE_TRACE_FIELD_SIZE_SHIFT)
277 #define __RTE_TRACE_FIELD_ID_SHIFT (16)
278 #define __RTE_TRACE_FIELD_ID_MASK (0xffffULL << __RTE_TRACE_FIELD_ID_SHIFT)
279 #define __RTE_TRACE_FIELD_ENABLE_MASK (1ULL << 63)
280 #define __RTE_TRACE_FIELD_ENABLE_DISCARD (1ULL << 62)
281
282 struct __rte_trace_stream_header {
283         uint32_t magic;
284         rte_uuid_t uuid;
285         uint32_t lcore_id;
286         char thread_name[__RTE_TRACE_EMIT_STRING_LEN_MAX];
287 } __rte_packed;
288
289 struct __rte_trace_header {
290         uint32_t offset;
291         uint32_t len;
292         struct __rte_trace_stream_header stream_header;
293         uint8_t mem[];
294 };
295
296 RTE_DECLARE_PER_LCORE(void *, trace_mem);
297
298 static __rte_always_inline void *
299 __rte_trace_mem_get(uint64_t in)
300 {
301         struct __rte_trace_header *trace = RTE_PER_LCORE(trace_mem);
302         const uint16_t sz = in & __RTE_TRACE_FIELD_SIZE_MASK;
303
304         /* Trace memory is not initialized for this thread */
305         if (unlikely(trace == NULL)) {
306                 __rte_trace_mem_per_thread_alloc();
307                 trace = RTE_PER_LCORE(trace_mem);
308                 if (unlikely(trace == NULL))
309                         return NULL;
310         }
311         /* Check the wrap around case */
312         uint32_t offset = trace->offset;
313         if (unlikely((offset + sz) >= trace->len)) {
314                 /* Disable the trace event if it in DISCARD mode */
315                 if (unlikely(in & __RTE_TRACE_FIELD_ENABLE_DISCARD))
316                         return NULL;
317
318                 offset = 0;
319         }
320         /* Align to event header size */
321         offset = RTE_ALIGN_CEIL(offset, __RTE_TRACE_EVENT_HEADER_SZ);
322         void *mem = RTE_PTR_ADD(&trace->mem[0], offset);
323         offset += sz;
324         trace->offset = offset;
325
326         return mem;
327 }
328
329 static __rte_always_inline void *
330 __rte_trace_point_emit_ev_header(void *mem, uint64_t in)
331 {
332         uint64_t val;
333
334         /* Event header [63:0] = id [63:48] | timestamp [47:0] */
335         val = rte_get_tsc_cycles() &
336                 ~(0xffffULL << __RTE_TRACE_EVENT_HEADER_ID_SHIFT);
337         val |= ((in & __RTE_TRACE_FIELD_ID_MASK) <<
338                 (__RTE_TRACE_EVENT_HEADER_ID_SHIFT -
339                  __RTE_TRACE_FIELD_ID_SHIFT));
340
341         *(uint64_t *)mem = val;
342         return RTE_PTR_ADD(mem, __RTE_TRACE_EVENT_HEADER_SZ);
343 }
344
345 #define __rte_trace_point_emit_header_generic(t) \
346 void *mem; \
347 do { \
348         const uint64_t val = __atomic_load_n(t, __ATOMIC_ACQUIRE); \
349         if (likely(!(val & __RTE_TRACE_FIELD_ENABLE_MASK))) \
350                 return; \
351         mem = __rte_trace_mem_get(val); \
352         if (unlikely(mem == NULL)) \
353                 return; \
354         mem = __rte_trace_point_emit_ev_header(mem, val); \
355 } while (0)
356
357 #define __rte_trace_point_emit_header_fp(t) \
358         if (!__rte_trace_point_fp_is_enabled()) \
359                 return; \
360         __rte_trace_point_emit_header_generic(t)
361
362 #define __rte_trace_point_emit(in, type) \
363 do { \
364         memcpy(mem, &(in), sizeof(in)); \
365         mem = RTE_PTR_ADD(mem, sizeof(in)); \
366 } while (0)
367
368 #define rte_trace_point_emit_string(in) \
369 do { \
370         if (unlikely(in == NULL)) \
371                 return; \
372         rte_strscpy(mem, in, __RTE_TRACE_EMIT_STRING_LEN_MAX); \
373         mem = RTE_PTR_ADD(mem, __RTE_TRACE_EMIT_STRING_LEN_MAX); \
374 } while (0)
375
376 #else
377
378 #define __rte_trace_point_emit_header_generic(t) RTE_SET_USED(t)
379 #define __rte_trace_point_emit_header_fp(t) RTE_SET_USED(t)
380 #define __rte_trace_point_emit(in, type) RTE_SET_USED(in)
381 #define rte_trace_point_emit_string(in) RTE_SET_USED(in)
382
383 #endif /* ALLOW_EXPERIMENTAL_API */
384 #endif /* _RTE_TRACE_POINT_REGISTER_H_ */
385
386 #define rte_trace_point_emit_u64(in) __rte_trace_point_emit(in, uint64_t)
387 #define rte_trace_point_emit_i64(in) __rte_trace_point_emit(in, int64_t)
388 #define rte_trace_point_emit_u32(in) __rte_trace_point_emit(in, uint32_t)
389 #define rte_trace_point_emit_i32(in) __rte_trace_point_emit(in, int32_t)
390 #define rte_trace_point_emit_u16(in) __rte_trace_point_emit(in, uint16_t)
391 #define rte_trace_point_emit_i16(in) __rte_trace_point_emit(in, int16_t)
392 #define rte_trace_point_emit_u8(in) __rte_trace_point_emit(in, uint8_t)
393 #define rte_trace_point_emit_i8(in) __rte_trace_point_emit(in, int8_t)
394 #define rte_trace_point_emit_int(in) __rte_trace_point_emit(in, int32_t)
395 #define rte_trace_point_emit_long(in) __rte_trace_point_emit(in, long)
396 #define rte_trace_point_emit_size_t(in) __rte_trace_point_emit(in, size_t)
397 #define rte_trace_point_emit_float(in) __rte_trace_point_emit(in, float)
398 #define rte_trace_point_emit_double(in) __rte_trace_point_emit(in, double)
399 #define rte_trace_point_emit_ptr(in) __rte_trace_point_emit(in, uintptr_t)
400
401 #endif /* __DOXYGEN__ */
402
403 #ifdef __cplusplus
404 }
405 #endif
406
407 #endif /* _RTE_TRACE_POINT_H_ */