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
This commit is contained in:
Martin Stein 2014-03-11 12:53:42 +01:00 committed by Norman Feske
parent 852785324f
commit 18cee192e2
2 changed files with 35 additions and 15 deletions

View File

@ -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;
}
}

View File

@ -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 **