Remove pointers from Genode::Fifo interface

Replace methods of Genode::Fifo returning pointers with methods which
call lambdas with references.

Ref #3135
This commit is contained in:
Ehmry - 2019-01-29 19:29:03 +01:00 committed by Norman Feske
parent 328c1ad96e
commit 38ab456c78
26 changed files with 367 additions and 380 deletions

View File

@ -35,7 +35,7 @@ using namespace Genode;
void Signal_source_component::release(Signal_context_component &context) void Signal_source_component::release(Signal_context_component &context)
{ {
if (context.enqueued()) if (context.enqueued())
_signal_queue.remove(&context); _signal_queue.remove(context);
} }
void Signal_source_component::submit(Signal_context_component &context, void Signal_source_component::submit(Signal_context_component &context,
@ -45,7 +45,7 @@ void Signal_source_component::submit(Signal_context_component &context,
context.increment_signal_cnt(cnt); context.increment_signal_cnt(cnt);
if (!context.enqueued()) { if (!context.enqueued()) {
_signal_queue.enqueue(&context); _signal_queue.enqueue(context);
/* wake up client */ /* wake up client */
Fiasco::l4_irq_trigger(_blocking_semaphore.data()->kcap()); Fiasco::l4_irq_trigger(_blocking_semaphore.data()->kcap());
@ -61,9 +61,11 @@ Signal_source::Signal Signal_source_component::wait_for_signal()
} }
/* dequeue and return pending signal */ /* dequeue and return pending signal */
Signal_context_component &context = *_signal_queue.dequeue(); Signal result { };
Signal result(context.imprint(), context.cnt()); _signal_queue.dequeue([&result] (Signal_context_component &context) {
context.reset_signal_cnt(); result = Signal(context.imprint(), context.cnt());
context.reset_signal_cnt();
});
return result; return result;
} }

View File

@ -1,43 +0,0 @@
/*
* \brief Queue with first-in first-out semantics
* \author Martin Stein
* \date 2012-11-30
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _CORE__KERNEL__FIFO_H_
#define _CORE__KERNEL__FIFO_H_
/* Genode includes */
#include <util/fifo.h>
namespace Kernel {
/**
* Queue with first-in first-out semantics
*
* \param T queue element type
*/
template <typename T>
class Fifo : public Genode::Fifo<T>
{
public:
/**
* Call function 'f' of type 'void (QT *)' for each queue element
*/
template <typename F> void for_each(F f)
{
typedef Genode::Fifo<T> B;
for (T * e = B::head(); e; e = e->B::Element::next()) { f(e); }
}
};
}
#endif /* _CORE__KERNEL__FIFO_H_ */

View File

@ -6,7 +6,7 @@
*/ */
/* /*
* Copyright (C) 2012-2017 Genode Labs GmbH * Copyright (C) 2012-2019 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
@ -110,15 +110,14 @@ void Ipc_node::_announce_request(Ipc_node &node)
} }
/* cannot receive yet, so queue request */ /* cannot receive yet, so queue request */
_request_queue.enqueue(&node); _request_queue.enqueue(node);
} }
void Ipc_node::_cancel_request_queue() void Ipc_node::_cancel_request_queue()
{ {
Ipc_node * node; _request_queue.dequeue_all([] (Ipc_node &node) {
while ((node = _request_queue.dequeue())) node._outbuf_request_cancelled(); });
node->_outbuf_request_cancelled();
} }
@ -143,7 +142,7 @@ void Ipc_node::_cancel_inbuf_request()
void Ipc_node::_announced_request_cancelled(Ipc_node &node) void Ipc_node::_announced_request_cancelled(Ipc_node &node)
{ {
if (_caller == &node) _caller = nullptr; if (_caller == &node) _caller = nullptr;
else _request_queue.remove(&node); else _request_queue.remove(node);
} }
@ -211,15 +210,16 @@ bool Ipc_node::await_request(unsigned rcv_caps)
_rcv_caps = rcv_caps; _rcv_caps = rcv_caps;
/* if anybody already announced a request receive it */ /* if no request announced then wait */
if (!_request_queue.empty()) { bool announced = false;
_receive_request(*_request_queue.dequeue());
return true;
}
/* no request announced, so wait */
_state = AWAIT_REQUEST; _state = AWAIT_REQUEST;
return false;
/* if anybody already announced a request receive it */
_request_queue.dequeue([&] (Ipc_node &ipc) {
_receive_request(ipc);
announced = true;
});
return announced;
} }

View File

