From e32b78d95d06c0d080ee20fc4877a9bc95d8e2f0 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Wed, 23 Nov 2016 20:31:35 +0100 Subject: [PATCH] os: extend ram_session_guard for platform_driver Issue #1039 --- repos/os/include/os/ram_session_guard.h | 115 +++++++++++++++++++-- repos/os/src/server/nic_bridge/component.h | 2 +- 2 files changed, 105 insertions(+), 12 deletions(-) diff --git a/repos/os/include/os/ram_session_guard.h b/repos/os/include/os/ram_session_guard.h index 97103df35..dd8f69b6a 100644 --- a/repos/os/include/os/ram_session_guard.h +++ b/repos/os/include/os/ram_session_guard.h @@ -25,35 +25,128 @@ class Genode::Ram_session_guard : public Genode::Ram_session { private: - Ram_session &_session; + Ram_session &_session; + Ram_session_capability _session_cap; + size_t _quota; - size_t _used; + size_t _used = 0; + size_t _withdraw = 0; + + /* XXX should be either a exception or a enum in rm_session */ + enum { RM_SESSION_INSUFFICIENT_QUOTA = -3 }; public: - Ram_session_guard(Ram_session &session, size_t quota) - : _session(session) { } + Ram_session_guard(Ram_session &session, Ram_session_capability cap, + size_t quota) + : _session(session), _session_cap(cap), _quota(quota) { } + + /** + * Convenient transfer_quota method throwing a exception iif the + * quota is insufficient. + */ + template + int transfer_quota(Ram_session_capability ram_session, size_t amount) + { + int const error = transfer_quota(ram_session, amount); + + if (error == RM_SESSION_INSUFFICIENT_QUOTA) + throw T(); + + return error; + } + + /** + * Extend allocation limit + */ + void upgrade(size_t additional_amount) { + _quota += additional_amount; } + + /** + * Consume bytes without actually allocating them + */ + bool withdraw(size_t size) + { + if ((_quota - _used) < size) + return false; + + _used += size; + _withdraw += size; + return true; + } + + /** + * Revert withdraw + */ + bool revert_withdraw(size_t size) + { + if (size > _withdraw) + return false; + + _used -= size; + _withdraw -= size; + + return true; + } + + /** + * Revert transfer quota + */ + int revert_transfer_quota(Ram_session &ram_session, + size_t amount) + { + if (amount > _used) + return -4; + + int error = ram_session.transfer_quota(_session_cap, amount); + if (!error) + _used -= amount; + + return error; + } + + /*************************** + ** Ram_session interface ** + ***************************/ + Ram_dataspace_capability alloc(size_t size, Cache_attribute cached = CACHED) override { - if (_used + size > _used) throw Quota_exceeded(); - _used += size; - return _session.alloc(size, cached); + if (_used + size <= _used || _used + size > _quota) + throw Quota_exceeded(); + + Ram_dataspace_capability cap = _session.alloc(size, cached); + + if (cap.valid()) + _used += size; + + return cap; } void free(Ram_dataspace_capability ds) override { size_t size = Dataspace_client(ds).size(); - _used -= size; _session.free(ds); + _used -= size; } int ref_account(Ram_session_capability ram_session) override { - return -1; } + return _session.ref_account(ram_session); } - int transfer_quota(Ram_session_capability ram_session, size_t amount) override { - return -1; } + int transfer_quota(Ram_session_capability ram_session, + size_t amount) override + { + if (_used + amount <= _used || _used + amount > _quota) + return RM_SESSION_INSUFFICIENT_QUOTA; + + int const error = _session.transfer_quota(ram_session, amount); + + if (!error) + _used += amount; + + return error; + } size_t quota() override { return _quota; } diff --git a/repos/os/src/server/nic_bridge/component.h b/repos/os/src/server/nic_bridge/component.h index 797b2c979..1cee8eb61 100644 --- a/repos/os/src/server/nic_bridge/component.h +++ b/repos/os/src/server/nic_bridge/component.h @@ -56,7 +56,7 @@ class Net::Stream_allocator Stream_allocator(Genode::Ram_session &ram, Genode::Region_map &rm, Genode::size_t amount) - : _ram(ram, amount), + : _ram(ram, Genode::Ram_session_capability(), amount), _heap(ram, rm), _range_alloc(&_heap) {}