forked from Minki/linux
nohz: Introduce arch_needs_cpu
Allow the architecture to request a normal jiffy tick when the system goes idle and tick_nohz_stop_sched_tick is called . On s390 the hook is used to prevent the system going fully idle if there has been an interrupt other than a clock comparator interrupt since the last wakeup. On s390 the HiperSockets response time for 1 connection ping-pong goes down from 42 to 34 microseconds. The CPU cost decreases by 27%. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> LKML-Reference: <20090929122533.402715150@de.ibm.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
eed3b9cf3f
commit
3c5d92a0cf
@ -183,6 +183,7 @@ struct s390_idle_data {
|
||||
unsigned long long idle_count;
|
||||
unsigned long long idle_enter;
|
||||
unsigned long long idle_time;
|
||||
int nohz_delay;
|
||||
};
|
||||
|
||||
DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
|
||||
@ -198,4 +199,11 @@ static inline void s390_idle_check(void)
|
||||
vtime_start_cpu();
|
||||
}
|
||||
|
||||
static inline int s390_nohz_delay(int cpu)
|
||||
{
|
||||
return per_cpu(s390_idle, cpu).nohz_delay != 0;
|
||||
}
|
||||
|
||||
#define arch_needs_cpu(cpu) s390_nohz_delay(cpu)
|
||||
|
||||
#endif /* _S390_CPUTIME_H */
|
||||
|
@ -126,6 +126,8 @@ void __irq_entry do_extint(struct pt_regs *regs, unsigned short code)
|
||||
/* Serve timer interrupts first. */
|
||||
clock_comparator_work();
|
||||
kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
|
||||
if (code != 0x1004)
|
||||
__get_cpu_var(s390_idle).nohz_delay = 1;
|
||||
index = ext_hash(code);
|
||||
for (p = ext_int_hash[index]; p; p = p->next) {
|
||||
if (likely(p->code == code))
|
||||
|
@ -167,6 +167,8 @@ void vtime_stop_cpu(void)
|
||||
/* Wait for external, I/O or machine check interrupt. */
|
||||
psw.mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT;
|
||||
|
||||
idle->nohz_delay = 0;
|
||||
|
||||
/* Check if the CPU timer needs to be reprogrammed. */
|
||||
if (vq->do_spt) {
|
||||
__u64 vmax = VTIMER_MAX_SLICE;
|
||||
|
@ -618,6 +618,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
|
||||
old_regs = set_irq_regs(regs);
|
||||
s390_idle_check();
|
||||
irq_enter();
|
||||
__get_cpu_var(s390_idle).nohz_delay = 1;
|
||||
if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
|
||||
/* Serve timer interrupts first. */
|
||||
clock_comparator_work();
|
||||
|
@ -98,6 +98,9 @@ extern int tick_check_oneshot_change(int allow_nohz);
|
||||
extern struct tick_sched *tick_get_tick_sched(int cpu);
|
||||
extern void tick_check_idle(int cpu);
|
||||
extern int tick_oneshot_mode_active(void);
|
||||
# ifndef arch_needs_cpu
|
||||
# define arch_needs_cpu(cpu) (0)
|
||||
# endif
|
||||
# else
|
||||
static inline void tick_clock_notify(void) { }
|
||||
static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
|
||||
|
@ -264,12 +264,15 @@ void tick_nohz_stop_sched_tick(int inidle)
|
||||
last_jiffies = jiffies;
|
||||
} while (read_seqretry(&xtime_lock, seq));
|
||||
|
||||
/* Get the next timer wheel timer */
|
||||
next_jiffies = get_next_timer_interrupt(last_jiffies);
|
||||
delta_jiffies = next_jiffies - last_jiffies;
|
||||
|
||||
if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu))
|
||||
if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) ||
|
||||
arch_needs_cpu(cpu)) {
|
||||
next_jiffies = last_jiffies + 1;
|
||||
delta_jiffies = 1;
|
||||
} else {
|
||||
/* Get the next timer wheel timer */
|
||||
next_jiffies = get_next_timer_interrupt(last_jiffies);
|
||||
delta_jiffies = next_jiffies - last_jiffies;
|
||||
}
|
||||
/*
|
||||
* Do not stop the tick, if we are only one off
|
||||
* or if the cpu is required for rcu
|
||||
|
Loading…
Reference in New Issue
Block a user