@ -6,7 +6,7 @@
*/ */
/* /*
* Copyright (C) 2012-2017 Genode Labs GmbH * Copyright (C) 2012-2019 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
@ -22,7 +22,6 @@
#include <base/internal/native_utcb.h> #include <base/internal/native_utcb.h>
/* core includes */ /* core includes */
#include <kernel/fifo.h>
#include <kernel/interface.h> #include <kernel/interface.h>
#include <assertion.h> #include <assertion.h>
@ -37,7 +36,7 @@ namespace Kernel
*/ */
class Ipc_node; class Ipc_node;
using Ipc_node_queue = Kernel::Fifo<Ipc_node>; using Ipc_node_queue = Genode::Fifo<Ipc_node>;
} }
class Kernel::Ipc_node : private Ipc_node_queue::Element class Kernel::Ipc_node : private Ipc_node_queue::Element
@ -56,7 +55,6 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
private: private:
friend class Core_thread; friend class Core_thread;
friend class Kernel::Fifo<Ipc_node>;
friend class Genode::Fifo<Ipc_node>; friend class Genode::Fifo<Ipc_node>;
State _state = INACTIVE; State _state = INACTIVE;
@ -174,11 +172,11 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
template <typename F> void for_each_helper(F f) template <typename F> void for_each_helper(F f)
{ {
/* if we have a helper in the receive buffer, call 'f' for it */ /* if we have a helper in the receive buffer, call 'f' for it */
if (_caller && _caller->_help) f(_caller); if (_caller && _caller->_help) f(*_caller);
/* call 'f' for each helper in our request queue */ /* call 'f' for each helper in our request queue */
_request_queue.for_each([f] (Ipc_node * const node) { _request_queue.for_each([f] (Ipc_node &node) {
if (node->_help) f(node); }); if (node._help) f(node); });
} }
/** /**

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2012-2017 Genode Labs GmbH * Copyright (C) 2012-2019 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
@ -30,10 +30,6 @@ void Signal_handler::cancel_waiting()
} }
Signal_handler::Signal_handler()
: _handlers_fe(this), _receiver(0) { }
Signal_handler::~Signal_handler() { cancel_waiting(); } Signal_handler::~Signal_handler() { cancel_waiting(); }
@ -47,7 +43,7 @@ void Signal_context_killer::cancel_waiting()
} }
Signal_context_killer::Signal_context_killer() : _context(0) { } Signal_context_killer::Signal_context_killer() : _context(nullptr) { }
Signal_context_killer::~Signal_context_killer() { cancel_waiting(); } Signal_context_killer::~Signal_context_killer() { cancel_waiting(); }
@ -128,14 +124,8 @@ Signal_context::~Signal_context()
Signal_context::Signal_context(Signal_receiver * const r, addr_t const imprint) Signal_context::Signal_context(Signal_receiver * const r, addr_t const imprint)
: :
_deliver_fe(this),
_contexts_fe(this),
_receiver(r), _receiver(r),
_imprint(imprint), _imprint(imprint)
_submits(0),
_ack(1),
_killed(0),
_killer(0)
{ {
r->_add_context(this); r->_add_context(this);
} }
@ -148,7 +138,7 @@ Signal_context::Signal_context(Signal_receiver * const r, addr_t const imprint)
void Signal_receiver::_add_deliverable(Signal_context * const c) void Signal_receiver::_add_deliverable(Signal_context * const c)
{ {
if (!c->_deliver_fe.enqueued()) { if (!c->_deliver_fe.enqueued()) {
_deliver.enqueue(&c->_deliver_fe); _deliver.enqueue(c->_deliver_fe);
} }
_listen(); _listen();
} }
@ -163,40 +153,46 @@ void Signal_receiver::_listen()
/* create a signal data-object */ /* create a signal data-object */
typedef Genode::Signal_context * Signal_imprint; typedef Genode::Signal_context * Signal_imprint;
auto const context = _deliver.dequeue()->object();
Signal_imprint const imprint =
reinterpret_cast<Signal_imprint>(context->_imprint);
Signal::Data data(imprint, context->_submits);
/* communicate signal data to handler */ _deliver.dequeue([&] (Signal_context::Fifo_element &elem) {
auto const handler = _handlers.dequeue()->object(); auto const context = &elem.object();
handler->_receiver = 0;
handler->_receive_signal(&data, sizeof(data)); Signal_imprint const imprint =
context->_delivered(); reinterpret_cast<Signal_imprint>(context->_imprint);
Signal::Data data(imprint, context->_submits);
/* communicate signal data to handler */
_handlers.dequeue([&] (Signal_handler::Fifo_element &elem) {
auto const handler = &elem.object();
handler->_receiver = 0;
handler->_receive_signal(&data, sizeof(data));
});
context->_delivered();
});
} }
} }
void Signal_receiver::_context_destructed(Signal_context * const c) void Signal_receiver::_context_destructed(Signal_context * const c)
{ {
_contexts.remove(&c->_contexts_fe); _contexts.remove(c->_contexts_fe);
if (!c->_deliver_fe.enqueued()) { return; } if (!c->_deliver_fe.enqueued()) { return; }
_deliver.remove(&c->_deliver_fe); _deliver.remove(c->_deliver_fe);
} }
void Signal_receiver::_handler_cancelled(Signal_handler * const h) { void Signal_receiver::_handler_cancelled(Signal_handler * const h) {
_handlers.remove(&h->_handlers_fe); } _handlers.remove(h->_handlers_fe); }
void Signal_receiver::_add_context(Signal_context * const c) { void Signal_receiver::_add_context(Signal_context * const c) {
_contexts.enqueue(&c->_contexts_fe); } _contexts.enqueue(c->_contexts_fe); }
int Signal_receiver::add_handler(Signal_handler * const h) int Signal_receiver::add_handler(Signal_handler * const h)
{ {
if (h->_receiver) { return -1; } if (h->_receiver) { return -1; }
_handlers.enqueue(&h->_handlers_fe); _handlers.enqueue(h->_handlers_fe);
h->_receiver = this; h->_receiver = this;
h->_await_signal(this); h->_await_signal(this);
_listen(); _listen();
@ -207,7 +203,6 @@ int Signal_receiver::add_handler(Signal_handler * const h)
Signal_receiver::~Signal_receiver() Signal_receiver::~Signal_receiver()
{ {
/* destruct all attached contexts */ /* destruct all attached contexts */
while (Signal_context * c = _contexts.dequeue()->object()) { _contexts.dequeue_all([] (Signal_context::Fifo_element &elem) {
c->~Signal_context(); elem.object().~Signal_context(); });
}
} }

View File

@ -58,8 +58,8 @@ class Kernel::Signal_handler
typedef Genode::Fifo_element<Signal_handler> Fifo_element; typedef Genode::Fifo_element<Signal_handler> Fifo_element;
Fifo_element _handlers_fe; Fifo_element _handlers_fe { *this };
Signal_receiver * _receiver; Signal_receiver * _receiver { nullptr };
/** /**
* Let the handler block for signal receipt * Let the handler block for signal receipt
@ -86,7 +86,7 @@ class Kernel::Signal_handler
public: public:
Signal_handler(); Signal_handler() { }
virtual ~Signal_handler(); virtual ~Signal_handler();
/** /**
@ -158,14 +158,14 @@ class Kernel::Signal_context : public Kernel::Object
typedef Genode::Fifo_element<Signal_context> Fifo_element; typedef Genode::Fifo_element<Signal_context> Fifo_element;
Fifo_element _deliver_fe; Fifo_element _deliver_fe { *this };
Fifo_element _contexts_fe; Fifo_element _contexts_fe { *this };
Signal_receiver * const _receiver; Signal_receiver * const _receiver;
addr_t const _imprint; addr_t const _imprint;
unsigned _submits; Signal_context_killer * _killer { nullptr };
bool _ack; unsigned _submits { 0 };
bool _killed; bool _ack { true };
Signal_context_killer * _killer; bool _killed { false };
/** /**
* Tell receiver about the submits of the context if any * Tell receiver about the submits of the context if any

View File

@ -151,15 +151,15 @@ void Thread::_await_request_failed()
void Thread::_deactivate_used_shares() void Thread::_deactivate_used_shares()
{ {
Cpu_job::_deactivate_own_share(); Cpu_job::_deactivate_own_share();
Ipc_node::for_each_helper([&] (Ipc_node * const h) { Ipc_node::for_each_helper([&] (Ipc_node &h) {
static_cast<Thread *>(h)->_deactivate_used_shares(); }); static_cast<Thread &>(h)._deactivate_used_shares(); });
} }
void Thread::_activate_used_shares() void Thread::_activate_used_shares()
{ {
Cpu_job::_activate_own_share(); Cpu_job::_activate_own_share();
Ipc_node::for_each_helper([&] (Ipc_node * const h) { Ipc_node::for_each_helper([&] (Ipc_node &h) {
static_cast<Thread *>(h)->_activate_used_shares(); }); static_cast<Thread &>(h)._activate_used_shares(); });
} }
void Thread::_become_active() void Thread::_become_active()

View File

@ -32,7 +32,7 @@ using namespace Genode;
void Signal_source_component::release(Signal_context_component &context) void Signal_source_component::release(Signal_context_component &context)
{ {
if (context.enqueued()) if (context.enqueued())
_signal_queue.remove(&context); _signal_queue.remove(context);
} }
@ -49,7 +49,7 @@ void Signal_source_component::submit(Signal_context_component &context,
if (context.enqueued()) if (context.enqueued())
return; return;
_signal_queue.enqueue(&context); _signal_queue.enqueue(context);
seL4_Signal(Capability_space::ipc_cap_data(_notify).sel.value()); seL4_Signal(Capability_space::ipc_cap_data(_notify).sel.value());
} }
@ -57,13 +57,13 @@ void Signal_source_component::submit(Signal_context_component &context,
Signal_source::Signal Signal_source_component::wait_for_signal() Signal_source::Signal Signal_source_component::wait_for_signal()
{ {
if (_signal_queue.empty()) Signal result(0, 0); /* just a dummy in the case of no signal pending */
return Signal(0, 0); /* just a dummy */
/* dequeue and return pending signal */ /* dequeue and return pending signal */
Signal_context_component &context = *_signal_queue.dequeue(); _signal_queue.dequeue([&result] (Signal_context_component &context) {
Signal result(context.imprint(), context.cnt()); result = Signal(context.imprint(), context.cnt());
context.reset_signal_cnt(); context.reset_signal_cnt();
});
return result; return result;
} }

