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