perf_counter: x86: self-IPI for pending work
Implement set_perf_counter_pending() with a self-IPI so that it will run ASAP in a usable context. For now use a second IRQ vector, because the primary vector pokes the apic in funny ways that seem to confuse things. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> LKML-Reference: <20090406094517.724626696@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Šī revīzija ir iekļauta:

revīziju iesūtīja
Ingo Molnar

vecāks
671dec5daf
revīzija
b6276f353b
@@ -849,6 +849,20 @@ void smp_perf_counter_interrupt(struct pt_regs *regs)
|
||||
irq_exit();
|
||||
}
|
||||
|
||||
void smp_perf_pending_interrupt(struct pt_regs *regs)
|
||||
{
|
||||
irq_enter();
|
||||
ack_APIC_irq();
|
||||
inc_irq_stat(apic_pending_irqs);
|
||||
perf_counter_do_pending();
|
||||
irq_exit();
|
||||
}
|
||||
|
||||
void set_perf_counter_pending(void)
|
||||
{
|
||||
apic->send_IPI_self(LOCAL_PENDING_VECTOR);
|
||||
}
|
||||
|
||||
void perf_counters_lapic_init(int nmi)
|
||||
{
|
||||
u32 apic_val;
|
||||
|
@@ -1028,6 +1028,8 @@ apicinterrupt SPURIOUS_APIC_VECTOR \
|
||||
#ifdef CONFIG_PERF_COUNTERS
|
||||
apicinterrupt LOCAL_PERF_VECTOR \
|
||||
perf_counter_interrupt smp_perf_counter_interrupt
|
||||
apicinterrupt LOCAL_PENDING_VECTOR \
|
||||
perf_pending_interrupt smp_perf_pending_interrupt
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@@ -67,6 +67,10 @@ static int show_other_interrupts(struct seq_file *p, int prec)
|
||||
for_each_online_cpu(j)
|
||||
seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs);
|
||||
seq_printf(p, " Performance counter interrupts\n");
|
||||
seq_printf(p, "PND: ");
|
||||
for_each_online_cpu(j)
|
||||
seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs);
|
||||
seq_printf(p, " Performance pending work\n");
|
||||
#endif
|
||||
if (generic_interrupt_extension) {
|
||||
seq_printf(p, "PLT: ");
|
||||
@@ -171,6 +175,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
|
||||
sum += irq_stats(cpu)->apic_timer_irqs;
|
||||
sum += irq_stats(cpu)->irq_spurious_count;
|
||||
sum += irq_stats(cpu)->apic_perf_irqs;
|
||||
sum += irq_stats(cpu)->apic_pending_irqs;
|
||||
#endif
|
||||
if (generic_interrupt_extension)
|
||||
sum += irq_stats(cpu)->generic_irqs;
|
||||
|
@@ -166,6 +166,7 @@ static void __init apic_intr_init(void)
|
||||
alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
|
||||
# ifdef CONFIG_PERF_COUNTERS
|
||||
alloc_intr_gate(LOCAL_PERF_VECTOR, perf_counter_interrupt);
|
||||
alloc_intr_gate(LOCAL_PENDING_VECTOR, perf_pending_interrupt);
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_X86_MCE_P4THERMAL
|
||||
|
@@ -156,6 +156,7 @@ static void __init apic_intr_init(void)
|
||||
/* Performance monitoring interrupt: */
|
||||
#ifdef CONFIG_PERF_COUNTERS
|
||||
alloc_intr_gate(LOCAL_PERF_VECTOR, perf_counter_interrupt);
|
||||
alloc_intr_gate(LOCAL_PENDING_VECTOR, perf_pending_interrupt);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Atsaukties uz šo jaunā problēmā
Block a user