View File

@ -6,7 +6,7 @@
*/ */
/* /*
* Copyright (C) 2006-2017 Genode Labs GmbH * Copyright (C) 2006-2019 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
@ -73,7 +73,8 @@ class Genode::Semaphore
* Remove element from queue and wake up the corresponding * Remove element from queue and wake up the corresponding
* blocking thread * blocking thread
*/ */
element = _queue.dequeue(); _queue.dequeue([&element] (Element &head) {
element = &head; });
} }
/* do not hold the lock while unblocking a waiting thread */ /* do not hold the lock while unblocking a waiting thread */
@ -94,7 +95,7 @@ class Genode::Semaphore
* in the wait queue. * in the wait queue.
*/ */
Element queue_element; Element queue_element;
_queue.enqueue(&queue_element); _queue.enqueue(queue_element);
_meta_lock.unlock(); _meta_lock.unlock();
/* /*

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2008-2017 Genode Labs GmbH * Copyright (C) 2008-2019 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
@ -37,71 +37,69 @@ class Genode::Fifo
friend class Fifo; friend class Fifo;
QT *_next; QT *_next { nullptr };
bool _enqueued; bool _enqueued { false };
public: public:
Element(): _next(0), _enqueued(false) { } Element() { }
/** /**
* Return true is fifo element is enqueued in a fifo * Return true is fifo element is enqueued in a fifo
*/ */
bool enqueued() { return _enqueued; } bool enqueued() { return _enqueued; }
/**
* Return true is fifo element is enqueued in a fifo
*
* \noapi
* \deprecated use 'enqueued' instead
*/
bool is_enqueued() { return enqueued(); }
/** /**
* Return next element in queue * Return next element in queue
*
* \deprecated use 'Fifo::for_each' instead
*/ */
QT *next() const { return _next; } QT *next() const { return _next; }
}; };
private: private:
QT *_head; /* oldest element */ QT *_head { nullptr }; /* oldest element */
Element *_tail; /* newest element */ Element *_tail { nullptr }; /* newest element */
public: public:
/** /**
* Return true if queue is empty * Return true if queue is empty
*/ */
bool empty() { return _tail == 0; } bool empty() { return _tail == nullptr; }
/** /**
* Constructor * Constructor
*/ */
Fifo(): _head(0), _tail(0) { } Fifo() { }
/** /**
* Return first queue element * If queue is not empty then call
* lambda 'func' of type 'void (QT&)'
* with the head element
*/ */
QT *head() const { return _head; } template <typename FUNC>
void head(FUNC const &func) const {
if (_head) func(*_head); }
/** /**
* Remove element explicitely from queue * Remove element explicitely from queue
*/ */
void remove(QT *qe) void remove(QT &qe)
{ {
if (empty()) return; if (empty()) return;
/* if specified element is the first of the queue */ /* if specified element is the first of the queue */
if (qe == _head) { if (&qe == _head) {
_head = qe->Fifo::Element::_next; _head = qe.Fifo::Element::_next;
if (!_head) _tail = 0; if (!_head) _tail = nullptr;
} }
else { else {
/* search specified element in the queue */ /* search specified element in the queue */
Element *e = _head; Element *e = _head;
while (e->_next && (e->_next != qe)) while (e->_next && (e->_next != &qe))
e = e->_next; e = e->_next;
/* element is not member of the queue */ /* element is not member of the queue */
@ -112,50 +110,78 @@ class Genode::Fifo
if (!e->Element::_next) _tail = e; if (!e->Element::_next) _tail = e;
} }
qe->Fifo::Element::_next = 0; qe.Fifo::Element::_next = nullptr;
qe->Fifo::Element::_enqueued = 0; qe.Fifo::Element::_enqueued = false;
} }
/** /**
* Attach element at the end of the queue * Attach element at the end of the queue
*/ */
void enqueue(QT *e) void enqueue(QT &e)
{ {
e->Fifo::Element::_next = 0; e.Fifo::Element::_next = nullptr;
e->Fifo::Element::_enqueued = true; e.Fifo::Element::_enqueued = true;
if (empty()) { if (empty()) {
_tail = _head = e; _tail = _head = &e;
return; return;
} }
_tail->Fifo::Element::_next = e; _tail->Fifo::Element::_next = &e;
_tail = e; _tail = &e;
}
/**
* Call lambda 'func' of type 'void (QT&)'
* for each queue element in order
*/
template <typename FUNC>
void for_each(FUNC const &func) const
{
QT *elem = _head;
while (elem != nullptr) {
/* take the next pointer so 'func' cannot modify it */
QT *next = elem->Fifo::Element::_next;;
func(*elem);
elem = next;
}
} }
/** /**
* Remove head element from queue * If queue is not empty then remove head and
* * call lambda 'func' of type 'void (QT&)'
* \return head element or 0 if queue is empty
*/ */
QT *dequeue() template <typename FUNC>
void dequeue(FUNC const &func)
{ {
QT *result = _head; QT *result = _head;
/* check if queue has only one last element */ /* check if queue has only one last element */
if (_head == _tail) { if (_head == _tail) {
_head = 0; _head = nullptr;
_tail = 0; _tail = nullptr;
} else } else
_head = _head->Fifo::Element::_next; _head = _head->Fifo::Element::_next;
/* mark fifo queue element as free */ /* mark fifo queue element as free */
if (result) { if (result) {
result->Fifo::Element::_next = 0; result->Fifo::Element::_next = nullptr;
result->Fifo::Element::_enqueued = false; result->Fifo::Element::_enqueued = false;
}
return result; /* pass to caller */
func(*result);
}
}
/**
* If queue is not empty then remove elements in order and
* call lambda 'func' of type 'void (QT&)'
*/
template <typename FUNC>
void dequeue_all(FUNC const &func)
{
while (_head != nullptr) dequeue(func);
} }
}; };
@ -174,26 +200,13 @@ class Genode::Fifo
template <typename T> template <typename T>
class Genode::Fifo_element : public Fifo<Fifo_element<T> >::Element class Genode::Fifo_element : public Fifo<Fifo_element<T> >::Element
{ {
T *_object; T &_object;
public: public:
Fifo_element(T *object) : _object(object) { } Fifo_element(T &object) : _object(object) { }
/** inline T &object() { return _object; }
* Get typed object pointer
*
* Zero-pointer save: Returns 0 if this pointer is 0 to
* cover the case of accessing an empty FIFO.
*/
/* prevent the compiler from optimizing out the 'this' pointer check */
__attribute__((optimize("-fno-delete-null-pointer-checks")))
inline T *object()
{
if (this) { return _object; }
return 0;
}
}; };
#endif /* _INCLUDE__UTIL__FIFO_H_ */ #endif /* _INCLUDE__UTIL__FIFO_H_ */

