mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-19 03:06:39 +00:00
parent
2c357a4f04
commit
01e8ee2752
@ -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<Pic>(); }
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
|
167
base-hw/src/core/kernel/irq_receiver.h
Normal file
167
base-hw/src/core/kernel/irq_receiver.h
Normal file
@ -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 <pic.h>
|
||||
#include <assert.h>
|
||||
#include <kernel/object.h>
|
||||
|
||||
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<Pic>(); }
|
||||
}
|
||||
|
||||
class Kernel::Irq_receiver : public Object_pool<Irq_receiver>::Item
|
||||
{
|
||||
private:
|
||||
|
||||
typedef Object_pool<Irq_receiver> 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_ */
|
@ -20,12 +20,12 @@
|
||||
/* core includes */
|
||||
#include <cpu.h>
|
||||
#include <tlb.h>
|
||||
#include <pic.h>
|
||||
#include <timer.h>
|
||||
#include <assert.h>
|
||||
#include <kernel/configuration.h>
|
||||
#include <kernel/scheduler.h>
|
||||
#include <kernel/object.h>
|
||||
#include <kernel/irq_receiver.h>
|
||||
|
||||
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<Irq_owner>::Item
|
||||
{
|
||||
/**
|
||||
* To get any instance of this class by its ID
|
||||
*/
|
||||
typedef Object_pool<Irq_owner> 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<Thread>::Element,
|
||||
public Ipc_node,
|
||||
public Irq_owner
|
||||
public Irq_receiver
|
||||
{
|
||||
enum State
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user