diff --git a/base/include/util/fifo.h b/base/include/util/fifo.h index 709765002..92e5d12e6 100644 --- a/base/include/util/fifo.h +++ b/base/include/util/fifo.h @@ -22,11 +22,6 @@ namespace Genode { template class Fifo { - private: - - QT *_head; /* oldest element */ - QT *_tail; /* newest element */ - public: class Element @@ -46,8 +41,18 @@ namespace Genode { * Return true is fifo element is enqueued in a fifo */ bool is_enqueued() { return _is_enqueued; } + + /** + * Return next element in queue + */ + QT *next() const { return _next; } }; + private: + + QT *_head; /* oldest element */ + Element *_tail; /* newest element */ + public: /** @@ -62,6 +67,42 @@ namespace Genode { */ Fifo(): _head(0), _tail(0) { } + /** + * Return first queue element + */ + QT *head() const { return _head; } + + /** + * Remove element explicitely from queue + */ + void remove(QT *qe) + { + if (empty()) return; + + /* if specified element is the first of the queue */ + if (qe == _head) { + _head = qe->Element::_next; + if (!_head) _tail = 0; + } + else { + + /* search specified element in the queue */ + Element *e = _head; + while (e->_next && (e->_next != qe)) + e = e->_next; + + /* element is not member of the queue */ + if (!e->_next) return; + + /* e->_next is the element to remove, skip it in list */ + e->Element::_next = e->Element::_next->Element::_next; + if (!e->Element::_next) _tail = e; + } + + qe->Element::_next = 0; + qe->Element::_is_enqueued = 0; + } + /** * Attach element at the end of the queue */ @@ -89,9 +130,10 @@ namespace Genode { QT *result = _head; /* check if queue has only one last element */ - if (_head == _tail) - _head = _tail = 0; - else + if (_head == _tail) { + _head = 0; + _tail = 0; + } else _head = _head->Fifo::Element::_next; /* mark fifo queue element as free */ diff --git a/base/src/core/include/rm_session_component.h b/base/src/core/include/rm_session_component.h index 5e6df370b..e6795ca33 100644 --- a/base/src/core/include/rm_session_component.h +++ b/base/src/core/include/rm_session_component.h @@ -26,6 +26,7 @@ #include #include #include +#include /* core includes */ #include @@ -101,7 +102,7 @@ namespace Genode { * be able to handle faults by arbitrary clients (not only its own * clients), it maintains the list head of faulters. */ - class Rm_faulter : public List::Element + class Rm_faulter : public Fifo::Element { private: @@ -268,7 +269,7 @@ namespace Genode { detach, pagefaults */ List _regions; /* region list for destruction */ - List _faulters; /* list of threads that faulted at + Fifo _faulters; /* list of threads that faulted at the region-manager session and wait for fault resolution */ List _clients; /* list of RM clients using this RM diff --git a/base/src/core/rm_session_component.cc b/base/src/core/rm_session_component.cc index 88bf7d237..6456779df 100644 --- a/base/src/core/rm_session_component.cc +++ b/base/src/core/rm_session_component.cc @@ -413,9 +413,9 @@ Rm_session_component::attach(Dataspace_capability ds_cap, size_t size, dsc, dsc->phys_addr(), dsc->size(), offset, (addr_t)r, (addr_t)r + size); /* check if attach operation resolves any faulting region-manager clients */ - for (Rm_faulter *faulter = _faulters.first(); faulter; ) { + for (Rm_faulter *faulter = _faulters.head(); faulter; ) { - /* remeber next pointer before possibly removing current list element */ + /* remember next pointer before possibly removing current list element */ Rm_faulter *next = faulter->next(); if (faulter->fault_in_addr_range((addr_t)r, size)) { @@ -643,7 +643,7 @@ void Rm_session_component::fault(Rm_faulter *faulter, addr_t pf_addr, faulter->fault(this, Rm_session::State(pf_type, pf_addr)); /* enqueue faulter */ - _faulters.insert(faulter); + _faulters.enqueue(faulter); /* issue fault signal */ _fault_notifier.submit(); @@ -671,7 +671,7 @@ Rm_session::State Rm_session_component::state() Lock::Guard lock_guard(_lock); /* pick one of the currently faulted threads */ - Rm_faulter *faulter = _faulters.first(); + Rm_faulter *faulter = _faulters.head(); /* return ready state if there are not current faulters */ if (!faulter) @@ -741,7 +741,7 @@ Rm_session_component::~Rm_session_component() _ds_ep->dissolve(&_ds); /* remove all faulters with pending page faults at this rm session */ - while (Rm_faulter *faulter = _faulters.first()) { + while (Rm_faulter *faulter = _faulters.head()) { _lock.unlock(); faulter->dissolve_from_faulting_rm_session(); _lock.lock();