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:
Norman Feske 2016-05-10 18:05:38 +02:00 committed by Christian Helmuth
parent 59aec6114b
commit a99989af40
66 changed files with 1261 additions and 1384 deletions

View File

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

View File

@ -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)

View File

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

View File

@ -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)

View File

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

View File

@ -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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)

View File

@ -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 */

View File

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

View File

@ -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_ */

View File

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

View File

@ -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_ */

View File

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

View File

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

View File

@ -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)),

View File

@ -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)

View File

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

View File

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

View File

@ -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)

View File

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

View File

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

View File

@ -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)

View File

@ -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)

View File

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

View File

@ -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,

View File

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

View File

@ -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;

View 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_ */

View 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_ */

View 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_ */

View File

@ -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_ */

View File

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

View File

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

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

View File

@ -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_ */

View 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_ */

View File

@ -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()),

View File

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

View File

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

View File

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

View File

@ -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) {

View File

@ -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:

View File

@ -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")
{

View File

@ -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) { }

View File

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

View File

@ -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),

View File

@ -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),

View File

@ -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)
{ }

View File

@ -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;

View File

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

View File

@ -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,

View File

@ -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)
{ }

View File

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

View File

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

View File

@ -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

View File

@ -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())

View File

@ -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()

View File

@ -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;

View File

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

View File

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

View File

@ -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)

View File

@ -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 {