From 01e8ee275264eb0d50662deecc4a1070233e780b Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Thu, 5 Sep 2013 12:47:19 +0200 Subject: [PATCH] hw: IRQ receiver in extra header & reviewed ref #528 --- base-hw/src/core/kernel.cc | 61 +-------- base-hw/src/core/kernel/irq_receiver.h | 167 +++++++++++++++++++++++++ base-hw/src/core/kernel/thread.h | 82 +----------- 3 files changed, 171 insertions(+), 139 deletions(-) create mode 100644 base-hw/src/core/kernel/irq_receiver.h diff --git a/base-hw/src/core/kernel.cc b/base-hw/src/core/kernel.cc index 5e49e2d51e..53f0175287 100644 --- a/base-hw/src/core/kernel.cc +++ b/base-hw/src/core/kernel.cc @@ -341,64 +341,8 @@ namespace Kernel Tlb * const tlb() { return _tlb; } Platform_pd * const platform_pd() { return _platform_pd; } }; - - - /** - * Access to static interrupt-controller - */ - static Pic * pic() { return unsynchronized_singleton(); } } - -bool Kernel::Irq_owner::allocate_irq(unsigned const irq) -{ - /* Check if an allocation is needed and possible */ - unsigned const id = irq_to_id(irq); - if (_id) return _id == id; - if (_pool()->object(id)) return 0; - - /* Let us own the IRQ, but mask it till we await it */ - pic()->mask(irq); - _id = id; - _pool()->insert(this); - return 1; -} - - -bool Kernel::Irq_owner::free_irq(unsigned const irq) -{ - if (_id != irq_to_id(irq)) return 0; - _pool()->remove(this); - _id = 0; - return 1; -} - - -void Kernel::Irq_owner::await_irq() -{ - assert(_id); - unsigned const irq = id_to_irq(_id); - pic()->unmask(irq); - _awaits_irq(); -} - - -void Kernel::Irq_owner::cancel_waiting() { - if (_id) pic()->mask(id_to_irq(_id)); } - - -void Kernel::Irq_owner::receive_irq(unsigned const irq) -{ - assert(_id == irq_to_id(irq)); - pic()->mask(irq); - _received_irq(); -} - - -Kernel::Irq_owner * Kernel::Irq_owner::owner(unsigned irq) { - return _pool()->object(irq_to_id(irq)); } - - namespace Kernel { /** @@ -837,8 +781,7 @@ namespace Kernel default: { - /* IRQ not owned by core, thus notify IRQ owner */ - Irq_owner * const o = Irq_owner::owner(irq); + Irq_receiver * const o = Irq_receiver::receiver(irq); assert(o); o->receive_irq(irq); break; } @@ -1521,7 +1464,7 @@ int Kernel::Thread::resume() return 0; case AWAIT_IRQ: PDBG("cancel IRQ receipt"); - Irq_owner::cancel_waiting(); + Irq_receiver::cancel_waiting(); _schedule(); return 0; case AWAIT_SIGNAL: diff --git a/base-hw/src/core/kernel/irq_receiver.h b/base-hw/src/core/kernel/irq_receiver.h new file mode 100644 index 0000000000..10769ac9ed --- /dev/null +++ b/base-hw/src/core/kernel/irq_receiver.h @@ -0,0 +1,167 @@ +/* + * \brief Exclusive ownership and handling of interrupts + * \author Martin Stein + * \date 2012-11-30 + */ + +/* + * Copyright (C) 2012-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _KERNEL__IRQ_RECEIVER_H_ +#define _KERNEL__IRQ_RECEIVER_H_ + +/* core includes */ +#include +#include +#include + +namespace Kernel +{ + /** + * Exclusive ownership and handling of one interrupt at a time + */ + class Irq_receiver; + + /** + * Return interrupt-controller singleton + */ + static Pic * pic() { return unsynchronized_singleton(); } +} + +class Kernel::Irq_receiver : public Object_pool::Item +{ + private: + + typedef Object_pool Pool; + + /** + * Return map that maps assigned interrupts to their receivers + */ + static Pool * _pool() { static Pool _pool; return &_pool; } + + /** + * Translate receiver ID 'id' to interrupt ID + */ + static unsigned _id_to_irq(unsigned id) { return id - 1; } + + /** + * Translate interrupt ID 'id' to receiver ID + */ + static unsigned _irq_to_id(unsigned irq) { return irq + 1; } + + /** + * Free interrupt of this receiver without sanity checks + */ + void _free_irq() + { + _pool()->remove(this); + _id = 0; + } + + /** + * Stop receiver from waiting for its interrupt without sanity checks + */ + void _cancel_waiting() { pic()->mask(_id_to_irq(_id)); } + + /** + * Gets called as soon as the receivers interrupt occurs + */ + virtual void _received_irq() = 0; + + /** + * Gets called when receiver starts waiting for its interrupt + */ + virtual void _awaits_irq() = 0; + + public: + + /** + * Constructor + */ + Irq_receiver() : Pool::Item(0) { } + + /** + * Destructor + */ + ~Irq_receiver() + { + if (_id) { + _cancel_waiting(); + _free_irq(); + } + } + + /** + * Assign interrupt 'irq' to the receiver + * + * \return wether the assignment succeeded + */ + bool allocate_irq(unsigned const irq) + { + /* check if an allocation is needed and possible */ + unsigned const id = _irq_to_id(irq); + if (_id) { return _id == id; } + if (_pool()->object(id)) { return 0; } + + /* allocate and mask the interrupt */ + pic()->mask(irq); + _id = id; + _pool()->insert(this); + return 1; + } + + /** + * Unassign interrupt 'irq' if it is assigned to the receiver + * + * \return wether the unassignment succeeded + */ + bool free_irq(unsigned const irq) + { + if (_id != _irq_to_id(irq)) { return 0; } + _free_irq(); + return 1; + } + + /** + * Unmask and await interrupt that is assigned to the receiver + */ + void await_irq() + { + if (!_id) { + PERR("waiting for imaginary interrupt"); + return; + } + unsigned const irq = _id_to_irq(_id); + pic()->unmask(irq); + _awaits_irq(); + } + + /** + * Stop waiting for the interrupt of the receiver + */ + void cancel_waiting() { if (_id) { _cancel_waiting(); } } + + /** + * Denote that the receivers interrupt 'irq' occured and mask it + */ + void receive_irq(unsigned const irq) + { + assert(_id == _irq_to_id(irq)); + pic()->mask(irq); + _received_irq(); + } + + /** + * Get receiver of IRQ 'irq' or 0 if the IRQ isn't assigned + */ + static Irq_receiver * receiver(unsigned irq) + { + return _pool()->object(_irq_to_id(irq)); + } +}; + +#endif /* _KERNEL__IRQ_RECEIVER_H_ */ diff --git a/base-hw/src/core/kernel/thread.h b/base-hw/src/core/kernel/thread.h index edccf362cb..4e4ab9c89f 100644 --- a/base-hw/src/core/kernel/thread.h +++ b/base-hw/src/core/kernel/thread.h @@ -20,12 +20,12 @@ /* core includes */ #include #include -#include #include #include #include #include #include +#include namespace Genode { @@ -234,84 +234,6 @@ namespace Kernel void cancel_waiting(); }; - /** - * Exclusive ownership and handling of one IRQ per instance at a max - */ - class Irq_owner : public Object_pool::Item - { - /** - * To get any instance of this class by its ID - */ - typedef Object_pool Pool; - static Pool * _pool() { static Pool _pool; return &_pool; } - - /** - * Is called when the IRQ we were waiting for has occured - */ - virtual void _received_irq() = 0; - - /** - * Is called when we start waiting for the occurence of an IRQ - */ - virtual void _awaits_irq() = 0; - - public: - - /** - * Translate 'Irq_owner_pool'-item ID to IRQ ID - */ - static unsigned id_to_irq(unsigned id) { return id - 1; } - - /** - * Translate IRQ ID to 'Irq_owner_pool'-item ID - */ - static unsigned irq_to_id(unsigned irq) { return irq + 1; } - - /** - * Constructor - */ - Irq_owner() : Pool::Item(0) { } - - /** - * Destructor - */ - virtual ~Irq_owner() { } - - /** - * Ensure that our 'receive_irq' gets called on IRQ 'irq' - * - * \return wether the IRQ is allocated to the caller or not - */ - bool allocate_irq(unsigned const irq); - - /** - * Release the ownership of the IRQ 'irq' if we own it - * - * \return wether the IRQ is freed or not - */ - bool free_irq(unsigned const irq); - - /** - * If we own an IRQ, enable it and await 'receive_irq' - */ - void await_irq(); - - /** - * Stop waiting for an IRQ if in a waiting state - */ - void cancel_waiting(); - - /** - * Denote occurence of an IRQ if we own it and awaited it - */ - void receive_irq(unsigned const irq); - - /** - * Get owner of IRQ or 0 if the IRQ is not owned by anyone - */ - static Irq_owner * owner(unsigned irq); - }; - /** * Kernel representation of a user thread */ @@ -320,7 +242,7 @@ namespace Kernel public Schedule_context, public Fifo::Element, public Ipc_node, - public Irq_owner + public Irq_receiver { enum State {