From 18cee192e20bc0b62fd181d0353ff71df86fb9e0 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Tue, 11 Mar 2014 12:53:42 +0100 Subject: [PATCH] hw: don't do redundant inter-processor interrupts At least with the ARM generic interrupt controller, inter-processor interrupts are edge triggered and banked for all source processors. Thus it might be possible that such an interrupt gets triggered redundantly until the targeted processor is able to grab the kernel lock. As we're only interested in making a processor recognize accumulative updates to its scheduler, we can omit further interrupts if there is one pending already at the targeted processor. ref #1088 --- base-hw/src/core/kernel/processor.cc | 26 ++++++++++++-------------- base-hw/src/core/kernel/processor.h | 24 +++++++++++++++++++++++- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/base-hw/src/core/kernel/processor.cc b/base-hw/src/core/kernel/processor.cc index 38fad9e099..d1a2361391 100644 --- a/base-hw/src/core/kernel/processor.cc +++ b/base-hw/src/core/kernel/processor.cc @@ -42,12 +42,7 @@ void Kernel::Processor_client::_interrupt(unsigned const processor_id) /* check wether the interrupt is our inter-processor interrupt */ } else if (ic->is_ip_interrupt(irq_id, processor_id)) { - /* - * This interrupt solely denotes that another processor has - * modified the scheduling plan of this processor and thus - * a more prior user context than the current one might be - * available. - */ + __processor->ip_interrupt(); /* after all it must be a user interrupt */ } else { @@ -61,15 +56,18 @@ void Kernel::Processor_client::_interrupt(unsigned const processor_id) } -void Kernel::Processor_client::_schedule() -{ - /* schedule thread */ - __processor->scheduler()->insert(this); +void Kernel::Processor_client::_schedule() { __processor->schedule(this); } - /* let processor of the scheduled thread notice the change immediately */ - unsigned const processor_id = __processor->id(); - if (processor_id != Processor::executing_id()) { - pic()->trigger_ip_interrupt(processor_id); + +void Kernel::Processor::schedule(Processor_client * const client) +{ + /* schedule processor client */ + _scheduler.insert(client); + + /* let the processor notice the change immediately */ + if (_id != executing_id() && !_ip_interrupt_pending) { + pic()->trigger_ip_interrupt(_id); + _ip_interrupt_pending = true; } } diff --git a/base-hw/src/core/kernel/processor.h b/base-hw/src/core/kernel/processor.h index c587763a40..7c7aa7a305 100644 --- a/base-hw/src/core/kernel/processor.h +++ b/base-hw/src/core/kernel/processor.h @@ -120,6 +120,7 @@ class Kernel::Processor : public Processor_driver unsigned const _id; Processor_scheduler _scheduler; + bool _ip_interrupt_pending; public: @@ -131,9 +132,30 @@ class Kernel::Processor : public Processor_driver */ Processor(unsigned const id, Processor_client * const idle_client) : - _id(id), _scheduler(idle_client) + _id(id), _scheduler(idle_client), _ip_interrupt_pending(false) { } + /** + * Notice that the inter-processor interrupt isn't pending anymore + */ + void ip_interrupt() + { + /* + * This interrupt solely denotes that another processor has + * modified the scheduling plan of this processor and thus + * a more prior user context than the current one might be + * available. + */ + _ip_interrupt_pending = false; + } + + /** + * Add a processor client to the scheduling plan of the processor + * + * \param client targeted client + */ + void schedule(Processor_client * const client); + /*************** ** Accessors **