diff --git a/repos/base/include/rom_session/client.h b/repos/base/include/rom_session/client.h index 5c4607b29c..fc33f5a297 100644 --- a/repos/base/include/rom_session/client.h +++ b/repos/base/include/rom_session/client.h @@ -17,18 +17,21 @@ #include #include -namespace Genode { +namespace Genode { struct Rom_session_client; } - struct Rom_session_client : Rpc_client - { - explicit Rom_session_client(Rom_session_capability session) - : Rpc_client(session) { } +struct Genode::Rom_session_client : Rpc_client +{ + explicit Rom_session_client(Rom_session_capability session) + : Rpc_client(session) { } - Rom_dataspace_capability dataspace() { - return call(); } + Rom_dataspace_capability dataspace() override { + return call(); } - void sigh(Signal_context_capability cap) { call(cap); } - }; -} + bool update() override { + return call(); } + + void sigh(Signal_context_capability cap) override { + call(cap); } +}; #endif /* _INCLUDE__ROM_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/rom_session/rom_session.h b/repos/base/include/rom_session/rom_session.h index fb21b917da..816bc7c668 100644 --- a/repos/base/include/rom_session/rom_session.h +++ b/repos/base/include/rom_session/rom_session.h @@ -3,12 +3,12 @@ * \author Norman Feske * \date 2006-07-06 * - * A ROM session corresponds to an open file. The file name is specified as an - * argument on session creation. + * A ROM session corresponds to a ROM module. The module name is specified as + * an argument on session creation. */ /* - * Copyright (C) 2006-2013 Genode Labs GmbH + * Copyright (C) 2006-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. @@ -25,58 +25,82 @@ namespace Genode { struct Rom_dataspace : Dataspace { }; + struct Rom_session; + typedef Capability Rom_dataspace_capability; - - struct Rom_session : Session - { - static const char *service_name() { return "ROM"; } - - virtual ~Rom_session() { } - - /** - * Request dataspace containing the ROM session data - * - * \return capability to ROM dataspace - * - * The capability may be invalid. - * - * Consecutive calls of this functions are not guaranteed to return the - * same dataspace as dynamic ROM sessions may update the ROM data - * during the lifetime of the session. When calling the function, the - * server may destroy the old dataspace and replace it with a new one - * containing the updated data. Hence, prior calling this function, the - * client should make sure to detach the previously requested dataspace - * from its local address space. - */ - virtual Rom_dataspace_capability dataspace() = 0; - - /** - * Register signal handler to be notified of ROM data changes - * - * The ROM session interface allows for the implementation of ROM - * services that dynamically update the data exported as ROM dataspace - * during the lifetime of the session. This is useful in scenarios - * where this data is generated rather than originating from a static - * file, for example to update a program's configuration at runtime. - * - * By installing a signal handler using the 'sigh()' function, the - * client will receive a notification each time the data changes at the - * server. From the client's perspective, the original data contained - * in the currently used dataspace remains unchanged until the client - * calls 'dataspace()' the next time. - */ - virtual void sigh(Signal_context_capability sigh) = 0; - - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC(Rpc_dataspace, Rom_dataspace_capability, dataspace); - GENODE_RPC(Rpc_sigh, void, sigh, Signal_context_capability); - - GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_sigh); - }; } + +struct Genode::Rom_session : Session +{ + static const char *service_name() { return "ROM"; } + + virtual ~Rom_session() { } + + /** + * Request dataspace containing the ROM session data + * + * \return capability to ROM dataspace + * + * The capability may be invalid. + * + * Consecutive calls of this functions are not guaranteed to return the + * same dataspace as dynamic ROM sessions may update the ROM data + * during the lifetime of the session. When calling the function, the + * server may destroy the old dataspace and replace it with a new one + * containing the updated data. Hence, prior calling this function, the + * client should make sure to detach the previously requested dataspace + * from its local address space. + */ + virtual Rom_dataspace_capability dataspace() = 0; + + /** + * Update ROM dataspace content + * + * This function is an optimization for use cases where ROM dataspaces + * are updated at a high rate. In such cases, requesting a new + * dataspace for each update induces a large overhead because + * memory mappings must be revoked and updated (e.g., handling the + * page faults referring to the dataspace). If the updated content + * fits in the existing dataspace, those costly operations can be + * omitted. + * + * When this function is called, the server may replace the dataspace + * content with new data. + * + * \return true if the existing dataspace contains up-to-date content, + * or false if a new dataspace must be requested via the + * 'dataspace' function + */ + virtual bool update() { return false; } + + /** + * Register signal handler to be notified of ROM data changes + * + * The ROM session interface allows for the implementation of ROM + * services that dynamically update the data exported as ROM dataspace + * during the lifetime of the session. This is useful in scenarios + * where this data is generated rather than originating from a static + * file, for example to update a program's configuration at runtime. + * + * By installing a signal handler using the 'sigh()' function, the + * client will receive a notification each time the data changes at the + * server. From the client's perspective, the original data contained + * in the currently used dataspace remains unchanged until the client + * calls 'dataspace()' the next time. + */ + virtual void sigh(Signal_context_capability sigh) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_dataspace, Rom_dataspace_capability, dataspace); + GENODE_RPC(Rpc_sigh, void, sigh, Signal_context_capability); + GENODE_RPC(Rpc_update, bool, update); + + GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_update, Rpc_sigh); +}; + #endif /* _INCLUDE__ROM_SESSION__ROM_SESSION_H_ */ diff --git a/repos/os/include/os/attached_rom_dataspace.h b/repos/os/include/os/attached_rom_dataspace.h index e88e8e6cc5..e36a48ba6c 100644 --- a/repos/os/include/os/attached_rom_dataspace.h +++ b/repos/os/include/os/attached_rom_dataspace.h @@ -79,9 +79,25 @@ class Genode::Attached_rom_dataspace void sigh(Signal_context_capability sigh) { _rom.sigh(sigh); } /** - * Re-attach ROM module + * Update ROM module content, re-attach if needed */ - void update() { _try_attach(); } + void update() + { + /* + * If the dataspace is already attached and the update fits into + * the existing dataspace, we can keep everything in place. The + * dataspace content gets updated by the call of '_rom.update'. + */ + if (_ds.is_constructed() && _rom.update() == true) + return; + + /* + * If there was no valid dataspace attached beforehand or the + * new data size exceeds the capacity of the existing dataspace, + * replace the current dataspace by a new one. + */ + _try_attach(); + } /** * Return true of content is present diff --git a/repos/os/src/server/report_rom/rom_service.h b/repos/os/src/server/report_rom/rom_service.h index 951acfbb7d..e0320d0fe9 100644 --- a/repos/os/src/server/report_rom/rom_service.h +++ b/repos/os/src/server/report_rom/rom_service.h @@ -73,6 +73,15 @@ class Rom::Session_component : public Genode::Rpc_object, return static_cap_cast(ds_cap); } + bool update() override + { + if (!_ds.is_constructed() || _module.size() > _ds->size()) + return false; + + _module.read_content(_ds->local_addr(), _ds->size()); + return true; + } + void sigh(Genode::Signal_context_capability sigh) override { _sigh = sigh;