From 734fc252e8c1f6f6504f40a6a56c58663bb2f2a2 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Tue, 16 May 2023 16:51:53 +0200 Subject: [PATCH] base: add Child_policy::start_initial_thread The added interface allows for the local interception of 'Cpu_thread::start' RPC calls. Issue #4917 --- .../base-linux/src/lib/base/child_process.cc | 17 ++++--- repos/base/include/base/child.h | 51 +++++++++++++++---- repos/base/src/lib/base/child.cc | 3 +- repos/base/src/lib/base/child_process.cc | 21 ++++---- 4 files changed, 64 insertions(+), 28 deletions(-) diff --git a/repos/base-linux/src/lib/base/child_process.cc b/repos/base-linux/src/lib/base/child_process.cc index 520c9be5d0..54b563663d 100644 --- a/repos/base-linux/src/lib/base/child_process.cc +++ b/repos/base-linux/src/lib/base/child_process.cc @@ -43,7 +43,7 @@ Child::Initial_thread::Initial_thread(Cpu_session &cpu, Child::Initial_thread::~Initial_thread() { } -void Child::Initial_thread::start(addr_t) { } +void Child::Initial_thread::start(addr_t, Start &) { } /* @@ -57,13 +57,14 @@ Child::Process::Loaded_executable::Loaded_executable(Type, Parent_capability) { } -Child::Process::Process(Type type, - Dataspace_capability ldso_ds, - Pd_session &pd, - Initial_thread_base &, - Region_map &local_rm, - Region_map &remote_rm, - Parent_capability parent_cap) +Child::Process::Process(Type type, + Dataspace_capability ldso_ds, + Pd_session &pd, + Initial_thread_base &, + Initial_thread::Start &, + Region_map &local_rm, + Region_map &remote_rm, + Parent_capability parent_cap) : loaded_executable(type, ldso_ds, pd, local_rm, remote_rm, parent_cap) { diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index d2cabfc1de..a4d20b5ed1 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -26,6 +26,7 @@ #include #include #include +#include #include namespace Genode { @@ -226,6 +227,14 @@ struct Genode::Child_policy _with_address_space(pd, Impl(fn)); } + /** + * Start initial thread of the child at instruction pointer 'ip' + */ + virtual void start_initial_thread(Capability thread, addr_t ip) + { + Cpu_thread_client(thread).start(ip, 0); + } + /** * Return true if ELF loading should be inhibited */ @@ -263,10 +272,18 @@ class Genode::Child : protected Rpc_object, struct Initial_thread_base : Interface { + struct Start : Interface + { + virtual void start_initial_thread(Capability, addr_t ip) = 0; + }; + /** * Start execution at specified instruction pointer + * + * The 'Child_policy' allows for the overriding of the default + * RPC-based implementation of 'start_initial_thread'. */ - virtual void start(addr_t ip) = 0; + virtual void start(addr_t ip, Start &) = 0; /** * Return capability of the initial thread @@ -283,6 +300,8 @@ class Genode::Child : protected Rpc_object, public: + using Initial_thread_base::Start; + typedef Cpu_session::Name Name; /** @@ -295,7 +314,7 @@ class Genode::Child : protected Rpc_object, Initial_thread(Cpu_session &, Pd_session_capability, Name const &); ~Initial_thread(); - void start(addr_t) override; + void start(addr_t, Start &) override; Capability cap() const override { return _cap; } }; @@ -348,6 +367,19 @@ class Genode::Child : protected Rpc_object, Constructible _initial_thread { }; + struct Initial_thread_start : Initial_thread::Start + { + Child_policy &_policy; + + void start_initial_thread(Capability cap, addr_t ip) override + { + _policy.start_initial_thread(cap, ip); + } + + Initial_thread_start(Child_policy &policy) : _policy(policy) { } + + } _initial_thread_start { _policy }; + struct Process { class Missing_dynamic_linker : Exception { }; @@ -405,13 +437,14 @@ class Genode::Child : protected Rpc_object, * initial thread must be done manually, i.e., as done for * implementing fork. */ - Process(Type type, - Dataspace_capability ldso_ds, - Pd_session &pd, - Initial_thread_base &initial_thread, - Region_map &local_rm, - Region_map &remote_rm, - Parent_capability parent); + Process(Type type, + Dataspace_capability ldso_ds, + Pd_session &pd, + Initial_thread_base &, + Initial_thread::Start &, + Region_map &local_rm, + Region_map &remote_rm, + Parent_capability parent); ~Process(); }; diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc index 2f4f0f31f7..dcbdf2728f 100644 --- a/repos/base/src/lib/base/child.cc +++ b/repos/base/src/lib/base/child.cc @@ -766,7 +766,8 @@ void Child::_try_construct_env_dependent_members() _initial_thread.construct(_cpu.session(), _pd.cap(), _policy.name()); _policy.with_address_space(_pd.session(), [&] (Region_map &address_space) { _process.construct(type, _linker_dataspace(), _pd.session(), - *_initial_thread, _local_rm, address_space, cap()); }); + *_initial_thread, _initial_thread_start, + _local_rm, address_space, cap()); }); } catch (Out_of_ram) { _error("out of RAM during ELF loading"); } catch (Out_of_caps) { _error("out of caps during ELF loading"); } diff --git a/repos/base/src/lib/base/child_process.cc b/repos/base/src/lib/base/child_process.cc index 4eb488879f..3545735583 100644 --- a/repos/base/src/lib/base/child_process.cc +++ b/repos/base/src/lib/base/child_process.cc @@ -170,19 +170,20 @@ Child::Initial_thread::~Initial_thread() } -void Child::Initial_thread::start(addr_t ip) +void Child::Initial_thread::start(addr_t ip, Start &start) { - Cpu_thread_client(_cap).start(ip, 0); + start.start_initial_thread(_cap, ip); } -Child::Process::Process(Type type, - Dataspace_capability ldso_ds, - Pd_session &pd, - Initial_thread_base &initial_thread, - Region_map &local_rm, - Region_map &remote_rm, - Parent_capability parent_cap) +Child::Process::Process(Type type, + Dataspace_capability ldso_ds, + Pd_session &pd, + Initial_thread_base &initial_thread, + Initial_thread::Start &start, + Region_map &local_rm, + Region_map &remote_rm, + Parent_capability parent_cap) : loaded_executable(type, ldso_ds, pd, local_rm, remote_rm, parent_cap) { @@ -198,7 +199,7 @@ Child::Process::Process(Type type, return; /* start main thread */ - initial_thread.start(loaded_executable.entry); + initial_thread.start(loaded_executable.entry, start); }