mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-21 03:55:04 +00:00
Separation of thread operations from CPU session
This patch moves the thread operations from the 'Cpu_session' to the 'Cpu_thread' interface. A noteworthy semantic change is the meaning of the former 'exception_handler' function, which used to define both, the default exception handler or a thread-specific signal handler. Now, the 'Cpu_session::exception_sigh' function defines the CPU-session-wide default handler whereas the 'Cpu_thread::exception_sigh' function defines the thread-specific one. To retain the ability to create 'Child' objects without invoking a capability, the child's initial thread must be created outside the 'Child::Process'. It is now represented by the 'Child::Initial_thread', which is passed as argument to the 'Child' constructor. Fixes #1939
This commit is contained in:
parent
59aec6114b
commit
a99989af40
@ -105,7 +105,7 @@ void Platform_thread::unbind()
|
||||
void Platform_thread::state(Thread_state s)
|
||||
{
|
||||
PDBG("Not implemented");
|
||||
throw Cpu_session::State_access_failed();
|
||||
throw Cpu_thread::State_access_failed();
|
||||
}
|
||||
|
||||
|
||||
|
@ -7,6 +7,7 @@ SRC_CC += stack_area.cc \
|
||||
core_region_map.cc \
|
||||
core_rpc_cap_alloc.cc \
|
||||
cpu_session_component.cc \
|
||||
cpu_thread_component.cc \
|
||||
cpu_session_support.cc \
|
||||
dataspace_component.cc \
|
||||
default_log.cc \
|
||||
@ -53,6 +54,7 @@ vpath rom_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cap_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_support.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_thread_component.cc $(GEN_CORE_DIR)
|
||||
vpath pd_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath rpc_cap_factory.cc $(GEN_CORE_DIR)
|
||||
vpath core_rpc_cap_alloc.cc $(GEN_CORE_DIR)
|
||||
|
@ -38,7 +38,7 @@ void Genode::Native_cpu_component::enable_vcpu(Genode::Thread_capability thread_
|
||||
auto lambda = [&] (Cpu_thread_component *thread) {
|
||||
if (!thread) return;
|
||||
|
||||
l4_cap_idx_t tid = thread->platform_thread()->thread().local.dst();
|
||||
l4_cap_idx_t tid = thread->platform_thread().thread().local.dst();
|
||||
|
||||
l4_msgtag_t tag = l4_thread_vcpu_control(tid, vcpu_state);
|
||||
if (l4_msgtag_has_error(tag))
|
||||
@ -55,7 +55,7 @@ Genode::Native_cpu_component::native_cap(Genode::Thread_capability cap)
|
||||
|
||||
auto lambda = [&] (Cpu_thread_component *thread) {
|
||||
return (!thread) ? Native_capability()
|
||||
: thread->platform_thread()->thread().local;
|
||||
: thread->platform_thread().thread().local;
|
||||
};
|
||||
return _thread_ep.apply(cap, lambda);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ SRC_CC += stack_area.cc \
|
||||
core_rpc_cap_alloc.cc \
|
||||
cpu_session_component.cc \
|
||||
cpu_session_support.cc \
|
||||
cpu_thread_component.cc \
|
||||
dataspace_component.cc \
|
||||
default_log.cc \
|
||||
dump_alloc.cc \
|
||||
@ -51,6 +52,7 @@ include $(GEN_CORE_DIR)/version.inc
|
||||
vpath stack_area.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_support.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_thread_component.cc $(GEN_CORE_DIR)
|
||||
vpath dataspace_component.cc $(GEN_CORE_DIR)
|
||||
vpath dump_alloc.cc $(GEN_CORE_DIR)
|
||||
vpath default_log.cc $(GEN_CORE_DIR)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/env.h>
|
||||
#include <cpu_thread/client.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
@ -76,9 +77,11 @@ void Thread::start()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
Cpu_thread_client cpu_thread(_thread_cap);
|
||||
|
||||
/* get gate-capability and badge of new thread */
|
||||
Thread_state state;
|
||||
try { state = _cpu_session->state(_thread_cap); }
|
||||
try { state = cpu_thread.state(); }
|
||||
catch (...) { throw Cpu_session::Thread_creation_failed(); }
|
||||
|
||||
/* remember UTCB of the new thread */
|
||||
@ -92,11 +95,11 @@ void Thread::start()
|
||||
l4_utcb_tcr_u(foc_utcb)->user[UTCB_TCR_THREAD_OBJ] = (addr_t)this;
|
||||
|
||||
/* register initial IP and SP at core */
|
||||
_cpu_session->start(_thread_cap, (addr_t)_thread_start, _stack->top());
|
||||
cpu_thread.start((addr_t)_thread_start, _stack->top());
|
||||
}
|
||||
|
||||
|
||||
void Thread::cancel_blocking()
|
||||
{
|
||||
_cpu_session->cancel_blocking(_thread_cap);
|
||||
Cpu_thread_client(_thread_cap).cancel_blocking();
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ INC_DIR += $(BASE_HW_DIR)/src/include $(BASE_DIR)/src/include
|
||||
SRC_CC += console.cc
|
||||
SRC_CC += cpu_session_component.cc
|
||||
SRC_CC += cpu_session_support.cc
|
||||
SRC_CC += cpu_thread_component.cc
|
||||
SRC_CC += core_region_map.cc
|
||||
SRC_CC += core_mem_alloc.cc
|
||||
SRC_CC += core_rpc_cap_alloc.cc
|
||||
|
@ -21,15 +21,9 @@
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Ram_dataspace_capability
|
||||
Cpu_session_component::utcb(Thread_capability thread_cap)
|
||||
Dataspace_capability Cpu_thread_component::utcb()
|
||||
{
|
||||
/* look up requested UTCB dataspace */
|
||||
auto lambda = [] (Cpu_thread_component *t) {
|
||||
if (!t) return Ram_dataspace_capability();
|
||||
return t->platform_thread()->utcb();
|
||||
};
|
||||
return _thread_ep->apply(thread_cap, lambda);
|
||||
return _platform_thread.utcb();
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/env.h>
|
||||
#include <cpu_thread/client.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack_allocator.h>
|
||||
@ -85,7 +86,7 @@ void Thread::start()
|
||||
{
|
||||
/* attach userland stack */
|
||||
try {
|
||||
Ram_dataspace_capability ds = _cpu_session->utcb(_thread_cap);
|
||||
Dataspace_capability ds = Cpu_thread_client(_thread_cap).utcb();
|
||||
size_t const size = sizeof(_stack->utcb());
|
||||
addr_t dst = Stack_allocator::addr_to_base(_stack) +
|
||||
stack_virtual_size() - size - stack_area_virtual_base();
|
||||
@ -95,11 +96,11 @@ void Thread::start()
|
||||
sleep_forever();
|
||||
}
|
||||
/* start thread with its initial IP and aligned SP */
|
||||
_cpu_session->start(_thread_cap, (addr_t)_thread_start, _stack->top());
|
||||
Cpu_thread_client(_thread_cap).start((addr_t)_thread_start, _stack->top());
|
||||
}
|
||||
|
||||
|
||||
void Thread::cancel_blocking()
|
||||
{
|
||||
_cpu_session->cancel_blocking(_thread_cap);
|
||||
Cpu_thread_client(_thread_cap).cancel_blocking();
|
||||
}
|
||||
|
@ -119,13 +119,13 @@ namespace Genode {
|
||||
Thread_state state()
|
||||
{
|
||||
PDBG("Not implemented");
|
||||
throw Cpu_session::State_access_failed();
|
||||
throw Cpu_thread::State_access_failed();
|
||||
}
|
||||
|
||||
void state(Thread_state)
|
||||
{
|
||||
PDBG("Not implemented");
|
||||
throw Cpu_session::State_access_failed();
|
||||
throw Cpu_thread::State_access_failed();
|
||||
}
|
||||
|
||||
const char *name() { return _name; }
|
||||
|
@ -21,7 +21,7 @@ using namespace Genode;
|
||||
void Native_cpu_component::thread_id(Thread_capability thread_cap, int pid, int tid)
|
||||
{
|
||||
_thread_ep.apply(thread_cap, [&] (Cpu_thread_component *thread) {
|
||||
if (thread) thread->platform_thread()->thread_id(pid, tid); });
|
||||
if (thread) thread->platform_thread().thread_id(pid, tid); });
|
||||
}
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ Untyped_capability Native_cpu_component::server_sd(Thread_capability thread_cap)
|
||||
|
||||
enum { DUMMY_LOCAL_NAME = 0 };
|
||||
typedef Native_capability::Dst Dst;
|
||||
return Untyped_capability(Dst(thread->platform_thread()->server_sd()),
|
||||
return Untyped_capability(Dst(thread->platform_thread().server_sd()),
|
||||
DUMMY_LOCAL_NAME);
|
||||
};
|
||||
return _thread_ep.apply(thread_cap, lambda);
|
||||
@ -46,7 +46,7 @@ Untyped_capability Native_cpu_component::client_sd(Thread_capability thread_cap)
|
||||
|
||||
enum { DUMMY_LOCAL_NAME = 0 };
|
||||
typedef Native_capability::Dst Dst;
|
||||
return Untyped_capability(Dst(thread->platform_thread()->client_sd()),
|
||||
return Untyped_capability(Dst(thread->platform_thread().client_sd()),
|
||||
DUMMY_LOCAL_NAME);
|
||||
};
|
||||
return _thread_ep.apply(thread_cap, lambda);
|
||||
|
@ -13,6 +13,7 @@ SRC_CC = main.cc \
|
||||
rom_session_component.cc \
|
||||
cpu_session_component.cc \
|
||||
cpu_session_support.cc \
|
||||
cpu_thread_component.cc \
|
||||
pd_session_component.cc \
|
||||
pd_upgrade_ram_quota.cc \
|
||||
dataspace_component.cc \
|
||||
@ -44,6 +45,7 @@ vpath main.cc $(GEN_CORE_DIR)
|
||||
vpath ram_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_support.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_thread_component.cc $(GEN_CORE_DIR)
|
||||
vpath pd_upgrade_ram_quota.cc $(GEN_CORE_DIR)
|
||||
vpath rpc_cap_factory.cc $(GEN_CORE_DIR)
|
||||
vpath platform_services.cc $(GEN_CORE_DIR)
|
||||
|
@ -32,16 +32,19 @@ using namespace Genode;
|
||||
* thread. Those information will be provided to core by the constructor of
|
||||
* the 'Platform_env' of the new process.
|
||||
*/
|
||||
Child::Process::Initial_thread::Initial_thread(Cpu_session &cpu,
|
||||
Pd_session_capability pd,
|
||||
char const *name)
|
||||
Child::Initial_thread::Initial_thread(Cpu_session &cpu,
|
||||
Pd_session_capability pd,
|
||||
Name const &name)
|
||||
:
|
||||
cpu(cpu),
|
||||
cap(cpu.create_thread(pd, name, Affinity::Location(), Cpu_session::Weight()))
|
||||
_cpu(cpu),
|
||||
_cap(cpu.create_thread(pd, name, Affinity::Location(), Cpu_session::Weight()))
|
||||
{ }
|
||||
|
||||
|
||||
Child::Process::Initial_thread::~Initial_thread() { }
|
||||
Child::Initial_thread::~Initial_thread() { }
|
||||
|
||||
|
||||
void Child::Initial_thread::start(addr_t) { }
|
||||
|
||||
|
||||
/*
|
||||
@ -60,13 +63,12 @@ Child::Process::Process(Dataspace_capability elf_ds,
|
||||
Pd_session_capability pd_cap,
|
||||
Pd_session &pd,
|
||||
Ram_session &ram,
|
||||
Cpu_session &cpu,
|
||||
Initial_thread_base &initial_thread,
|
||||
Region_map &local_rm,
|
||||
Region_map &remote_rm,
|
||||
Parent_capability parent_cap,
|
||||
char const *name)
|
||||
Parent_capability parent_cap)
|
||||
:
|
||||
initial_thread(cpu, pd_cap, name),
|
||||
initial_thread(initial_thread),
|
||||
loaded_executable(elf_ds, ldso_ds, ram, local_rm, remote_rm, parent_cap)
|
||||
{
|
||||
/* skip loading when called during fork */
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <base/snprintf.h>
|
||||
#include <base/sleep.h>
|
||||
#include <linux_native_cpu/client.h>
|
||||
#include <cpu_thread/client.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
@ -154,5 +155,5 @@ void Thread::start()
|
||||
|
||||
void Thread::cancel_blocking()
|
||||
{
|
||||
_cpu_session->cancel_blocking(_thread_cap);
|
||||
Cpu_thread_client(_thread_cap).cancel_blocking();
|
||||
}
|
||||
|
@ -21,96 +21,48 @@
|
||||
|
||||
#include <nova_cpu_session/nova_cpu_session.h>
|
||||
|
||||
namespace Genode {
|
||||
namespace Genode { struct Cpu_session_client; }
|
||||
|
||||
struct Cpu_session_client : Rpc_client<Nova_cpu_session>
|
||||
{
|
||||
explicit Cpu_session_client(Cpu_session_capability session)
|
||||
: Rpc_client<Nova_cpu_session>(static_cap_cast<Nova_cpu_session>(session)) { }
|
||||
|
||||
Thread_capability
|
||||
create_thread(Capability<Pd_session> pd, Name const &name,
|
||||
Affinity::Location affinity, Weight weight, addr_t utcb = 0) override {
|
||||
return call<Rpc_create_thread>(pd, name, affinity, weight, utcb); }
|
||||
struct Genode::Cpu_session_client : Rpc_client<Nova_cpu_session>
|
||||
{
|
||||
explicit Cpu_session_client(Cpu_session_capability session)
|
||||
: Rpc_client<Nova_cpu_session>(static_cap_cast<Nova_cpu_session>(session)) { }
|
||||
|
||||
Ram_dataspace_capability utcb(Thread_capability thread) override {
|
||||
return call<Rpc_utcb>(thread); }
|
||||
Thread_capability
|
||||
create_thread(Capability<Pd_session> pd, Name const &name,
|
||||
Affinity::Location affinity, Weight weight, addr_t utcb = 0) override {
|
||||
return call<Rpc_create_thread>(pd, name, affinity, weight, utcb); }
|
||||
|
||||
void kill_thread(Thread_capability thread) override {
|
||||
call<Rpc_kill_thread>(thread); }
|
||||
void kill_thread(Thread_capability thread) override {
|
||||
call<Rpc_kill_thread>(thread); }
|
||||
|
||||
int start(Thread_capability thread, addr_t ip, addr_t sp) override {
|
||||
return call<Rpc_start>(thread, ip, sp); }
|
||||
void exception_sigh(Signal_context_capability handler) override {
|
||||
call<Rpc_exception_sigh>(handler); }
|
||||
|
||||
void pause(Thread_capability thread) override
|
||||
{
|
||||
Native_capability block = call<Rpc_pause_sync>(thread);
|
||||
if (!block.valid())
|
||||
return;
|
||||
Affinity::Space affinity_space() const override {
|
||||
return call<Rpc_affinity_space>(); }
|
||||
|
||||
Nova::sm_ctrl(block.local_name(), Nova::SEMAPHORE_DOWN);
|
||||
}
|
||||
Dataspace_capability trace_control() override {
|
||||
return call<Rpc_trace_control>(); }
|
||||
|
||||
void resume(Thread_capability thread) override {
|
||||
call<Rpc_resume>(thread); }
|
||||
int ref_account(Cpu_session_capability session) override {
|
||||
return call<Rpc_ref_account>(session); }
|
||||
|
||||
void cancel_blocking(Thread_capability thread) override {
|
||||
call<Rpc_cancel_blocking>(thread); }
|
||||
int transfer_quota(Cpu_session_capability session, size_t amount) override {
|
||||
return call<Rpc_transfer_quota>(session, amount); }
|
||||
|
||||
Thread_state state(Thread_capability thread) override {
|
||||
return call<Rpc_get_state>(thread); }
|
||||
Quota quota() override { return call<Rpc_quota>(); }
|
||||
|
||||
void state(Thread_capability thread, Thread_state const &state) override {
|
||||
call<Rpc_set_state>(thread, state); }
|
||||
Capability<Native_cpu> native_cpu() override { return call<Rpc_native_cpu>(); }
|
||||
|
||||
void exception_handler(Thread_capability thread, Signal_context_capability handler) override {
|
||||
call<Rpc_exception_handler>(thread, handler); }
|
||||
private:
|
||||
|
||||
void single_step(Thread_capability thread, bool enable) override
|
||||
{
|
||||
Native_capability block = call<Rpc_single_step_sync>(thread, enable);
|
||||
if (!block.valid())
|
||||
return;
|
||||
Native_capability pause_sync(Thread_capability) {
|
||||
return Native_capability(); }
|
||||
|
||||
Nova::sm_ctrl(block.local_name(), Nova::SEMAPHORE_DOWN);
|
||||
}
|
||||
|
||||
Affinity::Space affinity_space() const override {
|
||||
return call<Rpc_affinity_space>(); }
|
||||
|
||||
void affinity(Thread_capability thread, Affinity::Location location) override {
|
||||
call<Rpc_affinity>(thread, location); }
|
||||
|
||||
Dataspace_capability trace_control() override {
|
||||
return call<Rpc_trace_control>(); }
|
||||
|
||||
unsigned trace_control_index(Thread_capability thread) override {
|
||||
return call<Rpc_trace_control_index>(thread); }
|
||||
|
||||
Dataspace_capability trace_buffer(Thread_capability thread) override {
|
||||
return call<Rpc_trace_buffer>(thread); }
|
||||
|
||||
Dataspace_capability trace_policy(Thread_capability thread) override {
|
||||
return call<Rpc_trace_policy>(thread); }
|
||||
|
||||
int ref_account(Cpu_session_capability session) override {
|
||||
return call<Rpc_ref_account>(session); }
|
||||
|
||||
int transfer_quota(Cpu_session_capability session, size_t amount) override {
|
||||
return call<Rpc_transfer_quota>(session, amount); }
|
||||
|
||||
Quota quota() override { return call<Rpc_quota>(); }
|
||||
|
||||
Capability<Native_cpu> native_cpu() override { return call<Rpc_native_cpu>(); }
|
||||
|
||||
private:
|
||||
|
||||
Native_capability pause_sync(Thread_capability) {
|
||||
return Native_capability(); }
|
||||
|
||||
Native_capability single_step_sync(Thread_capability, bool) {
|
||||
return Native_capability(); }
|
||||
};
|
||||
}
|
||||
Native_capability single_step_sync(Thread_capability, bool) {
|
||||
return Native_capability(); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__CPU_SESSION__CLIENT_H_ */
|
||||
|
@ -24,10 +24,10 @@ Native_capability
|
||||
Cpu_session_component::pause_sync(Thread_capability thread_cap)
|
||||
{
|
||||
auto lambda = [] (Cpu_thread_component *thread) {
|
||||
if (!thread || !thread->platform_thread())
|
||||
if (!thread)
|
||||
return Native_capability();
|
||||
|
||||
return thread->platform_thread()->pause();
|
||||
return thread->platform_thread().pause();
|
||||
};
|
||||
return _thread_ep->apply(thread_cap, lambda);
|
||||
}
|
||||
@ -39,10 +39,10 @@ Cpu_session_component::single_step_sync(Thread_capability thread_cap, bool enabl
|
||||
using namespace Genode;
|
||||
|
||||
auto lambda = [enable] (Cpu_thread_component *thread) {
|
||||
if (!thread || !thread->platform_thread())
|
||||
if (!thread)
|
||||
return Native_capability();
|
||||
|
||||
return thread->platform_thread()->single_step_sync(enable);
|
||||
return thread->platform_thread().single_step_sync(enable);
|
||||
};
|
||||
return _thread_ep->apply(thread_cap, lambda);
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <pager.h>
|
||||
#include <cpu_thread_component.h>
|
||||
#include <cpu_thread_allocator.h>
|
||||
#include <pd_session_component.h>
|
||||
#include <platform_thread.h>
|
||||
@ -33,325 +34,130 @@
|
||||
#include <trace/source_registry.h>
|
||||
#include <native_cpu_component.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* RPC interface of CPU thread
|
||||
*
|
||||
* We make 'Cpu_thread' a RPC object only to be able to lookup CPU threads
|
||||
* from thread capabilities supplied as arguments to CPU-session functions.
|
||||
* A CPU thread does not provide an actual RPC interface.
|
||||
*/
|
||||
struct Cpu_thread
|
||||
{
|
||||
GENODE_RPC_INTERFACE();
|
||||
};
|
||||
namespace Genode { class Cpu_session_component; }
|
||||
|
||||
|
||||
class Cpu_thread_component : public Rpc_object<Cpu_thread>,
|
||||
public List<Cpu_thread_component>::Element,
|
||||
public Trace::Source::Info_accessor
|
||||
{
|
||||
public:
|
||||
class Genode::Cpu_session_component : public Rpc_object<Nova_cpu_session>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Trace::Session_label Session_label;
|
||||
typedef Trace::Thread_name Thread_name;
|
||||
typedef Cpu_thread_component::Session_label Session_label;
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
Rpc_entrypoint &_ep;
|
||||
Pager_entrypoint &_pager_ep;
|
||||
Capability<Pd_session> _pd;
|
||||
Region_map_component &_address_space_region_map;
|
||||
Cpu_session::Weight const _weight;
|
||||
Session_label const _session_label;
|
||||
Thread_name const _name;
|
||||
Platform_thread _platform_thread;
|
||||
bool const _bound_to_pd;
|
||||
Session_label _label;
|
||||
Rpc_entrypoint *_session_ep;
|
||||
Rpc_entrypoint *_thread_ep;
|
||||
Pager_entrypoint *_pager_ep;
|
||||
Allocator_guard _md_alloc; /* guarded meta-data allocator */
|
||||
Cpu_thread_allocator _thread_alloc; /* meta-data allocator */
|
||||
Lock _thread_alloc_lock; /* protect allocator access */
|
||||
List<Cpu_thread_component> _thread_list;
|
||||
Lock _thread_list_lock; /* protect thread list */
|
||||
unsigned _priority; /* priority of threads
|
||||
created with this
|
||||
session */
|
||||
Affinity::Location _location; /* CPU affinity of this
|
||||
session */
|
||||
Trace::Source_registry &_trace_sources;
|
||||
Trace::Control_area _trace_control_area;
|
||||
|
||||
bool _bind_to_pd(Pd_session_component &pd)
|
||||
{
|
||||
if (!pd.bind_thread(_platform_thread))
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* Members for quota accounting
|
||||
*/
|
||||
|
||||
Signal_context_capability _sigh; /* exception handler */
|
||||
size_t _weight;
|
||||
size_t _quota;
|
||||
Cpu_session_component * _ref;
|
||||
List<Cpu_session_component> _ref_members;
|
||||
Lock _ref_members_lock;
|
||||
|
||||
struct Trace_control_slot
|
||||
{
|
||||
unsigned index = 0;
|
||||
Trace::Control_area &trace_control_area;
|
||||
Native_cpu_component _native_cpu;
|
||||
|
||||
Trace_control_slot(Trace::Control_area &trace_control_area)
|
||||
: trace_control_area(trace_control_area)
|
||||
{
|
||||
if (!trace_control_area.alloc(index))
|
||||
throw Cpu_session::Out_of_metadata();
|
||||
}
|
||||
friend class Native_cpu_component;
|
||||
|
||||
~Trace_control_slot()
|
||||
{
|
||||
trace_control_area.free(index);
|
||||
}
|
||||
void _incr_weight(size_t);
|
||||
void _decr_weight(size_t);
|
||||
size_t _weight_to_quota(size_t) const;
|
||||
void _decr_quota(size_t);
|
||||
void _incr_quota(size_t);
|
||||
void _update_thread_quota(Cpu_thread_component &) const;
|
||||
void _update_each_thread_quota();
|
||||
void _transfer_quota(Cpu_session_component *, size_t);
|
||||
void _insert_ref_member(Cpu_session_component *) { }
|
||||
void _unsync_remove_ref_member(Cpu_session_component *) { }
|
||||
void _remove_ref_member(Cpu_session_component *) { }
|
||||
void _deinit_ref_account();
|
||||
void _deinit_threads();
|
||||
|
||||
Trace::Control &control()
|
||||
{
|
||||
return *trace_control_area.at(index);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Exception handler to be invoked unless overridden by a
|
||||
* thread-specific handler via 'Cpu_thread::exception_sigh'
|
||||
*/
|
||||
Signal_context_capability _exception_sigh;
|
||||
|
||||
Trace_control_slot _trace_control_slot;
|
||||
/**
|
||||
* Raw thread-killing functionality
|
||||
*
|
||||
* This function is called from the 'kill_thread' function and
|
||||
* the destructor. Each these functions grab the list lock
|
||||
* by themselves and call this function to perform the actual
|
||||
* killing.
|
||||
*/
|
||||
void _unsynchronized_kill_thread(Thread_capability cap);
|
||||
|
||||
Trace::Source _trace_source { *this, _trace_control_slot.control() };
|
||||
/**
|
||||
* Convert session-local affinity location to physical location
|
||||
*/
|
||||
Affinity::Location _thread_affinity(Affinity::Location) const;
|
||||
|
||||
Weak_ptr<Address_space> _address_space = _platform_thread.address_space();
|
||||
public:
|
||||
|
||||
Rm_client _rm_client;
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Cpu_session_component(Rpc_entrypoint *session_ep,
|
||||
Rpc_entrypoint *thread_ep,
|
||||
Pager_entrypoint *pager_ep,
|
||||
Allocator *md_alloc,
|
||||
Trace::Source_registry &trace_sources,
|
||||
const char *args, Affinity const &affinity,
|
||||
size_t quota);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Cpu_session_component();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param ep entrypoint used for managing the thread RPC
|
||||
* object
|
||||
* \param pager_ep pager entrypoint used for handling the page
|
||||
* faults of the thread
|
||||
* \param pd PD session where the thread is executed
|
||||
* \param weight scheduling weight relative to the other
|
||||
* threads of the same CPU session
|
||||
* \param quota initial quota counter-value of the weight
|
||||
* \param labal label of the threads session
|
||||
* \param name name for the thread
|
||||
* \param priority scheduling priority
|
||||
* \param utcb user-local UTCB base
|
||||
* \param sigh initial exception handler
|
||||
*/
|
||||
Cpu_thread_component(Cpu_session_capability cpu_session_cap,
|
||||
Rpc_entrypoint &ep,
|
||||
Pager_entrypoint &pager_ep,
|
||||
Pd_session_component &pd,
|
||||
Trace::Control_area &trace_control_area,
|
||||
Cpu_session::Weight weight,
|
||||
size_t quota,
|
||||
Affinity::Location location,
|
||||
Session_label const &label,
|
||||
Thread_name const &name,
|
||||
unsigned priority,
|
||||
addr_t utcb,
|
||||
Signal_context_capability sigh)
|
||||
:
|
||||
_ep(ep), _pager_ep(pager_ep), _pd(pd.cap()),
|
||||
_address_space_region_map(pd.address_space_region_map()),
|
||||
_weight(weight),
|
||||
_session_label(label), _name(name),
|
||||
_platform_thread(name.string(), priority, location, utcb),
|
||||
_bound_to_pd(_bind_to_pd(pd)),
|
||||
_sigh(sigh),
|
||||
_trace_control_slot(trace_control_area),
|
||||
_rm_client(cpu_session_cap, _ep.manage(this),
|
||||
&_address_space_region_map,
|
||||
_platform_thread.pager_object_badge(),
|
||||
_address_space, _platform_thread.affinity())
|
||||
{
|
||||
update_exception_sigh();
|
||||
|
||||
_address_space_region_map.add_client(_rm_client);
|
||||
|
||||
/* acquaint thread with its pager object */
|
||||
_pager_ep.manage(&_rm_client);
|
||||
_platform_thread.pager(&_rm_client);
|
||||
}
|
||||
|
||||
~Cpu_thread_component()
|
||||
{
|
||||
_pager_ep.dissolve(&_rm_client);
|
||||
_ep.dissolve(this);
|
||||
|
||||
_address_space_region_map.remove_client(_rm_client);
|
||||
}
|
||||
|
||||
void affinity(Affinity::Location affinity)
|
||||
{
|
||||
_platform_thread.affinity(affinity);
|
||||
}
|
||||
/**
|
||||
* Register quota donation at allocator guard
|
||||
*/
|
||||
void upgrade_ram_quota(size_t ram_quota) { _md_alloc.upgrade(ram_quota); }
|
||||
|
||||
|
||||
/********************************************
|
||||
** Trace::Source::Info_accessor interface **
|
||||
********************************************/
|
||||
/***************************
|
||||
** CPU session interface **
|
||||
***************************/
|
||||
|
||||
Trace::Source::Info trace_source_info() const
|
||||
{
|
||||
return { _session_label, _name,
|
||||
_platform_thread.execution_time(),
|
||||
_platform_thread.affinity() };
|
||||
}
|
||||
Thread_capability create_thread(Capability<Pd_session>, Name const &,
|
||||
Affinity::Location, Weight, addr_t) override;
|
||||
void kill_thread(Thread_capability) override;
|
||||
void exception_sigh(Signal_context_capability) override;
|
||||
Affinity::Space affinity_space() const override;
|
||||
Dataspace_capability trace_control() override;
|
||||
int ref_account(Cpu_session_capability c) override;
|
||||
int transfer_quota(Cpu_session_capability, size_t) override;
|
||||
Quota quota() override;
|
||||
|
||||
Capability<Native_cpu> native_cpu() { return _native_cpu.cap(); }
|
||||
|
||||
|
||||
/************************
|
||||
** Accessor functions **
|
||||
************************/
|
||||
/******************************
|
||||
** NOVA specific extensions **
|
||||
******************************/
|
||||
|
||||
Platform_thread *platform_thread() { return &_platform_thread; }
|
||||
|
||||
Trace::Source *trace_source() { return &_trace_source; }
|
||||
|
||||
size_t weight() const { return Cpu_session::Weight::DEFAULT_WEIGHT; }
|
||||
|
||||
void sigh(Signal_context_capability sigh)
|
||||
{
|
||||
_sigh = sigh;
|
||||
update_exception_sigh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Propagate exception handler to platform thread
|
||||
*/
|
||||
void update_exception_sigh();
|
||||
|
||||
/**
|
||||
* Return index within the CPU-session's trace control area
|
||||
*/
|
||||
unsigned trace_control_index() const { return _trace_control_slot.index; }
|
||||
};
|
||||
|
||||
|
||||
class Cpu_session_component : public Rpc_object<Nova_cpu_session>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Cpu_thread_component::Session_label Session_label;
|
||||
|
||||
private:
|
||||
|
||||
Session_label _label;
|
||||
Rpc_entrypoint *_session_ep;
|
||||
Rpc_entrypoint *_thread_ep;
|
||||
Pager_entrypoint *_pager_ep;
|
||||
Allocator_guard _md_alloc; /* guarded meta-data allocator */
|
||||
Cpu_thread_allocator _thread_alloc; /* meta-data allocator */
|
||||
Lock _thread_alloc_lock; /* protect allocator access */
|
||||
List<Cpu_thread_component> _thread_list;
|
||||
Lock _thread_list_lock; /* protect thread list */
|
||||
unsigned _priority; /* priority of threads
|
||||
created with this
|
||||
session */
|
||||
Affinity::Location _location; /* CPU affinity of this
|
||||
session */
|
||||
Trace::Source_registry &_trace_sources;
|
||||
Trace::Control_area _trace_control_area;
|
||||
|
||||
/*
|
||||
* Members for quota accounting
|
||||
*/
|
||||
|
||||
size_t _weight;
|
||||
size_t _quota;
|
||||
Cpu_session_component * _ref;
|
||||
List<Cpu_session_component> _ref_members;
|
||||
Lock _ref_members_lock;
|
||||
|
||||
Native_cpu_component _native_cpu;
|
||||
|
||||
friend class Native_cpu_component;
|
||||
|
||||
void _incr_weight(size_t);
|
||||
void _decr_weight(size_t);
|
||||
size_t _weight_to_quota(size_t) const;
|
||||
void _decr_quota(size_t);
|
||||
void _incr_quota(size_t);
|
||||
void _update_thread_quota(Cpu_thread_component *) const;
|
||||
void _update_each_thread_quota();
|
||||
void _transfer_quota(Cpu_session_component *, size_t);
|
||||
void _insert_ref_member(Cpu_session_component *) { }
|
||||
void _unsync_remove_ref_member(Cpu_session_component *) { }
|
||||
void _remove_ref_member(Cpu_session_component *) { }
|
||||
void _deinit_ref_account();
|
||||
void _deinit_threads();
|
||||
|
||||
/**
|
||||
* Exception handler that will be invoked unless overridden by a
|
||||
* call of 'Cpu_session::exception_handler'.
|
||||
*/
|
||||
Signal_context_capability _default_exception_handler;
|
||||
|
||||
/**
|
||||
* Raw thread-killing functionality
|
||||
*
|
||||
* This function is called from the 'kill_thread' function and
|
||||
* the destructor. Each these functions grab the list lock
|
||||
* by themselves and call this function to perform the actual
|
||||
* killing.
|
||||
*/
|
||||
void _unsynchronized_kill_thread(Thread_capability cap);
|
||||
|
||||
/**
|
||||
* Convert session-local affinity location to physical location
|
||||
*/
|
||||
Affinity::Location _thread_affinity(Affinity::Location) const;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Cpu_session_component(Rpc_entrypoint *session_ep,
|
||||
Rpc_entrypoint *thread_ep,
|
||||
Pager_entrypoint *pager_ep,
|
||||
Allocator *md_alloc,
|
||||
Trace::Source_registry &trace_sources,
|
||||
const char *args, Affinity const &affinity,
|
||||
size_t quota);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Cpu_session_component();
|
||||
|
||||
/**
|
||||
* Register quota donation at allocator guard
|
||||
*/
|
||||
void upgrade_ram_quota(size_t ram_quota) { _md_alloc.upgrade(ram_quota); }
|
||||
|
||||
|
||||
/***************************
|
||||
** CPU session interface **
|
||||
***************************/
|
||||
|
||||
Thread_capability create_thread(Capability<Pd_session>, Name const &,
|
||||
Affinity::Location, Weight, addr_t) override;
|
||||
Ram_dataspace_capability utcb(Thread_capability thread) override;
|
||||
void kill_thread(Thread_capability) override;
|
||||
int start(Thread_capability, addr_t, addr_t) override;
|
||||
void pause(Thread_capability thread_cap) override;
|
||||
void resume(Thread_capability thread_cap) override;
|
||||
void single_step(Thread_capability thread_cap, bool enable) override;
|
||||
void cancel_blocking(Thread_capability) override;
|
||||
Thread_state state(Thread_capability) override;
|
||||
void state(Thread_capability, Thread_state const &) override;
|
||||
void exception_handler(Thread_capability, Signal_context_capability) override;
|
||||
Affinity::Space affinity_space() const override;
|
||||
void affinity(Thread_capability, Affinity::Location) override;
|
||||
Dataspace_capability trace_control() override;
|
||||
unsigned trace_control_index(Thread_capability) override;
|
||||
Dataspace_capability trace_buffer(Thread_capability) override;
|
||||
Dataspace_capability trace_policy(Thread_capability) override;
|
||||
int ref_account(Cpu_session_capability c) override;
|
||||
int transfer_quota(Cpu_session_capability, size_t) override;
|
||||
Quota quota() override;
|
||||
|
||||
Capability<Native_cpu> native_cpu() { return _native_cpu.cap(); }
|
||||
|
||||
|
||||
/******************************
|
||||
** NOVA specific extensions **
|
||||
******************************/
|
||||
|
||||
Native_capability pause_sync(Thread_capability) override;
|
||||
Native_capability single_step_sync(Thread_capability, bool) override;
|
||||
};
|
||||
}
|
||||
Native_capability pause_sync(Thread_capability) override;
|
||||
Native_capability single_step_sync(Thread_capability, bool) override;
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_ */
|
||||
|
@ -68,7 +68,7 @@ namespace Genode {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Platform_thread(const char *name = 0,
|
||||
Platform_thread(size_t, const char *name = 0,
|
||||
unsigned priority = 0,
|
||||
Affinity::Location affinity = Affinity::Location(),
|
||||
int thread_id = THREAD_INVALID);
|
||||
|
@ -28,7 +28,7 @@ Native_cpu_component::pager_cap(Thread_capability thread_cap)
|
||||
if (!thread)
|
||||
return Native_capability();
|
||||
|
||||
return thread->platform_thread()->pager()->cap();
|
||||
return thread->platform_thread().pager()->cap();
|
||||
};
|
||||
return _thread_ep.apply(thread_cap, lambda);
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ void Platform_thread::resume()
|
||||
|
||||
Thread_state Platform_thread::state()
|
||||
{
|
||||
if (!_pager) throw Cpu_session::State_access_failed();
|
||||
if (!_pager) throw Cpu_thread::State_access_failed();
|
||||
|
||||
Thread_state s;
|
||||
|
||||
@ -261,7 +261,7 @@ Thread_state Platform_thread::state()
|
||||
return s;
|
||||
}
|
||||
|
||||
throw Cpu_session::State_access_failed();
|
||||
throw Cpu_thread::State_access_failed();
|
||||
}
|
||||
|
||||
|
||||
@ -269,7 +269,7 @@ void Platform_thread::state(Thread_state s)
|
||||
{
|
||||
/* you can do it only once */
|
||||
if (_sel_exc_base != Native_thread::INVALID_INDEX)
|
||||
throw Cpu_session::State_access_failed();
|
||||
throw Cpu_thread::State_access_failed();
|
||||
|
||||
/*
|
||||
* s.sel_exc_base exception base of thread in caller
|
||||
@ -345,7 +345,7 @@ unsigned long long Platform_thread::execution_time() const
|
||||
}
|
||||
|
||||
|
||||
Platform_thread::Platform_thread(const char *name, unsigned prio,
|
||||
Platform_thread::Platform_thread(size_t, const char *name, unsigned prio,
|
||||
Affinity::Location affinity, int thread_id)
|
||||
:
|
||||
_pd(0), _pager(0), _id_base(cap_map()->insert(2)),
|
||||
|
@ -11,6 +11,7 @@ SRC_CC = stack_area.cc \
|
||||
cpu_session_component.cc \
|
||||
cpu_session_extension.cc \
|
||||
cpu_session_support.cc \
|
||||
cpu_thread_component.cc \
|
||||
dataspace_component.cc \
|
||||
default_log.cc \
|
||||
dump_alloc.cc \
|
||||
@ -53,6 +54,7 @@ vpath ram_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath rom_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_support.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_thread_component.cc $(GEN_CORE_DIR)
|
||||
vpath pd_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath pd_upgrade_ram_quota.cc $(GEN_CORE_DIR)
|
||||
vpath region_map_component.cc $(GEN_CORE_DIR)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <base/rpc_client.h>
|
||||
#include <session/session.h>
|
||||
#include <nova_native_cpu/client.h>
|
||||
#include <cpu_thread/client.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
@ -164,11 +165,11 @@ void Thread::start()
|
||||
/* local thread have no start instruction pointer - set via portal entry */
|
||||
addr_t thread_ip = global ? reinterpret_cast<addr_t>(_thread_start) : 0;
|
||||
|
||||
try { _cpu_session->state(_thread_cap, state); }
|
||||
Cpu_thread_client cpu_thread(_thread_cap);
|
||||
try { cpu_thread.state(state); }
|
||||
catch (...) { throw Cpu_session::Thread_creation_failed(); }
|
||||
|
||||
if (_cpu_session->start(_thread_cap, thread_ip, _stack->top()))
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
cpu_thread.start(thread_ip, _stack->top());
|
||||
|
||||
/* request native EC thread cap */
|
||||
native_thread().ec_sel = cap_map()->insert(1);
|
||||
@ -193,7 +194,7 @@ void Thread::start()
|
||||
|
||||
if (global)
|
||||
/* request creation of SC to let thread run*/
|
||||
_cpu_session->resume(_thread_cap);
|
||||
cpu_thread.resume();
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,6 +60,6 @@ Thread_state Platform_thread::state()
|
||||
void Platform_thread::state(Thread_state)
|
||||
{
|
||||
PDBG("Not implemented");
|
||||
throw Cpu_session::State_access_failed();
|
||||
throw Cpu_thread::State_access_failed();
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ SRC_CC += stack_area.cc \
|
||||
core_rpc_cap_alloc.cc \
|
||||
cpu_session_component.cc \
|
||||
cpu_session_support.cc \
|
||||
cpu_thread_component.cc \
|
||||
dataspace_component.cc \
|
||||
default_log.cc \
|
||||
dump_alloc.cc \
|
||||
@ -48,6 +49,7 @@ vpath ram_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath rom_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_support.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_thread_component.cc $(GEN_CORE_DIR)
|
||||
vpath pd_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath pd_upgrade_ram_quota.cc $(GEN_CORE_DIR)
|
||||
vpath pd_assign_pci.cc $(GEN_CORE_DIR)
|
||||
|
@ -17,10 +17,11 @@
|
||||
using namespace Genode;
|
||||
using namespace Pistachio;
|
||||
|
||||
Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability thread_cap)
|
||||
|
||||
Dataspace_capability Cpu_thread_component::utcb()
|
||||
{
|
||||
PERR("%s: Not implemented", __PRETTY_FUNCTION__);
|
||||
return Ram_dataspace_capability();
|
||||
return Dataspace_capability();
|
||||
}
|
||||
|
||||
|
||||
|
@ -175,7 +175,7 @@ void Platform_thread::unbind()
|
||||
void Platform_thread::state(Thread_state)
|
||||
{
|
||||
PDBG("Not implemented");
|
||||
throw Cpu_session::State_access_failed();
|
||||
throw Cpu_thread::State_access_failed();
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,6 +10,7 @@ SRC_CC = stack_area.cc \
|
||||
core_region_map.cc \
|
||||
cpu_session_component.cc \
|
||||
cpu_session_platform.cc \
|
||||
cpu_thread_component.cc \
|
||||
dataspace_component.cc \
|
||||
default_log.cc \
|
||||
dump_alloc.cc \
|
||||
@ -49,6 +50,7 @@ vpath ram_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath rom_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_support.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_thread_component.cc $(GEN_CORE_DIR)
|
||||
vpath pd_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath rpc_cap_factory.cc $(GEN_CORE_DIR)
|
||||
vpath pd_assign_pci.cc $(GEN_CORE_DIR)
|
||||
|
@ -9,6 +9,7 @@ SRC_CC += \
|
||||
rom_session_component.cc \
|
||||
cpu_session_component.cc \
|
||||
cpu_session_support.cc \
|
||||
cpu_thread_component.cc \
|
||||
pd_session_component.cc \
|
||||
rpc_cap_factory.cc \
|
||||
pd_assign_pci.cc \
|
||||
@ -47,6 +48,7 @@ vpath ram_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath rom_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_support.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_thread_component.cc $(GEN_CORE_DIR)
|
||||
vpath pd_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath pd_assign_pci.cc $(GEN_CORE_DIR)
|
||||
vpath pd_upgrade_ram_quota.cc $(GEN_CORE_DIR)
|
||||
|
@ -172,14 +172,14 @@ void Platform_thread::resume()
|
||||
void Platform_thread::state(Thread_state s)
|
||||
{
|
||||
PDBG("not implemented");
|
||||
throw Cpu_session::State_access_failed();
|
||||
throw Cpu_thread::State_access_failed();
|
||||
}
|
||||
|
||||
|
||||
Thread_state Platform_thread::state()
|
||||
{
|
||||
PDBG("not implemented");
|
||||
throw Cpu_session::State_access_failed();
|
||||
throw Cpu_thread::State_access_failed();
|
||||
}
|
||||
|
||||
|
||||
|
@ -152,6 +152,46 @@ struct Genode::Child_policy
|
||||
*/
|
||||
class Genode::Child : protected Rpc_object<Parent>
|
||||
{
|
||||
public:
|
||||
|
||||
struct Initial_thread_base
|
||||
{
|
||||
/**
|
||||
* Start execution at specified instruction pointer
|
||||
*/
|
||||
virtual void start(addr_t ip) = 0;
|
||||
|
||||
/**
|
||||
* Return capability of the initial thread
|
||||
*/
|
||||
virtual Capability<Cpu_thread> cap() = 0;
|
||||
};
|
||||
|
||||
struct Initial_thread : Initial_thread_base
|
||||
{
|
||||
private:
|
||||
|
||||
Cpu_session &_cpu;
|
||||
Thread_capability _cap;
|
||||
|
||||
public:
|
||||
|
||||
typedef Cpu_session::Name Name;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \throw Cpu_session::Thread_creation_failed
|
||||
* \throw Cpu_session::Out_of_metadata
|
||||
*/
|
||||
Initial_thread(Cpu_session &, Pd_session_capability, Name const &);
|
||||
~Initial_thread();
|
||||
|
||||
void start(addr_t) override;
|
||||
|
||||
Capability<Cpu_thread> cap() { return _cap; }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
class Session;
|
||||
@ -200,17 +240,11 @@ class Genode::Child : protected Rpc_object<Parent>
|
||||
|
||||
struct Process
|
||||
{
|
||||
struct Initial_thread
|
||||
{
|
||||
Cpu_session &cpu;
|
||||
Thread_capability cap;
|
||||
Initial_thread(Cpu_session &, Pd_session_capability, char const *);
|
||||
~Initial_thread();
|
||||
} initial_thread;
|
||||
|
||||
class Missing_dynamic_linker : Exception { };
|
||||
class Invalid_executable : Exception { };
|
||||
|
||||
Initial_thread_base &initial_thread;
|
||||
|
||||
struct Loaded_executable
|
||||
{
|
||||
/**
|
||||
@ -246,12 +280,9 @@ class Genode::Child : protected Rpc_object<Parent>
|
||||
*
|
||||
* \param ram RAM session used to allocate the BSS and
|
||||
* DATA segments for the new process
|
||||
* \param cpu CPU session used to create the initial thread
|
||||
* \param parent parent of the new protection domain
|
||||
* \param name name of protection domain
|
||||
*
|
||||
* \throw Cpu_session::Thread_creation_failed
|
||||
* \throw Cpu_session::Out_of_metadata
|
||||
* \throw Missing_dynamic_linker
|
||||
* \throw Invalid_executable
|
||||
* \throw Region_map::Attach_failed
|
||||
@ -272,11 +303,10 @@ class Genode::Child : protected Rpc_object<Parent>
|
||||
Pd_session_capability pd_cap,
|
||||
Pd_session &pd,
|
||||
Ram_session &ram,
|
||||
Cpu_session &cpu,
|
||||
Initial_thread_base &initial_thread,
|
||||
Region_map &local_rm,
|
||||
Region_map &remote_rm,
|
||||
Parent_capability parent,
|
||||
char const *name);
|
||||
Parent_capability parent);
|
||||
|
||||
~Process();
|
||||
};
|
||||
@ -327,39 +357,39 @@ class Genode::Child : protected Rpc_object<Parent>
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param elf_ds dataspace that contains the ELF binary
|
||||
* \param ldso_ds dataspace that contains the dynamic linker,
|
||||
* started if 'elf_ds' is a dynamically linked
|
||||
* executable
|
||||
* \param pd_cap capability of the new protection domain,
|
||||
* used as argument for creating the initial
|
||||
* thread, and handed out to the child as its
|
||||
* environment
|
||||
* \param pd PD session used for assigning the parent
|
||||
* capability of the new process
|
||||
* \param ram_cap RAM session capability handed out to the
|
||||
* child as its environment
|
||||
* \param ram RAM session used to allocate the BSS and
|
||||
* DATA segments and as backing store for the
|
||||
* local heap partition to keep child-specific
|
||||
* meta data
|
||||
* \param cpu_cap CPU session capability handed out to the
|
||||
* child as its environment
|
||||
* \param cpu CPU session for the new protection domain
|
||||
* \param local_rm local address space
|
||||
* \param remote_rm address space of new protection domain
|
||||
* \param pd_service provider of the 'pd' session
|
||||
* \param ram_service provider of the 'ram' session
|
||||
* \param cpu_service provider of the 'cpu' session
|
||||
* \param elf_ds dataspace that contains the ELF binary
|
||||
* \param ldso_ds dataspace that contains the dynamic linker,
|
||||
* started if 'elf_ds' is a dynamically linked
|
||||
* executable
|
||||
* \param pd_cap capability of the new protection domain,
|
||||
* used as argument for creating the initial
|
||||
* thread, and handed out to the child as its
|
||||
* environment
|
||||
* \param pd PD session used for assigning the parent
|
||||
* capability of the new process
|
||||
* \param ram_cap RAM session capability handed out to the
|
||||
* child as its environment
|
||||
* \param ram RAM session used to allocate the BSS and
|
||||
* DATA segments and as backing store for the
|
||||
* local heap partition to keep child-specific
|
||||
* meta data
|
||||
* \param cpu_cap CPU session capability handed out to the
|
||||
* child as its environment
|
||||
* \param initial_thread initial thread of the new protection domain
|
||||
* \param local_rm local address space
|
||||
* \param remote_rm address space of new protection domain
|
||||
* \param pd_service provider of the 'pd' session
|
||||
* \param ram_service provider of the 'ram' session
|
||||
* \param cpu_service provider of the 'cpu' session
|
||||
*
|
||||
* \throw Ram_session::Alloc_failed
|
||||
* \throw Process_startup_failed
|
||||
*
|
||||
* Usually, the pairs of 'pd' and 'pd_cap', 'cpu' and 'cpu_cap',
|
||||
* 'ram' and 'ram_cap' belong to each other. References to the
|
||||
* session interfaces are passed as separate arguments in addition
|
||||
* Usually, the pairs of 'pd' and 'pd_cap', 'initial_thread' and
|
||||
* 'cpu_cap', 'ram' and 'ram_cap' belong to each other. References to
|
||||
* the session interfaces are passed as separate arguments in addition
|
||||
* to the capabilities to allow the creator of a child to operate on
|
||||
* locally implemented sessions during the child initialization.
|
||||
* locally implemented interfaces during the child initialization.
|
||||
*
|
||||
* The 'ram_service', 'cpu_service', and 'pd_service' arguments are
|
||||
* needed to direct quota upgrades referring to the resources of
|
||||
@ -373,7 +403,7 @@ class Genode::Child : protected Rpc_object<Parent>
|
||||
Ram_session_capability ram_cap,
|
||||
Ram_session &ram,
|
||||
Cpu_session_capability cpu_cap,
|
||||
Cpu_session &cpu,
|
||||
Initial_thread_base &initial_thread,
|
||||
Region_map &local_rm,
|
||||
Region_map &remote_rm,
|
||||
Rpc_entrypoint &entrypoint,
|
||||
|
@ -30,54 +30,18 @@ struct Genode::Cpu_session_client : Rpc_client<Cpu_session>
|
||||
Affinity::Location affinity, Weight weight, addr_t utcb = 0) override {
|
||||
return call<Rpc_create_thread>(pd, name, affinity, weight, utcb); }
|
||||
|
||||
Ram_dataspace_capability utcb(Thread_capability thread) override {
|
||||
return call<Rpc_utcb>(thread); }
|
||||
|
||||
void kill_thread(Thread_capability thread) override {
|
||||
call<Rpc_kill_thread>(thread); }
|
||||
|
||||
int start(Thread_capability thread, addr_t ip, addr_t sp) override {
|
||||
return call<Rpc_start>(thread, ip, sp); }
|
||||
|
||||
void pause(Thread_capability thread) override {
|
||||
call<Rpc_pause>(thread); }
|
||||
|
||||
void resume(Thread_capability thread) override {
|
||||
call<Rpc_resume>(thread); }
|
||||
|
||||
void cancel_blocking(Thread_capability thread) override {
|
||||
call<Rpc_cancel_blocking>(thread); }
|
||||
|
||||
Thread_state state(Thread_capability thread) override {
|
||||
return call<Rpc_get_state>(thread); }
|
||||
|
||||
void state(Thread_capability thread, Thread_state const &state) override {
|
||||
call<Rpc_set_state>(thread, state); }
|
||||
|
||||
void exception_handler(Thread_capability thread, Signal_context_capability handler) override {
|
||||
call<Rpc_exception_handler>(thread, handler); }
|
||||
|
||||
void single_step(Thread_capability thread, bool enable) override {
|
||||
call<Rpc_single_step>(thread, enable); }
|
||||
void exception_sigh(Signal_context_capability sigh) override {
|
||||
call<Rpc_exception_sigh>(sigh); }
|
||||
|
||||
Affinity::Space affinity_space() const override {
|
||||
return call<Rpc_affinity_space>(); }
|
||||
|
||||
void affinity(Thread_capability thread, Affinity::Location location) override {
|
||||
call<Rpc_affinity>(thread, location); }
|
||||
|
||||
Dataspace_capability trace_control() override {
|
||||
return call<Rpc_trace_control>(); }
|
||||
|
||||
unsigned trace_control_index(Thread_capability thread) override {
|
||||
return call<Rpc_trace_control_index>(thread); }
|
||||
|
||||
Dataspace_capability trace_buffer(Thread_capability thread) override {
|
||||
return call<Rpc_trace_buffer>(thread); }
|
||||
|
||||
Dataspace_capability trace_policy(Thread_capability thread) override {
|
||||
return call<Rpc_trace_policy>(thread); }
|
||||
|
||||
int ref_account(Cpu_session_capability session) override {
|
||||
return call<Rpc_ref_account>(session); }
|
||||
|
||||
|
@ -15,15 +15,12 @@
|
||||
#define _INCLUDE__CPU_SESSION__CPU_SESSION_H_
|
||||
|
||||
#include <cpu_session/capability.h>
|
||||
#include <cpu_thread/cpu_thread.h>
|
||||
#include <base/stdint.h>
|
||||
#include <base/exception.h>
|
||||
#include <base/thread_state.h>
|
||||
#include <base/rpc_args.h>
|
||||
#include <base/signal.h>
|
||||
#include <base/affinity.h>
|
||||
#include <thread/capability.h>
|
||||
#include <session/session.h>
|
||||
#include <ram_session/ram_session.h>
|
||||
#include <dataspace/capability.h>
|
||||
#include <pd_session/pd_session.h>
|
||||
|
||||
namespace Genode { struct Cpu_session; }
|
||||
@ -36,7 +33,6 @@ struct Genode::Cpu_session : Session
|
||||
*********************/
|
||||
|
||||
class Thread_creation_failed : public Exception { };
|
||||
class State_access_failed : public Exception { };
|
||||
class Quota_exceeded : public Thread_creation_failed { };
|
||||
class Out_of_metadata : public Exception { };
|
||||
|
||||
@ -88,11 +84,6 @@ struct Genode::Cpu_session : Session
|
||||
Weight weight,
|
||||
addr_t utcb = 0) = 0;
|
||||
|
||||
/**
|
||||
* Get dataspace of the UTCB that is used by the specified thread
|
||||
*/
|
||||
virtual Ram_dataspace_capability utcb(Thread_capability thread) = 0;
|
||||
|
||||
/**
|
||||
* Kill an existing thread
|
||||
*
|
||||
@ -101,82 +92,16 @@ struct Genode::Cpu_session : Session
|
||||
virtual void kill_thread(Thread_capability thread) = 0;
|
||||
|
||||
/**
|
||||
* Modify instruction and stack pointer of thread - start the
|
||||
* thread
|
||||
* Register default signal handler for exceptions
|
||||
*
|
||||
* \param thread thread to start
|
||||
* \param ip initial instruction pointer
|
||||
* \param sp initial stack pointer
|
||||
*
|
||||
* \return 0 on success
|
||||
*/
|
||||
virtual int start(Thread_capability thread, addr_t ip, addr_t sp) = 0;
|
||||
|
||||
/**
|
||||
* Pause the specified thread
|
||||
*
|
||||
* After calling this method, the execution of the thread can be
|
||||
* continued by calling 'resume'.
|
||||
*/
|
||||
virtual void pause(Thread_capability thread) = 0;
|
||||
|
||||
/**
|
||||
* Resume the specified thread
|
||||
*/
|
||||
virtual void resume(Thread_capability thread) = 0;
|
||||
|
||||
/**
|
||||
* Cancel a currently blocking operation
|
||||
*
|
||||
* \param thread thread to unblock
|
||||
*/
|
||||
virtual void cancel_blocking(Thread_capability thread) = 0;
|
||||
|
||||
/**
|
||||
* Get the current state of a specific thread
|
||||
*
|
||||
* \param thread targeted thread
|
||||
* \return state of the targeted thread
|
||||
* \throw State_access_failed
|
||||
*/
|
||||
virtual Thread_state state(Thread_capability thread) = 0;
|
||||
|
||||
/**
|
||||
* Override the current state of a specific thread
|
||||
*
|
||||
* \param thread targeted thread
|
||||
* \param state state that shall be applied
|
||||
* \throw State_access_failed
|
||||
*/
|
||||
virtual void state(Thread_capability thread,
|
||||
Thread_state const &state) = 0;
|
||||
|
||||
/**
|
||||
* Register signal handler for exceptions of the specified thread
|
||||
*
|
||||
* If 'thread' is an invalid capability, the default exception
|
||||
* handler for the CPU session is set. This handler is used for
|
||||
* all threads that have no explicitly installed exception handler.
|
||||
* The new default signal handler will take effect for threads
|
||||
* created after the call.
|
||||
* This handler is used for all threads that have no explicitly installed
|
||||
* exception handler.
|
||||
*
|
||||
* On Linux, this exception is delivered when the process triggers
|
||||
* a SIGCHLD. On other platforms, this exception is delivered on
|
||||
* the occurrence of CPU exceptions such as division by zero.
|
||||
*/
|
||||
virtual void exception_handler(Thread_capability thread,
|
||||
Signal_context_capability handler) = 0;
|
||||
|
||||
/**
|
||||
* Enable/disable single stepping for specified thread.
|
||||
*
|
||||
* Since this method is currently supported by a small number of
|
||||
* platforms, we provide a default implementation
|
||||
*
|
||||
* \param thread thread to set into single step mode
|
||||
* \param enable true = enable single-step mode; false = disable
|
||||
*/
|
||||
virtual void single_step(Thread_capability, bool) {}
|
||||
virtual void exception_sigh(Signal_context_capability) = 0;
|
||||
|
||||
/**
|
||||
* Return affinity space of CPU nodes available to the CPU session
|
||||
@ -186,17 +111,6 @@ struct Genode::Cpu_session : Session
|
||||
*/
|
||||
virtual Affinity::Space affinity_space() const = 0;
|
||||
|
||||
/**
|
||||
* Define affinity of thread to one or multiple CPU nodes
|
||||
*
|
||||
* In the normal case, a thread is assigned to a single CPU.
|
||||
* Specifying more than one CPU node is supposed to principally
|
||||
* allow a CPU service to balance the load of threads among
|
||||
* multiple CPUs.
|
||||
*/
|
||||
virtual void affinity(Thread_capability thread,
|
||||
Affinity::Location affinity) = 0;
|
||||
|
||||
/**
|
||||
* Translate generic priority value to kernel-specific priority levels
|
||||
*
|
||||
@ -234,31 +148,6 @@ struct Genode::Cpu_session : Session
|
||||
*/
|
||||
virtual Dataspace_capability trace_control() = 0;
|
||||
|
||||
/**
|
||||
* Request index of a trace control block for given thread
|
||||
*
|
||||
* The trace control dataspace contains the control blocks for
|
||||
* all threads of the CPU session. Each thread gets assigned a
|
||||
* different index by the CPU service.
|
||||
*/
|
||||
virtual unsigned trace_control_index(Thread_capability thread) = 0;
|
||||
|
||||
/**
|
||||
* Request trace buffer for the specified thread
|
||||
*
|
||||
* The trace buffer is not accounted to the CPU session. It is
|
||||
* owned by a TRACE session.
|
||||
*/
|
||||
virtual Dataspace_capability trace_buffer(Thread_capability thread) = 0;
|
||||
|
||||
/**
|
||||
* Request trace policy
|
||||
*
|
||||
* The trace policy buffer is not accounted to the CPU session. It
|
||||
* is owned by a TRACE session.
|
||||
*/
|
||||
virtual Dataspace_capability trace_policy(Thread_capability thread) = 0;
|
||||
|
||||
/**
|
||||
* Define reference account for the CPU session
|
||||
*
|
||||
@ -329,27 +218,10 @@ struct Genode::Cpu_session : Session
|
||||
GENODE_TYPE_LIST(Thread_creation_failed, Out_of_metadata),
|
||||
Capability<Pd_session>, Name const &, Affinity::Location,
|
||||
Weight, addr_t);
|
||||
GENODE_RPC(Rpc_utcb, Ram_dataspace_capability, utcb, Thread_capability);
|
||||
GENODE_RPC(Rpc_kill_thread, void, kill_thread, Thread_capability);
|
||||
GENODE_RPC(Rpc_start, int, start, Thread_capability, addr_t, addr_t);
|
||||
GENODE_RPC(Rpc_pause, void, pause, Thread_capability);
|
||||
GENODE_RPC(Rpc_resume, void, resume, Thread_capability);
|
||||
GENODE_RPC(Rpc_cancel_blocking, void, cancel_blocking, Thread_capability);
|
||||
GENODE_RPC_THROW(Rpc_get_state, Thread_state, state,
|
||||
GENODE_TYPE_LIST(State_access_failed),
|
||||
Thread_capability);
|
||||
GENODE_RPC_THROW(Rpc_set_state, void, state,
|
||||
GENODE_TYPE_LIST(State_access_failed),
|
||||
Thread_capability, Thread_state const &);
|
||||
GENODE_RPC(Rpc_exception_handler, void, exception_handler,
|
||||
Thread_capability, Signal_context_capability);
|
||||
GENODE_RPC(Rpc_single_step, void, single_step, Thread_capability, bool);
|
||||
GENODE_RPC(Rpc_exception_sigh, void, exception_sigh, Signal_context_capability);
|
||||
GENODE_RPC(Rpc_affinity_space, Affinity::Space, affinity_space);
|
||||
GENODE_RPC(Rpc_affinity, void, affinity, Thread_capability, Affinity::Location);
|
||||
GENODE_RPC(Rpc_trace_control, Dataspace_capability, trace_control);
|
||||
GENODE_RPC(Rpc_trace_control_index, unsigned, trace_control_index, Thread_capability);
|
||||
GENODE_RPC(Rpc_trace_buffer, Dataspace_capability, trace_buffer, Thread_capability);
|
||||
GENODE_RPC(Rpc_trace_policy, Dataspace_capability, trace_policy, Thread_capability);
|
||||
GENODE_RPC(Rpc_ref_account, int, ref_account, Cpu_session_capability);
|
||||
GENODE_RPC(Rpc_transfer_quota, int, transfer_quota, Cpu_session_capability, size_t);
|
||||
GENODE_RPC(Rpc_quota, Quota, quota);
|
||||
@ -364,30 +236,19 @@ struct Genode::Cpu_session : Session
|
||||
* of employing the convenience macro 'GENODE_RPC_INTERFACE'.
|
||||
*/
|
||||
typedef Meta::Type_tuple<Rpc_create_thread,
|
||||
Meta::Type_tuple<Rpc_utcb,
|
||||
Meta::Type_tuple<Rpc_kill_thread,
|
||||
Meta::Type_tuple<Rpc_start,
|
||||
Meta::Type_tuple<Rpc_pause,
|
||||
Meta::Type_tuple<Rpc_resume,
|
||||
Meta::Type_tuple<Rpc_cancel_blocking,
|
||||
Meta::Type_tuple<Rpc_set_state,
|
||||
Meta::Type_tuple<Rpc_get_state,
|
||||
Meta::Type_tuple<Rpc_exception_handler,
|
||||
Meta::Type_tuple<Rpc_single_step,
|
||||
Meta::Type_tuple<Rpc_exception_sigh,
|
||||
Meta::Type_tuple<Rpc_affinity_space,
|
||||
Meta::Type_tuple<Rpc_affinity,
|
||||
Meta::Type_tuple<Rpc_trace_control,
|
||||
Meta::Type_tuple<Rpc_trace_control_index,
|
||||
Meta::Type_tuple<Rpc_trace_buffer,
|
||||
Meta::Type_tuple<Rpc_trace_policy,
|
||||
Meta::Type_tuple<Rpc_ref_account,
|
||||
Meta::Type_tuple<Rpc_transfer_quota,
|
||||
Meta::Type_tuple<Rpc_quota,
|
||||
Meta::Type_tuple<Rpc_native_cpu,
|
||||
Meta::Empty>
|
||||
> > > > > > > > > > > > > > > > > > > > Rpc_functions;
|
||||
> > > > > > > > Rpc_functions;
|
||||
};
|
||||
|
||||
|
||||
struct Genode::Cpu_session::Quota
|
||||
{
|
||||
size_t super_period_us;
|
||||
|
22
repos/base/include/cpu_thread/capability.h
Normal file
22
repos/base/include/cpu_thread/capability.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* \brief Thread capability type
|
||||
* \author Norman Feske
|
||||
* \date 2016-05-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__CPU_THREAD__CAPABILITY_H_
|
||||
#define _INCLUDE__CPU_THREAD__CAPABILITY_H_
|
||||
|
||||
#include <cpu_thread/cpu_thread.h>
|
||||
#include <base/capability.h>
|
||||
|
||||
namespace Genode { typedef Capability<Cpu_thread> Cpu_thread_capability; }
|
||||
|
||||
#endif /* _INCLUDE__CPU_THREAD__CAPABILITY_H_ */
|
68
repos/base/include/cpu_thread/client.h
Normal file
68
repos/base/include/cpu_thread/client.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* \brief Client-side CPU thread interface
|
||||
* \author Norman Feske
|
||||
* \date 2016-05-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__CPU_THREAD__CLIENT_H_
|
||||
#define _INCLUDE__CPU_THREAD__CLIENT_H_
|
||||
|
||||
#include <cpu_thread/cpu_thread.h>
|
||||
#include <base/rpc_client.h>
|
||||
|
||||
namespace Genode { struct Cpu_thread_client; }
|
||||
|
||||
|
||||
struct Genode::Cpu_thread_client : Rpc_client<Cpu_thread>
|
||||
{
|
||||
explicit Cpu_thread_client(Thread_capability cap)
|
||||
: Rpc_client<Cpu_thread>(cap) { }
|
||||
|
||||
Dataspace_capability utcb() override {
|
||||
return call<Rpc_utcb>(); }
|
||||
|
||||
void start(addr_t ip, addr_t sp) override {
|
||||
call<Rpc_start>(ip, sp); }
|
||||
|
||||
void pause() override {
|
||||
call<Rpc_pause>(); }
|
||||
|
||||
void resume() override {
|
||||
call<Rpc_resume>(); }
|
||||
|
||||
void cancel_blocking() override {
|
||||
call<Rpc_cancel_blocking>(); }
|
||||
|
||||
Thread_state state() override {
|
||||
return call<Rpc_get_state>(); }
|
||||
|
||||
void state(Thread_state const &state) override {
|
||||
call<Rpc_set_state>(state); }
|
||||
|
||||
void exception_sigh(Signal_context_capability handler) override {
|
||||
call<Rpc_exception_sigh>(handler); }
|
||||
|
||||
void single_step(bool enabled) override {
|
||||
call<Rpc_single_step>(enabled); }
|
||||
|
||||
void affinity(Affinity::Location location) override {
|
||||
call<Rpc_affinity>(location); }
|
||||
|
||||
unsigned trace_control_index() override {
|
||||
return call<Rpc_trace_control_index>(); }
|
||||
|
||||
Dataspace_capability trace_buffer() override {
|
||||
return call<Rpc_trace_buffer>(); }
|
||||
|
||||
Dataspace_capability trace_policy() override {
|
||||
return call<Rpc_trace_policy>(); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__CPU_THREAD__CLIENT_H_ */
|
182
repos/base/include/cpu_thread/cpu_thread.h
Normal file
182
repos/base/include/cpu_thread/cpu_thread.h
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* \brief CPU thread interface
|
||||
* \author Norman Feske
|
||||
* \date 2016-05-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__CPU_THREAD__CPU_THREAD_H_
|
||||
#define _INCLUDE__CPU_THREAD__CPU_THREAD_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
#include <base/exception.h>
|
||||
#include <base/thread_state.h>
|
||||
#include <base/signal.h>
|
||||
#include <base/affinity.h>
|
||||
#include <dataspace/capability.h>
|
||||
|
||||
namespace Genode { struct Cpu_thread; }
|
||||
|
||||
|
||||
struct Genode::Cpu_thread
|
||||
{
|
||||
class State_access_failed : public Exception { };
|
||||
|
||||
/**
|
||||
* Get dataspace of the thread's user-level thread-control block (UTCB)
|
||||
*/
|
||||
virtual Dataspace_capability utcb() = 0;
|
||||
|
||||
/**
|
||||
* Modify instruction and stack pointer of thread - start the thread
|
||||
*
|
||||
* \param thread thread to start
|
||||
* \param ip initial instruction pointer
|
||||
* \param sp initial stack pointer
|
||||
*/
|
||||
virtual void start(addr_t ip, addr_t sp) = 0;
|
||||
|
||||
/**
|
||||
* Pause the thread
|
||||
*
|
||||
* After calling this method, the execution of the thread can be
|
||||
* continued by calling 'resume'.
|
||||
*/
|
||||
virtual void pause() = 0;
|
||||
|
||||
/**
|
||||
* Resume the thread
|
||||
*/
|
||||
virtual void resume() = 0;
|
||||
|
||||
/**
|
||||
* Cancel a currently blocking operation
|
||||
*/
|
||||
virtual void cancel_blocking() = 0;
|
||||
|
||||
/**
|
||||
* Get the current thread state
|
||||
*
|
||||
* \return state of the targeted thread
|
||||
* \throw State_access_failed
|
||||
*/
|
||||
virtual Thread_state state() = 0;
|
||||
|
||||
/**
|
||||
* Override the current thread state
|
||||
*
|
||||
* \param state state that shall be applied
|
||||
* \throw State_access_failed
|
||||
*/
|
||||
virtual void state(Thread_state const &state) = 0;
|
||||
|
||||
/**
|
||||
* Register signal handler for exceptions of the thread
|
||||
*
|
||||
* On Linux, this exception is delivered when the process triggers
|
||||
* a SIGCHLD. On other platforms, this exception is delivered on
|
||||
* the occurrence of CPU exceptions such as division by zero.
|
||||
*/
|
||||
virtual void exception_sigh(Signal_context_capability handler) = 0;
|
||||
|
||||
/**
|
||||
* Enable/disable single stepping
|
||||
*
|
||||
* Since this method is currently supported by a small number of
|
||||
* platforms, we provide a default implementation
|
||||
*
|
||||
* \param enabled true = enable single-step mode; false = disable
|
||||
*/
|
||||
virtual void single_step(bool enabled) = 0;
|
||||
|
||||
/**
|
||||
* Define affinity of thread to one or multiple CPU nodes
|
||||
*
|
||||
* In the normal case, a thread is assigned to a single CPU. Specifying
|
||||
* more than one CPU node is supposed to principally allow a CPU service to
|
||||
* balance the load of threads among multiple CPUs.
|
||||
*
|
||||
* \param location location within the affinity space of the thread's
|
||||
* CPU session
|
||||
*/
|
||||
virtual void affinity(Affinity::Location location) = 0;
|
||||
|
||||
/**
|
||||
* Request index within the trace control block of the thread's CPU session
|
||||
*
|
||||
* The trace control dataspace contains the control blocks for all threads
|
||||
* of the CPU session. Each thread gets assigned a different index by the
|
||||
* CPU service.
|
||||
*/
|
||||
virtual unsigned trace_control_index() = 0;
|
||||
|
||||
/**
|
||||
* Request trace buffer for the thread
|
||||
*
|
||||
* The trace buffer is not accounted to the CPU session. It is owned by a
|
||||
* TRACE session.
|
||||
*/
|
||||
virtual Dataspace_capability trace_buffer() = 0;
|
||||
|
||||
/**
|
||||
* Request trace policy
|
||||
*
|
||||
* The trace policy buffer is not accounted to the CPU session. It is owned
|
||||
* by a TRACE session.
|
||||
*/
|
||||
virtual Dataspace_capability trace_policy() = 0;
|
||||
|
||||
|
||||
/*********************
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
GENODE_RPC(Rpc_utcb, Dataspace_capability, utcb);
|
||||
GENODE_RPC(Rpc_start, void, start, addr_t, addr_t);
|
||||
GENODE_RPC(Rpc_pause, void, pause);
|
||||
GENODE_RPC(Rpc_resume, void, resume);
|
||||
GENODE_RPC(Rpc_cancel_blocking, void, cancel_blocking);
|
||||
GENODE_RPC_THROW(Rpc_get_state, Thread_state, state,
|
||||
GENODE_TYPE_LIST(State_access_failed));
|
||||
GENODE_RPC_THROW(Rpc_set_state, void, state,
|
||||
GENODE_TYPE_LIST(State_access_failed),
|
||||
Thread_state const &);
|
||||
GENODE_RPC(Rpc_exception_sigh, void, exception_sigh, Signal_context_capability);
|
||||
GENODE_RPC(Rpc_single_step, void, single_step, bool);
|
||||
GENODE_RPC(Rpc_affinity, void, affinity, Affinity::Location);
|
||||
GENODE_RPC(Rpc_trace_control_index, unsigned, trace_control_index);
|
||||
GENODE_RPC(Rpc_trace_buffer, Dataspace_capability, trace_buffer);
|
||||
GENODE_RPC(Rpc_trace_policy, Dataspace_capability, trace_policy);
|
||||
|
||||
/*
|
||||
* 'GENODE_RPC_INTERFACE' declaration done manually
|
||||
*
|
||||
* The number of RPC functions of this interface exceeds the maximum
|
||||
* number of elements supported by 'Meta::Type_list'. Therefore, we
|
||||
* construct the type list by hand using nested type tuples instead
|
||||
* of employing the convenience macro 'GENODE_RPC_INTERFACE'.
|
||||
*/
|
||||
typedef Meta::Type_tuple<Rpc_utcb,
|
||||
Meta::Type_tuple<Rpc_start,
|
||||
Meta::Type_tuple<Rpc_pause,
|
||||
Meta::Type_tuple<Rpc_resume,
|
||||
Meta::Type_tuple<Rpc_cancel_blocking,
|
||||
Meta::Type_tuple<Rpc_set_state,
|
||||
Meta::Type_tuple<Rpc_get_state,
|
||||
Meta::Type_tuple<Rpc_exception_sigh,
|
||||
Meta::Type_tuple<Rpc_single_step,
|
||||
Meta::Type_tuple<Rpc_affinity,
|
||||
Meta::Type_tuple<Rpc_trace_control_index,
|
||||
Meta::Type_tuple<Rpc_trace_buffer,
|
||||
Meta::Type_tuple<Rpc_trace_policy,
|
||||
Meta::Empty>
|
||||
> > > > > > > > > > > > Rpc_functions;
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__CPU_THREAD__CPU_THREAD_H_ */
|
@ -2,6 +2,8 @@
|
||||
* \brief Thread capability type
|
||||
* \author Norman Feske
|
||||
* \date 2008-08-16
|
||||
*
|
||||
* \deprecated Use cpu_thread/capability.h instead
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -14,16 +16,8 @@
|
||||
#ifndef _INCLUDE__THREAD__CAPABILITY_H_
|
||||
#define _INCLUDE__THREAD__CAPABILITY_H_
|
||||
|
||||
#include <base/capability.h>
|
||||
#include <cpu_thread/capability.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/*
|
||||
* The 'Thread_capability' type is created by the CPU session.
|
||||
* Hence, we use the CPU session's 'Cpu_thread' as association.
|
||||
*/
|
||||
class Cpu_thread;
|
||||
typedef Capability<Cpu_thread> Thread_capability;
|
||||
}
|
||||
namespace Genode { typedef Cpu_thread_capability Thread_capability; }
|
||||
|
||||
#endif /* _INCLUDE__THREAD__CAPABILITY_H_ */
|
||||
|
@ -27,12 +27,6 @@ using namespace Genode;
|
||||
|
||||
static constexpr bool verbose = false;
|
||||
|
||||
void Cpu_thread_component::update_exception_sigh()
|
||||
{
|
||||
if (platform_thread()->pager())
|
||||
platform_thread()->pager()->exception_handler(_sigh);
|
||||
};
|
||||
|
||||
|
||||
Thread_capability Cpu_session_component::create_thread(Capability<Pd_session> pd_cap,
|
||||
Name const &name,
|
||||
@ -54,6 +48,7 @@ Thread_capability Cpu_session_component::create_thread(Capability<Pd_session> pd
|
||||
name.string(), weight.value, QUOTA_LIMIT);
|
||||
weight = Weight(QUOTA_LIMIT);
|
||||
}
|
||||
|
||||
Lock::Guard thread_list_lock_guard(_thread_list_lock);
|
||||
_incr_weight(weight.value);
|
||||
|
||||
@ -69,18 +64,18 @@ Thread_capability Cpu_session_component::create_thread(Capability<Pd_session> pd
|
||||
thread = new (&_thread_alloc)
|
||||
Cpu_thread_component(
|
||||
cap(), *_thread_ep, *_pager_ep, *pd, _trace_control_area,
|
||||
weight, _weight_to_quota(weight.value),
|
||||
_trace_sources, weight, _weight_to_quota(weight.value),
|
||||
_thread_affinity(affinity), _label, thread_name,
|
||||
_priority, utcb, _default_exception_handler);
|
||||
_priority, utcb);
|
||||
};
|
||||
|
||||
try { _thread_ep->apply(pd_cap, create_thread_lambda); }
|
||||
catch (Region_map::Out_of_metadata) { throw Out_of_metadata(); }
|
||||
catch (Allocator::Out_of_memory) { throw Out_of_metadata(); }
|
||||
|
||||
_thread_list.insert(thread);
|
||||
thread->session_exception_sigh(_exception_sigh);
|
||||
|
||||
_trace_sources.insert(thread->trace_source());
|
||||
_thread_list.insert(thread);
|
||||
|
||||
return thread->cap();
|
||||
}
|
||||
@ -114,8 +109,6 @@ void Cpu_session_component::_unsynchronized_kill_thread(Thread_capability thread
|
||||
|
||||
_thread_list.remove(thread);
|
||||
|
||||
_trace_sources.remove(thread->trace_source());
|
||||
|
||||
_decr_weight(thread->weight());
|
||||
|
||||
{
|
||||
@ -133,118 +126,14 @@ void Cpu_session_component::kill_thread(Thread_capability thread_cap)
|
||||
}
|
||||
|
||||
|
||||
int Cpu_session_component::start(Thread_capability thread_cap,
|
||||
addr_t ip, addr_t sp)
|
||||
void Cpu_session_component::exception_sigh(Signal_context_capability sigh)
|
||||
{
|
||||
auto lambda = [&] (Cpu_thread_component *thread) {
|
||||
if (!thread) return -1;
|
||||
_exception_sigh = sigh;
|
||||
|
||||
/*
|
||||
* If an exception handler was installed prior to the call of 'set_pager',
|
||||
* we need to update the pager object with the current exception handler.
|
||||
*/
|
||||
thread->update_exception_sigh();
|
||||
Lock::Guard lock_guard(_thread_list_lock);
|
||||
|
||||
return thread->platform_thread()->start((void *)ip, (void *)sp);
|
||||
};
|
||||
return _thread_ep->apply(thread_cap, lambda);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_session_component::pause(Thread_capability thread_cap)
|
||||
{
|
||||
auto lambda = [this] (Cpu_thread_component *thread) {
|
||||
if (!thread) return;
|
||||
|
||||
thread->platform_thread()->pause();
|
||||
};
|
||||
_thread_ep->apply(thread_cap, lambda);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_session_component::single_step(Thread_capability thread_cap, bool enabled)
|
||||
{
|
||||
auto lambda = [this, enabled] (Cpu_thread_component *thread) {
|
||||
if (!thread) return;
|
||||
|
||||
thread->platform_thread()->single_step(enabled);
|
||||
};
|
||||
_thread_ep->apply(thread_cap, lambda);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_session_component::resume(Thread_capability thread_cap)
|
||||
{
|
||||
auto lambda = [this] (Cpu_thread_component *thread) {
|
||||
if (!thread) return;
|
||||
|
||||
thread->platform_thread()->resume();
|
||||
};
|
||||
_thread_ep->apply(thread_cap, lambda);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_session_component::cancel_blocking(Thread_capability thread_cap)
|
||||
{
|
||||
auto lambda = [this] (Cpu_thread_component *thread) {
|
||||
if (!thread) return;
|
||||
|
||||
thread->platform_thread()->cancel_blocking();
|
||||
};
|
||||
_thread_ep->apply(thread_cap, lambda);
|
||||
}
|
||||
|
||||
|
||||
Thread_state Cpu_session_component::state(Thread_capability thread_cap)
|
||||
{
|
||||
auto lambda = [this] (Cpu_thread_component *thread) {
|
||||
if (!thread) throw State_access_failed();
|
||||
|
||||
return thread->platform_thread()->state();
|
||||
};
|
||||
return _thread_ep->apply(thread_cap, lambda);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_session_component::state(Thread_capability thread_cap,
|
||||
Thread_state const &state)
|
||||
{
|
||||
auto lambda = [&] (Cpu_thread_component *thread) {
|
||||
if (!thread) throw State_access_failed();
|
||||
|
||||
thread->platform_thread()->state(state);
|
||||
};
|
||||
_thread_ep->apply(thread_cap, lambda);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Cpu_session_component::exception_handler(Thread_capability thread_cap,
|
||||
Signal_context_capability sigh_cap)
|
||||
{
|
||||
/*
|
||||
* By specifying an invalid thread capability, the caller sets the default
|
||||
* exception handler for the CPU session.
|
||||
*/
|
||||
if (!thread_cap.valid()) {
|
||||
_default_exception_handler = sigh_cap;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If an invalid signal handler is specified for a valid thread, we revert
|
||||
* the signal handler to the CPU session's default signal handler.
|
||||
*/
|
||||
if (!sigh_cap.valid()) {
|
||||
sigh_cap = _default_exception_handler;
|
||||
}
|
||||
|
||||
auto lambda = [&] (Cpu_thread_component *thread) {
|
||||
if (!thread) return;
|
||||
|
||||
thread->sigh(sigh_cap);
|
||||
};
|
||||
_thread_ep->apply(thread_cap, lambda);
|
||||
for (Cpu_thread_component *t = _thread_list.first(); t; t = t->next())
|
||||
t->session_exception_sigh(_exception_sigh);
|
||||
}
|
||||
|
||||
|
||||
@ -258,57 +147,12 @@ Affinity::Space Cpu_session_component::affinity_space() const
|
||||
}
|
||||
|
||||
|
||||
void Cpu_session_component::affinity(Thread_capability thread_cap,
|
||||
Affinity::Location location)
|
||||
{
|
||||
auto lambda = [&] (Cpu_thread_component *thread) {
|
||||
if (!thread) return;
|
||||
|
||||
thread->affinity(_thread_affinity(location));
|
||||
};
|
||||
_thread_ep->apply(thread_cap, lambda);
|
||||
}
|
||||
|
||||
|
||||
Dataspace_capability Cpu_session_component::trace_control()
|
||||
{
|
||||
return _trace_control_area.dataspace();
|
||||
}
|
||||
|
||||
|
||||
unsigned Cpu_session_component::trace_control_index(Thread_capability thread_cap)
|
||||
{
|
||||
auto lambda = [] (Cpu_thread_component *thread) -> unsigned {
|
||||
if (!thread) return 0;
|
||||
|
||||
return thread->trace_control_index();
|
||||
};
|
||||
return _thread_ep->apply(thread_cap, lambda);
|
||||
}
|
||||
|
||||
|
||||
Dataspace_capability Cpu_session_component::trace_buffer(Thread_capability thread_cap)
|
||||
{
|
||||
auto lambda = [this] (Cpu_thread_component *thread) {
|
||||
if (!thread) return Dataspace_capability();
|
||||
|
||||
return thread->trace_source()->buffer();
|
||||
};
|
||||
return _thread_ep->apply(thread_cap, lambda);
|
||||
}
|
||||
|
||||
|
||||
Dataspace_capability Cpu_session_component::trace_policy(Thread_capability thread_cap)
|
||||
{
|
||||
auto lambda = [this] (Cpu_thread_component *thread) {
|
||||
if (!thread) return Dataspace_capability();
|
||||
|
||||
return thread->trace_source()->policy();
|
||||
};
|
||||
return _thread_ep->apply(thread_cap, lambda);
|
||||
}
|
||||
|
||||
|
||||
static size_t remaining_session_ram_quota(char const *args)
|
||||
{
|
||||
/*
|
||||
@ -472,9 +316,9 @@ void Cpu_session_component::_deinit_threads()
|
||||
|
||||
|
||||
void Cpu_session_component::
|
||||
_update_thread_quota(Cpu_thread_component * const thread) const
|
||||
_update_thread_quota(Cpu_thread_component &thread) const
|
||||
{
|
||||
thread->platform_thread()->quota(_weight_to_quota(thread->weight()));
|
||||
thread.quota(_weight_to_quota(thread.weight()));
|
||||
}
|
||||
|
||||
|
||||
@ -511,12 +355,11 @@ void Cpu_session_component::_incr_quota(size_t const quota)
|
||||
void Cpu_session_component::_update_each_thread_quota()
|
||||
{
|
||||
Cpu_thread_component * thread = _thread_list.first();
|
||||
for (; thread; thread = thread->next()) { _update_thread_quota(thread); }
|
||||
for (; thread; thread = thread->next()) { _update_thread_quota(*thread); }
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
Cpu_session_component::_weight_to_quota(size_t const weight) const {
|
||||
size_t Cpu_session_component::_weight_to_quota(size_t const weight) const {
|
||||
return (weight * _quota) / _weight; }
|
||||
|
||||
|
||||
|
@ -14,16 +14,16 @@
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
|
||||
/* Core includes */
|
||||
/* core includes */
|
||||
#include <cpu_session_component.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability thread_cap)
|
||||
Dataspace_capability Cpu_thread_component::utcb()
|
||||
{
|
||||
PERR("%s: Not implemented", __PRETTY_FUNCTION__);
|
||||
return Ram_dataspace_capability();
|
||||
return Dataspace_capability();
|
||||
}
|
||||
|
||||
|
||||
|
113
repos/base/src/core/cpu_thread_component.cc
Normal file
113
repos/base/src/core/cpu_thread_component.cc
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* \brief Core implementation of the CPU thread interface
|
||||
* \author Norman Feske
|
||||
* \date 2016-05-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <cpu_thread_component.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
void Cpu_thread_component::_update_exception_sigh()
|
||||
{
|
||||
Signal_context_capability sigh = _thread_sigh.valid()
|
||||
? _thread_sigh : _session_sigh;
|
||||
if (_platform_thread.pager())
|
||||
_platform_thread.pager()->exception_handler(sigh);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_thread_component::quota(size_t quota)
|
||||
{
|
||||
_platform_thread.quota(quota);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_thread_component::session_exception_sigh(Signal_context_capability sigh)
|
||||
{
|
||||
_session_sigh = sigh;
|
||||
_update_exception_sigh();
|
||||
}
|
||||
|
||||
|
||||
void Cpu_thread_component::start(addr_t ip, addr_t sp)
|
||||
{
|
||||
_platform_thread.start((void *)ip, (void *)sp);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_thread_component::pause()
|
||||
{
|
||||
_platform_thread.pause();
|
||||
}
|
||||
|
||||
|
||||
void Cpu_thread_component::single_step(bool enabled)
|
||||
{
|
||||
_platform_thread.single_step(enabled);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_thread_component::resume()
|
||||
{
|
||||
_platform_thread.resume();
|
||||
}
|
||||
|
||||
|
||||
void Cpu_thread_component::cancel_blocking()
|
||||
{
|
||||
_platform_thread.cancel_blocking();
|
||||
}
|
||||
|
||||
|
||||
Thread_state Cpu_thread_component::state()
|
||||
{
|
||||
return _platform_thread.state();
|
||||
}
|
||||
|
||||
|
||||
void Cpu_thread_component::state(Thread_state const &state)
|
||||
{
|
||||
_platform_thread.state(state);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_thread_component::exception_sigh(Signal_context_capability sigh)
|
||||
{
|
||||
_thread_sigh = sigh;
|
||||
_update_exception_sigh();
|
||||
}
|
||||
|
||||
|
||||
void Cpu_thread_component::affinity(Affinity::Location location)
|
||||
{
|
||||
_platform_thread.affinity(location);
|
||||
}
|
||||
|
||||
|
||||
unsigned Cpu_thread_component::trace_control_index()
|
||||
{
|
||||
return _trace_control_slot.index;
|
||||
}
|
||||
|
||||
|
||||
Dataspace_capability Cpu_thread_component::trace_buffer()
|
||||
{
|
||||
return _trace_source.buffer();
|
||||
}
|
||||
|
||||
|
||||
Dataspace_capability Cpu_thread_component::trace_policy()
|
||||
{
|
||||
return _trace_source.policy();
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <pager.h>
|
||||
#include <cpu_thread_component.h>
|
||||
#include <cpu_thread_allocator.h>
|
||||
#include <pd_session_component.h>
|
||||
#include <platform_thread.h>
|
||||
@ -30,342 +31,145 @@
|
||||
#include <trace/source_registry.h>
|
||||
#include <native_cpu_component.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* RPC interface of CPU thread
|
||||
*
|
||||
* We make 'Cpu_thread' a RPC object only to be able to lookup CPU threads
|
||||
* from thread capabilities supplied as arguments to CPU-session functions.
|
||||
* A CPU thread does not provide an actual RPC interface.
|
||||
*/
|
||||
struct Cpu_thread
|
||||
{
|
||||
GENODE_RPC_INTERFACE();
|
||||
};
|
||||
namespace Genode { class Cpu_session_component; }
|
||||
|
||||
|
||||
class Cpu_thread_component : public Rpc_object<Cpu_thread>,
|
||||
public List<Cpu_thread_component>::Element,
|
||||
public Trace::Source::Info_accessor
|
||||
{
|
||||
public:
|
||||
class Genode::Cpu_session_component : public Rpc_object<Cpu_session>,
|
||||
public List<Cpu_session_component>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Trace::Session_label Session_label;
|
||||
typedef Trace::Thread_name Thread_name;
|
||||
typedef Cpu_thread_component::Session_label Session_label;
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
Rpc_entrypoint &_ep;
|
||||
Pager_entrypoint &_pager_ep;
|
||||
Capability<Pd_session> _pd;
|
||||
Region_map_component &_address_space_region_map;
|
||||
Cpu_session::Weight const _weight;
|
||||
Session_label const _session_label;
|
||||
Thread_name const _name;
|
||||
Platform_thread _platform_thread;
|
||||
bool const _bound_to_pd;
|
||||
Session_label _label;
|
||||
Rpc_entrypoint * const _session_ep;
|
||||
Rpc_entrypoint *_thread_ep;
|
||||
Pager_entrypoint *_pager_ep;
|
||||
Allocator_guard _md_alloc; /* guarded meta-data allocator */
|
||||
Cpu_thread_allocator _thread_alloc; /* meta-data allocator */
|
||||
Lock _thread_alloc_lock; /* protect allocator access */
|
||||
List<Cpu_thread_component> _thread_list;
|
||||
Lock _thread_list_lock; /* protect thread list */
|
||||
unsigned _priority; /* priority of threads
|
||||
created with this
|
||||
session */
|
||||
Affinity::Location _location; /* CPU affinity of this
|
||||
session */
|
||||
Trace::Source_registry &_trace_sources;
|
||||
Trace::Control_area _trace_control_area;
|
||||
|
||||
bool _bind_to_pd(Pd_session_component &pd)
|
||||
{
|
||||
if (!pd.bind_thread(_platform_thread))
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* Members for quota accounting
|
||||
*/
|
||||
|
||||
Signal_context_capability _sigh; /* exception handler */
|
||||
size_t _weight;
|
||||
size_t _quota;
|
||||
Cpu_session_component * _ref;
|
||||
List<Cpu_session_component> _ref_members;
|
||||
Lock _ref_members_lock;
|
||||
|
||||
struct Trace_control_slot
|
||||
{
|
||||
unsigned index = 0;
|
||||
Trace::Control_area &trace_control_area;
|
||||
Native_cpu_component _native_cpu;
|
||||
|
||||
Trace_control_slot(Trace::Control_area &trace_control_area)
|
||||
: trace_control_area(trace_control_area)
|
||||
{
|
||||
if (!trace_control_area.alloc(index))
|
||||
throw Cpu_session::Out_of_metadata();
|
||||
}
|
||||
friend class Native_cpu_component;
|
||||
|
||||
~Trace_control_slot()
|
||||
{
|
||||
trace_control_area.free(index);
|
||||
}
|
||||
/*
|
||||
* Utilities for quota accounting
|
||||
*/
|
||||
|
||||
Trace::Control &control()
|
||||
{
|
||||
return *trace_control_area.at(index);
|
||||
}
|
||||
};
|
||||
void _incr_weight(size_t const weight);
|
||||
void _decr_weight(size_t const weight);
|
||||
size_t _weight_to_quota(size_t const weight) const;
|
||||
void _decr_quota(size_t const quota);
|
||||
void _incr_quota(size_t const quota);
|
||||
void _update_thread_quota(Cpu_thread_component &) const;
|
||||
void _update_each_thread_quota();
|
||||
void _transfer_quota(Cpu_session_component * const dst,
|
||||
size_t const quota);
|
||||
|
||||
Trace_control_slot _trace_control_slot;
|
||||
void _insert_ref_member(Cpu_session_component * const s)
|
||||
{
|
||||
Lock::Guard lock_guard(_ref_members_lock);
|
||||
_ref_members.insert(s);
|
||||
s->_ref = this;
|
||||
}
|
||||
|
||||
Trace::Source _trace_source { *this, _trace_control_slot.control() };
|
||||
void _unsync_remove_ref_member(Cpu_session_component * const s)
|
||||
{
|
||||
s->_ref = 0;
|
||||
_ref_members.remove(s);
|
||||
}
|
||||
|
||||
Weak_ptr<Address_space> _address_space = _platform_thread.address_space();
|
||||
void _remove_ref_member(Cpu_session_component * const s)
|
||||
{
|
||||
Lock::Guard lock_guard(_ref_members_lock);
|
||||
_unsync_remove_ref_member(s);
|
||||
}
|
||||
|
||||
Rm_client _rm_client;
|
||||
void _deinit_ref_account();
|
||||
void _deinit_threads();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Exception handler to be invoked unless overridden by a
|
||||
* thread-specific handler via 'Cpu_thread::exception_sigh'
|
||||
*/
|
||||
Signal_context_capability _exception_sigh;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param ep entrypoint used for managing the thread RPC
|
||||
* object
|
||||
* \param pager_ep pager entrypoint used for handling the page
|
||||
* faults of the thread
|
||||
* \param pd PD session where the thread is executed
|
||||
* \param weight scheduling weight relative to the other
|
||||
* threads of the same CPU session
|
||||
* \param quota initial quota counter-value of the weight
|
||||
* \param labal label of the threads session
|
||||
* \param name name for the thread
|
||||
* \param priority scheduling priority
|
||||
* \param utcb user-local UTCB base
|
||||
* \param sigh initial exception handler
|
||||
*/
|
||||
Cpu_thread_component(Cpu_session_capability cpu_session_cap,
|
||||
Rpc_entrypoint &ep,
|
||||
Pager_entrypoint &pager_ep,
|
||||
Pd_session_component &pd,
|
||||
Trace::Control_area &trace_control_area,
|
||||
Cpu_session::Weight weight,
|
||||
size_t quota,
|
||||
Affinity::Location location,
|
||||
Session_label const &label,
|
||||
Thread_name const &name,
|
||||
unsigned priority,
|
||||
addr_t utcb,
|
||||
Signal_context_capability sigh)
|
||||
:
|
||||
_ep(ep), _pager_ep(pager_ep), _pd(pd.cap()),
|
||||
_address_space_region_map(pd.address_space_region_map()),
|
||||
_weight(weight),
|
||||
_session_label(label), _name(name),
|
||||
_platform_thread(quota, name.string(), priority, location, utcb),
|
||||
_bound_to_pd(_bind_to_pd(pd)),
|
||||
_sigh(sigh),
|
||||
_trace_control_slot(trace_control_area),
|
||||
_rm_client(cpu_session_cap, _ep.manage(this),
|
||||
&_address_space_region_map,
|
||||
_platform_thread.pager_object_badge(),
|
||||
_address_space, _platform_thread.affinity())
|
||||
{
|
||||
update_exception_sigh();
|
||||
/**
|
||||
* Raw thread-killing functionality
|
||||
*
|
||||
* This function is called from the 'kill_thread' function and
|
||||
* the destructor. Each these functions grab the list lock
|
||||
* by themselves and call this function to perform the actual
|
||||
* killing.
|
||||
*/
|
||||
void _unsynchronized_kill_thread(Thread_capability cap);
|
||||
|
||||
_address_space_region_map.add_client(_rm_client);
|
||||
/**
|
||||
* Convert session-local affinity location to physical location
|
||||
*/
|
||||
Affinity::Location _thread_affinity(Affinity::Location) const;
|
||||
|
||||
/* acquaint thread with its pager object */
|
||||
_pager_ep.manage(&_rm_client);
|
||||
_platform_thread.pager(&_rm_client);
|
||||
}
|
||||
public:
|
||||
|
||||
~Cpu_thread_component()
|
||||
{
|
||||
_pager_ep.dissolve(&_rm_client);
|
||||
_ep.dissolve(this);
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Cpu_session_component(Rpc_entrypoint *session_ep,
|
||||
Rpc_entrypoint *thread_ep,
|
||||
Pager_entrypoint *pager_ep,
|
||||
Allocator *md_alloc,
|
||||
Trace::Source_registry &trace_sources,
|
||||
const char *args, Affinity const &affinity,
|
||||
size_t quota);
|
||||
|
||||
_address_space_region_map.remove_client(_rm_client);
|
||||
}
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Cpu_session_component();
|
||||
|
||||
void affinity(Affinity::Location affinity)
|
||||
{
|
||||
_platform_thread.affinity(affinity);
|
||||
}
|
||||
/**
|
||||
* Register quota donation at allocator guard
|
||||
*/
|
||||
void upgrade_ram_quota(size_t ram_quota) { _md_alloc.upgrade(ram_quota); }
|
||||
|
||||
|
||||
/********************************************
|
||||
** Trace::Source::Info_accessor interface **
|
||||
********************************************/
|
||||
/***************************
|
||||
** CPU session interface **
|
||||
***************************/
|
||||
|
||||
Trace::Source::Info trace_source_info() const
|
||||
{
|
||||
return { _session_label, _name,
|
||||
_platform_thread.execution_time(),
|
||||
_platform_thread.affinity() };
|
||||
}
|
||||
Thread_capability create_thread(Capability<Pd_session>, Name const &,
|
||||
Affinity::Location, Weight, addr_t) override;
|
||||
void kill_thread(Thread_capability) override;
|
||||
void exception_sigh(Signal_context_capability) override;
|
||||
Affinity::Space affinity_space() const override;
|
||||
Dataspace_capability trace_control() override;
|
||||
int ref_account(Cpu_session_capability c) override;
|
||||
int transfer_quota(Cpu_session_capability, size_t) override;
|
||||
Quota quota() override;
|
||||
|
||||
|
||||
/************************
|
||||
** Accessor functions **
|
||||
************************/
|
||||
|
||||
Capability<Pd_session> pd() const { return _pd; }
|
||||
|
||||
Platform_thread *platform_thread() { return &_platform_thread; }
|
||||
|
||||
Trace::Source *trace_source() { return &_trace_source; }
|
||||
|
||||
size_t weight() const { return _weight.value; }
|
||||
|
||||
void sigh(Signal_context_capability sigh)
|
||||
{
|
||||
_sigh = sigh;
|
||||
update_exception_sigh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Propagate exception handler to platform thread
|
||||
*/
|
||||
void update_exception_sigh();
|
||||
|
||||
/**
|
||||
* Return index within the CPU-session's trace control area
|
||||
*/
|
||||
unsigned trace_control_index() const { return _trace_control_slot.index; }
|
||||
};
|
||||
|
||||
|
||||
class Cpu_session_component : public Rpc_object<Cpu_session>,
|
||||
public List<Cpu_session_component>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Cpu_thread_component::Session_label Session_label;
|
||||
|
||||
private:
|
||||
|
||||
Session_label _label;
|
||||
Rpc_entrypoint * const _session_ep;
|
||||
Rpc_entrypoint *_thread_ep;
|
||||
Pager_entrypoint *_pager_ep;
|
||||
Allocator_guard _md_alloc; /* guarded meta-data allocator */
|
||||
Cpu_thread_allocator _thread_alloc; /* meta-data allocator */
|
||||
Lock _thread_alloc_lock; /* protect allocator access */
|
||||
List<Cpu_thread_component> _thread_list;
|
||||
Lock _thread_list_lock; /* protect thread list */
|
||||
unsigned _priority; /* priority of threads
|
||||
created with this
|
||||
session */
|
||||
Affinity::Location _location; /* CPU affinity of this
|
||||
session */
|
||||
Trace::Source_registry &_trace_sources;
|
||||
Trace::Control_area _trace_control_area;
|
||||
|
||||
/*
|
||||
* Members for quota accounting
|
||||
*/
|
||||
|
||||
size_t _weight;
|
||||
size_t _quota;
|
||||
Cpu_session_component * _ref;
|
||||
List<Cpu_session_component> _ref_members;
|
||||
Lock _ref_members_lock;
|
||||
|
||||
Native_cpu_component _native_cpu;
|
||||
|
||||
friend class Native_cpu_component;
|
||||
|
||||
/*
|
||||
* Utilities for quota accounting
|
||||
*/
|
||||
|
||||
void _incr_weight(size_t const weight);
|
||||
void _decr_weight(size_t const weight);
|
||||
size_t _weight_to_quota(size_t const weight) const;
|
||||
void _decr_quota(size_t const quota);
|
||||
void _incr_quota(size_t const quota);
|
||||
void _update_thread_quota(Cpu_thread_component *) const;
|
||||
void _update_each_thread_quota();
|
||||
void _transfer_quota(Cpu_session_component * const dst,
|
||||
size_t const quota);
|
||||
|
||||
void _insert_ref_member(Cpu_session_component * const s)
|
||||
{
|
||||
Lock::Guard lock_guard(_ref_members_lock);
|
||||
_ref_members.insert(s);
|
||||
s->_ref = this;
|
||||
}
|
||||
|
||||
void _unsync_remove_ref_member(Cpu_session_component * const s)
|
||||
{
|
||||
s->_ref = 0;
|
||||
_ref_members.remove(s);
|
||||
}
|
||||
|
||||
void _remove_ref_member(Cpu_session_component * const s)
|
||||
{
|
||||
Lock::Guard lock_guard(_ref_members_lock);
|
||||
_unsync_remove_ref_member(s);
|
||||
}
|
||||
|
||||
void _deinit_ref_account();
|
||||
void _deinit_threads();
|
||||
|
||||
/**
|
||||
* Exception handler that will be invoked unless overridden by a
|
||||
* call of 'Cpu_session::exception_handler'.
|
||||
*/
|
||||
Signal_context_capability _default_exception_handler;
|
||||
|
||||
/**
|
||||
* Raw thread-killing functionality
|
||||
*
|
||||
* This function is called from the 'kill_thread' function and
|
||||
* the destructor. Each these functions grab the list lock
|
||||
* by themselves and call this function to perform the actual
|
||||
* killing.
|
||||
*/
|
||||
void _unsynchronized_kill_thread(Thread_capability cap);
|
||||
|
||||
/**
|
||||
* Convert session-local affinity location to physical location
|
||||
*/
|
||||
Affinity::Location _thread_affinity(Affinity::Location) const;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Cpu_session_component(Rpc_entrypoint *session_ep,
|
||||
Rpc_entrypoint *thread_ep,
|
||||
Pager_entrypoint *pager_ep,
|
||||
Allocator *md_alloc,
|
||||
Trace::Source_registry &trace_sources,
|
||||
const char *args, Affinity const &affinity,
|
||||
size_t quota);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Cpu_session_component();
|
||||
|
||||
/**
|
||||
* Register quota donation at allocator guard
|
||||
*/
|
||||
void upgrade_ram_quota(size_t ram_quota) { _md_alloc.upgrade(ram_quota); }
|
||||
|
||||
|
||||
/***************************
|
||||
** CPU session interface **
|
||||
***************************/
|
||||
|
||||
Thread_capability create_thread(Capability<Pd_session>, Name const &,
|
||||
Affinity::Location, Weight, addr_t) override;
|
||||
Ram_dataspace_capability utcb(Thread_capability thread) override;
|
||||
void kill_thread(Thread_capability) override;
|
||||
int start(Thread_capability, addr_t, addr_t) override;
|
||||
void pause(Thread_capability thread_cap) override;
|
||||
void resume(Thread_capability thread_cap) override;
|
||||
void single_step(Thread_capability thread_cap, bool enable) override;
|
||||
void cancel_blocking(Thread_capability) override;
|
||||
Thread_state state(Thread_capability) override;
|
||||
void state(Thread_capability, Thread_state const &) override;
|
||||
void exception_handler(Thread_capability, Signal_context_capability) override;
|
||||
Affinity::Space affinity_space() const override;
|
||||
void affinity(Thread_capability, Affinity::Location) override;
|
||||
Dataspace_capability trace_control() override;
|
||||
unsigned trace_control_index(Thread_capability) override;
|
||||
Dataspace_capability trace_buffer(Thread_capability) override;
|
||||
Dataspace_capability trace_policy(Thread_capability) override;
|
||||
int ref_account(Cpu_session_capability c) override;
|
||||
int transfer_quota(Cpu_session_capability, size_t) override;
|
||||
Quota quota() override;
|
||||
|
||||
Capability<Native_cpu> native_cpu() override { return _native_cpu.cap(); }
|
||||
};
|
||||
}
|
||||
Capability<Native_cpu> native_cpu() override { return _native_cpu.cap(); }
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_ */
|
||||
|
224
repos/base/src/core/include/cpu_thread_component.h
Normal file
224
repos/base/src/core/include/cpu_thread_component.h
Normal file
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* \brief CPU thread RPC object
|
||||
* \author Norman Feske
|
||||
* \date 2016-05-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__CPU_THREAD_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__CPU_THREAD_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/list.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <cpu_thread/cpu_thread.h>
|
||||
|
||||
/* core includes */
|
||||
#include <pager.h>
|
||||
#include <cpu_thread_allocator.h>
|
||||
#include <pd_session_component.h>
|
||||
#include <platform_thread.h>
|
||||
#include <trace/control_area.h>
|
||||
#include <trace/source_registry.h>
|
||||
|
||||
namespace Genode { class Cpu_thread_component; }
|
||||
|
||||
|
||||
class Genode::Cpu_thread_component : public Rpc_object<Cpu_thread>,
|
||||
public List<Cpu_thread_component>::Element,
|
||||
public Trace::Source::Info_accessor
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Trace::Session_label Session_label;
|
||||
typedef Trace::Thread_name Thread_name;
|
||||
|
||||
private:
|
||||
|
||||
Rpc_entrypoint &_ep;
|
||||
Pager_entrypoint &_pager_ep;
|
||||
Capability<Pd_session> _pd;
|
||||
Region_map_component &_address_space_region_map;
|
||||
Cpu_session::Weight const _weight;
|
||||
Session_label const _session_label;
|
||||
Thread_name const _name;
|
||||
Platform_thread _platform_thread;
|
||||
bool const _bound_to_pd;
|
||||
|
||||
bool _bind_to_pd(Pd_session_component &pd)
|
||||
{
|
||||
if (!pd.bind_thread(_platform_thread))
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception handler as defined by 'Cpu_session::exception_sigh'
|
||||
*/
|
||||
Signal_context_capability _session_sigh;
|
||||
|
||||
/**
|
||||
* Exception handler as defined by 'Cpu_thread::exception_sigh'
|
||||
*/
|
||||
Signal_context_capability _thread_sigh;
|
||||
|
||||
struct Trace_control_slot
|
||||
{
|
||||
unsigned index = 0;
|
||||
Trace::Control_area &trace_control_area;
|
||||
|
||||
Trace_control_slot(Trace::Control_area &trace_control_area)
|
||||
: trace_control_area(trace_control_area)
|
||||
{
|
||||
if (!trace_control_area.alloc(index))
|
||||
throw Cpu_session::Out_of_metadata();
|
||||
}
|
||||
|
||||
~Trace_control_slot()
|
||||
{
|
||||
trace_control_area.free(index);
|
||||
}
|
||||
|
||||
Trace::Control &control()
|
||||
{
|
||||
return *trace_control_area.at(index);
|
||||
}
|
||||
};
|
||||
|
||||
Trace_control_slot _trace_control_slot;
|
||||
|
||||
Trace::Source _trace_source { *this, _trace_control_slot.control() };
|
||||
|
||||
Trace::Source_registry &_trace_sources;
|
||||
|
||||
Weak_ptr<Address_space> _address_space = _platform_thread.address_space();
|
||||
|
||||
Rm_client _rm_client;
|
||||
|
||||
/**
|
||||
* Propagate exception handler to platform thread
|
||||
*/
|
||||
void _update_exception_sigh();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param ep entrypoint used for managing the thread RPC
|
||||
* object
|
||||
* \param pager_ep pager entrypoint used for handling the page
|
||||
* faults of the thread
|
||||
* \param pd PD session where the thread is executed
|
||||
* \param weight scheduling weight relative to the other
|
||||
* threads of the same CPU session
|
||||
* \param quota initial quota counter-value of the weight
|
||||
* \param labal label of the threads session
|
||||
* \param name name for the thread
|
||||
* \param priority scheduling priority
|
||||
* \param utcb user-local UTCB base
|
||||
*/
|
||||
Cpu_thread_component(Cpu_session_capability cpu_session_cap,
|
||||
Rpc_entrypoint &ep,
|
||||
Pager_entrypoint &pager_ep,
|
||||
Pd_session_component &pd,
|
||||
Trace::Control_area &trace_control_area,
|
||||
Trace::Source_registry &trace_sources,
|
||||
Cpu_session::Weight weight,
|
||||
size_t quota,
|
||||
Affinity::Location location,
|
||||
Session_label const &label,
|
||||
Thread_name const &name,
|
||||
unsigned priority,
|
||||
addr_t utcb)
|
||||
:
|
||||
_ep(ep), _pager_ep(pager_ep), _pd(pd.cap()),
|
||||
_address_space_region_map(pd.address_space_region_map()),
|
||||
_weight(weight),
|
||||
_session_label(label), _name(name),
|
||||
_platform_thread(quota, name.string(), priority, location, utcb),
|
||||
_bound_to_pd(_bind_to_pd(pd)),
|
||||
_trace_control_slot(trace_control_area),
|
||||
_trace_sources(trace_sources),
|
||||
_rm_client(cpu_session_cap, _ep.manage(this),
|
||||
&_address_space_region_map,
|
||||
_platform_thread.pager_object_badge(),
|
||||
_address_space, _platform_thread.affinity())
|
||||
{
|
||||
_address_space_region_map.add_client(_rm_client);
|
||||
|
||||
/* acquaint thread with its pager object */
|
||||
_pager_ep.manage(&_rm_client);
|
||||
_platform_thread.pager(&_rm_client);
|
||||
_trace_sources.insert(&_trace_source);
|
||||
}
|
||||
|
||||
~Cpu_thread_component()
|
||||
{
|
||||
_trace_sources.remove(&_trace_source);
|
||||
_pager_ep.dissolve(&_rm_client);
|
||||
_ep.dissolve(this);
|
||||
|
||||
_address_space_region_map.remove_client(_rm_client);
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
** Trace::Source::Info_accessor interface **
|
||||
********************************************/
|
||||
|
||||
Trace::Source::Info trace_source_info() const
|
||||
{
|
||||
return { _session_label, _name,
|
||||
_platform_thread.execution_time(),
|
||||
_platform_thread.affinity() };
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
** Accessor functions **
|
||||
************************/
|
||||
|
||||
/**
|
||||
* Define default exception handler installed for the CPU session
|
||||
*/
|
||||
void session_exception_sigh(Signal_context_capability);
|
||||
|
||||
Capability<Pd_session> pd() const { return _pd; }
|
||||
|
||||
void quota(size_t);
|
||||
|
||||
/*
|
||||
* Called by platform-specific 'Native_cpu' operations
|
||||
*/
|
||||
Platform_thread &platform_thread() { return _platform_thread; }
|
||||
|
||||
size_t weight() const { return _weight.value; }
|
||||
|
||||
|
||||
/**************************
|
||||
** CPU thread interface **
|
||||
*************************/
|
||||
|
||||
Dataspace_capability utcb() override;
|
||||
void start(addr_t, addr_t) override;
|
||||
void pause() override;
|
||||
void resume() override;
|
||||
void single_step(bool) override;
|
||||
void cancel_blocking() override;
|
||||
Thread_state state() override;
|
||||
void state(Thread_state const &) override;
|
||||
void exception_sigh(Signal_context_capability) override;
|
||||
void affinity(Affinity::Location) override;
|
||||
unsigned trace_control_index() override;
|
||||
Dataspace_capability trace_buffer() override;
|
||||
Dataspace_capability trace_policy() override;
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__CPU_THREAD_COMPONENT_H_ */
|
@ -125,6 +125,8 @@ class Core_child : public Child_policy
|
||||
Ram_session_client _ram;
|
||||
Cpu_session_client _cpu;
|
||||
|
||||
Child::Initial_thread _initial_thread { _cpu, _pd, "name" };
|
||||
|
||||
Region_map_client _address_space;
|
||||
|
||||
Child _child;
|
||||
@ -139,11 +141,11 @@ class Core_child : public Child_policy
|
||||
Cpu_session_capability cpu,
|
||||
Service_registry &services)
|
||||
:
|
||||
_entrypoint(nullptr, STACK_SIZE, "init", false),
|
||||
_entrypoint(nullptr, STACK_SIZE, "name", false),
|
||||
_local_services(services),
|
||||
_pd(pd), _ram(ram), _cpu(cpu),
|
||||
_address_space(Pd_session_client(pd).address_space()),
|
||||
_child(elf_ds, _ldso_ds, _pd, _pd, _ram, _ram, _cpu, _cpu,
|
||||
_child(elf_ds, _ldso_ds, _pd, _pd, _ram, _ram, _cpu, _initial_thread,
|
||||
*env()->rm_session(), _address_space, _entrypoint, *this,
|
||||
*_local_services.find(Pd_session::service_name()),
|
||||
*_local_services.find(Ram_session::service_name()),
|
||||
|
@ -445,7 +445,7 @@ void Child::exit(int exit_value)
|
||||
|
||||
Thread_capability Child::main_thread_cap() const
|
||||
{
|
||||
return _process.initial_thread.cap;
|
||||
return _process.initial_thread.cap();
|
||||
}
|
||||
|
||||
|
||||
@ -482,7 +482,7 @@ Child::Child(Dataspace_capability elf_ds,
|
||||
Ram_session_capability ram_cap,
|
||||
Ram_session &ram,
|
||||
Cpu_session_capability cpu_cap,
|
||||
Cpu_session &cpu,
|
||||
Initial_thread_base &initial_thread,
|
||||
Region_map &local_rm,
|
||||
Region_map &remote_rm,
|
||||
Rpc_entrypoint &entrypoint,
|
||||
@ -500,8 +500,8 @@ try :
|
||||
_parent_cap(_entrypoint.manage(this)),
|
||||
_policy(policy),
|
||||
_server(_ram),
|
||||
_process(elf_ds, ldso_ds, pd_cap, pd, ram, cpu, local_rm, remote_rm,
|
||||
_parent_cap, policy.name())
|
||||
_process(elf_ds, ldso_ds, pd_cap, pd, ram, initial_thread, local_rm, remote_rm,
|
||||
_parent_cap)
|
||||
{ }
|
||||
catch (Cpu_session::Thread_creation_failed) { throw Process_startup_failed(); }
|
||||
catch (Cpu_session::Out_of_metadata) { throw Process_startup_failed(); }
|
||||
|
@ -15,6 +15,7 @@
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <base/child.h>
|
||||
#include <cpu_thread/client.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/elf.h>
|
||||
@ -162,18 +163,24 @@ Child::Process::Loaded_executable::Loaded_executable(Dataspace_capability elf_ds
|
||||
}
|
||||
|
||||
|
||||
Child::Process::Initial_thread::Initial_thread(Cpu_session &cpu,
|
||||
Pd_session_capability pd,
|
||||
char const *name)
|
||||
Child::Initial_thread::Initial_thread(Cpu_session &cpu,
|
||||
Pd_session_capability pd,
|
||||
Name const &name)
|
||||
:
|
||||
cpu(cpu),
|
||||
cap(cpu.create_thread(pd, name, Affinity::Location(), Cpu_session::Weight()))
|
||||
_cpu(cpu),
|
||||
_cap(cpu.create_thread(pd, name, Affinity::Location(), Cpu_session::Weight()))
|
||||
{ }
|
||||
|
||||
|
||||
Child::Process::Initial_thread::~Initial_thread()
|
||||
Child::Initial_thread::~Initial_thread()
|
||||
{
|
||||
cpu.kill_thread(cap);
|
||||
_cpu.kill_thread(_cap);
|
||||
}
|
||||
|
||||
|
||||
void Child::Initial_thread::start(addr_t ip)
|
||||
{
|
||||
Cpu_thread_client(_cap).start(ip, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -182,13 +189,12 @@ Child::Process::Process(Dataspace_capability elf_ds,
|
||||
Pd_session_capability pd_cap,
|
||||
Pd_session &pd,
|
||||
Ram_session &ram,
|
||||
Cpu_session &cpu,
|
||||
Initial_thread_base &initial_thread,
|
||||
Region_map &local_rm,
|
||||
Region_map &remote_rm,
|
||||
Parent_capability parent_cap,
|
||||
char const *name)
|
||||
Parent_capability parent_cap)
|
||||
:
|
||||
initial_thread(cpu, pd_cap, name),
|
||||
initial_thread(initial_thread),
|
||||
loaded_executable(elf_ds, ldso_ds, ram, local_rm, remote_rm, parent_cap)
|
||||
{
|
||||
/* register parent interface for new protection domain */
|
||||
@ -203,10 +209,7 @@ Child::Process::Process(Dataspace_capability elf_ds,
|
||||
return;
|
||||
|
||||
/* start main thread */
|
||||
if (cpu.start(initial_thread.cap, loaded_executable.entry, 0)) {
|
||||
PERR("start of initial thread failed");
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
}
|
||||
initial_thread.start(loaded_executable.entry);
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/env.h>
|
||||
#include <cpu_thread/client.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
@ -62,11 +63,11 @@ void Thread::start()
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
|
||||
/* start execution at initial instruction pointer and stack pointer */
|
||||
_cpu_session->start(_thread_cap, (addr_t)_thread_start, _stack->top());
|
||||
Cpu_thread_client(_thread_cap).start((addr_t)_thread_start, _stack->top());
|
||||
}
|
||||
|
||||
|
||||
void Thread::cancel_blocking()
|
||||
{
|
||||
_cpu_session->cancel_blocking(_thread_cap);
|
||||
Cpu_thread_client(_thread_cap).cancel_blocking();
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <base/trace/policy.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <util/construct_at.h>
|
||||
#include <cpu_thread/client.h>
|
||||
|
||||
/* local includes */
|
||||
#include <base/internal/trace_control.h>
|
||||
@ -74,7 +75,7 @@ bool Trace::Logger::_evaluate_control()
|
||||
Control::Inhibit_guard guard(*control);
|
||||
|
||||
/* obtain policy */
|
||||
Dataspace_capability policy_ds = cpu->trace_policy(thread_cap);
|
||||
Dataspace_capability policy_ds = Cpu_thread_client(thread_cap).trace_policy();
|
||||
|
||||
if (!policy_ds.valid()) {
|
||||
PWRN("could not obtain trace policy");
|
||||
@ -100,7 +101,7 @@ bool Trace::Logger::_evaluate_control()
|
||||
|
||||
/* obtain buffer */
|
||||
buffer = 0;
|
||||
Dataspace_capability buffer_ds = cpu->trace_buffer(thread_cap);
|
||||
Dataspace_capability buffer_ds = Cpu_thread_client(thread_cap).trace_buffer();
|
||||
|
||||
if (!buffer_ds.valid()) {
|
||||
PWRN("could not obtain trace buffer");
|
||||
@ -139,7 +140,7 @@ void Trace::Logger::init(Thread_capability thread, Cpu_session *cpu_session,
|
||||
thread_cap = thread;
|
||||
cpu = cpu_session;
|
||||
|
||||
unsigned const index = cpu->trace_control_index(thread);
|
||||
unsigned const index = Cpu_thread_client(thread).trace_control_index();
|
||||
Dataspace_capability ds = cpu->trace_control();
|
||||
size_t size = Dataspace_client(ds).size();
|
||||
if ((index + 1)*sizeof(Trace::Control) > size) {
|
||||
|
@ -39,7 +39,7 @@ class Sync_signal_transmitter : public Signal_transmitter
|
||||
}
|
||||
};
|
||||
|
||||
class Fpu_user : public Thread_deprecated<4 * 1024>
|
||||
class Fpu_user : public Thread_deprecated<0x2000>
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -79,10 +79,11 @@ class Test_child : public Child_policy
|
||||
*/
|
||||
Rpc_entrypoint _entrypoint;
|
||||
|
||||
Region_map_client _address_space;
|
||||
Pd_session_client _pd;
|
||||
Ram_session_client _ram;
|
||||
Cpu_session_client _cpu;
|
||||
Region_map_client _address_space;
|
||||
Pd_session_client _pd;
|
||||
Ram_session_client _ram;
|
||||
Cpu_session_client _cpu;
|
||||
Child::Initial_thread _initial_thread;
|
||||
|
||||
Child _child;
|
||||
|
||||
@ -101,8 +102,9 @@ class Test_child : public Child_policy
|
||||
:
|
||||
_entrypoint(cap, STACK_SIZE, "child", false),
|
||||
_address_space(pd.address_space()), _pd(pd), _ram(ram), _cpu(cpu),
|
||||
_initial_thread(_cpu, _pd, "child"),
|
||||
_child(elf_ds, Dataspace_capability(), _pd, _pd, _ram, _ram,
|
||||
_cpu, _cpu, *env()->rm_session(), _address_space,
|
||||
_cpu, _initial_thread, *env()->rm_session(), _address_space,
|
||||
_entrypoint, *this),
|
||||
_log_service("LOG")
|
||||
{
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <util/volatile_object.h>
|
||||
#include <cpu_session/connection.h>
|
||||
#include <cpu_thread/client.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
@ -259,16 +260,17 @@ static void test_pause_resume(Env &env)
|
||||
while (thread.loop < 1) { }
|
||||
|
||||
Thread_state state;
|
||||
Cpu_thread_client thread_client(thread.cap());
|
||||
|
||||
log("--- pausing ---");
|
||||
env.cpu().pause(thread.cap());
|
||||
thread_client.pause();
|
||||
unsigned loop_paused = thread.loop;
|
||||
log("--- paused ---");
|
||||
|
||||
log("--- reading thread state ---");
|
||||
try {
|
||||
state = env.cpu().state(thread.cap());
|
||||
} catch (Cpu_session::State_access_failed) {
|
||||
state = thread_client.state();
|
||||
} catch (Cpu_thread::State_access_failed) {
|
||||
throw -10;
|
||||
}
|
||||
if (loop_paused != thread.loop)
|
||||
@ -276,7 +278,7 @@ static void test_pause_resume(Env &env)
|
||||
|
||||
thread.beep = true;
|
||||
log("--- resuming thread ---");
|
||||
env.cpu().resume(thread.cap());
|
||||
thread_client.resume();
|
||||
|
||||
while (thread.loop == loop_paused) { }
|
||||
|
||||
|
@ -171,6 +171,8 @@ class Launchpad_child : public Genode::List<Launchpad_child>::Element
|
||||
Genode::Ram_session_client _ram;
|
||||
Genode::Cpu_session_client _cpu;
|
||||
|
||||
Genode::Child::Initial_thread _initial_thread;
|
||||
|
||||
Genode::Server _server;
|
||||
|
||||
Launchpad_child_policy _policy;
|
||||
@ -193,12 +195,13 @@ class Launchpad_child : public Genode::List<Launchpad_child>::Element
|
||||
_launchpad(launchpad),
|
||||
_entrypoint(cap_session, ENTRYPOINT_STACK_SIZE, name, false),
|
||||
_address_space(Genode::Pd_session_client(pd).address_space()),
|
||||
_rom(rom), _pd(pd), _ram(ram), _cpu(cpu), _server(_ram),
|
||||
_rom(rom), _pd(pd), _ram(ram), _cpu(cpu),
|
||||
_initial_thread(_cpu, _pd, name), _server(_ram),
|
||||
_policy(name, &_server, parent_services, child_services,
|
||||
config_ds, elf_ds, &_entrypoint),
|
||||
_child(elf_ds, _ldso_ds(), _pd, _pd, _ram, _ram, _cpu, _cpu,
|
||||
*Genode::env()->rm_session(), _address_space,
|
||||
_entrypoint, _policy)
|
||||
_child(elf_ds, _ldso_ds(), _pd, _pd, _ram, _ram, _cpu,
|
||||
_initial_thread, *Genode::env()->rm_session(),
|
||||
_address_space, _entrypoint, _policy)
|
||||
{
|
||||
_entrypoint.activate();
|
||||
}
|
||||
|
@ -48,6 +48,9 @@ class Child_base : public Genode::Child_policy
|
||||
|
||||
Label const _label;
|
||||
|
||||
size_t _ram_quota;
|
||||
size_t _ram_limit;
|
||||
|
||||
struct Resources
|
||||
{
|
||||
Genode::Pd_connection pd;
|
||||
@ -65,11 +68,11 @@ class Child_base : public Genode::Child_policy
|
||||
if (Genode::env()->ram_session()->transfer_quota(ram.cap(), ram_quota) != 0)
|
||||
throw Quota_exceeded();
|
||||
}
|
||||
};
|
||||
} _resources;
|
||||
|
||||
Genode::Child::Initial_thread _initial_thread { _resources.cpu, _resources.pd,
|
||||
_label.string() };
|
||||
|
||||
size_t _ram_quota;
|
||||
size_t _ram_limit;
|
||||
Resources _resources;
|
||||
Genode::Region_map_client _address_space { _resources.pd.address_space() };
|
||||
Genode::Service_registry _parent_services;
|
||||
Genode::Rom_connection _binary_rom;
|
||||
@ -122,7 +125,7 @@ class Child_base : public Genode::Child_policy
|
||||
_binary_policy("binary", _binary_rom.dataspace(), &_entrypoint),
|
||||
_config_policy("config", _entrypoint, &_resources.ram),
|
||||
_child(_binary_rom.dataspace(), ldso_ds, _resources.pd, _resources.pd,
|
||||
_resources.ram, _resources.ram, _resources.cpu, _resources.cpu,
|
||||
_resources.ram, _resources.ram, _resources.cpu, _initial_thread,
|
||||
*Genode::env()->rm_session(), _address_space,
|
||||
_entrypoint, *this),
|
||||
_yield_response_sigh_cap(yield_response_sig_cap),
|
||||
|
@ -501,6 +501,8 @@ class Init::Child : Genode::Child_policy
|
||||
}
|
||||
} _resources;
|
||||
|
||||
Genode::Child::Initial_thread _initial_thread { _resources.cpu, _resources.pd,
|
||||
_name.unique };
|
||||
/*
|
||||
* Entry point used for serving the parent interface and the
|
||||
* locally provided ROM sessions for the 'config' and 'binary'
|
||||
@ -559,7 +561,8 @@ class Init::Child : Genode::Child_policy
|
||||
_name(start_node, name_registry),
|
||||
_resources(start_node, _name.unique, prio_levels,
|
||||
affinity_space),
|
||||
_entrypoint(&cap_session, ENTRYPOINT_STACK_SIZE, _name.unique, false, _resources.affinity.location()),
|
||||
_entrypoint(&cap_session, ENTRYPOINT_STACK_SIZE, _name.unique, false,
|
||||
_resources.affinity.location()),
|
||||
_binary_rom(_name.file, _name.file),
|
||||
_binary_rom_ds(_binary_rom.dataspace()),
|
||||
_config(_resources.ram.cap(), start_node),
|
||||
@ -567,7 +570,7 @@ class Init::Child : Genode::Child_policy
|
||||
_child(_binary_rom_ds, ldso_ds,
|
||||
_resources.pd, _resources.pd,
|
||||
_resources.ram, _resources.ram,
|
||||
_resources.cpu, _resources.cpu,
|
||||
_resources.cpu, _initial_thread,
|
||||
*Genode::env()->rm_session(), _address_space, _entrypoint, *this),
|
||||
_parent_services(parent_services),
|
||||
_child_services(child_services),
|
||||
|
@ -176,9 +176,10 @@ class Genode::Slave
|
||||
if (ram_ref.transfer_quota(ram.cap(), ram_quota))
|
||||
throw Quota_exceeded();
|
||||
}
|
||||
};
|
||||
} _resources;
|
||||
|
||||
Genode::Child::Initial_thread _initial_thread;
|
||||
|
||||
Resources _resources;
|
||||
Genode::Region_map_client _address_space { _resources.pd.address_space() };
|
||||
Genode::Child _child;
|
||||
|
||||
@ -191,8 +192,9 @@ class Genode::Slave
|
||||
Dataspace_capability ldso_ds = Dataspace_capability())
|
||||
:
|
||||
_resources(slave_policy.name(), ram_quota, ram_ref_cap),
|
||||
_initial_thread(_resources.cpu, _resources.pd, slave_policy.name()),
|
||||
_child(slave_policy.binary(), ldso_ds, _resources.pd, _resources.pd,
|
||||
_resources.ram, _resources.ram, _resources.cpu, _resources.cpu,
|
||||
_resources.ram, _resources.ram, _resources.cpu, _initial_thread,
|
||||
*env()->rm_session(), _address_space, entrypoint, slave_policy)
|
||||
{ }
|
||||
|
||||
|
@ -33,10 +33,9 @@ namespace Loader {
|
||||
{
|
||||
private:
|
||||
|
||||
struct Label {
|
||||
char string[Session::Name::MAX_SIZE];
|
||||
Label(char const *l) { strncpy(string, l, sizeof(string)); }
|
||||
} _label;
|
||||
typedef String<Session::Name::MAX_SIZE> Label;
|
||||
|
||||
Label _label;
|
||||
|
||||
Rpc_entrypoint &_ep;
|
||||
|
||||
@ -67,12 +66,16 @@ namespace Loader {
|
||||
* Install CPU exception and RM fault handler assigned by
|
||||
* the loader client via 'Loader_session::fault_handler'.
|
||||
*/
|
||||
cpu.exception_handler(Thread_capability(), fault_sigh);
|
||||
cpu.exception_sigh(fault_sigh);
|
||||
Region_map_client address_space(pd.address_space());
|
||||
address_space.fault_handler(fault_sigh);
|
||||
}
|
||||
} _resources;
|
||||
|
||||
Genode::Child::Initial_thread _initial_thread { _resources.cpu,
|
||||
_resources.pd,
|
||||
_label.string() };
|
||||
|
||||
Region_map_client _address_space { _resources.pd.address_space() };
|
||||
|
||||
Service_registry &_parent_services;
|
||||
@ -117,7 +120,7 @@ namespace Loader {
|
||||
:
|
||||
_label(label),
|
||||
_ep(ep),
|
||||
_resources(_label.string, ram_session_client, ram_quota, fault_sigh),
|
||||
_resources(_label.string(), ram_session_client, ram_quota, fault_sigh),
|
||||
_parent_services(parent_services),
|
||||
_local_nitpicker_service(local_nitpicker_service),
|
||||
_local_rom_service(local_rom_service),
|
||||
@ -125,11 +128,11 @@ namespace Loader {
|
||||
_local_pd_service(local_pd_service),
|
||||
_binary_rom_session(_rom_session(binary_name)),
|
||||
_binary_policy("binary", _binary_rom_session.dataspace(), &_ep),
|
||||
_labeling_policy(_label.string),
|
||||
_labeling_policy(_label.string()),
|
||||
_child(_binary_rom_session.dataspace(), ldso_ds,
|
||||
_resources.pd, _resources.pd,
|
||||
_resources.ram, _resources.ram,
|
||||
_resources.cpu, _resources.cpu,
|
||||
_resources.cpu, _initial_thread,
|
||||
*env()->rm_session(), _address_space, _ep, *this)
|
||||
{ }
|
||||
|
||||
@ -143,15 +146,15 @@ namespace Loader {
|
||||
** Child-policy interface **
|
||||
****************************/
|
||||
|
||||
char const *name() const { return _label.string; }
|
||||
char const *name() const override { return _label.string(); }
|
||||
|
||||
void filter_session_args(char const *service, char *args, size_t args_len)
|
||||
void filter_session_args(char const *service, char *args, size_t args_len) override
|
||||
{
|
||||
_labeling_policy.filter_session_args(service, args, args_len);
|
||||
}
|
||||
|
||||
Service *resolve_session_request(const char *name,
|
||||
const char *args)
|
||||
const char *args) override
|
||||
{
|
||||
Service *service = 0;
|
||||
|
||||
|
@ -156,7 +156,7 @@ class Loader::Session_component : public Rpc_object<Session>
|
||||
Affinity const &affinity)
|
||||
{
|
||||
Capability<Cpu_session> cap = env()->parent()->session<Cpu_session>(args, affinity);
|
||||
Cpu_session_client(cap).exception_handler(Thread_capability(), fault_sigh);
|
||||
Cpu_session_client(cap).exception_sigh(fault_sigh);
|
||||
return cap;
|
||||
}
|
||||
|
||||
|
@ -42,16 +42,17 @@ class Bomb_child_resources
|
||||
Genode::Rom_connection _rom;
|
||||
Genode::Ram_connection _ram;
|
||||
Genode::Cpu_connection _cpu;
|
||||
char _name[32];
|
||||
|
||||
typedef String<32> Name;
|
||||
Name _name;
|
||||
|
||||
Genode::Region_map_client _address_space { _pd.address_space() };
|
||||
|
||||
Bomb_child_resources(const char *file_name, const char *name,
|
||||
Genode::size_t ram_quota)
|
||||
: _pd(name), _rom(file_name, name), _ram(name), _cpu(name)
|
||||
:
|
||||
_pd(name), _rom(file_name, name), _ram(name), _cpu(name), _name(name)
|
||||
{
|
||||
Genode::strncpy(_name, name, sizeof(_name));
|
||||
|
||||
_ram.ref_account(env()->ram_session_cap());
|
||||
Genode::env()->ram_session()->transfer_quota(_ram.cap(), ram_quota);
|
||||
|
||||
@ -65,11 +66,14 @@ class Bomb_child_resources
|
||||
|
||||
class Bomb_child : private Bomb_child_resources,
|
||||
public Genode::Child_policy,
|
||||
private Init::Child_policy_enforce_labeling,
|
||||
public Genode::List<Bomb_child>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Init::Child_policy_enforce_labeling _enforce_labeling_policy;
|
||||
|
||||
Genode::Child::Initial_thread _initial_thread;
|
||||
|
||||
/*
|
||||
* Entry point used for serving the parent interface
|
||||
*/
|
||||
@ -90,10 +94,11 @@ class Bomb_child : private Bomb_child_resources,
|
||||
unsigned generation)
|
||||
:
|
||||
Bomb_child_resources(file_name, unique_name, ram_quota),
|
||||
Init::Child_policy_enforce_labeling(Bomb_child_resources::_name),
|
||||
_enforce_labeling_policy(_name.string()),
|
||||
_initial_thread(_cpu, _pd, unique_name),
|
||||
_entrypoint(cap_session, STACK_SIZE, "bomb_ep_child", false),
|
||||
_child(_rom.dataspace(), Genode::Dataspace_capability(),
|
||||
_pd, _pd, _ram, _ram, _cpu, _cpu,
|
||||
_pd, _pd, _ram, _ram, _cpu, _initial_thread,
|
||||
*Genode::env()->rm_session(), _address_space, _entrypoint, *this),
|
||||
_parent_services(parent_services),
|
||||
_config_policy("config", _entrypoint, &_ram)
|
||||
@ -113,11 +118,11 @@ class Bomb_child : private Bomb_child_resources,
|
||||
** Child-policy interface **
|
||||
****************************/
|
||||
|
||||
const char *name() const { return Bomb_child_resources::_name; }
|
||||
const char *name() const { return Bomb_child_resources::_name.string(); }
|
||||
|
||||
void filter_session_args(const char * x, char *args, Genode::size_t args_len)
|
||||
{
|
||||
Child_policy_enforce_labeling::filter_session_args(0, args, args_len);
|
||||
_enforce_labeling_policy.filter_session_args(0, args, args_len);
|
||||
}
|
||||
|
||||
Service *resolve_session_request(const char *service_name,
|
||||
|
@ -68,7 +68,7 @@ class Test_child : public Genode::Child_policy
|
||||
env()->ram_session()->transfer_quota(ram.cap(), CHILD_QUOTA);
|
||||
|
||||
/* register default exception handler */
|
||||
cpu.exception_handler(Thread_capability(), sigh);
|
||||
cpu.exception_sigh(sigh);
|
||||
|
||||
/* register handler for unresolvable page faults */
|
||||
Region_map_client address_space(pd.address_space());
|
||||
@ -76,6 +76,8 @@ class Test_child : public Genode::Child_policy
|
||||
}
|
||||
} _resources;
|
||||
|
||||
Genode::Child::Initial_thread _initial_thread;
|
||||
|
||||
/*
|
||||
* The order of the following members is important. The services must
|
||||
* appear before the child to ensure the correct order of destruction.
|
||||
@ -99,12 +101,13 @@ class Test_child : public Genode::Child_policy
|
||||
Genode::Signal_context_capability sigh)
|
||||
:
|
||||
_resources(sigh, elf_name),
|
||||
_initial_thread(_resources.cpu, _resources.pd, elf_name),
|
||||
_elf(elf_name),
|
||||
_log_service("LOG"), _rm_service("RM"),
|
||||
_child(_elf.dataspace(), Genode::Dataspace_capability(),
|
||||
_resources.pd, _resources.pd,
|
||||
_resources.ram, _resources.ram,
|
||||
_resources.cpu, _resources.cpu,
|
||||
_resources.cpu, _initial_thread,
|
||||
*Genode::env()->rm_session(), _address_space, ep, *this)
|
||||
{ }
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <base/printf.h>
|
||||
#include <base/snprintf.h>
|
||||
#include <base/exception.h>
|
||||
#include <cpu_thread/client.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
@ -149,7 +150,7 @@ struct Stress_thread : public Genode::Thread_deprecated<4*1024*sizeof(Genode::ad
|
||||
Stress_thread(Vfs::File_system &vfs, char const *parent, Affinity::Location affinity)
|
||||
: Thread_deprecated(parent), path(parent), count(0), vfs(vfs)
|
||||
{
|
||||
env()->cpu_session()->affinity(cap(), affinity);
|
||||
Cpu_thread_client(cap()).affinity(affinity);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <base/cap_map.h>
|
||||
#include <foc_native_cpu/client.h>
|
||||
#include <cpu_session/client.h>
|
||||
#include <cpu_thread/client.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <foc/native_thread.h>
|
||||
|
||||
@ -62,7 +63,7 @@ namespace L4lx {
|
||||
_data(data ? *data : 0),
|
||||
_vcpu_state(vcpu_state),
|
||||
_cpu_nr(cpu_nr),
|
||||
_utcb((Fiasco::l4_utcb_t *)_cpu_session->state(cap()).utcb)
|
||||
_utcb((Fiasco::l4_utcb_t *)Genode::Cpu_thread_client(cap()).state().utcb)
|
||||
{
|
||||
start();
|
||||
|
||||
@ -95,8 +96,7 @@ namespace L4lx {
|
||||
|
||||
void set_affinity(unsigned i)
|
||||
{
|
||||
cpu_connection()->affinity(_thread_cap,
|
||||
Genode::Affinity::Location(i, 0));
|
||||
Genode::Cpu_thread_client(_thread_cap).affinity(Genode::Affinity::Location(i, 0));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <pd_session/connection.h>
|
||||
#include <region_map/client.h>
|
||||
#include <nova_native_cpu/client.h>
|
||||
#include <cpu_thread/client.h>
|
||||
|
||||
/* NOVA includes */
|
||||
#include <nova/native_thread.h>
|
||||
@ -76,7 +77,9 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
|
||||
state.sel_exc_base = Native_thread::INVALID_INDEX;
|
||||
state.is_vcpu = true;
|
||||
|
||||
_cpu_session->state(vcpu_vm, state);
|
||||
Cpu_thread_client cpu_thread(vcpu_vm);
|
||||
|
||||
cpu_thread.state(state);
|
||||
|
||||
/* obtain interface to NOVA-specific CPU session operations */
|
||||
Nova_native_cpu_client native_cpu(_cpu_session->native_cpu());
|
||||
@ -91,7 +94,7 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
|
||||
delegate_vcpu_portals(pager_cap, exc_base());
|
||||
|
||||
/* start vCPU in separate PD */
|
||||
_cpu_session->start(vcpu_vm, 0, 0);
|
||||
cpu_thread.start(0, 0);
|
||||
|
||||
/*
|
||||
* Request native EC thread cap and put it next to the
|
||||
|
@ -65,6 +65,8 @@ namespace Gdb_monitor {
|
||||
|
||||
Region_map_client _address_space { _pd.address_space() };
|
||||
|
||||
Child::Initial_thread _initial_thread;
|
||||
|
||||
Child _child;
|
||||
|
||||
Genode::Rpc_entrypoint *_root_ep;
|
||||
@ -244,8 +246,9 @@ namespace Gdb_monitor {
|
||||
_cpu_root(&_entrypoint, env()->heap() /* should be _child.heap() */, &_gdb_stub_thread),
|
||||
_cpu_session(_get_cpu_session_cap()),
|
||||
_ram_session(ram_session),
|
||||
_initial_thread(_cpu_session, _pd.cap(), unique_name),
|
||||
_child(elf_ds, ldso_ds, _pd.cap(), _pd,
|
||||
_ram_session, _ram_session, _cpu_session, _cpu_session,
|
||||
_ram_session, _ram_session, _cpu_session, _initial_thread,
|
||||
*Genode::env()->rm_session(), _address_space, _entrypoint, *this),
|
||||
_root_ep(root_ep),
|
||||
_rom_service(&_entrypoint, _child.heap())
|
||||
|
@ -82,10 +82,10 @@ Cpu_session_component::create_thread(Capability<Pd_session> pd,
|
||||
}
|
||||
|
||||
|
||||
Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability thread)
|
||||
{
|
||||
return _parent_cpu_session.utcb(thread);
|
||||
}
|
||||
//Ram_dataspace_capability Cpu_session_component::utcb(Thread_capability thread)
|
||||
//{
|
||||
// return _parent_cpu_session.utcb(thread);
|
||||
//}
|
||||
|
||||
|
||||
void Cpu_session_component::kill_thread(Thread_capability thread_cap)
|
||||
@ -123,70 +123,69 @@ Thread_capability Cpu_session_component::next(Thread_capability thread_cap)
|
||||
}
|
||||
|
||||
|
||||
int Cpu_session_component::start(Thread_capability thread_cap,
|
||||
addr_t ip, addr_t sp)
|
||||
//int Cpu_session_component::start(Thread_capability thread_cap,
|
||||
// addr_t ip, addr_t sp)
|
||||
//{
|
||||
// Thread_info *thread_info = _thread_info(thread_cap);
|
||||
//
|
||||
// if (thread_info)
|
||||
// exception_handler(thread_cap, _exception_signal_receiver->manage(thread_info));
|
||||
//
|
||||
// int result = _parent_cpu_session.start(thread_cap, ip, sp);
|
||||
//
|
||||
// if (thread_info) {
|
||||
// /* pause the first thread */
|
||||
// if (thread_info->lwpid() == GENODE_LWP_BASE)
|
||||
// pause(thread_cap);
|
||||
//
|
||||
// genode_add_thread(thread_info->lwpid());
|
||||
// }
|
||||
//
|
||||
// return result;
|
||||
//}
|
||||
|
||||
|
||||
//void Cpu_session_component::pause(Thread_capability thread_cap)
|
||||
//{
|
||||
// _parent_cpu_session.pause(thread_cap);
|
||||
//}
|
||||
|
||||
|
||||
//void Cpu_session_component::resume(Thread_capability thread_cap)
|
||||
//{
|
||||
// _parent_cpu_session.resume(thread_cap);
|
||||
//}
|
||||
|
||||
|
||||
//void Cpu_session_component::cancel_blocking(Thread_capability thread_cap)
|
||||
//{
|
||||
// _parent_cpu_session.cancel_blocking(thread_cap);
|
||||
//}
|
||||
|
||||
|
||||
//void Cpu_session_component::state(Thread_capability thread_cap,
|
||||
// Thread_state const &state)
|
||||
//{
|
||||
// _parent_cpu_session.state(thread_cap, state);
|
||||
//}
|
||||
|
||||
|
||||
//Thread_state Cpu_session_component::state(Thread_capability thread_cap)
|
||||
//{
|
||||
// return _parent_cpu_session.state(thread_cap);
|
||||
//}
|
||||
|
||||
|
||||
void Cpu_session_component::exception_sigh(Signal_context_capability sigh_cap)
|
||||
{
|
||||
Thread_info *thread_info = _thread_info(thread_cap);
|
||||
|
||||
if (thread_info)
|
||||
exception_handler(thread_cap, _exception_signal_receiver->manage(thread_info));
|
||||
|
||||
int result = _parent_cpu_session.start(thread_cap, ip, sp);
|
||||
|
||||
if (thread_info) {
|
||||
/* pause the first thread */
|
||||
if (thread_info->lwpid() == GENODE_LWP_BASE)
|
||||
pause(thread_cap);
|
||||
|
||||
genode_add_thread(thread_info->lwpid());
|
||||
}
|
||||
|
||||
return result;
|
||||
_parent_cpu_session.exception_sigh(sigh_cap);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_session_component::pause(Thread_capability thread_cap)
|
||||
{
|
||||
_parent_cpu_session.pause(thread_cap);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_session_component::resume(Thread_capability thread_cap)
|
||||
{
|
||||
_parent_cpu_session.resume(thread_cap);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_session_component::cancel_blocking(Thread_capability thread_cap)
|
||||
{
|
||||
_parent_cpu_session.cancel_blocking(thread_cap);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_session_component::state(Thread_capability thread_cap,
|
||||
Thread_state const &state)
|
||||
{
|
||||
_parent_cpu_session.state(thread_cap, state);
|
||||
}
|
||||
|
||||
|
||||
Thread_state Cpu_session_component::state(Thread_capability thread_cap)
|
||||
{
|
||||
return _parent_cpu_session.state(thread_cap);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_session_component::exception_handler(Thread_capability thread_cap,
|
||||
Signal_context_capability sigh_cap)
|
||||
{
|
||||
_parent_cpu_session.exception_handler(thread_cap, sigh_cap);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_session_component::single_step(Thread_capability thread_cap, bool enable)
|
||||
{
|
||||
_parent_cpu_session.single_step(thread_cap, enable);
|
||||
}
|
||||
//void Cpu_session_component::single_step(Thread_capability thread_cap, bool enable)
|
||||
//{
|
||||
// _parent_cpu_session.single_step(thread_cap, enable);
|
||||
//}
|
||||
|
||||
|
||||
Affinity::Space Cpu_session_component::affinity_space() const
|
||||
@ -195,11 +194,11 @@ Affinity::Space Cpu_session_component::affinity_space() const
|
||||
}
|
||||
|
||||
|
||||
void Cpu_session_component::affinity(Thread_capability thread_cap,
|
||||
Affinity::Location location)
|
||||
{
|
||||
_parent_cpu_session.affinity(thread_cap, location);
|
||||
}
|
||||
//void Cpu_session_component::affinity(Thread_capability thread_cap,
|
||||
// Affinity::Location location)
|
||||
//{
|
||||
// _parent_cpu_session.affinity(thread_cap, location);
|
||||
//}
|
||||
|
||||
|
||||
Dataspace_capability Cpu_session_component::trace_control()
|
||||
@ -208,22 +207,22 @@ Dataspace_capability Cpu_session_component::trace_control()
|
||||
}
|
||||
|
||||
|
||||
unsigned Cpu_session_component::trace_control_index(Thread_capability thread)
|
||||
{
|
||||
return _parent_cpu_session.trace_control_index(thread);
|
||||
}
|
||||
//unsigned Cpu_session_component::trace_control_index(Thread_capability thread)
|
||||
//{
|
||||
// return _parent_cpu_session.trace_control_index(thread);
|
||||
//}
|
||||
|
||||
|
||||
Dataspace_capability Cpu_session_component::trace_buffer(Thread_capability thread)
|
||||
{
|
||||
return _parent_cpu_session.trace_buffer(thread);
|
||||
}
|
||||
//Dataspace_capability Cpu_session_component::trace_buffer(Thread_capability thread)
|
||||
//{
|
||||
// return _parent_cpu_session.trace_buffer(thread);
|
||||
//}
|
||||
|
||||
|
||||
Dataspace_capability Cpu_session_component::trace_policy(Thread_capability thread)
|
||||
{
|
||||
return _parent_cpu_session.trace_policy(thread);
|
||||
}
|
||||
//Dataspace_capability Cpu_session_component::trace_policy(Thread_capability thread)
|
||||
//{
|
||||
// return _parent_cpu_session.trace_policy(thread);
|
||||
//}
|
||||
|
||||
|
||||
Capability<Cpu_session::Native_cpu> Cpu_session_component::native_cpu()
|
||||
|
@ -58,23 +58,10 @@ class Cpu_session_component : public Rpc_object<Cpu_session>
|
||||
|
||||
Thread_capability create_thread(Capability<Pd_session>, Name const &,
|
||||
Affinity::Location, Weight, addr_t) override;
|
||||
Ram_dataspace_capability utcb(Thread_capability thread) override;
|
||||
void kill_thread(Thread_capability) override;
|
||||
int start(Thread_capability, addr_t, addr_t) override;
|
||||
void pause(Thread_capability thread_cap) override;
|
||||
void resume(Thread_capability thread_cap) override;
|
||||
void cancel_blocking(Thread_capability) override;
|
||||
Thread_state state(Thread_capability) override;
|
||||
void state(Thread_capability, Thread_state const &) override;
|
||||
void exception_handler(Thread_capability thread,
|
||||
Signal_context_capability handler) override;
|
||||
void single_step(Thread_capability thread, bool enable) override;
|
||||
void exception_sigh(Signal_context_capability handler) override;
|
||||
Affinity::Space affinity_space() const override;
|
||||
void affinity(Thread_capability, Affinity::Location) override;
|
||||
Dataspace_capability trace_control() override;
|
||||
unsigned trace_control_index(Thread_capability) override;
|
||||
Dataspace_capability trace_buffer(Thread_capability) override;
|
||||
Dataspace_capability trace_policy(Thread_capability) override;
|
||||
int ref_account(Cpu_session_capability c) override;
|
||||
int transfer_quota(Cpu_session_capability c, size_t q) override;
|
||||
Quota quota() override;
|
||||
|
@ -24,6 +24,7 @@ int linux_detach_one_lwp (struct inferior_list_entry *entry, void *args);
|
||||
#include <base/env.h>
|
||||
#include <base/printf.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <cpu_thread/client.h>
|
||||
|
||||
#include "cpu_session_component.h"
|
||||
|
||||
@ -113,7 +114,7 @@ extern "C" void genode_stop_all_threads()
|
||||
Thread_capability thread_cap = csc->first();
|
||||
|
||||
while (thread_cap.valid()) {
|
||||
csc->pause(thread_cap);
|
||||
Cpu_thread_client(thread_cap).pause();
|
||||
thread_cap = csc->next(thread_cap);
|
||||
}
|
||||
}
|
||||
@ -126,7 +127,7 @@ extern "C" void genode_resume_all_threads()
|
||||
Thread_capability thread_cap = csc->first();
|
||||
|
||||
while (thread_cap.valid()) {
|
||||
csc->resume(thread_cap);
|
||||
Cpu_thread_client(thread_cap).resume();
|
||||
thread_cap = csc->next(thread_cap);
|
||||
}
|
||||
}
|
||||
@ -162,7 +163,7 @@ void genode_interrupt_thread(unsigned long lwpid)
|
||||
return;
|
||||
}
|
||||
|
||||
csc->pause(thread_cap);
|
||||
Cpu_thread_client(thread_cap).pause();
|
||||
}
|
||||
|
||||
|
||||
@ -177,8 +178,9 @@ void genode_continue_thread(unsigned long lwpid, int single_step)
|
||||
return;
|
||||
}
|
||||
|
||||
csc->single_step(thread_cap, single_step);
|
||||
csc->resume(thread_cap);
|
||||
Cpu_thread_client cpu_thread(thread_cap);
|
||||
cpu_thread.single_step(single_step);
|
||||
cpu_thread.resume();
|
||||
}
|
||||
|
||||
|
||||
@ -206,7 +208,7 @@ unsigned long genode_find_segfault_lwpid()
|
||||
|
||||
try {
|
||||
|
||||
Thread_state thread_state = csc->state(thread_cap);
|
||||
Thread_state thread_state = Cpu_thread_client(thread_cap).state();
|
||||
|
||||
if (thread_state.unresolved_page_fault) {
|
||||
|
||||
@ -214,12 +216,12 @@ unsigned long genode_find_segfault_lwpid()
|
||||
* On base-foc it is necessary to pause the thread before
|
||||
* IP and SP are available in the thread state.
|
||||
*/
|
||||
csc->pause(thread_cap);
|
||||
Cpu_thread_client(thread_cap).pause();
|
||||
|
||||
return csc->lwpid(thread_cap);
|
||||
}
|
||||
|
||||
} catch (Cpu_session::State_access_failed) { }
|
||||
} catch (Cpu_thread::State_access_failed) { }
|
||||
|
||||
thread_cap = csc->next(thread_cap);
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ extern "C" {
|
||||
#define _private private
|
||||
}
|
||||
|
||||
#include <cpu_thread/client.h>
|
||||
|
||||
#include "cpu_session_component.h"
|
||||
#include "gdb_stub_thread.h"
|
||||
|
||||
@ -33,7 +35,9 @@ Thread_state get_current_thread_state()
|
||||
|
||||
ptid_t ptid = ((struct inferior_list_entry*)current_inferior)->id;
|
||||
|
||||
return csc->state(csc->thread_cap(ptid.lwp));
|
||||
Cpu_thread_client cpu_thread(csc->thread_cap(ptid.lwp));
|
||||
|
||||
return cpu_thread.state();
|
||||
}
|
||||
|
||||
void set_current_thread_state(Thread_state thread_state)
|
||||
@ -42,6 +46,8 @@ void set_current_thread_state(Thread_state thread_state)
|
||||
|
||||
ptid_t ptid = ((struct inferior_list_entry*)current_inferior)->id;
|
||||
|
||||
csc->state(csc->thread_cap(ptid.lwp), thread_state);
|
||||
Cpu_thread_client cpu_thread(csc->thread_cap(ptid.lwp));
|
||||
|
||||
cpu_thread.state(thread_state);
|
||||
}
|
||||
|
||||
|
@ -166,6 +166,8 @@ namespace Noux {
|
||||
|
||||
} _resources;
|
||||
|
||||
Genode::Child::Initial_thread _initial_thread;
|
||||
|
||||
Region_map_client _address_space { _pd.address_space() };
|
||||
|
||||
/**
|
||||
@ -359,6 +361,7 @@ namespace Noux {
|
||||
_entrypoint(cap_session, STACK_SIZE, "noux_process", false),
|
||||
_pd(binary_name, resources_ep, _ds_registry),
|
||||
_resources(binary_name, resources_ep, _ds_registry, _pd.core_pd_cap(), false),
|
||||
_initial_thread(_resources.cpu, _pd.cap(), binary_name),
|
||||
_args(ARGS_DS_SIZE, args),
|
||||
_env(env),
|
||||
_elf(binary_name, root_dir, root_dir->dataspace(binary_name)),
|
||||
@ -385,7 +388,7 @@ namespace Noux {
|
||||
_child(forked ? Dataspace_capability() : _elf._binary_ds,
|
||||
_ldso_ds, _pd.cap(), _pd,
|
||||
_resources.ram.cap(), _resources.ram,
|
||||
_resources.cpu.cap(), _resources.cpu,
|
||||
_resources.cpu.cap(), _initial_thread,
|
||||
*Genode::env()->rm_session(), _address_space,
|
||||
_entrypoint, _child_policy, _parent_pd_service,
|
||||
_parent_ram_service, _local_cpu_service)
|
||||
|
@ -27,6 +27,7 @@
|
||||
/* Genode includes */
|
||||
#include <base/rpc_server.h>
|
||||
#include <cpu_session/connection.h>
|
||||
#include <cpu_thread/client.h>
|
||||
|
||||
namespace Noux {
|
||||
|
||||
@ -69,7 +70,8 @@ namespace Noux {
|
||||
*/
|
||||
void start_main_thread(addr_t ip, addr_t sp)
|
||||
{
|
||||
_cpu.start(_threads[MAIN_THREAD_IDX], ip, sp);
|
||||
Capability<Cpu_thread> main_thread = _threads[MAIN_THREAD_IDX];
|
||||
Cpu_thread_client(main_thread).start(ip, sp);
|
||||
}
|
||||
|
||||
Cpu_session_capability cpu_cap() { return _cpu.cap(); }
|
||||
@ -106,9 +108,6 @@ namespace Noux {
|
||||
throw Thread_creation_failed();
|
||||
}
|
||||
|
||||
Ram_dataspace_capability utcb(Thread_capability thread) override {
|
||||
return _cpu.utcb(thread); }
|
||||
|
||||
void kill_thread(Thread_capability thread) override
|
||||
{
|
||||
/* purge local copy of thread capability */
|
||||
@ -119,55 +118,15 @@ namespace Noux {
|
||||
_cpu.kill_thread(thread);
|
||||
}
|
||||
|
||||
int start(Thread_capability thread, addr_t ip, addr_t sp) override
|
||||
{
|
||||
if (_forked) {
|
||||
PINF("defer attempt to start thread at ip 0x%lx", ip);
|
||||
return 0;
|
||||
}
|
||||
return _cpu.start(thread, ip, sp);
|
||||
}
|
||||
|
||||
void pause(Thread_capability thread) override {
|
||||
_cpu.pause(thread); }
|
||||
|
||||
void resume(Thread_capability thread) override {
|
||||
_cpu.resume(thread); }
|
||||
|
||||
void cancel_blocking(Thread_capability thread) override {
|
||||
_cpu.cancel_blocking(thread); }
|
||||
|
||||
Thread_state state(Thread_capability thread) override {
|
||||
return _cpu.state(thread); }
|
||||
|
||||
void state(Thread_capability thread, Thread_state const &state) override {
|
||||
_cpu.state(thread, state); }
|
||||
|
||||
void exception_handler(Thread_capability thread,
|
||||
Signal_context_capability handler) override {
|
||||
_cpu.exception_handler(thread, handler); }
|
||||
|
||||
void single_step(Thread_capability thread, bool enable) override {
|
||||
_cpu.single_step(thread, enable); }
|
||||
void exception_sigh(Signal_context_capability handler) override {
|
||||
_cpu.exception_sigh(handler); }
|
||||
|
||||
Affinity::Space affinity_space() const override {
|
||||
return _cpu.affinity_space(); }
|
||||
|
||||
void affinity(Thread_capability thread, Affinity::Location location) override {
|
||||
_cpu.affinity(thread, location); }
|
||||
|
||||
Dataspace_capability trace_control() override {
|
||||
return _cpu.trace_control(); }
|
||||
|
||||
unsigned trace_control_index(Thread_capability thread) override {
|
||||
return _cpu.trace_control_index(thread); }
|
||||
|
||||
Dataspace_capability trace_buffer(Thread_capability thread) override {
|
||||
return _cpu.trace_buffer(thread); }
|
||||
|
||||
Dataspace_capability trace_policy(Thread_capability thread) override {
|
||||
return _cpu.trace_policy(thread); }
|
||||
|
||||
Quota quota() override { return _cpu.quota(); }
|
||||
|
||||
int ref_account(Cpu_session_capability c) override {
|
||||
|
Loading…
Reference in New Issue
Block a user