Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright (C) 2016 Intel Corporation.
3 : * All rights reserved.
4 : */
5 :
6 : /**
7 : * \file
8 : * Tracepoint library
9 : */
10 :
11 : #ifndef _SPDK_TRACE_H_
12 : #define _SPDK_TRACE_H_
13 :
14 : #include "spdk/stdinc.h"
15 : #include "spdk/assert.h"
16 :
17 : #ifdef __cplusplus
18 : extern "C" {
19 : #endif
20 :
21 : #define SPDK_TRACE_SHM_NAME_BASE "_trace."
22 : #define SPDK_DEFAULT_NUM_TRACE_ENTRIES (32 * 1024)
23 :
24 : struct spdk_trace_entry {
25 : uint64_t tsc;
26 : uint16_t tpoint_id;
27 : uint16_t owner_id;
28 : uint32_t size;
29 : uint64_t object_id;
30 : uint8_t args[8];
31 : };
32 :
33 : struct spdk_trace_entry_buffer {
34 : uint64_t tsc;
35 : uint16_t tpoint_id;
36 : uint8_t data[22];
37 : };
38 :
39 : SPDK_STATIC_ASSERT(sizeof(struct spdk_trace_entry_buffer) == sizeof(struct spdk_trace_entry),
40 : "Invalid size of trace entry buffer");
41 :
42 : /* If type changes from a uint8_t, change this value. */
43 : #define SPDK_TRACE_MAX_OWNER_TYPE (UCHAR_MAX + 1)
44 :
45 : struct spdk_trace_owner_type {
46 : uint8_t type;
47 : char id_prefix;
48 : };
49 :
50 : struct spdk_trace_owner {
51 : uint64_t tsc;
52 : uint8_t type;
53 : char description[];
54 : } __attribute__((packed));
55 :
56 : /* If type changes from a uint8_t, change this value. */
57 : #define SPDK_TRACE_MAX_OBJECT (UCHAR_MAX + 1)
58 :
59 : struct spdk_trace_object {
60 : uint8_t type;
61 : char id_prefix;
62 : };
63 :
64 : #define SPDK_TRACE_THREAD_NAME_LEN 16
65 : #define SPDK_TRACE_MAX_GROUP_ID 20
66 : #define SPDK_TRACE_MAX_TPOINT_ID (SPDK_TRACE_MAX_GROUP_ID * 64)
67 : #define SPDK_TPOINT_ID(group, tpoint) ((group * 64) + tpoint)
68 :
69 : #define SPDK_TRACE_ARG_TYPE_INT 0
70 : #define SPDK_TRACE_ARG_TYPE_PTR 1
71 : #define SPDK_TRACE_ARG_TYPE_STR 2
72 :
73 : #define SPDK_TRACE_MAX_ARGS_COUNT 8
74 : #define SPDK_TRACE_MAX_RELATIONS 16
75 :
76 : struct spdk_trace_argument {
77 : char name[14];
78 : uint8_t type;
79 : uint8_t size;
80 : };
81 :
82 : struct spdk_trace_tpoint {
83 : char name[24];
84 : uint16_t tpoint_id;
85 : uint8_t owner_type;
86 : uint8_t object_type;
87 : uint8_t new_object;
88 : uint8_t num_args;
89 : struct spdk_trace_argument args[SPDK_TRACE_MAX_ARGS_COUNT];
90 : /** Relations between tracepoint and trace object */
91 : struct {
92 : uint8_t object_type;
93 : uint8_t arg_index;
94 : } related_objects[SPDK_TRACE_MAX_RELATIONS];
95 : };
96 :
97 : struct spdk_trace_history {
98 : /** Logical core number associated with this structure instance. */
99 : int lcore;
100 :
101 : /** Number of trace_entries contained in each trace_history. */
102 : uint64_t num_entries;
103 :
104 : /**
105 : * Running count of number of occurrences of each tracepoint on this
106 : * lcore. Debug tools can use this to easily count tracepoints such as
107 : * number of SCSI tasks completed or PDUs read.
108 : */
109 : uint64_t tpoint_count[SPDK_TRACE_MAX_TPOINT_ID];
110 :
111 : /** Index to next spdk_trace_entry to fill. */
112 : uint64_t next_entry;
113 :
114 : /**
115 : * Circular buffer of spdk_trace_entry structures for tracing
116 : * tpoints on this core. Debug tool spdk_trace reads this
117 : * buffer from shared memory to post-process the tpoint entries and
118 : * display in a human-readable format.
119 : */
120 : struct spdk_trace_entry entries[0];
121 : };
122 :
123 : #define SPDK_TRACE_MAX_LCORE 1024
124 :
125 : struct spdk_trace_file {
126 : uint64_t file_size;
127 : uint64_t tsc_rate;
128 : uint64_t tpoint_mask[SPDK_TRACE_MAX_GROUP_ID];
129 : char tname[SPDK_TRACE_MAX_LCORE][SPDK_TRACE_THREAD_NAME_LEN];
130 : struct spdk_trace_owner_type owner_type[SPDK_TRACE_MAX_OWNER_TYPE];
131 : struct spdk_trace_object object[UCHAR_MAX + 1];
132 : struct spdk_trace_tpoint tpoint[SPDK_TRACE_MAX_TPOINT_ID];
133 :
134 : uint16_t num_owners;
135 : uint16_t owner_description_size;
136 : uint8_t reserved[4];
137 :
138 : /** Offset of each trace_history from the beginning of this data structure. */
139 : uint64_t lcore_history_offsets[SPDK_TRACE_MAX_LCORE];
140 :
141 : /** Offset of beginning of struct spdk_trace_owner data. */
142 : uint64_t owner_offset;
143 :
144 : /** Variable sized data sections are at the end of this data structure,
145 : * referenced by offsets defined in this structure.
146 : */
147 : uint8_t data[0];
148 : };
149 : extern struct spdk_trace_file *g_trace_file;
150 :
151 : static inline uint64_t
152 0 : spdk_get_trace_history_size(uint64_t num_entries)
153 : {
154 0 : return sizeof(struct spdk_trace_history) + num_entries * sizeof(struct spdk_trace_entry);
155 : }
156 :
157 : static inline uint64_t
158 0 : spdk_get_trace_file_size(struct spdk_trace_file *trace_file)
159 : {
160 0 : return trace_file->file_size;
161 : }
162 :
163 : static inline struct spdk_trace_history *
164 0 : spdk_get_per_lcore_history(struct spdk_trace_file *trace_file, unsigned lcore)
165 : {
166 0 : uint64_t lcore_history_offset;
167 :
168 0 : if (lcore >= SPDK_TRACE_MAX_LCORE) {
169 0 : return NULL;
170 : }
171 :
172 0 : lcore_history_offset = trace_file->lcore_history_offsets[lcore];
173 0 : if (lcore_history_offset == 0) {
174 0 : return NULL;
175 : }
176 :
177 0 : return (struct spdk_trace_history *)(((char *)trace_file) + lcore_history_offset);
178 0 : }
179 :
180 : static inline struct spdk_trace_owner *
181 0 : spdk_get_trace_owner(const struct spdk_trace_file *trace_file, uint16_t owner_id)
182 : {
183 0 : uint64_t owner_size;
184 :
185 0 : if (owner_id >= trace_file->num_owners) {
186 0 : return NULL;
187 : }
188 :
189 0 : owner_size = sizeof(struct spdk_trace_owner) + trace_file->owner_description_size;
190 0 : return (struct spdk_trace_owner *)
191 0 : (((char *)trace_file) + trace_file->owner_offset + owner_id * owner_size);
192 0 : }
193 :
194 : void _spdk_trace_record(uint64_t tsc, uint16_t tpoint_id, uint16_t owner_id,
195 : uint32_t size, uint64_t object_id, int num_args, ...);
196 :
197 : #define spdk_trace_tpoint_enabled(tpoint_id) \
198 : spdk_unlikely((g_trace_file != NULL && \
199 : ((1ULL << (tpoint_id & 0x3F)) & g_trace_file->tpoint_mask[tpoint_id >> 6])))
200 :
201 : #define _spdk_trace_record_tsc(tsc, tpoint_id, owner_id, size, object_id, num_args, ...) \
202 : do { \
203 : assert(tpoint_id < SPDK_TRACE_MAX_TPOINT_ID); \
204 : if (!spdk_trace_tpoint_enabled(tpoint_id)) { \
205 : break; \
206 : } \
207 : _spdk_trace_record(tsc, tpoint_id, owner_id, size, object_id, \
208 : num_args, ## __VA_ARGS__); \
209 : } while (0)
210 :
211 : /* Return the number of variable arguments. */
212 : #define spdk_trace_num_args(...) _spdk_trace_num_args(, ## __VA_ARGS__)
213 : #define _spdk_trace_num_args(...) __spdk_trace_num_args(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0)
214 : #define __spdk_trace_num_args(v, a1, a2, a3, a4, a5, a6, a7, a8, count, ...) count
215 :
216 : /**
217 : * Record the current trace state for tracing tpoints. Debug tool can read the
218 : * information from shared memory to post-process the tpoint entries and display
219 : * in a human-readable format.
220 : *
221 : * \param tsc Current tsc.
222 : * \param tpoint_id Tracepoint id to record.
223 : * \param owner_id Owner id to record.
224 : * \param size Size to record.
225 : * \param object_id Object id to record.
226 : * \param ... Extra tracepoint arguments. The number, types, and order of the arguments
227 : * must match the definition of the tracepoint.
228 : */
229 : #define spdk_trace_record_tsc(tsc, tpoint_id, owner_id, size, object_id, ...) \
230 : _spdk_trace_record_tsc(tsc, tpoint_id, owner_id, size, object_id, \
231 : spdk_trace_num_args(__VA_ARGS__), ## __VA_ARGS__)
232 :
233 : /**
234 : * Record the current trace state for tracing tpoints. Debug tool can read the
235 : * information from shared memory to post-process the tpoint entries and display
236 : * in a human-readable format. This macro will call spdk_get_ticks() to get
237 : * the current tsc to save in the tracepoint.
238 : *
239 : * \param tpoint_id Tracepoint id to record.
240 : * \param owner_id Owner id to record.
241 : * \param size Size to record.
242 : * \param object_id Object id to record.
243 : * \param ... Extra tracepoint arguments. The number, types, and order of the arguments
244 : * must match the definition of the tracepoint.
245 : */
246 : #define spdk_trace_record(tpoint_id, owner_id, size, object_id, ...) \
247 : spdk_trace_record_tsc(0, tpoint_id, owner_id, size, object_id, ## __VA_ARGS__)
248 :
249 : /**
250 : * Get the current tpoint mask of the given tpoint group.
251 : *
252 : * \param group_id Tpoint group id associated with the tpoint mask.
253 : *
254 : * \return current tpoint mask.
255 : */
256 : uint64_t spdk_trace_get_tpoint_mask(uint32_t group_id);
257 :
258 : /**
259 : * Add the specified tpoints to the current tpoint mask for the given tpoint group.
260 : *
261 : * \param group_id Tpoint group id associated with the tpoint mask.
262 : * \param tpoint_mask Tpoint mask which indicates which tpoints to add to the
263 : * current tpoint mask.
264 : */
265 : void spdk_trace_set_tpoints(uint32_t group_id, uint64_t tpoint_mask);
266 :
267 : /**
268 : * Clear the specified tpoints from the current tpoint mask for the given tpoint group.
269 : *
270 : * \param group_id Tpoint group id associated with the tpoint mask.
271 : * \param tpoint_mask Tpoint mask which indicates which tpoints to clear from
272 : * the current tpoint mask.
273 : */
274 : void spdk_trace_clear_tpoints(uint32_t group_id, uint64_t tpoint_mask);
275 :
276 : /**
277 : * Get a mask of all tracepoint groups which have at least one tracepoint enabled.
278 : *
279 : * \return a mask of all tracepoint groups.
280 : */
281 : uint64_t spdk_trace_get_tpoint_group_mask(void);
282 :
283 : /**
284 : * For each tpoint group specified in the group mask, enable all of its tpoints.
285 : *
286 : * \param tpoint_group_mask Tpoint group mask that indicates which tpoints to enable.
287 : */
288 : void spdk_trace_set_tpoint_group_mask(uint64_t tpoint_group_mask);
289 :
290 : /**
291 : * For each tpoint group specified in the group mask, disable all of its tpoints.
292 : *
293 : * \param tpoint_group_mask Tpoint group mask that indicates which tpoints to disable.
294 : */
295 : void spdk_trace_clear_tpoint_group_mask(uint64_t tpoint_group_mask);
296 :
297 : /**
298 : * Initialize the trace environment. Debug tool can read the information from
299 : * the given shared memory to post-process the tpoint entries and display in a
300 : * human-readable format.
301 : *
302 : * \param shm_name Name of shared memory.
303 : * \param num_entries Number of trace entries per lcore.
304 : * \param num_threads Number of user created threads.
305 : * \return 0 on success, else non-zero indicates a failure.
306 : */
307 : int spdk_trace_init(const char *shm_name, uint64_t num_entries, uint32_t num_threads);
308 :
309 : /**
310 : * Initialize trace environment for an user created thread.
311 : *
312 : * \return 0 on success, else non-zero indicates a failure.
313 : */
314 : int spdk_trace_register_user_thread(void);
315 :
316 : /**
317 : * De-initialize trace environment for an user created thread.
318 : *
319 : * \return 0 on success, else non-zero indicates a failure.
320 : */
321 : int spdk_trace_unregister_user_thread(void);
322 :
323 : /**
324 : * Unmap global trace memory structs.
325 : */
326 : void spdk_trace_cleanup(void);
327 :
328 : #define OWNER_TYPE_NONE 0
329 : #define OBJECT_NONE 0
330 :
331 : /**
332 : * Register the trace owner type.
333 : *
334 : * \param type Type of the trace owner.
335 : * \param id_prefix Prefix of id for the trace owner.
336 : */
337 : void spdk_trace_register_owner_type(uint8_t type, char id_prefix);
338 :
339 : /**
340 : * Register the trace owner.
341 : *
342 : * \param owner_type Type of the owner being registered.
343 : * \param description Textual string describing the trace owner.
344 : * \return Allocated owner_id for the newly registered owner. Returns 0 if
345 : * no trace_id could be allocated.
346 : */
347 : uint16_t spdk_trace_register_owner(uint8_t owner_type, const char *description);
348 :
349 : /**
350 : * Change the description for a previously registered owner.
351 : *
352 : * \param owner_id ID of previously registered owner.
353 : * \param description New description for the owner.
354 : */
355 : void spdk_trace_owner_set_description(uint16_t owner_id, const char *description);
356 :
357 : /**
358 : * Append to the description for a previously registered owner.
359 : *
360 : * A space will be inserted before the appended string.
361 : *
362 : * This may be useful for modules that are modifying an existing description
363 : * with additional information.
364 : *
365 : * Callers may pass 0 safely, in this case the function will just be a nop.
366 : *
367 : * \param owner_id ID of previously registered owner.
368 : * \param description Additional description for the owner
369 : */
370 : void spdk_trace_owner_append_description(uint16_t owner_id, const char *description);
371 :
372 : /**
373 : * Unregister a previously registered owner.
374 : *
375 : * Callers may pass 0 safely, in this case the function will just be a nop.
376 : *
377 : * \param owner_id ID of previously registered owner.
378 : */
379 : void spdk_trace_unregister_owner(uint16_t owner_id);
380 :
381 : /**
382 : * Register the trace object.
383 : *
384 : * \param type Type of the trace object.
385 : * \param id_prefix Prefix of id for the trace object.
386 : */
387 : void spdk_trace_register_object(uint8_t type, char id_prefix);
388 :
389 : /**
390 : * Register the description for a tpoint with a single argument.
391 : *
392 : * \param name Name for the tpoint.
393 : * \param tpoint_id Id for the tpoint.
394 : * \param owner_type Owner type for the tpoint.
395 : * \param object_type Object type for the tpoint.
396 : * \param new_object New object for the tpoint.
397 : * \param arg1_type Type of arg1.
398 : * \param arg1_name Name of argument.
399 : */
400 : void spdk_trace_register_description(const char *name, uint16_t tpoint_id, uint8_t owner_type,
401 : uint8_t object_type, uint8_t new_object,
402 : uint8_t arg1_type, const char *arg1_name);
403 :
404 : struct spdk_trace_tpoint_opts {
405 : const char *name;
406 : uint16_t tpoint_id;
407 : uint8_t owner_type;
408 : uint8_t object_type;
409 : uint8_t new_object;
410 : struct {
411 : const char *name;
412 : uint8_t type;
413 : uint8_t size;
414 : } args[SPDK_TRACE_MAX_ARGS_COUNT];
415 : };
416 :
417 : /**
418 : * Register the description for a number of tpoints. This function allows the user to register
419 : * tracepoints with multiple arguments.
420 : *
421 : * \param opts Array of structures describing tpoints and their arguments.
422 : * \param num_opts Number of tpoints to register (size of the opts array).
423 : */
424 : void spdk_trace_register_description_ext(const struct spdk_trace_tpoint_opts *opts,
425 : size_t num_opts);
426 :
427 : struct spdk_trace_register_fn *spdk_trace_get_first_register_fn(void);
428 :
429 : struct spdk_trace_register_fn *spdk_trace_get_next_register_fn(struct spdk_trace_register_fn
430 : *register_fn);
431 :
432 : /**
433 : * Bind trace type to a given trace object. This allows for matching traces
434 : * with the same parent trace object.
435 : *
436 : * \param tpoint_id Type of trace to be bound
437 : * \param object_type Tracepoint object type to bind to
438 : * \param arg_index Index of argument containing context information
439 : */
440 : void spdk_trace_tpoint_register_relation(uint16_t tpoint_id, uint8_t object_type,
441 : uint8_t arg_index);
442 :
443 : /**
444 : * Enable trace on specific tpoint group
445 : *
446 : * \param group_name Name of group to enable, "all" for enabling all groups.
447 : * \return 0 on success, else non-zero indicates a failure.
448 : */
449 : int spdk_trace_enable_tpoint_group(const char *group_name);
450 :
451 : /**
452 : * Disable trace on specific tpoint group
453 : *
454 : * \param group_name Name of group to disable, "all" for disabling all groups.
455 : * \return 0 on success, else non-zero indicates a failure.
456 : */
457 : int spdk_trace_disable_tpoint_group(const char *group_name);
458 :
459 : /**
460 : * Show trace mask and its usage.
461 : *
462 : * \param f File to hold the mask's information.
463 : * \param tmask_arg Command line option to set the trace group mask.
464 : */
465 : void spdk_trace_mask_usage(FILE *f, const char *tmask_arg);
466 :
467 : /**
468 : * Create a tracepoint group mask from tracepoint group name
469 : *
470 : * \param group_name tracepoint group name string
471 : * \return tpoint group mask on success, 0 on failure
472 : */
473 : uint64_t spdk_trace_create_tpoint_group_mask(const char *group_name);
474 :
475 : struct spdk_trace_register_fn {
476 : const char *name;
477 : uint8_t tgroup_id;
478 : void (*reg_fn)(void);
479 : struct spdk_trace_register_fn *next;
480 : };
481 :
482 : /**
483 : * Add new trace register function.
484 : *
485 : * \param reg_fn Trace register function to add.
486 : */
487 : void spdk_trace_add_register_fn(struct spdk_trace_register_fn *reg_fn);
488 :
489 : #define SPDK_TRACE_REGISTER_FN(fn, name_str, _tgroup_id) \
490 : static void fn(void); \
491 : struct spdk_trace_register_fn reg_ ## fn = { \
492 : .name = name_str, \
493 : .tgroup_id = _tgroup_id, \
494 : .reg_fn = fn, \
495 : .next = NULL, \
496 : }; \
497 : __attribute__((constructor)) static void _ ## fn(void) \
498 : { \
499 : spdk_trace_add_register_fn(®_ ## fn); \
500 : }
501 :
502 : #ifdef __cplusplus
503 : }
504 : #endif
505 :
506 : #endif
|