From bdfbe9f20e084d1bc1b67003a385fd2249df3234 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Sat, 11 Jan 2014 00:09:13 +0100 Subject: [PATCH] New 'os/attached_dataspace.h' utility The new Attached_dataspace complements the existing Attached_* utilities with a simple version that can be used with any kind of dataspaces. It may be even useful as a common base type for the other variants. For example, this patch simplifies Attached_rom_dataspace and removes the Terminal::Client::Io_buffer. --- os/include/os/attached_dataspace.h | 83 +++++++++++++++ os/include/os/attached_rom_dataspace.h | 120 +++++++++------------- os/include/terminal_session/client.h | 137 +++++++++++-------------- 3 files changed, 189 insertions(+), 151 deletions(-) create mode 100644 os/include/os/attached_dataspace.h diff --git a/os/include/os/attached_dataspace.h b/os/include/os/attached_dataspace.h new file mode 100644 index 0000000000..87b104491d --- /dev/null +++ b/os/include/os/attached_dataspace.h @@ -0,0 +1,83 @@ +/* + * \brief Dataspace utility + * \author Norman Feske + * \date 2014-01-10 + */ + +/* + * Copyright (C) 2014 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 _INCLUDE__OS__ATTACHED_DATASPACE_H_ +#define _INCLUDE__OS__ATTACHED_DATASPACE_H_ + +#include +#include + +namespace Genode { class Attached_dataspace; } + + +class Genode::Attached_dataspace : Noncopyable +{ + public: + + /** + * Exception type + */ + class Invalid_dataspace { }; + + private: + + Dataspace_capability _ds; + + size_t const _size = { Dataspace_client(_ds).size() }; + + void * const _local_addr = { env()->rm_session()->attach(_ds) }; + + Dataspace_capability _check(Dataspace_capability ds) + { + if (ds.valid()) + return ds; + + throw Invalid_dataspace(); + } + + public: + + /** + * Constructor + * + * \throw Rm_session::Attach_failed + * \throw Invalid_dataspace + */ + Attached_dataspace(Dataspace_capability ds) : _ds(_check(ds)) { } + + /** + * Destructor + */ + ~Attached_dataspace() { env()->rm_session()->detach(_local_addr); } + + /** + * Return capability of the used dataspace + */ + Dataspace_capability cap() const { return _ds; } + + /** + * Request local address + * + * This is a template to avoid inconvenient casts at the caller. + * A newly attached dataspace is untyped memory anyway. + */ + template + T *local_addr() { return static_cast(_local_addr); } + + /** + * Return size + */ + size_t size() const { return _size; } +}; + +#endif /* _INCLUDE__OS__ATTACHED_DATASPACE_H_ */ diff --git a/os/include/os/attached_rom_dataspace.h b/os/include/os/attached_rom_dataspace.h index cebdc458d4..f86182b4a7 100644 --- a/os/include/os/attached_rom_dataspace.h +++ b/os/include/os/attached_rom_dataspace.h @@ -14,93 +14,65 @@ #ifndef _INCLUDE__OS__ATTACHED_ROM_DATASPACE_H_ #define _INCLUDE__OS__ATTACHED_ROM_DATASPACE_H_ +#include +#include #include -#include -#include -namespace Genode { +namespace Genode { class Attached_rom_dataspace; } - class Attached_rom_dataspace - { - private: - Rom_connection _rom; - Rom_dataspace_capability _ds; - size_t _size; - void *_local_addr = 0; +class Genode::Attached_rom_dataspace +{ + private: - void _detach() - { - if (!_local_addr) - return; + Rom_connection _rom; - env()->rm_session()->detach(_local_addr); - _local_addr = 0; - _size = 0; - } + /* + * A ROM module may change or disappear over the lifetime of a ROM + * session. In contrast to the plain 'Attached_dataspace', which is + * always be valid once constructed, a 'Attached_rom_dataspace' has + * to handle the validity of the dataspace. + */ + Lazy_volatile_object _ds; - void _attach() - { - if (_local_addr) - _detach(); + /** + * Try to attach the ROM module, ignore invalid dataspaces + */ + void _try_attach() + { + try { _ds.construct(_rom.dataspace()); } + catch (Attached_dataspace::Invalid_dataspace) { } + } - _ds = _rom.dataspace(); - if (_ds.valid()) { - _size = Dataspace_client(_ds).size(); - _local_addr = env()->rm_session()->attach(_ds); - } - } + public: - public: + /** + * Constructor + * + * \throw Rom_connection::Rom_connection_failed + * \throw Rm_session::Attach_failed + */ + Attached_rom_dataspace(char const *name) + : _rom(name) { _try_attach(); } - /** - * Constructor - * - * \throw Rom_connection::Rom_connection_failed - * \throw Rm_session::Attach_failed - */ - Attached_rom_dataspace(char const *name) - : _rom(name) { _attach(); } + template T *local_addr() { return _ds->local_addr(); } - /** - * Destructor - */ - ~Attached_rom_dataspace() { _detach(); } + size_t size() const { return _ds->size(); } - /** - * Return capability of the used ROM dataspace - */ - Rom_dataspace_capability cap() const { return _ds; } + /** + * Register signal handler for ROM module changes + */ + void sigh(Signal_context_capability sigh) { _rom.sigh(sigh); } - /** - * Request local address - * - * This is a template to avoid inconvenient casts at the caller. - * A newly allocated ROM dataspace is untyped memory anyway. - */ - template - T *local_addr() { return static_cast(_local_addr); } + /** + * Re-attach ROM module + */ + void update() { _try_attach(); } - /** - * Return size - */ - size_t size() const { return _size; } - - /** - * Register signal handler for ROM module changes - */ - void sigh(Signal_context_capability sigh) { _rom.sigh(sigh); } - - /** - * Re-attach ROM module - */ - void update() { _attach(); } - - /** - * Return true of content is present - */ - bool is_valid() const { return _local_addr != 0; } - }; -} + /** + * Return true of content is present + */ + bool is_valid() const { return _ds.is_constructed(); } +}; #endif /* _INCLUDE__OS__ATTACHED_ROM_DATASPACE_H_ */ diff --git a/os/include/terminal_session/client.h b/os/include/terminal_session/client.h index 7d8b5212a1..32b868acae 100644 --- a/os/include/terminal_session/client.h +++ b/os/include/terminal_session/client.h @@ -18,103 +18,86 @@ #include #include #include -#include #include +#include #include -namespace Terminal { +namespace Terminal { class Session_client; } - class Session_client : public Genode::Rpc_client - { - private: - /** - * Shared-memory buffer used for carrying the payload - * of read/write operations - */ - struct Io_buffer - { - Genode::Dataspace_capability ds_cap; - char *base; - Genode::size_t size; - Genode::Lock lock; +class Terminal::Session_client : public Genode::Rpc_client +{ + private: - Io_buffer(Genode::Dataspace_capability ds_cap) - : - ds_cap(ds_cap), - base(Genode::env()->rm_session()->attach(ds_cap)), - size(ds_cap.call()) - { } + Genode::Lock _lock; - ~Io_buffer() - { - Genode::env()->rm_session()->detach(base); - } - }; + /** + * Shared-memory buffer used for carrying the payload + * of read/write operations + */ + Genode::Attached_dataspace _io_buffer; - Io_buffer _io_buffer; + public: - public: + Session_client(Genode::Capability cap) + : + Genode::Rpc_client(cap), + _io_buffer(call()) + { } - Session_client(Genode::Capability cap) - : - Genode::Rpc_client(cap), - _io_buffer(call()) - { } + Size size() { return call(); } - Size size() { return call(); } + bool avail() { return call(); } - bool avail() { return call(); } + Genode::size_t read(void *buf, Genode::size_t buf_size) + { + Genode::Lock::Guard _guard(_lock); - Genode::size_t read(void *buf, Genode::size_t buf_size) - { - Genode::Lock::Guard _guard(_io_buffer.lock); + /* instruct server to fill the I/O buffer */ + Genode::size_t num_bytes = call(buf_size); - /* instruct server to fill the I/O buffer */ - Genode::size_t num_bytes = call(buf_size); + /* copy-out I/O buffer */ + num_bytes = Genode::min(num_bytes, buf_size); + Genode::memcpy(buf, _io_buffer.local_addr(), num_bytes); - /* copy-out I/O buffer */ - num_bytes = Genode::min(num_bytes, buf_size); - Genode::memcpy(buf, _io_buffer.base, num_bytes); + return num_bytes; + } - return num_bytes; + Genode::size_t write(void const *buf, Genode::size_t num_bytes) + { + Genode::Lock::Guard _guard(_lock); + + Genode::size_t written_bytes = 0; + char const * const src = (char const *)buf; + + while (written_bytes < num_bytes) { + + /* copy payload to I/O buffer */ + Genode::size_t n = Genode::min(num_bytes - written_bytes, + _io_buffer.size()); + Genode::memcpy(_io_buffer.local_addr(), + src + written_bytes, n); + + /* tell server to pick up new I/O buffer content */ + call(n); + + written_bytes += n; } + return num_bytes; + } - Genode::size_t write(void const *buf, Genode::size_t num_bytes) - { - Genode::Lock::Guard _guard(_io_buffer.lock); + void connected_sigh(Genode::Signal_context_capability cap) + { + call(cap); + } - Genode::size_t written_bytes = 0; - char const * const src = (char const *)buf; + void read_avail_sigh(Genode::Signal_context_capability cap) + { + call(cap); + } - while (written_bytes < num_bytes) { - - /* copy payload to I/O buffer */ - Genode::size_t n = Genode::min(num_bytes - written_bytes, - _io_buffer.size); - Genode::memcpy(_io_buffer.base, src + written_bytes, n); - - /* tell server to pick up new I/O buffer content */ - call(n); - - written_bytes += n; - } - return num_bytes; - } - - void connected_sigh(Genode::Signal_context_capability cap) - { - call(cap); - } - - void read_avail_sigh(Genode::Signal_context_capability cap) - { - call(cap); - } - - Genode::size_t io_buffer_size() const { return _io_buffer.size; } - }; -} + Genode::size_t io_buffer_size() const { return _io_buffer.size(); } +}; #endif /* _INCLUDE__TERMINAL_SESSION__CLIENT_H_ */