diff --git a/repos/base-codezero/src/core/include/irq_session_component.h b/repos/base-codezero/src/core/include/irq_session_component.h
deleted file mode 100644
index 734de0531f..0000000000
--- a/repos/base-codezero/src/core/include/irq_session_component.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * \brief IRQ session interface for NOVA
- * \author Norman Feske
- * \date 2010-01-30
- */
-
-/*
- * Copyright (C) 2010-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 _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
-#define _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
-
-#include
-#include
-
-#include
-
-namespace Genode {
-
- class Irq_session_component : public Rpc_object,
- public List::Element
- {
- private:
-
- enum { STACK_SIZE = 4096 };
-
- unsigned _irq_number;
- Range_allocator *_irq_alloc;
- Rpc_entrypoint _entrypoint;
- Irq_session_capability _cap;
- bool _attached;
-
- public:
-
- /**
- * Constructor
- *
- * \param cap_session capability session to use
- * \param irq_alloc platform-dependent IRQ allocator
- * \param args session construction arguments
- */
- Irq_session_component(Cap_session *cap_session,
- Range_allocator *irq_alloc,
- const char *args);
-
- /**
- * Destructor
- */
- ~Irq_session_component();
-
- /**
- * Return capability to this session
- *
- * If an initialization error occurs, returned capability is invalid.
- */
- Irq_session_capability cap() const { return _cap; }
-
-
- /***************************
- ** Irq session interface **
- ***************************/
-
- void wait_for_irq();
- Irq_signal signal();
- };
-}
-
-#endif /* _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ */
diff --git a/repos/base-codezero/src/core/irq_session_component.cc b/repos/base-codezero/src/core/irq_session_component.cc
index 6a6d3556fd..08e40ad040 100644
--- a/repos/base-codezero/src/core/irq_session_component.cc
+++ b/repos/base-codezero/src/core/irq_session_component.cc
@@ -22,57 +22,123 @@
#include
+namespace Genode {
+ typedef Irq_proxy > Irq_proxy_base;
+ class Irq_proxy_component;
+}
+
using namespace Genode;
+/**
+ * Platform-specific proxy code
+ */
-void Irq_session_component::wait_for_irq()
+class Genode::Irq_proxy_component : public Irq_proxy_base
{
- using namespace Codezero;
+ private:
- /* attach thread to IRQ when first called */
- if (!_attached) {
- int ret = l4_irq_control(IRQ_CONTROL_REGISTER, 0, _irq_number);
- if (ret < 0) {
- PERR("l4_irq_control(IRQ_CONTROL_REGISTER) returned %d", ret);
- sleep_forever();
+ bool _irq_attached;
+
+ protected:
+
+ bool _associate() { return true; }
+
+ void _wait_for_irq()
+ {
+ using namespace Codezero;
+
+ /* attach thread to IRQ when first called */
+ if (!_irq_attached) {
+ int ret = l4_irq_control(IRQ_CONTROL_REGISTER, 0, _irq_number);
+ if (ret < 0) {
+ PERR("l4_irq_control(IRQ_CONTROL_REGISTER) returned %d", ret);
+ sleep_forever();
+ }
+ _irq_attached = true;
+ }
+
+ /* block for IRQ */
+ int ret = l4_irq_control(IRQ_CONTROL_WAIT, 0, _irq_number);
+ if (ret < 0)
+ PWRN("l4_irq_control(IRQ_CONTROL_WAIT) returned %d", ret);
}
- _attached = true;
+
+ void _ack_irq() { }
+
+ public:
+
+ Irq_proxy_component(long irq_number)
+ :
+ Irq_proxy(irq_number),
+ _irq_attached(false)
+ {
+ _start();
+ }
+};
+
+
+/***************************
+ ** IRQ session component **
+ ***************************/
+
+
+void Irq_session_component::ack_irq()
+{
+ if (!_proxy) {
+ PERR("Expected to find IRQ proxy for IRQ %02x", _irq_number);
+ return;
}
- /* block for IRQ */
- int ret = l4_irq_control(IRQ_CONTROL_WAIT, 0, _irq_number);
- if (ret < 0)
- PWRN("l4_irq_control(IRQ_CONTROL_WAIT) returned %d", ret);
+ _proxy->ack_irq();
}
-Irq_session_component::Irq_session_component(Cap_session *cap_session,
- Range_allocator *irq_alloc,
+Irq_session_component::Irq_session_component(Range_allocator *irq_alloc,
const char *args)
:
- _irq_alloc(irq_alloc),
- _entrypoint(cap_session, STACK_SIZE, "irq"),
- _attached(false)
+ _irq_alloc(irq_alloc)
{
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
- if (!irq_alloc || (irq_number == -1)||
- irq_alloc->alloc_addr(1, irq_number).is_error()) {
- PERR("unavailable IRQ %lx requested", irq_number);
- return;
+ if (irq_number == -1) {
+ PERR("invalid IRQ number requested");
+
+ throw Root::Unavailable();
}
+
+ /* check if IRQ thread was started before */
+ _proxy = Irq_proxy_component::get_irq_proxy(irq_number, irq_alloc);
+ if (!_proxy) {
+ PERR("unavailable IRQ %lx requested", irq_number);
+ throw Root::Unavailable();
+ }
+
_irq_number = irq_number;
- _cap = Irq_session_capability(_entrypoint.manage(this));
}
Irq_session_component::~Irq_session_component()
{
- PERR("not yet implemented");
+ if (!_proxy) return;
+
+ if (_irq_sigh.valid())
+ _proxy->remove_sharer(&_irq_sigh);
}
-Irq_signal Irq_session_component::signal()
+void Irq_session_component::sigh(Genode::Signal_context_capability sigh)
{
- PDBG("not implemented;");
- return Irq_signal();
+ if (!_proxy) {
+ PERR("signal handler got not registered - irq thread unavailable");
+ return;
+ }
+
+ Genode::Signal_context_capability old = _irq_sigh;
+
+ if (old.valid() && !sigh.valid())
+ _proxy->remove_sharer(&_irq_sigh);
+
+ _irq_sigh = sigh;
+
+ if (!old.valid() && sigh.valid())
+ _proxy->add_sharer(&_irq_sigh);
}
diff --git a/repos/base-fiasco/src/core/irq_session_component.cc b/repos/base-fiasco/src/core/irq_session_component.cc
index e7b738a863..a2d649ca14 100644
--- a/repos/base-fiasco/src/core/irq_session_component.cc
+++ b/repos/base-fiasco/src/core/irq_session_component.cc
@@ -18,6 +18,7 @@
#include
/* core includes */
+#include
#include
#include
@@ -28,101 +29,150 @@ namespace Fiasco {
#include
}
+namespace Genode {
+ typedef Irq_proxy > Irq_proxy_base;
+ class Irq_proxy_component;
+}
+
+
using namespace Genode;
-bool Irq_session_component::Irq_control_component::associate_to_irq(unsigned irq_number)
+/**
+ * Platform-specific proxy code
+ */
+
+class Genode::Irq_proxy_component : public Irq_proxy_base
{
- using namespace Fiasco;
+ protected:
- int err;
- l4_threadid_t irq_tid;
- l4_umword_t dw0, dw1;
- l4_msgdope_t result;
+ bool _associate()
+ {
+ using namespace Fiasco;
- l4_make_taskid_from_irq(irq_number, &irq_tid);
+ int err;
+ l4_threadid_t irq_tid;
+ l4_umword_t dw0, dw1;
+ l4_msgdope_t result;
- /* boost thread to IRQ priority */
- enum { IRQ_PRIORITY = 0xC0 };
+ l4_make_taskid_from_irq(_irq_number, &irq_tid);
- l4_sched_param_t param = {sp:{prio:IRQ_PRIORITY, small:0, state:0, time_exp:0, time_man:0}};
- l4_threadid_t ext_preempter = L4_INVALID_ID;
- l4_threadid_t partner = L4_INVALID_ID;
- l4_sched_param_t old_param;
- l4_thread_schedule(l4_myself(), param, &ext_preempter, &partner, &old_param);
+ /* boost thread to IRQ priority */
+ enum { IRQ_PRIORITY = 0xC0 };
- err = l4_ipc_receive(irq_tid,
- L4_IPC_SHORT_MSG, &dw0, &dw1,
- L4_IPC_BOTH_TIMEOUT_0, &result);
+ l4_sched_param_t param = {sp:{prio:IRQ_PRIORITY, small:0, state:0,
+ time_exp:0, time_man:0}};
+ l4_threadid_t ext_preempter = L4_INVALID_ID;
+ l4_threadid_t partner = L4_INVALID_ID;
+ l4_sched_param_t old_param;
+ l4_thread_schedule(l4_myself(), param, &ext_preempter, &partner,
+ &old_param);
- if (err != L4_IPC_RETIMEOUT) PERR("IRQ association failed");
+ err = l4_ipc_receive(irq_tid,
+ L4_IPC_SHORT_MSG, &dw0, &dw1,
+ L4_IPC_BOTH_TIMEOUT_0, &result);
- return (err == L4_IPC_RETIMEOUT);
+ if (err != L4_IPC_RETIMEOUT) PERR("IRQ association failed");
+
+ return (err == L4_IPC_RETIMEOUT);
+ }
+
+ void _wait_for_irq()
+ {
+ using namespace Fiasco;
+
+ l4_threadid_t irq_tid;
+ l4_umword_t dw0=0, dw1=0;
+ l4_msgdope_t result;
+
+ l4_make_taskid_from_irq(_irq_number, &irq_tid);
+
+ do {
+ l4_ipc_call(irq_tid,
+ L4_IPC_SHORT_MSG, 0, 0,
+ L4_IPC_SHORT_MSG, &dw0, &dw1,
+ L4_IPC_NEVER, &result);
+
+ if (L4_IPC_IS_ERROR(result))
+ PERR("Ipc error %lx", L4_IPC_ERROR(result));
+ } while (L4_IPC_IS_ERROR(result));
+ }
+
+ void _ack_irq() { }
+
+ public:
+
+ Irq_proxy_component(long irq_number)
+ :
+ Irq_proxy(irq_number)
+ {
+ _start();
+ }
+};
+
+
+/***************************
+ ** IRQ session component **
+ ***************************/
+
+
+void Irq_session_component::ack_irq()
+{
+ if (!_proxy) {
+ PERR("Expected to find IRQ proxy for IRQ %02x", _irq_number);
+ return;
+ }
+
+ _proxy->ack_irq();
}
-void Irq_session_component::wait_for_irq()
-{
- using namespace Fiasco;
-
- l4_threadid_t irq_tid;
- l4_umword_t dw0=0, dw1=0;
- l4_msgdope_t result;
-
- l4_make_taskid_from_irq(_irq_number, &irq_tid);
-
- do {
- l4_ipc_call(irq_tid,
- L4_IPC_SHORT_MSG, 0, 0,
- L4_IPC_SHORT_MSG, &dw0, &dw1,
- L4_IPC_NEVER, &result);
-
- if (L4_IPC_IS_ERROR(result)) PERR("Ipc error %lx", L4_IPC_ERROR(result));
- } while (L4_IPC_IS_ERROR(result));
-}
-
-
-Irq_session_component::Irq_session_component(Cap_session *cap_session,
- Range_allocator *irq_alloc,
+Irq_session_component::Irq_session_component(Range_allocator *irq_alloc,
const char *args)
:
- _irq_alloc(irq_alloc),
- _ep(cap_session, STACK_SIZE, "irqctrl"),
- _control_cap(_ep.manage(&_control_component)),
- _control_client(_control_cap)
+ _irq_alloc(irq_alloc)
{
- bool shared = Arg_string::find_arg(args, "irq_shared").bool_value(false);
- if (shared) {
- PWRN("IRQ sharing not supported");
- throw Root::Invalid_args();
- }
-
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
- if (irq_number == -1 || !irq_alloc ||
- irq_alloc->alloc_addr(1, irq_number).is_error()) {
- PERR("Unavailable IRQ %lx requested", irq_number);
- throw Root::Invalid_args();
+ if (irq_number == -1) {
+ PERR("invalid IRQ number requested");
+
+ throw Root::Unavailable();
}
+
+ /* check if IRQ thread was started before */
+ _proxy = Irq_proxy_component::get_irq_proxy(irq_number, irq_alloc);
+ if (!_proxy) {
+ PERR("unavailable IRQ %lx requested", irq_number);
+ throw Root::Unavailable();
+ }
+
_irq_number = irq_number;
-
- if (!_control_client.associate_to_irq(irq_number)) {
- PWRN("IRQ association failed");
- throw Root::Invalid_args();
- }
-
- /* initialize capability */
- _irq_cap = Irq_session_capability(_ep.manage(this));
}
Irq_session_component::~Irq_session_component()
{
- PERR("Implement me, immediately!");
+ if (!_proxy) return;
+
+ if (_irq_sigh.valid())
+ _proxy->remove_sharer(&_irq_sigh);
}
-Irq_signal Irq_session_component::signal()
+void Irq_session_component::sigh(Genode::Signal_context_capability sigh)
{
- PDBG("not implemented;");
- return Irq_signal();
+ if (!_proxy) {
+ PERR("signal handler got not registered - irq thread unavailable");
+ return;
+ }
+
+ Genode::Signal_context_capability old = _irq_sigh;
+
+ if (old.valid() && !sigh.valid())
+ _proxy->remove_sharer(&_irq_sigh);
+
+ _irq_sigh = sigh;
+
+ if (!old.valid() && sigh.valid())
+ _proxy->add_sharer(&_irq_sigh);
}
diff --git a/repos/base-foc/src/core/arndale/target.mk b/repos/base-foc/src/core/arndale/target.mk
index 6a182a0b0e..4b79b46f82 100644
--- a/repos/base-foc/src/core/arndale/target.mk
+++ b/repos/base-foc/src/core/arndale/target.mk
@@ -4,6 +4,5 @@ LD_TEXT_ADDR = 0x80100000
REQUIRES += arm foc_arndale
SRC_CC += arm/platform_arm.cc
-INC_DIR += $(REP_DIR)/src/core/include/arm
vpath platform_services.cc $(GEN_CORE_DIR)
diff --git a/repos/base-foc/src/core/imx53/target.mk b/repos/base-foc/src/core/imx53/target.mk
index 77717ad4ab..f26500ed68 100644
--- a/repos/base-foc/src/core/imx53/target.mk
+++ b/repos/base-foc/src/core/imx53/target.mk
@@ -2,7 +2,6 @@ include $(PRG_DIR)/../target.inc
REQUIRES += arm foc_imx53
SRC_CC += arm/platform_arm.cc
-INC_DIR += $(REP_DIR)/src/core/include/arm
LD_TEXT_ADDR = 0x70140000
diff --git a/repos/base-foc/src/core/include/arm/irq_proxy_component.h b/repos/base-foc/src/core/include/arm/irq_proxy_component.h
deleted file mode 100644
index ef7c896b91..0000000000
--- a/repos/base-foc/src/core/include/arm/irq_proxy_component.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * \brief Base class for shared interrupts on ARM
- * \author Sebastian Sumpf
- * \date 2012-10-05
- */
-
-/*
- * 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 _CORE__INCLUDE__ARM__IRQ_PROXY_COMPONENT_H_
-#define _CORE__INCLUDE__ARM__IRQ_PROXY_COMPONENT_H_
-
-#include
-
-namespace Genode {
-
-/**
- * On ARM we disable shared interrupts
- */
-typedef Irq_proxy_single Irq_proxy_base;
-
-}
-
-#endif /* _CORE__INCLUDE__ARM__IRQ_PROXY_COMPONENT_H_ */
-
diff --git a/repos/base-foc/src/core/include/irq_session_component.h b/repos/base-foc/src/core/include/irq_session_component.h
deleted file mode 100644
index b6f4bf5ed1..0000000000
--- a/repos/base-foc/src/core/include/irq_session_component.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * \brief IRQ session interface for Fiasco.OC
- * \author Stefan Kalkowski
- * \date 2011-01-28
- */
-
-/*
- * Copyright (C) 2011-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 _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
-#define _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
-
-#include
-#include
-#include
-#include
-
-#include
-
-namespace Genode {
-
- class Irq_proxy_component;
-
- class Irq_session_component : public Rpc_object,
- public List::Element
- {
- private:
-
-
- /*
- * Each IRQ session uses a dedicated server activation
- */
- enum { STACK_SIZE = 2048 };
- Rpc_entrypoint _ep;
-
- Irq_session_capability _irq_cap;
- Irq_proxy_component *_proxy;
-
- public:
-
- /**
- * Constructor
- *
- * \param cap_session capability session to use
- * \param irq_alloc platform-dependent IRQ allocator
- * \param args session construction arguments
- */
- Irq_session_component(Cap_session *cap_session,
- Range_allocator *irq_alloc,
- const char *args);
-
- /**
- * Destructor
- */
- ~Irq_session_component();
-
- /**
- * Return capability to this session
- *
- * If an initialization error occurs, returned capability is invalid.
- */
- Irq_session_capability cap() const { return _irq_cap; }
-
-
- /***************************
- ** Irq session interface **
- ***************************/
-
- void wait_for_irq();
- Irq_signal signal();
- };
-}
-
-#endif /* _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ */
diff --git a/repos/base-foc/src/core/include/x86/irq_proxy_component.h b/repos/base-foc/src/core/include/x86/irq_proxy_component.h
deleted file mode 100644
index c9625aaab9..0000000000
--- a/repos/base-foc/src/core/include/x86/irq_proxy_component.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * \brief Base class for shared interrupts on x86
- * \author Sebastian Sumpf
- * \date 2012-10-05
- */
-
-/*
- * 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 _CORE__INCLUDE__X86__IRQ_PROXY_COMPONENT_H_
-#define _CORE__INCLUDE__X86__IRQ_PROXY_COMPONENT_H_
-
-#include
-
-namespace Genode {
- typedef Irq_proxy > Irq_proxy_base;
-}
-
-#endif /* _CORE__INCLUDE__X86__IRQ_PROXY_COMPONENT_H_ */
-
diff --git a/repos/base-foc/src/core/irq_session_component.cc b/repos/base-foc/src/core/irq_session_component.cc
index deb058b03d..2125f218e3 100644
--- a/repos/base-foc/src/core/irq_session_component.cc
+++ b/repos/base-foc/src/core/irq_session_component.cc
@@ -21,7 +21,6 @@
/* core includes */
#include
-#include
#include
#include
#include
@@ -39,6 +38,7 @@ using namespace Genode;
namespace Genode {
class Interrupt_handler;
class Irq_proxy_component;
+ typedef Irq_proxy > Irq_proxy_base;
}
/**
@@ -69,10 +69,10 @@ class Genode::Irq_proxy_component : public Irq_proxy_base
{
private:
- Cap_index *_cap;
- Semaphore _sem;
- long _trigger; /* interrupt trigger */
- long _polarity; /* interrupt polarity */
+ Cap_index *_cap;
+ Semaphore _sem;
+ Irq_session::Trigger _trigger; /* interrupt trigger */
+ Irq_session::Polarity _polarity; /* interrupt polarity */
Native_thread _capability() const { return _cap->kcap(); }
@@ -123,107 +123,162 @@ class Genode::Irq_proxy_component : public Irq_proxy_base
:
Irq_proxy_base(irq_number),
_cap(cap_map()->insert(platform_specific()->cap_id_alloc()->alloc())),
- _sem(), _trigger(-1), _polarity(-1) { }
-
- Semaphore *semaphore() { return &_sem; }
-
- void start(long trigger, long polarity)
+ _sem(), _trigger(Irq_session::TRIGGER_UNCHANGED),
+ _polarity(Irq_session::POLARITY_UNCHANGED)
{
- _trigger = trigger;
- _polarity = polarity;
_start();
}
- bool match_mode(long trigger, long polarity)
+ Semaphore *semaphore() { return &_sem; }
+
+ Irq_session::Trigger trigger() const { return _trigger; }
+ Irq_session::Polarity polarity() const { return _polarity; }
+
+ void setup_irq_mode(Irq_session::Trigger t, Irq_session::Polarity p)
{
- if (trigger == Irq_session::TRIGGER_UNCHANGED &&
- polarity == Irq_session::POLARITY_UNCHANGED)
- return true;
+ _trigger = t;
+ _polarity = p;
- if (_trigger < 0 && _polarity < 0)
- return true;
-
- return _trigger == trigger && _polarity == polarity;
+ /* set interrupt mode */
+ Platform::setup_irq_mode(_irq_number, _trigger, _polarity);
}
-
- long trigger() const { return _trigger; }
- long polarity() const { return _polarity; }
};
-/********************************
- ** IRQ session implementation **
- ********************************/
+/***************************
+ ** IRQ session component **
+ ***************************/
-Irq_session_component::Irq_session_component(Cap_session *cap_session,
- Range_allocator *irq_alloc,
- const char *args)
-:
- _ep(cap_session, STACK_SIZE, "irqctrl"),
- _proxy(0)
+void Irq_session_component::ack_irq()
{
- using namespace Fiasco;
-
- long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
- if (irq_number == -1) {
- PERR("Unavailable IRQ %lx requested", irq_number);
- throw Root::Invalid_args();
+ if (!_proxy) {
+ PERR("Expected to find IRQ proxy for IRQ %02x", _irq_number);
+ return;
}
- long irq_trigger = Arg_string::find_arg(args, "irq_trigger").long_value(-1);
- irq_trigger = irq_trigger == -1 ? 0 : irq_trigger;
+ _proxy->ack_irq();
+}
- long irq_polarity = Arg_string::find_arg(args, "irq_polarity").long_value(-1);
- irq_polarity = irq_polarity == -1 ? 0 : irq_polarity;
+
+Irq_session_component::Irq_session_component(Range_allocator *irq_alloc,
+ const char *args)
+{
+ long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
+ if (irq_number == -1) {
+ PERR("invalid IRQ number requested");
+ throw Root::Unavailable();
+ }
+
+ long irq_t = Arg_string::find_arg(args, "irq_trigger").long_value(-1);
+ long irq_p = Arg_string::find_arg(args, "irq_polarity").long_value(-1);
+
+ Irq_session::Trigger irq_trigger;
+ Irq_session::Polarity irq_polarity;
+
+ switch(irq_t) {
+ case -1:
+ case Irq_session::TRIGGER_UNCHANGED:
+ irq_trigger = Irq_session::TRIGGER_UNCHANGED;
+ break;
+ case Irq_session::TRIGGER_EDGE:
+ irq_trigger = Irq_session::TRIGGER_EDGE;
+ break;
+ case Irq_session::TRIGGER_LEVEL:
+ irq_trigger = Irq_session::TRIGGER_LEVEL;
+ break;
+ default:
+ throw Root::Unavailable();
+ }
+
+ switch(irq_p) {
+ case -1:
+ case POLARITY_UNCHANGED:
+ irq_polarity = POLARITY_UNCHANGED;
+ break;
+ case POLARITY_HIGH:
+ irq_polarity = POLARITY_HIGH;
+ break;
+ case POLARITY_LOW:
+ irq_polarity = POLARITY_LOW;
+ break;
+ default:
+ throw Root::Unavailable();
+ }
/*
- * temorary hack for fiasco.oc using the local-apic,
+ * temporary hack for fiasco.oc using the local-apic,
* where old pic-line 0 maps to 2
*/
if (irq_number == 0)
irq_number = 2;
- if (!(_proxy = Irq_proxy_component::get_irq_proxy(irq_number,
- irq_alloc))) {
- PERR("No proxy for IRQ %lu found", irq_number);
+ /* check if IRQ thread was started before */
+ _proxy = Irq_proxy_component::get_irq_proxy(irq_number, irq_alloc);
+ if (!_proxy) {
+ PERR("unavailable IRQ %lx requested", irq_number);
throw Root::Unavailable();
}
+ bool setup = false;
+ bool fail = false;
+
/* sanity check */
- if (!_proxy->match_mode(irq_trigger, irq_polarity)) {
- PERR("Interrupt mode mismatch: IRQ %ld current mode: t: %ld p: %ld"
- "request mode: trg: %ld p: %ld",
+ if (irq_trigger != TRIGGER_UNCHANGED && _proxy->trigger() != irq_trigger) {
+ if (_proxy->trigger() == TRIGGER_UNCHANGED)
+ setup = true;
+ else
+ fail = true;
+ }
+
+ if (irq_polarity != POLARITY_UNCHANGED && _proxy->polarity() != irq_polarity) {
+ if (_proxy->polarity() == POLARITY_UNCHANGED)
+ setup = true;
+ else
+ fail = true;
+ }
+
+ if (fail) {
+ PERR("Interrupt mode mismatch: IRQ %ld current mode: t: %d p: %d "
+ "request mode: trg: %d p: %d",
irq_number, _proxy->trigger(), _proxy->polarity(),
irq_trigger, irq_polarity);
throw Root::Unavailable();
}
- /* set interrupt mode and start proxy */
- _proxy->start(irq_trigger, irq_polarity);
+ if (setup)
+ /* set interrupt mode */
+ _proxy->setup_irq_mode(irq_trigger, irq_polarity);
- if (!_proxy->add_sharer())
- throw Root::Unavailable();
-
- /* initialize capability */
- _irq_cap = _ep.manage(this);
+ _irq_number = irq_number;
}
-void Irq_session_component::wait_for_irq()
+Irq_session_component::~Irq_session_component()
{
- _proxy->wait_for_irq();
+ if (!_proxy) return;
+
+ if (_irq_sigh.valid())
+ _proxy->remove_sharer(&_irq_sigh);
}
-Irq_session_component::~Irq_session_component() {
- _proxy->remove_sharer(); }
-
-
-Irq_signal Irq_session_component::signal()
+void Irq_session_component::sigh(Genode::Signal_context_capability sigh)
{
- PDBG("not implemented;");
- return Irq_signal();
+ if (!_proxy) {
+ PERR("signal handler got not registered - irq thread unavailable");
+ return;
+ }
+
+ Genode::Signal_context_capability old = _irq_sigh;
+
+ if (old.valid() && !sigh.valid())
+ _proxy->remove_sharer(&_irq_sigh);
+
+ _irq_sigh = sigh;
+
+ if (!old.valid() && sigh.valid())
+ _proxy->add_sharer(&_irq_sigh);
}
diff --git a/repos/base-foc/src/core/panda/target.mk b/repos/base-foc/src/core/panda/target.mk
index 23cc6be317..c48250925c 100644
--- a/repos/base-foc/src/core/panda/target.mk
+++ b/repos/base-foc/src/core/panda/target.mk
@@ -4,6 +4,5 @@ LD_TEXT_ADDR = 0x80140000
REQUIRES += arm foc_panda
SRC_CC += arm/platform_arm.cc
-INC_DIR += $(REP_DIR)/src/core/include/arm
vpath platform_services.cc $(GEN_CORE_DIR)
diff --git a/repos/base-foc/src/core/pbxa9/target.mk b/repos/base-foc/src/core/pbxa9/target.mk
index 2ec8396d95..a031b0dacf 100644
--- a/repos/base-foc/src/core/pbxa9/target.mk
+++ b/repos/base-foc/src/core/pbxa9/target.mk
@@ -2,7 +2,6 @@ include $(PRG_DIR)/../target.inc
REQUIRES += arm foc_pbxa9
SRC_CC += arm/platform_arm.cc
-INC_DIR += $(REP_DIR)/src/core/include/arm
LD_TEXT_ADDR = 0x70490000
diff --git a/repos/base-foc/src/core/vea9x4/target.mk b/repos/base-foc/src/core/vea9x4/target.mk
index 06e95dbf05..6292d97a80 100644
--- a/repos/base-foc/src/core/vea9x4/target.mk
+++ b/repos/base-foc/src/core/vea9x4/target.mk
@@ -2,7 +2,6 @@ include $(PRG_DIR)/../target.inc
REQUIRES += arm foc_vea9x4
SRC_CC += arm/platform_arm.cc
-INC_DIR += $(REP_DIR)/src/core/include/arm
LD_TEXT_ADDR = 0x60490000
diff --git a/repos/base-foc/src/core/x86/target.mk b/repos/base-foc/src/core/x86/target.mk
index d36e32095c..f04ab9298c 100644
--- a/repos/base-foc/src/core/x86/target.mk
+++ b/repos/base-foc/src/core/x86/target.mk
@@ -5,7 +5,5 @@ REQUIRES += x86
SRC_CC += io_port_session_component.cc \
x86/platform_x86.cc
-INC_DIR += $(REP_DIR)/src/core/include/x86
-
vpath io_port_session_component.cc $(GEN_CORE_DIR)/x86
vpath platform_services.cc $(GEN_CORE_DIR)/x86
diff --git a/repos/base-hw/include/kernel/interface.h b/repos/base-hw/include/kernel/interface.h
index be951cbcc7..79c6b6ab29 100644
--- a/repos/base-hw/include/kernel/interface.h
+++ b/repos/base-hw/include/kernel/interface.h
@@ -207,12 +207,10 @@ namespace Kernel
* Await any context of a receiver and optionally ack a context before
*
* \param receiver_id kernel name of the targeted signal receiver
- * \param context_id kernel name of a context that shall be acknowledged
*
* \retval 0 suceeded
* \retval -1 failed
*
- * If context is set to 0, the call doesn't acknowledge any context.
* If this call returns 0, an instance of 'Signal::Data' is located at the
* base of the callers UTCB. Every occurence of a signal is provided
* through this function until it gets delivered through this function or
@@ -223,10 +221,9 @@ namespace Kernel
* deliver again unless its last delivery has been acknowledged via
* ack_signal.
*/
- inline int await_signal(unsigned const receiver_id,
- unsigned const context_id)
+ inline int await_signal(unsigned const receiver_id)
{
- return call(call_id_await_signal(), receiver_id, context_id);
+ return call(call_id_await_signal(), receiver_id);
}
diff --git a/repos/base-hw/src/base/irq/platform.cc b/repos/base-hw/src/base/irq/platform.cc
deleted file mode 100644
index 181ff2f7e7..0000000000
--- a/repos/base-hw/src/base/irq/platform.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * \brief Client-side IRQ session interface - specific for base-hw
- * \author Martin Stein
- * \date 2013-10-24
- */
-
-/*
- * Copyright (C) 2013-2015 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.
- */
-
-#include
-
-void Genode::Irq_session_client::wait_for_irq()
-{
- while (Kernel::await_signal(irq_signal.receiver_id,
- irq_signal.context_id))
- {
- PERR("failed to receive interrupt");
- }
-}
diff --git a/repos/base-hw/src/base/signal/signal.cc b/repos/base-hw/src/base/signal/signal.cc
index 0653b421a3..c296103cab 100644
--- a/repos/base-hw/src/base/signal/signal.cc
+++ b/repos/base-hw/src/base/signal/signal.cc
@@ -189,7 +189,7 @@ bool Signal_receiver::pending() { return Kernel::signal_pending(_cap.dst()); }
Signal Signal_receiver::wait_for_signal()
{
/* await a signal */
- if (Kernel::await_signal(_cap.dst(), 0)) {
+ if (Kernel::await_signal(_cap.dst())) {
PERR("failed to receive signal");
return Signal(Signal::Data());
}
diff --git a/repos/base-hw/src/core/include/irq_session_component.h b/repos/base-hw/src/core/include/irq_session_component.h
index ee1c1e91f8..ddd36bb2b8 100644
--- a/repos/base-hw/src/core/include/irq_session_component.h
+++ b/repos/base-hw/src/core/include/irq_session_component.h
@@ -5,71 +5,59 @@
*/
/*
- * Copyright (C) 2013 Genode Labs GmbH
+ * Copyright (C) 2013-2015 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 _INCLUDE__IRQ_SESSION_COMPONENT_H_
-#define _INCLUDE__IRQ_SESSION_COMPONENT_H_
+#define __INCLUDE__IRQ_SESSION_COMPONENT_H_
/* Genode includes */
#include
#include
#include
-namespace Genode
-{
- /**
- * Backend for IRQ sessions to core
- */
- class Irq_session_component
- :
- public Rpc_object,
- public List::Element
- {
- private:
-
- Range_allocator * const _irq_alloc;
- Irq_session_capability _cap;
- Irq_signal _signal;
- Genode::uint8_t _kernel_object[sizeof(Kernel::User_irq)];
-
- public:
-
- /**
- * Constructor
- *
- * \param cap_session capability session to use
- * \param irq_alloc interrupt allocator
- * \param args session construction arguments
- */
- Irq_session_component(Cap_session * const cap_session,
- Range_allocator * const irq_alloc,
- const char * const args);
-
- /**
- * Destructor
- */
- ~Irq_session_component();
-
- /**
- * Return capability to this session
- *
- * If an initialization error occurs, returned _cap is invalid.
- */
- Irq_session_capability cap() const { return _cap; }
-
-
- /*****************
- ** Irq_session **
- *****************/
-
- void wait_for_irq();
-
- Irq_signal signal();
- };
+namespace Genode {
+ class Irq_session_component;
}
+class Genode::Irq_session_component : public Rpc_object,
+ public List::Element
+{
+ private:
+
+ unsigned _irq_number;
+ Range_allocator *_irq_alloc;
+ Genode::uint8_t _kernel_object[sizeof(Kernel::User_irq)];
+
+ Signal_context_capability _sig_cap;
+
+ unsigned _find_irq_number(const char * const args);
+
+ public:
+
+ /**
+ * Constructor
+ *
+ * \param irq_alloc platform-dependent IRQ allocator
+ * \param args session construction arguments
+ */
+ Irq_session_component(Range_allocator *irq_alloc,
+ const char *args);
+
+ /**
+ * Destructor
+ */
+ ~Irq_session_component();
+
+ /***************************
+ ** Irq session interface **
+ ***************************/
+
+ void ack_irq();
+ void sigh(Signal_context_capability) override;
+};
+
#endif /* _INCLUDE__IRQ_SESSION_COMPONENT_H_ */
diff --git a/repos/base-hw/src/core/include/kernel/core_interface.h b/repos/base-hw/src/core/include/kernel/core_interface.h
index 99262b1665..9104918503 100644
--- a/repos/base-hw/src/core/include/kernel/core_interface.h
+++ b/repos/base-hw/src/core/include/kernel/core_interface.h
@@ -353,12 +353,14 @@ namespace Kernel
/**
* Create an interrupt object
*
- * \param p memory donation for the irq object
- * \param irq_nr interrupt number
+ * \param p memory donation for the irq object
+ * \param irq_nr interrupt number
+ * \param signal_context_id kernel name of the signal context
*/
- inline void new_irq(addr_t const p, unsigned irq_nr)
+ inline int new_irq(addr_t const p, unsigned irq_nr,
+ unsigned signal_context_id)
{
- call(call_id_new_irq(), (Call_arg) p, irq_nr);
+ return call(call_id_new_irq(), (Call_arg) p, irq_nr, signal_context_id);
}
/**
diff --git a/repos/base-hw/src/core/include/kernel/irq.h b/repos/base-hw/src/core/include/kernel/irq.h
index 5273eeff3f..83ec010da8 100644
--- a/repos/base-hw/src/core/include/kernel/irq.h
+++ b/repos/base-hw/src/core/include/kernel/irq.h
@@ -47,8 +47,14 @@ namespace Genode
class Kernel::Irq : public Object_pool::Item
{
+ public:
+
+ using Pool = Object_pool;
+
protected:
+ Pool &_pool;
+
/**
* Get kernel name of the interrupt
*/
@@ -56,16 +62,6 @@ class Kernel::Irq : public Object_pool::Item
public:
- using Pool = Object_pool;
-
- /**
- * Constructor
- *
- * \param irq_id kernel name of the interrupt
- */
- Irq(unsigned const irq_id)
- : Pool::Item(irq_id) { }
-
/**
* Constructor
*
@@ -73,14 +69,9 @@ class Kernel::Irq : public Object_pool::Item
* \param pool pool this interrupt shall belong to
*/
Irq(unsigned const irq_id, Pool &pool)
- : Irq(irq_id) { pool.insert(this); }
+ : Pool::Item(irq_id), _pool(pool) { _pool.insert(this); }
- /**
- * Destructor
- *
- * By now, there is no use case to destruct interrupts
- */
- virtual ~Irq() { PERR("destruction of interrupts not implemented"); }
+ virtual ~Irq() { _pool.remove(this); }
/**
* Handle occurence of the interrupt
@@ -102,12 +93,12 @@ class Kernel::Irq : public Object_pool::Item
class Kernel::User_irq
:
public Kernel::Irq,
- public Signal_receiver,
- public Signal_context,
public Signal_ack_handler
{
private:
+ Signal_context &_context;
+
/**
* Get map that provides all user interrupts by their kernel names
*/
@@ -127,30 +118,25 @@ class Kernel::User_irq
*
* \param irq_id kernel name of the interrupt
*/
- User_irq(unsigned const irq_id)
- : Irq(irq_id), Signal_context(this, 0)
+ User_irq(unsigned const irq_id, Signal_context &context)
+ : Irq(irq_id, *_pool()), _context(context)
{
- _pool()->insert(this);
disable();
- Signal_context::ack_handler(this);
+ _context.ack_handler(this);
}
- /**
- * Get kernel name of the interrupt-signal receiver
- */
- unsigned receiver_id() const { return Signal_receiver::Object::id(); }
-
- /**
- * Get kernel name of the interrupt-signal context
- */
- unsigned context_id() const { return Signal_context::Object::id(); }
+ ~User_irq()
+ {
+ _context.ack_handler(nullptr);
+ disable();
+ }
/**
* Handle occurence of the interrupt
*/
void occurred()
{
- Signal_context::submit(1);
+ _context.submit(1);
disable();
}
diff --git a/repos/base-hw/src/core/irq_session_component.cc b/repos/base-hw/src/core/irq_session_component.cc
index 561dca7dd8..891e7bea53 100644
--- a/repos/base-hw/src/core/irq_session_component.cc
+++ b/repos/base-hw/src/core/irq_session_component.cc
@@ -22,64 +22,53 @@
using namespace Genode;
-/**
- * On other platforms, every IRQ session component creates its entrypoint.
- * However, on base-hw this isn't necessary as users can wait for their
- * interrupts directly. Instead of replacing cores generic irq_root.h and
- * main.cc with base-hw specific versions, we simply use a local singleton.h
- */
-static Rpc_entrypoint * irq_session_ep()
+
+unsigned Irq_session_component::_find_irq_number(const char * const args)
{
- enum { STACK_SIZE = 2048 };
- static Rpc_entrypoint
- _ep(core_env()->cap_session(), STACK_SIZE, "irq_session_ep");
- return &_ep;
+ return Arg_string::find_arg(args, "irq_number").long_value(-1);
}
-void Irq_session_component::wait_for_irq() { PERR("not implemented"); }
-Irq_signal Irq_session_component::signal() { return _signal; }
+void Irq_session_component::ack_irq()
+{
+ Kernel::ack_signal(_sig_cap.dst());
+}
+
+
+void Irq_session_component::sigh(Signal_context_capability cap)
+{
+ if (_sig_cap.valid()) {
+ PWRN("signal handler already registered for IRQ %u", _irq_number);
+ return;
+ }
+
+ _sig_cap = cap;
+
+ if (Kernel::new_irq((addr_t)&_kernel_object, _irq_number, _sig_cap.dst()))
+ PWRN("invalid signal handler for IRQ %u", _irq_number);
+}
+
Irq_session_component::~Irq_session_component()
{
using namespace Kernel;
- irq_session_ep()->dissolve(this);
User_irq * kirq = reinterpret_cast(&_kernel_object);
_irq_alloc->free((void *)(addr_t)static_cast(kirq)->id());
- Kernel::delete_irq(kirq);
+ if (_sig_cap.valid())
+ Kernel::delete_irq(kirq);
}
-Irq_session_component::Irq_session_component(Cap_session * const cap_session,
- Range_allocator * const irq_alloc,
- const char * const args)
-: _irq_alloc(irq_alloc)
+
+Irq_session_component::Irq_session_component(Range_allocator * const irq_alloc,
+ const char * const args)
+:
+ _irq_number(Platform::irq(_find_irq_number(args))),
+ _irq_alloc(irq_alloc)
{
- using namespace Kernel;
-
- /* check arguments */
- bool shared = Arg_string::find_arg(args, "irq_shared").bool_value(false);
- if (shared) {
- PERR("shared interrupts not supported");
- throw Root::Invalid_args();
- }
-
/* allocate interrupt */
- long irq_nr = Arg_string::find_arg(args, "irq_number").long_value(-1);
- bool error = irq_nr < 0 || !_irq_alloc;
-
- /* enable platform specific code to apply mappings */
- long const plat_irq_nr = Platform::irq(irq_nr);
-
- error |= _irq_alloc->alloc_addr(1, plat_irq_nr).is_error();
- if (error) {
+ if (_irq_alloc->alloc_addr(1, _irq_number).is_error()) {
PERR("unavailable interrupt requested");
throw Root::Invalid_args();
}
-
- /* make interrupt accessible */
- new_irq((addr_t)&_kernel_object, plat_irq_nr);
- User_irq * kirq = reinterpret_cast(&_kernel_object);
- _signal = { kirq->receiver_id(), kirq->context_id() };
- _cap = Irq_session_capability(irq_session_ep()->manage(this));
}
diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc
index cb0dcc3a19..e545fb3582 100644
--- a/repos/base-hw/src/core/kernel/thread.cc
+++ b/repos/base-hw/src/core/kernel/thread.cc
@@ -582,13 +582,6 @@ void Thread::_call_new_signal_context()
void Thread::_call_await_signal()
{
- /* check wether to acknowledge a context */
- unsigned const context_id = user_arg_2();
- if (context_id) {
- Signal_context * const c = Signal_context::pool()->object(context_id);
- if (c) { c->ack(); }
- else { PWRN("failed to acknowledge signal context"); }
- }
/* lookup receiver */
unsigned const receiver_id = user_arg_1();
Signal_receiver * const r = Signal_receiver::pool()->object(receiver_id);
@@ -688,8 +681,19 @@ void Thread::_call_delete_signal_receiver() {
reinterpret_cast(user_arg_1())->~Signal_receiver(); }
-void Thread::_call_new_irq() {
- new ((void *)user_arg_1()) User_irq(user_arg_2()); }
+void Thread::_call_new_irq()
+{
+ Signal_context * const c = Signal_context::pool()->object(user_arg_3());
+ if (!c) {
+ PWRN("%s -> %s: invalid signal context for interrupt",
+ pd_label(), label());
+ user_arg_0(-1);
+ return;
+ }
+
+ new ((void *)user_arg_1()) User_irq(user_arg_2(), *c);
+ user_arg_0(0);
+}
void Thread::_call_delete_irq() {
diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc
index 90e03f0fde..1931e0a85c 100644
--- a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc
+++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc
@@ -49,7 +49,7 @@ extern Genode::addr_t _vt_host_context_ptr;
struct Kernel::Vm_irq : Kernel::Irq
{
- Vm_irq(unsigned const irq) : Kernel::Irq(irq) {}
+ Vm_irq(unsigned const irq) : Kernel::Irq(irq, *cpu_pool()->executing_cpu()) {}
/**
* A VM interrupt gets injected into the VM scheduled on the current CPU
@@ -180,10 +180,6 @@ struct Kernel::Virtual_timer
void Kernel::prepare_hypervisor()
{
- Cpu * cpu = cpu_pool()->executing_cpu();
- cpu->insert(&Virtual_timer::timer().irq);
- cpu->insert(&Virtual_pic::pic().irq);
-
/* set hypervisor exception vector */
Cpu::hyp_exception_entry_at(&_vt_host_entry);
diff --git a/repos/base-linux/lib/mk/base-common.mk b/repos/base-linux/lib/mk/base-common.mk
index 4f275331df..14aa27d52d 100644
--- a/repos/base-linux/lib/mk/base-common.mk
+++ b/repos/base-linux/lib/mk/base-common.mk
@@ -20,6 +20,7 @@ SRC_CC += env/rm_session_mmap.cc env/debug.cc
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += thread/trace.cc thread/thread_env.cc thread/context_allocator.cc
+SRC_CC += irq/platform.cc
INC_DIR += $(REP_DIR)/src/base/lock $(BASE_DIR)/src/base/lock
INC_DIR += $(REP_DIR)/src/base/ipc
diff --git a/repos/base-linux/src/core/include/irq_session_component.h b/repos/base-linux/src/core/include/irq_session_component.h
index ff6bbbf881..f45e54ec94 100644
--- a/repos/base-linux/src/core/include/irq_session_component.h
+++ b/repos/base-linux/src/core/include/irq_session_component.h
@@ -15,46 +15,38 @@
#define _CORE__INCLUDE__LINUX__IRQ_SESSION_COMPONENT_H_
#include
-#include
#include
#include
namespace Genode {
-
- class Irq_session_component : public List::Element
- {
- public:
-
- /**
- * Constructor
- *
- * \param cap_session capability session to use
- * \param irq_alloc platform-dependent IRQ allocator
- * \param args session construction arguments
- */
- Irq_session_component(Cap_session *cap_session,
- Range_allocator *irq_alloc,
- const char *args) { }
-
- /**
- * Destructor
- */
- ~Irq_session_component() { }
-
- /**
- * Return capability to this session
- *
- * Capability is always invalid under Linux.
- */
- Session_capability cap() const { return Session_capability(); }
-
-
- /***************************
- ** Irq session interface **
- ***************************/
-
- void wait_for_irq() { }
- };
+ class Irq_session_component;
}
+class Genode::Irq_session_component : public Rpc_object,
+ public List::Element
+{
+ public:
+
+ /**
+ * Constructor
+ *
+ * \param irq_alloc platform-dependent IRQ allocator
+ * \param args session construction arguments
+ */
+ Irq_session_component(Range_allocator *irq_alloc,
+ const char *args) { }
+
+ /**
+ * Destructor
+ */
+ ~Irq_session_component() { }
+
+ /***************************
+ ** Irq session interface **
+ ***************************/
+
+ void ack_irq() { }
+ void sigh(Signal_context_capability) override { }
+};
+
#endif /* _CORE__INCLUDE__LINUX__IRQ_SESSION_COMPONENT_H_ */
diff --git a/repos/base-nova/src/core/include/irq_session_component.h b/repos/base-nova/src/core/include/irq_session_component.h
deleted file mode 100644
index 89dd6d8335..0000000000
--- a/repos/base-nova/src/core/include/irq_session_component.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * \brief IRQ session interface for NOVA
- * \author Norman Feske
- * \date 2010-01-30
- */
-
-/*
- * Copyright (C) 2010-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 _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
-#define _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
-
-#include
-#include
-#include
-
-#include
-
-namespace Genode {
-
- class Irq_proxy_component;
-
- class Irq_session_component : public Rpc_object,
- public List::Element
- {
- private:
-
- /*
- * Each IRQ session uses a dedicated server activation
- */
- enum { STACK_SIZE = 2048 };
- Rpc_entrypoint _ep;
- Irq_session_capability _irq_cap;
- Irq_proxy_component *_proxy;
-
- public:
-
- /**
- * Constructor
- *
- * \param cap_session capability session to use
- * \param irq_alloc platform-dependent IRQ allocator
- * \param args session construction arguments
- */
- Irq_session_component(Cap_session *cap_session,
- Range_allocator *irq_alloc,
- const char *args);
-
- /**
- * Destructor
- */
- ~Irq_session_component();
-
- /**
- * Return capability to this session
- *
- * If an initialization error occurs, returned capability is invalid.
- */
- Irq_session_capability cap() const { return _irq_cap; }
-
-
- /***************************
- ** Irq session interface **
- ***************************/
-
- void wait_for_irq();
- Irq_signal signal();
- };
-}
-
-#endif /* _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ */
diff --git a/repos/base-nova/src/core/irq_session_component.cc b/repos/base-nova/src/core/irq_session_component.cc
index 61aab161c3..9c1e89e416 100644
--- a/repos/base-nova/src/core/irq_session_component.cc
+++ b/repos/base-nova/src/core/irq_session_component.cc
@@ -170,43 +170,68 @@ class Genode::Irq_proxy_component : public Irq_proxy
};
-typedef Irq_proxy Proxy;
-void Irq_session_component::wait_for_irq()
+/***************************
+ ** IRQ session component **
+ ***************************/
+
+
+void Irq_session_component::ack_irq()
{
- _proxy->wait_for_irq();
- /* interrupt ocurred and proxy woke us up */
+ if (!_proxy) {
+ PERR("Expected to find IRQ proxy for IRQ %02x", _irq_number);
+ return;
+ }
+
+ _proxy->ack_irq();
}
-Irq_session_component::Irq_session_component(Cap_session *cap_session,
- Range_allocator *irq_alloc,
+Irq_session_component::Irq_session_component(Range_allocator *irq_alloc,
const char *args)
-:
- _ep(cap_session, STACK_SIZE, "irq")
{
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
-
- /* check if IRQ thread was started before */
- _proxy = Proxy::get_irq_proxy(irq_number, irq_alloc);
- if (irq_number == -1 || !_proxy) {
- PERR("Unavailable IRQ %lx requested", irq_number);
+ if (irq_number == -1) {
+ PERR("invalid IRQ number requested");
throw Root::Unavailable();
}
- _proxy->add_sharer();
+ /* check if IRQ thread was started before */
+ typedef Irq_proxy Proxy;
+ _proxy = Proxy::get_irq_proxy(irq_number, irq_alloc);
+ if (!_proxy) {
+ PERR("unavailable IRQ %lx requested", irq_number);
+ throw Root::Unavailable();
+ }
- /* initialize capability */
- _irq_cap = _ep.manage(this);
+ _irq_number = irq_number;
}
-Irq_session_component::~Irq_session_component() { }
-
-
-Irq_signal Irq_session_component::signal()
+Irq_session_component::~Irq_session_component()
{
- PDBG("not implemented;");
- return Irq_signal();
+ if (_proxy) return;
+
+ if (_irq_sigh.valid())
+ _proxy->remove_sharer(&_irq_sigh);
+}
+
+
+void Irq_session_component::sigh(Genode::Signal_context_capability sigh)
+{
+ if (!_proxy) {
+ PERR("signal handler got not registered - irq thread unavailable");
+ return;
+ }
+
+ Genode::Signal_context_capability old = _irq_sigh;
+
+ if (old.valid() && !sigh.valid())
+ _proxy->remove_sharer(&_irq_sigh);
+
+ _irq_sigh = sigh;
+
+ if (!old.valid() && sigh.valid())
+ _proxy->add_sharer(&_irq_sigh);
}
diff --git a/repos/base-okl4/src/core/irq_session_component.cc b/repos/base-okl4/src/core/irq_session_component.cc
index 5806b6c41e..5ef06c72f5 100644
--- a/repos/base-okl4/src/core/irq_session_component.cc
+++ b/repos/base-okl4/src/core/irq_session_component.cc
@@ -12,10 +12,12 @@
* under the terms of the GNU General Public License version 2.
*/
-#include
+/* Genode includes */
+#include
+#include
/* core includes */
-#include
+#include
/* OKL4 includes */
namespace Okl4 { extern "C" {
@@ -30,12 +32,6 @@ using namespace Okl4;
using namespace Genode;
-/**
- * Proxy class with generic thread
- */
-typedef Irq_proxy > Proxy;
-
-
/* XXX move this functionality to a central place instead of duplicating it */
static inline Okl4::L4_ThreadId_t thread_get_my_global_id()
{
@@ -44,11 +40,15 @@ static inline Okl4::L4_ThreadId_t thread_get_my_global_id()
return myself;
}
+namespace Genode {
+ typedef Irq_proxy > Irq_proxy_base;
+ class Irq_proxy_component;
+}
/**
* Platform-specific proxy code
*/
-class Irq_proxy_component : public Proxy
+class Genode::Irq_proxy_component : public Irq_proxy_base
{
protected:
@@ -80,13 +80,14 @@ class Irq_proxy_component : public Proxy
/* prepare ourself to receive asynchronous IRQ notifications */
L4_Set_NotifyMask(1 << IRQ_NOTIFY_BIT);
- L4_Accept(L4_NotifyMsgAcceptor);
return true;
}
void _wait_for_irq()
{
+ L4_Accept(L4_NotifyMsgAcceptor);
+
/* wait for asynchronous interrupt notification */
L4_ThreadId_t partner = L4_nilthread;
L4_ReplyWait(partner, &partner);
@@ -111,35 +112,23 @@ class Irq_proxy_component : public Proxy
** IRQ session component **
***************************/
-bool Irq_session_component::Irq_control_component::associate_to_irq(unsigned irq)
-{
- return true;
-}
-
-void Irq_session_component::wait_for_irq()
+void Irq_session_component::ack_irq()
{
/* block at interrupt proxy */
- Proxy *p = Proxy::get_irq_proxy(_irq_number);
- if (!p) {
+ if (!_proxy) {
PERR("Expected to find IRQ proxy for IRQ %02x", _irq_number);
return;
}
- p->wait_for_irq();
-
- /* interrupt ocurred and proxy woke us up */
+ _proxy->ack_irq();
}
-Irq_session_component::Irq_session_component(Cap_session *cap_session,
- Range_allocator *irq_alloc,
+Irq_session_component::Irq_session_component(Range_allocator *irq_alloc,
const char *args)
:
- _irq_alloc(irq_alloc),
- _ep(cap_session, STACK_SIZE, "irqctrl"),
- _irq_attached(false),
- _control_client(Capability())
+ _irq_alloc(irq_alloc)
{
/*
* XXX Removed irq_shared argument as this is the default now. If we need
@@ -154,30 +143,39 @@ Irq_session_component::Irq_session_component(Cap_session *cap_session,
}
/* check if IRQ thread was started before */
- Proxy *irq_proxy = Proxy::get_irq_proxy(irq_number, irq_alloc);
- if (!irq_proxy) {
+ _proxy = Irq_proxy_component::get_irq_proxy(irq_number, irq_alloc);
+ if (!_proxy) {
PERR("unavailable IRQ %lx requested", irq_number);
-
throw Root::Unavailable();
}
- irq_proxy->add_sharer();
_irq_number = irq_number;
-
- /* initialize capability */
- _irq_cap = _ep.manage(this);
}
Irq_session_component::~Irq_session_component()
{
- PERR("not yet implemented");
- /* TODO del_sharer() resp. put_sharer() */
+ if (!_proxy) return;
+
+ if (_irq_sigh.valid())
+ _proxy->remove_sharer(&_irq_sigh);
}
-Irq_signal Irq_session_component::signal()
+void Irq_session_component::sigh(Genode::Signal_context_capability sigh)
{
- PDBG("not implemented;");
- return Irq_signal();
+ if (!_proxy) {
+ PERR("signal handler got not registered - irq thread unavailable");
+ return;
+ }
+
+ Genode::Signal_context_capability old = _irq_sigh;
+
+ if (old.valid() && !sigh.valid())
+ _proxy->remove_sharer(&_irq_sigh);
+
+ _irq_sigh = sigh;
+
+ if (!old.valid() && sigh.valid())
+ _proxy->add_sharer(&_irq_sigh);
}
diff --git a/repos/base-pistachio/src/core/irq_session_component.cc b/repos/base-pistachio/src/core/irq_session_component.cc
index df67eb1f39..c985d862ad 100644
--- a/repos/base-pistachio/src/core/irq_session_component.cc
+++ b/repos/base-pistachio/src/core/irq_session_component.cc
@@ -18,6 +18,7 @@
#include
/* core includes */
+#include
#include
#include
@@ -39,102 +40,161 @@ static inline L4_ThreadId_t irqno_to_threadid(unsigned int irqno)
}
-bool Irq_session_component::Irq_control_component::associate_to_irq(unsigned)
-{
- /*
- * We defer the association with the IRQ to the first call of the
- * 'wait_for_irq' function.
- */
- return true;
+namespace Genode {
+ typedef Irq_proxy > Irq_proxy_base;
+ class Irq_proxy_component;
}
-void Irq_session_component::wait_for_irq()
+/**
+ * Platform-specific proxy code
+ */
+
+class Genode::Irq_proxy_component : public Irq_proxy_base
{
- L4_ThreadId_t irq_thread = irqno_to_threadid(_irq_number);
+ private:
- /* attach to IRQ when called for the first time */
- L4_MsgTag_t res;
- if (!_irq_attached) {
+ /*
+ * On Pistachio, an IRQ is unmasked right after attaching.
+ * Hence, the kernel may send an IRQ IPC when the IRQ hander is
+ * not explicitly waiting for an IRQ but when it is waiting for
+ * a client's 'wait_for_irq' RPC call. To avoid this conflict, we
+ * lazily associate to the IRQ when calling the 'wait_for_irq'
+ * function for the first time. We use the '_irq_attached' flag
+ * for detecting the first call.
+ */
+ bool _irq_attached; /* true if IRQ is already attached */
- if (L4_AssociateInterrupt(irq_thread, L4_Myself()) != true) {
- PERR("L4_AssociateInterrupt failed");
- return;
+ protected:
+
+ bool _associate() { return true; }
+
+ void _wait_for_irq()
+ {
+ L4_ThreadId_t irq_thread = irqno_to_threadid(_irq_number);
+
+ /* attach to IRQ when called for the first time */
+ L4_MsgTag_t res;
+ if (!_irq_attached) {
+
+ if (L4_AssociateInterrupt(irq_thread, L4_Myself()) != true) {
+ PERR("L4_AssociateInterrupt failed");
+ return;
+ }
+
+ /*
+ * Right after associating with an interrupt, the interrupt is
+ * unmasked. Hence, we do not need to send an unmask message
+ * to the IRQ thread but just wait for the IRQ.
+ */
+ L4_Set_MsgTag(L4_Niltag);
+ res = L4_Receive(irq_thread);
+
+ /*
+ * Now, the IRQ is masked. To receive the next IRQ we have to send
+ * an unmask message to the IRQ thread first.
+ */
+ _irq_attached = true;
+
+ /* receive subsequent interrupt */
+ } else {
+
+ /* send unmask message and wait for new IRQ */
+ L4_Set_MsgTag(L4_Niltag);
+ res = L4_Call(irq_thread);
+ }
+
+ if (L4_IpcFailed(res)) {
+ PERR("ipc error while waiting for interrupt.");
+ return;
+ }
}
- /*
- * Right after associating with an interrupt, the interrupt is
- * unmasked. Hence, we do not need to send an unmask message
- * to the IRQ thread but just wait for the IRQ.
- */
- L4_Set_MsgTag(L4_Niltag);
- res = L4_Receive(irq_thread);
+ void _ack_irq() { }
- /*
- * Now, the IRQ is masked. To receive the next IRQ we have to send
- * an unmask message to the IRQ thread first.
- */
- _irq_attached = true;
+ public:
- /* receive subsequent interrupt */
- } else {
+ Irq_proxy_component(long irq_number)
+ :
+ Irq_proxy(irq_number),
+ _irq_attached(false)
+ {
+ _start();
+ }
- /* send unmask message and wait for new IRQ */
- L4_Set_MsgTag(L4_Niltag);
- res = L4_Call(irq_thread);
- }
+ ~Irq_proxy_component()
+ {
+ L4_ThreadId_t const thread_id = irqno_to_threadid(_irq_number);
+ L4_Word_t const res = L4_DeassociateInterrupt(thread_id);
- if (L4_IpcFailed(res)) {
- PERR("ipc error while waiting for interrupt.");
+ if (res != 1)
+ PERR("L4_DeassociateInterrupt failed");
+ }
+};
+
+
+/***************************
+ ** IRQ session component **
+ ***************************/
+
+
+void Irq_session_component::ack_irq()
+{
+ if (!_proxy) {
+ PERR("Expected to find IRQ proxy for IRQ %02x", _irq_number);
return;
}
+
+ _proxy->ack_irq();
}
-Irq_session_component::Irq_session_component(Cap_session *cap_session,
- Range_allocator *irq_alloc,
+Irq_session_component::Irq_session_component(Range_allocator *irq_alloc,
const char *args)
:
- _irq_alloc(irq_alloc),
- _ep(cap_session, STACK_SIZE, "irqctrl"),
- _irq_attached(false),
- _control_client(Capability())
+ _irq_alloc(irq_alloc)
{
- bool shared = Arg_string::find_arg(args, "irq_shared").bool_value(false);
- if (shared) {
- PWRN("IRQ sharing not supported");
-
- /* FIXME error condition -> exception */
- return;
- }
-
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
- if (irq_number == -1 || !irq_alloc ||
- irq_alloc->alloc_addr(1, irq_number).is_error()) {
- PERR("unavailable IRQ %lx requested", irq_number);
+ if (irq_number == -1) {
+ PERR("invalid IRQ number requested");
- /* FIXME error condition -> exception */
- return;
+ throw Root::Unavailable();
}
- _irq_number = irq_number;
- /* initialize capability */
- _irq_cap = _ep.manage(this);
+ /* check if IRQ thread was started before */
+ _proxy = Irq_proxy_component::get_irq_proxy(irq_number, irq_alloc);
+ if (!_proxy) {
+ PERR("unavailable IRQ %lx requested", irq_number);
+ throw Root::Unavailable();
+ }
+
+ _irq_number = irq_number;
}
Irq_session_component::~Irq_session_component()
{
- L4_Word_t res = L4_DeassociateInterrupt(irqno_to_threadid(_irq_number));
+ if (!_proxy) return;
- if (res != 1) {
- PERR("L4_DeassociateInterrupt failed");
- }
+ if (_irq_sigh.valid())
+ _proxy->remove_sharer(&_irq_sigh);
}
-Irq_signal Irq_session_component::signal()
+void Irq_session_component::sigh(Genode::Signal_context_capability sigh)
{
- PDBG("not implemented;");
- return Irq_signal();
+ if (!_proxy) {
+ PERR("signal handler got not registered - irq thread unavailable");
+ return;
+ }
+
+ Genode::Signal_context_capability old = _irq_sigh;
+
+ if (old.valid() && !sigh.valid())
+ _proxy->remove_sharer(&_irq_sigh);
+
+ _irq_sigh = sigh;
+
+ if (!old.valid() && sigh.valid())
+ _proxy->add_sharer(&_irq_sigh);
}
diff --git a/repos/base/include/irq_session/client.h b/repos/base/include/irq_session/client.h
index c19218aef0..d0cecef3bc 100644
--- a/repos/base/include/irq_session/client.h
+++ b/repos/base/include/irq_session/client.h
@@ -26,11 +26,6 @@ namespace Genode { struct Irq_session_client; }
*/
struct Genode::Irq_session_client : Rpc_client
{
- /*
- * FIXME: This is used only client-internal and could thus be protected.
- */
- Irq_signal const irq_signal;
-
/**
* Constructor
*
@@ -38,8 +33,7 @@ struct Genode::Irq_session_client : Rpc_client
*/
explicit Irq_session_client(Irq_session_capability const & session)
:
- Rpc_client(session),
- irq_signal(signal())
+ Rpc_client(session)
{ }
@@ -47,9 +41,9 @@ struct Genode::Irq_session_client : Rpc_client
** Irq_session **
*****************/
- Irq_signal signal() override { return call(); }
+ void ack_irq() override;
- void wait_for_irq() override;
+ void sigh(Signal_context_capability sigh) override { call(sigh); }
};
#endif /* _INCLUDE__IRQ_SESSION__CLIENT_H_ */
diff --git a/repos/base/include/irq_session/connection.h b/repos/base/include/irq_session/connection.h
index 70012b2a30..cdf3ada81b 100644
--- a/repos/base/include/irq_session/connection.h
+++ b/repos/base/include/irq_session/connection.h
@@ -21,22 +21,47 @@ namespace Genode { struct Irq_connection; }
struct Genode::Irq_connection : Connection, Irq_session_client
{
- /**
- * Constructor
- *
- * \param irq physical interrupt number
- * \param trigger interrupt trigger (e.g., level/edge)
- * \param polarity interrupt trigger polarity (e.g., low/high)
- */
- Irq_connection(unsigned irq,
- Irq_session::Trigger trigger = Irq_session::TRIGGER_UNCHANGED,
- Irq_session::Polarity polarity = Irq_session::POLARITY_UNCHANGED)
- :
- Connection(
- session("ram_quota=4K, irq_number=%u, irq_trigger=%u, irq_polarity=%u",
- irq, trigger, polarity)),
- Irq_session_client(cap())
- { }
+
+ private:
+
+ Genode::Signal_receiver _sig_rec;
+ Genode::Signal_context _sigh_ctx;
+ Genode::Signal_context_capability _sigh_cap;
+
+ public:
+
+ /**
+ * Constructor
+ *
+ * \param irq physical interrupt number
+ * \param trigger interrupt trigger (e.g., level/edge)
+ * \param polarity interrupt trigger polarity (e.g., low/high)
+ */
+ Irq_connection(unsigned irq,
+ Irq_session::Trigger trigger = Irq_session::TRIGGER_UNCHANGED,
+ Irq_session::Polarity polarity = Irq_session::POLARITY_UNCHANGED)
+ :
+ Connection(
+ session("ram_quota=4K, irq_number=%u, irq_trigger=%u, irq_polarity=%u",
+ irq, trigger, polarity)),
+ Irq_session_client(cap()),
+ _sigh_cap(_sig_rec.manage(&_sigh_ctx))
+ {
+ /* register default signal handler */
+ Irq_session_client::sigh(_sigh_cap);
+ }
+
+ ~Irq_connection()
+ {
+ Irq_session_client::sigh(Genode::Signal_context_capability());
+ _sig_rec.dissolve(&_sigh_ctx);
+ }
+
+ /**
+ * Convenience function to acknowledge last IRQ and to block calling
+ * thread until next IRQ fires.
+ */
+ void wait_for_irq();
};
#endif /* _INCLUDE__IRQ_SESSION__CONNECTION_H_ */
diff --git a/repos/base/include/irq_session/irq_session.h b/repos/base/include/irq_session/irq_session.h
index 0fd7c1955f..a204700100 100644
--- a/repos/base/include/irq_session/irq_session.h
+++ b/repos/base/include/irq_session/irq_session.h
@@ -6,8 +6,7 @@
*
* An open IRQ session represents a valid IRQ attachment/association.
* Initially, the interrupt is masked and will only occur if enabled. This is
- * done by calling wait_for_irq(). When the interrupt is delivered to the
- * client, it was acknowledged and masked at the interrupt controller before.
+ * done by calling ack_irq().
*
* Disassociation from an IRQ is done by closing the session.
*/
@@ -22,25 +21,15 @@
#ifndef _INCLUDE__IRQ_SESSION__IRQ_SESSION_H_
#define _INCLUDE__IRQ_SESSION__IRQ_SESSION_H_
+#include
#include
#include
namespace Genode {
struct Irq_session;
- struct Irq_signal;
}
-/**
- * Information that enables a user to await and ack an IRQ directly
- */
-struct Genode::Irq_signal
-{
- unsigned receiver_id;
- unsigned context_id;
-};
-
-
struct Genode::Irq_session : Session
{
/**
@@ -59,17 +48,14 @@ struct Genode::Irq_session : Session
virtual ~Irq_session() { }
/**
- * Await the next occurence of the interrupt of this session
+ * Acknowledge handling of last interrupt - re-enables interrupt reception
*/
- virtual void wait_for_irq() = 0;
+ virtual void ack_irq() = 0;
/**
- * Get information for direct interrupt handling
- *
- * FIXME: This is used only client-internal and could thus be protected.
+ * Register irq signal handler
*/
- virtual Irq_signal signal() = 0;
-
+ virtual void sigh(Genode::Signal_context_capability sigh) = 0;
/*************
** Session **
@@ -82,9 +68,9 @@ struct Genode::Irq_session : Session
** RPC declaration **
*********************/
- GENODE_RPC(Rpc_wait_for_irq, void, wait_for_irq);
- GENODE_RPC(Rpc_signal, Irq_signal, signal);
- GENODE_RPC_INTERFACE(Rpc_wait_for_irq, Rpc_signal);
+ GENODE_RPC(Rpc_ack_irq, void, ack_irq);
+ GENODE_RPC(Rpc_sigh, void, sigh, Genode::Signal_context_capability);
+ GENODE_RPC_INTERFACE(Rpc_ack_irq, Rpc_sigh);
};
#endif /* _INCLUDE__IRQ_SESSION__IRQ_SESSION_H_ */
diff --git a/repos/base/src/base/irq/platform.cc b/repos/base/src/base/irq/platform.cc
index e2bc9cd7c8..73c837b018 100644
--- a/repos/base/src/base/irq/platform.cc
+++ b/repos/base/src/base/irq/platform.cc
@@ -11,9 +11,18 @@
* under the terms of the GNU General Public License version 2.
*/
-#include
+#include
-void Genode::Irq_session_client::wait_for_irq()
+void Genode::Irq_session_client::ack_irq()
{
- call();
+ call();
+}
+
+
+void Genode::Irq_connection::wait_for_irq()
+{
+ ack_irq();
+ Signal s = _sig_rec.wait_for_signal();
+ if (s.num() != 1)
+ PWRN("unexpected number of IRqs received %u", s.num());
}
diff --git a/repos/base/src/core/include/irq_proxy.h b/repos/base/src/core/include/irq_proxy.h
index ff4a9cd4aa..463957948a 100644
--- a/repos/base/src/core/include/irq_proxy.h
+++ b/repos/base/src/core/include/irq_proxy.h
@@ -9,36 +9,34 @@
#define _CORE__INCLUDE__IRQ_PROXY_H_
#include
-#include
-#include
namespace Genode {
- class Irq_blocker;
+ class Irq_sigh;
template class Irq_proxy;
- class Irq_thread_dummy;
- class Irq_proxy_single;
}
-class Genode::Irq_blocker : public Genode::List::Element
+class Genode::Irq_sigh : public Genode::Signal_context_capability,
+ public Genode::List::Element
{
- private:
-
- Lock _wait_lock;
-
public:
- Irq_blocker() : _wait_lock(Lock::LOCKED) { }
+ inline Irq_sigh * operator= (const Signal_context_capability &cap)
+ {
+ Signal_context_capability::operator=(cap);
+ return this;
+ }
- void block() { _wait_lock.lock(); }
- void unblock() { _wait_lock.unlock(); }
+ Irq_sigh() { }
+
+ void notify() { Genode::Signal_transmitter(*this).submit(1); }
};
/*
* Proxy thread that associates to the interrupt and unblocks waiting irqctrl
- * threads. Maybe, we should utilize our signals for interrupt delivery...
+ * threads.
*
* XXX resources are not accounted as the interrupt is shared
*/
@@ -56,8 +54,8 @@ class Genode::Irq_proxy : public THREAD,
Lock _mutex; /* protects this object */
int _num_sharers; /* number of clients sharing this IRQ */
Semaphore _sleep; /* wake me up if aspired blockers return */
- List _blocker_list;
- int _num_blockers; /* number of currently blocked clients */
+ List _sigh_list;
+ int _num_acknowledgers; /* number of currently blocked clients */
bool _woken_up; /* client decided to wake me up -
this prevents multiple wakeups
to happen during initialization */
@@ -102,20 +100,8 @@ class Genode::Irq_proxy : public THREAD,
while (1) {
_wait_for_irq();
- {
- Lock::Guard lock_guard(_mutex);
-
- /* inform blocked clients */
- Irq_blocker *b;
- while ((b = _blocker_list.first())) {
- _blocker_list.remove(b);
- b->unblock();
- }
-
- /* reset blocker state */
- _num_blockers = 0;
- _woken_up = false;
- }
+ /* notify all */
+ notify_about_irq(1);
/*
* We must wait for all clients to ack their interrupt,
@@ -146,7 +132,8 @@ class Genode::Irq_proxy : public THREAD,
:
THREAD(_construct_name(irq_number)),
_startup_lock(Lock::LOCKED), _irq_number(irq_number),
- _mutex(Lock::UNLOCKED), _num_sharers(0), _num_blockers(0), _woken_up(false)
+ _mutex(Lock::UNLOCKED), _num_sharers(0), _num_acknowledgers(0), _woken_up(false)
+
{ }
/**
@@ -163,43 +150,68 @@ class Genode::Irq_proxy : public THREAD,
}
/**
- * Block until interrupt occured
+ * Acknowledgements of clients
*/
- virtual void wait_for_irq()
+ virtual bool ack_irq()
{
- Irq_blocker blocker;
- {
- Lock::Guard lock_guard(_mutex);
+ Lock::Guard lock_guard(_mutex);
- _blocker_list.insert(&blocker);
- _num_blockers++;
+ _num_acknowledgers++;
- /*
- * The proxy thread is woken up if no client woke it up before
- * and this client is the last aspired blocker.
- */
- if (!_woken_up && _num_blockers == _num_sharers) {
- _sleep.up();
- _woken_up = true;
- }
+ /*
+ * The proxy thread has to be woken up if no client woke it up
+ * before and this client is the last aspired acknowledger.
+ */
+ if (!_woken_up && _num_acknowledgers == _num_sharers) {
+ _sleep.up();
+ _woken_up = true;
}
- blocker.block();
+
+ return _woken_up;
}
+ /**
+ * Notify all clients about irq
+ */
+ void notify_about_irq(unsigned)
+ {
+ Lock::Guard lock_guard(_mutex);
+
+ /* reset acknowledger state */
+ _num_acknowledgers = 0;
+ _woken_up = false;
+
+ /* inform blocked clients */
+ for (Irq_sigh * s = _sigh_list.first(); s ; s = s->next())
+ s->notify();
+ }
long irq_number() const { return _irq_number; }
- virtual bool add_sharer()
+ virtual bool add_sharer(Irq_sigh *s)
{
Lock::Guard lock_guard(_mutex);
+
++_num_sharers;
+ _sigh_list.insert(s);
+
return true;
}
- virtual void remove_sharer()
+ virtual void remove_sharer(Irq_sigh *s)
{
Lock::Guard lock_guard(_mutex);
+
+ _sigh_list.remove(s);
--_num_sharers;
+
+ if (_woken_up)
+ return;
+
+ if (_num_acknowledgers == _num_sharers) {
+ _sleep.up();
+ _woken_up = true;
+ }
}
template
@@ -225,51 +237,4 @@ class Genode::Irq_proxy : public THREAD,
}
};
-
-/**
- * Dummy thread
- */
-class Genode::Irq_thread_dummy
-{
- public:
-
- Irq_thread_dummy(char const *name) { }
- void start() { }
-};
-
-
-/**
- * Non-threaded proxy that disables shared interrupts
- */
-class Genode::Irq_proxy_single : public Genode::Irq_proxy
-{
- protected:
-
- void _start()
- {
- _associate();
- }
-
- public:
-
- Irq_proxy_single(long irq_number) : Irq_proxy(irq_number) { }
-
- bool add_sharer()
- {
- Lock::Guard lock_guard(_mutex);
-
- if (_num_sharers)
- return false;
-
- _num_sharers = 1;
- return true;
- }
-
- void wait_for_irq()
- {
- _wait_for_irq();
- _ack_irq();
- }
-};
-
#endif /* _CORE__INCLUDE__IRQ_PROXY_H_ */
diff --git a/repos/base/src/core/include/irq_root.h b/repos/base/src/core/include/irq_root.h
index 794e9a8380..573aa77dd0 100644
--- a/repos/base/src/core/include/irq_root.h
+++ b/repos/base/src/core/include/irq_root.h
@@ -1,13 +1,12 @@
/*
* \brief IRQ root interface
* \author Christian Helmuth
+ * \author Alexander Boettcher
* \date 2007-09-13
- *
- * FIXME locking
*/
/*
- * Copyright (C) 2007-2013 Genode Labs GmbH
+ * Copyright (C) 2007-2015 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.
@@ -16,98 +15,37 @@
#ifndef _CORE__INCLUDE__IRQ_ROOT_H_
#define _CORE__INCLUDE__IRQ_ROOT_H_
-/* Genode includes */
-#include
-#include
-#include
-#include
-
-/* core includes */
+#include
#include
-namespace Genode {
+namespace Genode { class Irq_root; }
- class Irq_root : public Rpc_object >
- {
+class Genode::Irq_root : public Root_component
+{
- private:
+ private:
- Cap_session *_cap_session;
- Range_allocator *_irq_alloc; /* platform irq allocator */
- Allocator *_md_alloc; /* meta-data allocator */
- List _sessions; /* started irq sessions */
+ Range_allocator *_irq_alloc; /* platform irq allocator */
- public:
+ protected:
- /**
- * Constructor
- *
- * \param cap_session capability allocator
- * \param irq_alloc IRQ range that can be assigned to clients
- * \param md_alloc meta-data allocator to be used by root component
- */
- Irq_root(Cap_session *cap_session,
- Range_allocator *irq_alloc,
- Allocator *md_alloc)
- : _cap_session(cap_session), _irq_alloc(irq_alloc), _md_alloc(md_alloc) { }
+ Irq_session_component *_create_session(const char *args) {
+ return new (md_alloc()) Irq_session_component(_irq_alloc, args); }
+ public:
- /********************
- ** Root interface **
- ********************/
-
- Session_capability session(Session_args const &args, Affinity const &affinity)
- {
- if (!args.is_valid_string()) throw Invalid_args();
-
- /*
- * We need to decrease 'ram_quota' by
- * the size of the session object.
- */
- size_t ram_quota = Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0);
- long remaining_ram_quota = ram_quota - sizeof(Irq_session_component) -
- _md_alloc->overhead(sizeof(Irq_session_component));
- if (remaining_ram_quota < 0) {
- PERR("Insufficient ram quota, provided=%zu, required=%zu",
- ram_quota, sizeof(Irq_session_component) +
- _md_alloc->overhead(sizeof(Irq_session_component)));
- return Session_capability();
- }
-
- Irq_session_component *s;
- try {
- s = new (_md_alloc) Irq_session_component(_cap_session, _irq_alloc, args.string());
- } catch (Allocator::Out_of_memory) { return Session_capability(); }
-
- if (!s->cap().valid())
- return Session_capability();
-
- _sessions.insert(s);
-
- return s->cap();
- }
-
- void upgrade(Session_capability, Upgrade_args const &)
- {
- /* there is no need to upgrade an IRQ session */
- }
-
- void close(Session_capability session)
- {
- Irq_session_component *s = _sessions.first();
-
- for (; s; s = s->next()) {
- if (s->cap().local_name() == session.local_name())
- break;
- }
- if (!s) return;
-
- _sessions.remove(s);
-
- /* XXX Currently we support only one client... */
- destroy(_md_alloc, s);
- }
- };
-}
+ /**
+ * Constructor
+ *
+ * \param session_ep entry point for managing irq session objects
+ * \param irq_alloc IRQ range that can be assigned to clients
+ * \param md_alloc meta-data allocator to be used by root component
+ */
+ Irq_root(Rpc_entrypoint *session_ep, Range_allocator *irq_alloc,
+ Allocator *md_alloc)
+ :
+ Root_component(session_ep, md_alloc),
+ _irq_alloc(irq_alloc) { }
+};
#endif /* _CORE__INCLUDE__IRQ_ROOT_H_ */
diff --git a/repos/base/src/core/include/irq_session_component.h b/repos/base/src/core/include/irq_session_component.h
index ea016af2a6..49249b635d 100644
--- a/repos/base/src/core/include/irq_session_component.h
+++ b/repos/base/src/core/include/irq_session_component.h
@@ -14,128 +14,51 @@
#ifndef _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
#define _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
-#include
#include
#include
#include
#include
#include
-
-/* XXX Notes
- *
- * - each H/W IRQ is an irq thread
- * - each irq thread has an Rpc_entrypoint
- * -> irq thread is special Server_activation
- * -> IRQ session is Rpc_object
- *
- * - session("IRQ", "irq_num=") -> Native_capability(irq_thread, cap)
- * - cap must be generated at CAP
- * - cap must be managed by irq_thread-local Rpc_entrypoint
- *
- * - irq thread states
- * 1. wait_for_client --[ client calls wait_for_irq ]--> 2.
- * 2. wait_for_irq --[ kernel signals irq ]--> 3.
- * 3. irq_occured --[ inform client about occurence ]--> 1.
- *
- * - irq thread roles
- * - Irq_server (Ipc_server) for client
- * - Fiasco_irq_client (Ipc_client) at kernel
- */
+#include
namespace Genode {
-
- class Irq_session_component : public Rpc_object,
- public List::Element
- {
- private:
-
- struct Irq_control
- {
- GENODE_RPC(Rpc_associate_to_irq, bool, associate_to_irq, unsigned);
- GENODE_RPC_INTERFACE(Rpc_associate_to_irq);
- };
-
- struct Irq_control_client : Rpc_client
- {
- Irq_control_client(Capability cap)
- : Rpc_client(cap) { }
-
- bool associate_to_irq(unsigned irq_number) {
- return call(irq_number); }
- };
-
- struct Irq_control_component : Rpc_object
- {
- /**
- * Associate to IRQ at Fiasco
- *
- * This is executed by the IRQ server activation itself.
- */
- bool associate_to_irq(unsigned irq_number);
- };
-
- unsigned _irq_number;
- Range_allocator *_irq_alloc;
-
- enum { STACK_SIZE = 2048 };
- Rpc_entrypoint _ep;
-
- /*
- * On Pistachio, an IRQ is unmasked right after attaching.
- * Hence, the kernel may send an IRQ IPC when the IRQ hander is
- * not explicitly waiting for an IRQ but when it is waiting for
- * a client's 'wait_for_irq' RPC call. To avoid this conflict, we
- * lazily associate to the IRQ when calling the 'wait_for_irq'
- * function for the first time. We use the '_irq_attached' flag
- * for detecting the first call. On other kernels, this variable
- * may be unused.
- */
- unsigned _irq_attached; /* true if IRQ is already attached */
-
-
- /********************************************
- ** IRQ control server (internal use only) **
- ********************************************/
-
- Irq_control_component _control_component; /* ctrl component */
- Capability _control_cap; /* capability for ctrl server */
- Irq_control_client _control_client; /* ctrl client */
- Capability _irq_cap; /* capability for IRQ */
-
- public:
-
- /**
- * Constructor
- *
- * \param cap_session capability session to use
- * \param irq_alloc platform-dependent IRQ allocator
- * \param args session construction arguments
- */
- Irq_session_component(Cap_session *cap_session,
- Range_allocator *irq_alloc,
- const char *args);
-
- /**
- * Destructor
- */
- ~Irq_session_component();
-
- /**
- * Return capability to this session
- *
- * If an initialization error occurs, returned _cap is invalid.
- */
- Capability cap() const { return _irq_cap; }
-
-
- /***************************
- ** Irq session interface **
- ***************************/
-
- void wait_for_irq();
- Irq_signal signal();
- };
+ class Irq_proxy_component;
+ class Irq_session_component;
}
+class Genode::Irq_session_component : public Rpc_object,
+ public List::Element
+{
+ private:
+
+ unsigned _irq_number;
+ Range_allocator *_irq_alloc;
+ Irq_proxy_component *_proxy;
+
+ Irq_sigh _irq_sigh;
+
+ public:
+
+ /**
+ * Constructor
+ *
+ * \param irq_alloc platform-dependent IRQ allocator
+ * \param args session construction arguments
+ */
+ Irq_session_component(Range_allocator *irq_alloc,
+ const char *args);
+
+ /**
+ * Destructor
+ */
+ ~Irq_session_component();
+
+ /***************************
+ ** Irq session interface **
+ ***************************/
+
+ void ack_irq();
+ void sigh(Signal_context_capability) override;
+};
+
#endif /* _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ */
diff --git a/repos/base/src/core/main.cc b/repos/base/src/core/main.cc
index cf300aca67..282817eda3 100644
--- a/repos/base/src/core/main.cc
+++ b/repos/base/src/core/main.cc
@@ -220,8 +220,7 @@ int main()
static Log_root log_root (e, &sliced_heap);
static Io_mem_root io_mem_root (e, e, platform()->io_mem_alloc(),
platform()->ram_alloc(), &sliced_heap);
- static Irq_root irq_root (core_env()->cap_session(),
- platform()->irq_alloc(), &sliced_heap);
+ static Irq_root irq_root (e, platform()->irq_alloc(), &sliced_heap);
static Trace::Root trace_root (e, &sliced_heap, trace_sources, trace_policies);
/*