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)
{
if (context.enqueued())
_signal_queue.remove(&context);
_signal_queue.remove(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);
if (!context.enqueued()) {
_signal_queue.enqueue(&context);
_signal_queue.enqueue(context);
/* wake up client */
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 */
Signal_context_component &context = *_signal_queue.dequeue();
Signal result(context.imprint(), context.cnt());
context.reset_signal_cnt();
Signal result { };
_signal_queue.dequeue([&result] (Signal_context_component &context) {
result = Signal(context.imprint(), context.cnt());
context.reset_signal_cnt();
});
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
* 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 */
_request_queue.enqueue(&node);
_request_queue.enqueue(node);
}
void Ipc_node::_cancel_request_queue()
{
Ipc_node * node;
while ((node = _request_queue.dequeue()))
node->_outbuf_request_cancelled();
_request_queue.dequeue_all([] (Ipc_node &node) {
node._outbuf_request_cancelled(); });
}
@ -143,7 +142,7 @@ void Ipc_node::_cancel_inbuf_request()
void Ipc_node::_announced_request_cancelled(Ipc_node &node)
{
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;
/* if anybody already announced a request receive it */
if (!_request_queue.empty()) {
_receive_request(*_request_queue.dequeue());
return true;
}
/* no request announced, so wait */
/* if no request announced then wait */
bool announced = false;
_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
* under the terms of the GNU Affero General Public License version 3.
@ -22,7 +22,6 @@
#include <base/internal/native_utcb.h>
/* core includes */
#include <kernel/fifo.h>
#include <kernel/interface.h>
#include <assertion.h>
@ -37,7 +36,7 @@ namespace Kernel
*/
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
@ -56,7 +55,6 @@ class Kernel::Ipc_node : private Ipc_node_queue::Element
private:
friend class Core_thread;
friend class Kernel::Fifo<Ipc_node>;
friend class Genode::Fifo<Ipc_node>;
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)
{
/* 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 */
_request_queue.for_each([f] (Ipc_node * const node) {
if (node->_help) f(node); });
_request_queue.for_each([f] (Ipc_node &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
* 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(); }
@ -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(); }
@ -128,14 +124,8 @@ Signal_context::~Signal_context()
Signal_context::Signal_context(Signal_receiver * const r, addr_t const imprint)
:
_deliver_fe(this),
_contexts_fe(this),
_receiver(r),
_imprint(imprint),
_submits(0),
_ack(1),
_killed(0),
_killer(0)
_imprint(imprint)
{
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)
{
if (!c->_deliver_fe.enqueued()) {
_deliver.enqueue(&c->_deliver_fe);
_deliver.enqueue(c->_deliver_fe);
}
_listen();
}
@ -163,40 +153,46 @@ void Signal_receiver::_listen()
/* create a signal data-object */
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 */
auto const handler = _handlers.dequeue()->object();
handler->_receiver = 0;
handler->_receive_signal(&data, sizeof(data));
context->_delivered();
_deliver.dequeue([&] (Signal_context::Fifo_element &elem) {
auto const context = &elem.object();
Signal_imprint const imprint =
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)
{
_contexts.remove(&c->_contexts_fe);
_contexts.remove(c->_contexts_fe);
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) {
_handlers.remove(&h->_handlers_fe); }
_handlers.remove(h->_handlers_fe); }
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)
{
if (h->_receiver) { return -1; }
_handlers.enqueue(&h->_handlers_fe);
_handlers.enqueue(h->_handlers_fe);
h->_receiver = this;
h->_await_signal(this);
_listen();
@ -207,7 +203,6 @@ int Signal_receiver::add_handler(Signal_handler * const h)
Signal_receiver::~Signal_receiver()
{
/* destruct all attached contexts */
while (Signal_context * c = _contexts.dequeue()->object()) {
c->~Signal_context();
}
_contexts.dequeue_all([] (Signal_context::Fifo_element &elem) {
elem.object().~Signal_context(); });
}

View File

@ -58,8 +58,8 @@ class Kernel::Signal_handler
typedef Genode::Fifo_element<Signal_handler> Fifo_element;
Fifo_element _handlers_fe;
Signal_receiver * _receiver;
Fifo_element _handlers_fe { *this };
Signal_receiver * _receiver { nullptr };
/**
* Let the handler block for signal receipt
@ -86,7 +86,7 @@ class Kernel::Signal_handler
public:
Signal_handler();
Signal_handler() { }
virtual ~Signal_handler();
/**
@ -158,14 +158,14 @@ class Kernel::Signal_context : public Kernel::Object
typedef Genode::Fifo_element<Signal_context> Fifo_element;
Fifo_element _deliver_fe;
Fifo_element _contexts_fe;
Fifo_element _deliver_fe { *this };
Fifo_element _contexts_fe { *this };
Signal_receiver * const _receiver;
addr_t const _imprint;
unsigned _submits;
bool _ack;
bool _killed;
Signal_context_killer * _killer;
Signal_context_killer * _killer { nullptr };
unsigned _submits { 0 };
bool _ack { true };
bool _killed { false };
/**
* 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()
{
Cpu_job::_deactivate_own_share();
Ipc_node::for_each_helper([&] (Ipc_node * const h) {
static_cast<Thread *>(h)->_deactivate_used_shares(); });
Ipc_node::for_each_helper([&] (Ipc_node &h) {
static_cast<Thread &>(h)._deactivate_used_shares(); });
}
void Thread::_activate_used_shares()
{
Cpu_job::_activate_own_share();
Ipc_node::for_each_helper([&] (Ipc_node * const h) {
static_cast<Thread *>(h)->_activate_used_shares(); });
Ipc_node::for_each_helper([&] (Ipc_node &h) {
static_cast<Thread &>(h)._activate_used_shares(); });
}
void Thread::_become_active()

View File

@ -32,7 +32,7 @@ using namespace Genode;
void Signal_source_component::release(Signal_context_component &context)
{
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())
return;
_signal_queue.enqueue(&context);
_signal_queue.enqueue(context);
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()
{
if (_signal_queue.empty())
return Signal(0, 0); /* just a dummy */
Signal result(0, 0); /* just a dummy in the case of no signal pending */
/* dequeue and return pending signal */
Signal_context_component &context = *_signal_queue.dequeue();
Signal result(context.imprint(), context.cnt());
context.reset_signal_cnt();
_signal_queue.dequeue([&result] (Signal_context_component &context) {
result = Signal(context.imprint(), context.cnt());
context.reset_signal_cnt();
});
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
* 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
* blocking thread
*/
element = _queue.dequeue();
_queue.dequeue([&element] (Element &head) {
element = &head; });
}
/* do not hold the lock while unblocking a waiting thread */
@ -94,7 +95,7 @@ class Genode::Semaphore
* in the wait queue.
*/
Element queue_element;
_queue.enqueue(&queue_element);
_queue.enqueue(queue_element);
_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
* under the terms of the GNU Affero General Public License version 3.
@ -37,71 +37,69 @@ class Genode::Fifo
friend class Fifo;
QT *_next;
bool _enqueued;
QT *_next { nullptr };
bool _enqueued { false };
public:
Element(): _next(0), _enqueued(false) { }
Element() { }
/**
* Return true is fifo element is enqueued in a fifo
*/
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
*
* \deprecated use 'Fifo::for_each' instead
*/
QT *next() const { return _next; }
};
private:
QT *_head; /* oldest element */
Element *_tail; /* newest element */
QT *_head { nullptr }; /* oldest element */
Element *_tail { nullptr }; /* newest element */
public:
/**
* Return true if queue is empty
*/
bool empty() { return _tail == 0; }
bool empty() { return _tail == nullptr; }
/**
* 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
*/
void remove(QT *qe)
void remove(QT &qe)
{
if (empty()) return;
/* if specified element is the first of the queue */
if (qe == _head) {
_head = qe->Fifo::Element::_next;
if (!_head) _tail = 0;
if (&qe == _head) {
_head = qe.Fifo::Element::_next;
if (!_head) _tail = nullptr;
}
else {
/* search specified element in the queue */
Element *e = _head;
while (e->_next && (e->_next != qe))
while (e->_next && (e->_next != &qe))
e = e->_next;
/* element is not member of the queue */
@ -112,50 +110,78 @@ class Genode::Fifo
if (!e->Element::_next) _tail = e;
}
qe->Fifo::Element::_next = 0;
qe->Fifo::Element::_enqueued = 0;
qe.Fifo::Element::_next = nullptr;
qe.Fifo::Element::_enqueued = false;
}
/**
* Attach element at the end of the queue
*/
void enqueue(QT *e)
void enqueue(QT &e)
{
e->Fifo::Element::_next = 0;
e->Fifo::Element::_enqueued = true;
e.Fifo::Element::_next = nullptr;
e.Fifo::Element::_enqueued = true;
if (empty()) {
_tail = _head = e;
_tail = _head = &e;
return;
}
_tail->Fifo::Element::_next = e;
_tail = e;
_tail->Fifo::Element::_next = &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
*
* \return head element or 0 if queue is empty
* If queue is not empty then remove head and
* call lambda 'func' of type 'void (QT&)'
*/
QT *dequeue()
template <typename FUNC>
void dequeue(FUNC const &func)
{
QT *result = _head;
/* check if queue has only one last element */
if (_head == _tail) {
_head = 0;
_tail = 0;
_head = nullptr;
_tail = nullptr;
} else
_head = _head->Fifo::Element::_next;
/* mark fifo queue element as free */
if (result) {
result->Fifo::Element::_next = 0;
result->Fifo::Element::_next = nullptr;
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>
class Genode::Fifo_element : public Fifo<Fifo_element<T> >::Element
{
T *_object;
T &_object;
public:
Fifo_element(T *object) : _object(object) { }
Fifo_element(T &object) : _object(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;
}
inline T &object() { return _object; }
};
#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) { }
using Fifo<Rm_faulter>::Element::next;
/**
* 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
* 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);
/* check if attach operation resolves any faulting region-manager clients */
for (Rm_faulter *faulter = _faulters.head(); faulter; ) {
/* 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.for_each([&] (Rm_faulter &faulter) {
if (faulter.fault_in_addr_range((addr_t)attach_at, size)) {
_faulters.remove(faulter);
faulter->continue_after_resolved_fault();
faulter.continue_after_resolved_fault();
}
faulter = next;
}
});
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));
/* enqueue faulter */
_faulters.enqueue(&faulter);
_faulters.enqueue(faulter);
/* issue fault signal */
_fault_notifier.submit();
@ -617,9 +611,9 @@ void Region_map_component::discard_faulter(Rm_faulter &faulter, bool do_lock)
{
if (do_lock) {
Lock::Guard lock_guard(_lock);
_faulters.remove(&faulter);
_faulters.remove(faulter);
} else
_faulters.remove(&faulter);
_faulters.remove(faulter);
}
@ -634,15 +628,13 @@ Region_map::State Region_map_component::state()
/* serialize access */
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 */
if (!faulter_ptr)
return Region_map::State();
Region_map::State result;
/* return fault information regarding the first faulter of the list */
return faulter_ptr->fault_state();
/* otherwise return fault information regarding the first faulter */
_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)
{
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 {
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 */
}
/* dequeue and return pending signal */
Signal_context_component &context = *_signal_queue.dequeue();
Signal result(context.imprint(), context.cnt());
context.reset_signal_cnt();
Signal result { };
_signal_queue.dequeue([&result] (Signal_context_component &context) {
result = Signal(context.imprint(), context.cnt());
context.reset_signal_cnt();
});
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)
{
for (Object const *o = &obj; o; o = o->next_obj()) {
if (o->is_binary())
continue;
log(" ", Hex(o->link_map().addr),
" .. ", Hex(o->link_map().addr + o->size() - 1),
": ", o->name());
}
if (!obj.is_binary())
log(" ", Hex(obj.link_map().addr),
" .. ", Hex(obj.link_map().addr + obj.size() - 1),
": ", obj.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
* 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),
_md_alloc(&md_alloc)
{
deps.enqueue(this);
deps.enqueue(*this);
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)
{
for (Dependency const *d = dep.head(); d; d = d->next())
if (!strcmp(file, d->obj().name()))
return true;
bool result = false;
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);
} catch (...) {
Init::list()->flush();
while (Dependency *d = _deps.dequeue())
destroy(_md_alloc, d);
_deps.dequeue_all([&] (Dependency &d) {
destroy(_md_alloc, &d); });
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
* under the terms of the GNU Affero General Public License version 3.
@ -135,7 +135,7 @@ class Linker::Dynamic
throw Fatal();
}
Needed *n = new (*_md_alloc) Needed(d->un.ptr);
_needed.enqueue(n);
_needed.enqueue(*n);
}
template <typename T>
@ -199,8 +199,8 @@ class Linker::Dynamic
if (!_md_alloc)
return;
while (Needed *n = _needed.dequeue())
destroy(*_md_alloc, n);
_needed.dequeue_all([&] (Needed &n) {
destroy(*_md_alloc, &n); });
}
void call_init_function() const
@ -310,8 +310,8 @@ class Linker::Dynamic
template <typename FUNC>
void for_each_dependency(FUNC const &fn) const
{
for (Needed *n = _needed.head(); n; n = n->next())
fn(n->path(_strtab));
_needed.for_each([&] (Needed &n) {
fn(n.path(_strtab)); });
}
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
* under the terms of the GNU Affero General Public License version 3.
@ -273,18 +273,27 @@ class Linker::Root_object
~Root_object()
{
while (Dependency *d = _deps.dequeue())
destroy(_md_alloc, d);
_deps.dequeue_all([&] (Dependency &d) {
destroy(_md_alloc, &d); });
}
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; }
};

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
* 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 */
Init::list()->insert(this);
obj_list()->enqueue(this);
obj_list()->enqueue(*this);
/* add to link map */
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);
/* remove from loaded objects list */
obj_list()->remove(this);
obj_list()->remove(*this);
}
/**
@ -314,7 +314,7 @@ Linker::Ld &Linker::Ld::linker()
{
Ld_vtable()
{
Elf_object::obj_list()->enqueue(this);
Elf_object::obj_list()->enqueue(*this);
plt_setup();
}
};
@ -502,24 +502,30 @@ bool Linker::Object::needs_static_construction()
Object &Linker::load(Env &env, Allocator &md_alloc, char const *path,
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)
log("LOAD: ", Linker::file(path), " == ", e->name());
if (!strcmp(Linker::file(path), e->name())) {
e->load();
return *e;
if (!strcmp(Linker::file(path), e.name())) {
e.load();
result = &e;
}
}
}
return *new (md_alloc) Elf_object(env, md_alloc, path, dep, keep);
});
if (result == nullptr)
result = new (md_alloc) Elf_object(env, md_alloc, path, dep, keep);
return *result;
}
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() +
Thread::stack_area_virtual_size() - 1),
": stack area");
dump_link_map(*Elf_object::obj_list()->head());
Elf_object::obj_list()->for_each([] (Object const &obj) {
dump_link_map(obj); });
}
} catch (...) { }

View File

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

View File

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

View File

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

View File

@ -64,7 +64,7 @@ class Isoc_packet : Fifo<Isoc_packet>::Element
{
if (!valid()) return false;
int remaining = _size - _offset;
unsigned remaining = _size - _offset;
int copy_size = min(usb_packet->iov.size, remaining);
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
{
Usb_host_device(const Usb_host_device&);
const Usb_host_device& operator=(const Usb_host_device&);
struct Could_not_create_device : Exception { };
bool deleted = false;
char const *label = nullptr;
Dev_info const info;
USBHostDevice *qemu_dev;
USBHostDevice *qemu_dev { nullptr };
/* submit queue + ack queue + 1 -> max nr of packets in flight */
enum { NUM_COMPLETIONS = Usb::Session::TX_QUEUE_SIZE * 2 + 1 };
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 };
Signal_receiver &sig_rec;
@ -323,7 +326,9 @@ struct Usb_host_device : List<Usb_host_device>::Element
/* isochronous in */
free_completion(packet);
_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;
}
if (isoc_read_queue.head()->copy(packet)) {
free_packet(isoc_read_queue.dequeue());
}
isoc_read_queue.head([&] (Isoc_packet &head) {
if (head.copy(packet)) {
isoc_read_queue.remove(head);
free_packet(&head);
}
});
return true;
}
@ -351,9 +359,7 @@ struct Usb_host_device : List<Usb_host_device>::Element
bool isoc_new_packet()
{
unsigned count = 0;
for (Isoc_packet *packet = isoc_read_queue.head(); packet;
packet = packet->next(), count++);
isoc_read_queue.for_each([&count] (Isoc_packet&) { count++; });
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)
{
/* flush finished and stored data */
for (Isoc_packet *packet = isoc_read_queue.head(); packet; )
{
if (!all && (!packet->valid() || packet->packet().transfer.ep != ep)) {
packet = packet->next();
continue;
isoc_read_queue.for_each([&] (Isoc_packet &packet) {
if (!all && (!packet.valid() || packet.packet().transfer.ep != ep)) {
return;
}
Isoc_packet *next = packet->next();
isoc_read_queue.remove(packet);
free_packet(packet);
packet = next;
}
free_packet(&packet);
});
/* flush in flight packets */
flush_completion(ep);

View File

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

View File

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

View File

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

View File

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