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); } }