diff --git a/repos/base-nova/include/signal_session/source_client.h b/repos/base-nova/include/signal_session/source_client.h index c69aa25bd..8cd4aabfb 100644 --- a/repos/base-nova/include/signal_session/source_client.h +++ b/repos/base-nova/include/signal_session/source_client.h @@ -62,7 +62,14 @@ namespace Genode { */ Signal_source_client(Signal_source_capability cap) : Rpc_client( - static_cap_cast(cap)) { } + static_cap_cast(cap)) + { + /* + * Make sure that we have acquired the + * semaphore from the server + */ + _init_sem(); + } /***************************** @@ -71,25 +78,18 @@ namespace Genode { Signal wait_for_signal() { - /* - * Make sure that we have acquired the - * semaphore from the server - */ - _init_sem(); - /* * Block on semaphore, will be unblocked if * signal is available */ - if (Nova::sm_ctrl(_sem.local_name(), Nova::SEMAPHORE_DOWN)) - nova_die(); + using namespace Nova; + mword_t value = 0; + mword_t count = 0; + if (uint8_t res = si_ctrl(_sem.local_name(), SEMAPHORE_DOWN, + value, count)) + PWRN("signal reception failed - error %u", res); - /* - * Now that the server has unblocked the semaphore, we are sure - * that there is a signal pending. The following 'wait_for_signal' - * request will be immediately answered. - */ - return call(); + return Signal(value, count); } }; } diff --git a/repos/base-nova/include/signal_session/source_rpc_object.h b/repos/base-nova/include/signal_session/source_rpc_object.h index 4a05cf5f4..39aeacf84 100644 --- a/repos/base-nova/include/signal_session/source_rpc_object.h +++ b/repos/base-nova/include/signal_session/source_rpc_object.h @@ -10,7 +10,7 @@ */ /* - * Copyright (C) 2010-2013 Genode Labs GmbH + * Copyright (C) 2010-2015 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. @@ -27,32 +27,9 @@ namespace Genode { struct Signal_source_rpc_object; } struct Genode::Signal_source_rpc_object : Rpc_object { - private: + public: Native_capability _blocking_semaphore; - bool _missed_wakeup; - - protected: - - void _wakeup_client() - { - if (!_blocking_semaphore.valid()) { - _missed_wakeup = true; - return; - } - - if (_missed_wakeup) - _missed_wakeup = false; - - /* wake up client */ - uint8_t res = Nova::sm_ctrl(_blocking_semaphore.local_name(), - Nova::SEMAPHORE_UP); - if (res != Nova::NOVA_OK) { - PWRN("%s - signal delivery failed - error %x", - __func__, res); - _missed_wakeup = true; - } - } public: @@ -62,12 +39,9 @@ struct Genode::Signal_source_rpc_object : Rpc_object + +using namespace Genode; + +/************************ + ** Signal transmitter ** + ************************/ +void Signal_transmitter::submit(unsigned cnt) +{ + { + Trace::Signal_submit trace_event(cnt); + } + + using namespace Nova; + + uint8_t res = NOVA_OK; + for (unsigned i = 0; res == NOVA_OK && i < cnt; i++) + res = sm_ctrl(_context.local_name(), SEMAPHORE_UP); + + if (res != NOVA_OK) + PDBG("failed - error %u", res); +} diff --git a/repos/base-nova/src/core/include/signal_session_component.h b/repos/base-nova/src/core/include/signal_session_component.h new file mode 100644 index 000000000..dfb201ee0 --- /dev/null +++ b/repos/base-nova/src/core/include/signal_session_component.h @@ -0,0 +1,135 @@ +/* + * \brief Signal service + * \author Norman Feske + * \date 2009-08-05 + */ + +/* + * Copyright (C) 2009-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _CORE__INCLUDE__SIGNAL_SESSION_COMPONENT_H_ +#define _CORE__INCLUDE__SIGNAL_SESSION_COMPONENT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Genode { + + class Signal_source_component; + class Signal_context_component; + + typedef Fifo Signal_queue; + + class Signal_context_component : public Object_pool::Entry + { + public: + + /** + * Constructor + */ + Signal_context_component(Signal_context_capability cap) + : Object_pool::Entry(cap) { } + }; + + + class Signal_source_component : public Signal_source_rpc_object + { + public: + + /** + * Constructor + */ + Signal_source_component(Rpc_entrypoint *) { } + + /***************************** + ** Signal-source interface ** + *****************************/ + + Signal wait_for_signal() { return Signal(0, 0); } + }; + + + class Signal_session_component : public Rpc_object + { + private: + + Rpc_entrypoint *_source_ep; + Object_pool _signal_queue; + Signal_source_component _source; + Signal_source_capability _source_cap; + Allocator_guard _md_alloc; + Tslab _contexts_slab; + Ipc_ostream *_ipc_ostream; + + public: + + /** + * Constructor + * + * \param source_ep entrypoint holding signal-source component + * objects + * \param context_ep global pool of all signal contexts + * \param md_alloc backing-store allocator for + * signal-context component objects + * + * To maintain proper synchronization, 'signal_source_ep' must be + * the same entrypoint as used for the signal-session component. + * The 'signal_context_ep' is only used for associative array + * to map signal-context capabilities to 'Signal_context_component' + * objects and as capability allocator for such objects. + */ + Signal_session_component(Rpc_entrypoint *source_ep, + Rpc_entrypoint *context_ep, + Allocator *context_md_alloc, + size_t ram_quota); + + ~Signal_session_component(); + + /** + * Register quota donation at allocator guard + */ + void upgrade_ram_quota(size_t ram_quota) { _md_alloc.upgrade(ram_quota); } + + + /****************************** + ** Signal-session interface ** + ******************************/ + + Signal_source_capability signal_source(); + Signal_context_capability alloc_context(long imprint); + void free_context(Signal_context_capability context_cap); + void submit(Signal_context_capability context_cap, unsigned cnt); + + + /************************** + ** Rpc_object interface ** + **************************/ + + Rpc_exception_code dispatch(int opcode, Ipc_istream &is, Ipc_ostream &os) + { + /* + * Make IPC output stream available to the submit function. The + * stream is used to carry signal payload for the out-of-order + * handling of 'wait_for_signal' replies. + */ + _ipc_ostream = &os; + + /* dispatch RPC */ + return Rpc_object::dispatch(opcode, is, os); + } + }; +} + +#endif /* _CORE__INCLUDE__CAP_SESSION_COMPONENT_H_ */ diff --git a/repos/base-nova/src/core/signal_session_component.cc b/repos/base-nova/src/core/signal_session_component.cc new file mode 100644 index 000000000..3c07ea999 --- /dev/null +++ b/repos/base-nova/src/core/signal_session_component.cc @@ -0,0 +1,110 @@ +/* + * \brief Implementation of the SIGNAL interface + * \author Alexander Boettcher + * \date 2015-03-04 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include + +/* core includes */ +#include + +using namespace Genode; + + +/****************************** + ** Signal-session component ** + ******************************/ + +Signal_session_component::Signal_session_component(Rpc_entrypoint *source_ep, + Rpc_entrypoint *context_ep, + Allocator *context_md_alloc, + size_t ram_quota) +: + _source_ep(source_ep), + _source(source_ep), + _source_cap(_source_ep->manage(&_source)), + _md_alloc(context_md_alloc, ram_quota), + _contexts_slab(&_md_alloc) +{ } + + +Signal_session_component::~Signal_session_component() +{ + /* remove _signal_source from entrypoint */ + _source_ep->dissolve(&_source); + + /* free all signal contexts */ + while (Signal_context_component *r = _contexts_slab.first_object()) + free_context(reinterpret_cap_cast(Native_capability(r->cap()))); +} + + +Signal_source_capability Signal_session_component::signal_source() +{ + return _source_cap; +} + +extern "C" Genode::addr_t __core_pd_sel; + +Signal_context_capability Signal_session_component::alloc_context(long imprint) +{ + Native_capability sm = _source._blocking_semaphore; + + if (!sm.valid()) { + PWRN("signal receiver sm is not valid"); + return Signal_context_capability(); + } + + Native_capability si(cap_map()->insert()); + Signal_context_capability cap = reinterpret_cap_cast(si); + + uint8_t res = Nova::create_si(cap.local_name(), __core_pd_sel, imprint, + sm.local_name()); + if (res != Nova::NOVA_OK) { + PWRN("creating signal failed - error %u", res); + return Signal_context_capability(); + } + + try { + _signal_queue.insert(new (&_contexts_slab) Signal_context_component(cap)); + } catch (Allocator::Out_of_memory) { + throw Out_of_metadata(); + } + + /* return unique capability for the signal context */ + return cap; +} + + +void Signal_session_component::free_context(Signal_context_capability context_cap) +{ + Signal_context_component * context = + dynamic_cast(_signal_queue.lookup_and_lock(context_cap.local_name())); + if (!context) { + PWRN("%p - specified signal-context capability has wrong type %lx", + this, context_cap.local_name()); + return; + } + + _signal_queue.remove_locked(context); + destroy(&_contexts_slab, context); + + Nova::revoke(Nova::Obj_crd(context_cap.local_name(), 0)); + cap_map()->remove(context_cap.local_name(), 0); +} + + +void Signal_session_component::submit(Signal_context_capability context_cap, + unsigned cnt) +{ + PDBG("should not be called"); +} diff --git a/repos/base-nova/src/core/signal_source_component.cc b/repos/base-nova/src/core/signal_source_component.cc deleted file mode 100644 index 9a502f536..000000000 --- a/repos/base-nova/src/core/signal_source_component.cc +++ /dev/null @@ -1,89 +0,0 @@ -/* - * \brief Implementation of the SIGNAL interface - * \author Norman Feske - * \date 2009-08-11 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include - -/* core includes */ -#include -#include - -/* NOVA includes */ -#include - -using namespace Genode; - - -/***************************** - ** Signal-source component ** - *****************************/ - -void Signal_source_component::release(Signal_context_component *context) -{ - if (context && context->is_enqueued()) - _signal_queue.remove(context); -} - - -void Signal_source_component::submit(Signal_context_component *context, - Ipc_ostream *ostream, - int cnt) -{ - /* enqueue signal to context */ - context->increment_signal_cnt(cnt); - - if (!context->is_enqueued()) { - _signal_queue.enqueue(context); - - _wakeup_client(); - } -} - - -Signal_source::Signal Signal_source_component::wait_for_signal() -{ - if (_signal_queue.empty()) { - PWRN("unexpected call of wait_for_signal"); - return Signal(0, 0); - } - - /* dequeue and return pending signal */ - Signal_context_component *context = _signal_queue.dequeue(); - Signal result(context->imprint(), context->cnt()); - context->reset_signal_cnt(); - return result; -} - - -Signal_source_component::Signal_source_component(Rpc_entrypoint *ep) -: - _entrypoint(ep), _finalizer(*this), - _finalizer_cap(_entrypoint->manage(&_finalizer)) { } - - -Signal_source_component::~Signal_source_component() -{ - _finalizer_cap.call(); - _entrypoint->dissolve(&_finalizer); -} - - -void Signal_source_component::Finalizer_component::exit() -{ - /* - * On NOVA, the signal-source client does not use a blocking call - * to wait for signals. Hence, we do not need to take care of - * releasing the reply capability of such a call. - */ -} diff --git a/repos/base-nova/src/core/target.inc b/repos/base-nova/src/core/target.inc index dbab69a0a..d585d076a 100644 --- a/repos/base-nova/src/core/target.inc +++ b/repos/base-nova/src/core/target.inc @@ -24,7 +24,6 @@ SRC_CC = main.cc \ io_port_session_component.cc \ irq_session_component.cc \ signal_session_component.cc \ - signal_source_component.cc \ trace_session_component.cc \ core_rm_session.cc \ context_area.cc \ @@ -48,7 +47,6 @@ vpath rom_session_component.cc $(GEN_CORE_DIR) vpath cpu_session_component.cc $(GEN_CORE_DIR) vpath pd_session_component.cc $(GEN_CORE_DIR) vpath rm_session_component.cc $(GEN_CORE_DIR) -vpath signal_session_component.cc $(GEN_CORE_DIR) vpath trace_session_component.cc $(GEN_CORE_DIR) vpath io_port_session_component.cc $(GEN_CORE_DIR)/x86 vpath io_mem_session_component.cc $(GEN_CORE_DIR)