base: add Child_policy::start_initial_thread

The added interface allows for the local interception of
'Cpu_thread::start' RPC calls.

Issue #4917
This commit is contained in:
Norman Feske 2023-05-16 16:51:53 +02:00
parent f2153f9b2f
commit 734fc252e8
4 changed files with 64 additions and 28 deletions

View File

@ -43,7 +43,7 @@ Child::Initial_thread::Initial_thread(Cpu_session &cpu,
Child::Initial_thread::~Initial_thread() { } 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) { } Parent_capability) { }
Child::Process::Process(Type type, Child::Process::Process(Type type,
Dataspace_capability ldso_ds, Dataspace_capability ldso_ds,
Pd_session &pd, Pd_session &pd,
Initial_thread_base &, Initial_thread_base &,
Region_map &local_rm, Initial_thread::Start &,
Region_map &remote_rm, Region_map &local_rm,
Parent_capability parent_cap) Region_map &remote_rm,
Parent_capability parent_cap)
: :
loaded_executable(type, ldso_ds, pd, local_rm, remote_rm, parent_cap) loaded_executable(type, ldso_ds, pd, local_rm, remote_rm, parent_cap)
{ {

View File

@ -26,6 +26,7 @@
#include <cpu_session/connection.h> #include <cpu_session/connection.h>
#include <log_session/connection.h> #include <log_session/connection.h>
#include <rom_session/connection.h> #include <rom_session/connection.h>
#include <cpu_thread/client.h>
#include <parent/capability.h> #include <parent/capability.h>
namespace Genode { namespace Genode {
@ -226,6 +227,14 @@ struct Genode::Child_policy
_with_address_space(pd, Impl(fn)); _with_address_space(pd, Impl(fn));
} }
/**
* Start initial thread of the child at instruction pointer 'ip'
*/
virtual void start_initial_thread(Capability<Cpu_thread> thread, addr_t ip)
{
Cpu_thread_client(thread).start(ip, 0);
}
/** /**
* Return true if ELF loading should be inhibited * Return true if ELF loading should be inhibited
*/ */
@ -263,10 +272,18 @@ class Genode::Child : protected Rpc_object<Parent>,
struct Initial_thread_base : Interface struct Initial_thread_base : Interface
{ {
struct Start : Interface
{
virtual void start_initial_thread(Capability<Cpu_thread>, addr_t ip) = 0;
};
/** /**
* Start execution at specified instruction pointer * 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 * Return capability of the initial thread
@ -283,6 +300,8 @@ class Genode::Child : protected Rpc_object<Parent>,
public: public:
using Initial_thread_base::Start;
typedef Cpu_session::Name Name; typedef Cpu_session::Name Name;
/** /**
@ -295,7 +314,7 @@ class Genode::Child : protected Rpc_object<Parent>,
Initial_thread(Cpu_session &, Pd_session_capability, Name const &); Initial_thread(Cpu_session &, Pd_session_capability, Name const &);
~Initial_thread(); ~Initial_thread();
void start(addr_t) override; void start(addr_t, Start &) override;
Capability<Cpu_thread> cap() const override { return _cap; } Capability<Cpu_thread> cap() const override { return _cap; }
}; };
@ -348,6 +367,19 @@ class Genode::Child : protected Rpc_object<Parent>,
Constructible<Initial_thread> _initial_thread { }; Constructible<Initial_thread> _initial_thread { };
struct Initial_thread_start : Initial_thread::Start
{
Child_policy &_policy;
void start_initial_thread(Capability<Cpu_thread> 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 struct Process
{ {
class Missing_dynamic_linker : Exception { }; class Missing_dynamic_linker : Exception { };
@ -405,13 +437,14 @@ class Genode::Child : protected Rpc_object<Parent>,
* initial thread must be done manually, i.e., as done for * initial thread must be done manually, i.e., as done for
* implementing fork. * implementing fork.
*/ */
Process(Type type, Process(Type type,
Dataspace_capability ldso_ds, Dataspace_capability ldso_ds,
Pd_session &pd, Pd_session &pd,
Initial_thread_base &initial_thread, Initial_thread_base &,
Region_map &local_rm, Initial_thread::Start &,
Region_map &remote_rm, Region_map &local_rm,
Parent_capability parent); Region_map &remote_rm,
Parent_capability parent);
~Process(); ~Process();
}; };

View File

@ -766,7 +766,8 @@ void Child::_try_construct_env_dependent_members()
_initial_thread.construct(_cpu.session(), _pd.cap(), _policy.name()); _initial_thread.construct(_cpu.session(), _pd.cap(), _policy.name());
_policy.with_address_space(_pd.session(), [&] (Region_map &address_space) { _policy.with_address_space(_pd.session(), [&] (Region_map &address_space) {
_process.construct(type, _linker_dataspace(), _pd.session(), _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_ram) { _error("out of RAM during ELF loading"); }
catch (Out_of_caps) { _error("out of caps during ELF loading"); } catch (Out_of_caps) { _error("out of caps during ELF loading"); }

View File

@ -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, Child::Process::Process(Type type,
Dataspace_capability ldso_ds, Dataspace_capability ldso_ds,
Pd_session &pd, Pd_session &pd,
Initial_thread_base &initial_thread, Initial_thread_base &initial_thread,
Region_map &local_rm, Initial_thread::Start &start,
Region_map &remote_rm, Region_map &local_rm,
Parent_capability parent_cap) Region_map &remote_rm,
Parent_capability parent_cap)
: :
loaded_executable(type, ldso_ds, pd, local_rm, remote_rm, parent_cap) loaded_executable(type, ldso_ds, pd, local_rm, remote_rm, parent_cap)
{ {
@ -198,7 +199,7 @@ Child::Process::Process(Type type,
return; return;
/* start main thread */ /* start main thread */
initial_thread.start(loaded_executable.entry); initial_thread.start(loaded_executable.entry, start);
} }