lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Sun, 17 Jun 2012 00:35:20 -0600
From:	Hakan Akkan <hakanakkan@...il.com>
To:	Frederic Weisbecker <fweisbec@...il.com>
CC:	LKML <linux-kernel@...r.kernel.org>
Subject: [PATCH] nohz/cpuset: Make a CPU stick with do_timer() duty in the
 presence of nohz cpusets

An adaptive nohz (AHZ) CPU may not do do_timer() for a while
despite being non-idle. When all other CPUs are idle, AHZ
CPUs might be using stale jiffies values. To prevent this
always keep a CPU with ticks if there is one or more AHZ
CPUs.

The patch changes can_stop_{idle,adaptive}_tick functions
and prevents either the last CPU who did the do_timer() duty
or the AHZ CPU itself from stopping its sched timer if there
is one or more AHZ CPUs in the system. This means AHZ CPUs
might keep the ticks running for short periods until a
non-AHZ CPU takes the charge away in
tick_do_timer_check_handler() function. When a non-AHZ CPU
takes the charge, it never gives it away so that AHZ CPUs
can run tickless.

Signed-off-by: Hakan Akkan <hakanakkan@...il.com>
CC: Frederic Weisbecker <fweisbec@...il.com>
---
 include/linux/cpuset.h   |    3 ++-
 kernel/cpuset.c          |    5 +++++
 kernel/time/tick-sched.c |   31 ++++++++++++++++++++++++++++++-
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index ccbc2fd..19aa448 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -266,11 +266,12 @@ static inline bool cpuset_adaptive_nohz(void)
 
 extern void cpuset_exit_nohz_interrupt(void *unused);
 extern void cpuset_nohz_flush_cputimes(void);
+extern bool nohz_cpu_exist(void);
 #else
 static inline bool cpuset_cpu_adaptive_nohz(int cpu) { return false; }
 static inline bool cpuset_adaptive_nohz(void) { return false; }
 static inline void cpuset_nohz_flush_cputimes(void) { }
-
+static inline bool nohz_cpu_exist(void) { return false; }
 #endif /* CONFIG_CPUSETS_NO_HZ */
 
 #endif /* _LINUX_CPUSET_H */
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 858217b..ccbaac9 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1231,6 +1231,11 @@ DEFINE_PER_CPU(int, cpu_adaptive_nohz_ref);
 
 static cpumask_t nohz_cpuset_mask;
 
+inline bool nohz_cpu_exist(void)
+{
+	return !cpumask_empty(&nohz_cpuset_mask);
+}
+
 static void flush_cputime_interrupt(void *unused)
 {
 	trace_printk("IPI: flush cputime\n");
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index bdc8aeb..e60d541 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -409,6 +409,25 @@ out:
 	return ret;
 }
 
+static inline bool must_take_timer_duty(int cpu)
+{
+	int handler = tick_do_timer_cpu;
+	bool ret = false;
+	bool tick_needed = nohz_cpu_exist();
+
+	/*
+	 * A CPU will have to take the timer duty if there is an adaptive
+	 * nohz CPU in the system. The last handler == cpu check ensures
+	 * that the last cpu that did the do_timer() sticks with the duty.
+	 * A normal (non nohz) cpu will take the charge from a nohz cpu in
+	 * tick_do_timer_check_handler anyway.
+	 */
+	if (tick_needed && (handler == TICK_DO_TIMER_NONE || handler == cpu))
+		ret = true;
+
+	return ret;
+}
+
 static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
 {
 	/*
@@ -421,6 +440,9 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
 	if (unlikely(!cpu_online(cpu))) {
 		if (cpu == tick_do_timer_cpu)
 			tick_do_timer_cpu = TICK_DO_TIMER_NONE;
+	} else if (must_take_timer_duty(cpu)) {
+		tick_do_timer_cpu = cpu;
+		return false;
 	}
 
 	if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
@@ -512,6 +534,13 @@ void tick_nohz_idle_enter(void)
 #ifdef CONFIG_CPUSETS_NO_HZ
 static bool can_stop_adaptive_tick(void)
 {
+	int cpu = smp_processor_id();
+
+	if (must_take_timer_duty(cpu)) {
+		tick_do_timer_cpu = cpu;
+		return false;
+	}
+
 	if (!sched_can_stop_tick())
 		return false;
 
@@ -519,7 +548,7 @@ static bool can_stop_adaptive_tick(void)
 		return false;
 
 	/* Is there a grace period to complete ? */
-	if (rcu_pending(smp_processor_id()))
+	if (rcu_pending(cpu))
 		return false;
 
 	return true;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