From c9272937e76541a876749aca7350cacef560edee Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Fri, 27 Mar 2015 14:05:55 +0100 Subject: [PATCH] CPU session: apply quota via relative weightings Physical CPU quota was previously given to a thread on construction only by directly specifying a percentage of the quota of the according CPU session. Now, a new thread is given a weighting that can be any value. The physical counter-value of such a weighting depends on the weightings of the other threads at the CPU session. Thus, the physical quota of all threads of a CPU session must be updated when a weighting is added or removed. This is each time the session creates or destroys a thread. This commit also adapts the "cpu_quota" test in base-hw accordingly. Ref #1464 --- .../src/base/thread/thread_start.cc | 3 +- .../src/core/cpu_session_support.cc | 2 + .../src/core/include/platform_thread.h | 5 + .../src/core/cpu_session_support.cc | 2 + .../src/core/include/platform_thread.h | 5 + .../base-foc/include/foc_cpu_session/client.h | 8 +- repos/base-foc/src/base/thread/thread.cc | 8 +- .../base-foc/src/base/thread/thread_start.cc | 4 +- .../src/core/cpu_session_extension.cc | 3 + .../src/core/include/cpu_session_component.h | 36 +-- .../src/core/include/platform_thread.h | 5 + repos/base-hw/run/cpu_quota.run | 161 ------------ repos/base-hw/src/base/thread/start.cc | 5 +- repos/base-hw/src/core/cpu_session_support.cc | 8 + .../base-hw/src/core/include/kernel/thread.h | 5 + .../src/core/include/platform_thread.h | 11 +- .../src/core/include/spec/arm/cpu_support.h | 2 + .../include/spec/x86/{cpu.h => cpu_support.h} | 6 +- .../src/core/include/spec/x86_64/cpu.h | 22 ++ repos/base-hw/src/core/kernel/kernel.cc | 2 + repos/base-hw/src/core/kernel/thread.cc | 15 +- repos/base-hw/src/core/platform_thread.cc | 8 +- .../include/sync_session/capability.h | 30 +++ .../cpu_quota/include/sync_session/client.h | 43 +++ .../include/sync_session/connection.h | 59 +++++ .../include/sync_session/sync_session.h | 56 ++++ repos/base-hw/src/test/cpu_quota/main.cc | 148 +++++++++-- repos/base-hw/src/test/cpu_quota/sync/main.cc | 152 +++++++++++ .../base-hw/src/test/cpu_quota/sync/target.mk | 17 ++ repos/base-hw/src/test/cpu_quota/target.mk | 5 +- .../include/linux_cpu_session/client.h | 8 +- repos/base-linux/src/base/env/platform_env.h | 4 +- repos/base-linux/src/base/process/process.cc | 3 +- .../src/base/thread/thread_linux.cc | 4 +- .../src/core/cpu_session_support.cc | 2 + .../src/core/include/cpu_session_component.h | 36 +-- .../src/core/include/platform_thread.h | 5 + repos/base-linux/src/platform/lx_hybrid.cc | 9 +- repos/base-nova/include/cpu_session/client.h | 8 +- repos/base-nova/src/base/pager/pager.cc | 2 +- repos/base-nova/src/base/server/server.cc | 2 +- .../base-nova/src/base/thread/thread_nova.cc | 4 +- .../base-nova/src/core/cpu_session_support.cc | 2 + .../src/core/include/cpu_session_component.h | 36 +-- .../src/core/include/platform_thread.h | 5 + .../src/core/irq_session_component.cc | 6 +- .../base-okl4/src/core/cpu_session_support.cc | 2 + .../src/core/include/platform_thread.h | 5 + .../src/core/cpu_session_platform.cc | 2 + .../src/core/include/platform_thread.h | 5 + repos/base/include/base/pager.h | 8 +- repos/base/include/base/thread.h | 61 +++-- repos/base/include/cpu_session/client.h | 4 +- repos/base/include/cpu_session/cpu_session.h | 47 ++-- repos/base/src/base/process/process.cc | 3 +- repos/base/src/base/server/common.cc | 2 +- repos/base/src/base/thread/thread_start.cc | 4 +- repos/base/src/core/cpu_session_component.cc | 168 ++++++++---- .../src/core/include/cpu_session_component.h | 60 ++--- repos/base/src/core/main.cc | 5 +- repos/libports/src/lib/pthread/thread.h | 4 +- repos/os/include/init/child.h | 64 ++--- repos/os/include/os/irq_activation.h | 4 +- repos/os/run/cpu_quota.run | 244 ++++++++++++++++++ repos/ports-foc/src/lib/l4lx/include/vcpu.h | 4 +- repos/ports/include/vmm/vcpu_dispatcher.h | 4 +- repos/ports/include/vmm/vcpu_thread.h | 10 +- .../app/gdb_monitor/cpu_session_component.cc | 12 +- .../app/gdb_monitor/cpu_session_component.h | 3 +- repos/ports/src/noux/cpu_session_component.h | 15 +- tool/autopilot.list | 1 + 71 files changed, 1230 insertions(+), 483 deletions(-) delete mode 100644 repos/base-hw/run/cpu_quota.run rename repos/base-hw/src/core/include/spec/x86/{cpu.h => cpu_support.h} (98%) create mode 100644 repos/base-hw/src/core/include/spec/x86_64/cpu.h create mode 100644 repos/base-hw/src/test/cpu_quota/include/sync_session/capability.h create mode 100644 repos/base-hw/src/test/cpu_quota/include/sync_session/client.h create mode 100644 repos/base-hw/src/test/cpu_quota/include/sync_session/connection.h create mode 100644 repos/base-hw/src/test/cpu_quota/include/sync_session/sync_session.h create mode 100644 repos/base-hw/src/test/cpu_quota/sync/main.cc create mode 100644 repos/base-hw/src/test/cpu_quota/sync/target.mk create mode 100644 repos/os/run/cpu_quota.run diff --git a/repos/base-codezero/src/base/thread/thread_start.cc b/repos/base-codezero/src/base/thread/thread_start.cc index 658d901f3..571ec4a44 100644 --- a/repos/base-codezero/src/base/thread/thread_start.cc +++ b/repos/base-codezero/src/base/thread/thread_start.cc @@ -55,7 +55,8 @@ void Thread_base::start() /* create thread at core */ char buf[48]; name(buf, sizeof(buf)); - _thread_cap = _cpu_session->create_thread(0, buf); + enum { WEIGHT = Cpu_session::DEFAULT_WEIGHT }; + _thread_cap = _cpu_session->create_thread(WEIGHT, buf); /* assign thread to protection domain */ env()->pd_session()->bind_thread(_thread_cap); diff --git a/repos/base-codezero/src/core/cpu_session_support.cc b/repos/base-codezero/src/core/cpu_session_support.cc index 754544838..38bc99bd6 100644 --- a/repos/base-codezero/src/core/cpu_session_support.cc +++ b/repos/base-codezero/src/core/cpu_session_support.cc @@ -26,3 +26,5 @@ Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability thread_ca return Ram_dataspace_capability(); } + +Cpu_session::Quota Cpu_session_component::quota() { return Quota(); } diff --git a/repos/base-codezero/src/core/include/platform_thread.h b/repos/base-codezero/src/core/include/platform_thread.h index 5b2b12ddd..8651bd013 100644 --- a/repos/base-codezero/src/core/include/platform_thread.h +++ b/repos/base-codezero/src/core/include/platform_thread.h @@ -152,6 +152,11 @@ namespace Genode { ***********************/ addr_t utcb() const { return _utcb; } + + /** + * Set CPU quota of the thread to 'quota' + */ + void quota(size_t const quota) { /* not supported*/ } }; } diff --git a/repos/base-fiasco/src/core/cpu_session_support.cc b/repos/base-fiasco/src/core/cpu_session_support.cc index 754544838..38bc99bd6 100644 --- a/repos/base-fiasco/src/core/cpu_session_support.cc +++ b/repos/base-fiasco/src/core/cpu_session_support.cc @@ -26,3 +26,5 @@ Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability thread_ca return Ram_dataspace_capability(); } + +Cpu_session::Quota Cpu_session_component::quota() { return Quota(); } diff --git a/repos/base-fiasco/src/core/include/platform_thread.h b/repos/base-fiasco/src/core/include/platform_thread.h index cae41e725..8f6fb54eb 100644 --- a/repos/base-fiasco/src/core/include/platform_thread.h +++ b/repos/base-fiasco/src/core/include/platform_thread.h @@ -150,6 +150,11 @@ namespace Genode { unsigned long pager_object_badge() const { return convert_native_thread_id_to_badge(_l4_thread_id); } + /** + * Set CPU quota of the thread to 'quota' + */ + void quota(size_t const quota) { /* not supported*/ } + /******************************* ** Fiasco-specific Accessors ** diff --git a/repos/base-foc/include/foc_cpu_session/client.h b/repos/base-foc/include/foc_cpu_session/client.h index fe39bf211..ad520c19c 100644 --- a/repos/base-foc/include/foc_cpu_session/client.h +++ b/repos/base-foc/include/foc_cpu_session/client.h @@ -25,8 +25,8 @@ namespace Genode { explicit Foc_cpu_session_client(Cpu_session_capability session) : Rpc_client(static_cap_cast(session)) { } - Thread_capability create_thread(size_t, Name const &name, addr_t utcb = 0) { - return call(0, name, utcb); } + Thread_capability create_thread(size_t weight, Name const &name, addr_t utcb = 0) { + return call(weight, name, utcb); } Ram_dataspace_capability utcb(Thread_capability thread) { return call(thread); } @@ -100,9 +100,7 @@ namespace Genode { int transfer_quota(Cpu_session_capability session, size_t amount) { return call(session, amount); } - size_t quota() { return call(); } - - size_t used() { return call(); } + Quota quota() override { return call(); } }; } diff --git a/repos/base-foc/src/base/thread/thread.cc b/repos/base-foc/src/base/thread/thread.cc index 5ccf4544c..143ce477b 100644 --- a/repos/base-foc/src/base/thread/thread.cc +++ b/repos/base-foc/src/base/thread/thread.cc @@ -186,7 +186,7 @@ void Thread_base::free_secondary_stack(void* stack_addr) } -Thread_base::Thread_base(size_t, const char *name, size_t stack_size, +Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size, Type const type, Cpu_session *cpu_session) : _cpu_session(cpu_session), @@ -195,13 +195,13 @@ Thread_base::Thread_base(size_t, const char *name, size_t stack_size, _join_lock(Lock::LOCKED) { strncpy(_context->name, name, sizeof(_context->name)); - _init_platform_thread(0, type); + _init_platform_thread(weight, type); } -Thread_base::Thread_base(size_t, const char *name, size_t stack_size, +Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size, Type type) -: Thread_base(0, name, stack_size, type, nullptr) { } +: Thread_base(weight, name, stack_size, type, nullptr) { } Thread_base::~Thread_base() diff --git a/repos/base-foc/src/base/thread/thread_start.cc b/repos/base-foc/src/base/thread/thread_start.cc index 1f1e80f7d..b12aa94b8 100644 --- a/repos/base-foc/src/base/thread/thread_start.cc +++ b/repos/base-foc/src/base/thread/thread_start.cc @@ -39,7 +39,7 @@ void Thread_base::_deinit_platform_thread() } -void Thread_base::_init_platform_thread(size_t, Type type) +void Thread_base::_init_platform_thread(size_t weight, Type type) { /* if no cpu session is given, use it from the environment */ if (!_cpu_session) @@ -50,7 +50,7 @@ void Thread_base::_init_platform_thread(size_t, Type type) /* create thread at core */ char buf[48]; name(buf, sizeof(buf)); - _thread_cap = _cpu_session->create_thread(0, buf); + _thread_cap = _cpu_session->create_thread(weight, buf); /* assign thread to protection domain */ if (!_thread_cap.valid() || diff --git a/repos/base-foc/src/core/cpu_session_extension.cc b/repos/base-foc/src/core/cpu_session_extension.cc index d732882d7..779a0269d 100644 --- a/repos/base-foc/src/core/cpu_session_extension.cc +++ b/repos/base-foc/src/core/cpu_session_extension.cc @@ -107,3 +107,6 @@ void Genode::Cpu_session_component::single_step(Genode::Thread_capability thread Fiasco::l4_thread_ex_regs(tid, ~0UL, ~0UL, flags); } + + +Genode::Cpu_session::Quota Genode::Cpu_session_component::quota() { return Quota(); } diff --git a/repos/base-foc/src/core/include/cpu_session_component.h b/repos/base-foc/src/core/include/cpu_session_component.h index 3ab17ca59..2852b58ef 100644 --- a/repos/base-foc/src/core/include/cpu_session_component.h +++ b/repos/base-foc/src/core/include/cpu_session_component.h @@ -64,7 +64,9 @@ namespace Genode { public: - Cpu_thread_component(size_t, Session_label const &label, + Cpu_thread_component(size_t const weight, + size_t const quota, + Session_label const &label, Thread_name const &name, unsigned priority, addr_t utcb, Signal_context_capability sigh, @@ -88,7 +90,8 @@ namespace Genode { bool bound() const { return _bound; } void bound(bool b) { _bound = b; } Trace::Source *trace_source() { return &_trace_source; } - size_t quota() { return 0; } + + size_t weight() const { return Cpu_session::DEFAULT_WEIGHT; } void sigh(Signal_context_capability sigh) { @@ -138,24 +141,26 @@ namespace Genode { session */ Trace::Source_registry &_trace_sources; Trace::Control_area _trace_control_area; - Cpu_session_component * _ref; - size_t _used; + + size_t _weight; size_t _quota; + Cpu_session_component * _ref; List _ref_members; Lock _ref_members_lock; - size_t _global_to_local(size_t const q) const { return 0; } - size_t _avail() { return 0; } + void _incr_weight(size_t); + void _decr_weight(size_t); + size_t _weight_to_quota(size_t) const; + void _decr_quota(size_t); + void _incr_quota(size_t); + void _update_thread_quota(Cpu_thread_component *) const; + void _update_each_thread_quota(); + void _transfer_quota(Cpu_session_component *, size_t); + void _insert_ref_member(Cpu_session_component *) { } + void _unsync_remove_ref_member(Cpu_session_component *) { } + void _remove_ref_member(Cpu_session_component *) { } void _deinit_ref_account(); void _deinit_threads(); - size_t _local_to_global(size_t) const { return 0; } - void _insuff_for_consume(size_t); - int _insuff_for_transfer(size_t); - int _transfer_back(size_t) { return -1; } - int _transfer_forth(Cpu_session_component *, size_t) { return -1; } - void _insert_ref_member(Cpu_session_component *) { } - void _remove_ref_member(Cpu_session_component *) { } - void _unsync_remove_ref_member(Cpu_session_component *) { } /** * Exception handler that will be invoked unless overridden by a @@ -224,8 +229,7 @@ namespace Genode { Dataspace_capability trace_policy(Thread_capability); int ref_account(Cpu_session_capability c); int transfer_quota(Cpu_session_capability c, size_t q); - size_t used(); - size_t quota(); + Quota quota() override; /*********************************** diff --git a/repos/base-foc/src/core/include/platform_thread.h b/repos/base-foc/src/core/include/platform_thread.h index 316637ad6..1e94e559b 100644 --- a/repos/base-foc/src/core/include/platform_thread.h +++ b/repos/base-foc/src/core/include/platform_thread.h @@ -167,6 +167,11 @@ namespace Genode { unsigned long pager_object_badge() { return (unsigned long) _thread.local.dst(); } + /** + * Set CPU quota of the thread to 'quota' + */ + void quota(size_t const quota) { /* not supported*/ } + /******************************* ** Fiasco-specific Accessors ** diff --git a/repos/base-hw/run/cpu_quota.run b/repos/base-hw/run/cpu_quota.run deleted file mode 100644 index 0834edd61..000000000 --- a/repos/base-hw/run/cpu_quota.run +++ /dev/null @@ -1,161 +0,0 @@ -# -# Build -# - -build "core init drivers/timer test/cpu_quota" - -# -# Boot image -# - -create_boot_directory - -install_config { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -} - -build_boot_image "core init timer test-cpu_quota" - -# -# Execution -# - -append qemu_args "-nographic -m 64" - -run_genode_until "test.*\n.*test.*\n.*test.*\n" 60 - -# -# Conclusion -# - -set slow_opt 0.10 -set middle_opt 0.25 -set fast_opt 0.65 -set err 0.02 - -regexp {[0-9]+} [regexp -inline {slow.*[0-9]+} $output] slow_cnt -regexp {[0-9]+} [regexp -inline {middle.*[0-9]+} $output] middle_cnt -regexp {[0-9]+} [regexp -inline {fast.*[0-9]+} $output] fast_cnt -set total_cnt [expr $fast_cnt + $middle_cnt + $slow_cnt] - -set slow_fac [expr $slow_cnt / double($total_cnt) ] -set middle_fac [expr $middle_cnt / double($total_cnt) ] -set fast_fac [expr $fast_cnt / double($total_cnt) ] - -set failed 0 -if {[expr $slow_fac > $slow_opt + $err || $slow_fac < $slow_opt - $err]} { - set is_pc [expr round($slow_fac * 10000) / 100] - set opt_pc [expr round($slow_opt * 10000) / 100] - puts stderr "Error: Slow counter received $is_pc% of the CPU time." - puts stderr " Should receive $opt_pc%." - set failed 1 -} -if {[expr $middle_fac > $middle_opt + $err || $middle_fac < $middle_opt - $err]} { - set is_pc [expr round($middle_fac * 10000) / 100] - set opt_pc [expr round($middle_opt * 10000) / 100] - puts stderr "Error: Middle counter received $is_pc% of the CPU time." - puts stderr " Should receive $opt_pc%." - set failed 1 -} -if {[expr $fast_fac > $fast_opt + $err || $fast_fac < $fast_opt - $err]} { - set is_pc [expr round($fast_fac * 10000) / 100] - set opt_pc [expr round($fast_opt * 10000) / 100] - puts stderr "Error: Fast counter received $is_pc% of the CPU time." - puts stderr " Should receive $opt_pc%." - set failed 1 -} -if {$failed} { - exit -1 -} else { - puts "Test succeeded" -} diff --git a/repos/base-hw/src/base/thread/start.cc b/repos/base-hw/src/base/thread/start.cc index 03546a833..7d806da87 100644 --- a/repos/base-hw/src/base/thread/start.cc +++ b/repos/base-hw/src/base/thread/start.cc @@ -30,7 +30,7 @@ extern Native_thread_id _main_thread_id; ** Thread_base ** *****************/ -void Thread_base::_init_platform_thread(size_t quota, Type type) +void Thread_base::_init_platform_thread(size_t weight, Type type) { if (!_cpu_session) { _cpu_session = env()->cpu_session(); } if (type == NORMAL) { @@ -38,7 +38,8 @@ void Thread_base::_init_platform_thread(size_t quota, Type type) /* create server object */ char buf[48]; name(buf, sizeof(buf)); - _thread_cap = _cpu_session->create_thread(quota, buf, (addr_t)&_context->utcb); + addr_t const utcb = (addr_t)&_context->utcb; + _thread_cap = _cpu_session->create_thread(weight, buf, utcb); return; } /* if we got reinitialized we have to get rid of the old UTCB */ diff --git a/repos/base-hw/src/core/cpu_session_support.cc b/repos/base-hw/src/core/cpu_session_support.cc index 1ecca9f23..27a314bcd 100644 --- a/repos/base-hw/src/core/cpu_session_support.cc +++ b/repos/base-hw/src/core/cpu_session_support.cc @@ -16,6 +16,7 @@ /* core includes */ #include +#include using namespace Genode; @@ -30,3 +31,10 @@ Cpu_session_component::utcb(Thread_capability thread_cap) return t->platform_thread()->utcb(); } + +Cpu_session::Quota Cpu_session_component::quota() +{ + size_t const spu = Kernel::cpu_quota_ms * 1000; + size_t const u = quota_lim_downscale(_quota, spu); + return { spu, u }; +} diff --git a/repos/base-hw/src/core/include/kernel/thread.h b/repos/base-hw/src/core/include/kernel/thread.h index 707393a9c..c802bf84f 100644 --- a/repos/base-hw/src/core/include/kernel/thread.h +++ b/repos/base-hw/src/core/include/kernel/thread.h @@ -157,6 +157,11 @@ class Kernel::Thread */ int _read_reg(addr_t const id, addr_t & value) const; + /** + * Return amount of timer tics that 'quota' is worth + */ + size_t _core_to_kernel_quota(size_t const quota) const; + /** * Override a thread register * diff --git a/repos/base-hw/src/core/include/platform_thread.h b/repos/base-hw/src/core/include/platform_thread.h index bc1c2e2e2..c154c2cfc 100644 --- a/repos/base-hw/src/core/include/platform_thread.h +++ b/repos/base-hw/src/core/include/platform_thread.h @@ -75,12 +75,6 @@ namespace Genode { */ bool _attaches_utcb_by_itself(); - static size_t _generic_to_platform_quota(size_t const q) - { - assert(Kernel::cpu_quota_ms <= Cpu_session::QUOTA_LIMIT); - return (q * Kernel::cpu_quota_ms) >> 15; - } - public: /** @@ -143,6 +137,11 @@ namespace Genode { */ void cancel_blocking() { resume(); } + /** + * Set CPU quota of the thread to 'quota' + */ + void quota(size_t const quota); + /** * Get raw thread state */ diff --git a/repos/base-hw/src/core/include/spec/arm/cpu_support.h b/repos/base-hw/src/core/include/spec/arm/cpu_support.h index e414c6593..60d7b953e 100644 --- a/repos/base-hw/src/core/include/spec/arm/cpu_support.h +++ b/repos/base-hw/src/core/include/spec/arm/cpu_support.h @@ -29,6 +29,8 @@ namespace Genode * CPU driver for core */ class Arm; + + typedef Genode::uint64_t sizet_arithm_t; } class Genode::Arm diff --git a/repos/base-hw/src/core/include/spec/x86/cpu.h b/repos/base-hw/src/core/include/spec/x86/cpu_support.h similarity index 98% rename from repos/base-hw/src/core/include/spec/x86/cpu.h rename to repos/base-hw/src/core/include/spec/x86/cpu_support.h index 921502f2b..6ae0e0706 100644 --- a/repos/base-hw/src/core/include/spec/x86/cpu.h +++ b/repos/base-hw/src/core/include/spec/x86/cpu_support.h @@ -13,8 +13,8 @@ * under the terms of the GNU General Public License version 2. */ -#ifndef _CPU_H_ -#define _CPU_H_ +#ifndef _SPEC__X86__CPU_SUPPORT_H_ +#define _SPEC__X86__CPU_SUPPORT_H_ /* Genode includes */ #include @@ -445,4 +445,4 @@ class Genode::Cpu }; -#endif /* _CPU_H_ */ +#endif /* _SPEC__X86__CPU_SUPPORT_H_ */ diff --git a/repos/base-hw/src/core/include/spec/x86_64/cpu.h b/repos/base-hw/src/core/include/spec/x86_64/cpu.h new file mode 100644 index 000000000..3a43e074c --- /dev/null +++ b/repos/base-hw/src/core/include/spec/x86_64/cpu.h @@ -0,0 +1,22 @@ +/* + * \brief CPU driver for core + * \author Martin stein + * \date 2015-04-20 + */ + +/* + * Copyright (C) 2015 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. + */ + +#ifndef _CPU_H_ +#define _CPU_H_ + +/* core includes */ +#include + +namespace Genode { typedef __uint128_t sizet_arithm_t; } + +#endif /* _CPU_H_ */ diff --git a/repos/base-hw/src/core/kernel/kernel.cc b/repos/base-hw/src/core/kernel/kernel.cc index 05338f4b6..71e381e9c 100644 --- a/repos/base-hw/src/core/kernel/kernel.cc +++ b/repos/base-hw/src/core/kernel/kernel.cc @@ -46,6 +46,8 @@ extern void * _start_secondary_cpus; extern int _prog_img_beg; extern int _prog_img_end; +static_assert(sizeof(Genode::sizet_arithm_t) >= 2 * sizeof(size_t), + "Bad result type for size_t arithmetics."); namespace Kernel { diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc index 1bbe6f4de..5ef9e6e96 100644 --- a/repos/base-hw/src/core/kernel/thread.cc +++ b/repos/base-hw/src/core/kernel/thread.cc @@ -15,6 +15,7 @@ /* Genode includes */ #include #include +#include /* core includes */ #include @@ -224,12 +225,21 @@ void Thread::_call_new_pd() void Thread::_call_delete_pd() { reinterpret_cast(user_arg_1())->~Pd(); } +size_t Thread::_core_to_kernel_quota(size_t const quota) const +{ + using Genode::Cpu_session; + using Genode::sizet_arithm_t; + size_t const tics = cpu_pool()->timer()->ms_to_tics(Kernel::cpu_quota_ms); + return Cpu_session::quota_lim_downscale(quota, tics); +} + + void Thread::_call_new_thread() { /* create new thread */ void * const p = (void *)user_arg_1(); unsigned const priority = user_arg_2(); - unsigned const quota = cpu_pool()->timer()->ms_to_tics(user_arg_3()); + unsigned const quota = _core_to_kernel_quota(user_arg_3()); char const * const label = (char *)user_arg_4(); Thread * const t = new (p) Thread(priority, quota, label); user_arg_0(t->id()); @@ -239,8 +249,7 @@ void Thread::_call_new_thread() void Thread::_call_thread_quota() { Thread * const thread = (Thread *)user_arg_1(); - unsigned const quota = cpu_pool()->timer()->ms_to_tics(user_arg_2()); - thread->Cpu_job::quota(quota); + thread->Cpu_job::quota(_core_to_kernel_quota(user_arg_2())); } diff --git a/repos/base-hw/src/core/platform_thread.cc b/repos/base-hw/src/core/platform_thread.cc index c1d95dab1..f219f13ee 100644 --- a/repos/base-hw/src/core/platform_thread.cc +++ b/repos/base-hw/src/core/platform_thread.cc @@ -78,6 +78,10 @@ Platform_thread::~Platform_thread() } +void Platform_thread::quota(size_t const quota) { + Kernel::thread_quota((Kernel::Thread *)_kernel_thread, quota); } + + Platform_thread::Platform_thread(const char * const label, Native_utcb * utcb) : _pd(Kernel::core_pd()->platform_pd()), @@ -110,7 +114,8 @@ Platform_thread::Platform_thread(const char * const label, } -Platform_thread::Platform_thread(size_t quota, const char * const label, +Platform_thread::Platform_thread(size_t const quota, + const char * const label, unsigned const virt_prio, addr_t const utcb) : @@ -139,7 +144,6 @@ Platform_thread::Platform_thread(size_t quota, const char * const label, /* create kernel object */ constexpr unsigned max_prio = Kernel::Cpu_priority::max; auto const phys_prio = Cpu_session::scale_priority(max_prio, virt_prio); - quota = _generic_to_platform_quota(quota); _id = Kernel::new_thread(_kernel_thread, phys_prio, quota, _label); if (!_id) { PERR("failed to create kernel object"); diff --git a/repos/base-hw/src/test/cpu_quota/include/sync_session/capability.h b/repos/base-hw/src/test/cpu_quota/include/sync_session/capability.h new file mode 100644 index 000000000..15bc26766 --- /dev/null +++ b/repos/base-hw/src/test/cpu_quota/include/sync_session/capability.h @@ -0,0 +1,30 @@ +/* + * \brief Sync-session capability type + * \author Martin Stein + * \date 2015-04-07 + */ + +/* + * Copyright (C) 2015 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. + */ + +#ifndef _SYNC_SESSION__CAPABILITY_H_ +#define _SYNC_SESSION__CAPABILITY_H_ + +/* Genode includes */ +#include + +/* local includes */ +#include + +namespace Sync +{ + using Genode::Capability; + + typedef Capability Session_capability; +} + +#endif /* _SYNC_SESSION__CAPABILITY_H_ */ diff --git a/repos/base-hw/src/test/cpu_quota/include/sync_session/client.h b/repos/base-hw/src/test/cpu_quota/include/sync_session/client.h new file mode 100644 index 000000000..17a6854e4 --- /dev/null +++ b/repos/base-hw/src/test/cpu_quota/include/sync_session/client.h @@ -0,0 +1,43 @@ +/* + * \brief Client-side Sync-session interface + * \author Martin Stein + * \date 2015-04-07 + */ + +/* + * Copyright (C) 2015 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. + */ + +#ifndef _SYNC_SESSION__CLIENT_H_ +#define _SYNC_SESSION__CLIENT_H_ + +/* Genode includes */ +#include + +/* local includes */ +#include + +namespace Sync +{ + using Genode::Rpc_client; + + struct Session_client; +} + + +struct Sync::Session_client : Rpc_client +{ + explicit Session_client(Session_capability session) + : Rpc_client(session) { } + + void threshold(unsigned id, unsigned threshold) override { + call(id, threshold); } + + void submit(unsigned id, Signal_context_capability sigc) override { + call(id, sigc); } +}; + +#endif /* _SYNC_SESSION__CLIENT_H_ */ diff --git a/repos/base-hw/src/test/cpu_quota/include/sync_session/connection.h b/repos/base-hw/src/test/cpu_quota/include/sync_session/connection.h new file mode 100644 index 000000000..1e65df437 --- /dev/null +++ b/repos/base-hw/src/test/cpu_quota/include/sync_session/connection.h @@ -0,0 +1,59 @@ +/* + * \brief Connection to Sync service + * \author Martin Stein + * \date 2015-04-07 + */ + +/* + * Copyright (C) 2015 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. + */ + +#ifndef _SYNC_SESSION__CONNECTION_H_ +#define _SYNC_SESSION__CONNECTION_H_ + +/* Genode includes */ +#include + +/* local includes */ +#include + +namespace Sync +{ + using Genode::Parent; + + class Connection; +} + + +class Sync::Connection : public Genode::Connection, + public Session_client +{ + public: + + class Connection_failed : public Parent::Exception { }; + + private: + + Session_capability _create_session() + { + try { return session("ram_quota=4K"); } + catch (...) { throw Connection_failed(); } + } + + public: + + /** + * Constructor + * + * \throw Connection_failed + */ + Connection() : + Genode::Connection(_create_session()), + Session_client(cap()) + { } +}; + +#endif /* _SYNC_SESSION__CONNECTION_H_ */ diff --git a/repos/base-hw/src/test/cpu_quota/include/sync_session/sync_session.h b/repos/base-hw/src/test/cpu_quota/include/sync_session/sync_session.h new file mode 100644 index 000000000..740075774 --- /dev/null +++ b/repos/base-hw/src/test/cpu_quota/include/sync_session/sync_session.h @@ -0,0 +1,56 @@ +/* + * \brief Sync session interface + * \author Martin Stein + * \date 2015-04-07 + */ + +/* + * Copyright (C) 2015 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. + */ + +#ifndef _SYNC_SESSION__SYNC_SESSION_H_ +#define _SYNC_SESSION__SYNC_SESSION_H_ + +/* Genode includes */ +#include +#include + +namespace Sync +{ + using Genode::Signal_context_capability; + + struct Session; +} + + +struct Sync::Session : Genode::Session +{ + static const char *service_name() { return "Sync"; } + + virtual ~Session() { } + + /** + * Set the submission threshold of a synchronization signal + */ + virtual void threshold(unsigned id, unsigned threshold) = 0; + + /** + * Submit to a synchronization signal + */ + virtual void submit(unsigned id, Signal_context_capability sigc) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_threshold, void, threshold, unsigned, unsigned); + GENODE_RPC(Rpc_submit, void, submit, unsigned, Signal_context_capability); + + GENODE_RPC_INTERFACE(Rpc_threshold, Rpc_submit); +}; + +#endif /* _SYNC_SESSION__SYNC_SESSION_H_ */ diff --git a/repos/base-hw/src/test/cpu_quota/main.cc b/repos/base-hw/src/test/cpu_quota/main.cc index 4dca62db2..4eb0598c4 100644 --- a/repos/base-hw/src/test/cpu_quota/main.cc +++ b/repos/base-hw/src/test/cpu_quota/main.cc @@ -1,5 +1,5 @@ /* - * \brief Diversified test of the Register and MMIO framework + * \brief Test the distribution and application of CPU quota * \author Martin Stein * \date 2012-01-09 */ @@ -14,50 +14,150 @@ /* Genode includes */ #include #include -#include #include #include +#include using namespace Genode; -class My_thread : public Thread<8 * 1024> +enum { SYNC_SIG = 0 }; + +namespace Sync { class Signal; } + +class Single_signal { private: - Signal_receiver * const _sigr; - bool volatile _stop; + Signal_receiver _sigr; + Signal_context _sigx; + Signal_context_capability _sigc; + Signal_transmitter _sigt; public: - My_thread(Signal_receiver * const sigr) - : Thread(Cpu_session::pc_to_quota(100), "counter"), - _sigr(sigr), _stop(0) { } + Single_signal() : _sigc(_sigr.manage(&_sigx)), _sigt(_sigc) { } + + ~Single_signal() { _sigr.dissolve(&_sigx); } + + void receive() { _sigr.wait_for_signal(); } + + void submit() { _sigt.submit(); } +}; + +class Sync::Signal +{ + private: + + Signal_receiver _sigr; + Signal_context _sigx; + Signal_context_capability _sigc; + Session * const _session; + unsigned const _id; + + public: + + Signal(Session * const session, unsigned const id) + : _sigc(_sigr.manage(&_sigx)), _session(session), _id(id) { } + + ~Signal() { _sigr.dissolve(&_sigx); } + + void threshold(unsigned const threshold) { + _session->threshold(_id, threshold); } + + void sync() + { + _session->submit(_id, _sigc); + _sigr.wait_for_signal(); + } +}; + +class Counter : private Thread<8 * 1024> +{ + private: + + char const _name; + unsigned volatile _value; + Sync::Signal _sync_sig; + unsigned volatile _stage; + Single_signal _stage_1_end; + Single_signal _stage_2_reached; + + inline void _stage_0_and_1(unsigned volatile & value) + { + _stage_1_end.receive(); + _stage = 0; + _sync_sig.sync(); + while(_stage == 0) { value++; } + } void entry() { - _sigr->wait_for_signal(); - unsigned volatile i = 0; - while(!_stop) { i++; } - printf("%u\n", i); + unsigned volatile value = 0; + while (_stage < 2) { _stage_0_and_1(value); } + _value = value; + _stage_2_reached.submit(); sleep_forever(); } - void stop() { _stop = 1; } + public: + + Counter(char const name, size_t const weight, + Sync::Session * const sync) + : + Thread(weight, "counter"), _name(name), _value(0) , + _sync_sig(sync, SYNC_SIG), _stage(1) + { + Thread::start(); + } + + void destruct() + { + _stage = 2; + _stage_2_reached.receive(); + this->~Counter(); + } + + void pause() { _stage = 1; } + + void go() { _stage_1_end.submit(); } + + void result() { printf("counter %c %u\n", _name, _value); } }; + int main() { + /* prepare */ Timer::Connection timer; - Signal_receiver sigr; - Signal_context sigx; - Signal_context_capability sigc = sigr.manage(&sigx); - Signal_transmitter sigt(sigc); - My_thread thread(&sigr); - thread.start(); - timer.msleep(3000); - sigt.submit(); - timer.msleep(30000); - thread.stop(); + Sync::Connection sync; + Sync::Signal sync_sig(&sync, SYNC_SIG); + Counter counter_a('A', Cpu_session::quota_lim_upscale(10, 100), &sync); + Counter counter_b('B', Cpu_session::quota_lim_upscale(90, 100), &sync); + + /* measure stage 1 */ + sync_sig.threshold(9); + counter_a.go(); + counter_b.go(); + sync_sig.sync(); + timer.msleep(45000); + counter_a.pause(); + counter_b.destruct(); + + /* measure stage 2 */ + sync_sig.threshold(6); + counter_a.go(); + sync_sig.sync(); + timer.msleep(15000); + counter_a.destruct(); + + /* print results */ + sync_sig.threshold(3); + sync_sig.sync(); + Cpu_session::Quota quota = Genode::env()->cpu_session()->quota(); + Genode::printf("quota super period %zu\n", quota.super_period_us); + Genode::printf("quota %zu\n", quota.us); + counter_a.result(); + counter_b.result(); + printf("done\n"); sleep_forever(); } - diff --git a/repos/base-hw/src/test/cpu_quota/sync/main.cc b/repos/base-hw/src/test/cpu_quota/sync/main.cc new file mode 100644 index 000000000..911d3b4a3 --- /dev/null +++ b/repos/base-hw/src/test/cpu_quota/sync/main.cc @@ -0,0 +1,152 @@ +/* + * \brief Provide sync signals for cross-component synchronization + * \author Martin Stein + * \date 2015-04-07 + */ + +/* + * Copyright (C) 2015 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. + */ + +/* Genode includes */ +#include +#include + +/* local includes */ +#include + +namespace Sync +{ + enum { NR_OF_SIGNALS = 1 }; + + using Server::Entrypoint; + using Genode::Rpc_object; + using Genode::env; + using Genode::Root_component; + using Genode::Allocator; + using Genode::Signal_transmitter; + + class Signal; + class Session_component; + class Root; + struct Main; +} + +class Sync::Signal +{ + friend class Root; + + private: + + enum { NR_OF_TRANSMITTERS = 9 }; + + Signal_transmitter _transmitters[NR_OF_TRANSMITTERS]; + unsigned _submitted; + unsigned _threshold; + + void _check() + { + if (_submitted < _threshold) { return; } + for (unsigned i = 0; i < _submitted; i++) { + _transmitters[i].submit(); } + _submitted = 0; + } + + void _reset() + { + _submitted = 0; + _threshold = 0; + } + + public: + + void threshold(unsigned const threshold) + { + _threshold = threshold; + _check(); + } + + void submit(Signal_context_capability & sigc) + { + _transmitters[_submitted] = Signal_transmitter(sigc); + _submitted++; + _check(); + } +}; + +class Sync::Session_component : public Rpc_object +{ + private: + + Signal * const _signals; + + public: + + Session_component(Signal * const signals) : _signals(signals) { } + + void threshold(unsigned id, unsigned threshold) override + { + if (id >= NR_OF_SIGNALS) { return; } + _signals[id].threshold(threshold); + } + + void + submit(unsigned const id, Signal_context_capability sigc) override + { + if (id >= NR_OF_SIGNALS) { return; } + _signals[id].submit(sigc); + } +}; + +class Sync::Root : public Root_component +{ + private: + + Signal _signals[NR_OF_SIGNALS]; + + protected: + + Session_component *_create_session(const char *args) + { + try { return new (md_alloc()) Session_component(_signals); } + catch (...) { throw Root::Exception(); } + } + + public: + + Root(Entrypoint & ep, Allocator & md_alloc) + : Root_component(&ep.rpc_ep(), &md_alloc) + { + for (unsigned i = 0; i < NR_OF_SIGNALS; i++) { + _signals[i]._reset(); } + } +}; + +struct Sync::Main +{ + Server::Entrypoint & ep; + + Root root; + + Main(Server::Entrypoint & ep) : ep(ep), root(ep, *env()->heap()) { + env()->parent()->announce(ep.manage(root)); } +}; + + +/************ + ** Server ** + ************/ + +namespace Server +{ + using namespace Sync; + + char const *name() { return "sync_ep"; } + + size_t stack_size() { return 2 * 1024 * sizeof(long); } + + void construct(Entrypoint & ep) { static Main main(ep); } +} diff --git a/repos/base-hw/src/test/cpu_quota/sync/target.mk b/repos/base-hw/src/test/cpu_quota/sync/target.mk new file mode 100644 index 000000000..eba2684db --- /dev/null +++ b/repos/base-hw/src/test/cpu_quota/sync/target.mk @@ -0,0 +1,17 @@ +# +# \brief Provide cross-component synchronization +# \author Martin Stein +# \date 2014-10-13 +# + +# Set program name +TARGET = test-sync + +# Add C++ sources +SRC_CC = main.cc + +# Add include paths +INC_DIR += $(PRG_DIR)/../include + +# Add libraries +LIBS = base server diff --git a/repos/base-hw/src/test/cpu_quota/target.mk b/repos/base-hw/src/test/cpu_quota/target.mk index f0d82308d..2033599ff 100644 --- a/repos/base-hw/src/test/cpu_quota/target.mk +++ b/repos/base-hw/src/test/cpu_quota/target.mk @@ -1,5 +1,5 @@ # -# \brief Test static configuration of CPU-time distribution +# \brief Test the distribution and application of CPU quota # \author Martin Stein # \date 2014-10-13 # @@ -10,5 +10,8 @@ TARGET = test-cpu_quota # Add C++ sources SRC_CC += main.cc +# Add include paths +INC_DIR += $(PRG_DIR)/include + # Add libraries LIBS += base diff --git a/repos/base-linux/include/linux_cpu_session/client.h b/repos/base-linux/include/linux_cpu_session/client.h index a957e3893..df153cd83 100644 --- a/repos/base-linux/include/linux_cpu_session/client.h +++ b/repos/base-linux/include/linux_cpu_session/client.h @@ -24,8 +24,8 @@ namespace Genode { explicit Linux_cpu_session_client(Capability session) : Rpc_client(session) { } - Thread_capability create_thread(size_t, Name const &name, addr_t utcb = 0) { - return call(0, name, utcb); } + Thread_capability create_thread(size_t weight, Name const &name, addr_t utcb = 0) { + return call(weight, name, utcb); } Ram_dataspace_capability utcb(Thread_capability thread) { return call(thread); } @@ -84,9 +84,7 @@ namespace Genode { int transfer_quota(Cpu_session_capability session, size_t amount) { return call(session, amount); } - size_t quota() { return call(); } - - size_t used() { return call(); } + Quota quota() override { return call(); } /***************************** * Linux-specific extension ** diff --git a/repos/base-linux/src/base/env/platform_env.h b/repos/base-linux/src/base/env/platform_env.h index 1e618d1bf..b0d615bcf 100644 --- a/repos/base-linux/src/base/env/platform_env.h +++ b/repos/base-linux/src/base/env/platform_env.h @@ -44,10 +44,10 @@ struct Genode::Expanding_cpu_session_client Expanding_cpu_session_client(Genode::Capability cap) : Upgradeable_client(cap) { } - Thread_capability create_thread(size_t, Name const &name, addr_t utcb) + Thread_capability create_thread(size_t weight, Name const &name, addr_t utcb) { return retry( - [&] () { return Linux_cpu_session_client::create_thread(0, name, utcb); }, + [&] () { return Linux_cpu_session_client::create_thread(weight, name, utcb); }, [&] () { upgrade_ram(8*1024); }); } }; diff --git a/repos/base-linux/src/base/process/process.cc b/repos/base-linux/src/base/process/process.cc index 0bc54601a..476446622 100644 --- a/repos/base-linux/src/base/process/process.cc +++ b/repos/base-linux/src/base/process/process.cc @@ -80,7 +80,8 @@ Process::Process(Dataspace_capability elf_data_ds_cap, * thread. Those information will be provided to core by the constructor of * the 'Platform_env' of the new process. */ - _thread0_cap = _cpu_session_client.create_thread(0, name); + enum { WEIGHT = Cpu_session::DEFAULT_WEIGHT }; + _thread0_cap = _cpu_session_client.create_thread(WEIGHT, name); Linux_pd_session_client lx_pd(static_cap_cast(_pd.cap())); diff --git a/repos/base-linux/src/base/thread/thread_linux.cc b/repos/base-linux/src/base/thread/thread_linux.cc index d1d3fd535..2ff5243d8 100644 --- a/repos/base-linux/src/base/thread/thread_linux.cc +++ b/repos/base-linux/src/base/thread/thread_linux.cc @@ -69,7 +69,7 @@ void Thread_base::_thread_start() } -void Thread_base::_init_platform_thread(size_t, Type type) +void Thread_base::_init_platform_thread(size_t weight, Type type) { /* if no cpu session is given, use it from the environment */ if (!_cpu_session) @@ -77,7 +77,7 @@ void Thread_base::_init_platform_thread(size_t, Type type) /* for normal threads create an object at the CPU session */ if (type == NORMAL) { - _thread_cap = _cpu_session->create_thread(0, _context->name); + _thread_cap = _cpu_session->create_thread(weight, _context->name); return; } /* adjust initial object state for main threads */ diff --git a/repos/base-linux/src/core/cpu_session_support.cc b/repos/base-linux/src/core/cpu_session_support.cc index 754544838..38bc99bd6 100644 --- a/repos/base-linux/src/core/cpu_session_support.cc +++ b/repos/base-linux/src/core/cpu_session_support.cc @@ -26,3 +26,5 @@ Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability thread_ca return Ram_dataspace_capability(); } + +Cpu_session::Quota Cpu_session_component::quota() { return Quota(); } diff --git a/repos/base-linux/src/core/include/cpu_session_component.h b/repos/base-linux/src/core/include/cpu_session_component.h index 51206d30c..266c788e5 100644 --- a/repos/base-linux/src/core/include/cpu_session_component.h +++ b/repos/base-linux/src/core/include/cpu_session_component.h @@ -63,7 +63,9 @@ namespace Genode { public: - Cpu_thread_component(size_t, Session_label const &label, + Cpu_thread_component(size_t const weight, + size_t const quota, + Session_label const &label, Thread_name const &name, unsigned priority, addr_t utcb, Signal_context_capability sigh, @@ -87,7 +89,8 @@ namespace Genode { bool bound() const { return _bound; } void bound(bool b) { _bound = b; } Trace::Source *trace_source() { return &_trace_source; } - size_t quota() { return 0; } + + size_t weight() const { return Cpu_session::DEFAULT_WEIGHT; } void sigh(Signal_context_capability sigh) { @@ -131,24 +134,26 @@ namespace Genode { session */ Trace::Source_registry &_trace_sources; Trace::Control_area _trace_control_area; - Cpu_session_component * _ref; - size_t _used; + + size_t _weight; size_t _quota; + Cpu_session_component * _ref; List _ref_members; Lock _ref_members_lock; - size_t _global_to_local(size_t const q) const { return 0; } - size_t _avail() { return 0; } + void _incr_weight(size_t); + void _decr_weight(size_t); + size_t _weight_to_quota(size_t) const; + void _decr_quota(size_t); + void _incr_quota(size_t); + void _update_thread_quota(Cpu_thread_component *) const; + void _update_each_thread_quota(); + void _transfer_quota(Cpu_session_component *, size_t); + void _insert_ref_member(Cpu_session_component *) { } + void _unsync_remove_ref_member(Cpu_session_component *) { } + void _remove_ref_member(Cpu_session_component *) { } void _deinit_ref_account(); void _deinit_threads(); - size_t _local_to_global(size_t) const { return 0; } - void _insuff_for_consume(size_t); - int _insuff_for_transfer(size_t); - int _transfer_back(size_t) { return -1; } - int _transfer_forth(Cpu_session_component *, size_t) { return -1; } - void _insert_ref_member(Cpu_session_component *) { } - void _remove_ref_member(Cpu_session_component *) { } - void _unsync_remove_ref_member(Cpu_session_component *) { } /** * Exception handler that will be invoked unless overridden by a @@ -214,8 +219,7 @@ namespace Genode { Dataspace_capability trace_policy(Thread_capability); int ref_account(Cpu_session_capability c); int transfer_quota(Cpu_session_capability c, size_t q); - size_t used(); - size_t quota(); + Quota quota() override; /******************************* diff --git a/repos/base-linux/src/core/include/platform_thread.h b/repos/base-linux/src/core/include/platform_thread.h index af93f4255..71257d964 100644 --- a/repos/base-linux/src/core/include/platform_thread.h +++ b/repos/base-linux/src/core/include/platform_thread.h @@ -153,6 +153,11 @@ namespace Genode { { _registry()->submit_exception(pid); } + + /** + * Set CPU quota of the thread to 'quota' + */ + void quota(size_t const quota) { /* not supported*/ } }; } diff --git a/repos/base-linux/src/platform/lx_hybrid.cc b/repos/base-linux/src/platform/lx_hybrid.cc index b13a24b40..ba8241ded 100644 --- a/repos/base-linux/src/platform/lx_hybrid.cc +++ b/repos/base-linux/src/platform/lx_hybrid.cc @@ -401,7 +401,7 @@ void Thread_base::join() } -Thread_base::Thread_base(size_t, const char *name, size_t stack_size, +Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size, Type type, Cpu_session * cpu_sess) : _cpu_session(cpu_sess) { @@ -420,13 +420,14 @@ Thread_base::Thread_base(size_t, const char *name, size_t stack_size, Linux_cpu_session *cpu = cpu_session(_cpu_session); - _thread_cap = cpu->create_thread(0, name); + _thread_cap = cpu->create_thread(weight, name); cpu->thread_id(_thread_cap, _tid.pid, _tid.tid); } -Thread_base::Thread_base(size_t, const char *name, size_t stack_size, Type type) -: Thread_base(0, name, stack_size, type, env()->cpu_session()) { } +Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size, + Type type) +: Thread_base(weight, name, stack_size, type, env()->cpu_session()) { } void Thread_base::cancel_blocking() { diff --git a/repos/base-nova/include/cpu_session/client.h b/repos/base-nova/include/cpu_session/client.h index 77c819b97..64fae6202 100644 --- a/repos/base-nova/include/cpu_session/client.h +++ b/repos/base-nova/include/cpu_session/client.h @@ -28,8 +28,8 @@ namespace Genode { explicit Cpu_session_client(Cpu_session_capability session) : Rpc_client(static_cap_cast(session)) { } - Thread_capability create_thread(size_t, Name const &name, addr_t utcb = 0) { - return call(0, name, utcb); } + Thread_capability create_thread(size_t weight, Name const &name, addr_t utcb = 0) { + return call(weight, name, utcb); } Ram_dataspace_capability utcb(Thread_capability thread) { return call(thread); } @@ -100,9 +100,7 @@ namespace Genode { int transfer_quota(Cpu_session_capability session, size_t amount) { return call(session, amount); } - size_t quota() { return call(); } - - size_t used() { return call(); } + Quota quota() override { return call(); } private: diff --git a/repos/base-nova/src/base/pager/pager.cc b/repos/base-nova/src/base/pager/pager.cc index e8682dde1..298742800 100644 --- a/repos/base-nova/src/base/pager/pager.cc +++ b/repos/base-nova/src/base/pager/pager.cc @@ -599,7 +599,7 @@ Pager_object::~Pager_object() Pager_activation_base::Pager_activation_base(const char *name, size_t stack_size) : - Thread_base(0, name, stack_size), + Thread_base(Cpu_session::DEFAULT_WEIGHT, name, stack_size), _cap(Native_capability()), _ep(0), _cap_valid(Lock::LOCKED) { /* tell thread starting code on which CPU to let run the pager */ diff --git a/repos/base-nova/src/base/server/server.cc b/repos/base-nova/src/base/server/server.cc index b2045663e..9febb5cda 100644 --- a/repos/base-nova/src/base/server/server.cc +++ b/repos/base-nova/src/base/server/server.cc @@ -221,7 +221,7 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, const char *name, bool start_on_construction, Affinity::Location location) : - Thread_base(0, name, stack_size), + Thread_base(Cpu_session::DEFAULT_WEIGHT, name, stack_size), _curr_obj(start_on_construction ? 0 : (Rpc_object_base *)~0UL), _delay_start(Lock::LOCKED), _cap_session(cap_session) diff --git a/repos/base-nova/src/base/thread/thread_nova.cc b/repos/base-nova/src/base/thread/thread_nova.cc index d25479fd9..689654606 100644 --- a/repos/base-nova/src/base/thread/thread_nova.cc +++ b/repos/base-nova/src/base/thread/thread_nova.cc @@ -65,7 +65,7 @@ void Thread_base::_thread_start() ** Thread base ** *****************/ -void Thread_base::_init_platform_thread(size_t, Type type) +void Thread_base::_init_platform_thread(size_t weight, Type type) { using namespace Nova; @@ -101,7 +101,7 @@ void Thread_base::_init_platform_thread(size_t, Type type) char buf[48]; name(buf, sizeof(buf)); - _thread_cap = _cpu_session->create_thread(0, buf); + _thread_cap = _cpu_session->create_thread(weight, buf); if (!_thread_cap.valid()) throw Cpu_session::Thread_creation_failed(); diff --git a/repos/base-nova/src/core/cpu_session_support.cc b/repos/base-nova/src/core/cpu_session_support.cc index d55cadade..43809899b 100644 --- a/repos/base-nova/src/core/cpu_session_support.cc +++ b/repos/base-nova/src/core/cpu_session_support.cc @@ -26,3 +26,5 @@ Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability thread_ca return Ram_dataspace_capability(); } + +Cpu_session::Quota Cpu_session_component::quota() { return Quota(); } diff --git a/repos/base-nova/src/core/include/cpu_session_component.h b/repos/base-nova/src/core/include/cpu_session_component.h index c11c42dfd..df888df19 100644 --- a/repos/base-nova/src/core/include/cpu_session_component.h +++ b/repos/base-nova/src/core/include/cpu_session_component.h @@ -64,7 +64,9 @@ namespace Genode { public: - Cpu_thread_component(size_t, Session_label const &label, + Cpu_thread_component(size_t const weight, + size_t const quota, + Session_label const &label, Thread_name const &name, unsigned priority, addr_t utcb, Signal_context_capability sigh, @@ -88,7 +90,8 @@ namespace Genode { bool bound() const { return _bound; } void bound(bool b) { _bound = b; } Trace::Source *trace_source() { return &_trace_source; } - size_t quota() { return 0; } + + size_t weight() const { return Cpu_session::DEFAULT_WEIGHT; } void sigh(Signal_context_capability sigh) { @@ -138,24 +141,26 @@ namespace Genode { session */ Trace::Source_registry &_trace_sources; Trace::Control_area _trace_control_area; - Cpu_session_component * _ref; - size_t _used; + + size_t _weight; size_t _quota; + Cpu_session_component * _ref; List _ref_members; Lock _ref_members_lock; - size_t _global_to_local(size_t const q) const { return 0; } - size_t _avail() { return 0; } + void _incr_weight(size_t); + void _decr_weight(size_t); + size_t _weight_to_quota(size_t) const; + void _decr_quota(size_t); + void _incr_quota(size_t); + void _update_thread_quota(Cpu_thread_component *) const; + void _update_each_thread_quota(); + void _transfer_quota(Cpu_session_component *, size_t); + void _insert_ref_member(Cpu_session_component *) { } + void _unsync_remove_ref_member(Cpu_session_component *) { } + void _remove_ref_member(Cpu_session_component *) { } void _deinit_ref_account(); void _deinit_threads(); - size_t _local_to_global(size_t) const { return 0; } - void _insuff_for_consume(size_t); - int _insuff_for_transfer(size_t); - int _transfer_back(size_t) { return -1; } - int _transfer_forth(Cpu_session_component *, size_t) { return -1; } - void _insert_ref_member(Cpu_session_component *) { } - void _remove_ref_member(Cpu_session_component *) { } - void _unsync_remove_ref_member(Cpu_session_component *) { } /** * Exception handler that will be invoked unless overridden by a @@ -222,8 +227,7 @@ namespace Genode { Dataspace_capability trace_policy(Thread_capability); int ref_account(Cpu_session_capability c); int transfer_quota(Cpu_session_capability c, size_t q); - size_t used(); - size_t quota(); + Quota quota() override; /****************************** diff --git a/repos/base-nova/src/core/include/platform_thread.h b/repos/base-nova/src/core/include/platform_thread.h index a79eb9623..9bf58d9ae 100644 --- a/repos/base-nova/src/core/include/platform_thread.h +++ b/repos/base-nova/src/core/include/platform_thread.h @@ -164,6 +164,11 @@ namespace Genode { } Native_capability single_step(bool on); + + /** + * Set CPU quota of the thread to 'quota' + */ + void quota(size_t const quota) { /* not supported*/ } }; } diff --git a/repos/base-nova/src/core/irq_session_component.cc b/repos/base-nova/src/core/irq_session_component.cc index 9c1e89e41..3e1615e69 100644 --- a/repos/base-nova/src/core/irq_session_component.cc +++ b/repos/base-nova/src/core/irq_session_component.cc @@ -41,6 +41,9 @@ class Irq_thread : public Thread_base { private: + enum { STACK_SIZE = 1024 * sizeof(addr_t) }; + enum { WEIGHT = Cpu_session::DEFAULT_WEIGHT }; + static void _thread_start() { Thread_base::myself()->entry(); @@ -49,7 +52,8 @@ class Irq_thread : public Thread_base public: - Irq_thread(char const *name) : Thread_base(0, name, 1024 * sizeof(addr_t)) { } + Irq_thread(char const *name) : Thread_base(WEIGHT, name, STACK_SIZE) + { } /** * Create global EC, associate it to SC diff --git a/repos/base-okl4/src/core/cpu_session_support.cc b/repos/base-okl4/src/core/cpu_session_support.cc index 754544838..38bc99bd6 100644 --- a/repos/base-okl4/src/core/cpu_session_support.cc +++ b/repos/base-okl4/src/core/cpu_session_support.cc @@ -26,3 +26,5 @@ Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability thread_ca return Ram_dataspace_capability(); } + +Cpu_session::Quota Cpu_session_component::quota() { return Quota(); } diff --git a/repos/base-okl4/src/core/include/platform_thread.h b/repos/base-okl4/src/core/include/platform_thread.h index 066d6114f..ff386d734 100644 --- a/repos/base-okl4/src/core/include/platform_thread.h +++ b/repos/base-okl4/src/core/include/platform_thread.h @@ -147,6 +147,11 @@ namespace Genode { */ Affinity::Location affinity() { return Affinity::Location(); } + /** + * Set CPU quota of the thread + */ + void quota(size_t) { /* not supported */ } + /***************************** ** OKL4-specific Accessors ** diff --git a/repos/base-pistachio/src/core/cpu_session_platform.cc b/repos/base-pistachio/src/core/cpu_session_platform.cc index 1962f3b01..727e5088c 100644 --- a/repos/base-pistachio/src/core/cpu_session_platform.cc +++ b/repos/base-pistachio/src/core/cpu_session_platform.cc @@ -32,3 +32,5 @@ Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability thread_ca return Ram_dataspace_capability(); } + +Cpu_session::Quota Cpu_session_component::quota() { return Quota(); } diff --git a/repos/base-pistachio/src/core/include/platform_thread.h b/repos/base-pistachio/src/core/include/platform_thread.h index da9c9ef94..e5b78672b 100644 --- a/repos/base-pistachio/src/core/include/platform_thread.h +++ b/repos/base-pistachio/src/core/include/platform_thread.h @@ -148,6 +148,11 @@ namespace Genode { */ Affinity::Location affinity(); + /** + * Set CPU quota of the thread to 'quota' + */ + void quota(size_t const quota) { /* not supported*/ } + /********************************** ** Pistachio-specific Accessors ** diff --git a/repos/base/include/base/pager.h b/repos/base/include/base/pager.h index 7a21b1342..8876c07fa 100644 --- a/repos/base/include/base/pager.h +++ b/repos/base/include/base/pager.h @@ -132,6 +132,8 @@ class Genode::Pager_activation_base: public Thread_base { private: + enum { WEIGHT = Cpu_session::DEFAULT_WEIGHT }; + Native_capability _cap; Pager_entrypoint *_ep; /* entry point to which the activation belongs */ @@ -142,9 +144,9 @@ class Genode::Pager_activation_base: public Thread_base public: - Pager_activation_base(const char *name, size_t stack_size) : - Thread_base(0, name, stack_size), - _cap(Native_capability()), _ep(0), _cap_valid(Lock::LOCKED) { } + Pager_activation_base(const char *name, size_t stack_size) + : Thread_base(WEIGHT, name, stack_size), _cap(Native_capability()), + _ep(0), _cap_valid(Lock::LOCKED) { } /** * Set entry point, which the activation serves diff --git a/repos/base/include/base/thread.h b/repos/base/include/base/thread.h index f30cb220d..321bbc0ed 100644 --- a/repos/base/include/base/thread.h +++ b/repos/base/include/base/thread.h @@ -330,10 +330,10 @@ class Genode::Thread_base /** * Hook for platform-specific constructor supplements * - * \param quota CPU quota that shall be granted to the thread - * \param type enables selection of special initialization + * \param weight weighting regarding the CPU session quota + * \param type enables selection of special initialization */ - void _init_platform_thread(size_t quota, Type type); + void _init_platform_thread(size_t weight, Type type); public: @@ -347,14 +347,14 @@ class Genode::Thread_base * at least set Context::ds_cap in a way that it references * the dataspace of the already attached stack. */ - Thread_base(size_t quota, const char *name, size_t stack_size, + Thread_base(size_t weight, const char *name, size_t stack_size, Type type); /** * Constructor * - * \param quota CPU quota that shall be granted to the thread - * \param name thread name for DEBUGging + * \param weight weighting regarding the CPU session quota + * \param name thread name (for debugging) * \param stack_size stack size * * \throw Stack_too_large @@ -366,10 +366,8 @@ class Genode::Thread_base * internally used by the framework for storing thread-context * information such as the thread's name ('Context'). */ - Thread_base(size_t quota, const char *name, size_t stack_size) - : - Thread_base(quota, name, stack_size, NORMAL) - { } + Thread_base(size_t weight, const char *name, size_t stack_size) + : Thread_base(weight, name, stack_size, NORMAL) { } /** * Constructor @@ -380,8 +378,8 @@ class Genode::Thread_base * \noapi Using multiple CPU sessions within a single component is * an experimental feature. * - * \param quota CPU quota that shall be granted to the thread - * \param name thread name for debugging + * \param weight weighting regarding the CPU session quota + * \param name thread name (for debugging) * \param stack_size stack size * \param type enables selection of special construction * \param cpu_session capability to cpu session used for construction @@ -390,7 +388,7 @@ class Genode::Thread_base * \throw Stack_alloc_failed * \throw Context_alloc_failed */ - Thread_base(size_t quota, const char *name, size_t stack_size, + Thread_base(size_t weight, const char *name, size_t stack_size, Type type, Cpu_session *); /** @@ -536,53 +534,54 @@ class Genode::Thread : public Thread_base /** * Constructor * - * \param quota CPU quota that shall be granted to the thread - * \param name thread name (for debugging) - * \param type enables selection of special construction + * \param weight weighting regarding the CPU session quota + * \param name thread name (for debugging) + * \param type enables selection of special construction */ - explicit Thread(size_t quota, const char *name) - : Thread_base(quota, name, STACK_SIZE, Type::NORMAL) { } + explicit Thread(size_t weight, const char *name) + : Thread_base(weight, name, STACK_SIZE, Type::NORMAL) { } /** * Constructor * - * \param quota CPU quota that shall be granted to the thread - * \param name thread name (for debugging) - * \param type enables selection of special construction + * \param weight weighting regarding the CPU session quota + * \param name thread name (for debugging) + * \param type enables selection of special construction * * \noapi */ - explicit Thread(size_t quota, const char *name, Type type) - : Thread_base(quota, name, STACK_SIZE, type) { } + explicit Thread(size_t weight, const char *name, Type type) + : Thread_base(weight, name, STACK_SIZE, type) { } /** * Constructor * - * \param quota CPU quota that shall be granted to the thread + * \param weight weighting regarding the CPU session quota * \param name thread name (for debugging) * \param cpu_session thread created via specific cpu session * * \noapi */ - explicit Thread(size_t quota, const char *name, Cpu_session * cpu_session) - : Thread_base(quota, name, STACK_SIZE, Type::NORMAL, cpu_session) - { } + explicit Thread(size_t weight, const char *name, + Cpu_session * cpu_session) + : Thread_base(weight, name, STACK_SIZE, Type::NORMAL, cpu_session) { } /** - * Shortcut for 'Thread(0, name, type)' + * Shortcut for 'Thread(DEFAULT_WEIGHT, name, type)' * * \noapi */ explicit Thread(const char *name, Type type = NORMAL) - : Thread_base(0, name, STACK_SIZE, type) { } + : Thread_base(Cpu_session::DEFAULT_WEIGHT, name, STACK_SIZE, type) { } /** - * Shortcut for 'Thread(0, name, cpu_session)' + * Shortcut for 'Thread(DEFAULT_WEIGHT, name, cpu_session)' * * \noapi */ explicit Thread(const char *name, Cpu_session * cpu_session) - : Thread_base(0, name, STACK_SIZE, Type::NORMAL, cpu_session) + : Thread_base(Cpu_session::DEFAULT_WEIGHT, name, STACK_SIZE, + Type::NORMAL, cpu_session) { } }; diff --git a/repos/base/include/cpu_session/client.h b/repos/base/include/cpu_session/client.h index 781e38bd4..9331e201c 100644 --- a/repos/base/include/cpu_session/client.h +++ b/repos/base/include/cpu_session/client.h @@ -86,9 +86,7 @@ struct Genode::Cpu_session_client : Rpc_client int transfer_quota(Cpu_session_capability session, size_t amount) override { return call(session, amount); } - size_t quota() override { return call(); } - - size_t used() override { return call(); } + Quota quota() override { return call(); } }; #endif /* _INCLUDE__CPU_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/cpu_session/cpu_session.h b/repos/base/include/cpu_session/cpu_session.h index 50fa035d7..15496e0f3 100644 --- a/repos/base/include/cpu_session/cpu_session.h +++ b/repos/base/include/cpu_session/cpu_session.h @@ -47,9 +47,15 @@ struct Genode::Cpu_session : Session enum { QUOTA_LIMIT_LOG2 = 15 }; enum { QUOTA_LIMIT = 1 << QUOTA_LIMIT_LOG2 }; enum { DEFAULT_PRIORITY = 0 }; + enum { DEFAULT_WEIGHT = 10 }; typedef Rpc_in_buffer Name; + /** + * Physical quota configuration + */ + struct Quota; + virtual ~Cpu_session() { } /** @@ -264,7 +270,8 @@ struct Genode::Cpu_session : Session * Transfer quota to another CPU session * * \param cpu_session receiver of quota donation - * \param amount amount of quota to donate + * \param amount percentage of the session quota scaled up to + * the 'QUOTA_LIMIT' space * \return 0 on success * * Quota can only be transfered if the specified CPU session is @@ -274,29 +281,23 @@ struct Genode::Cpu_session : Session size_t amount) = 0; /** - * Return current quota limit + * Return quota configuration of the session */ - virtual size_t quota() = 0; + virtual Quota quota() = 0; /** - * Return amount of used quota + * Scale up 'value' from its space with 'limit' to the 'QUOTA_LIMIT' space */ - virtual size_t used() = 0; + template + static size_t quota_lim_upscale(size_t const value, size_t const limit) { + return ((T)value << Cpu_session::QUOTA_LIMIT_LOG2) / limit; } /** - * Return amount of available quota + * Scale down 'value' from the 'QUOTA_LIMIT' space to a space with 'limit' */ - size_t avail() - { - size_t q = quota(), u = used(); - return q > u ? q - u : 0; - } - - /** - * Transform percentage of CPU utilization into CPU quota - */ - static size_t pc_to_quota(size_t const pc) { - return (pc << QUOTA_LIMIT_LOG2) / 100; } + template + static size_t quota_lim_downscale(size_t const value, size_t const limit) { + return ((T)value * limit) >> Cpu_session::QUOTA_LIMIT_LOG2; } /********************* ** RPC declaration ** @@ -329,8 +330,7 @@ struct Genode::Cpu_session : Session GENODE_RPC(Rpc_trace_policy, Dataspace_capability, trace_policy, Thread_capability); GENODE_RPC(Rpc_ref_account, int, ref_account, Cpu_session_capability); GENODE_RPC(Rpc_transfer_quota, int, transfer_quota, Cpu_session_capability, size_t); - GENODE_RPC(Rpc_quota, size_t, quota); - GENODE_RPC(Rpc_used, size_t, used); + GENODE_RPC(Rpc_quota, Quota, quota); /* * 'GENODE_RPC_INTERFACE' declaration done manually @@ -361,9 +361,14 @@ struct Genode::Cpu_session : Session Meta::Type_tuple - > > > > > > > > > > > > > > > > > > > > > Rpc_functions; + > > > > > > > > > > > > > > > > > > > > Rpc_functions; +}; + +struct Genode::Cpu_session::Quota +{ + size_t super_period_us; + size_t us; }; #endif /* _INCLUDE__CPU_SESSION__CPU_SESSION_H_ */ diff --git a/repos/base/src/base/process/process.cc b/repos/base/src/base/process/process.cc index d62414115..852adb6cb 100644 --- a/repos/base/src/base/process/process.cc +++ b/repos/base/src/base/process/process.cc @@ -198,7 +198,8 @@ Process::Process(Dataspace_capability elf_ds_cap, /* create thread0 */ try { - _thread0_cap = _cpu_session_client.create_thread(0, name); + enum { WEIGHT = Cpu_session::DEFAULT_WEIGHT }; + _thread0_cap = _cpu_session_client.create_thread(WEIGHT, name); } catch (Cpu_session::Thread_creation_failed) { PERR("Creation of thread0 failed"); throw THREAD_FAIL; diff --git a/repos/base/src/base/server/common.cc b/repos/base/src/base/server/common.cc index 243b4ccdf..75e25e48e 100644 --- a/repos/base/src/base/server/common.cc +++ b/repos/base/src/base/server/common.cc @@ -102,7 +102,7 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, char const *name, bool start_on_construction, Affinity::Location location) : - Thread_base(0, name, stack_size), + Thread_base(Cpu_session::DEFAULT_WEIGHT, name, stack_size), _cap(Untyped_capability()), _curr_obj(0), _cap_valid(Lock::LOCKED), _delay_start(Lock::LOCKED), _delay_exit(Lock::LOCKED), diff --git a/repos/base/src/base/thread/thread_start.cc b/repos/base/src/base/thread/thread_start.cc index debe74574..35399093b 100644 --- a/repos/base/src/base/thread/thread_start.cc +++ b/repos/base/src/base/thread/thread_start.cc @@ -54,7 +54,9 @@ void Thread_base::start() /* create thread at core */ char buf[48]; name(buf, sizeof(buf)); - _thread_cap = _cpu_session->create_thread(0, buf, (addr_t)&_context->utcb); + enum { WEIGHT = Cpu_session::DEFAULT_WEIGHT }; + addr_t const utcb = (addr_t)&_context->utcb; + _thread_cap = _cpu_session->create_thread(WEIGHT, buf, utcb); if (!_thread_cap.valid()) throw Cpu_session::Thread_creation_failed(); diff --git a/repos/base/src/core/cpu_session_component.cc b/repos/base/src/core/cpu_session_component.cc index c9cfd39a4..ddf876614 100644 --- a/repos/base/src/core/cpu_session_component.cc +++ b/repos/base/src/core/cpu_session_component.cc @@ -33,14 +33,10 @@ void Cpu_thread_component::update_exception_sigh() }; -Thread_capability Cpu_session_component::create_thread(size_t quota, +Thread_capability Cpu_session_component::create_thread(size_t weight, Name const &name, addr_t utcb) { - /* check for sufficient quota */ - quota = _local_to_global(quota); - if (quota > avail()) { _insuff_for_consume(quota); } - unsigned trace_control_index = 0; if (!_trace_control_area.alloc(trace_control_index)) throw Out_of_metadata(); @@ -51,16 +47,27 @@ Thread_capability Cpu_session_component::create_thread(size_t quota, Trace::Thread_name thread_name(name.string()); Cpu_thread_component *thread = 0; + + if (weight == 0) { + PWRN("Thread %s: Bad weight 0, using %i instead.", + name.string(), DEFAULT_WEIGHT); + weight = DEFAULT_WEIGHT; + } + if (weight > QUOTA_LIMIT) { + PWRN("Thread %s: Oversized weight %zu, using %i instead.", + name.string(), weight, QUOTA_LIMIT); + weight = QUOTA_LIMIT; + } + Lock::Guard thread_list_lock_guard(_thread_list_lock); + _incr_weight(weight); + try { Lock::Guard slab_lock_guard(_thread_alloc_lock); thread = new(&_thread_alloc) Cpu_thread_component( - quota, _label, thread_name, _priority, utcb, - _default_exception_handler, trace_control_index, - *trace_control); - - /* account quota */ - _used += quota; + weight, _weight_to_quota(weight), _label, thread_name, + _priority, utcb, _default_exception_handler, + trace_control_index, *trace_control); /* set default affinity defined by CPU session */ thread->platform_thread()->affinity(_location); @@ -68,7 +75,6 @@ Thread_capability Cpu_session_component::create_thread(size_t quota, throw Out_of_metadata(); } - Lock::Guard thread_list_lock_guard(_thread_list_lock); _thread_list.insert(thread); _trace_sources.insert(thread->trace_source()); @@ -86,7 +92,7 @@ void Cpu_session_component::_unsynchronized_kill_thread(Cpu_thread_component *th unsigned const trace_control_index = thread->trace_control_index(); - _used -= thread->quota(); + _decr_weight(thread->weight()); Lock::Guard lock_guard(_thread_alloc_lock); destroy(&_thread_alloc, thread); @@ -290,39 +296,72 @@ static size_t remaining_session_ram_quota(char const *args) } -int Cpu_session_component::transfer_quota(Cpu_session_capability c, size_t q) +void Cpu_session_component::_transfer_quota(Cpu_session_component * const dst, + size_t const quota) { - /* lookup targeted CPU-session */ - Object_pool::Guard s(_session_ep->lookup_and_lock(c)); - if (!s) { return -1; } - - /* translate quota argument and check limits */ - q = _local_to_global(q); - if (q > avail()) { return _insuff_for_transfer(q); } - - /* transfer quota to targeted CPU-session */ - if (s->_ref == this) { return _transfer_forth(s, q); } - if (s == _ref) { return _transfer_back(q); } - return -2; + if (!quota) { return; } + _decr_quota(quota); + dst->_incr_quota(quota); } -int Cpu_session_component::ref_account(Cpu_session_capability c) +int Cpu_session_component::transfer_quota(Cpu_session_capability dst_cap, + size_t amount) +{ + /* lookup targeted CPU session */ + Object_pool::Guard + dst(_session_ep->lookup_and_lock(dst_cap)); + if (!dst) { + PWRN("Transfer CPU quota, %s, targeted session not found", + _label.string()); + return -1; + } + /* check reference relationship */ + if (dst->_ref != this && dst != _ref) { + PWRN("Transfer CPU quota, %s -> %s, no reference relation", + _label.string(), dst->_label.string()); + return -2; + } + /* check quota availability */ + size_t const quota = quota_lim_downscale(_quota, amount); + if (quota > _quota) { + PWRN("Transfer CPU quota, %s -> %s, insufficient quota %zu, need %zu", + _label.string(), dst->_label.string(), _quota, quota); + return -3; + } + /* transfer quota */ + _transfer_quota(dst, quota); + return 0; +} + + +int Cpu_session_component::ref_account(Cpu_session_capability ref_cap) { /* * Ensure that the ref account is set only once * * FIXME Add check for cycles along the tree of reference accounts */ - if (_ref) { return -2; } - - /* lookup targeted CPU-session */ - Object_pool::Guard s(_session_ep->lookup_and_lock(c)); - if (!s) { return -1; } - if (s == this) { return -3; } + if (_ref) { + PWRN("Set ref account, %s, set already", + _label.string()); + return -2; } + /* lookup and check targeted CPU-session */ + Object_pool::Guard + ref(_session_ep->lookup_and_lock(ref_cap)); + if (!ref) { + PWRN("Set ref account, %s, targeted session not found", + _label.string()); + return -1; + } + if (ref == this) { + PWRN("Set ref account, %s, self reference not allowed", + _label.string()); + return -3; + } /* establish ref-account relation from targeted CPU-session to us */ - _ref = s; + _ref = ref; _ref->_insert_ref_member(this); return 0; } @@ -335,7 +374,7 @@ Cpu_session_component::Cpu_session_component(Rpc_entrypoint *session_ep, Trace::Source_registry &trace_sources, char const *args, Affinity const &affinity, - size_t quota) + size_t const quota) : _session_ep(session_ep), _thread_ep(thread_ep), _pager_ep(pager_ep), @@ -345,7 +384,7 @@ Cpu_session_component::Cpu_session_component(Rpc_entrypoint *session_ep, /* map affinity to a location within the physical affinity space */ _location(affinity.scale_to(platform()->affinity_space())), - _trace_sources(trace_sources), _ref(0), _used(0), _quota(quota) + _trace_sources(trace_sources), _quota(quota), _ref(0) { /* remember session label */ char buf[Session_label::size()]; @@ -375,7 +414,7 @@ void Cpu_session_component::_deinit_ref_account() if (!_ref) { return; } /* give back our remaining quota to our ref account */ - _transfer_back(_quota); + _transfer_quota(_ref, _quota); /* remove ref-account relation between us and our ref-account */ Cpu_session_component * const orig_ref = _ref; @@ -405,30 +444,53 @@ void Cpu_session_component::_deinit_threads() } -int Cpu_session_component::_insuff_for_transfer(size_t const q) +void Cpu_session_component:: +_update_thread_quota(Cpu_thread_component * const thread) const { - if (verbose) { - PWRN("Insufficient CPU quota for transfer: %s", _label.string()); - PWRN(" avail %zu", _avail()); - PWRN(" needed %zu", q); - } - return -3; + thread->platform_thread()->quota(_weight_to_quota(thread->weight())); } -void Cpu_session_component::_insuff_for_consume(size_t const q) +void Cpu_session_component::_incr_weight(size_t const weight) { - if (verbose) { - PWRN("Insufficient CPU quota for consumption: %s", _label.string()); - PWRN(" avail %zu", _avail()); - PWRN(" needed %zu", q); - } - throw Quota_exceeded(); + _weight += weight; + if (_quota) { _update_each_thread_quota(); } } -size_t Cpu_session_component::used() { return _global_to_local(_used); } -size_t Cpu_session_component::quota() { return _global_to_local(_quota); } +void Cpu_session_component::_decr_weight(size_t const weight) +{ + _weight -= weight; + if (_quota) { _update_each_thread_quota(); } +} + + +void Cpu_session_component::_decr_quota(size_t const quota) +{ + Lock::Guard lock_guard(_thread_list_lock); + _quota -= quota; + _update_each_thread_quota(); +} + + +void Cpu_session_component::_incr_quota(size_t const quota) +{ + Lock::Guard lock_guard(_thread_list_lock); + _quota += quota; + _update_each_thread_quota(); +} + + +void Cpu_session_component::_update_each_thread_quota() +{ + Cpu_thread_component * thread = _thread_list.first(); + for (; thread; thread = thread->next()) { _update_thread_quota(thread); } +} + + +size_t +Cpu_session_component::_weight_to_quota(size_t const weight) const { + return (weight * _quota) / _weight; } /**************************** diff --git a/repos/base/src/core/include/cpu_session_component.h b/repos/base/src/core/include/cpu_session_component.h index 8d58b697c..b9bd5e4da 100644 --- a/repos/base/src/core/include/cpu_session_component.h +++ b/repos/base/src/core/include/cpu_session_component.h @@ -53,7 +53,7 @@ namespace Genode { private: - size_t const _quota; + size_t const _weight; Thread_name const _name; Platform_thread _platform_thread; bool _bound; /* pd binding flag */ @@ -63,14 +63,27 @@ namespace Genode { public: - Cpu_thread_component(size_t quota, Session_label const &label, + /** + * Constructor + * + * \param weight weighting regarding the CPU session quota + * \param quota initial quota counter-value of the weight + * \param labal label of the threads session + * \param name name for the thread + * \param priority scheduling priority + * \param utcb user-local UTCB base + * \param sigh initial exception handler + */ + Cpu_thread_component(size_t const weight, + size_t const quota, + Session_label const &label, Thread_name const &name, unsigned priority, addr_t utcb, Signal_context_capability sigh, unsigned trace_control_index, Trace::Control &trace_control) : - _quota(quota), _name(name), + _weight(weight), _name(name), _platform_thread(quota, name.string(), priority, utcb), _bound(false), _sigh(sigh), _trace_control_index(trace_control_index), @@ -88,7 +101,7 @@ namespace Genode { bool bound() const { return _bound; } void bound(bool b) { _bound = b; } Trace::Source *trace_source() { return &_trace_source; } - size_t quota() const { return _quota; } + size_t weight() const { return _weight; } void sigh(Signal_context_capability sigh) { @@ -138,9 +151,9 @@ namespace Genode { * Members for quota accounting */ - Cpu_session_component * _ref; - size_t _used; + size_t _weight; size_t _quota; + Cpu_session_component * _ref; List _ref_members; Lock _ref_members_lock; @@ -148,32 +161,22 @@ namespace Genode { * Utilities for quota accounting */ - size_t _avail() { return _quota - _used; } + void _incr_weight(size_t const weight); - size_t _local_to_global(size_t const q) const { - return (q * _quota) >> Cpu_session::QUOTA_LIMIT_LOG2; } + void _decr_weight(size_t const weight); - size_t _global_to_local(size_t const q) const { - if (!_quota) { return 0; } - return (q << Cpu_session::QUOTA_LIMIT_LOG2) / _quota; } + size_t _weight_to_quota(size_t const weight) const; - int _insuff_for_transfer(size_t const q); + void _decr_quota(size_t const quota); - void _insuff_for_consume(size_t const q); + void _incr_quota(size_t const quota); - int _transfer_back(size_t const q) - { - _quota -= q; - _ref->_used -= q; - return 0; - } + void _update_thread_quota(Cpu_thread_component *) const; - int _transfer_forth(Cpu_session_component * const s, size_t const q) - { - s->_quota += q; - _used += q; - return 0; - } + void _update_each_thread_quota(); + + void _transfer_quota(Cpu_session_component * const dst, + size_t const quota); void _insert_ref_member(Cpu_session_component * const s) { @@ -261,9 +264,8 @@ namespace Genode { Dataspace_capability trace_buffer(Thread_capability); Dataspace_capability trace_policy(Thread_capability); int ref_account(Cpu_session_capability c); - int transfer_quota(Cpu_session_capability c, size_t q); - size_t used(); - size_t quota(); + int transfer_quota(Cpu_session_capability, size_t); + Quota quota() override; }; } diff --git a/repos/base/src/core/main.cc b/repos/base/src/core/main.cc index 282817eda..3569c7351 100644 --- a/repos/base/src/core/main.cc +++ b/repos/base/src/core/main.cc @@ -263,14 +263,13 @@ int main() Ram_session_client(init_ram_session_cap).ref_account(env()->ram_session_cap()); /* create CPU session for init and transfer all of the CPU quota to it */ - constexpr size_t cpu_quota = Cpu_session::QUOTA_LIMIT; static Cpu_session_component cpu(e, e, rm_root.pager_ep(), &sliced_heap, trace_sources, - "label=\"core\"", Affinity(), cpu_quota); + "label=\"core\"", Affinity(), Cpu_session::QUOTA_LIMIT); Cpu_session_capability cpu_cap = core_env()->entrypoint()->manage(&cpu); Cpu_connection init_cpu("init"); init_cpu.ref_account(cpu_cap); - cpu.transfer_quota(init_cpu, cpu_quota); + cpu.transfer_quota(init_cpu, Cpu_session::quota_lim_upscale(100, 100)); Rm_connection init_rm; diff --git a/repos/libports/src/lib/pthread/thread.h b/repos/libports/src/lib/pthread/thread.h index a8df90f37..246826621 100644 --- a/repos/libports/src/lib/pthread/thread.h +++ b/repos/libports/src/lib/pthread/thread.h @@ -38,10 +38,12 @@ extern "C" { void *(*_start_routine) (void *); void *_arg; + enum { WEIGHT = Genode::Cpu_session::DEFAULT_WEIGHT }; + pthread(pthread_attr_t attr, void *(*start_routine) (void *), void *arg, size_t stack_size, char const * name, Genode::Cpu_session * cpu) - : Thread_base(0, name, stack_size, Type::NORMAL, cpu), + : Thread_base(WEIGHT, name, stack_size, Type::NORMAL, cpu), _attr(attr), _start_routine(start_routine), _arg(arg) diff --git a/repos/os/include/init/child.h b/repos/os/include/init/child.h index c8fb74877..a54b443ec 100644 --- a/repos/os/include/init/child.h +++ b/repos/os/include/init/child.h @@ -42,6 +42,12 @@ namespace Init { extern bool config_verbose; + static void warn_insuff_quota(Genode::size_t const avail) + { + if (!config_verbose) { return; } + Genode::printf("Warning: Specified quota exceeds available quota.\n"); + Genode::printf(" Proceeding with a quota of %zu.\n", avail); + } inline long read_priority(Genode::Xml_node start_node) { @@ -103,13 +109,6 @@ namespace Init { } - /** - * Return amount of CPU time that is currently unused - */ - static inline Genode::size_t avail_slack_cpu_quota() { - return Genode::env()->cpu_session()->avail(); } - - /** * Return true if service XML node matches the specified service name */ @@ -395,21 +394,12 @@ class Init::Child : Genode::Child_policy struct Read_quota { - void warn_unsuff_quota(Genode::size_t const avail) - { - using namespace Genode; - if (!config_verbose) { return; } - Genode::printf("Warning: Specified quota exceeds available quota.\n"); - Genode::printf(" Proceeding with a quota of %zu.\n", avail); - } - Read_quota(Genode::Xml_node start_node, Genode::size_t & ram_quota, - Genode::size_t & cpu_quota, + Genode::size_t & cpu_quota_pc, bool & constrain_phys) { Genode::Number_of_bytes ram_bytes = 0; - Genode::size_t cpu_percent = 0; try { Genode::Xml_node rsc = start_node.sub_node("resource"); @@ -419,12 +409,11 @@ class Init::Child : Genode::Child_policy rsc.attribute("quantum").value(&ram_bytes); constrain_phys = rsc.attribute("constrain_phys").has_value("yes"); } else if (rsc.attribute("name").has_value("CPU")) { - rsc.attribute("quantum").value(&cpu_percent); } + rsc.attribute("quantum").value(&cpu_quota_pc); } } catch (...) { } } } catch (...) { } ram_quota = ram_bytes; - cpu_quota = Genode::Cpu_session::pc_to_quota(cpu_percent); /* * If the configured RAM quota exceeds our own quota, we donate @@ -435,13 +424,7 @@ class Init::Child : Genode::Child_policy Genode::size_t const ram_avail = avail_slack_ram_quota(); if (ram_quota > ram_avail) { ram_quota = ram_avail; - warn_unsuff_quota(ram_avail); - } - - Genode::size_t const cpu_avail = avail_slack_cpu_quota(); - if (cpu_quota > cpu_avail) { - cpu_quota = cpu_avail; - warn_unsuff_quota(cpu_avail); + warn_insuff_quota(ram_avail); } } }; @@ -455,17 +438,19 @@ class Init::Child : Genode::Child_policy long priority; Genode::Affinity affinity; Genode::size_t ram_quota; - Genode::size_t cpu_quota; + Genode::size_t cpu_quota_pc; bool constrain_phys; Genode::Ram_connection ram; Genode::Cpu_connection cpu; Genode::Rm_connection rm; + inline void transfer_cpu_quota(); + Resources(Genode::Xml_node start_node, const char *label, long prio_levels_log2, Genode::Affinity::Space const &affinity_space) : - Read_quota(start_node, ram_quota, cpu_quota, constrain_phys), + Read_quota(start_node, ram_quota, cpu_quota_pc, constrain_phys), prio_levels_log2(prio_levels_log2), priority(read_priority(start_node)), affinity(affinity_space, @@ -487,8 +472,7 @@ class Init::Child : Genode::Child_policy ram.ref_account(Genode::env()->ram_session_cap()); Genode::env()->ram_session()->transfer_quota(ram.cap(), ram_quota); - cpu.ref_account(Genode::env()->cpu_session_cap()); - Genode::env()->cpu_session()->transfer_quota(cpu.cap(), cpu_quota); + transfer_cpu_quota(); } } _resources; @@ -801,4 +785,24 @@ class Init::Child : Genode::Child_policy Genode::Native_pd_args const *pd_args() const { return &_pd_args; } }; + +void Init::Child::Resources::transfer_cpu_quota() +{ + using Genode::Cpu_session; + using Genode::size_t; + static size_t avail = Cpu_session::quota_lim_upscale( 100, 100); + size_t const need = Cpu_session::quota_lim_upscale(cpu_quota_pc, 100); + size_t need_adj; + if (need > avail) { + warn_insuff_quota(Cpu_session::quota_lim_downscale(avail, 100)); + need_adj = Cpu_session::quota_lim_upscale(100, 100); + avail = 0; + } else { + need_adj = Cpu_session::quota_lim_upscale(need, avail); + avail -= need; + } + cpu.ref_account(Genode::env()->cpu_session_cap()); + Genode::env()->cpu_session()->transfer_quota(cpu.cap(), need_adj); +} + #endif /* _INCLUDE__INIT__CHILD_H_ */ diff --git a/repos/os/include/os/irq_activation.h b/repos/os/include/os/irq_activation.h index 896f1b72a..316898a45 100644 --- a/repos/os/include/os/irq_activation.h +++ b/repos/os/include/os/irq_activation.h @@ -41,6 +41,8 @@ class Genode::Irq_activation : Thread_base { private: + enum { WEIGHT = Cpu_session::DEFAULT_WEIGHT }; + int _number; Irq_connection _connection; Irq_handler &_handler; @@ -72,7 +74,7 @@ class Genode::Irq_activation : Thread_base */ Irq_activation(int irq_number, Irq_handler &handler, size_t stack_size) : - Thread_base(0, _create_thread_name(irq_number), stack_size), + Thread_base(WEIGHT, _create_thread_name(irq_number), stack_size), _number(irq_number), _connection(irq_number), _handler(handler), _dispatcher(_sig_rec, *this, &Irq_activation::_handle) { diff --git a/repos/os/run/cpu_quota.run b/repos/os/run/cpu_quota.run new file mode 100644 index 000000000..0211e8b34 --- /dev/null +++ b/repos/os/run/cpu_quota.run @@ -0,0 +1,244 @@ +# +# Check platform +# +# HW is the only kernel that provides appliance of quota to the scheduling. +# On X86, the timer driver uses the PIT with a timeout of max. 54 ms. Thus, +# the driver needs to restart the timer permanently which is a hard job with 6 +# high-priority counter-threads in the background. As a consequence, timeouts +# take much longer than requested and the test fails. However, as the PIT +# tends to be replaced by a better timing source, we simply skip X86 for now. +# +# +assert_spec hw +assert_spec arm + +# +# Build +# + +build "core init drivers/timer test/cpu_quota" + +# +# Boot image +# + +create_boot_directory + +install_config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +build_boot_image "core init timer test-cpu_quota test-sync" + +# +# Execution +# + +append qemu_args "-nographic -m 64" + +run_genode_until ".*done.*\n.*done.*\n.*done.*\n" 100 + +# +# Conclusion +# + +proc check_counter { name opt cnt total_cnt } { + + set err 1 + set is [expr double($cnt) / $total_cnt ] + set is_pc [expr double(round($is * 100000)) / 1000] + set opt_pc [expr double(round($opt * 100000)) / 1000] + + if {[expr $is > $opt + $err || $is < $opt - $err]} { + puts stderr "Error: $name received $is_pc % of the CPU time." + puts stderr " Should receive $opt_pc %." + exit -1 + } + puts "$name: $is_pc % (optimal $opt_pc %)" +} + +proc check_quota { name opt_sp quota_sp opt quota } { + + if {[expr $quota != $opt]} { + puts stderr "Error: $name has CPU quota of $quota us." + puts stderr " Should have $opt us." + exit -1 + } + if {[expr $quota_sp != $opt_sp]} { + puts stderr "Error: $name has CPU quota super-period of $quota_sp us." + puts stderr " Should have $opt_sp us." + exit -1 + } +} + +regexp {[0-9]+} [regexp -inline {slow. quota [0-9]+} $output] slow_quota +regexp {[0-9]+} [regexp -inline {midl. quota [0-9]+} $output] midl_quota +regexp {[0-9]+} [regexp -inline {fast. quota [0-9]+} $output] fast_quota + +regexp {[0-9]+} [regexp -inline {slow. quota super period [0-9]+} $output] slow_quota_sp +regexp {[0-9]+} [regexp -inline {midl. quota super period [0-9]+} $output] midl_quota_sp +regexp {[0-9]+} [regexp -inline {fast. quota super period [0-9]+} $output] fast_quota_sp + +# +# We have to consider the rounding errors as the two translations from init to +# core and then from core to the user are distinct. +# +# Slow quota (1000000 * (0x8000 * 5 / 100)) / 0x8000 = 49987 +# Slow quota (1000000 * (0x8000 * 20 / 100)) / 0x8000 = 199981 +# Slow quota (1000000 * (0x8000 * 60 / 100)) / 0x8000 = 599975 +# +check_quota "Slow test" 1000000 $slow_quota_sp 49987 $slow_quota +check_quota "Middle test" 1000000 $midl_quota_sp 199981 $midl_quota +check_quota "Fast test" 1000000 $fast_quota_sp 599975 $fast_quota + +regexp {[0-9]+} [regexp -inline {slow. counter A [0-9]+} $output] slow_a_cnt +regexp {[0-9]+} [regexp -inline {midl. counter A [0-9]+} $output] midl_a_cnt +regexp {[0-9]+} [regexp -inline {fast. counter A [0-9]+} $output] fast_a_cnt +regexp {[0-9]+} [regexp -inline {slow. counter B [0-9]+} $output] slow_b_cnt +regexp {[0-9]+} [regexp -inline {midl. counter B [0-9]+} $output] midl_b_cnt +regexp {[0-9]+} [regexp -inline {fast. counter B [0-9]+} $output] fast_b_cnt + +set total_cnt [expr $fast_a_cnt + $midl_a_cnt + $slow_a_cnt + $fast_b_cnt + $midl_b_cnt + $slow_b_cnt] + +# +# Slow 5.0 % claim + 5.0 % fill = 10 % +# Stage 1 +# A 0.5 % claim + 2.5 % fill = 3 % +# B 4.5 % claim + 2.5 % fill = 7 % +# Stage 2 +# A 5.0 % claim + 5.0 % fill = 10 % +# Total +# A 3/4 * 3 + 1/4 * 10 = 4.75 % +# A 3/4 * 7 + 1/4 * 0 = 5.25 % +# +check_counter "Slow counter A" 0.0475 $slow_a_cnt $total_cnt +check_counter "Slow counter B" 0.0525 $slow_b_cnt $total_cnt + +# +# Middle 20 % claim + 5.0 % fill = 25.0 % +# Stage 1 +# A 2 % claim + 2.5 % fill = 4.5 % +# B 18 % claim + 2.5 % fill = 20.5 % +# Stage 2 +# A 20 % claim + 5.0 % fill = 25.0 % +# Total +# A 3/4 * 4.5 + 1/4 * 25 = 9.625 % +# A 3/4 * 20.5 + 1/4 * 0 = 15.375 % +# +check_counter "Middle counter A" 0.09625 $midl_a_cnt $total_cnt +check_counter "Middle counter B" 0.15375 $midl_b_cnt $total_cnt + +# +# Fast 60 % claim + 5.0 % fill = 65.0 % +# Stage 1 +# A 6 % claim + 2.5 % fill = 8.5 % +# B 54 % claim + 2.5 % fill = 56.5 % +# Stage 2 +# A 60 % claim + 5.0 % fill = 65.0 % +# Total +# A 3/4 * 8.5 + 1/4 * 65 = 22.625 % +# A 3/4 * 56.5 + 1/4 * 0 = 42.375 % +# +check_counter "Fast counter A" 0.22625 $fast_a_cnt $total_cnt +check_counter "Fast counter B" 0.42375 $fast_b_cnt $total_cnt + +puts "Test succeeded" diff --git a/repos/ports-foc/src/lib/l4lx/include/vcpu.h b/repos/ports-foc/src/lib/l4lx/include/vcpu.h index 8b0c93901..cadba6211 100644 --- a/repos/ports-foc/src/lib/l4lx/include/vcpu.h +++ b/repos/ports-foc/src/lib/l4lx/include/vcpu.h @@ -35,6 +35,8 @@ namespace L4lx { { private: + enum { WEIGHT = Genode::Cpu_session::DEFAULT_WEIGHT }; + Genode::Lock _lock; L4_CV void (*_func)(void *data); unsigned long _data; @@ -50,7 +52,7 @@ namespace L4lx { Genode::size_t stack_size, Genode::addr_t vcpu_state, unsigned cpu_nr) - : Genode::Thread_base(0, str, stack_size), + : Genode::Thread_base(WEIGHT, str, stack_size), _lock(Genode::Cancelable_lock::LOCKED), _func(func), _data(data ? *data : 0), diff --git a/repos/ports/include/vmm/vcpu_dispatcher.h b/repos/ports/include/vmm/vcpu_dispatcher.h index 8a9e8d224..6be6351ea 100644 --- a/repos/ports/include/vmm/vcpu_dispatcher.h +++ b/repos/ports/include/vmm/vcpu_dispatcher.h @@ -31,6 +31,8 @@ class Vmm::Vcpu_dispatcher : public T { private: + enum { WEIGHT = Genode::Cpu_session::DEFAULT_WEIGHT }; + Cap_connection &_cap; /** @@ -61,7 +63,7 @@ class Vmm::Vcpu_dispatcher : public T Cpu_session * cpu_session, Genode::Affinity::Location location) : - T(0, "vCPU dispatcher", stack_size), + T(WEIGHT, "vCPU dispatcher", stack_size), _cap(cap) { using namespace Genode; diff --git a/repos/ports/include/vmm/vcpu_thread.h b/repos/ports/include/vmm/vcpu_thread.h index c7b453bd8..037acbdae 100644 --- a/repos/ports/include/vmm/vcpu_thread.h +++ b/repos/ports/include/vmm/vcpu_thread.h @@ -62,8 +62,10 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread { using namespace Genode; - Thread_capability vcpu_vm = _cpu_session->create_thread(0, "vCPU"); - + enum { WEIGHT = Cpu_session::DEFAULT_WEIGHT }; + Thread_capability vcpu_vm = + _cpu_session->create_thread(WEIGHT, "vCPU"); + /* assign thread to protection domain */ _pd_session.bind_thread(vcpu_vm); @@ -104,12 +106,14 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread class Vmm::Vcpu_same_pd : public Vmm::Vcpu_thread, Genode::Thread_base { + enum { WEIGHT = Genode::Cpu_session::DEFAULT_WEIGHT }; + public: Vcpu_same_pd(size_t stack_size, Cpu_session * cpu_session, Genode::Affinity::Location location) : - Thread_base(0, "vCPU", stack_size, Type::NORMAL, cpu_session) + Thread_base(WEIGHT, "vCPU", stack_size, Type::NORMAL, cpu_session) { /* release pre-allocated selectors of Thread */ Genode::cap_map()->remove(tid().exc_pt_sel, Nova::NUM_INITIAL_PT_LOG2); diff --git a/repos/ports/src/app/gdb_monitor/cpu_session_component.cc b/repos/ports/src/app/gdb_monitor/cpu_session_component.cc index 8d339a422..093d52d5f 100644 --- a/repos/ports/src/app/gdb_monitor/cpu_session_component.cc +++ b/repos/ports/src/app/gdb_monitor/cpu_session_component.cc @@ -63,10 +63,12 @@ Thread_capability Cpu_session_component::thread_cap(unsigned long lwpid) } -Thread_capability Cpu_session_component::create_thread(size_t, Cpu_session::Name const &name, addr_t utcb) +Thread_capability +Cpu_session_component::create_thread(size_t weight, Name const &name, + addr_t utcb) { Thread_capability thread_cap = - _parent_cpu_session.create_thread(0, name.string(), utcb); + _parent_cpu_session.create_thread(weight, name.string(), utcb); if (thread_cap.valid()) { Thread_info *thread_info = new (env()->heap()) Thread_info(thread_cap, new_lwpid++); @@ -239,10 +241,8 @@ Cpu_session_component::~Cpu_session_component() { } -size_t Cpu_session_component::quota() { return 0; } - -size_t Cpu_session_component::used() { return 0; } - int Cpu_session_component::ref_account(Cpu_session_capability) { return -1; } int Cpu_session_component::transfer_quota(Cpu_session_capability, size_t) { return -1; } + +Cpu_session::Quota Cpu_session_component::quota() { return Quota(); } diff --git a/repos/ports/src/app/gdb_monitor/cpu_session_component.h b/repos/ports/src/app/gdb_monitor/cpu_session_component.h index 1a722f926..15d66fd1d 100644 --- a/repos/ports/src/app/gdb_monitor/cpu_session_component.h +++ b/repos/ports/src/app/gdb_monitor/cpu_session_component.h @@ -78,8 +78,7 @@ class Cpu_session_component : public Rpc_object Dataspace_capability trace_policy(Thread_capability); int ref_account(Cpu_session_capability c); int transfer_quota(Cpu_session_capability c, size_t q); - size_t used(); - size_t quota(); + Quota quota() override; }; #endif /* _CPU_SESSION_COMPONENT_H_ */ diff --git a/repos/ports/src/noux/cpu_session_component.h b/repos/ports/src/noux/cpu_session_component.h index 78d81d12a..cd34a3883 100644 --- a/repos/ports/src/noux/cpu_session_component.h +++ b/repos/ports/src/noux/cpu_session_component.h @@ -71,7 +71,7 @@ namespace Noux { ** Cpu_session interface ** ***************************/ - Thread_capability create_thread(size_t, Name const &name, + Thread_capability create_thread(size_t weight, Name const &name, addr_t utcb) { /* @@ -83,7 +83,7 @@ namespace Noux { while (1); return Thread_capability(); } - _main_thread = _cpu.create_thread(0, name, utcb); + _main_thread = _cpu.create_thread(weight, name, utcb); return _main_thread; } @@ -147,10 +147,13 @@ namespace Noux { Dataspace_capability trace_policy(Thread_capability thread) { return _cpu.trace_policy(thread); } - size_t quota() { return 0; } - size_t used() { return 0; } - int ref_account(Cpu_session_capability) { return -1; } - int transfer_quota(Cpu_session_capability, size_t) { return -1; } + Quota quota() override { return _cpu.quota(); } + + int ref_account(Cpu_session_capability c) override { + return _cpu.ref_account(c); } + + int transfer_quota(Cpu_session_capability c, size_t q) override { + return _cpu.transfer_quota(c, q); } }; } diff --git a/tool/autopilot.list b/tool/autopilot.list index f34ef7ed1..33537c7a4 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -50,3 +50,4 @@ vbox_auto_win8 tz_vmm vmm bomb +cpu_quota