/* * \brief RAM service used by Noux processes * \author Norman Feske * \date 2012-02-22 * * The custom implementation of the RAM session interface provides a pool of * RAM shared by Noux and all Noux processes. The use of a shared pool * alleviates the need to assign RAM quota to individual Noux processes. * * Furthermore, the custom implementation is needed to get hold of the RAM * dataspaces allocated by each Noux process. When forking a process, the * acquired information (in the form of 'Ram_dataspace_info' objects) is used * to create a shadow copy of the forking address space. */ /* * Copyright (C) 2012-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 _NOUX__RAM_SESSION_COMPONENT_H_ #define _NOUX__RAM_SESSION_COMPONENT_H_ /* Genode includes */ #include #include /* Noux includes */ #include namespace Noux { struct Ram_dataspace_info; struct Ram_session_component; using namespace Genode; } struct Noux::Ram_dataspace_info : Dataspace_info, List::Element { Ram_dataspace_info(Ram_dataspace_capability ds_cap) : Dataspace_info(ds_cap) { } Dataspace_capability fork(Ram_session &ram, Region_map &local_rm, Allocator &alloc, Dataspace_registry &ds_registry, Rpc_entrypoint &) override { size_t const size = Dataspace_client(ds_cap()).size(); Ram_dataspace_capability dst_ds_cap; try { dst_ds_cap = ram.alloc(size); Attached_dataspace src_ds(local_rm, ds_cap()); Attached_dataspace dst_ds(local_rm, dst_ds_cap); memcpy(dst_ds.local_addr(), src_ds.local_addr(), size); ds_registry.insert(new (alloc) Ram_dataspace_info(dst_ds_cap)); return dst_ds_cap; } catch (...) { error("fork of RAM dataspace failed"); if (dst_ds_cap.valid()) ram.free(dst_ds_cap); return Dataspace_capability(); } } void poke(Region_map &rm, addr_t dst_offset, char const *src, size_t len) override { if (!src) return; if ((dst_offset >= size()) || (dst_offset + len > size())) { error("illegal attemt to write beyond dataspace boundary"); return; } try { Attached_dataspace ds(rm, ds_cap()); memcpy(ds.local_addr() + dst_offset, src, len); } catch (...) { warning("poke: failed to attach RAM dataspace"); } } }; class Noux::Ram_session_component : public Rpc_object { private: Ram_session &_ram; Allocator &_alloc; Rpc_entrypoint &_ep; List _list; /* * Track the RAM resources accumulated via RAM session allocations. * * XXX not used yet */ size_t _used_ram_quota = 0; Dataspace_registry &_registry; public: /** * Constructor */ Ram_session_component(Ram_session &ram, Allocator &alloc, Rpc_entrypoint &ep, Dataspace_registry ®istry) : _ram(ram), _alloc(alloc), _ep(ep), _registry(registry) { _ep.manage(this); } /** * Destructor */ ~Ram_session_component() { _ep.dissolve(this); Ram_dataspace_info *info = 0; while ((info = _list.first())) free(static_cap_cast(info->ds_cap())); } /*************************** ** Ram_session interface ** ***************************/ Ram_dataspace_capability alloc(size_t size, Cache_attribute cached) override { Ram_dataspace_capability ds_cap = _ram.alloc(size, cached); Ram_dataspace_info *ds_info = new (_alloc) Ram_dataspace_info(ds_cap); _used_ram_quota += ds_info->size(); _registry.insert(ds_info); _list.insert(ds_info); return ds_cap; } void free(Ram_dataspace_capability ds_cap) override { Ram_dataspace_info *ds_info; auto lambda = [&] (Ram_dataspace_info *rdi) { ds_info = rdi; if (!ds_info) { error("RAM free: dataspace lookup failed"); return; } _registry.remove(ds_info); ds_info->dissolve_users(); _list.remove(ds_info); _used_ram_quota -= ds_info->size(); _ram.free(ds_cap); }; _registry.apply(ds_cap, lambda); destroy(_alloc, ds_info); } size_t dataspace_size(Ram_dataspace_capability ds_cap) const override { size_t result = 0; _registry.apply(ds_cap, [&] (Ram_dataspace_info *rdi) { if (rdi) result = rdi->size(); }); return result; } int ref_account(Ram_session_capability) { return 0; } int transfer_quota(Ram_session_capability, size_t) { return 0; } size_t quota() { return _ram.quota(); } size_t used() { return _used_ram_quota; } }; #endif /* _NOUX__RAM_SESSION_COMPONENT_H_ */