All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] perf: skew perf_mux_hrtimer_handler firing across cpus
@ 2026-10-29 23:28 Benjamin Segall
  2026-10-29 23:42 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Benjamin Segall @ 2026-10-29 23:28 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark
  Cc: linux-perf-users, linux-kernel

When in nohz_full, perf_mux_hrtimer will wind up checking if it needs to
update jiffies as of commit 53e87e3cdc15 ("timers/nohz: Last resort update
jiffies on nohz_full IRQ entry"). When perf is run systemwide or against
a wide process and needs the mux timer, this will fire against many cpus
at the same interval. Then, much like the timer tick did, this will
result in unnecessary lock contention on jiffies_lock. This is
particularly unfortunate since nohz_full is intended to reduce the time
spent in irqs on those cpus.

Adopt the same solution as sched_skew_tick and just have a different
offset for the timer on each cpu, and make sure to redo the skew if the
interval is changed.

Signed-off-by: Ben Segall <bsegall@google.com>
---
 include/linux/perf_event.h |  1 +
 kernel/events/core.c       | 12 ++++++++++++
 2 files changed, 13 insertions(+)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index eb3f7bab498ca..e1cb052af3d2e 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1123,10 +1123,11 @@ struct perf_cpu_pmu_context {
 	int				pmu_disable_count;
 
 	raw_spinlock_t			hrtimer_lock;
 	struct hrtimer			hrtimer;
 	ktime_t				hrtimer_interval;
+	ktime_t				hrtimer_old_interval;
 	unsigned int			hrtimer_active;
 };
 
 /**
  * struct perf_event_cpu_context - per cpu event context structure
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 457d75ea71420..7885071bf0856 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1277,17 +1277,29 @@ static void perf_cgroup_switch(struct task_struct *task)
  */
 static enum hrtimer_restart perf_mux_hrtimer_handler(struct hrtimer *hr)
 {
 	struct perf_cpu_pmu_context *cpc;
 	bool rotations;
+	u64 offset;
 
 	lockdep_assert_irqs_disabled();
 
 	cpc = container_of(hr, struct perf_cpu_pmu_context, hrtimer);
 	rotations = perf_rotate_context(cpc);
 
 	raw_spin_lock(&cpc->hrtimer_lock);
+	if (cpc->hrtimer_old_interval != cpc->hrtimer_interval) {
+		/*
+		 * Skew the timer to avoid contention on jiffies_lock in
+		 * nohz_full, whenever we change interval
+		 */
+		offset = cpc->hrtimer_interval;
+		do_div(offset, num_possible_cpus());
+		offset *= smp_processor_id(); /* we are PINNED_HARD */
+		hrtimer_set_expires(hr, offset);
+		cpc->hrtimer_old_interval = cpc->hrtimer_interval;
+	}
 	if (rotations)
 		hrtimer_forward_now(hr, cpc->hrtimer_interval);
 	else
 		cpc->hrtimer_active = 0;
 	raw_spin_unlock(&cpc->hrtimer_lock);
-- 
2.56.0.317.g454f8302e1-goog


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-29 23:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-29 23:28 [PATCH] perf: skew perf_mux_hrtimer_handler firing across cpus Benjamin Segall
2026-10-29 23:42 ` sashiko-bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.