From 2a0f940bd726d30d5d42b2ed33f9c597ecbad7eb Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Tue, 9 Jan 2018 13:54:36 +0100 Subject: [PATCH] top: adapt to ram usage of trace connection Issue #2638 --- repos/os/src/app/top/main.cc | 68 +++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/repos/os/src/app/top/main.cc b/repos/os/src/app/top/main.cc index 9c29090b2..ca74bd4e8 100644 --- a/repos/os/src/app/top/main.cc +++ b/repos/os/src/app/top/main.cc @@ -72,11 +72,34 @@ struct Trace_subject_registry /* most significant consumer per CPU */ Entry const * load[MAX_CPUS_X][MAX_CPUS_Y][MAX_ELEMENTS_PER_CPU]; + bool _reconstruct_trace_connection = false; + + unsigned update_subjects(Genode::Pd_session &pd, + Genode::Trace::Connection &trace) + { + Genode::Ram_quota ram_quota; + + do { + try { + return trace.subjects(_subjects, MAX_SUBJECTS); + } catch (Genode::Out_of_ram) { + trace.upgrade_ram(4096); + } + + ram_quota = pd.avail_ram(); + _reconstruct_trace_connection = (ram_quota.value < 4 * 4096); + + } while (ram_quota.value >= 2 * 4096); + + return 0; + } + public: - void update(Genode::Trace::Connection &trace, Genode::Allocator &alloc) + void update(Genode::Pd_session &pd, Genode::Trace::Connection &trace, + Genode::Allocator &alloc) { - unsigned const num_subjects = trace.subjects(_subjects, MAX_SUBJECTS); + unsigned const num_subjects = update_subjects(pd, trace); if (num_subjects == MAX_SUBJECTS) Genode::error("Not enough memory for all threads - " @@ -103,6 +126,20 @@ struct Trace_subject_registry Genode::destroy(alloc, e); } } + + if (_reconstruct_trace_connection) + throw Genode::Out_of_ram(); + } + + void flush(Genode::Trace::Connection &trace, Genode::Allocator &alloc) + { + _reconstruct_trace_connection = false; + + while (Entry * const e = _entries.first()) { + trace.free(e->id); + _entries.remove(e); + Genode::destroy(alloc, e); + } } void top() @@ -226,7 +263,14 @@ struct App::Main { Env &_env; - Trace::Connection _trace { _env, 512*1024, 32*1024, 0 }; + enum { + TRACE_RAM_QUOTA = 10 * 4096, + ARG_BUFFER_RAM = 32 * 1024, + PARENT_LEVELS = 0 + }; + + Reconstructible _trace { _env, TRACE_RAM_QUOTA, + ARG_BUFFER_RAM, PARENT_LEVELS }; static unsigned long _default_period_ms() { return 5000; } @@ -274,11 +318,27 @@ void App::Main::_handle_config() void App::Main::_handle_period() { + bool reconstruct = false; + /* update subject information */ - _trace_subject_registry.update(_trace, _heap); + try { + _trace_subject_registry.update(_env.pd(), *_trace, _heap); + } catch (Genode::Out_of_ram) { + reconstruct = true; + } /* show most significant consumers */ _trace_subject_registry.top(); + + /* by destructing the session we free up the allocated memory in core */ + if (reconstruct) { + Genode::warning("re-construct trace session because of out of memory"); + + _trace_subject_registry.flush(*_trace, _heap); + + _trace.destruct(); + _trace.construct(_env, TRACE_RAM_QUOTA, ARG_BUFFER_RAM, PARENT_LEVELS); + } }