Warning: This file is not a C or C++ file. It does not have highlighting.
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
---|---|
2 | #undef TRACE_SYSTEM |
3 | #define TRACE_SYSTEM timer |
4 | |
5 | #if !defined(_TRACE_TIMER_H) || defined(TRACE_HEADER_MULTI_READ) |
6 | #define _TRACE_TIMER_H |
7 | |
8 | #include <linux/tracepoint.h> |
9 | #include <linux/hrtimer.h> |
10 | #include <linux/timer.h> |
11 | |
12 | DECLARE_EVENT_CLASS(timer_class, |
13 | |
14 | TP_PROTO(struct timer_list *timer), |
15 | |
16 | TP_ARGS(timer), |
17 | |
18 | TP_STRUCT__entry( |
19 | __field( void *, timer ) |
20 | ), |
21 | |
22 | TP_fast_assign( |
23 | __entry->timer = timer; |
24 | ), |
25 | |
26 | TP_printk("timer=%p", __entry->timer) |
27 | ); |
28 | |
29 | /** |
30 | * timer_init - called when the timer is initialized |
31 | * @timer: pointer to struct timer_list |
32 | */ |
33 | DEFINE_EVENT(timer_class, timer_init, |
34 | |
35 | TP_PROTO(struct timer_list *timer), |
36 | |
37 | TP_ARGS(timer) |
38 | ); |
39 | |
40 | #define decode_timer_flags(flags) \ |
41 | __print_flags(flags, "|", \ |
42 | { TIMER_MIGRATING, "M" }, \ |
43 | { TIMER_DEFERRABLE, "D" }, \ |
44 | { TIMER_PINNED, "P" }, \ |
45 | { TIMER_IRQSAFE, "I" }) |
46 | |
47 | /** |
48 | * timer_start - called when the timer is started |
49 | * @timer: pointer to struct timer_list |
50 | * @bucket_expiry: the bucket expiry time |
51 | */ |
52 | TRACE_EVENT(timer_start, |
53 | |
54 | TP_PROTO(struct timer_list *timer, |
55 | unsigned long bucket_expiry), |
56 | |
57 | TP_ARGS(timer, bucket_expiry), |
58 | |
59 | TP_STRUCT__entry( |
60 | __field( void *, timer ) |
61 | __field( void *, function ) |
62 | __field( unsigned long, expires ) |
63 | __field( unsigned long, bucket_expiry ) |
64 | __field( unsigned long, now ) |
65 | __field( unsigned int, flags ) |
66 | ), |
67 | |
68 | TP_fast_assign( |
69 | __entry->timer = timer; |
70 | __entry->function = timer->function; |
71 | __entry->expires = timer->expires; |
72 | __entry->bucket_expiry = bucket_expiry; |
73 | __entry->now = jiffies; |
74 | __entry->flags = timer->flags; |
75 | ), |
76 | |
77 | TP_printk("timer=%p function=%ps expires=%lu [timeout=%ld] bucket_expiry=%lu cpu=%u idx=%u flags=%s", |
78 | __entry->timer, __entry->function, __entry->expires, |
79 | (long)__entry->expires - __entry->now, |
80 | __entry->bucket_expiry, __entry->flags & TIMER_CPUMASK, |
81 | __entry->flags >> TIMER_ARRAYSHIFT, |
82 | decode_timer_flags(__entry->flags & TIMER_TRACE_FLAGMASK)) |
83 | ); |
84 | |
85 | /** |
86 | * timer_expire_entry - called immediately before the timer callback |
87 | * @timer: pointer to struct timer_list |
88 | * @baseclk: value of timer_base::clk when timer expires |
89 | * |
90 | * Allows to determine the timer latency. |
91 | */ |
92 | TRACE_EVENT(timer_expire_entry, |
93 | |
94 | TP_PROTO(struct timer_list *timer, unsigned long baseclk), |
95 | |
96 | TP_ARGS(timer, baseclk), |
97 | |
98 | TP_STRUCT__entry( |
99 | __field( void *, timer ) |
100 | __field( unsigned long, now ) |
101 | __field( void *, function) |
102 | __field( unsigned long, baseclk ) |
103 | ), |
104 | |
105 | TP_fast_assign( |
106 | __entry->timer = timer; |
107 | __entry->now = jiffies; |
108 | __entry->function = timer->function; |
109 | __entry->baseclk = baseclk; |
110 | ), |
111 | |
112 | TP_printk("timer=%p function=%ps now=%lu baseclk=%lu", |
113 | __entry->timer, __entry->function, __entry->now, |
114 | __entry->baseclk) |
115 | ); |
116 | |
117 | /** |
118 | * timer_expire_exit - called immediately after the timer callback returns |
119 | * @timer: pointer to struct timer_list |
120 | * |
121 | * When used in combination with the timer_expire_entry tracepoint we can |
122 | * determine the runtime of the timer callback function. |
123 | * |
124 | * NOTE: Do NOT dereference timer in TP_fast_assign. The pointer might |
125 | * be invalid. We solely track the pointer. |
126 | */ |
127 | DEFINE_EVENT(timer_class, timer_expire_exit, |
128 | |
129 | TP_PROTO(struct timer_list *timer), |
130 | |
131 | TP_ARGS(timer) |
132 | ); |
133 | |
134 | /** |
135 | * timer_cancel - called when the timer is canceled |
136 | * @timer: pointer to struct timer_list |
137 | */ |
138 | DEFINE_EVENT(timer_class, timer_cancel, |
139 | |
140 | TP_PROTO(struct timer_list *timer), |
141 | |
142 | TP_ARGS(timer) |
143 | ); |
144 | |
145 | TRACE_EVENT(timer_base_idle, |
146 | |
147 | TP_PROTO(bool is_idle, unsigned int cpu), |
148 | |
149 | TP_ARGS(is_idle, cpu), |
150 | |
151 | TP_STRUCT__entry( |
152 | __field( bool, is_idle ) |
153 | __field( unsigned int, cpu ) |
154 | ), |
155 | |
156 | TP_fast_assign( |
157 | __entry->is_idle = is_idle; |
158 | __entry->cpu = cpu; |
159 | ), |
160 | |
161 | TP_printk("is_idle=%d cpu=%d", |
162 | __entry->is_idle, __entry->cpu) |
163 | ); |
164 | |
165 | #define decode_clockid(type) \ |
166 | __print_symbolic(type, \ |
167 | { CLOCK_REALTIME, "CLOCK_REALTIME" }, \ |
168 | { CLOCK_MONOTONIC, "CLOCK_MONOTONIC" }, \ |
169 | { CLOCK_BOOTTIME, "CLOCK_BOOTTIME" }, \ |
170 | { CLOCK_TAI, "CLOCK_TAI" }) |
171 | |
172 | #define decode_hrtimer_mode(mode) \ |
173 | __print_symbolic(mode, \ |
174 | { HRTIMER_MODE_ABS, "ABS" }, \ |
175 | { HRTIMER_MODE_REL, "REL" }, \ |
176 | { HRTIMER_MODE_ABS_PINNED, "ABS|PINNED" }, \ |
177 | { HRTIMER_MODE_REL_PINNED, "REL|PINNED" }, \ |
178 | { HRTIMER_MODE_ABS_SOFT, "ABS|SOFT" }, \ |
179 | { HRTIMER_MODE_REL_SOFT, "REL|SOFT" }, \ |
180 | { HRTIMER_MODE_ABS_PINNED_SOFT, "ABS|PINNED|SOFT" }, \ |
181 | { HRTIMER_MODE_REL_PINNED_SOFT, "REL|PINNED|SOFT" }, \ |
182 | { HRTIMER_MODE_ABS_HARD, "ABS|HARD" }, \ |
183 | { HRTIMER_MODE_REL_HARD, "REL|HARD" }, \ |
184 | { HRTIMER_MODE_ABS_PINNED_HARD, "ABS|PINNED|HARD" }, \ |
185 | { HRTIMER_MODE_REL_PINNED_HARD, "REL|PINNED|HARD" }) |
186 | |
187 | /** |
188 | * hrtimer_init - called when the hrtimer is initialized |
189 | * @hrtimer: pointer to struct hrtimer |
190 | * @clockid: the hrtimers clock |
191 | * @mode: the hrtimers mode |
192 | */ |
193 | TRACE_EVENT(hrtimer_init, |
194 | |
195 | TP_PROTO(struct hrtimer *hrtimer, clockid_t clockid, |
196 | enum hrtimer_mode mode), |
197 | |
198 | TP_ARGS(hrtimer, clockid, mode), |
199 | |
200 | TP_STRUCT__entry( |
201 | __field( void *, hrtimer ) |
202 | __field( clockid_t, clockid ) |
203 | __field( enum hrtimer_mode, mode ) |
204 | ), |
205 | |
206 | TP_fast_assign( |
207 | __entry->hrtimer = hrtimer; |
208 | __entry->clockid = clockid; |
209 | __entry->mode = mode; |
210 | ), |
211 | |
212 | TP_printk("hrtimer=%p clockid=%s mode=%s", __entry->hrtimer, |
213 | decode_clockid(__entry->clockid), |
214 | decode_hrtimer_mode(__entry->mode)) |
215 | ); |
216 | |
217 | /** |
218 | * hrtimer_start - called when the hrtimer is started |
219 | * @hrtimer: pointer to struct hrtimer |
220 | * @mode: the hrtimers mode |
221 | */ |
222 | TRACE_EVENT(hrtimer_start, |
223 | |
224 | TP_PROTO(struct hrtimer *hrtimer, enum hrtimer_mode mode), |
225 | |
226 | TP_ARGS(hrtimer, mode), |
227 | |
228 | TP_STRUCT__entry( |
229 | __field( void *, hrtimer ) |
230 | __field( void *, function ) |
231 | __field( s64, expires ) |
232 | __field( s64, softexpires ) |
233 | __field( enum hrtimer_mode, mode ) |
234 | ), |
235 | |
236 | TP_fast_assign( |
237 | __entry->hrtimer = hrtimer; |
238 | __entry->function = hrtimer->function; |
239 | __entry->expires = hrtimer_get_expires(hrtimer); |
240 | __entry->softexpires = hrtimer_get_softexpires(hrtimer); |
241 | __entry->mode = mode; |
242 | ), |
243 | |
244 | TP_printk("hrtimer=%p function=%ps expires=%llu softexpires=%llu " |
245 | "mode=%s", __entry->hrtimer, __entry->function, |
246 | (unsigned long long) __entry->expires, |
247 | (unsigned long long) __entry->softexpires, |
248 | decode_hrtimer_mode(__entry->mode)) |
249 | ); |
250 | |
251 | /** |
252 | * hrtimer_expire_entry - called immediately before the hrtimer callback |
253 | * @hrtimer: pointer to struct hrtimer |
254 | * @now: pointer to variable which contains current time of the |
255 | * timers base. |
256 | * |
257 | * Allows to determine the timer latency. |
258 | */ |
259 | TRACE_EVENT(hrtimer_expire_entry, |
260 | |
261 | TP_PROTO(struct hrtimer *hrtimer, ktime_t *now), |
262 | |
263 | TP_ARGS(hrtimer, now), |
264 | |
265 | TP_STRUCT__entry( |
266 | __field( void *, hrtimer ) |
267 | __field( s64, now ) |
268 | __field( void *, function) |
269 | ), |
270 | |
271 | TP_fast_assign( |
272 | __entry->hrtimer = hrtimer; |
273 | __entry->now = *now; |
274 | __entry->function = hrtimer->function; |
275 | ), |
276 | |
277 | TP_printk("hrtimer=%p function=%ps now=%llu", |
278 | __entry->hrtimer, __entry->function, |
279 | (unsigned long long) __entry->now) |
280 | ); |
281 | |
282 | DECLARE_EVENT_CLASS(hrtimer_class, |
283 | |
284 | TP_PROTO(struct hrtimer *hrtimer), |
285 | |
286 | TP_ARGS(hrtimer), |
287 | |
288 | TP_STRUCT__entry( |
289 | __field( void *, hrtimer ) |
290 | ), |
291 | |
292 | TP_fast_assign( |
293 | __entry->hrtimer = hrtimer; |
294 | ), |
295 | |
296 | TP_printk("hrtimer=%p", __entry->hrtimer) |
297 | ); |
298 | |
299 | /** |
300 | * hrtimer_expire_exit - called immediately after the hrtimer callback returns |
301 | * @hrtimer: pointer to struct hrtimer |
302 | * |
303 | * When used in combination with the hrtimer_expire_entry tracepoint we can |
304 | * determine the runtime of the callback function. |
305 | */ |
306 | DEFINE_EVENT(hrtimer_class, hrtimer_expire_exit, |
307 | |
308 | TP_PROTO(struct hrtimer *hrtimer), |
309 | |
310 | TP_ARGS(hrtimer) |
311 | ); |
312 | |
313 | /** |
314 | * hrtimer_cancel - called when the hrtimer is canceled |
315 | * @hrtimer: pointer to struct hrtimer |
316 | */ |
317 | DEFINE_EVENT(hrtimer_class, hrtimer_cancel, |
318 | |
319 | TP_PROTO(struct hrtimer *hrtimer), |
320 | |
321 | TP_ARGS(hrtimer) |
322 | ); |
323 | |
324 | /** |
325 | * itimer_state - called when itimer is started or canceled |
326 | * @which: name of the interval timer |
327 | * @value: the itimers value, itimer is canceled if value->it_value is |
328 | * zero, otherwise it is started |
329 | * @expires: the itimers expiry time |
330 | */ |
331 | TRACE_EVENT(itimer_state, |
332 | |
333 | TP_PROTO(int which, const struct itimerspec64 *const value, |
334 | unsigned long long expires), |
335 | |
336 | TP_ARGS(which, value, expires), |
337 | |
338 | TP_STRUCT__entry( |
339 | __field( int, which ) |
340 | __field( unsigned long long, expires ) |
341 | __field( long, value_sec ) |
342 | __field( long, value_nsec ) |
343 | __field( long, interval_sec ) |
344 | __field( long, interval_nsec ) |
345 | ), |
346 | |
347 | TP_fast_assign( |
348 | __entry->which = which; |
349 | __entry->expires = expires; |
350 | __entry->value_sec = value->it_value.tv_sec; |
351 | __entry->value_nsec = value->it_value.tv_nsec; |
352 | __entry->interval_sec = value->it_interval.tv_sec; |
353 | __entry->interval_nsec = value->it_interval.tv_nsec; |
354 | ), |
355 | |
356 | TP_printk("which=%d expires=%llu it_value=%ld.%06ld it_interval=%ld.%06ld", |
357 | __entry->which, __entry->expires, |
358 | __entry->value_sec, __entry->value_nsec / NSEC_PER_USEC, |
359 | __entry->interval_sec, __entry->interval_nsec / NSEC_PER_USEC) |
360 | ); |
361 | |
362 | /** |
363 | * itimer_expire - called when itimer expires |
364 | * @which: type of the interval timer |
365 | * @pid: pid of the process which owns the timer |
366 | * @now: current time, used to calculate the latency of itimer |
367 | */ |
368 | TRACE_EVENT(itimer_expire, |
369 | |
370 | TP_PROTO(int which, struct pid *pid, unsigned long long now), |
371 | |
372 | TP_ARGS(which, pid, now), |
373 | |
374 | TP_STRUCT__entry( |
375 | __field( int , which ) |
376 | __field( pid_t, pid ) |
377 | __field( unsigned long long, now ) |
378 | ), |
379 | |
380 | TP_fast_assign( |
381 | __entry->which = which; |
382 | __entry->now = now; |
383 | __entry->pid = pid_nr(pid); |
384 | ), |
385 | |
386 | TP_printk("which=%d pid=%d now=%llu", __entry->which, |
387 | (int) __entry->pid, __entry->now) |
388 | ); |
389 | |
390 | #ifdef CONFIG_NO_HZ_COMMON |
391 | |
392 | #define TICK_DEP_NAMES \ |
393 | tick_dep_mask_name(NONE) \ |
394 | tick_dep_name(POSIX_TIMER) \ |
395 | tick_dep_name(PERF_EVENTS) \ |
396 | tick_dep_name(SCHED) \ |
397 | tick_dep_name(CLOCK_UNSTABLE) \ |
398 | tick_dep_name(RCU) \ |
399 | tick_dep_name_end(RCU_EXP) |
400 | |
401 | #undef tick_dep_name |
402 | #undef tick_dep_mask_name |
403 | #undef tick_dep_name_end |
404 | |
405 | /* The MASK will convert to their bits and they need to be processed too */ |
406 | #define tick_dep_name(sdep) TRACE_DEFINE_ENUM(TICK_DEP_BIT_##sdep); \ |
407 | TRACE_DEFINE_ENUM(TICK_DEP_MASK_##sdep); |
408 | #define tick_dep_name_end(sdep) TRACE_DEFINE_ENUM(TICK_DEP_BIT_##sdep); \ |
409 | TRACE_DEFINE_ENUM(TICK_DEP_MASK_##sdep); |
410 | /* NONE only has a mask defined for it */ |
411 | #define tick_dep_mask_name(sdep) TRACE_DEFINE_ENUM(TICK_DEP_MASK_##sdep); |
412 | |
413 | TICK_DEP_NAMES |
414 | |
415 | #undef tick_dep_name |
416 | #undef tick_dep_mask_name |
417 | #undef tick_dep_name_end |
418 | |
419 | #define tick_dep_name(sdep) { TICK_DEP_MASK_##sdep, #sdep }, |
420 | #define tick_dep_mask_name(sdep) { TICK_DEP_MASK_##sdep, #sdep }, |
421 | #define tick_dep_name_end(sdep) { TICK_DEP_MASK_##sdep, #sdep } |
422 | |
423 | #define show_tick_dep_name(val) \ |
424 | __print_symbolic(val, TICK_DEP_NAMES) |
425 | |
426 | TRACE_EVENT(tick_stop, |
427 | |
428 | TP_PROTO(int success, int dependency), |
429 | |
430 | TP_ARGS(success, dependency), |
431 | |
432 | TP_STRUCT__entry( |
433 | __field( int , success ) |
434 | __field( int , dependency ) |
435 | ), |
436 | |
437 | TP_fast_assign( |
438 | __entry->success = success; |
439 | __entry->dependency = dependency; |
440 | ), |
441 | |
442 | TP_printk("success=%d dependency=%s", __entry->success, \ |
443 | show_tick_dep_name(__entry->dependency)) |
444 | ); |
445 | #endif |
446 | |
447 | #endif /* _TRACE_TIMER_H */ |
448 | |
449 | /* This part must be outside protection */ |
450 | #include <trace/define_trace.h> |
451 |
Warning: This file is not a C or C++ file. It does not have highlighting.