View File

@ -131,8 +131,6 @@ class Genode::Rm_faulter : Fifo<Rm_faulter>::Element, Interface
*/ */
explicit Rm_faulter(Pager_object &pager_object) : _pager_object(pager_object) { } explicit Rm_faulter(Pager_object &pager_object) : _pager_object(pager_object) { }
using Fifo<Rm_faulter>::Element::next;
/** /**
* Assign fault state * Assign fault state
*/ */

View File

@ -7,7 +7,7 @@
*/ */
/* /*
* Copyright (C) 2006-2017 Genode Labs GmbH * Copyright (C) 2006-2019 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
@ -451,18 +451,12 @@ Region_map_component::attach(Dataspace_capability ds_cap, size_t size,
dsc->attached_to(region); dsc->attached_to(region);
/* check if attach operation resolves any faulting region-manager clients */ /* check if attach operation resolves any faulting region-manager clients */
for (Rm_faulter *faulter = _faulters.head(); faulter; ) { _faulters.for_each([&] (Rm_faulter &faulter) {
if (faulter.fault_in_addr_range((addr_t)attach_at, size)) {
/* remember next pointer before possibly removing current list element */
Rm_faulter *next = faulter->next();
if (faulter->fault_in_addr_range((addr_t)attach_at, size)) {
_faulters.remove(faulter); _faulters.remove(faulter);
faulter->continue_after_resolved_fault(); faulter.continue_after_resolved_fault();
} }
});
faulter = next;
}
return attach_at; return attach_at;
}; };
@ -606,7 +600,7 @@ void Region_map_component::fault(Rm_faulter &faulter, addr_t pf_addr,
faulter.fault(*this, Region_map::State(pf_type, pf_addr)); faulter.fault(*this, Region_map::State(pf_type, pf_addr));
/* enqueue faulter */ /* enqueue faulter */
_faulters.enqueue(&faulter); _faulters.enqueue(faulter);
/* issue fault signal */ /* issue fault signal */
_fault_notifier.submit(); _fault_notifier.submit();
@ -617,9 +611,9 @@ void Region_map_component::discard_faulter(Rm_faulter &faulter, bool do_lock)
{ {
if (do_lock) { if (do_lock) {
Lock::Guard lock_guard(_lock); Lock::Guard lock_guard(_lock);
_faulters.remove(&faulter); _faulters.remove(faulter);
} else } else
_faulters.remove(&faulter); _faulters.remove(faulter);
} }
@ -634,15 +628,13 @@ Region_map::State Region_map_component::state()
/* serialize access */ /* serialize access */
Lock::Guard lock_guard(_lock); Lock::Guard lock_guard(_lock);
/* pick one of the currently faulted threads */
Rm_faulter *faulter_ptr = _faulters.head();
/* return ready state if there are not current faulters */ /* return ready state if there are not current faulters */
if (!faulter_ptr) Region_map::State result;
return Region_map::State();
/* return fault information regarding the first faulter of the list */ /* otherwise return fault information regarding the first faulter */
return faulter_ptr->fault_state(); _faulters.head([&] (Rm_faulter &faulter) {
result = faulter.fault_state(); });
return result;
} }

View File

@ -27,7 +27,7 @@ using namespace Genode;
void Signal_source_component::release(Signal_context_component &context) void Signal_source_component::release(Signal_context_component &context)
{ {
if (context.enqueued()) if (context.enqueued())
_signal_queue.remove(&context); _signal_queue.remove(context);
} }
@ -59,7 +59,7 @@ void Signal_source_component::submit(Signal_context_component &context,
} else { } else {
if (!context.enqueued()) if (!context.enqueued())
_signal_queue.enqueue(&context); _signal_queue.enqueue(context);
} }
} }
@ -78,10 +78,13 @@ Signal_source::Signal Signal_source_component::wait_for_signal()
return Signal(0, 0); /* just a dummy */ return Signal(0, 0); /* just a dummy */
} }
/* dequeue and return pending signal */ /* dequeue and return pending signal */
Signal_context_component &context = *_signal_queue.dequeue(); Signal result { };
Signal result(context.imprint(), context.cnt()); _signal_queue.dequeue([&result] (Signal_context_component &context) {
context.reset_signal_cnt(); result = Signal(context.imprint(), context.cnt());
context.reset_signal_cnt();
});
return result; return result;
} }

View File

