hw: inter-processor interrupt on remote scheduling

ref 
This commit is contained in:
Martin Stein 2014-03-10 15:37:20 +01:00 committed by Norman Feske
parent 044a109c3a
commit a8d071b372
5 changed files with 129 additions and 7 deletions
base-hw/src/core

View File

@ -200,6 +200,25 @@ namespace Imx53
if (i <= MAX_INTERRUPT_ID)
write<Enclear::Clear_enable>(1, i);
}
/**
* Wether an interrupt is inter-processor interrupt of a processor
*
* \param interrupt_id kernel name of the interrupt
* \param processor_id kernel name of the processor
*/
bool is_ip_interrupt(unsigned const interrupt_id,
unsigned const processor_id)
{
return false;
}
/**
* Trigger the inter-processor interrupt of a processor
*
* \param processor_id kernel name of the processor
*/
void trigger_ip_interrupt(unsigned const processor_id) { }
};
}

View File

@ -30,14 +30,26 @@ void Kernel::Execution_context::_interrupt(unsigned const processor_id)
{
/* determine handling for specific interrupt */
unsigned irq_id;
if (pic()->take_request(irq_id))
Pic * const ic = pic();
if (ic->take_request(irq_id))
{
/* check wether the interrupt is a scheduling timeout */
if (timer()->interrupt_id(processor_id) == irq_id)
{
/* handle scheduling timeout */
/* check wether the interrupt is a processor-scheduling timeout */
if (timer()->interrupt_id(processor_id) == irq_id) {
__processor->scheduler()->yield_occupation();
timer()->clear_interrupt(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.
*/
/* after all it must be a user interrupt */
} else {
/* try to inform the user interrupt-handler */
@ -45,23 +57,32 @@ void Kernel::Execution_context::_interrupt(unsigned const processor_id)
}
}
/* end interrupt request at controller */
pic()->finish_request();
ic->finish_request();
}
void Kernel::Execution_context::_schedule()
{
/* schedule thread */
__processor->scheduler()->insert(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::Execution_context::_unschedule()
{
assert(__processor->id() == Processor::executing_id());
__processor->scheduler()->remove(this);
}
void Kernel::Execution_context::_yield()
{
assert(__processor->id() == Processor::executing_id());
__processor->scheduler()->yield_occupation();
}

View File

@ -127,6 +127,15 @@ class Arm_gic::Pic
struct Edge_triggered : Bitfield<1, 1> { };
};
/**
* Software generated interrupt register
*/
struct Sgir : Register<0xf00, 32>
{
struct Sgi_int_id : Bitfield<0, 4> { };
struct Cpu_target_list : Bitfield<16, 8> { };
};
/**
* Minimum supported interrupt priority
*/
@ -201,7 +210,6 @@ class Arm_gic::Pic
struct Iar : Register<0x0c, 32, true>
{
struct Irq_id : Bitfield<0,10> { };
struct Cpu_id : Bitfield<10,3> { };
};
/**
@ -222,6 +230,16 @@ class Arm_gic::Pic
*/
inline static bool _use_security_ext();
/**
* Return inter-processor interrupt of a specific processor
*
* \param processor_id kernel name of targeted processor
*/
unsigned _ip_interrupt(unsigned const processor_id) const
{
return processor_id + 1;
}
public:
/**
@ -337,6 +355,32 @@ class Arm_gic::Pic
{
_distr.write<Distr::Icenabler::Clear_enable>(1, interrupt_id);
}
/**
* Wether an interrupt is inter-processor interrupt of a processor
*
* \param interrupt_id kernel name of the interrupt
* \param processor_id kernel name of the processor
*/
bool is_ip_interrupt(unsigned const interrupt_id,
unsigned const processor_id)
{
return interrupt_id == _ip_interrupt(processor_id);
}
/**
* Trigger the inter-processor interrupt of a processor
*
* \param processor_id kernel name of the processor
*/
void trigger_ip_interrupt(unsigned const processor_id)
{
typedef Distr::Sgir Sgir;
Sgir::access_t sgir = 0;
Sgir::Sgi_int_id::set(sgir, _ip_interrupt(processor_id));
Sgir::Cpu_target_list::set(sgir, 1 << processor_id);
_distr.write<Sgir>(sgir);
}
};
#endif /* _PIC__ARM_GIC_H_ */

View File

@ -203,6 +203,25 @@ namespace Imx31
*/
void mask(unsigned const i) {
if (i <= MAX_INTERRUPT_ID) write<Intdisnum>(i); }
/**
* Wether an interrupt is inter-processor interrupt of a processor
*
* \param interrupt_id kernel name of the interrupt
* \param processor_id kernel name of the processor
*/
bool is_ip_interrupt(unsigned const interrupt_id,
unsigned const processor_id)
{
return false;
}
/**
* Trigger the inter-processor interrupt of a processor
*
* \param processor_id kernel name of the processor
*/
void trigger_ip_interrupt(unsigned const processor_id) { }
};
}

View File

@ -117,6 +117,25 @@ namespace Kernel
else
write<Irq_disable_gpu_2>(1 << (i - 8 - 32));
}
/**
* Wether an interrupt is inter-processor interrupt of a processor
*
* \param interrupt_id kernel name of the interrupt
* \param processor_id kernel name of the processor
*/
bool is_ip_interrupt(unsigned const interrupt_id,
unsigned const processor_id)
{
return false;
}
/**
* Trigger the inter-processor interrupt of a processor
*
* \param processor_id kernel name of the processor
*/
void trigger_ip_interrupt(unsigned const processor_id) { }
};
}