* [PATCH 1/5] nohz: Separate idle sleeping time accounting from nohz logic
2012-06-11 16:53 [GIT PULL] nohz: Generalize nohz APIs for adaptive tickless Frederic Weisbecker
@ 2012-06-11 16:53 ` Frederic Weisbecker
2012-06-11 18:09 ` Frederic Weisbecker
2012-06-11 16:53 ` [PATCH 2/5] nohz: Make nohz API agnostic against idle ticks cputime accounting Frederic Weisbecker
` (3 subsequent siblings)
4 siblings, 1 reply; 7+ messages in thread
From: Frederic Weisbecker @ 2012-06-11 16:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: LKML, Frederic Weisbecker, Alessio Igor Bogani, Andrew Morton,
Avi Kivity, Chris Metcalf, Christoph Lameter, Daniel Lezcano,
Geoff Levand, Gilad Ben Yossef, Hakan Akkan, Kevin Hilman,
Max Krasnyansky, Paul E. McKenney, Peter Zijlstra,
Stephen Hemminger, Steven Rostedt, Sven-Thorsten Dietrich,
Thomas Gleixner
As we plan to be able to stop the tick outside the idle task, we
need to prepare for separating nohz logic from idle. As a start,
this pulls the idle sleeping time accounting out of the tick
stop/restart API to the callers on idle entry/exit.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Alessio Igor Bogani <abogani@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Avi Kivity <avi@redhat.com>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Geoff Levand <geoff@infradead.org>
Cc: Gilad Ben Yossef <gilad@benyossef.com>
Cc: Hakan Akkan <hakanakkan@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Kevin Hilman <khilman@ti.com>
Cc: Max Krasnyansky <maxk@qualcomm.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Sven-Thorsten Dietrich <thebigcorporation@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
kernel/time/tick-sched.c | 78 +++++++++++++++++++++++++--------------------
1 files changed, 43 insertions(+), 35 deletions(-)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index da70c6d..6321a20 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -271,10 +271,10 @@ u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
}
EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us);
-static void tick_nohz_stop_sched_tick(struct tick_sched *ts)
+static void tick_nohz_stop_sched_tick(struct tick_sched *ts, ktime_t now)
{
unsigned long seq, last_jiffies, next_jiffies, delta_jiffies;
- ktime_t last_update, expires, now;
+ ktime_t last_update, expires;
struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
u64 time_delta;
int cpu;
@@ -282,8 +282,6 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts)
cpu = smp_processor_id();
ts = &per_cpu(tick_cpu_sched, cpu);
- now = tick_nohz_start_idle(cpu, ts);
-
/*
* If this cpu is offline and it is the one which updates
* jiffies, then give up the assignment and let it be taken by
@@ -444,6 +442,14 @@ out:
ts->sleep_length = ktime_sub(dev->next_event, now);
}
+static void __tick_nohz_idle_enter(struct tick_sched *ts)
+{
+ ktime_t now;
+
+ now = tick_nohz_start_idle(smp_processor_id(), ts);
+ tick_nohz_stop_sched_tick(ts, now);
+}
+
/**
* tick_nohz_idle_enter - stop the idle tick from the idle task
*
@@ -479,7 +485,7 @@ void tick_nohz_idle_enter(void)
* update of the idle time accounting in tick_nohz_start_idle().
*/
ts->inidle = 1;
- tick_nohz_stop_sched_tick(ts);
+ __tick_nohz_idle_enter(ts);
local_irq_enable();
}
@@ -499,7 +505,7 @@ void tick_nohz_irq_exit(void)
if (!ts->inidle)
return;
- tick_nohz_stop_sched_tick(ts);
+ __tick_nohz_idle_enter(ts);
}
/**
@@ -540,39 +546,11 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
}
}
-/**
- * tick_nohz_idle_exit - restart the idle tick from the idle task
- *
- * Restart the idle tick when the CPU is woken up from idle
- * This also exit the RCU extended quiescent state. The CPU
- * can use RCU again after this function is called.
- */
-void tick_nohz_idle_exit(void)
+static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
{
- int cpu = smp_processor_id();
- struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
#ifndef CONFIG_VIRT_CPU_ACCOUNTING
unsigned long ticks;
#endif
- ktime_t now;
-
- local_irq_disable();
-
- WARN_ON_ONCE(!ts->inidle);
-
- ts->inidle = 0;
-
- if (ts->idle_active || ts->tick_stopped)
- now = ktime_get();
-
- if (ts->idle_active)
- tick_nohz_stop_idle(cpu, now);
-
- if (!ts->tick_stopped) {
- local_irq_enable();
- return;
- }
-
/* Update jiffies first */
select_nohz_load_balancer(0);
tick_do_update_jiffies64(now);
@@ -600,6 +578,36 @@ void tick_nohz_idle_exit(void)
ts->idle_exittime = now;
tick_nohz_restart(ts, now);
+}
+
+/**
+ * tick_nohz_idle_exit - restart the idle tick from the idle task
+ *
+ * Restart the idle tick when the CPU is woken up from idle
+ * This also exit the RCU extended quiescent state. The CPU
+ * can use RCU again after this function is called.
+ */
+void tick_nohz_idle_exit(void)
+
+{
+ int cpu = smp_processor_id();
+ struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+ ktime_t now;
+
+ local_irq_disable();
+
+ WARN_ON_ONCE(!ts->inidle);
+
+ ts->inidle = 0;
+
+ if (ts->idle_active || ts->tick_stopped)
+ now = ktime_get();
+
+ if (ts->idle_active)
+ tick_nohz_stop_idle(cpu, now);
+
+ if (ts->tick_stopped)
+ tick_nohz_restart_sched_tick(ts, now);
local_irq_enable();
}
--
1.7.5.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 1/5] nohz: Separate idle sleeping time accounting from nohz logic
2012-06-11 16:53 ` [PATCH 1/5] nohz: Separate idle sleeping time accounting from nohz logic Frederic Weisbecker
@ 2012-06-11 18:09 ` Frederic Weisbecker
0 siblings, 0 replies; 7+ messages in thread
From: Frederic Weisbecker @ 2012-06-11 18:09 UTC (permalink / raw)
To: Ingo Molnar
Cc: LKML, Alessio Igor Bogani, Andrew Morton, Avi Kivity,
Chris Metcalf, Christoph Lameter, Daniel Lezcano, Geoff Levand,
Gilad Ben Yossef, Hakan Akkan, Kevin Hilman, Max Krasnyansky,
Paul E. McKenney, Peter Zijlstra, Stephen Hemminger,
Steven Rostedt, Sven-Thorsten Dietrich, Thomas Gleixner
On Mon, Jun 11, 2012 at 06:53:18PM +0200, Frederic Weisbecker wrote:
> +}
> +
> +/**
> + * tick_nohz_idle_exit - restart the idle tick from the idle task
> + *
> + * Restart the idle tick when the CPU is woken up from idle
> + * This also exit the RCU extended quiescent state. The CPU
> + * can use RCU again after this function is called.
> + */
> +void tick_nohz_idle_exit(void)
> +
> +{
Thomas pointed me to the above undesired newline. I fixed that
in the branch nohz-for-tip-2
Thanks.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/5] nohz: Make nohz API agnostic against idle ticks cputime accounting
2012-06-11 16:53 [GIT PULL] nohz: Generalize nohz APIs for adaptive tickless Frederic Weisbecker
2012-06-11 16:53 ` [PATCH 1/5] nohz: Separate idle sleeping time accounting from nohz logic Frederic Weisbecker
@ 2012-06-11 16:53 ` Frederic Weisbecker
2012-06-11 16:53 ` [PATCH 3/5] nohz: Rename ts->idle_tick to ts->last_tick Frederic Weisbecker
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Frederic Weisbecker @ 2012-06-11 16:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: LKML, Frederic Weisbecker, Alessio Igor Bogani, Andrew Morton,
Avi Kivity, Chris Metcalf, Christoph Lameter, Daniel Lezcano,
Geoff Levand, Gilad Ben Yossef, Hakan Akkan, Kevin Hilman,
Max Krasnyansky, Paul E. McKenney, Peter Zijlstra,
Stephen Hemminger, Steven Rostedt, Sven-Thorsten Dietrich,
Thomas Gleixner
When the timer tick fires, it accounts the new jiffy as either part
of system, user or idle time. This is how we record the cputime
statistics.
But when the tick is stopped from the idle task, we still need
to record the number of jiffies spent tickless until we restart
the tick and fall back to traditional tick-based cputime accounting.
To do this, we take a snapshot of jiffies when the tick is stopped
and compute the difference against the new value of jiffies when
the tick is restarted. Then we account this whole difference to
the idle cputime.
However we are preparing to be able to stop the tick from other places
than idle. So this idle time accounting needs to be performed from
the callers of nohz APIs, not from the nohz APIs themselves because
we now want them to be agnostic against places that stop/restart tick.
Therefore, we pull the tickless idle time accounting out of generic
nohz helpers up to idle entry/exit callers.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Alessio Igor Bogani <abogani@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Avi Kivity <avi@redhat.com>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Geoff Levand <geoff@infradead.org>
Cc: Gilad Ben Yossef <gilad@benyossef.com>
Cc: Hakan Akkan <hakanakkan@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Kevin Hilman <khilman@ti.com>
Cc: Max Krasnyansky <maxk@qualcomm.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Sven-Thorsten Dietrich <thebigcorporation@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
kernel/time/tick-sched.c | 37 ++++++++++++++++++++++---------------
1 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 6321a20..e9966f7 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -402,7 +402,6 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts, ktime_t now)
ts->idle_tick = hrtimer_get_expires(&ts->sched_timer);
ts->tick_stopped = 1;
- ts->idle_jiffies = last_jiffies;
}
ts->idle_sleeps++;
@@ -445,9 +444,13 @@ out:
static void __tick_nohz_idle_enter(struct tick_sched *ts)
{
ktime_t now;
+ int was_stopped = ts->tick_stopped;
now = tick_nohz_start_idle(smp_processor_id(), ts);
tick_nohz_stop_sched_tick(ts, now);
+
+ if (!was_stopped && ts->tick_stopped)
+ ts->idle_jiffies = ts->last_jiffies;
}
/**
@@ -548,15 +551,25 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
{
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
- unsigned long ticks;
-#endif
/* Update jiffies first */
select_nohz_load_balancer(0);
tick_do_update_jiffies64(now);
update_cpu_load_nohz();
+ touch_softlockup_watchdog();
+ /*
+ * Cancel the scheduled timer and restore the tick
+ */
+ ts->tick_stopped = 0;
+ ts->idle_exittime = now;
+
+ tick_nohz_restart(ts, now);
+}
+
+static void tick_nohz_account_idle_ticks(struct tick_sched *ts)
+{
#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+ unsigned long ticks;
/*
* We stopped the tick in idle. Update process times would miss the
* time we slept as update_process_times does only a 1 tick
@@ -569,15 +582,6 @@ static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
if (ticks && ticks < LONG_MAX)
account_idle_ticks(ticks);
#endif
-
- touch_softlockup_watchdog();
- /*
- * Cancel the scheduled timer and restore the tick
- */
- ts->tick_stopped = 0;
- ts->idle_exittime = now;
-
- tick_nohz_restart(ts, now);
}
/**
@@ -606,8 +610,10 @@ void tick_nohz_idle_exit(void)
if (ts->idle_active)
tick_nohz_stop_idle(cpu, now);
- if (ts->tick_stopped)
+ if (ts->tick_stopped) {
tick_nohz_restart_sched_tick(ts, now);
+ tick_nohz_account_idle_ticks(ts);
+ }
local_irq_enable();
}
@@ -812,7 +818,8 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
*/
if (ts->tick_stopped) {
touch_softlockup_watchdog();
- ts->idle_jiffies++;
+ if (idle_cpu(cpu))
+ ts->idle_jiffies++;
}
update_process_times(user_mode(regs));
profile_tick(CPU_PROFILING);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 3/5] nohz: Rename ts->idle_tick to ts->last_tick
2012-06-11 16:53 [GIT PULL] nohz: Generalize nohz APIs for adaptive tickless Frederic Weisbecker
2012-06-11 16:53 ` [PATCH 1/5] nohz: Separate idle sleeping time accounting from nohz logic Frederic Weisbecker
2012-06-11 16:53 ` [PATCH 2/5] nohz: Make nohz API agnostic against idle ticks cputime accounting Frederic Weisbecker
@ 2012-06-11 16:53 ` Frederic Weisbecker
2012-06-11 16:53 ` [PATCH 4/5] nohz: Move ts->idle_calls incrementation into strict idle logic Frederic Weisbecker
2012-06-11 16:53 ` [PATCH 5/5] nohz: Move next idle expiry time record into idle logic area Frederic Weisbecker
4 siblings, 0 replies; 7+ messages in thread
From: Frederic Weisbecker @ 2012-06-11 16:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: LKML, Frederic Weisbecker, Alessio Igor Bogani, Andrew Morton,
Avi Kivity, Chris Metcalf, Christoph Lameter, Daniel Lezcano,
Geoff Levand, Gilad Ben Yossef, Hakan Akkan, Kevin Hilman,
Max Krasnyansky, Paul E. McKenney, Peter Zijlstra,
Stephen Hemminger, Steven Rostedt, Sven-Thorsten Dietrich,
Thomas Gleixner
Now that idle and nohz logics are going to be independant each others,
ts->idle_tick becomes too much a biased name to describe the field that
saves the last scheduled tick on top of which we re-calculate the next
tick to schedule when the timer is restarted.
We want to reuse this even to stop the tick outside idle cases. So let's
rename it to some more generic name: ts->last_tick.
This changes a bit the timer list stat export so we need to increase its
version.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Alessio Igor Bogani <abogani@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Avi Kivity <avi@redhat.com>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Geoff Levand <geoff@infradead.org>
Cc: Gilad Ben Yossef <gilad@benyossef.com>
Cc: Hakan Akkan <hakanakkan@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Kevin Hilman <khilman@ti.com>
Cc: Max Krasnyansky <maxk@qualcomm.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Sven-Thorsten Dietrich <thebigcorporation@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
include/linux/tick.h | 8 ++++----
kernel/time/tick-sched.c | 4 ++--
kernel/time/timer_list.c | 4 ++--
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/include/linux/tick.h b/include/linux/tick.h
index ab8be90..f37fceb 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -31,10 +31,10 @@ enum tick_nohz_mode {
* struct tick_sched - sched tick emulation and no idle tick control/stats
* @sched_timer: hrtimer to schedule the periodic tick in high
* resolution mode
- * @idle_tick: Store the last idle tick expiry time when the tick
- * timer is modified for idle sleeps. This is necessary
+ * @last_tick: Store the last tick expiry time when the tick
+ * timer is modified for nohz sleeps. This is necessary
* to resume the tick timer operation in the timeline
- * when the CPU returns from idle
+ * when the CPU returns from nohz sleep.
* @tick_stopped: Indicator that the idle tick has been stopped
* @idle_jiffies: jiffies at the entry to idle for idle time accounting
* @idle_calls: Total number of idle calls
@@ -51,7 +51,7 @@ struct tick_sched {
struct hrtimer sched_timer;
unsigned long check_clocks;
enum tick_nohz_mode nohz_mode;
- ktime_t idle_tick;
+ ktime_t last_tick;
int inidle;
int tick_stopped;
unsigned long idle_jiffies;
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index e9966f7..69ab8d9 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -400,7 +400,7 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts, ktime_t now)
if (!ts->tick_stopped) {
select_nohz_load_balancer(1);
- ts->idle_tick = hrtimer_get_expires(&ts->sched_timer);
+ ts->last_tick = hrtimer_get_expires(&ts->sched_timer);
ts->tick_stopped = 1;
}
@@ -526,7 +526,7 @@ ktime_t tick_nohz_get_sleep_length(void)
static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
{
hrtimer_cancel(&ts->sched_timer);
- hrtimer_set_expires(&ts->sched_timer, ts->idle_tick);
+ hrtimer_set_expires(&ts->sched_timer, ts->last_tick);
while (1) {
/* Forward the time to expire in the future */
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index 3258455..af5a7e9 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -167,7 +167,7 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now)
{
struct tick_sched *ts = tick_get_tick_sched(cpu);
P(nohz_mode);
- P_ns(idle_tick);
+ P_ns(last_tick);
P(tick_stopped);
P(idle_jiffies);
P(idle_calls);
@@ -259,7 +259,7 @@ static int timer_list_show(struct seq_file *m, void *v)
u64 now = ktime_to_ns(ktime_get());
int cpu;
- SEQ_printf(m, "Timer List Version: v0.6\n");
+ SEQ_printf(m, "Timer List Version: v0.7\n");
SEQ_printf(m, "HRTIMER_MAX_CLOCK_BASES: %d\n", HRTIMER_MAX_CLOCK_BASES);
SEQ_printf(m, "now at %Ld nsecs\n", (unsigned long long)now);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 4/5] nohz: Move ts->idle_calls incrementation into strict idle logic
2012-06-11 16:53 [GIT PULL] nohz: Generalize nohz APIs for adaptive tickless Frederic Weisbecker
` (2 preceding siblings ...)
2012-06-11 16:53 ` [PATCH 3/5] nohz: Rename ts->idle_tick to ts->last_tick Frederic Weisbecker
@ 2012-06-11 16:53 ` Frederic Weisbecker
2012-06-11 16:53 ` [PATCH 5/5] nohz: Move next idle expiry time record into idle logic area Frederic Weisbecker
4 siblings, 0 replies; 7+ messages in thread
From: Frederic Weisbecker @ 2012-06-11 16:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: LKML, Frederic Weisbecker, Alessio Igor Bogani, Andrew Morton,
Avi Kivity, Chris Metcalf, Christoph Lameter, Daniel Lezcano,
Geoff Levand, Gilad Ben Yossef, Hakan Akkan, Kevin Hilman,
Max Krasnyansky, Paul E. McKenney, Peter Zijlstra,
Stephen Hemminger, Steven Rostedt, Sven-Thorsten Dietrich,
Thomas Gleixner
Since we want to prepare for making the nohz API to work further
the idle case, we need to pull ts->idle_calls incrementation up to
the callers in idle.
To perform this, we split tick_nohz_stop_sched_tick() in two parts:
a first one that checks if we can really stop the tick for idle,
and another that actually stops it. Then from the callers in idle,
we check if we can stop the tick and only then we increment idle_calls
and finally relay to the nohz API that won't care about these details
anymore.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Alessio Igor Bogani <abogani@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Avi Kivity <avi@redhat.com>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Geoff Levand <geoff@infradead.org>
Cc: Gilad Ben Yossef <gilad@benyossef.com>
Cc: Hakan Akkan <hakanakkan@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Kevin Hilman <khilman@ti.com>
Cc: Max Krasnyansky <maxk@qualcomm.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Sven-Thorsten Dietrich <thebigcorporation@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
kernel/time/tick-sched.c | 86 +++++++++++++++++++++++++---------------------
1 files changed, 47 insertions(+), 39 deletions(-)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 69ab8d9..087833a 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -271,47 +271,15 @@ u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
}
EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us);
-static void tick_nohz_stop_sched_tick(struct tick_sched *ts, ktime_t now)
+static void tick_nohz_stop_sched_tick(struct tick_sched *ts,
+ ktime_t now, int cpu)
{
unsigned long seq, last_jiffies, next_jiffies, delta_jiffies;
ktime_t last_update, expires;
struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
u64 time_delta;
- int cpu;
-
- cpu = smp_processor_id();
- ts = &per_cpu(tick_cpu_sched, cpu);
-
- /*
- * If this cpu is offline and it is the one which updates
- * jiffies, then give up the assignment and let it be taken by
- * the cpu which runs the tick timer next. If we don't drop
- * this here the jiffies might be stale and do_timer() never
- * invoked.
- */
- if (unlikely(!cpu_online(cpu))) {
- if (cpu == tick_do_timer_cpu)
- tick_do_timer_cpu = TICK_DO_TIMER_NONE;
- }
-
- if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
- return;
-
- if (need_resched())
- return;
- if (unlikely(local_softirq_pending() && cpu_online(cpu))) {
- static int ratelimit;
-
- if (ratelimit < 10) {
- printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
- (unsigned int) local_softirq_pending());
- ratelimit++;
- }
- return;
- }
- ts->idle_calls++;
/* Read jiffies and the time when jiffies were updated last */
do {
seq = read_seqbegin(&xtime_lock);
@@ -441,16 +409,56 @@ out:
ts->sleep_length = ktime_sub(dev->next_event, now);
}
+static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
+{
+ /*
+ * If this cpu is offline and it is the one which updates
+ * jiffies, then give up the assignment and let it be taken by
+ * the cpu which runs the tick timer next. If we don't drop
+ * this here the jiffies might be stale and do_timer() never
+ * invoked.
+ */
+ if (unlikely(!cpu_online(cpu))) {
+ if (cpu == tick_do_timer_cpu)
+ tick_do_timer_cpu = TICK_DO_TIMER_NONE;
+ }
+
+ if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
+ return false;
+
+ if (need_resched())
+ return false;
+
+ if (unlikely(local_softirq_pending() && cpu_online(cpu))) {
+ static int ratelimit;
+
+ if (ratelimit < 10) {
+ printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
+ (unsigned int) local_softirq_pending());
+ ratelimit++;
+ }
+ return false;
+ }
+
+ return true;
+}
+
static void __tick_nohz_idle_enter(struct tick_sched *ts)
{
ktime_t now;
- int was_stopped = ts->tick_stopped;
+ int cpu = smp_processor_id();
- now = tick_nohz_start_idle(smp_processor_id(), ts);
- tick_nohz_stop_sched_tick(ts, now);
+ now = tick_nohz_start_idle(cpu, ts);
- if (!was_stopped && ts->tick_stopped)
- ts->idle_jiffies = ts->last_jiffies;
+ if (can_stop_idle_tick(cpu, ts)) {
+ int was_stopped = ts->tick_stopped;
+
+ ts->idle_calls++;
+ tick_nohz_stop_sched_tick(ts, now, cpu);
+
+ if (!was_stopped && ts->tick_stopped)
+ ts->idle_jiffies = ts->last_jiffies;
+ }
}
/**
--
1.7.5.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 5/5] nohz: Move next idle expiry time record into idle logic area
2012-06-11 16:53 [GIT PULL] nohz: Generalize nohz APIs for adaptive tickless Frederic Weisbecker
` (3 preceding siblings ...)
2012-06-11 16:53 ` [PATCH 4/5] nohz: Move ts->idle_calls incrementation into strict idle logic Frederic Weisbecker
@ 2012-06-11 16:53 ` Frederic Weisbecker
4 siblings, 0 replies; 7+ messages in thread
From: Frederic Weisbecker @ 2012-06-11 16:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: LKML, Frederic Weisbecker, Alessio Igor Bogani, Andrew Morton,
Avi Kivity, Chris Metcalf, Christoph Lameter, Daniel Lezcano,
Geoff Levand, Gilad Ben Yossef, Hakan Akkan, Kevin Hilman,
Max Krasnyansky, Paul E. McKenney, Peter Zijlstra,
Stephen Hemminger, Steven Rostedt, Sven-Thorsten Dietrich,
Thomas Gleixner
The next idle expiry time record and idle sleeps tracking are
statistics that only concern idle.
Since we want the nohz APIs to become usable further idle
context, let's pull up the handling of these statistics to the
callers in idle.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Alessio Igor Bogani <abogani@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Avi Kivity <avi@redhat.com>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Geoff Levand <geoff@infradead.org>
Cc: Gilad Ben Yossef <gilad@benyossef.com>
Cc: Hakan Akkan <hakanakkan@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Kevin Hilman <khilman@ti.com>
Cc: Max Krasnyansky <maxk@qualcomm.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Sven-Thorsten Dietrich <thebigcorporation@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
kernel/time/tick-sched.c | 24 ++++++++++++++----------
1 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 087833a..12ecce6 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -271,11 +271,11 @@ u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
}
EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us);
-static void tick_nohz_stop_sched_tick(struct tick_sched *ts,
- ktime_t now, int cpu)
+static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,
+ ktime_t now, int cpu)
{
unsigned long seq, last_jiffies, next_jiffies, delta_jiffies;
- ktime_t last_update, expires;
+ ktime_t last_update, expires, ret = { .tv64 = 0 };
struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
u64 time_delta;
@@ -358,6 +358,8 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts,
if (ts->tick_stopped && ktime_equal(expires, dev->next_event))
goto out;
+ ret = expires;
+
/*
* nohz_stop_sched_tick can be called several times before
* the nohz_restart_sched_tick is called. This happens when
@@ -372,11 +374,6 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts,
ts->tick_stopped = 1;
}
- ts->idle_sleeps++;
-
- /* Mark expires */
- ts->idle_expires = expires;
-
/*
* If the expiration time == KTIME_MAX, then
* in this case we simply stop the tick timer.
@@ -407,6 +404,8 @@ out:
ts->next_jiffies = next_jiffies;
ts->last_jiffies = last_jiffies;
ts->sleep_length = ktime_sub(dev->next_event, now);
+
+ return ret;
}
static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
@@ -445,7 +444,7 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
static void __tick_nohz_idle_enter(struct tick_sched *ts)
{
- ktime_t now;
+ ktime_t now, expires;
int cpu = smp_processor_id();
now = tick_nohz_start_idle(cpu, ts);
@@ -454,7 +453,12 @@ static void __tick_nohz_idle_enter(struct tick_sched *ts)
int was_stopped = ts->tick_stopped;
ts->idle_calls++;
- tick_nohz_stop_sched_tick(ts, now, cpu);
+
+ expires = tick_nohz_stop_sched_tick(ts, now, cpu);
+ if (expires.tv64 > 0LL) {
+ ts->idle_sleeps++;
+ ts->idle_expires = expires;
+ }
if (!was_stopped && ts->tick_stopped)
ts->idle_jiffies = ts->last_jiffies;
--
1.7.5.4
^ permalink raw reply related [flat|nested] 7+ messages in thread