@ -28,13 +28,8 @@ extern "C" void brk(Linker::Debug *, Linker::Link_map *) { }
void Linker::dump_link_map(Object const &obj) void Linker::dump_link_map(Object const &obj)
{ {
for (Object const *o = &obj; o; o = o->next_obj()) { if (!obj.is_binary())
log(" ", Hex(obj.link_map().addr),
if (o->is_binary()) " .. ", Hex(obj.link_map().addr + obj.size() - 1),
continue; ": ", obj.name());
log(" ", Hex(o->link_map().addr),
" .. ", Hex(o->link_map().addr + o->size() - 1),
": ", o->name());
}
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2015-2017 Genode Labs GmbH * Copyright (C) 2015-2019 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
@ -28,7 +28,7 @@ Linker::Dependency::Dependency(Env &env, Allocator &md_alloc,
_root(root), _root(root),
_md_alloc(&md_alloc) _md_alloc(&md_alloc)
{ {
deps.enqueue(this); deps.enqueue(*this);
load_needed(env, *_md_alloc, deps, keep); load_needed(env, *_md_alloc, deps, keep);
} }
@ -47,11 +47,14 @@ Linker::Dependency::~Dependency()
bool Linker::Dependency::in_dep(char const *file, Fifo<Dependency> const &dep) bool Linker::Dependency::in_dep(char const *file, Fifo<Dependency> const &dep)
{ {
for (Dependency const *d = dep.head(); d; d = d->next()) bool result = false;
if (!strcmp(file, d->obj().name()))
return true;
return false; dep.for_each([&] (Dependency const &d) {
if (!result && !strcmp(file, d.obj().name()))
result = true;
});
return result;
} }
@ -95,9 +98,8 @@ Linker::Root_object::Root_object(Env &env, Allocator &md_alloc,
Init::list()->initialize(bind, STAGE_SO); Init::list()->initialize(bind, STAGE_SO);
} catch (...) { } catch (...) {
Init::list()->flush(); Init::list()->flush();
while (Dependency *d = _deps.dequeue()) _deps.dequeue_all([&] (Dependency &d) {
destroy(_md_alloc, d); destroy(_md_alloc, &d); });
throw; throw;
} }
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2015-2017 Genode Labs GmbH * Copyright (C) 2015-2019 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
@ -135,7 +135,7 @@ class Linker::Dynamic
throw Fatal(); throw Fatal();
} }
Needed *n = new (*_md_alloc) Needed(d->un.ptr); Needed *n = new (*_md_alloc) Needed(d->un.ptr);
_needed.enqueue(n); _needed.enqueue(*n);
} }
template <typename T> template <typename T>
@ -199,8 +199,8 @@ class Linker::Dynamic
if (!_md_alloc) if (!_md_alloc)
return; return;
while (Needed *n = _needed.dequeue()) _needed.dequeue_all([&] (Needed &n) {
destroy(*_md_alloc, n); destroy(*_md_alloc, &n); });
} }
void call_init_function() const void call_init_function() const
@ -310,8 +310,8 @@ class Linker::Dynamic
template <typename FUNC> template <typename FUNC>
void for_each_dependency(FUNC const &fn) const void for_each_dependency(FUNC const &fn) const
{ {
for (Needed *n = _needed.head(); n; n = n->next()) _needed.for_each([&] (Needed &n) {
fn(n->path(_strtab)); fn(n.path(_strtab)); });
} }
void relocate(Bind bind) SELF_RELOC void relocate(Bind bind) SELF_RELOC

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2014-2017 Genode Labs GmbH * Copyright (C) 2014-2019 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
@ -273,18 +273,27 @@ class Linker::Root_object
~Root_object() ~Root_object()
{ {
while (Dependency *d = _deps.dequeue()) _deps.dequeue_all([&] (Dependency &d) {
destroy(_md_alloc, d); destroy(_md_alloc, &d); });
} }
Link_map const &link_map() const Link_map const &link_map() const
{ {
return _deps.head()->obj().link_map(); Link_map const *map = nullptr;
_deps.head([&] (Dependency &d) {
map = &d.obj().link_map(); });
return *map;
} }
Dependency const *first_dep() const { return _deps.head(); } Dependency const *first_dep() const
{
Dependency const *dep = nullptr;
_deps.head([&] (Dependency const &head) {
dep = &head; });
return dep;
}
void enqueue(Dependency &dep) { _deps.enqueue(&dep); } void enqueue(Dependency &dep) { _deps.enqueue(dep); }
Fifo<Dependency> &deps() { return _deps; } Fifo<Dependency> &deps() { return _deps; }
}; };

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2014-2017 Genode Labs GmbH * Copyright (C) 2014-2019 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
@ -129,7 +129,7 @@ class Linker::Elf_object : public Object, private Fifo<Elf_object>::Element
{ {
/* register for static construction and relocation */ /* register for static construction and relocation */
Init::list()->insert(this); Init::list()->insert(this);
obj_list()->enqueue(this); obj_list()->enqueue(*this);
/* add to link map */ /* add to link map */
Debug::state_change(Debug::ADD, nullptr); Debug::state_change(Debug::ADD, nullptr);
@ -151,7 +151,7 @@ class Linker::Elf_object : public Object, private Fifo<Elf_object>::Element
Debug::state_change(Debug::CONSISTENT, nullptr); Debug::state_change(Debug::CONSISTENT, nullptr);
/* remove from loaded objects list */ /* remove from loaded objects list */
obj_list()->remove(this); obj_list()->remove(*this);
} }
/** /**
@ -314,7 +314,7 @@ Linker::Ld &Linker::Ld::linker()
{ {
Ld_vtable() Ld_vtable()
{ {
Elf_object::obj_list()->enqueue(this); Elf_object::obj_list()->enqueue(*this);
plt_setup(); plt_setup();
} }
}; };
@ -502,24 +502,30 @@ bool Linker::Object::needs_static_construction()
Object &Linker::load(Env &env, Allocator &md_alloc, char const *path, Object &Linker::load(Env &env, Allocator &md_alloc, char const *path,
Dependency &dep, Keep keep) Dependency &dep, Keep keep)
{ {
for (Object *e = Elf_object::obj_list()->head(); e; e = e->next_obj()) { Object *result = nullptr;
Elf_object::obj_list()->for_each([&] (Object &e) {
if (result == nullptr) {
if (verbose_loading)
log("LOAD: ", Linker::file(path), " == ", e.name());
if (verbose_loading) if (!strcmp(Linker::file(path), e.name())) {
log("LOAD: ", Linker::file(path), " == ", e->name()); e.load();
result = &e;
if (!strcmp(Linker::file(path), e->name())) { }
e->load();
return *e;
} }
} });
if (result == nullptr)
return *new (md_alloc) Elf_object(env, md_alloc, path, dep, keep); result = new (md_alloc) Elf_object(env, md_alloc, path, dep, keep);
return *result;
} }
Object *Linker::obj_list_head() Object *Linker::obj_list_head()
{ {
return Elf_object::obj_list()->head(); Object *result = nullptr;
Elf_object::obj_list()->head([&result] (Object &obj) {
result = &obj; });
return result;
} }
@ -704,7 +710,8 @@ void Component::construct(Genode::Env &env)
" .. ", Hex(Thread::stack_area_virtual_base() + " .. ", Hex(Thread::stack_area_virtual_base() +
Thread::stack_area_virtual_size() - 1), Thread::stack_area_virtual_size() - 1),
": stack area"); ": stack area");
dump_link_map(*Elf_object::obj_list()->head()); Elf_object::obj_list()->for_each([] (Object const &obj) {
dump_link_map(obj); });
} }
} catch (...) { } } catch (...) { }

View File

@ -108,10 +108,12 @@ class Timed_semaphore : public Semaphore
* Iterate through the queue and find the thread, * Iterate through the queue and find the thread,
* with the corresponding timeout. * with the corresponding timeout.
*/ */
Element *first = Semaphore::_queue.dequeue(); Element *first = nullptr;
Semaphore::_queue.dequeue([&first] (Element &e) {
first = &e; });
Element *e = first; Element *e = first;
while (true) { while (e) {
/* /*
* Wakeup the thread. * Wakeup the thread.
@ -124,8 +126,10 @@ class Timed_semaphore : public Semaphore
/* /*
* Noninvolved threads are enqueued again. * Noninvolved threads are enqueued again.
*/ */
Semaphore::_queue.enqueue(e); Semaphore::_queue.enqueue(*e);
e = Semaphore::_queue.dequeue(); e = nullptr;
Semaphore::_queue.dequeue([&e] (Element &next) {
e = &next; });
/* /*
* Maybe, the alarm was triggered just after the corresponding * Maybe, the alarm was triggered just after the corresponding
@ -210,7 +214,7 @@ class Timed_semaphore : public Semaphore
* in the wait queue. * in the wait queue.
*/ */
Element queue_element; Element queue_element;
Semaphore::_queue.enqueue(&queue_element); Semaphore::_queue.enqueue(queue_element);
Semaphore::_meta_lock.unlock(); Semaphore::_meta_lock.unlock();
/* Create the timeout */ /* Create the timeout */

View File

@ -78,7 +78,7 @@ struct rumpuser_mtx
if (try_enter) if (try_enter)
return false; return false;
fifo.enqueue(&applicant); fifo.enqueue(applicant);
} }
applicant.block(); applicant.block();
} }
@ -99,8 +99,8 @@ struct rumpuser_mtx
owner = nullptr; owner = nullptr;
} }
if (Applicant *applicant = fifo.dequeue()) fifo.dequeue([] (Applicant &applicant) {
applicant->wake_up(); applicant.wake_up(); });
} }
}; };

