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 | * @expires: the timers expiry time |
51 | * @flags: the timers flags |
52 | */ |
53 | TRACE_EVENT(timer_start, |
54 | |
55 | TP_PROTO(struct timer_list *timer, |
56 | unsigned long expires, |
57 | unsigned int flags), |
58 | |
59 | TP_ARGS(timer, expires, flags), |
60 | |
61 | TP_STRUCT__entry( |
62 | __field( void *, timer ) |
63 | __field( void *, function ) |
64 | __field( unsigned long, expires ) |
65 | __field( unsigned long, now ) |
66 | __field( unsigned int, flags ) |
67 | ), |
68 | |
69 | TP_fast_assign( |
70 | __entry->timer = timer; |
71 | __entry->function = timer->function; |
72 | __entry->expires = expires; |
73 | __entry->now = jiffies; |
74 | __entry->flags = flags; |
75 | ), |
76 | |
77 | TP_printk("timer=%p function=%ps expires=%lu [timeout=%ld] cpu=%u idx=%u flags=%s" , |
78 | __entry->timer, __entry->function, __entry->expires, |
79 | (long)__entry->expires - __entry->now, |
80 | __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 | #define decode_clockid(type) \ |
146 | __print_symbolic(type, \ |
147 | { CLOCK_REALTIME, "CLOCK_REALTIME" }, \ |
148 | { CLOCK_MONOTONIC, "CLOCK_MONOTONIC" }, \ |
149 | { CLOCK_BOOTTIME, "CLOCK_BOOTTIME" }, \ |
150 | { CLOCK_TAI, "CLOCK_TAI" }) |
151 | |
152 | #define decode_hrtimer_mode(mode) \ |
153 | __print_symbolic(mode, \ |
154 | { HRTIMER_MODE_ABS, "ABS" }, \ |
155 | { HRTIMER_MODE_REL, "REL" }, \ |
156 | { HRTIMER_MODE_ABS_PINNED, "ABS|PINNED" }, \ |
157 | { HRTIMER_MODE_REL_PINNED, "REL|PINNED" }, \ |
158 | { HRTIMER_MODE_ABS_SOFT, "ABS|SOFT" }, \ |
159 | { HRTIMER_MODE_REL_SOFT, "REL|SOFT" }, \ |
160 | { HRTIMER_MODE_ABS_PINNED_SOFT, "ABS|PINNED|SOFT" }, \ |
161 | { HRTIMER_MODE_REL_PINNED_SOFT, "REL|PINNED|SOFT" }, \ |
162 | { HRTIMER_MODE_ABS_HARD, "ABS|HARD" }, \ |
163 | { HRTIMER_MODE_REL_HARD, "REL|HARD" }, \ |
164 | { HRTIMER_MODE_ABS_PINNED_HARD, "ABS|PINNED|HARD" }, \ |
165 | { HRTIMER_MODE_REL_PINNED_HARD, "REL|PINNED|HARD" }) |
166 | |
167 | /** |
168 | * hrtimer_init - called when the hrtimer is initialized |
169 | * @hrtimer: pointer to struct hrtimer |
170 | * @clockid: the hrtimers clock |
171 | * @mode: the hrtimers mode |
172 | */ |
173 | TRACE_EVENT(hrtimer_init, |
174 | |
175 | TP_PROTO(struct hrtimer *hrtimer, clockid_t clockid, |
176 | enum hrtimer_mode mode), |
177 | |
178 | TP_ARGS(hrtimer, clockid, mode), |
179 | |
180 | TP_STRUCT__entry( |
181 | __field( void *, hrtimer ) |
182 | __field( clockid_t, clockid ) |
183 | __field( enum hrtimer_mode, mode ) |
184 | ), |
185 | |
186 | TP_fast_assign( |
187 | __entry->hrtimer = hrtimer; |
188 | __entry->clockid = clockid; |
189 | __entry->mode = mode; |
190 | ), |
191 | |
192 | TP_printk("hrtimer=%p clockid=%s mode=%s" , __entry->hrtimer, |
193 | decode_clockid(__entry->clockid), |
194 | decode_hrtimer_mode(__entry->mode)) |
195 | ); |
196 | |
197 | /** |
198 | * hrtimer_start - called when the hrtimer is started |
199 | * @hrtimer: pointer to struct hrtimer |
200 | * @mode: the hrtimers mode |
201 | */ |
202 | TRACE_EVENT(hrtimer_start, |
203 | |
204 | TP_PROTO(struct hrtimer *hrtimer, enum hrtimer_mode mode), |
205 | |
206 | TP_ARGS(hrtimer, mode), |
207 | |
208 | TP_STRUCT__entry( |
209 | __field( void *, hrtimer ) |
210 | __field( void *, function ) |
211 | __field( s64, expires ) |
212 | __field( s64, softexpires ) |
213 | __field( enum hrtimer_mode, mode ) |
214 | ), |
215 | |
216 | TP_fast_assign( |
217 | __entry->hrtimer = hrtimer; |
218 | __entry->function = hrtimer->function; |
219 | __entry->expires = hrtimer_get_expires(hrtimer); |
220 | __entry->softexpires = hrtimer_get_softexpires(hrtimer); |
221 | __entry->mode = mode; |
222 | ), |
223 | |
224 | TP_printk("hrtimer=%p function=%ps expires=%llu softexpires=%llu " |
225 | "mode=%s" , __entry->hrtimer, __entry->function, |
226 | (unsigned long long) __entry->expires, |
227 | (unsigned long long) __entry->softexpires, |
228 | decode_hrtimer_mode(__entry->mode)) |
229 | ); |
230 | |
231 | /** |
232 | * hrtimer_expire_entry - called immediately before the hrtimer callback |
233 | * @hrtimer: pointer to struct hrtimer |
234 | * @now: pointer to variable which contains current time of the |
235 | * timers base. |
236 | * |
237 | * Allows to determine the timer latency. |
238 | */ |
239 | TRACE_EVENT(hrtimer_expire_entry, |
240 | |
241 | TP_PROTO(struct hrtimer *hrtimer, ktime_t *now), |
242 | |
243 | TP_ARGS(hrtimer, now), |
244 | |
245 | TP_STRUCT__entry( |
246 | __field( void *, hrtimer ) |
247 | __field( s64, now ) |
248 | __field( void *, function) |
249 | ), |
250 | |
251 | TP_fast_assign( |
252 | __entry->hrtimer = hrtimer; |
253 | __entry->now = *now; |
254 | __entry->function = hrtimer->function; |
255 | ), |
256 | |
257 | TP_printk("hrtimer=%p function=%ps now=%llu" , |
258 | __entry->hrtimer, __entry->function, |
259 | (unsigned long long) __entry->now) |
260 | ); |
261 | |
262 | DECLARE_EVENT_CLASS(hrtimer_class, |
263 | |
264 | TP_PROTO(struct hrtimer *hrtimer), |
265 | |
266 | TP_ARGS(hrtimer), |
267 | |
268 | TP_STRUCT__entry( |
269 | __field( void *, hrtimer ) |
270 | ), |
271 | |
272 | TP_fast_assign( |
273 | __entry->hrtimer = hrtimer; |
274 | ), |
275 | |
276 | TP_printk("hrtimer=%p" , __entry->hrtimer) |
277 | ); |
278 | |
279 | /** |
280 | * hrtimer_expire_exit - called immediately after the hrtimer callback returns |
281 | * @hrtimer: pointer to struct hrtimer |
282 | * |
283 | * When used in combination with the hrtimer_expire_entry tracepoint we can |
284 | * determine the runtime of the callback function. |
285 | */ |
286 | DEFINE_EVENT(hrtimer_class, hrtimer_expire_exit, |
287 | |
288 | TP_PROTO(struct hrtimer *hrtimer), |
289 | |
290 | TP_ARGS(hrtimer) |
291 | ); |
292 | |
293 | /** |
294 | * hrtimer_cancel - called when the hrtimer is canceled |
295 | * @hrtimer: pointer to struct hrtimer |
296 | */ |
297 | DEFINE_EVENT(hrtimer_class, hrtimer_cancel, |
298 | |
299 | TP_PROTO(struct hrtimer *hrtimer), |
300 | |
301 | TP_ARGS(hrtimer) |
302 | ); |
303 | |
304 | /** |
305 | * itimer_state - called when itimer is started or canceled |
306 | * @which: name of the interval timer |
307 | * @value: the itimers value, itimer is canceled if value->it_value is |
308 | * zero, otherwise it is started |
309 | * @expires: the itimers expiry time |
310 | */ |
311 | TRACE_EVENT(itimer_state, |
312 | |
313 | TP_PROTO(int which, const struct itimerspec64 *const value, |
314 | unsigned long long expires), |
315 | |
316 | TP_ARGS(which, value, expires), |
317 | |
318 | TP_STRUCT__entry( |
319 | __field( int, which ) |
320 | __field( unsigned long long, expires ) |
321 | __field( long, value_sec ) |
322 | __field( long, value_nsec ) |
323 | __field( long, interval_sec ) |
324 | __field( long, interval_nsec ) |
325 | ), |
326 | |
327 | TP_fast_assign( |
328 | __entry->which = which; |
329 | __entry->expires = expires; |
330 | __entry->value_sec = value->it_value.tv_sec; |
331 | __entry->value_nsec = value->it_value.tv_nsec; |
332 | __entry->interval_sec = value->it_interval.tv_sec; |
333 | __entry->interval_nsec = value->it_interval.tv_nsec; |
334 | ), |
335 | |
336 | TP_printk("which=%d expires=%llu it_value=%ld.%06ld it_interval=%ld.%06ld" , |
337 | __entry->which, __entry->expires, |
338 | __entry->value_sec, __entry->value_nsec / NSEC_PER_USEC, |
339 | __entry->interval_sec, __entry->interval_nsec / NSEC_PER_USEC) |
340 | ); |
341 | |
342 | /** |
343 | * itimer_expire - called when itimer expires |
344 | * @which: type of the interval timer |
345 | * @pid: pid of the process which owns the timer |
346 | * @now: current time, used to calculate the latency of itimer |
347 | */ |
348 | TRACE_EVENT(itimer_expire, |
349 | |
350 | TP_PROTO(int which, struct pid *pid, unsigned long long now), |
351 | |
352 | TP_ARGS(which, pid, now), |
353 | |
354 | TP_STRUCT__entry( |
355 | __field( int , which ) |
356 | __field( pid_t, pid ) |
357 | __field( unsigned long long, now ) |
358 | ), |
359 | |
360 | TP_fast_assign( |
361 | __entry->which = which; |
362 | __entry->now = now; |
363 | __entry->pid = pid_nr(pid); |
364 | ), |
365 | |
366 | TP_printk("which=%d pid=%d now=%llu" , __entry->which, |
367 | (int) __entry->pid, __entry->now) |
368 | ); |
369 | |
370 | #ifdef CONFIG_NO_HZ_COMMON |
371 | |
372 | #define TICK_DEP_NAMES \ |
373 | tick_dep_mask_name(NONE) \ |
374 | tick_dep_name(POSIX_TIMER) \ |
375 | tick_dep_name(PERF_EVENTS) \ |
376 | tick_dep_name(SCHED) \ |
377 | tick_dep_name(CLOCK_UNSTABLE) \ |
378 | tick_dep_name(RCU) \ |
379 | tick_dep_name_end(RCU_EXP) |
380 | |
381 | #undef tick_dep_name |
382 | #undef tick_dep_mask_name |
383 | #undef tick_dep_name_end |
384 | |
385 | /* The MASK will convert to their bits and they need to be processed too */ |
386 | #define tick_dep_name(sdep) TRACE_DEFINE_ENUM(TICK_DEP_BIT_##sdep); \ |
387 | TRACE_DEFINE_ENUM(TICK_DEP_MASK_##sdep); |
388 | #define tick_dep_name_end(sdep) TRACE_DEFINE_ENUM(TICK_DEP_BIT_##sdep); \ |
389 | TRACE_DEFINE_ENUM(TICK_DEP_MASK_##sdep); |
390 | /* NONE only has a mask defined for it */ |
391 | #define tick_dep_mask_name(sdep) TRACE_DEFINE_ENUM(TICK_DEP_MASK_##sdep); |
392 | |
393 | TICK_DEP_NAMES |
394 | |
395 | #undef tick_dep_name |
396 | #undef tick_dep_mask_name |
397 | #undef tick_dep_name_end |
398 | |
399 | #define tick_dep_name(sdep) { TICK_DEP_MASK_##sdep, #sdep }, |
400 | #define tick_dep_mask_name(sdep) { TICK_DEP_MASK_##sdep, #sdep }, |
401 | #define tick_dep_name_end(sdep) { TICK_DEP_MASK_##sdep, #sdep } |
402 | |
403 | #define show_tick_dep_name(val) \ |
404 | __print_symbolic(val, TICK_DEP_NAMES) |
405 | |
406 | TRACE_EVENT(tick_stop, |
407 | |
408 | TP_PROTO(int success, int dependency), |
409 | |
410 | TP_ARGS(success, dependency), |
411 | |
412 | TP_STRUCT__entry( |
413 | __field( int , success ) |
414 | __field( int , dependency ) |
415 | ), |
416 | |
417 | TP_fast_assign( |
418 | __entry->success = success; |
419 | __entry->dependency = dependency; |
420 | ), |
421 | |
422 | TP_printk("success=%d dependency=%s" , __entry->success, \ |
423 | show_tick_dep_name(__entry->dependency)) |
424 | ); |
425 | #endif |
426 | |
427 | #endif /* _TRACE_TIMER_H */ |
428 | |
429 | /* This part must be outside protection */ |
430 | #include <trace/define_trace.h> |
431 | |