/* * \brief Platform-independent part of server-side RPC framework * \author Norman Feske * \date 2006-05-12 */ /* * Copyright (C) 2006-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. */ /* Genode includes */ #include #include #include #include /* base-internal includes */ #include #include using namespace Genode; void Rpc_entrypoint::_dissolve(Rpc_object_base *obj) { /* don't dissolve RPC object twice */ if (!obj->cap().valid()) return; /* make sure nobody is able to find this object */ remove(obj); _free_rpc_cap(_pd_session, obj->cap()); /* effectively invalidate the capability used before */ obj->cap(Untyped_capability()); /* now the object may be safely destructed */ } void Rpc_entrypoint::_block_until_cap_valid() { _cap_valid.lock(); } void Rpc_entrypoint::reply_signal_info(Untyped_capability reply_cap, unsigned long imprint, unsigned long cnt) { Msgbuf snd_buf; snd_buf.insert(Signal_source::Signal(imprint, cnt)); ipc_reply(reply_cap, Rpc_exception_code(Rpc_exception_code::SUCCESS), snd_buf); } void Rpc_entrypoint::activate() { _delay_start.unlock(); } bool Rpc_entrypoint::is_myself() const { return (Thread::myself() == this); } Rpc_entrypoint::Rpc_entrypoint(Pd_session *pd_session, size_t stack_size, char const *name, bool start_on_construction, Affinity::Location location) : Thread(Cpu_session::Weight::DEFAULT_WEIGHT, name, _native_stack_size(stack_size), location), _cap(Untyped_capability()), _cap_valid(Lock::LOCKED), _delay_start(Lock::LOCKED), _delay_exit(Lock::LOCKED), _pd_session(*pd_session) { Thread::start(); _block_until_cap_valid(); if (start_on_construction) activate(); _exit_cap = manage(&_exit_handler); } Rpc_entrypoint::~Rpc_entrypoint() { /* * We have to make sure the server loop is running which is only the case * if the Rpc_entrypoint was actived before we execute the RPC call. */ _delay_start.unlock(); /* leave server loop */ _exit_cap.call(); dissolve(&_exit_handler); if (!empty()) warning("object pool not empty in ", __func__); /* * Now that we finished the 'dissolve' steps above (which need a working * 'Ipc_server' in the context of the entrypoint thread), we can allow the * entrypoint thread to leave the scope. Thereby, the 'Ipc_server' object * will get destructed. */ _delay_exit.unlock(); join(); }