View File

@ -109,10 +109,13 @@ class Libc::Timed_semaphore : public Semaphore
* Iterate through the queue and find the thread, * Iterate through the queue and find the thread,
* with the corresponding timeout. * with the corresponding timeout.
*/ */
Element *first = Semaphore::_queue.dequeue();
Element *first = nullptr;
Semaphore::_queue.dequeue([&first] (Element &e) {
first = &e; });
Element *e = first; Element *e = first;
while (true) { while (e) {
/* /*
* Wakeup the thread. * Wakeup the thread.
@ -125,8 +128,10 @@ class Libc::Timed_semaphore : public Semaphore
/* /*
* Noninvolved threads are enqueued again. * Noninvolved threads are enqueued again.
*/ */
Semaphore::_queue.enqueue(e); Semaphore::_queue.enqueue(*e);
e = Semaphore::_queue.dequeue(); e = nullptr;
Semaphore::_queue.dequeue([&e] (Element &next) {
e = &next; });
/* /*
* Maybe, the alarm was triggered just after the corresponding * Maybe, the alarm was triggered just after the corresponding
@ -211,7 +216,7 @@ class Libc::Timed_semaphore : public Semaphore
* in the wait queue. * in the wait queue.
*/ */
Element queue_element; Element queue_element;
Semaphore::_queue.enqueue(&queue_element); Semaphore::_queue.enqueue(queue_element);
Semaphore::_meta_lock.unlock(); Semaphore::_meta_lock.unlock();
/* Create the timeout */ /* Create the timeout */

View File

@ -64,7 +64,7 @@ class Isoc_packet : Fifo<Isoc_packet>::Element
{ {
if (!valid()) return false; if (!valid()) return false;
int remaining = _size - _offset; unsigned remaining = _size - _offset;
int copy_size = min(usb_packet->iov.size, remaining); int copy_size = min(usb_packet->iov.size, remaining);
usb_packet_copy(usb_packet, _content + _offset, copy_size); usb_packet_copy(usb_packet, _content + _offset, copy_size);
@ -202,19 +202,22 @@ struct Dev_info
struct Usb_host_device : List<Usb_host_device>::Element struct Usb_host_device : List<Usb_host_device>::Element
{ {
Usb_host_device(const Usb_host_device&);
const Usb_host_device& operator=(const Usb_host_device&);
struct Could_not_create_device : Exception { }; struct Could_not_create_device : Exception { };
bool deleted = false; bool deleted = false;
char const *label = nullptr; char const *label = nullptr;
Dev_info const info; Dev_info const info;
USBHostDevice *qemu_dev; USBHostDevice *qemu_dev { nullptr };
/* submit queue + ack queue + 1 -> max nr of packets in flight */ /* submit queue + ack queue + 1 -> max nr of packets in flight */
enum { NUM_COMPLETIONS = Usb::Session::TX_QUEUE_SIZE * 2 + 1 }; enum { NUM_COMPLETIONS = Usb::Session::TX_QUEUE_SIZE * 2 + 1 };
Completion completion[NUM_COMPLETIONS]; Completion completion[NUM_COMPLETIONS];
Fifo<Isoc_packet> isoc_read_queue; Fifo<Isoc_packet> isoc_read_queue { };
Reconstructible<Isoc_packet> isoc_write_packet { Usb::Packet_descriptor(), nullptr }; Reconstructible<Isoc_packet> isoc_write_packet { Usb::Packet_descriptor(), nullptr };
Signal_receiver &sig_rec; Signal_receiver &sig_rec;
@ -323,7 +326,9 @@ struct Usb_host_device : List<Usb_host_device>::Element
/* isochronous in */ /* isochronous in */
free_completion(packet); free_completion(packet);
_isoc_in_pending--; _isoc_in_pending--;
isoc_read_queue.enqueue(new (_alloc) Isoc_packet(packet, content)); Isoc_packet *new_packet = new (_alloc)
Isoc_packet(packet, content);
isoc_read_queue.enqueue(*new_packet);
} }
} }
} }
@ -339,9 +344,12 @@ struct Usb_host_device : List<Usb_host_device>::Element
return false; return false;
} }
if (isoc_read_queue.head()->copy(packet)) { isoc_read_queue.head([&] (Isoc_packet &head) {
free_packet(isoc_read_queue.dequeue()); if (head.copy(packet)) {
} isoc_read_queue.remove(head);
free_packet(&head);
}
});
return true; return true;
} }
@ -351,9 +359,7 @@ struct Usb_host_device : List<Usb_host_device>::Element
bool isoc_new_packet() bool isoc_new_packet()
{ {
unsigned count = 0; unsigned count = 0;
for (Isoc_packet *packet = isoc_read_queue.head(); packet; isoc_read_queue.for_each([&count] (Isoc_packet&) { count++; });
packet = packet->next(), count++);
return (count + _isoc_in_pending) < 3 ? true : false; return (count + _isoc_in_pending) < 3 ? true : false;
} }
@ -394,18 +400,14 @@ struct Usb_host_device : List<Usb_host_device>::Element
void isoc_in_flush(unsigned ep, bool all = false) void isoc_in_flush(unsigned ep, bool all = false)
{ {
/* flush finished and stored data */ /* flush finished and stored data */
for (Isoc_packet *packet = isoc_read_queue.head(); packet; ) isoc_read_queue.for_each([&] (Isoc_packet &packet) {
{ if (!all && (!packet.valid() || packet.packet().transfer.ep != ep)) {
if (!all && (!packet->valid() || packet->packet().transfer.ep != ep)) { return;
packet = packet->next();
continue;
} }
Isoc_packet *next = packet->next();
isoc_read_queue.remove(packet); isoc_read_queue.remove(packet);
free_packet(packet); free_packet(&packet);
packet = next; });
}
/* flush in flight packets */ /* flush in flight packets */
flush_completion(ep); flush_completion(ep);

View File

@ -702,7 +702,7 @@ class Lwip::Udp_socket_dir final :
return n; return n;
} }
u16_t peek(void *dst, size_t count) u16_t peek(void *dst, size_t count) const
{ {
count = min((size_t)buf->tot_len, count); count = min((size_t)buf->tot_len, count);
return pbuf_copy_partial(buf, dst, count, offset); return pbuf_copy_partial(buf, dst, count, offset);
@ -763,7 +763,7 @@ class Lwip::Udp_socket_dir final :
{ {
try { try {
Packet *pkt = new (_packet_slab) Packet(addr, port, buf); Packet *pkt = new (_packet_slab) Packet(addr, port, buf);
_packet_queue.enqueue(pkt); _packet_queue.enqueue(*pkt);
} catch (...) { } catch (...) {
Genode::warning("failed to queue UDP packet, dropping"); Genode::warning("failed to queue UDP packet, dropping");
pbuf_free(buf); pbuf_free(buf);
@ -794,25 +794,28 @@ class Lwip::Udp_socket_dir final :
char *dst, file_size count, char *dst, file_size count,
file_size &out_count) override file_size &out_count) override
{ {
Read_result result = Read_result::READ_ERR_INVALID;
switch(handle.kind) { switch(handle.kind) {
case Lwip_file_handle::DATA: { case Lwip_file_handle::DATA: {
if (Packet *pkt = _packet_queue.head()) { result = Read_result::READ_QUEUED;
out_count = pkt->read(dst, count); _packet_queue.head([&] (Packet &pkt) {
if (pkt->empty()) { out_count = pkt.read(dst, count);
destroy(_packet_slab, _packet_queue.dequeue()); if (pkt.empty()) {
_packet_queue.remove(pkt);
destroy(_packet_slab, &pkt);
} }
return Read_result::READ_OK; result = Read_result::READ_OK;
} });
return Read_result::READ_QUEUED;
} }
case Lwip_file_handle::PEEK: { case Lwip_file_handle::PEEK:
if (Packet *pkt = _packet_queue.head()) { _packet_queue.head([&] (Packet const &pkt) {
out_count = pkt->peek(dst, count); out_count = pkt.peek(dst, count);
} result = Read_result::READ_OK;
return Read_result::READ_OK; });
} break;
case Lwip_file_handle::LOCAL: case Lwip_file_handle::LOCAL:
case Lwip_file_handle::BIND: { case Lwip_file_handle::BIND: {
@ -834,28 +837,27 @@ class Lwip::Udp_socket_dir final :
return Read_result::READ_OK; return Read_result::READ_OK;
} }
case Lwip_file_handle::REMOTE: { case Lwip_file_handle::REMOTE:
if (count < ENDPOINT_STRLEN_MAX) { if (count < ENDPOINT_STRLEN_MAX) {
Genode::error("VFS LwIP: accept file read buffer is too small"); Genode::error("VFS LwIP: accept file read buffer is too small");
return Read_result::READ_ERR_INVALID; result = Read_result::READ_ERR_INVALID;
} } else
if (ip_addr_isany(&_pcb->remote_ip)) { if (ip_addr_isany(&_pcb->remote_ip)) {
if (Packet *pkt = _packet_queue.head()) { _packet_queue.head([&] (Packet &pkt) {
char const *ip_str = ipaddr_ntoa(&pkt->addr); char const *ip_str = ipaddr_ntoa(&pkt.addr);
/* TODO: IPv6 */ /* TODO: IPv6 */
out_count = Genode::snprintf(dst, count, "%s:%d\n", out_count = Genode::snprintf(dst, count, "%s:%d\n",
ip_str, pkt->port); ip_str, pkt.port);
return Read_result::READ_OK; result = Read_result::READ_OK;
} });
} else { } else {
char const *ip_str = ipaddr_ntoa(&_pcb->remote_ip); char const *ip_str = ipaddr_ntoa(&_pcb->remote_ip);
/* TODO: [IPv6]:port */ /* TODO: [IPv6]:port */
out_count = Genode::snprintf(dst, count, "%s:%d\n", out_count = Genode::snprintf(dst, count, "%s:%d\n",
ip_str, _pcb->remote_port); ip_str, _pcb->remote_port);
return Read_result::READ_OK; result = Read_result::READ_OK;
} }
break; break;
}
case Lwip_file_handle::LOCATION: case Lwip_file_handle::LOCATION:
/* /*
@ -869,7 +871,7 @@ class Lwip::Udp_socket_dir final :
default: break; default: break;
} }
return Read_result::READ_ERR_INVALID; return result;
} }
Write_result write(Lwip_file_handle &handle, Write_result write(Lwip_file_handle &handle,

View File

@ -190,26 +190,25 @@ struct Test::Main
{ {
try { try {
Genode::Reporter::Xml_generator xml(_result_reporter, [&] () { Genode::Reporter::Xml_generator xml(_result_reporter, [&] () {
for (Test_result *tr = _results.head(); tr; _results.for_each([&] (Test_result &tr) {
tr = tr->next()) {
xml.node("result", [&] () { xml.node("result", [&] () {
xml.attribute("test", tr->name); xml.attribute("test", tr.name);
xml.attribute("rx", tr->result.rx); xml.attribute("rx", tr.result.rx);
xml.attribute("tx", tr->result.tx); xml.attribute("tx", tr.result.tx);
xml.attribute("bytes", tr->result.bytes); xml.attribute("bytes", tr.result.bytes);
xml.attribute("size", tr->result.request_size); xml.attribute("size", tr.result.request_size);
xml.attribute("bsize", tr->result.block_size); xml.attribute("bsize", tr.result.block_size);
xml.attribute("duration", tr->result.duration); xml.attribute("duration", tr.result.duration);
if (_calculate) { if (_calculate) {
/* XXX */ /* XXX */
xml.attribute("mibs", (unsigned)(tr->result.mibs * (1<<20u))); xml.attribute("mibs", (unsigned)(tr.result.mibs * (1<<20u)));
xml.attribute("iops", (unsigned)(tr->result.iops + 0.5f)); xml.attribute("iops", (unsigned)(tr.result.iops + 0.5f));
} }
xml.attribute("result", tr->result.success ? 0 : 1); xml.attribute("result", tr.result.success ? 0 : 1);
}); });
} });
}); });
} catch (...) { Genode::warning("could generate results report"); } } catch (...) { Genode::warning("could generate results report"); }
} }
@ -235,7 +234,7 @@ struct Test::Main
if (_report) { if (_report) {
Test_result *tr = new (&_heap) Test_result(_current->name()); Test_result *tr = new (&_heap) Test_result(_current->name());
tr->result = r; tr->result = r;
_results.enqueue(tr); _results.enqueue(*tr);
_generate_report(); _generate_report();
} }
@ -249,25 +248,22 @@ struct Test::Main
/* execute next test */ /* execute next test */
if (!_current) { if (!_current) {
while (true) { _tests.dequeue([&] (Test_base &head) {
_current = _tests.dequeue(); if (_verbose) { Genode::log("start ", head.name()); }
if (_current) { try {
if (_verbose) { Genode::log("start ", _current->name()); } head.start(_stop_on_error);
_current = &head;
try { } catch (...) {
_current->start(_stop_on_error); Genode::log("Could not start ", head.name());
break; Genode::destroy(&_heap, &head);
} catch (...) {
Genode::log("Could not start ", _current->name());
Genode::destroy(&_heap, _current);
}
} else {
/* execution is finished */
Genode::log("--- all tests finished ---");
_env.parent().exit(_success ? 0 : 1);
break;
} }
} });
}
if (!_current) {
/* execution is finished */
Genode::log("--- all tests finished ---");
_env.parent().exit(_success ? 0 : 1);
} }
} }
@ -283,25 +279,25 @@ struct Test::Main
if (node.has_type("ping_pong")) { if (node.has_type("ping_pong")) {
Test_base *t = new (&_heap) Test_base *t = new (&_heap)
Ping_pong(_env, _heap, node, _finished_sigh); Ping_pong(_env, _heap, node, _finished_sigh);
_tests.enqueue(t); _tests.enqueue(*t);
} else } else
if (node.has_type("random")) { if (node.has_type("random")) {
Test_base *t = new (&_heap) Test_base *t = new (&_heap)
Random(_env, _heap, node, _finished_sigh); Random(_env, _heap, node, _finished_sigh);
_tests.enqueue(t); _tests.enqueue(*t);
} else } else
if (node.has_type("replay")) { if (node.has_type("replay")) {
Test_base *t = new (&_heap) Test_base *t = new (&_heap)
Replay(_env, _heap, node, _finished_sigh); Replay(_env, _heap, node, _finished_sigh);
_tests.enqueue(t); _tests.enqueue(*t);
} else } else
if (node.has_type("sequential")) { if (node.has_type("sequential")) {
Test_base *t = new (&_heap) Test_base *t = new (&_heap)
Sequential(_env, _heap, node, _finished_sigh); Sequential(_env, _heap, node, _finished_sigh);
_tests.enqueue(t); _tests.enqueue(*t);
} }
}); });
} catch (...) { Genode::error("invalid tests"); } } catch (...) { Genode::error("invalid tests"); }
@ -326,10 +322,8 @@ struct Test::Main
~Main() ~Main()
{ {
Test_result * tr = nullptr; _results.dequeue_all([&] (Test_result &tr) {
while ((tr = _results.dequeue())) { Genode::destroy(&_heap, &tr); });
Genode::destroy(&_heap, tr);
}
} }
private: private:

