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