mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 08:25:38 +00:00
base & core: Use FIFO to queue RM faulters.
By now RM faulters are hold in a LIFO. Thus a starvation problem occurs on managed dataspaces when multiple threads throw pagefaults continuously.
This commit is contained in:
parent
05f5999e71
commit
b7c1404fbf
@ -22,11 +22,6 @@ namespace Genode {
|
||||
template <typename QT>
|
||||
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 */
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <base/signal.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <util/list.h>
|
||||
#include <util/fifo.h>
|
||||
|
||||
/* core includes */
|
||||
#include <platform.h>
|
||||
@ -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<Rm_faulter>::Element
|
||||
class Rm_faulter : public Fifo<Rm_faulter>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
@ -268,7 +269,7 @@ namespace Genode {
|
||||
detach, pagefaults */
|
||||
List<Rm_region_ref> _regions; /* region list for destruction */
|
||||
|
||||
List<Rm_faulter> _faulters; /* list of threads that faulted at
|
||||
Fifo<Rm_faulter> _faulters; /* list of threads that faulted at
|
||||
the region-manager session and wait
|
||||
for fault resolution */
|
||||
List<Rm_client> _clients; /* list of RM clients using this RM
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user