aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-07-31 04:27:19 -0400
committerIngo Molnar <mingo@kernel.org>2015-07-31 04:28:53 -0400
commit555ee95a0a5a525ad2f1654fab0bd157de832b4f (patch)
tree5ff341bedaa848027d5eba1e2a9fbfaeb9501250
parent8400935737bf02d97da281bdcd139a421624b6ba (diff)
parentde734f89b67c2df30e35a09e7e56a3659e5b6ac6 (diff)
Merge branch 'timers/nohz-for-tip' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks into timers/nohz
Pull NOHZ updates from Frederic Weisbecker: - Fix some jiffies based cputime assumptions. No real harm because the concerned code isn't used by full dynticks. - Simplify jiffies <-> usecs conversions. Remove dead code. - Remove early hacks on nohz full code that avoided messing up idle nohz internals. Now nohz integrates well full and idle and such hack have become needless. - Restart nohz full tick from irq exit. A simplification and a preparation for future optimization on scheduler kick to nohz full. - Simple code cleanups. - Tile driver isolation enhancement on top of nohz. Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/alpha/kernel/osf_sys.c13
-rw-r--r--arch/x86/kernel/apm_32.c2
-rw-r--r--drivers/net/ethernet/tile/tilegx.c4
-rw-r--r--include/linux/jiffies.h9
-rw-r--r--include/linux/tick.h25
-rw-r--r--kernel/sched/core.c2
-rw-r--r--kernel/time/tick-sched.c72
-rw-r--r--kernel/time/time.c10
8 files changed, 62 insertions, 75 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 36dc91ace83a..6cc08166ff00 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -1138,6 +1138,7 @@ SYSCALL_DEFINE2(osf_getrusage, int, who, struct rusage32 __user *, ru)
1138{ 1138{
1139 struct rusage32 r; 1139 struct rusage32 r;
1140 cputime_t utime, stime; 1140 cputime_t utime, stime;
1141 unsigned long utime_jiffies, stime_jiffies;
1141 1142
1142 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN) 1143 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
1143 return -EINVAL; 1144 return -EINVAL;
@@ -1146,14 +1147,18 @@ SYSCALL_DEFINE2(osf_getrusage, int, who, struct rusage32 __user *, ru)
1146 switch (who) { 1147 switch (who) {
1147 case RUSAGE_SELF: 1148 case RUSAGE_SELF:
1148 task_cputime(current, &utime, &stime); 1149 task_cputime(current, &utime, &stime);
1149 jiffies_to_timeval32(utime, &r.ru_utime); 1150 utime_jiffies = cputime_to_jiffies(utime);
1150 jiffies_to_timeval32(stime, &r.ru_stime); 1151 stime_jiffies = cputime_to_jiffies(stime);
1152 jiffies_to_timeval32(utime_jiffies, &r.ru_utime);
1153 jiffies_to_timeval32(stime_jiffies, &r.ru_stime);
1151 r.ru_minflt = current->min_flt; 1154 r.ru_minflt = current->min_flt;
1152 r.ru_majflt = current->maj_flt; 1155 r.ru_majflt = current->maj_flt;
1153 break; 1156 break;
1154 case RUSAGE_CHILDREN: 1157 case RUSAGE_CHILDREN:
1155 jiffies_to_timeval32(current->signal->cutime, &r.ru_utime); 1158 utime_jiffies = cputime_to_jiffies(current->signal->cutime);
1156 jiffies_to_timeval32(current->signal->cstime, &r.ru_stime); 1159 stime_jiffies = cputime_to_jiffies(current->signal->cstime);
1160 jiffies_to_timeval32(utime_jiffies, &r.ru_utime);
1161 jiffies_to_timeval32(stime_jiffies, &r.ru_stime);
1157 r.ru_minflt = current->signal->cmin_flt; 1162 r.ru_minflt = current->signal->cmin_flt;
1158 r.ru_majflt = current->signal->cmaj_flt; 1163 r.ru_majflt = current->signal->cmaj_flt;
1159 break; 1164 break;
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 927ec9235947..052c9c3026cc 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -919,7 +919,7 @@ recalc:
919 } else if (jiffies_since_last_check > idle_period) { 919 } else if (jiffies_since_last_check > idle_period) {
920 unsigned int idle_percentage; 920 unsigned int idle_percentage;
921 921
922 idle_percentage = stime - last_stime; 922 idle_percentage = cputime_to_jiffies(stime - last_stime);
923 idle_percentage *= 100; 923 idle_percentage *= 100;
924 idle_percentage /= jiffies_since_last_check; 924 idle_percentage /= jiffies_since_last_check;
925 use_apm_idle = (idle_percentage > idle_threshold); 925 use_apm_idle = (idle_percentage > idle_threshold);
diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c
index a3f7610002aa..0a15acc075b3 100644
--- a/drivers/net/ethernet/tile/tilegx.c
+++ b/drivers/net/ethernet/tile/tilegx.c
@@ -40,6 +40,7 @@
40#include <linux/tcp.h> 40#include <linux/tcp.h>
41#include <linux/net_tstamp.h> 41#include <linux/net_tstamp.h>
42#include <linux/ptp_clock_kernel.h> 42#include <linux/ptp_clock_kernel.h>
43#include <linux/tick.h>
43 44
44#include <asm/checksum.h> 45#include <asm/checksum.h>
45#include <asm/homecache.h> 46#include <asm/homecache.h>
@@ -2273,7 +2274,8 @@ static int __init tile_net_init_module(void)
2273 tile_net_dev_init(name, mac); 2274 tile_net_dev_init(name, mac);
2274 2275
2275 if (!network_cpus_init()) 2276 if (!network_cpus_init())
2276 network_cpus_map = *cpu_online_mask; 2277 cpumask_and(&network_cpus_map, housekeeping_cpumask(),
2278 cpu_online_mask);
2277 2279
2278 return 0; 2280 return 0;
2279} 2281}
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 535fd3bb1ba8..7c6febede6ba 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -363,18 +363,11 @@ static inline unsigned long msecs_to_jiffies(const unsigned int m)
363} 363}
364 364
365extern unsigned long __usecs_to_jiffies(const unsigned int u); 365extern unsigned long __usecs_to_jiffies(const unsigned int u);
366#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ) 366#if !(USEC_PER_SEC % HZ)
367static inline unsigned long _usecs_to_jiffies(const unsigned int u) 367static inline unsigned long _usecs_to_jiffies(const unsigned int u)
368{ 368{
369 return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ); 369 return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ);
370} 370}
371#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
372static inline unsigned long _usecs_to_jiffies(const unsigned int u)
373{
374 return u * (HZ / USEC_PER_SEC);
375}
376static inline unsigned long _usecs_to_jiffies(const unsigned int u)
377{
378#else 371#else
379static inline unsigned long _usecs_to_jiffies(const unsigned int u) 372static inline unsigned long _usecs_to_jiffies(const unsigned int u)
380{ 373{
diff --git a/include/linux/tick.h b/include/linux/tick.h
index edbfc9a5293e..48d901f83f92 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -147,22 +147,29 @@ static inline void tick_nohz_full_add_cpus_to(struct cpumask *mask)
147 cpumask_or(mask, mask, tick_nohz_full_mask); 147 cpumask_or(mask, mask, tick_nohz_full_mask);
148} 148}
149 149
150extern void __tick_nohz_full_check(void);
151extern void tick_nohz_full_kick(void); 150extern void tick_nohz_full_kick(void);
152extern void tick_nohz_full_kick_cpu(int cpu); 151extern void tick_nohz_full_kick_cpu(int cpu);
153extern void tick_nohz_full_kick_all(void); 152extern void tick_nohz_full_kick_all(void);
154extern void __tick_nohz_task_switch(struct task_struct *tsk); 153extern void __tick_nohz_task_switch(void);
155#else 154#else
156static inline bool tick_nohz_full_enabled(void) { return false; } 155static inline bool tick_nohz_full_enabled(void) { return false; }
157static inline bool tick_nohz_full_cpu(int cpu) { return false; } 156static inline bool tick_nohz_full_cpu(int cpu) { return false; }
158static inline void tick_nohz_full_add_cpus_to(struct cpumask *mask) { } 157static inline void tick_nohz_full_add_cpus_to(struct cpumask *mask) { }
159static inline void __tick_nohz_full_check(void) { }
160static inline void tick_nohz_full_kick_cpu(int cpu) { } 158static inline void tick_nohz_full_kick_cpu(int cpu) { }
161static inline void tick_nohz_full_kick(void) { } 159static inline void tick_nohz_full_kick(void) { }
162static inline void tick_nohz_full_kick_all(void) { } 160static inline void tick_nohz_full_kick_all(void) { }
163static inline void __tick_nohz_task_switch(struct task_struct *tsk) { } 161static inline void __tick_nohz_task_switch(void) { }
164#endif 162#endif
165 163
164static inline const struct cpumask *housekeeping_cpumask(void)
165{
166#ifdef CONFIG_NO_HZ_FULL
167 if (tick_nohz_full_enabled())
168 return housekeeping_mask;
169#endif
170 return cpu_possible_mask;
171}
172
166static inline bool is_housekeeping_cpu(int cpu) 173static inline bool is_housekeeping_cpu(int cpu)
167{ 174{
168#ifdef CONFIG_NO_HZ_FULL 175#ifdef CONFIG_NO_HZ_FULL
@@ -181,16 +188,10 @@ static inline void housekeeping_affine(struct task_struct *t)
181#endif 188#endif
182} 189}
183 190
184static inline void tick_nohz_full_check(void) 191static inline void tick_nohz_task_switch(void)
185{
186 if (tick_nohz_full_enabled())
187 __tick_nohz_full_check();
188}
189
190static inline void tick_nohz_task_switch(struct task_struct *tsk)
191{ 192{
192 if (tick_nohz_full_enabled()) 193 if (tick_nohz_full_enabled())
193 __tick_nohz_task_switch(tsk); 194 __tick_nohz_task_switch();
194} 195}
195 196
196#endif 197#endif
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 78b4bad10081..4d34035bb3ee 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2489,7 +2489,7 @@ static struct rq *finish_task_switch(struct task_struct *prev)
2489 put_task_struct(prev); 2489 put_task_struct(prev);
2490 } 2490 }
2491 2491
2492 tick_nohz_task_switch(current); 2492 tick_nohz_task_switch();
2493 return rq; 2493 return rq;
2494} 2494}
2495 2495
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index c792429e98c6..3319e16f31e5 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -197,27 +197,9 @@ static bool can_stop_full_tick(void)
197 return true; 197 return true;
198} 198}
199 199
200static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now);
201
202/*
203 * Re-evaluate the need for the tick on the current CPU
204 * and restart it if necessary.
205 */
206void __tick_nohz_full_check(void)
207{
208 struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
209
210 if (tick_nohz_full_cpu(smp_processor_id())) {
211 if (ts->tick_stopped && !is_idle_task(current)) {
212 if (!can_stop_full_tick())
213 tick_nohz_restart_sched_tick(ts, ktime_get());
214 }
215 }
216}
217
218static void nohz_full_kick_work_func(struct irq_work *work) 200static void nohz_full_kick_work_func(struct irq_work *work)
219{ 201{
220 __tick_nohz_full_check(); 202 /* Empty, the tick restart happens on tick_nohz_irq_exit() */
221} 203}
222 204
223static DEFINE_PER_CPU(struct irq_work, nohz_full_kick_work) = { 205static DEFINE_PER_CPU(struct irq_work, nohz_full_kick_work) = {
@@ -252,7 +234,7 @@ void tick_nohz_full_kick_cpu(int cpu)
252 234
253static void nohz_full_kick_ipi(void *info) 235static void nohz_full_kick_ipi(void *info)
254{ 236{
255 __tick_nohz_full_check(); 237 /* Empty, the tick restart happens on tick_nohz_irq_exit() */
256} 238}
257 239
258/* 240/*
@@ -276,7 +258,7 @@ void tick_nohz_full_kick_all(void)
276 * It might need the tick due to per task/process properties: 258 * It might need the tick due to per task/process properties:
277 * perf events, posix cpu timers, ... 259 * perf events, posix cpu timers, ...
278 */ 260 */
279void __tick_nohz_task_switch(struct task_struct *tsk) 261void __tick_nohz_task_switch(void)
280{ 262{
281 unsigned long flags; 263 unsigned long flags;
282 264
@@ -705,21 +687,38 @@ out:
705 return tick; 687 return tick;
706} 688}
707 689
708static void tick_nohz_full_stop_tick(struct tick_sched *ts) 690static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
691{
692 /* Update jiffies first */
693 tick_do_update_jiffies64(now);
694 update_cpu_load_nohz();
695
696 calc_load_exit_idle();
697 touch_softlockup_watchdog();
698 /*
699 * Cancel the scheduled timer and restore the tick
700 */
701 ts->tick_stopped = 0;
702 ts->idle_exittime = now;
703
704 tick_nohz_restart(ts, now);
705}
706
707static void tick_nohz_full_update_tick(struct tick_sched *ts)
709{ 708{
710#ifdef CONFIG_NO_HZ_FULL 709#ifdef CONFIG_NO_HZ_FULL
711 int cpu = smp_processor_id(); 710 int cpu = smp_processor_id();
712 711
713 if (!tick_nohz_full_cpu(cpu) || is_idle_task(current)) 712 if (!tick_nohz_full_cpu(cpu))
714 return; 713 return;
715 714
716 if (!ts->tick_stopped && ts->nohz_mode == NOHZ_MODE_INACTIVE) 715 if (!ts->tick_stopped && ts->nohz_mode == NOHZ_MODE_INACTIVE)
717 return; 716 return;
718 717
719 if (!can_stop_full_tick()) 718 if (can_stop_full_tick())
720 return; 719 tick_nohz_stop_sched_tick(ts, ktime_get(), cpu);
721 720 else if (ts->tick_stopped)
722 tick_nohz_stop_sched_tick(ts, ktime_get(), cpu); 721 tick_nohz_restart_sched_tick(ts, ktime_get());
723#endif 722#endif
724} 723}
725 724
@@ -849,7 +848,7 @@ void tick_nohz_irq_exit(void)
849 if (ts->inidle) 848 if (ts->inidle)
850 __tick_nohz_idle_enter(ts); 849 __tick_nohz_idle_enter(ts);
851 else 850 else
852 tick_nohz_full_stop_tick(ts); 851 tick_nohz_full_update_tick(ts);
853} 852}
854 853
855/** 854/**
@@ -864,23 +863,6 @@ ktime_t tick_nohz_get_sleep_length(void)
864 return ts->sleep_length; 863 return ts->sleep_length;
865} 864}
866 865
867static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
868{
869 /* Update jiffies first */
870 tick_do_update_jiffies64(now);
871 update_cpu_load_nohz();
872
873 calc_load_exit_idle();
874 touch_softlockup_watchdog();
875 /*
876 * Cancel the scheduled timer and restore the tick
877 */
878 ts->tick_stopped = 0;
879 ts->idle_exittime = now;
880
881 tick_nohz_restart(ts, now);
882}
883
884static void tick_nohz_account_idle_ticks(struct tick_sched *ts) 866static void tick_nohz_account_idle_ticks(struct tick_sched *ts)
885{ 867{
886#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE 868#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
diff --git a/kernel/time/time.c b/kernel/time/time.c
index 85d5bb1d67eb..ad1bf23e6eb7 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -268,10 +268,14 @@ EXPORT_SYMBOL(jiffies_to_msecs);
268 268
269unsigned int jiffies_to_usecs(const unsigned long j) 269unsigned int jiffies_to_usecs(const unsigned long j)
270{ 270{
271#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ) 271 /*
272 * Hz usually doesn't go much further MSEC_PER_SEC.
273 * jiffies_to_usecs() and usecs_to_jiffies() depend on that.
274 */
275 BUILD_BUG_ON(HZ > USEC_PER_SEC);
276
277#if !(USEC_PER_SEC % HZ)
272 return (USEC_PER_SEC / HZ) * j; 278 return (USEC_PER_SEC / HZ) * j;
273#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
274 return (j + (HZ / USEC_PER_SEC) - 1)/(HZ / USEC_PER_SEC);
275#else 279#else
276# if BITS_PER_LONG == 32 280# if BITS_PER_LONG == 32
277 return (HZ_TO_USEC_MUL32 * j) >> HZ_TO_USEC_SHR32; 281 return (HZ_TO_USEC_MUL32 * j) >> HZ_TO_USEC_SHR32;