Skip to content

Commit e017f5b

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 a8759ee commit e017f5b

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
@@ -218,19 +218,21 @@ TRACE_EVENT(hrtimer_setup,
218218
* hrtimer_start - called when the hrtimer is started
219219
* @hrtimer: pointer to struct hrtimer
220220
* @mode: the hrtimers mode
221+
* @was_armed: Was armed when hrtimer_start*() was invoked
221222
*/
222223
TRACE_EVENT(hrtimer_start,
223224

224-
TP_PROTO(struct hrtimer *hrtimer, enum hrtimer_mode mode),
225+
TP_PROTO(struct hrtimer *hrtimer, enum hrtimer_mode mode, bool was_armed),
225226

226-
TP_ARGS(hrtimer, mode),
227+
TP_ARGS(hrtimer, mode, was_armed),
227228

228229
TP_STRUCT__entry(
229230
__field( void *, hrtimer )
230231
__field( void *, function )
231232
__field( s64, expires )
232233
__field( s64, softexpires )
233234
__field( enum hrtimer_mode, mode )
235+
__field( bool, was_armed )
234236
),
235237

236238
TP_fast_assign(
@@ -239,13 +241,14 @@ TRACE_EVENT(hrtimer_start,
239241
__entry->expires = hrtimer_get_expires(hrtimer);
240242
__entry->softexpires = hrtimer_get_softexpires(hrtimer);
241243
__entry->mode = mode;
244+
__entry->was_armed = was_armed;
242245
),
243246

244247
TP_printk("hrtimer=%p function=%ps expires=%llu softexpires=%llu "
245-
"mode=%s", __entry->hrtimer, __entry->function,
248+
"mode=%s was_armed=%d", __entry->hrtimer, __entry->function,
246249
(unsigned long long) __entry->expires,
247250
(unsigned long long) __entry->softexpires,
248-
decode_hrtimer_mode(__entry->mode))
251+
decode_hrtimer_mode(__entry->mode), __entry->was_armed)
249252
);
250253

251254
/**

kernel/time/hrtimer.c

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -471,17 +471,10 @@ static inline void debug_setup_on_stack(struct hrtimer *timer, clockid_t clockid
471471
trace_hrtimer_setup(timer, clockid, mode);
472472
}
473473

474-
static inline void debug_activate(struct hrtimer *timer,
475-
enum hrtimer_mode mode)
474+
static inline void debug_activate(struct hrtimer *timer, enum hrtimer_mode mode, bool was_armed)
476475
{
477476
debug_hrtimer_activate(timer, mode);
478-
trace_hrtimer_start(timer, mode);
479-
}
480-
481-
static inline void debug_deactivate(struct hrtimer *timer)
482-
{
483-
debug_hrtimer_deactivate(timer);
484-
trace_hrtimer_cancel(timer);
477+
trace_hrtimer_start(timer, mode, was_armed);
485478
}
486479

487480
static struct hrtimer_clock_base *
@@ -1076,9 +1069,9 @@ EXPORT_SYMBOL_GPL(hrtimer_forward);
10761069
* Returns true when the new timer is the leftmost timer in the tree.
10771070
*/
10781071
static bool enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base,
1079-
enum hrtimer_mode mode)
1072+
enum hrtimer_mode mode, bool was_armed)
10801073
{
1081-
debug_activate(timer, mode);
1074+
debug_activate(timer, mode, was_armed);
10821075
WARN_ON_ONCE(!base->cpu_base->online);
10831076

10841077
base->cpu_base->active_bases |= 1 << base->index;
@@ -1138,6 +1131,8 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base,
11381131
if (state & HRTIMER_STATE_ENQUEUED) {
11391132
bool reprogram;
11401133

1134+
debug_hrtimer_deactivate(timer);
1135+
11411136
/*
11421137
* Remove the timer and force reprogramming when high
11431138
* resolution mode is active and the timer is on the current
@@ -1146,7 +1141,6 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base,
11461141
* reprogramming happens in the interrupt handler. This is a
11471142
* rare case and less expensive than a smp call.
11481143
*/
1149-
debug_deactivate(timer);
11501144
reprogram = base->cpu_base == this_cpu_ptr(&hrtimer_bases);
11511145

11521146
/*
@@ -1213,15 +1207,15 @@ static int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
12131207
{
12141208
struct hrtimer_cpu_base *this_cpu_base = this_cpu_ptr(&hrtimer_bases);
12151209
struct hrtimer_clock_base *new_base;
1216-
bool force_local, first;
1210+
bool force_local, first, was_armed;
12171211

12181212
/*
12191213
* If the timer is on the local cpu base and is the first expiring
12201214
* timer then this might end up reprogramming the hardware twice
1221-
* (on removal and on enqueue). To avoid that by prevent the
1222-
* reprogram on removal, keep the timer local to the current CPU
1223-
* and enforce reprogramming after it is queued no matter whether
1224-
* it is the new first expiring timer again or not.
1215+
* (on removal and on enqueue). To avoid that prevent the reprogram
1216+
* on removal, keep the timer local to the current CPU and enforce
1217+
* reprogramming after it is queued no matter whether it is the new
1218+
* first expiring timer again or not.
12251219
*/
12261220
force_local = base->cpu_base == this_cpu_base;
12271221
force_local &= base->cpu_base->next_timer == timer;
@@ -1243,7 +1237,7 @@ static int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
12431237
* avoids programming the underlying clock event twice (once at
12441238
* removal and once after enqueue).
12451239
*/
1246-
remove_hrtimer(timer, base, true, force_local);
1240+
was_armed = remove_hrtimer(timer, base, true, force_local);
12471241

12481242
if (mode & HRTIMER_MODE_REL)
12491243
tim = ktime_add_safe(tim, __hrtimer_cb_get_time(base->clockid));
@@ -1260,7 +1254,7 @@ static int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
12601254
new_base = base;
12611255
}
12621256

1263-
first = enqueue_hrtimer(timer, new_base, mode);
1257+
first = enqueue_hrtimer(timer, new_base, mode, was_armed);
12641258

12651259
/*
12661260
* If the hrtimer interrupt is running, then it will reevaluate the
@@ -1362,8 +1356,11 @@ int hrtimer_try_to_cancel(struct hrtimer *timer)
13621356

13631357
base = lock_hrtimer_base(timer, &flags);
13641358

1365-
if (!hrtimer_callback_running(timer))
1359+
if (!hrtimer_callback_running(timer)) {
13661360
ret = remove_hrtimer(timer, base, false, false);
1361+
if (ret)
1362+
trace_hrtimer_cancel(timer);
1363+
}
13671364

13681365
unlock_hrtimer_base(timer, &flags);
13691366

@@ -1799,7 +1796,7 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
17991796
*/
18001797
if (restart != HRTIMER_NORESTART &&
18011798
!(timer->state & HRTIMER_STATE_ENQUEUED))
1802-
enqueue_hrtimer(timer, base, HRTIMER_MODE_ABS);
1799+
enqueue_hrtimer(timer, base, HRTIMER_MODE_ABS, false);
18031800

18041801
/*
18051802
* Separate the ->running assignment from the ->state assignment.
@@ -2278,7 +2275,7 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
22782275
while ((node = timerqueue_getnext(&old_base->active))) {
22792276
timer = container_of(node, struct hrtimer, node);
22802277
BUG_ON(hrtimer_callback_running(timer));
2281-
debug_deactivate(timer);
2278+
debug_hrtimer_deactivate(timer);
22822279

22832280
/*
22842281
* Mark it as ENQUEUED not INACTIVE otherwise the
@@ -2295,7 +2292,7 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
22952292
* sort out already expired timers and reprogram the
22962293
* event device.
22972294
*/
2298-
enqueue_hrtimer(timer, new_base, HRTIMER_MODE_ABS);
2295+
enqueue_hrtimer(timer, new_base, HRTIMER_MODE_ABS, true);
22992296
}
23002297
}
23012298

0 commit comments

Comments
 (0)