]>
Commit | Line | Data |
---|---|---|
8de80845 GKH |
1 | From 3c5d92a0cfb5103c0d5ab74d4ae6373d3af38148 Mon Sep 17 00:00:00 2001 |
2 | From: Martin Schwidefsky <schwidefsky@de.ibm.com> | |
3 | Date: Tue, 29 Sep 2009 14:25:16 +0200 | |
4 | Subject: nohz: Introduce arch_needs_cpu | |
5 | ||
6 | From: Martin Schwidefsky <schwidefsky@de.ibm.com> | |
7 | ||
8 | commit 3c5d92a0cfb5103c0d5ab74d4ae6373d3af38148 upstream. | |
9 | ||
10 | Allow the architecture to request a normal jiffy tick when the system | |
11 | goes idle and tick_nohz_stop_sched_tick is called . On s390 the hook is | |
12 | used to prevent the system going fully idle if there has been an | |
13 | interrupt other than a clock comparator interrupt since the last wakeup. | |
14 | ||
15 | On s390 the HiperSockets response time for 1 connection ping-pong goes | |
16 | down from 42 to 34 microseconds. The CPU cost decreases by 27%. | |
17 | ||
18 | Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> | |
19 | LKML-Reference: <20090929122533.402715150@de.ibm.com> | |
20 | Signed-off-by: Thomas Gleixner <tglx@linutronix.de> | |
21 | Acked-by: John Jolly <jjolly@suse.de> | |
22 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
23 | ||
24 | --- | |
25 | arch/s390/include/asm/cputime.h | 8 ++++++++ | |
26 | arch/s390/kernel/s390_ext.c | 2 ++ | |
27 | arch/s390/kernel/vtime.c | 2 ++ | |
28 | drivers/s390/cio/cio.c | 1 + | |
29 | include/linux/tick.h | 3 +++ | |
30 | kernel/time/tick-sched.c | 13 ++++++++----- | |
31 | 6 files changed, 24 insertions(+), 5 deletions(-) | |
32 | ||
33 | --- a/arch/s390/include/asm/cputime.h | |
34 | +++ b/arch/s390/include/asm/cputime.h | |
35 | @@ -183,6 +183,7 @@ struct s390_idle_data { | |
36 | unsigned long long idle_count; | |
37 | unsigned long long idle_enter; | |
38 | unsigned long long idle_time; | |
39 | + int nohz_delay; | |
40 | }; | |
41 | ||
42 | DECLARE_PER_CPU(struct s390_idle_data, s390_idle); | |
43 | @@ -198,4 +199,11 @@ static inline void s390_idle_check(void) | |
44 | vtime_start_cpu(); | |
45 | } | |
46 | ||
47 | +static inline int s390_nohz_delay(int cpu) | |
48 | +{ | |
49 | + return per_cpu(s390_idle, cpu).nohz_delay != 0; | |
50 | +} | |
51 | + | |
52 | +#define arch_needs_cpu(cpu) s390_nohz_delay(cpu) | |
53 | + | |
54 | #endif /* _S390_CPUTIME_H */ | |
55 | --- a/arch/s390/kernel/s390_ext.c | |
56 | +++ b/arch/s390/kernel/s390_ext.c | |
57 | @@ -126,6 +126,8 @@ void __irq_entry do_extint(struct pt_reg | |
58 | /* Serve timer interrupts first. */ | |
59 | clock_comparator_work(); | |
60 | kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; | |
61 | + if (code != 0x1004) | |
62 | + __get_cpu_var(s390_idle).nohz_delay = 1; | |
63 | index = ext_hash(code); | |
64 | for (p = ext_int_hash[index]; p; p = p->next) { | |
65 | if (likely(p->code == code)) | |
66 | --- a/arch/s390/kernel/vtime.c | |
67 | +++ b/arch/s390/kernel/vtime.c | |
68 | @@ -167,6 +167,8 @@ void vtime_stop_cpu(void) | |
69 | /* Wait for external, I/O or machine check interrupt. */ | |
70 | psw.mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT; | |
71 | ||
72 | + idle->nohz_delay = 0; | |
73 | + | |
74 | /* Check if the CPU timer needs to be reprogrammed. */ | |
75 | if (vq->do_spt) { | |
76 | __u64 vmax = VTIMER_MAX_SLICE; | |
77 | --- a/drivers/s390/cio/cio.c | |
78 | +++ b/drivers/s390/cio/cio.c | |
79 | @@ -618,6 +618,7 @@ void __irq_entry do_IRQ(struct pt_regs * | |
80 | old_regs = set_irq_regs(regs); | |
81 | s390_idle_check(); | |
82 | irq_enter(); | |
83 | + __get_cpu_var(s390_idle).nohz_delay = 1; | |
84 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) | |
85 | /* Serve timer interrupts first. */ | |
86 | clock_comparator_work(); | |
87 | --- a/include/linux/tick.h | |
88 | +++ b/include/linux/tick.h | |
89 | @@ -98,6 +98,9 @@ extern int tick_check_oneshot_change(int | |
90 | extern struct tick_sched *tick_get_tick_sched(int cpu); | |
91 | extern void tick_check_idle(int cpu); | |
92 | extern int tick_oneshot_mode_active(void); | |
93 | +# ifndef arch_needs_cpu | |
94 | +# define arch_needs_cpu(cpu) (0) | |
95 | +# endif | |
96 | # else | |
97 | static inline void tick_clock_notify(void) { } | |
98 | static inline int tick_check_oneshot_change(int allow_nohz) { return 0; } | |
99 | --- a/kernel/time/tick-sched.c | |
100 | +++ b/kernel/time/tick-sched.c | |
101 | @@ -289,12 +289,15 @@ void tick_nohz_stop_sched_tick(int inidl | |
102 | time_delta = KTIME_MAX; | |
103 | } while (read_seqretry(&xtime_lock, seq)); | |
104 | ||
105 | - /* Get the next timer wheel timer */ | |
106 | - next_jiffies = get_next_timer_interrupt(last_jiffies); | |
107 | - delta_jiffies = next_jiffies - last_jiffies; | |
108 | - | |
109 | - if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu)) | |
110 | + if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) || | |
111 | + arch_needs_cpu(cpu)) { | |
112 | + next_jiffies = last_jiffies + 1; | |
113 | delta_jiffies = 1; | |
114 | + } else { | |
115 | + /* Get the next timer wheel timer */ | |
116 | + next_jiffies = get_next_timer_interrupt(last_jiffies); | |
117 | + delta_jiffies = next_jiffies - last_jiffies; | |
118 | + } | |
119 | /* | |
120 | * Do not stop the tick, if we are only one off | |
121 | * or if the cpu is required for rcu |