View File

@ -66,27 +66,25 @@ struct Test::Replay : Test_base
try { try {
while (_block->tx()->ready_to_submit() && more) { while (_block->tx()->ready_to_submit() && more) {
/* peak at head ... */ /* peak at head ... */
Request *req = requests.head(); more = false;
if (!req) { return; } requests.dequeue([&] (Request &req) {
Block::Packet_descriptor p(
_block->tx()->alloc_packet(req.count * _block_size),
req.op, req.nr, req.count);
Block::Packet_descriptor p( bool const write = req.op == Block::Packet_descriptor::WRITE;
_block->tx()->alloc_packet(req->count * _block_size),
req->op, req->nr, req->count);
bool const write = req->op == Block::Packet_descriptor::WRITE; /* simulate write */
if (write) {
char * const content = _block->tx()->packet_content(p);
Genode::memcpy(content, _scratch_buffer, p.size());
}
/* simulate write */ _block->tx()->submit_packet(p);
if (write) {
char * const content = _block->tx()->packet_content(p);
Genode::memcpy(content, _scratch_buffer, p.size());
}
_block->tx()->submit_packet(p); Genode::destroy(&alloc, &req);
more = _bulk;
/* ... and only remove it if we could submit it */ });
req = requests.dequeue();
Genode::destroy(&alloc, req);
more = _bulk;
} }
} catch (...) { } } catch (...) { }
} }
@ -161,7 +159,7 @@ struct Test::Replay : Test_base
else if (type == "write") { op = Block::Packet_descriptor::WRITE; } else if (type == "write") { op = Block::Packet_descriptor::WRITE; }
else { throw -1; } else { throw -1; }
requests.enqueue(new (&alloc) Request(op, nr, count)); requests.enqueue(*(new (&alloc) Request(op, nr, count)));
++request_num; ++request_num;
}); });
} catch (...) { } catch (...) {

View File

@ -853,10 +853,10 @@ struct Igd::Device
bool _vgpu_already_scheduled(Vgpu &vgpu) const bool _vgpu_already_scheduled(Vgpu &vgpu) const
{ {
for (Vgpu *v = _vgpu_list.head(); v; v = v->next()) { bool result = false;
if (v == &vgpu) { return true; } _vgpu_list.for_each([&] (Vgpu const &v) {
} result |= (&v == &vgpu); });
return false; return result;
} }
void _submit_execlist(Engine<Rcs_context> &engine) void _submit_execlist(Engine<Rcs_context> &engine)
@ -881,11 +881,19 @@ struct Igd::Device
Vgpu *_unschedule_current_vgpu() Vgpu *_unschedule_current_vgpu()
{ {
Vgpu *gpu = _vgpu_list.dequeue(); Vgpu *result = nullptr;
return gpu; _vgpu_list.dequeue([&] (Vgpu &head) {
result = &head; });
return result;
} }
Vgpu *_current_vgpu() { return _vgpu_list.head(); } Vgpu *_current_vgpu()
{
Vgpu *result = nullptr;
_vgpu_list.head([&] (Vgpu &head) {
result = &head; });
return result;
}
void _schedule_current_vgpu() void _schedule_current_vgpu()
{ {
@ -1189,7 +1197,7 @@ struct Igd::Device
Vgpu const *pending = _current_vgpu(); Vgpu const *pending = _current_vgpu();
_vgpu_list.enqueue(&vgpu); _vgpu_list.enqueue(vgpu);
if (pending) { return; } if (pending) { return; }
@ -1211,9 +1219,11 @@ struct Igd::Device
*/ */
bool vgpu_active(Vgpu const &vgpu) const bool vgpu_active(Vgpu const &vgpu) const
{ {
Vgpu const *curr = _vgpu_list.head(); bool result = false;
if (!curr) { return false; } _vgpu_list.head([&] (Vgpu const &curr) {
return &vgpu == curr ? true : false; result = (&vgpu == &curr);
});
return result;
} }
/********************* /*********************