From 87b08d6c7f06b9cde1857528bd778e767ca92295 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Thu, 4 Jun 2020 16:04:29 +0200 Subject: [PATCH] libc: support pthread placement configuration Up to now all pthreads get placed on one CPU. The patch adds support to evaluate a libc pthread configuration specifying a placement strategy. The default strategy is now to use all available CPUs as imposed by Genode's affinity configuration for the pthread application. The old behaviour, putting all pthreads on one single cpu can be still configured by: ... Fixes #3775 --- repos/libports/src/lib/libc/internal/init.h | 1 + repos/libports/src/lib/libc/internal/kernel.h | 7 ++++ repos/libports/src/lib/libc/kernel.cc | 1 + repos/libports/src/lib/libc/pthread_create.cc | 37 ++++++++++++++++--- 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/repos/libports/src/lib/libc/internal/init.h b/repos/libports/src/lib/libc/internal/init.h index ee819a05b..5e50f0c46 100644 --- a/repos/libports/src/lib/libc/internal/init.h +++ b/repos/libports/src/lib/libc/internal/init.h @@ -109,6 +109,7 @@ namespace Libc { * Pthread/semaphore support */ void init_pthread_support(Suspend &, Resume &, Timer_accessor &); + void init_pthread_support(Genode::Cpu_session &, Xml_node); void init_semaphore_support(Timer_accessor &); struct Config_accessor : Interface diff --git a/repos/libports/src/lib/libc/internal/kernel.h b/repos/libports/src/lib/libc/internal/kernel.h index 7fe5b0b7b..ea46b2cf2 100644 --- a/repos/libports/src/lib/libc/internal/kernel.h +++ b/repos/libports/src/lib/libc/internal/kernel.h @@ -167,6 +167,13 @@ struct Libc::Kernel final : Vfs::Io_response_handler, : Xml_node(""); } + Xml_node _pthread_config() + { + return _libc_env.libc_config().has_sub_node("pthread") + ? _libc_env.libc_config().sub_node("pthread") + : Xml_node(""); + } + typedef String Config_attr; Config_attr const _rtc_path = _libc_env.libc_config().attribute_value("rtc", Config_attr()); diff --git a/repos/libports/src/lib/libc/kernel.cc b/repos/libports/src/lib/libc/kernel.cc index 5dd4b2a2d..600d20659 100644 --- a/repos/libports/src/lib/libc/kernel.cc +++ b/repos/libports/src/lib/libc/kernel.cc @@ -399,6 +399,7 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap) init_semaphore_support(_timer_accessor); init_pthread_support(*this, *this, _timer_accessor); + init_pthread_support(env.cpu(), _pthread_config()); _env.ep().register_io_progress_handler(*this); diff --git a/repos/libports/src/lib/libc/pthread_create.cc b/repos/libports/src/lib/libc/pthread_create.cc index 3a764b852..ed8c29c1d 100644 --- a/repos/libports/src/lib/libc/pthread_create.cc +++ b/repos/libports/src/lib/libc/pthread_create.cc @@ -24,11 +24,28 @@ #include /* libc-internal includes */ +#include #include #include -static Genode::String<32> pthread_name() +static Genode::Cpu_session * _cpu_session { nullptr }; +static bool _single_cpu { false }; + +void Libc::init_pthread_support(Genode::Cpu_session &cpu_session, + Genode::Xml_node node) +{ + _cpu_session = &cpu_session; + + String<32> placement("all-cpus"); + placement = node.attribute_value("placement", placement); + + if (placement == "single-cpu") + _single_cpu = true; +} + + +static unsigned pthread_id() { static Genode::Lock mutex; @@ -36,9 +53,7 @@ static Genode::String<32> pthread_name() Genode::Lock::Guard guard(mutex); - ++id; - - return { "pthread.", id }; + return id++; } @@ -80,12 +95,22 @@ extern "C" int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { + if (!_cpu_session || !start_routine || !thread) + return EINVAL; + size_t const stack_size = (attr && *attr && (*attr)->stack_size) ? (*attr)->stack_size : Libc::Component::stack_size(); + using Genode::Affinity; + + unsigned const id { pthread_id() }; + Genode::String<32> const pthread_name { "pthread.", id }; + Affinity::Space space { _cpu_session->affinity_space() }; + Affinity::Location location { space.location_of_index(_single_cpu ? 0 : id) }; + return Libc::pthread_create(thread, start_routine, arg, stack_size, - pthread_name().string(), nullptr, - Genode::Affinity::Location()); + pthread_name.string(), _cpu_session, + location); } }