diff --git a/base-foc/src/core/cpu_session_extension.cc b/base-foc/src/core/cpu_session_extension.cc index 5f1bf9a7e..2480b8d2f 100644 --- a/base-foc/src/core/cpu_session_extension.cc +++ b/base-foc/src/core/cpu_session_extension.cc @@ -24,6 +24,7 @@ namespace Fiasco { #include } +static Genode::Avl_tree _irq_tree; Genode::Ram_dataspace_capability Genode::Cpu_session_component::utcb(Genode::Thread_capability thread_cap) { @@ -69,18 +70,30 @@ Genode::Cpu_session_component::native_cap(Genode::Thread_capability cap) Genode::Native_capability Genode::Cpu_session_component::alloc_irq() { using namespace Fiasco; + using namespace Genode; + /* find irq object container of this cpu-session */ + Cpu_session_irqs* node = _irq_tree.first(); + if (node) + node = node->find_by_session(this); + + /* if not found, we've to create one */ + if (!node) { + node = new (&_md_alloc) Cpu_session_irqs(this); + _irq_tree.insert(node); + } + + /* construct irq kernel-object */ Cap_index* i = cap_map()->insert(platform_specific()->cap_id_alloc()->alloc()); l4_msgtag_t res = l4_factory_create_irq(L4_BASE_FACTORY_CAP, i->kcap()); - if (l4_error(res)) + if (l4_error(res)) { PWRN("Allocation of irq object failed!"); + return Genode::Native_capability(); + } - /* - * Increment reference-counter, because we don't hold any - * reference to IRQ object by now - */ - i->inc(); - return Genode::Native_capability(i); + /* construct cap and hold a reference in the irq container object */ + Genode::Native_capability cap(i); + return (node->add(cap)) ? cap : Genode::Native_capability(); } diff --git a/base-foc/src/core/include/cpu_session_component.h b/base-foc/src/core/include/cpu_session_component.h index 360995bab..2e48ecd32 100644 --- a/base-foc/src/core/include/cpu_session_component.h +++ b/base-foc/src/core/include/cpu_session_component.h @@ -151,6 +151,45 @@ namespace Genode { Native_capability native_cap(Thread_capability); Native_capability alloc_irq(); }; + + + class Cpu_session_irqs : public Avl_node + { + private: + + enum { IRQ_MAX = 20 }; + + Cpu_session_component* _owner; + Native_capability _irqs[IRQ_MAX]; + unsigned _cnt; + + public: + + Cpu_session_irqs(Cpu_session_component *owner) + : _owner(owner), _cnt(0) {} + + bool add(Native_capability irq) + { + if (_cnt >= (IRQ_MAX - 1)) + return false; + _irqs[_cnt++] = irq; + return true; + } + + /************************ + ** Avl node interface ** + ************************/ + + bool higher(Cpu_session_irqs *c) { return (c->_owner > _owner); } + + Cpu_session_irqs *find_by_session(Cpu_session_component *o) + { + if (o == _owner) return this; + + Cpu_session_irqs *c = Avl_node::child(o > _owner); + return c ? c->find_by_session(o) : 0; + } + }; } #endif /* _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_ */