[PATCH 4/5] nohz_full: tracking the full dynticks cpu number

From: Alex Shi
Date: Wed Dec 11 2013 - 05:32:52 EST


This patch try to track the full dynticks cpu number with a global
varible nr_nohz_busy_cpus.

When ts->tick_stopped and !ts->inidle, it is time for full dyntick.
To achieve this, the ts->inidle = 0 was delayed in tick_nohz_idle_exit
safely.

But the patch failed, it may increases 2 or 3 times continuously without
a decrease. so nr_nohz_busy_cpus increased to 28 in 7200 seconds. :(

---
include/linux/tick.h | 3 +++
kernel/time/tick-sched.c | 19 +++++++++++++++++--
2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/include/linux/tick.h b/include/linux/tick.h
index 5128d33..3784f9f 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -161,6 +161,7 @@ static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; }

#ifdef CONFIG_NO_HZ_FULL
extern bool tick_nohz_full_running;
+extern atomic_t nr_nohz_busy_cpus;
extern cpumask_var_t tick_nohz_full_mask;

static inline bool tick_nohz_full_enabled(void)
@@ -184,6 +185,7 @@ extern void __tick_nohz_full_check(void);
extern void tick_nohz_full_kick(void);
extern void tick_nohz_full_kick_all(void);
extern void __tick_nohz_task_switch(struct task_struct *tsk);
+extern bool has_nohz_busy_cpus(void);
#else
static inline void tick_nohz_init(void) { }
static inline bool tick_nohz_full_enabled(void) { return false; }
@@ -192,6 +194,7 @@ static inline void __tick_nohz_full_check(void) { }
static inline void tick_nohz_full_kick(void) { }
static inline void tick_nohz_full_kick_all(void) { }
static inline void __tick_nohz_task_switch(struct task_struct *tsk) { }
+static inline bool has_nohz_busy_cpus(void) { return true; }
#endif

static inline void tick_nohz_full_check(void)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index b55d1c0..37f2784 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -148,9 +148,13 @@ static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
profile_tick(CPU_PROFILING);
}

+atomic_t nr_nohz_busy_cpus = ATOMIC_INIT(0);
#ifdef CONFIG_NO_HZ_FULL
cpumask_var_t tick_nohz_full_mask;
bool tick_nohz_full_running;
+inline bool has_nohz_busy_cpus(void) {
+ return !!atomic_read(&nr_nohz_busy_cpus);
+}

static bool can_stop_full_tick(void)
{
@@ -642,6 +646,11 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,
ts->last_tick = hrtimer_get_expires(&ts->sched_timer);
ts->tick_stopped = 1;
trace_tick_stop(1, " ");
+ if (!ts->inidle) {
+ if (atomic_inc_return(&nr_nohz_busy_cpus) != 1) {
+ printk(KERN_ERR "inc cpu %d as %d\n", cpu, test);
+ }
+ }
}

/*
@@ -881,6 +890,12 @@ static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
ts->tick_stopped = 0;
ts->idle_exittime = now;

+ if (!ts->inidle) {
+ if (atomic_dec_return(&nr_nohz_busy_cpus)) {
+ printk(KERN_ERR "dec cpu %d to %d\n",
+ smp_processor_id(), atomic_read(&nr_nohz_busy_cpus));
+ }
+ }
tick_nohz_restart(ts, now);
}

@@ -922,8 +937,6 @@ void tick_nohz_idle_exit(void)

WARN_ON_ONCE(!ts->inidle);

- ts->inidle = 0;
-
if (ts->idle_active || ts->tick_stopped)
now = ktime_get();

@@ -935,6 +948,8 @@ void tick_nohz_idle_exit(void)
tick_nohz_account_idle_ticks(ts);
}

+ ts->inidle = 0;
+
local_irq_enable();
}
EXPORT_SYMBOL_GPL(tick_nohz_idle_exit);
--
1.8.1.2

--
Thanks
Alex
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/