From a8d071b372623c7a7134717f92a07ef1eb0ae5ef Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Mon, 10 Mar 2014 15:37:20 +0100 Subject: [PATCH] hw: inter-processor interrupt on remote scheduling ref #1088 --- base-hw/src/core/imx53/pic_base.h | 19 ++++++++++++ base-hw/src/core/kernel/scheduler.cc | 33 ++++++++++++++++---- base-hw/src/core/pic/arm_gic.h | 46 +++++++++++++++++++++++++++- base-hw/src/core/pic/imx31.h | 19 ++++++++++++ base-hw/src/core/rpi/pic.h | 19 ++++++++++++ 5 files changed, 129 insertions(+), 7 deletions(-) diff --git a/base-hw/src/core/imx53/pic_base.h b/base-hw/src/core/imx53/pic_base.h index d2c73d96f2..36e1b59d4c 100644 --- a/base-hw/src/core/imx53/pic_base.h +++ b/base-hw/src/core/imx53/pic_base.h @@ -200,6 +200,25 @@ namespace Imx53 if (i <= MAX_INTERRUPT_ID) write(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) { } }; } diff --git a/base-hw/src/core/kernel/scheduler.cc b/base-hw/src/core/kernel/scheduler.cc index 4ce8aad920..31ecae781e 100644 --- a/base-hw/src/core/kernel/scheduler.cc +++ b/base-hw/src/core/kernel/scheduler.cc @@ -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(); } diff --git a/base-hw/src/core/pic/arm_gic.h b/base-hw/src/core/pic/arm_gic.h index 2859657a74..78d1414087 100644 --- a/base-hw/src/core/pic/arm_gic.h +++ b/base-hw/src/core/pic/arm_gic.h @@ -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(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); + } }; #endif /* _PIC__ARM_GIC_H_ */ diff --git a/base-hw/src/core/pic/imx31.h b/base-hw/src/core/pic/imx31.h index b0bcd04732..96f96bf475 100644 --- a/base-hw/src/core/pic/imx31.h +++ b/base-hw/src/core/pic/imx31.h @@ -203,6 +203,25 @@ namespace Imx31 */ void mask(unsigned const i) { if (i <= MAX_INTERRUPT_ID) write(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) { } }; } diff --git a/base-hw/src/core/rpi/pic.h b/base-hw/src/core/rpi/pic.h index 395b985d0d..7385500750 100644 --- a/base-hw/src/core/rpi/pic.h +++ b/base-hw/src/core/rpi/pic.h @@ -117,6 +117,25 @@ namespace Kernel else write(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) { } }; }