Skip to content

Commit ca2d280

Browse files
Thomas Gleixnergregkh
authored andcommitted
hrtimer: Reduce trace noise in hrtimer_start()
[ Upstream commit f2e388a ] hrtimer_start() when invoked with an already armed timer traces like: <comm>-.. [032] d.h2. 5.002263: hrtimer_cancel: hrtimer= .... <comm>-.. [032] d.h1. 5.002263: hrtimer_start: hrtimer= .... Which is incorrect as the timer doesn't get canceled. Just the expiry time changes. The internal dequeue operation which is required for that is not really interesting for trace analysis. But it makes it tedious to keep real cancellations and the above case apart. Remove the cancel tracing in hrtimer_start() and add a 'was_armed' indicator to the hrtimer start tracepoint, which clearly indicates what the state of the hrtimer is when hrtimer_start() is invoked: <comm>-.. [032] d.h1. 6.200103: hrtimer_start: hrtimer= .... was_armed=0 <comm>-.. [032] d.h1. 6.200558: hrtimer_start: hrtimer= .... was_armed=1 Fixes: c6a2a17 ("hrtimer: Add tracepoint for hrtimers") Signed-off-by: Thomas Gleixner <tglx@kernel.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://patch.msgid.link/20260224163430.208491877@kernel.org Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent ece8be2 commit ca2d280

2 files changed

Lines changed: 27 additions & 27 deletions

File tree

