From f80c0500af1feb0e01664ca36998d811a76970fb Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Sat, 28 Sep 2013 20:12:10 +0200 Subject: [PATCH] Test for 'Parent::resource_request' interface --- base/src/base/env/platform_env.h | 7 +- os/run/resource_request.run | 40 ++++++++ os/src/test/resource_request/main.cc | 131 +++++++++++++++++++++++++ os/src/test/resource_request/target.mk | 3 + tool/autopilot.list | 1 + 5 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 os/run/resource_request.run create mode 100644 os/src/test/resource_request/main.cc create mode 100644 os/src/test/resource_request/target.mk diff --git a/base/src/base/env/platform_env.h b/base/src/base/env/platform_env.h index 5780ba0e2..6823a4144 100644 --- a/base/src/base/env/platform_env.h +++ b/base/src/base/env/platform_env.h @@ -146,7 +146,12 @@ class Genode::Platform_env : public Genode::Env, public Emergency_ram_reserve ** Emergency_ram_reserve interface ** *************************************/ - void release() { _resources.ram.free(_emergency_ram_ds); } + void release() { + + PDBG("used before freeing emergency=%zd", _resources.ram.used()); + _resources.ram.free(_emergency_ram_ds); + PDBG("used after freeing emergency=%zd", _resources.ram.used()); + } /******************* diff --git a/os/run/resource_request.run b/os/run/resource_request.run new file mode 100644 index 000000000..a900bc409 --- /dev/null +++ b/os/run/resource_request.run @@ -0,0 +1,40 @@ +build "core init test/resource_request drivers/timer" + +create_boot_directory + +install_config { + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +build_boot_image "core init timer test-resource_request" + +append qemu_args "-nographic -m 128" + +run_genode_until {child exited with exit value 0.*\n} 30 + +puts "Test succeeded" diff --git a/os/src/test/resource_request/main.cc b/os/src/test/resource_request/main.cc new file mode 100644 index 000000000..ade029d57 --- /dev/null +++ b/os/src/test/resource_request/main.cc @@ -0,0 +1,131 @@ +/* + * \brief Test for dynamic resource requests + * \author Norman Feske + * \date 2013-09-27 + * + * This test exercises various situations where a process might need to request + * additional resources from its parent. + */ + +/* + * Copyright (C) 2013 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. + */ + +#include +#include +#include + + +static Genode::size_t used_quota() +{ + return Genode::env()->ram_session()->used(); +} + + +static void print_quota_stats() +{ + PLOG("quota: avail=%zd used=%zd", + Genode::env()->ram_session()->avail(), used_quota()); +} + + +#define ASSERT(cond) \ + if (!(cond)) { \ + PERR("assertion %s failed", #cond); \ + return -2; } + + +int main(int argc, char **argv) +{ + using namespace Genode; + + printf("--- test-resource_request started ---\n"); + + /* + * Consume initial quota to let the test trigger the corner cases of + * exceeded quota. + */ + size_t const avail_quota = env()->ram_session()->avail(); + enum { KEEP_QUOTA = 64*1024 }; + size_t const wasted_quota = (avail_quota >= KEEP_QUOTA) + ? avail_quota - KEEP_QUOTA : 0; + if (wasted_quota) + env()->ram_session()->alloc(wasted_quota); + + printf("wasted available quota of %zd bytes\n", wasted_quota); + + print_quota_stats(); + + /* + * Out of memory while upgrading session quotas. + * + * This test provokes the signal session to consume more resources than + * donated via the initial session creation. Once drained, we need to + * successively upgrade the session. At one point, we will run out of our + * initial quota. Now, before we can issue another upgrade, we first need + * to request additional resources. + */ + printf("\n-- draining signal session --\n"); + { + enum { NUM_SIG_CTX = 2000U }; + static Signal_context sig_ctx[NUM_SIG_CTX]; + static Signal_receiver sig_rec; + + for (unsigned i = 0; i < NUM_SIG_CTX; i++) + sig_rec.manage(&sig_ctx[i]); + + print_quota_stats(); + + for (unsigned i = 0; i < NUM_SIG_CTX; i++) + sig_rec.dissolve(&sig_ctx[i]); + } + print_quota_stats(); + size_t const used_quota_after_draining_session = used_quota(); + + /* + * When creating a new session, we try to donate RAM quota to the server. + * Because, we don't have any RAM quota left, we need to issue another + * resource request to the parent. + */ + printf("\n-- out-of-memory during session request --\n"); + static Ram_connection ram; + ram.ref_account(env()->ram_session_cap()); + print_quota_stats(); + size_t const used_quota_after_session_request = used_quota(); + + /* + * Quota transfers from the process' RAM session may result in resource + * requests, too. + */ + printf("\n-- out-of-memory during transfer-quota --\n"); + int ret = env()->ram_session()->transfer_quota(ram.cap(), 512*1024); + if (ret != 0) { + PERR("transfer quota failed (ret = %d)", ret); + return -1; + } + print_quota_stats(); + size_t const used_quota_after_transfer = used_quota(); + + /* + * Finally, resource requests could be caused by a regular allocation, + * which is the most likely case in normal scenarios. + */ + printf("\n-- out-of-memory during RAM allocation --\n"); + env()->ram_session()->alloc(512*1024); + print_quota_stats(); + size_t used_quota_after_alloc = used_quota(); + + /* + * Validate asserted effect of the individual steps on the used quota. + */ + ASSERT(used_quota_after_session_request == used_quota_after_draining_session); + ASSERT(used_quota_after_transfer == used_quota_after_session_request); + ASSERT(used_quota_after_alloc > used_quota_after_transfer); + + printf("--- finished test-resource_request ---\n"); + + return 0; +} diff --git a/os/src/test/resource_request/target.mk b/os/src/test/resource_request/target.mk new file mode 100644 index 000000000..c87f9b573 --- /dev/null +++ b/os/src/test/resource_request/target.mk @@ -0,0 +1,3 @@ +TARGET = test-resource_request +SRC_CC = main.cc +LIBS = base diff --git a/tool/autopilot.list b/tool/autopilot.list index 77b6166f8..751db82f9 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -29,3 +29,4 @@ noux_tool_chain_auto affinity mp_server seoul-auto +resource_request