include/trace/events/timer.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,19 +198,21 @@ TRACE_EVENT(hrtimer_init,
198198
* hrtimer_start - called when the hrtimer is started
199199
* @hrtimer: pointer to struct hrtimer
200200
* @mode: the hrtimers mode
201+
* @was_armed: Was armed when hrtimer_start*() was invoked
201202
*/
202203
TRACE_EVENT(hrtimer_start,
203204

204-
TP_PROTO(struct hrtimer *hrtimer, enum hrtimer_mode mode),
205+
TP_PROTO(struct hrtimer *hrtimer, enum hrtimer_mode mode, bool was_armed),
205206

206-
TP_ARGS(hrtimer, mode),
207+
TP_ARGS(hrtimer, mode, was_armed),
207208

208209
TP_STRUCT__entry(
209210
__field( void *, hrtimer )
210211
__field( void *, function )
211212
__field( s64, expires )
212213
__field( s64, softexpires )
213214
__field( enum hrtimer_mode, mode )
215+
__field( bool, was_armed )
214216
),
215217

216218
TP_fast_assign(
@@ -219,13 +221,14 @@ TRACE_EVENT(hrtimer_start,
219221
__entry->expires = hrtimer_get_expires(hrtimer);
220222
__entry->softexpires = hrtimer_get_softexpires(hrtimer);
221223
__entry->mode = mode;
224+
__entry->was_armed = was_armed;
222225
),
223226

224227
TP_printk("hrtimer=%p function=%ps expires=%llu softexpires=%llu "
225-
"mode=%s", __entry->hrtimer, __entry->function,
228+
"mode=%s was_armed=%d", __entry->hrtimer, __entry->function,
226229
(unsigned long long) __entry->expires,
227230
(unsigned long long) __entry->softexpires,
228-
decode_hrtimer_mode(__entry->mode))
231+
decode_hrtimer_mode(__entry->mode), __entry->was_armed)
229232
);
230233

231234
/**

kernel/time/hrtimer.c

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -499,17 +499,10 @@ debug_init(struct hrtimer *timer, clockid_t clockid,
499499
trace_hrtimer_init(timer, clockid, mode);
500500
}
501501

502-
static inline void debug_activate(struct hrtimer *timer,
503-
enum hrtimer_mode mode)
502+
static inline void debug_activate(struct hrtimer *timer, enum hrtimer_mode mode, bool was_armed)
504503
{
505504
debug_hrtimer_activate(timer, mode);
506-
trace_hrtimer_start(timer, mode);
507-
}
508-
509-
static inline void debug_deactivate(struct hrtimer *timer)
510-
{
511-
debug_hrtimer_deactivate(timer);
512-
trace_hrtimer_cancel(timer);
505+
trace_hrtimer_start(timer, mode, was_armed);
513506
}
514507

515508
static struct hrtimer_clock_base *
@@ -1102,9 +1095,9 @@ EXPORT_SYMBOL_GPL(hrtimer_forward);
11021095
* Returns true when the new timer is the leftmost timer in the tree.
11031096
*/
11041097
static bool enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base,
1105-
enum hrtimer_mode mode)
1098+
enum hrtimer_mode mode, bool was_armed)
11061099
{
1107-
debug_activate(timer, mode);
1100+
debug_activate(timer, mode, was_armed);
11081101
WARN_ON_ONCE(!base->cpu_base->online);
11091102

11101103
base->cpu_base->active_bases |= 1 << base->index;
@@ -1164,6 +1157,8 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base,
11641157
if (state & HRTIMER_STATE_ENQUEUED) {
11651158
bool reprogram;
11661159

1160+
debug_hrtimer_deactivate(timer);
1161+
11671162
/*
11681163
* Remove the timer and force reprogramming when high
11691164
* resolution mode is active and the timer is on the current
@@ -1172,7 +1167,6 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base,
11721167
* reprogramming happens in the interrupt handler. This is a
11731168
* rare case and less expensive than a smp call.
11741169
*/
1175-
debug_deactivate(timer);
11761170
reprogram = base->cpu_base == this_cpu_ptr(&hrtimer_bases);
11771171

11781172
/*
@@ -1239,15 +1233,15 @@ static int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
12391233
{
12401234
struct hrtimer_cpu_base *this_cpu_base = this_cpu_ptr(&hrtimer_bases);
12411235
struct hrtimer_clock_base *new_base;
1242-
bool force_local, first;
1236+
bool force_local, first, was_armed;
12431237

12441238
/*
12451239
* If the timer is on the local cpu base and is the first expiring
12461240
* timer then this might end up reprogramming the hardware twice
1247-
* (on removal and on enqueue). To avoid that by prevent the
1248-
* reprogram on removal, keep the timer local to the current CPU
1249-
* and enforce reprogramming after it is queued no matter whether
1250-
* it is the new first expiring timer again or not.
1241+
* (on removal and on enqueue). To avoid that prevent the reprogram
1242+
* on removal, keep the timer local to the current CPU and enforce
1243+
* reprogramming after it is queued no matter whether it is the new
1244+
* first expiring timer again or not.
12511245
*/
12521246
force_local = base->cpu_base == this_cpu_base;
12531247
force_local &= base->cpu_base->next_timer == timer;
@@ -1269,7 +1263,7 @@ static int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
12691263
* avoids programming the underlying clock event twice (once at
12701264
* removal and once after enqueue).
12711265
*/
1272-
remove_hrtimer(timer, base, true, force_local);
1266+
was_armed = remove_hrtimer(timer, base, true, force_local);
12731267

12741268
if (mode & HRTIMER_MODE_REL)
12751269
tim = ktime_add_safe(tim, base->get_time());
@@ -1286,7 +1280,7 @@ static int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
12861280
new_base = base;
12871281
}
12881282

1289-
first = enqueue_hrtimer(timer, new_base, mode);
1283+
first = enqueue_hrtimer(timer, new_base, mode, was_armed);
12901284

12911285
/*
12921286
* If the hrtimer interrupt is running, then it will reevaluate the
@@ -1390,8 +1384,11 @@ int hrtimer_try_to_cancel(struct hrtimer *timer)
13901384

13911385
base = lock_hrtimer_base(timer, &flags);
13921386

1393-
if (!hrtimer_callback_running(timer))
1387+
if (!hrtimer_callback_running(timer)) {
13941388
ret = remove_hrtimer(timer, base, false, false);
1389+
if (ret)
1390+
trace_hrtimer_cancel(timer);
1391+
}
13951392

13961393
unlock_hrtimer_base(timer, &flags);
13971394

@@ -1771,7 +1768,7 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
17711768
*/
17721769
if (restart != HRTIMER_NORESTART &&
17731770
!(timer->state & HRTIMER_STATE_ENQUEUED))
1774-
enqueue_hrtimer(timer, base, HRTIMER_MODE_ABS);
1771+
enqueue_hrtimer(timer, base, HRTIMER_MODE_ABS, false);
17751772

17761773
/*
17771774
* Separate the ->running assignment from the ->state assignment.
@@ -2253,7 +2250,7 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
22532250
while ((node = timerqueue_getnext(&old_base->active))) {
22542251
timer = container_of(node, struct hrtimer, node);
22552252
BUG_ON(hrtimer_callback_running(timer));
2256-
debug_deactivate(timer);
2253+
debug_hrtimer_deactivate(timer);
22572254

22582255
/*
22592256
* Mark it as ENQUEUED not INACTIVE otherwise the
@@ -2270,7 +2267,7 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
22702267
* sort out already expired timers and reprogram the
22712268
* event device.
22722269
*/
2273-
enqueue_hrtimer(timer, new_base, HRTIMER_MODE_ABS);
2270+
enqueue_hrtimer(timer, new_base, HRTIMER_MODE_ABS, true);
22742271
}
22752272
}
22762273

0 commit comments

Comments
 (0)