diff --git a/repos/base-fiasco/src/core/pager.cc b/repos/base-fiasco/src/core/pager.cc
index cba6f257af..458125d76e 100644
--- a/repos/base-fiasco/src/core/pager.cc
+++ b/repos/base-fiasco/src/core/pager.cc
@@ -101,7 +101,9 @@ void Ipc_pager::acknowledge_wakeup()
Untyped_capability Pager_entrypoint::_pager_object_cap(unsigned long badge)
{
- return Capability_space::import(native_thread().l4id, Rpc_obj_key(badge));
+ return with_native_thread(
+ [&] (Native_thread &nt) { return Capability_space::import(nt.l4id, Rpc_obj_key(badge)); },
+ [&] { return Untyped_capability(); });
}
diff --git a/repos/base-fiasco/src/core/thread_start.cc b/repos/base-fiasco/src/core/thread_start.cc
index 53b4302d94..7c49f350fa 100644
--- a/repos/base-fiasco/src/core/thread_start.cc
+++ b/repos/base-fiasco/src/core/thread_start.cc
@@ -35,21 +35,30 @@ void Thread::_thread_start()
Thread::Start_result Thread::start()
{
+ if (!_stack)
+ return Start_result::DENIED;
+
+ Stack &stack = *_stack;
+
+ Native_thread &nt = stack.native_thread();
+
/* create and start platform thread */
- native_thread().pt = new (platform().core_mem_alloc())
- Platform_thread(platform_specific().core_pd(), _stack->name().string());
+ try {
+ nt.pt = new (platform().core_mem_alloc())
+ Platform_thread(platform_specific().core_pd(), stack.name().string());
+ }
+ catch (...) { return Start_result::DENIED; }
- native_thread().pt->pager(platform_specific().core_pager());
- native_thread().l4id = native_thread().pt->native_thread_id();
+ nt.pt->pager(platform_specific().core_pager());
+ nt.l4id = nt.pt->native_thread_id();
- native_thread().pt->start((void *)_thread_start, stack_top());
+ nt.pt->start((void *)_thread_start, (void *)stack.top());
return Start_result::OK;
}
-void Thread::_deinit_platform_thread()
+void Thread::_deinit_native_thread(Stack &stack)
{
- /* destruct platform thread */
- destroy(platform().core_mem_alloc(), native_thread().pt);
+ destroy(platform().core_mem_alloc(), stack.native_thread().pt);
}
diff --git a/repos/base-fiasco/src/include/base/internal/native_thread.h b/repos/base-fiasco/src/include/base/internal/native_thread.h
index 1234c529e5..cd32cd2400 100644
--- a/repos/base-fiasco/src/include/base/internal/native_thread.h
+++ b/repos/base-fiasco/src/include/base/internal/native_thread.h
@@ -15,7 +15,7 @@
#define _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_
/* Genode includes */
-#include
+#include
/* L4/Fiasco includes */
#include
@@ -25,9 +25,9 @@ namespace Core { struct Platform_thread; }
namespace Genode { struct Native_thread; }
-struct Genode::Native_thread
+struct Genode::Native_thread : Noncopyable
{
- Fiasco::l4_threadid_t l4id;
+ Fiasco::l4_threadid_t l4id { };
/**
* Only used in core
@@ -36,7 +36,9 @@ struct Genode::Native_thread
* thread object, which is going to be destroyed on destruction of the
* 'Thread'.
*/
- Core::Platform_thread *pt;
+ struct { Core::Platform_thread *pt = nullptr; };
+
+ Native_thread() { }
};
#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_ */
diff --git a/repos/base-fiasco/src/lib/base/thread_bootstrap.cc b/repos/base-fiasco/src/lib/base/thread_bootstrap.cc
index a2415bd40c..ce88819b54 100644
--- a/repos/base-fiasco/src/lib/base/thread_bootstrap.cc
+++ b/repos/base-fiasco/src/lib/base/thread_bootstrap.cc
@@ -42,7 +42,7 @@ void Genode::prepare_init_main_thread() { }
void Thread::_thread_bootstrap() { }
-void Thread::_init_platform_thread(size_t, Type type)
+void Thread::_init_native_thread(Stack &, size_t, Type type)
{
if (type == NORMAL) return;
diff --git a/repos/base-foc/include/foc/native_thread.h b/repos/base-foc/include/foc/native_thread.h
index 4fe5f7c130..724a578ed3 100644
--- a/repos/base-foc/include/foc/native_thread.h
+++ b/repos/base-foc/include/foc/native_thread.h
@@ -19,22 +19,21 @@
#define _INCLUDE__FOC__NATIVE_THREAD_H_
/* Genode includes */
-#include
+#include
#include
#include
namespace Genode { struct Native_thread; }
-struct Genode::Native_thread
+struct Genode::Native_thread : Noncopyable
{
- Foc::l4_cap_idx_t kcap = 0;
+ Foc::l4_cap_idx_t kcap { };
/* receive window for capability selectors received at the server side */
Receive_window rcv_window { };
Native_thread() { }
- explicit Native_thread(Foc::l4_cap_idx_t kcap) : kcap(kcap) { }
};
#endif /* _INCLUDE__FOC__NATIVE_THREAD_H_ */
diff --git a/repos/base-foc/src/core/thread_start.cc b/repos/base-foc/src/core/thread_start.cc
index 48a8d7afa5..6ef235f3ce 100644
--- a/repos/base-foc/src/core/thread_start.cc
+++ b/repos/base-foc/src/core/thread_start.cc
@@ -29,40 +29,13 @@
using namespace Core;
-void Thread::_deinit_platform_thread()
-{
- warning(__func__, ": not implemented yet!");
-}
+void Thread::_deinit_native_thread(Stack &) { }
-void Thread::_init_platform_thread(size_t, Type) { }
+void Thread::_init_native_thread(Stack &, size_t, Type) { }
-Thread::Start_result Thread::start()
-{
- using namespace Foc;
-
- /* create and start platform thread */
- Platform_thread &pt = *new (platform().core_mem_alloc())
- Platform_thread(_stack->name().string());
-
- platform_specific().core_pd().bind_thread(pt);
-
- l4_utcb_t * const foc_utcb = (l4_utcb_t *)(pt.utcb());
-
- native_thread() = Native_thread(pt.gate().remote);
-
- utcb()->foc_utcb = foc_utcb;
-
- _thread_cap =
- reinterpret_cap_cast(Native_capability(pt.thread().local));
-
- pt.pager(platform_specific().core_pager());
-
- l4_utcb_tcr_u(foc_utcb)->user[UTCB_TCR_BADGE] = (unsigned long) pt.gate().local.data();
- l4_utcb_tcr_u(foc_utcb)->user[UTCB_TCR_THREAD_OBJ] = (addr_t)this;
-
- pt.start((void *)_thread_start, stack_top());
+namespace {
struct Core_trace_source : public Core::Trace::Source::Info_accessor,
private Core::Trace::Control,
@@ -95,9 +68,9 @@ Thread::Start_result Thread::start()
}
return { Session_label("core"), thread.name(),
- Trace::Execution_time(ec_time, sc_time, 10000,
- platform_thread.prio()),
- thread._affinity };
+ Genode::Trace::Execution_time(ec_time, sc_time, 10000,
+ platform_thread.prio()),
+ thread.affinity() };
}
Core_trace_source(Core::Trace::Source_registry ®istry, Thread &t,
@@ -109,9 +82,44 @@ Thread::Start_result Thread::start()
registry.insert(this);
}
};
+}
- new (platform().core_mem_alloc()) Core_trace_source(Core::Trace::sources(),
- *this, pt);
+
+Thread::Start_result Thread::start()
+{
+ using namespace Foc;
+
+ try {
+ /* create and start platform thread */
+ Platform_thread &pt = *new (platform().core_mem_alloc())
+ Platform_thread(_stack->name().string());
+
+ platform_specific().core_pd().bind_thread(pt);
+
+ l4_utcb_t * const foc_utcb = (l4_utcb_t *)(pt.utcb());
+
+ with_native_thread([&] (Native_thread &nt) {
+ nt.kcap = pt.gate().remote; });
+
+ utcb()->foc_utcb = foc_utcb;
+
+ _thread_cap =
+ reinterpret_cap_cast(Native_capability(pt.thread().local));
+
+ pt.pager(platform_specific().core_pager());
+
+ l4_utcb_tcr_u(foc_utcb)->user[UTCB_TCR_BADGE] = (unsigned long) pt.gate().local.data();
+ l4_utcb_tcr_u(foc_utcb)->user[UTCB_TCR_THREAD_OBJ] = (addr_t)this;
+
+ pt.start((void *)_thread_start, stack_top());
+
+ try {
+ new (platform().core_mem_alloc())
+ Core_trace_source(Core::Trace::sources(), *this, pt);
+ }
+ catch (...) { }
+ }
+ catch (...) { return Start_result::DENIED; }
return Start_result::OK;
}
diff --git a/repos/base-foc/src/include/base/internal/lock_helper.h b/repos/base-foc/src/include/base/internal/lock_helper.h
index 3d2f16977f..861465909c 100644
--- a/repos/base-foc/src/include/base/internal/lock_helper.h
+++ b/repos/base-foc/src/include/base/internal/lock_helper.h
@@ -35,6 +35,17 @@
static inline void thread_yield() { Foc::l4_thread_yield(); }
+static inline Foc::l4_cap_idx_t foc_cap_idx(Genode::Thread *thread_ptr)
+{
+ if (!thread_ptr)
+ return Foc::MAIN_THREAD_CAP;
+
+ return thread_ptr->with_native_thread(
+ [&] (Genode::Native_thread &nt) { return nt.kcap; },
+ [&] { return Foc::MAIN_THREAD_CAP; });
+}
+
+
/**
* Custom ExchangeRegisters wrapper for waking up a thread
*
@@ -44,13 +55,9 @@ static inline void thread_yield() { Foc::l4_thread_yield(); }
*
* \return true if the thread was in blocking state
*/
-static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_base)
+static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_ptr)
{
- Foc::l4_cap_idx_t tid = thread_base ?
- thread_base->native_thread().kcap :
- Foc::MAIN_THREAD_CAP;
- Foc::l4_cap_idx_t irq = tid + Foc::THREAD_IRQ_CAP;
- Foc::l4_irq_trigger(irq);
+ Foc::l4_irq_trigger(foc_cap_idx(thread_ptr) + Foc::THREAD_IRQ_CAP);
return true;
}
@@ -58,12 +65,9 @@ static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_base)
/**
* Yield CPU time to the specified thread
*/
-static inline void thread_switch_to(Genode::Thread *thread_base)
+static inline void thread_switch_to(Genode::Thread *thread_ptr)
{
- Foc::l4_cap_idx_t tid = thread_base ?
- thread_base->native_thread().kcap :
- Foc::MAIN_THREAD_CAP;
- Foc::l4_thread_switch(tid);
+ Foc::l4_thread_switch(foc_cap_idx(thread_ptr));
}
@@ -78,13 +82,8 @@ __attribute__((used))
static void thread_stop_myself(Genode::Thread *)
{
using namespace Foc;
-
- Genode::Thread *myself = Genode::Thread::myself();
- Foc::l4_cap_idx_t tid = myself ?
- myself->native_thread().kcap :
- Foc::MAIN_THREAD_CAP;
- Foc::l4_cap_idx_t irq = tid + THREAD_IRQ_CAP;
- l4_irq_receive(irq, L4_IPC_NEVER);
+ l4_irq_receive(foc_cap_idx(Genode::Thread::myself()) + THREAD_IRQ_CAP,
+ L4_IPC_NEVER);
}
#endif /* _INCLUDE__BASE__INTERNAL__LOCK_HELPER_H_ */
diff --git a/repos/base-foc/src/lib/base/ipc.cc b/repos/base-foc/src/lib/base/ipc.cc
index f096586385..c42bff717a 100644
--- a/repos/base-foc/src/lib/base/ipc.cc
+++ b/repos/base-foc/src/lib/base/ipc.cc
@@ -310,52 +310,57 @@ Rpc_request Genode::ipc_reply_wait(Reply_capability const &,
Msgbuf_base &reply_msg,
Msgbuf_base &request_msg)
{
- Receive_window &rcv_window = Thread::myself()->native_thread().rcv_window;
+ return Thread::myself()->with_native_thread([&] (Native_thread &nt) {
- bool need_to_wait = false;
+ Receive_window &rcv_window = nt.rcv_window;
- for (;;) {
+ bool need_to_wait = false;
- request_msg.reset();
+ for (;;) {
- /* prepare receive window in UTCB */
- addr_t rcv_cap_sel = rcv_window.rcv_cap_sel_base();
- for (size_t i = 0; i < Msgbuf_base::MAX_CAPS_PER_MSG; i++) {
- l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
- rcv_cap_sel += L4_CAP_SIZE;
+ request_msg.reset();
+
+ /* prepare receive window in UTCB */
+ addr_t rcv_cap_sel = rcv_window.rcv_cap_sel_base();
+ for (size_t i = 0; i < Msgbuf_base::MAX_CAPS_PER_MSG; i++) {
+ l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
+ rcv_cap_sel += L4_CAP_SIZE;
+ }
+ l4_utcb_br()->bdr &= ~L4_BDR_OFFSET_MASK;
+
+ l4_msgtag_t request_tag;
+ l4_umword_t label = 0; /* kernel-protected label of invoked capability */
+
+ if (exc.value != Rpc_exception_code::INVALID_OBJECT && !need_to_wait) {
+
+ l4_msgtag_t const reply_tag = copy_msgbuf_to_utcb(reply_msg, exc.value);
+
+ request_tag = l4_ipc_reply_and_wait(l4_utcb(), reply_tag, &label, L4_IPC_SEND_TIMEOUT_0);
+ } else {
+ request_tag = l4_ipc_wait(l4_utcb(), &label, L4_IPC_NEVER);
+ }
+
+ if (ipc_error(request_tag, false)) {
+ need_to_wait = true;
+ continue;
+ } else need_to_wait = false;
+
+ /* copy request message from the UTCBs message registers */
+ unsigned long const badge =
+ extract_msg_from_utcb(request_tag, rcv_window, request_msg);
+
+ /* ignore request if we detect a forged badge */
+ if (!badge_matches_label(badge, label)) {
+ raw("badge does not match label, ignoring request");
+ continue;
+ }
+
+ return Rpc_request(Native_capability(), badge);
}
- l4_utcb_br()->bdr &= ~L4_BDR_OFFSET_MASK;
-
- l4_msgtag_t request_tag;
- l4_umword_t label = 0; /* kernel-protected label of invoked capability */
-
- if (exc.value != Rpc_exception_code::INVALID_OBJECT
- && !need_to_wait) {
-
- l4_msgtag_t const reply_tag = copy_msgbuf_to_utcb(reply_msg, exc.value);
-
- request_tag = l4_ipc_reply_and_wait(l4_utcb(), reply_tag, &label, L4_IPC_SEND_TIMEOUT_0);
- } else {
- request_tag = l4_ipc_wait(l4_utcb(), &label, L4_IPC_NEVER);
- }
-
- if (ipc_error(request_tag, false)) {
- need_to_wait = true;
- continue;
- } else need_to_wait = false;
-
- /* copy request message from the UTCBs message registers */
- unsigned long const badge =
- extract_msg_from_utcb(request_tag, rcv_window, request_msg);
-
- /* ignore request if we detect a forged badge */
- if (!badge_matches_label(badge, label)) {
- raw("badge does not match label, ignoring request");
- continue;
- }
-
- return Rpc_request(Native_capability(), badge);
- }
+ },
+ [&] () -> Rpc_request {
+ sleep_forever(); /* ipc_reply_wait called by uninitialized thread */
+ });
}
@@ -363,7 +368,8 @@ Ipc_server::Ipc_server()
:
Native_capability((Cap_index*)Foc::l4_utcb_tcr()->user[Foc::UTCB_TCR_BADGE])
{
- Thread::myself()->native_thread().rcv_window.init();
+ Thread::myself()->with_native_thread([&] (Native_thread &nt) {
+ nt.rcv_window.init(); });
}
diff --git a/repos/base-foc/src/lib/base/thread_start.cc b/repos/base-foc/src/lib/base/thread_start.cc
index 92d6e1f07f..9ecfe9cef1 100644
--- a/repos/base-foc/src/lib/base/thread_start.cc
+++ b/repos/base-foc/src/lib/base/thread_start.cc
@@ -46,11 +46,11 @@ static Thread_capability main_thread_cap(Thread_capability main_cap = { })
}
-void Thread::_deinit_platform_thread()
+void Thread::_deinit_native_thread(Stack &stack)
{
using namespace Foc;
- if (native_thread().kcap) {
+ if (stack.native_thread().kcap) {
Cap_index *i = (Cap_index*)l4_utcb_tcr_u(utcb()->foc_utcb)->user[UTCB_TCR_BADGE];
cap_map().remove(i);
}
@@ -61,7 +61,7 @@ void Thread::_deinit_platform_thread()
}
-void Thread::_init_platform_thread(size_t weight, Type type)
+void Thread::_init_native_thread(Stack &stack, size_t weight, Type type)
{
_init_cpu_session_and_trace_control();
@@ -74,7 +74,7 @@ void Thread::_init_platform_thread(size_t weight, Type type)
}
/* adjust values whose computation differs for a main thread */
- native_thread().kcap = Foc::MAIN_THREAD_CAP;
+ stack.native_thread().kcap = Foc::MAIN_THREAD_CAP;
_thread_cap = main_thread_cap();
if (_thread_cap.failed()) {
@@ -104,7 +104,8 @@ Thread::Start_result Thread::start()
Foc::l4_utcb_t * const foc_utcb = (Foc::l4_utcb_t *)state.utcb;
utcb()->foc_utcb = foc_utcb;
- native_thread() = Native_thread(state.kcap);
+ with_native_thread([&] (Native_thread &nt) {
+ nt.kcap = state.kcap; });
Cap_index *i = cap_map().insert(state.id, state.kcap);
l4_utcb_tcr_u(foc_utcb)->user[UTCB_TCR_BADGE] = (unsigned long) i;
diff --git a/repos/base-foc/src/lib/base/x86/vm.cc b/repos/base-foc/src/lib/base/x86/vm.cc
index a8fb4d598e..ac493368cf 100644
--- a/repos/base-foc/src/lib/base/x86/vm.cc
+++ b/repos/base-foc/src/lib/base/x86/vm.cc
@@ -423,9 +423,11 @@ struct Foc_vcpu : Thread, Noncopyable
/* consume notification */
while (vcpu->sticky_flags) {
- Foc::l4_cap_idx_t tid = native_thread().kcap;
- Foc::l4_cap_idx_t irq = tid + Foc::TASK_VCPU_IRQ_CAP;
- l4_irq_receive(irq, L4_IPC_RECV_TIMEOUT_0);
+ with_native_thread([&] (Native_thread &nt) {
+ Foc::l4_cap_idx_t tid = nt.kcap;
+ Foc::l4_cap_idx_t irq = tid + Foc::TASK_VCPU_IRQ_CAP;
+ l4_irq_receive(irq, L4_IPC_RECV_TIMEOUT_0);
+ });
}
}
}
@@ -449,9 +451,11 @@ struct Foc_vcpu : Thread, Noncopyable
/* consume notification */
while (vcpu->sticky_flags) {
- Foc::l4_cap_idx_t tid = native_thread().kcap;
- Foc::l4_cap_idx_t irq = tid + Foc::TASK_VCPU_IRQ_CAP;
- l4_irq_receive(irq, L4_IPC_RECV_TIMEOUT_0);
+ with_native_thread([&] (Native_thread &nt) {
+ Foc::l4_cap_idx_t tid = nt.kcap;
+ Foc::l4_cap_idx_t irq = tid + Foc::TASK_VCPU_IRQ_CAP;
+ l4_irq_receive(irq, L4_IPC_RECV_TIMEOUT_0);
+ });
}
}
@@ -1341,9 +1345,11 @@ struct Foc_vcpu : Thread, Noncopyable
_state_request = PAUSE;
/* Trigger vCPU exit */
- Foc::l4_cap_idx_t tid = native_thread().kcap;
- Foc::l4_cap_idx_t irq = tid + Foc::TASK_VCPU_IRQ_CAP;
- Foc::l4_irq_trigger(irq);
+ with_native_thread([&] (Native_thread &nt) {
+ Foc::l4_cap_idx_t tid = nt.kcap;
+ Foc::l4_cap_idx_t irq = tid + Foc::TASK_VCPU_IRQ_CAP;
+ Foc::l4_irq_trigger(irq);
+ });
_wake_up.up();
}
diff --git a/repos/base-foc/src/timer/foc/component.cc b/repos/base-foc/src/timer/foc/component.cc
index 7058c5fde2..38ce2cace1 100644
--- a/repos/base-foc/src/timer/foc/component.cc
+++ b/repos/base-foc/src/timer/foc/component.cc
@@ -134,7 +134,7 @@ class Timer::Device
void entry() override
{
- _myself = native_thread().kcap;
+ with_native_thread([&] (Native_thread &nt) { _myself = nt.kcap; });
for (;;) {
diff --git a/repos/base-hw/src/core/pager.cc b/repos/base-hw/src/core/pager.cc
index 98855756a8..157ed2b123 100644
--- a/repos/base-hw/src/core/pager.cc
+++ b/repos/base-hw/src/core/pager.cc
@@ -199,12 +199,11 @@ void Pager_entrypoint::dissolve(Pager_object &o)
Pager_capability Pager_entrypoint::manage(Pager_object &o)
{
unsigned const cpu = o.location().xpos();
- if (cpu >= _cpus) {
+ if (cpu >= _cpus)
error("Invalid location of pager object ", cpu);
- } else {
- o.start_paging(_threads[cpu]._kobj,
- *_threads[cpu].native_thread().platform_thread);
- }
+ else
+ _threads[cpu].with_native_thread([&] (Native_thread &nt) {
+ o.start_paging(_threads[cpu]._kobj, *nt.platform_thread); });
return reinterpret_cap_cast(o.cap());
}
diff --git a/repos/base-hw/src/core/thread_start.cc b/repos/base-hw/src/core/thread_start.cc
index 9c811da98f..a736fc2656 100644
--- a/repos/base-hw/src/core/thread_start.cc
+++ b/repos/base-hw/src/core/thread_start.cc
@@ -32,13 +32,7 @@ using namespace Core;
namespace Hw { extern Untyped_capability _main_thread_cap; }
-Thread::Start_result Thread::start()
-{
- /* start thread with stack pointer at the top of stack */
- native_thread().platform_thread->start((void *)&_thread_start, stack_top());
-
- if (_thread_cap.failed())
- return Start_result::DENIED;
+namespace {
struct Trace_source : public Core::Trace::Source::Info_accessor,
private Core::Trace::Control,
@@ -51,11 +45,11 @@ Thread::Start_result Thread::start()
*/
Info trace_source_info() const override
{
- Platform_thread * t = thread.native_thread().platform_thread;
+ Genode::Trace::Execution_time execution_time { 0, 0 };
- Trace::Execution_time execution_time { 0, 0 };
- if (t)
- execution_time = t->execution_time();
+ thread.with_native_thread([&] (Native_thread &nt) {
+ if (nt.platform_thread)
+ execution_time = nt.platform_thread->execution_time(); });
return { Session_label("core"), thread.name(),
execution_time, thread.affinity() };
@@ -70,34 +64,52 @@ Thread::Start_result Thread::start()
registry.insert(this);
}
};
+}
+
+
+Thread::Start_result Thread::start()
+{
+ if (!_stack)
+ return Start_result::DENIED;
+
+ Stack &stack = *_stack;
+
+ Native_thread &nt = stack.native_thread();
+
+ /* start thread with stack pointer at the top of stack */
+ nt.platform_thread->start((void *)&_thread_start, (void *)stack.top());
+
+ if (_thread_cap.failed())
+ return Start_result::DENIED;;
/* create trace sources for core threads */
- new (platform().core_mem_alloc()) Trace_source(Core::Trace::sources(), *this);
+ try {
+ new (platform().core_mem_alloc()) Trace_source(Core::Trace::sources(), *this);
+ } catch (...) { }
return Start_result::OK;
}
-void Thread::_deinit_platform_thread()
+void Thread::_deinit_native_thread(Stack &stack)
{
- /* destruct platform thread */
- destroy(platform().core_mem_alloc(), native_thread().platform_thread);
+ destroy(platform().core_mem_alloc(), stack.native_thread().platform_thread);
}
-void Thread::_init_platform_thread(size_t, Type type)
+void Thread::_init_native_thread(Stack &stack, size_t, Type type)
{
if (type == NORMAL) {
- native_thread().platform_thread = new (platform().core_mem_alloc())
- Platform_thread(_stack->name(), _stack->utcb());
+ stack.native_thread().platform_thread = new (platform().core_mem_alloc())
+ Platform_thread(_stack->name(), stack.utcb());
return;
}
/* remap initial main-thread UTCB according to stack-area spec */
map_local(Platform::core_main_thread_phys_utcb(),
- (addr_t)&_stack->utcb(),
+ (addr_t)&stack.utcb(),
max(sizeof(Native_utcb) / get_page_size(), (size_t)1));
/* adjust initial object state in case of a main thread */
- native_thread().cap = Hw::_main_thread_cap;
+ stack.native_thread().cap = Hw::_main_thread_cap;
}
diff --git a/repos/base-hw/src/include/base/internal/lock_helper.h b/repos/base-hw/src/include/base/internal/lock_helper.h
index 6e6e4e9bb8..5bb6c46686 100644
--- a/repos/base-hw/src/include/base/internal/lock_helper.h
+++ b/repos/base-hw/src/include/base/internal/lock_helper.h
@@ -32,11 +32,16 @@ static inline void thread_yield() { Kernel::yield_thread(); }
/**
* Return kernel name of thread t
*/
-static inline Kernel::capid_t
-native_thread_id(Genode::Thread * const t)
+static inline Kernel::capid_t native_thread_id(Genode::Thread *thread_ptr)
{
using Genode::Capability_space::capid;
- return t ? capid(t->native_thread().cap) : capid(Hw::_main_thread_cap);
+
+ if (!thread_ptr)
+ return capid(Hw::_main_thread_cap);
+
+ return thread_ptr->with_native_thread(
+ [&] (Genode::Native_thread &nt) { return capid(nt.cap); },
+ [&] { return Kernel::cap_id_invalid(); });
}
@@ -52,10 +57,9 @@ static inline void thread_switch_to(Genode::Thread *)
/**
* Resume thread t and return wether t was paused or not
*/
-static inline bool
-thread_check_stopped_and_restart(Genode::Thread * const t)
+static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_ptr)
{
- return Kernel::restart_thread(native_thread_id(t));
+ return Kernel::restart_thread(native_thread_id(thread_ptr));
}
diff --git a/repos/base-hw/src/include/base/internal/native_thread.h b/repos/base-hw/src/include/base/internal/native_thread.h
index fa412db38e..4c80e05e38 100644
--- a/repos/base-hw/src/include/base/internal/native_thread.h
+++ b/repos/base-hw/src/include/base/internal/native_thread.h
@@ -14,19 +14,21 @@
#ifndef _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_
#define _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_
-#include
+#include
#include
namespace Genode { struct Native_thread; }
-
namespace Core { class Platform_thread; }
-struct Genode::Native_thread
+struct Genode::Native_thread : Noncopyable
{
- Core::Platform_thread *platform_thread;
- Native_capability cap;
+ Native_capability cap { };
+
+ struct { Core::Platform_thread *platform_thread; };
+
+ Native_thread() { }
};
#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_ */
diff --git a/repos/base-hw/src/lib/base/ipc.cc b/repos/base-hw/src/lib/base/ipc.cc
index 0bd382cb04..509ef198d2 100644
--- a/repos/base-hw/src/lib/base/ipc.cc
+++ b/repos/base-hw/src/lib/base/ipc.cc
@@ -165,11 +165,18 @@ Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &,
}
-Ipc_server::Ipc_server()
-:
- Native_capability(Thread::myself() ? Thread::myself()->native_thread().cap
- : Hw::_main_thread_cap)
-{ }
+static inline Native_capability my_native_thread_cap()
+{
+ if (!Thread::myself())
+ return Hw::_main_thread_cap;
+
+ return Thread::myself()->with_native_thread(
+ [&] (Native_thread &nt) { return nt.cap; },
+ [&] { return Native_capability(); });
+}
+
+
+Ipc_server::Ipc_server() : Native_capability(my_native_thread_cap()) { }
Ipc_server::~Ipc_server() { }
diff --git a/repos/base-hw/src/lib/base/thread_bootstrap.cc b/repos/base-hw/src/lib/base/thread_bootstrap.cc
index 77e6dd0303..fef7068771 100644
--- a/repos/base-hw/src/lib/base/thread_bootstrap.cc
+++ b/repos/base-hw/src/lib/base/thread_bootstrap.cc
@@ -84,8 +84,10 @@ void Thread::_thread_start()
void Thread::_thread_bootstrap()
{
- Kernel::capid_t capid = myself()->utcb()->cap_get(Native_utcb::THREAD_MYSELF);
- native_thread().cap = Capability_space::import(capid);
- if (native_thread().cap.valid())
- Kernel::ack_cap(Capability_space::capid(native_thread().cap));
+ with_native_thread([&] (Native_thread &nt) {
+ Kernel::capid_t capid = myself()->utcb()->cap_get(Native_utcb::THREAD_MYSELF);
+ nt.cap = Capability_space::import(capid);
+ if (nt.cap.valid())
+ Kernel::ack_cap(Capability_space::capid(nt.cap));
+ });
}
diff --git a/repos/base-hw/src/lib/base/thread_start.cc b/repos/base-hw/src/lib/base/thread_start.cc
index 4416750504..e49049362d 100644
--- a/repos/base-hw/src/lib/base/thread_start.cc
+++ b/repos/base-hw/src/lib/base/thread_start.cc
@@ -51,14 +51,14 @@ static Thread_capability main_thread_cap(Thread_capability main_cap = { })
** Thread **
************/
-void Thread::_init_platform_thread(size_t weight, Type type)
+void Thread::_init_native_thread(Stack &stack, size_t weight, Type type)
{
_init_cpu_session_and_trace_control();
if (type == NORMAL) {
/* create server object */
- addr_t const utcb = (addr_t)&_stack->utcb();
+ addr_t const utcb = (addr_t)&stack.utcb();
_thread_cap = _cpu_session->create_thread(pd_session_cap(), name(), _affinity,
Weight(weight), utcb);
@@ -67,7 +67,7 @@ void Thread::_init_platform_thread(size_t weight, Type type)
/* if we got reinitialized we have to get rid of the old UTCB */
size_t const utcb_size = sizeof(Native_utcb);
addr_t const stack_area = stack_area_virtual_base();
- addr_t const utcb_new = (addr_t)&_stack->utcb() - stack_area;
+ addr_t const utcb_new = (addr_t)&stack.utcb() - stack_area;
/* remap initial main-thread UTCB according to stack-area spec */
if (env_stack_area_region_map->attach(Hw::_main_thread_utcb_ds, {
@@ -81,12 +81,12 @@ void Thread::_init_platform_thread(size_t weight, Type type)
error("failed to attach UTCB to local address space");
/* adjust initial object state in case of a main thread */
- native_thread().cap = Hw::_main_thread_cap;
+ stack.native_thread().cap = Hw::_main_thread_cap;
_thread_cap = main_thread_cap();
}
-void Thread::_deinit_platform_thread()
+void Thread::_deinit_native_thread(Stack &stack)
{
if (!_cpu_session) {
error("Thread::_cpu_session unexpectedly not defined");
@@ -98,8 +98,8 @@ void Thread::_deinit_platform_thread()
[&] (Cpu_session::Create_thread_error) { });
/* detach userland stack */
- size_t const size = sizeof(_stack->utcb());
- addr_t utcb = Stack_allocator::addr_to_base(_stack) +
+ size_t const size = sizeof(stack.utcb());
+ addr_t utcb = Stack_allocator::addr_to_base(&stack) +
stack_virtual_size() - size - stack_area_virtual_base();
env_stack_area_region_map->detach(utcb);
}
@@ -107,6 +107,11 @@ void Thread::_deinit_platform_thread()
Thread::Start_result Thread::start()
{
+ if (!_stack)
+ return Start_result::DENIED;
+
+ Stack &stack = *_stack;
+
while (avail_capability_slab() < 5)
upgrade_capability_slab();
@@ -115,19 +120,19 @@ Thread::Start_result Thread::start()
Cpu_thread_client cpu_thread(cap);
/* attach UTCB at top of stack */
- size_t const size = sizeof(_stack->utcb());
+ size_t const size = sizeof(stack.utcb());
return env_stack_area_region_map->attach(cpu_thread.utcb(), {
.size = size,
.offset = { },
.use_at = true,
- .at = Stack_allocator::addr_to_base(_stack)
+ .at = Stack_allocator::addr_to_base(&stack)
+ stack_virtual_size() - size - stack_area_virtual_base(),
.executable = { },
.writeable = true
}).convert(
[&] (Region_map::Range) {
/* start execution with initial IP and aligned SP */
- cpu_thread.start((addr_t)_thread_start, _stack->top());
+ cpu_thread.start((addr_t)_thread_start, stack.top());
return Start_result::OK;
},
[&] (Region_map::Attach_error) {
diff --git a/repos/base-linux/src/core/core_rpc_cap_alloc.cc b/repos/base-linux/src/core/core_rpc_cap_alloc.cc
index f086920b74..a923cc9c84 100644
--- a/repos/base-linux/src/core/core_rpc_cap_alloc.cc
+++ b/repos/base-linux/src/core/core_rpc_cap_alloc.cc
@@ -27,11 +27,14 @@ void Genode::init_rpc_cap_alloc(Parent &) { }
Native_capability Rpc_entrypoint::_alloc_rpc_cap(Pd_session &, Native_capability,
addr_t)
{
- return Thread::native_thread().epoll.alloc_rpc_cap();
+ return with_native_thread(
+ [&] (Native_thread &nt) { return nt.epoll.alloc_rpc_cap(); },
+ [&] { return Native_capability(); });
}
void Rpc_entrypoint::_free_rpc_cap(Pd_session &, Native_capability cap)
{
- Thread::native_thread().epoll.free_rpc_cap(cap);
+ with_native_thread([&] (Native_thread &nt) {
+ nt.epoll.free_rpc_cap(cap); });
}
diff --git a/repos/base-linux/src/core/thread_linux.cc b/repos/base-linux/src/core/thread_linux.cc
index beb5d34882..46f326df54 100644
--- a/repos/base-linux/src/core/thread_linux.cc
+++ b/repos/base-linux/src/core/thread_linux.cc
@@ -58,15 +58,19 @@ void Thread::_thread_start()
}
-void Thread::_init_platform_thread(size_t, Type) { }
+void Thread::_init_native_thread(Stack &, size_t, Type) { }
-void Thread::_deinit_platform_thread() { }
+void Thread::_deinit_native_thread(Stack &) { }
Thread::Start_result Thread::start()
{
- native_thread().tid = lx_create_thread(Thread::_thread_start, stack_top());
- native_thread().pid = lx_getpid();
- return Start_result::OK;
+ return with_native_thread(
+ [&] (Native_thread &nt) {
+ nt.tid = lx_create_thread(Thread::_thread_start, stack_top());
+ nt.pid = lx_getpid();
+ return Start_result::OK;
+ },
+ [&] { return Start_result::DENIED; });
}
diff --git a/repos/base-linux/src/include/base/internal/lock_helper.h b/repos/base-linux/src/include/base/internal/lock_helper.h
index 37321ae45c..87c880c391 100644
--- a/repos/base-linux/src/include/base/internal/lock_helper.h
+++ b/repos/base-linux/src/include/base/internal/lock_helper.h
@@ -37,12 +37,23 @@ static inline void thread_yield()
}
-static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_base)
+static inline int *futex_counter_ptr(Genode::Thread *thread_ptr)
{
- const int *futex_counter_ptr = thread_base ?
- &thread_base->native_thread().futex_counter :
- &main_thread_futex_counter;
- return lx_futex(futex_counter_ptr, LX_FUTEX_WAKE, 1);
+ if (!thread_ptr)
+ return &main_thread_futex_counter;
+
+ return thread_ptr->with_native_thread(
+ [&] (Genode::Native_thread &nt) { return &nt.futex_counter; },
+ [&] {
+ Genode::error("attempt to access futex of invalid thread");
+ return (int *)nullptr;
+ });
+}
+
+
+static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_ptr)
+{
+ return lx_futex(futex_counter_ptr(thread_ptr), LX_FUTEX_WAKE, 1);
}
@@ -56,10 +67,7 @@ static inline void thread_stop_myself(Genode::Thread *myself)
* 'thread_check_stopped_and_restart()' function will get called
* repeatedly until this thread has actually executed the syscall.
*/
- const int *futex_counter_ptr = myself ?
- &myself->native_thread().futex_counter :
- &main_thread_futex_counter;
- lx_futex(futex_counter_ptr, LX_FUTEX_WAIT, 0);
+ lx_futex(futex_counter_ptr(myself), LX_FUTEX_WAIT, 0);
}
#endif /* _INCLUDE__BASE__INTERNAL__LOCK_HELPER_H_ */
diff --git a/repos/base-linux/src/include/base/internal/native_thread.h b/repos/base-linux/src/include/base/internal/native_thread.h
index 9f7740fd39..6eda9989ad 100644
--- a/repos/base-linux/src/include/base/internal/native_thread.h
+++ b/repos/base-linux/src/include/base/internal/native_thread.h
@@ -22,92 +22,82 @@
namespace Genode { struct Native_thread; }
-class Genode::Native_thread
+struct Genode::Native_thread : Noncopyable
{
- private:
+ /*
+ * Unfortunately, both - PID and TID - are needed for lx_tgkill()
+ */
+ unsigned int tid = 0; /* Native thread ID type as returned by the
+ 'clone' system call */
+ unsigned int pid = 0; /* process ID (resp. thread-group ID) */
- /*
- * Noncopyable
- */
- Native_thread(Native_thread const &);
- Native_thread &operator = (Native_thread const &);
+ bool is_ipc_server = false;
- public:
+ /**
+ * Natively aligned memory location used in the lock implementation
+ */
+ int futex_counter __attribute__((aligned(sizeof(Genode::addr_t)))) = 0;
- /*
- * Unfortunately, both - PID and TID - are needed for lx_tgkill()
- */
- unsigned int tid = 0; /* Native thread ID type as returned by the
- 'clone' system call */
- unsigned int pid = 0; /* process ID (resp. thread-group ID) */
+ struct Meta_data;
- bool is_ipc_server = false;
+ /**
+ * Opaque pointer to additional thread-specific meta data
+ *
+ * This pointer is used by hybrid Linux/Genode programs to maintain
+ * POSIX-thread-related meta data. For non-hybrid Genode programs, it
+ * remains unused.
+ */
+ struct { Meta_data *meta_data = nullptr; };
- /**
- * Natively aligned memory location used in the lock implementation
- */
- int futex_counter __attribute__((aligned(sizeof(Genode::addr_t)))) = 0;
+ class Epoll
+ {
+ private:
- struct Meta_data;
+ Lx_socketpair _control { };
- /**
- * Opaque pointer to additional thread-specific meta data
- *
- * This pointer is used by hybrid Linux/Genode programs to maintain
- * POSIX-thread-related meta data. For non-hybrid Genode programs, it
- * remains unused.
- */
- Meta_data *meta_data = nullptr;
+ Lx_epoll_sd const _epoll;
- class Epoll
- {
- private:
+ void _add (Lx_sd);
+ void _remove(Lx_sd);
- Lx_socketpair _control { };
+ bool _rpc_ep_exited = false;
- Lx_epoll_sd const _epoll;
+ struct Control_function : Interface
+ {
+ virtual void execute() = 0;
+ };
- void _add (Lx_sd);
- void _remove(Lx_sd);
+ /*
+ * Execute functor 'fn' in the context of the 'poll' method.
+ */
+ void _exec_control(auto const &fn);
- bool _rpc_ep_exited = false;
+ public:
- struct Control_function : Interface
- {
- virtual void execute() = 0;
- };
+ Epoll();
- /*
- * Execute functor 'fn' in the context of the 'poll' method.
- */
- void _exec_control(auto const &fn);
+ ~Epoll();
- public:
+ /**
+ * Wait for incoming RPC messages
+ *
+ * \return valid socket descriptor that matches the invoked
+ * RPC object
+ */
+ Lx_sd poll();
- Epoll();
+ Native_capability alloc_rpc_cap();
- ~Epoll();
+ void free_rpc_cap(Native_capability);
- /**
- * Wait for incoming RPC messages
- *
- * \return valid socket descriptor that matches the invoked
- * RPC object
- */
- Lx_sd poll();
+ /**
+ * Flag RPC entrypoint as no longer in charge of dispatching
+ */
+ void rpc_ep_exited() { _rpc_ep_exited = true; }
- Native_capability alloc_rpc_cap();
+ } epoll { };
- void free_rpc_cap(Native_capability);
-
- /**
- * Flag RPC entrypoint as no longer in charge of dispatching
- */
- void rpc_ep_exited() { _rpc_ep_exited = true; }
-
- } epoll { };
-
- Native_thread() { }
+ Native_thread() { }
};
#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_ */
diff --git a/repos/base-linux/src/lib/base/ipc.cc b/repos/base-linux/src/lib/base/ipc.cc
index 2683db3256..f0e62580ad 100644
--- a/repos/base-linux/src/lib/base/ipc.cc
+++ b/repos/base-linux/src/lib/base/ipc.cc
@@ -392,36 +392,38 @@ Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
for (;;) lx_nanosleep(&ts, 0);
}
- Native_thread::Epoll &epoll = myself_ptr->native_thread().epoll;
+ return myself_ptr->with_native_thread([&] (Native_thread &nt) {
- for (;;) {
+ for (;;) {
- Lx_sd const selected_sd = epoll.poll();
+ Lx_sd const selected_sd = nt.epoll.poll();
- Protocol_header &header = request_msg.header();
- Message msg(header.msg_start(), sizeof(Protocol_header) + request_msg.capacity());
+ Protocol_header &header = request_msg.header();
+ Message msg(header.msg_start(), sizeof(Protocol_header) + request_msg.capacity());
- msg.accept_sockets(Message::MAX_SDS_PER_MSG);
+ msg.accept_sockets(Message::MAX_SDS_PER_MSG);
- request_msg.reset();
- int const ret = lx_recvmsg(selected_sd, msg.msg(), 0x40);
+ request_msg.reset();
+ int const ret = lx_recvmsg(selected_sd, msg.msg(), 0x40);
- if (ret < 0)
- continue;
+ if (ret < 0)
+ continue;
- if (msg.num_sockets() == 0 || !msg.socket_at_index(0).valid()) {
- warning("ipc_reply_wait: failed to obtain reply socket");
- continue;
+ if (msg.num_sockets() == 0 || !msg.socket_at_index(0).valid()) {
+ warning("ipc_reply_wait: failed to obtain reply socket");
+ continue;
+ }
+
+ Lx_sd const reply_socket = msg.socket_at_index(0);
+
+ /* start at offset 1 to skip the reply channel */
+ extract_sds_from_message(1, msg, header, request_msg);
+
+ return Rpc_request(Capability_space::import(Rpc_destination(reply_socket),
+ Rpc_obj_key()), selected_sd.value);
}
- Lx_sd const reply_socket = msg.socket_at_index(0);
-
- /* start at offset 1 to skip the reply channel */
- extract_sds_from_message(1, msg, header, request_msg);
-
- return Rpc_request(Capability_space::import(Rpc_destination(reply_socket),
- Rpc_obj_key()), selected_sd.value);
- }
+ }, [&] () -> Rpc_request { sleep_forever(); });
}
@@ -435,16 +437,16 @@ Ipc_server::Ipc_server()
if (!Thread::myself())
return;
- Native_thread &native_thread = Thread::myself()->native_thread();
+ Thread::myself()->with_native_thread([&] (Native_thread &nt) {
- if (native_thread.is_ipc_server) {
- Genode::raw(lx_getpid(), ":", lx_gettid(),
- " unexpected multiple instantiation of Ipc_server by one thread");
- struct Ipc_server_multiple_instance { };
- throw Ipc_server_multiple_instance();
- }
+ if (nt.is_ipc_server) {
+ Genode::raw(lx_getpid(), ":", lx_gettid(),
+ " unexpected multiple instantiation of Ipc_server by one thread");
+ sleep_forever();
+ }
- native_thread.is_ipc_server = true;
+ nt.is_ipc_server = true;
+ });
}
@@ -457,7 +459,6 @@ Ipc_server::~Ipc_server()
* Reset thread role to non-server such that we can enter 'sleep_forever'
* without getting a warning.
*/
- Native_thread &native_thread = Thread::myself()->native_thread();
-
- native_thread.is_ipc_server = false;
+ Thread::myself()->with_native_thread([&] (Native_thread &nt) {
+ nt.is_ipc_server = false; });
}
diff --git a/repos/base-linux/src/lib/base/native_thread.cc b/repos/base-linux/src/lib/base/native_thread.cc
index 5936fd7985..957c348b52 100644
--- a/repos/base-linux/src/lib/base/native_thread.cc
+++ b/repos/base-linux/src/lib/base/native_thread.cc
@@ -130,8 +130,12 @@ void Native_thread::Epoll::_exec_control(FN const &fn)
* If 'myself_ptr' is nullptr, the caller is the initial thread w/o
* a valid 'Thread' object associated yet. This thread is never polling.
*/
- bool const myself_is_polling = (myself_ptr != nullptr)
- && (&myself_ptr->native_thread().epoll == this);
+ auto myself_is_polling = [&]
+ {
+ return myself_ptr && myself_ptr->with_native_thread(
+ [&] (Native_thread &nt) { return (&nt.epoll == this); },
+ [&] { return false; });
+ };
/*
* If caller runs in the context of the same thread that executes 'poll' we
@@ -139,7 +143,7 @@ void Native_thread::Epoll::_exec_control(FN const &fn)
* block at this time. If the RPC entrypoint has existed its dispatch
* loop, it also cannot poll anymore.
*/
- if (myself_is_polling || _rpc_ep_exited) {
+ if (myself_is_polling() || _rpc_ep_exited) {
fn();
return;
}
diff --git a/repos/base-linux/src/lib/base/rpc_cap_alloc.cc b/repos/base-linux/src/lib/base/rpc_cap_alloc.cc
index 044f942552..88f2ebec88 100644
--- a/repos/base-linux/src/lib/base/rpc_cap_alloc.cc
+++ b/repos/base-linux/src/lib/base/rpc_cap_alloc.cc
@@ -61,26 +61,29 @@ Native_capability Rpc_entrypoint::_alloc_rpc_cap(Pd_session& pd, Native_capabili
"cap_quota=", cap_upgrade).string());
});
}
- return Thread::native_thread().epoll.alloc_rpc_cap();
+ return with_native_thread(
+ [&] (Native_thread &nt) { return nt.epoll.alloc_rpc_cap(); },
+ [&] { return Native_capability(); });
}
void Rpc_entrypoint::_free_rpc_cap(Pd_session& pd, Native_capability cap)
{
- Native_thread::Epoll &epoll = Thread::native_thread().epoll;
+ with_native_thread([&] (Native_thread &nt) {
- /*
- * Flag RPC entrypoint as exited to prevent 'free_rpc_cap' from issuing
- * a remote control request.
- */
- if (_exit_handler.exit)
- epoll.rpc_ep_exited();
+ /*
+ * Flag RPC entrypoint as exited to prevent 'free_rpc_cap' from issuing
+ * a remote control request.
+ */
+ if (_exit_handler.exit)
+ nt.epoll.rpc_ep_exited();
- /*
- * Perform the accounting of the PDs cap quota at core, to remain
- * consistent with other kernel platforms.
- */
- pd.free_rpc_cap(Native_capability());
+ /*
+ * Perform the accounting of the PDs cap quota at core, to remain
+ * consistent with other kernel platforms.
+ */
+ pd.free_rpc_cap(Native_capability());
- epoll.free_rpc_cap(cap);
+ nt.epoll.free_rpc_cap(cap);
+ });
}
diff --git a/repos/base-linux/src/lib/base/thread_linux.cc b/repos/base-linux/src/lib/base/thread_linux.cc
index f34b62e639..a5cb046fc4 100644
--- a/repos/base-linux/src/lib/base/thread_linux.cc
+++ b/repos/base-linux/src/lib/base/thread_linux.cc
@@ -83,10 +83,10 @@ void Thread::_thread_start()
lx_sigaction(LX_SIGUSR1, empty_signal_handler, false);
/* inform core about the new thread and process ID of the new thread */
- {
+ thread->with_native_thread([&] (Native_thread &nt) {
Linux_native_cpu_client native_cpu(thread->_cpu_session->native_cpu());
- native_cpu.thread_id(thread->cap(), thread->native_thread().pid, thread->native_thread().tid);
- }
+ native_cpu.thread_id(thread->cap(), nt.pid, nt.tid);
+ });
/* wakeup 'start' function */
startup_lock().wakeup();
@@ -100,7 +100,7 @@ void Thread::_thread_start()
}
-void Thread::_init_platform_thread(size_t /* weight */, Type type)
+void Thread::_init_native_thread(Stack &stack, size_t /* weight */, Type type)
{
/* if no cpu session is given, use it from the environment */
if (!_cpu_session) {
@@ -110,7 +110,7 @@ void Thread::_init_platform_thread(size_t /* weight */, Type type)
/* for normal threads create an object at the CPU session */
if (type == NORMAL) {
- _cpu_session->create_thread(pd_session_cap(), _stack->name().string(),
+ _cpu_session->create_thread(pd_session_cap(), stack.name(),
Affinity::Location(), Weight()).with_result(
[&] (Thread_capability cap) { _thread_cap = cap; },
[&] (Cpu_session::Create_thread_error) {
@@ -119,12 +119,12 @@ void Thread::_init_platform_thread(size_t /* weight */, Type type)
return;
}
/* adjust initial object state for main threads */
- native_thread().futex_counter = main_thread_futex_counter;
+ stack.native_thread().futex_counter = main_thread_futex_counter;
_thread_cap = main_thread_cap();
}
-void Thread::_deinit_platform_thread()
+void Thread::_deinit_native_thread(Stack &stack)
{
/*
* Kill thread until it is really really dead
@@ -139,12 +139,12 @@ void Thread::_deinit_platform_thread()
* anymore.
*/
for (;;) {
+ Native_thread &nt = stack.native_thread();
/* destroy thread locally */
- int pid = native_thread().pid;
- if (pid == 0) break;
+ if (nt.pid == 0) break;
- int ret = lx_tgkill(pid, native_thread().tid, LX_SIGCANCEL);
+ int ret = lx_tgkill(nt.pid, nt.tid, LX_SIGCANCEL);
if (ret < 0) break;
@@ -180,8 +180,10 @@ Thread::Start_result Thread::start()
threadlib_initialized = true;
}
- native_thread().tid = lx_create_thread(Thread::_thread_start, stack_top());
- native_thread().pid = lx_getpid();
+ with_native_thread([&] (Native_thread &nt) {
+ nt.tid = lx_create_thread(Thread::_thread_start, stack_top());
+ nt.pid = lx_getpid();
+ });
/* wait until the 'thread_start' function got entered */
startup_lock().block();
diff --git a/repos/base-linux/src/lib/lx_hybrid/lx_hybrid.cc b/repos/base-linux/src/lib/lx_hybrid/lx_hybrid.cc
index 9bb2af2684..1d7501b501 100644
--- a/repos/base-linux/src/lib/lx_hybrid/lx_hybrid.cc
+++ b/repos/base-linux/src/lib/lx_hybrid/lx_hybrid.cc
@@ -383,9 +383,10 @@ static void adopt_thread(Native_thread::Meta_data *meta_data)
/*
* Initialize thread meta data
*/
- Native_thread &native_thread = meta_data->thread_base.native_thread();
- native_thread.tid = lx_gettid();
- native_thread.pid = lx_getpid();
+ meta_data->thread_base.with_native_thread([&] (Native_thread &nt) {
+ nt.tid = lx_gettid();
+ nt.pid = lx_getpid();
+ });
}
@@ -483,10 +484,10 @@ Thread *Thread::myself()
new (global_alloc()) Thread_meta_data_adopted(thread);
/*
- * Initialize 'Thread::_native_thread' to point to the default-
+ * Initialize 'Thread::_native_thread_ptr' to point to the default-
* constructed 'Native_thread' (part of 'Meta_data').
*/
- meta_data->thread_base._native_thread = &meta_data->native_thread;
+ meta_data->thread_base._native_thread_ptr = &meta_data->native_thread;
adopt_thread(meta_data);
return thread;
@@ -498,20 +499,20 @@ Thread::Start_result Thread::start()
/*
* Unblock thread that is supposed to slumber in 'thread_start'.
*/
- native_thread().meta_data->started();
+ with_native_thread([&] (Native_thread &nt) {
+ nt.meta_data->started(); });
+
return Start_result::OK;
}
void Thread::join()
{
- native_thread().meta_data->wait_for_join();
+ with_native_thread([&] (Native_thread &nt) {
+ nt.meta_data->wait_for_join(); });
}
-Native_thread &Thread::native_thread() { return *_native_thread; }
-
-
Thread::Thread(size_t weight, const char *name, size_t /* stack size */,
Type, Cpu_session * cpu_sess, Affinity::Location)
: _cpu_session(cpu_sess), _affinity()
@@ -519,7 +520,7 @@ Thread::Thread(size_t weight, const char *name, size_t /* stack size */,
Native_thread::Meta_data *meta_data =
new (global_alloc()) Thread_meta_data_created(this);
- _native_thread = &meta_data->native_thread;
+ _native_thread_ptr = &meta_data->native_thread;
int const ret = pthread_create(&meta_data->pt, 0, thread_start, meta_data);
if (ret) {
@@ -528,18 +529,21 @@ Thread::Thread(size_t weight, const char *name, size_t /* stack size */,
throw Out_of_stack_space();
}
- native_thread().meta_data->wait_for_construction();
+ with_native_thread([&] (Native_thread &nt) {
- _thread_cap = _cpu_session->create_thread(_env_ptr->pd_session_cap(), name,
- Location(), Weight(weight));
- _thread_cap.with_result(
- [&] (Thread_capability cap) {
- Linux_native_cpu_client native_cpu(_cpu_session->native_cpu());
- native_cpu.thread_id(cap, native_thread().pid, native_thread().tid);
- },
- [&] (Cpu_session::Create_thread_error) {
- error("failed to create hybrid thread"); }
- );
+ nt.meta_data->wait_for_construction();
+
+ _thread_cap = _cpu_session->create_thread(_env_ptr->pd_session_cap(), name,
+ Location(), Weight(weight));
+ _thread_cap.with_result(
+ [&] (Thread_capability cap) {
+ Linux_native_cpu_client native_cpu(_cpu_session->native_cpu());
+ native_cpu.thread_id(cap, nt.pid, nt.tid);
+ },
+ [&] (Cpu_session::Create_thread_error) {
+ error("failed to create hybrid thread"); }
+ );
+ });
}
@@ -561,22 +565,25 @@ Thread::Thread(Env &env, Name const &name, size_t stack_size)
Thread::~Thread()
{
- bool const needs_join = (pthread_cancel(native_thread().meta_data->pt) == 0);
+ with_native_thread([&] (Native_thread &nt) {
- if (needs_join) {
- int const ret = pthread_join(native_thread().meta_data->pt, 0);
- if (ret)
- warning("pthread_join unexpectedly returned "
- "with ", ret, " (errno=", errno, ")");
- }
+ bool const needs_join = (pthread_cancel(nt.meta_data->pt) == 0);
- Thread_meta_data_created *meta_data =
- dynamic_cast(native_thread().meta_data);
+ if (needs_join) {
+ int const ret = pthread_join(nt.meta_data->pt, 0);
+ if (ret)
+ warning("pthread_join unexpectedly returned "
+ "with ", ret, " (errno=", errno, ")");
+ }
- if (meta_data)
- destroy(global_alloc(), meta_data);
+ Thread_meta_data_created *meta_data =
+ dynamic_cast(nt.meta_data);
- _native_thread = nullptr;
+ if (meta_data)
+ destroy(global_alloc(), meta_data);
+ });
+
+ _native_thread_ptr = nullptr;
/* inform core about the killed thread */
_thread_cap.with_result(
diff --git a/repos/base-nova/include/nova/native_thread.h b/repos/base-nova/include/nova/native_thread.h
index 6f751a6f11..f71e36b127 100644
--- a/repos/base-nova/include/nova/native_thread.h
+++ b/repos/base-nova/include/nova/native_thread.h
@@ -19,21 +19,17 @@
#ifndef _INCLUDE__NOVA__NATIVE_THREAD_H_
#define _INCLUDE__NOVA__NATIVE_THREAD_H_
-#include
#include
namespace Genode { struct Native_thread; }
-struct Genode::Native_thread
+
+struct Genode::Native_thread : Noncopyable
{
static constexpr unsigned long INVALID_INDEX = ~0UL;
- addr_t ec_sel { 0 }; /* selector for execution context */
- addr_t exc_pt_sel { 0 }; /* base of event portal window */
- addr_t initial_ip { 0 }; /* initial IP of local thread */
-
- /* receive window for capability selectors received at the server side */
- Receive_window server_rcv_window { };
+ addr_t ec_sel = INVALID_INDEX; /* selector for execution context */
+ addr_t exc_pt_sel = INVALID_INDEX; /* base of event portal window */
/*
* Designated selector to populate with the result of an IPC call
@@ -49,13 +45,19 @@ struct Genode::Native_thread
*/
addr_t client_rcv_sel = INVALID_INDEX;
- void reset_client_rcv_sel() { client_rcv_sel = INVALID_INDEX; }
+ addr_t initial_ip = 0;
+
+ /* receive window for capability selectors received at the server side */
+ Receive_window server_rcv_window { };
Native_capability pager_cap { };
- Native_thread() : ec_sel(INVALID_INDEX),
- exc_pt_sel(INVALID_INDEX),
- initial_ip(0) { }
+ Native_thread() { }
+
+ /* ec_sel is invalid until thread gets started */
+ bool ec_valid() const { return ec_sel != INVALID_INDEX; }
+
+ void reset_client_rcv_sel() { client_rcv_sel = INVALID_INDEX; }
};
#endif /* _INCLUDE__NOVA__NATIVE_THREAD_H_ */
diff --git a/repos/base-nova/src/core/pager.cc b/repos/base-nova/src/core/pager.cc
index 4ecc61667f..c7c410c525 100644
--- a/repos/base-nova/src/core/pager.cc
+++ b/repos/base-nova/src/core/pager.cc
@@ -569,13 +569,16 @@ void Exception_handlers::register_handler(Pager_object &obj, Mtd mtd,
void (* __attribute__((regparm(1))) func)(Pager_object &))
{
uint8_t res = !Nova::NOVA_OK;
- with_pager_thread(obj.location(), platform_specific(), [&] (Pager_thread &pager_thread) {
- addr_t const ec_sel = pager_thread.native_thread().ec_sel;
+ with_pager_thread(obj.location(), platform_specific(), [&] (Pager_thread &thread) {
+ thread.with_native_thread([&] (Native_thread &nt) {
+ addr_t const ec_sel = nt.ec_sel;
- /* compiler generates instance of exception entry if not specified */
- addr_t entry = func ? (addr_t)func : (addr_t)(&_handler);
- res = create_portal(obj.exc_pt_sel_client() + EV,
- platform_specific().core_pd_sel(), ec_sel, mtd, entry, &obj);
+ /* compiler generates instance of exception entry if not specified */
+ addr_t entry = func ? (addr_t)func : (addr_t)(&_handler);
+ res = create_portal(obj.exc_pt_sel_client() + EV,
+ platform_specific().core_pd_sel(),
+ ec_sel, mtd, entry, &obj);
+ });
});
if (res != Nova::NOVA_OK)
@@ -644,13 +647,15 @@ void Pager_object::_construct_pager()
uint8_t res = !Nova::NOVA_OK;
with_pager_thread(_location, platform_specific(), [&] (Pager_thread &pager_thread) {
+ pager_thread.with_native_thread([&] (Native_thread &nt) {
- addr_t const ec_sel = pager_thread.native_thread().ec_sel;
+ addr_t const ec_sel = nt.ec_sel;
- /* create portal for final cleanup call used during destruction */
- res = create_portal(sel_pt_cleanup(), pd_sel, ec_sel, Mtd(0),
- reinterpret_cast(_invoke_handler),
- this);
+ /* create portal for final cleanup call used during destruction */
+ res = create_portal(sel_pt_cleanup(), pd_sel, ec_sel, Mtd(0),
+ reinterpret_cast(_invoke_handler),
+ this);
+ });
});
if (res != Nova::NOVA_OK) {
error("could not create pager cleanup portal, error=", res);
@@ -872,8 +877,10 @@ void Pager_object::_oom_handler(addr_t pager_dst, addr_t pager_src,
if (assert) {
error("unknown OOM case - stop core pager thread");
- utcb.set_msg_word(0);
- reply(myself.stack_top(), myself.native_thread().exc_pt_sel + Nova::SM_SEL_EC);
+ myself.with_native_thread([&] (Native_thread &nt) {
+ utcb.set_msg_word(0);
+ reply(myself.stack_top(), nt.exc_pt_sel + Nova::SM_SEL_EC);
+ });
}
/* be strict in case of the -strict- STOP policy - stop causing thread */
@@ -892,8 +899,11 @@ void Pager_object::_oom_handler(addr_t pager_dst, addr_t pager_src,
case SRC_PD_UNKNOWN:
/* should not happen on Genode - we create and know every PD in core */
error("Unknown PD has insufficient kernel memory left - stop thread");
- utcb.set_msg_word(0);
- reply(myself.stack_top(), myself.native_thread().exc_pt_sel + Nova::SM_SEL_EC);
+ myself.with_native_thread([&] (Native_thread &nt) {
+ utcb.set_msg_word(0);
+ reply(myself.stack_top(), nt.exc_pt_sel + Nova::SM_SEL_EC);
+ });
+ break;
case SRC_CORE_PD:
/* core PD -> other PD, which has insufficient kernel resources */
@@ -943,13 +953,14 @@ addr_t Pager_object::create_oom_portal()
{
uint8_t res = !Nova::NOVA_OK;
- with_pager_thread(_location, platform_specific(),
- [&] (Pager_thread &thread) {
+ with_pager_thread(_location, platform_specific(), [&] (Pager_thread &thread) {
+ thread.with_native_thread([&] (Native_thread &nt) {
addr_t const core_pd_sel = platform_specific().core_pd_sel();
- addr_t const ec_sel = thread.native_thread().ec_sel;
+ addr_t const ec_sel = nt.ec_sel;
res = create_portal(sel_oom_portal(), core_pd_sel, ec_sel, Mtd(0),
reinterpret_cast(_oom_handler),
this);
+ });
});
if (res == Nova::NOVA_OK)
diff --git a/repos/base-nova/src/core/thread_start.cc b/repos/base-nova/src/core/thread_start.cc
index 78f7b8ab6c..9039d18c0a 100644
--- a/repos/base-nova/src/core/thread_start.cc
+++ b/repos/base-nova/src/core/thread_start.cc
@@ -30,51 +30,54 @@
using namespace Core;
-void Thread::_init_platform_thread(size_t, Type type)
+void Thread::_init_native_thread(Stack &stack, size_t, Type type)
{
+ Native_thread &nt = stack.native_thread();
+
/*
* This function is called for constructing server activations and pager
* objects. It allocates capability selectors for the thread's execution
* context and a synchronization-helper semaphore needed for 'Lock'.
*/
- using namespace Nova;
- if (type == MAIN)
- {
+ if (type == MAIN) {
+
/* set EC selector according to NOVA spec */
- native_thread().ec_sel = platform_specific().core_pd_sel() + 1;
+ nt.ec_sel = platform_specific().core_pd_sel() + 1;
/*
* Exception base of first thread in core is 0. We have to set
* it here so that Thread code finds the semaphore of the
* main thread.
*/
- native_thread().exc_pt_sel = 0;
-
+ nt.exc_pt_sel = 0;
return;
}
- native_thread().ec_sel = cap_map().insert(1);
- native_thread().exc_pt_sel = cap_map().insert(NUM_INITIAL_PT_LOG2);
+
+ nt.ec_sel = cap_map().insert(1);
+ nt.exc_pt_sel = cap_map().insert(Nova::NUM_INITIAL_PT_LOG2);
/* create running semaphore required for locking */
- addr_t rs_sel = native_thread().exc_pt_sel + SM_SEL_EC;
- uint8_t res = create_sm(rs_sel, platform_specific().core_pd_sel(), 0);
- if (res != NOVA_OK)
+ addr_t rs_sel = nt.exc_pt_sel + Nova::SM_SEL_EC;
+ uint8_t res = Nova::create_sm(rs_sel, platform_specific().core_pd_sel(), 0);
+ if (res != Nova::NOVA_OK)
error("Thread::_init_platform_thread: create_sm returned ", res);
}
-void Thread::_deinit_platform_thread()
+void Thread::_deinit_native_thread(Stack &stack)
{
- unmap_local(Nova::Obj_crd(native_thread().ec_sel, 1));
- unmap_local(Nova::Obj_crd(native_thread().exc_pt_sel, Nova::NUM_INITIAL_PT_LOG2));
+ Native_thread &nt = stack.native_thread();
- cap_map().remove(native_thread().ec_sel, 1, false);
- cap_map().remove(native_thread().exc_pt_sel, Nova::NUM_INITIAL_PT_LOG2, false);
+ unmap_local(Nova::Obj_crd(nt.ec_sel, 1));
+ unmap_local(Nova::Obj_crd(nt.exc_pt_sel, Nova::NUM_INITIAL_PT_LOG2));
+
+ cap_map().remove(nt.ec_sel, 1, false);
+ cap_map().remove(nt.exc_pt_sel, Nova::NUM_INITIAL_PT_LOG2, false);
/* revoke utcb */
Nova::Rights rwx(true, true, true);
- addr_t utcb = reinterpret_cast(&_stack->utcb());
+ addr_t utcb = reinterpret_cast(&stack.utcb());
Nova::revoke(Nova::Mem_crd(utcb >> 12, 0, rwx));
}
@@ -93,9 +96,11 @@ Thread::Start_result Thread::start()
/* create local EC */
enum { LOCAL_THREAD = false };
unsigned const kernel_cpu_id = platform_specific().kernel_cpu_id(_affinity);
- uint8_t res = create_ec(native_thread().ec_sel,
- platform_specific().core_pd_sel(), kernel_cpu_id,
- (mword_t)&utcb, sp, native_thread().exc_pt_sel, LOCAL_THREAD);
+
+ uint8_t res { };
+ with_native_thread([&] (Native_thread &nt) {
+ res = create_ec(nt.ec_sel, platform_specific().core_pd_sel(), kernel_cpu_id,
+ (mword_t)&utcb, sp, nt.exc_pt_sel, LOCAL_THREAD); });
if (res != NOVA_OK) {
error("Thread::start: create_ec returned ", res);
return Start_result::DENIED;
@@ -109,10 +114,16 @@ Thread::Start_result Thread::start()
if (i == SM_SEL_EC)
continue;
- if (map_local(platform_specific().core_pd_sel(),
- *reinterpret_cast(Thread::myself()->utcb()),
- Obj_crd(i, 0),
- Obj_crd(native_thread().exc_pt_sel + i, 0))) {
+ bool page_fault_portal_ok = with_native_thread(
+ [&] (Native_thread &nt) {
+ return !map_local(platform_specific().core_pd_sel(),
+ *reinterpret_cast(Thread::myself()->utcb()),
+ Obj_crd(i, 0),
+ Obj_crd(nt.exc_pt_sel + i, 0));
+ },
+ [&] { return false; });
+
+ if (!page_fault_portal_ok) {
error("Thread::start: failed to create page-fault portal");
return Start_result::DENIED;
}
@@ -131,9 +142,11 @@ Thread::Start_result Thread::start()
{
uint64_t ec_time = 0;
- uint8_t res = Nova::ec_time(thread.native_thread().ec_sel, ec_time);
- if (res != Nova::NOVA_OK)
- warning("ec_time for core thread failed res=", res);
+ thread.with_native_thread([&] (Native_thread &nt) {
+ uint8_t res = Nova::ec_time(nt.ec_sel, ec_time);
+ if (res != Nova::NOVA_OK)
+ warning("ec_time for core thread failed res=", res);
+ });
return { Session_label("core"), thread.name(),
Trace::Execution_time(ec_time, 0), thread._affinity };
diff --git a/repos/base-nova/src/include/base/internal/lock_helper.h b/repos/base-nova/src/include/base/internal/lock_helper.h
index 58bbaf5379..566798aa3b 100644
--- a/repos/base-nova/src/include/base/internal/lock_helper.h
+++ b/repos/base-nova/src/include/base/internal/lock_helper.h
@@ -32,13 +32,22 @@
extern int main_thread_running_semaphore();
-static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_base)
+static inline Genode::addr_t sm_sel_ec(Genode::Thread *thread_ptr)
{
- Genode::addr_t sem = thread_base ?
- thread_base->native_thread().exc_pt_sel + Nova::SM_SEL_EC :
- main_thread_running_semaphore();
+ if (!thread_ptr)
+ return main_thread_running_semaphore();
- Nova::sm_ctrl(sem, Nova::SEMAPHORE_UP);
+ using namespace Genode;
+
+ return thread_ptr->with_native_thread(
+ [&] (Native_thread &nt) { return nt.exc_pt_sel + Nova::SM_SEL_EC; },
+ [&] { error("attempt to synchronize invalid thread"); return 0UL; });
+}
+
+
+static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_ptr)
+{
+ Nova::sm_ctrl(sm_sel_ec(thread_ptr), Nova::SEMAPHORE_UP);
return true;
}
@@ -48,16 +57,7 @@ static inline void thread_switch_to(Genode::Thread *) { }
static inline void thread_stop_myself(Genode::Thread *myself)
{
- using namespace Genode;
- using namespace Nova;
-
- addr_t sem;
- if (myself)
- sem = myself->native_thread().exc_pt_sel + SM_SEL_EC;
- else
- sem = main_thread_running_semaphore();
-
- sm_ctrl(sem, SEMAPHORE_DOWNZERO);
+ Nova::sm_ctrl(sm_sel_ec(myself), Nova::SEMAPHORE_DOWNZERO);
}
#endif /* _INCLUDE__BASE__INTERNAL__LOCK_HELPER_H_ */
diff --git a/repos/base-nova/src/include/base/internal/spin_lock.h b/repos/base-nova/src/include/base/internal/spin_lock.h
index 0ad7f70d93..d4025e845f 100644
--- a/repos/base-nova/src/include/base/internal/spin_lock.h
+++ b/repos/base-nova/src/include/base/internal/spin_lock.h
@@ -29,14 +29,28 @@ enum State {
enum { RESERVED_BITS = 12, COUNTER_MASK = 0xFFC };
+
+static inline Genode::addr_t ec_sel(Genode::Thread *thread_ptr)
+{
+ if (!thread_ptr)
+ return Nova::EC_SEL_THREAD;
+
+ using namespace Genode;
+
+ return thread_ptr->with_native_thread(
+ [&] (Native_thread &nt) { return nt.ec_sel; },
+ [&] { error("failed to obtain ec_sel for invalid thread"); return 0UL; });
+}
+
+
template
static inline void spinlock_lock(volatile T *lock_variable)
{
using Genode::cmpxchg;
Genode::Thread * myself = Genode::Thread::myself();
- T const tid = (T)(myself ? myself->native_thread().ec_sel
- : (Genode::addr_t)Nova::EC_SEL_THREAD);
+
+ T const tid = (T)ec_sel(myself);
unsigned help_counter = 0;
diff --git a/repos/base-nova/src/include/signal_source/client.h b/repos/base-nova/src/include/signal_source/client.h
index ac64d000c8..691f0d6d89 100644
--- a/repos/base-nova/src/include/signal_source/client.h
+++ b/repos/base-nova/src/include/signal_source/client.h
@@ -54,11 +54,13 @@ namespace Genode {
: Rpc_client(static_cap_cast(cap))
{
/* request mapping of semaphore capability selector */
- Thread * myself = Thread::myself();
- auto const &exc_base = myself->native_thread().exc_pt_sel;
- request_signal_sm_cap(exc_base + Nova::PT_SEL_PAGE_FAULT,
- exc_base + Nova::SM_SEL_SIGNAL);
- _sem = Capability_space::import(exc_base + Nova::SM_SEL_SIGNAL);
+ Thread &myself = *Thread::myself();
+ myself.with_native_thread([&] (Native_thread &nt) {
+ auto const exc_base = nt.exc_pt_sel;
+ request_signal_sm_cap(exc_base + Nova::PT_SEL_PAGE_FAULT,
+ exc_base + Nova::SM_SEL_SIGNAL);
+ _sem = Capability_space::import(exc_base + Nova::SM_SEL_SIGNAL);
+ });
call(_sem);
}
diff --git a/repos/base-nova/src/lib/base/ipc.cc b/repos/base-nova/src/lib/base/ipc.cc
index eb23dbce79..2054c5f6da 100644
--- a/repos/base-nova/src/lib/base/ipc.cc
+++ b/repos/base-nova/src/lib/base/ipc.cc
@@ -65,8 +65,15 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
* Determine manually defined selector for receiving the call result.
* See the comment in 'base-nova/include/nova/native_thread.h'.
*/
- addr_t const manual_rcv_sel = myself ? myself->native_thread().client_rcv_sel
- : Receive_window::INVALID_INDEX;
+ auto manual_rcv_sel_for_myself = [&]
+ {
+ addr_t sel = Receive_window::INVALID_INDEX;
+ if (myself)
+ myself->with_native_thread([&] (Native_thread &nt) {
+ sel = nt.client_rcv_sel; });
+ return sel;
+ };
+ addr_t const manual_rcv_sel = manual_rcv_sel_for_myself();
/* if we can't setup receive window, die in order to recognize the issue */
if (!rcv_window.prepare_rcv_window(utcb, manual_rcv_sel))
diff --git a/repos/base-nova/src/lib/base/rpc_entrypoint.cc b/repos/base-nova/src/lib/base/rpc_entrypoint.cc
index eea468eac2..d8b91132b0 100644
--- a/repos/base-nova/src/lib/base/rpc_entrypoint.cc
+++ b/repos/base-nova/src/lib/base/rpc_entrypoint.cc
@@ -42,27 +42,29 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
return obj->cap();
}
- Untyped_capability ec_cap;
+ return with_native_thread(
+ [&] (Native_thread &nt) {
- /* _ec_sel is invalid until thread gets started */
- if (native_thread().ec_sel != Native_thread::INVALID_INDEX)
- ec_cap = Capability_space::import(native_thread().ec_sel);
- else
- ec_cap = Thread::cap();
+ Untyped_capability const ec_cap =
+ nt.ec_valid() ? Capability_space::import(nt.ec_sel) : Thread::cap();
- Untyped_capability obj_cap = _alloc_rpc_cap(_pd_session, ec_cap,
- (addr_t)&_activation_entry);
- if (!obj_cap.valid())
- return obj_cap;
+ Untyped_capability const obj_cap =
+ _alloc_rpc_cap(_pd_session, ec_cap, (addr_t)&_activation_entry);
- /* add server object to object pool */
- obj->cap(obj_cap);
- insert(obj);
+ if (!obj_cap.valid())
+ return Untyped_capability();
- /* return object capability managed by entrypoint thread */
- return obj_cap;
+ /* add server object to object pool */
+ obj->cap(obj_cap);
+ insert(obj);
+
+ /* return object capability managed by entrypoint thread */
+ return obj_cap;
+ },
+ [&] { return Untyped_capability(); });
}
+
static void cleanup_call(Rpc_object_base *obj, Nova::Utcb * ep_utcb,
Native_capability &cap)
{
@@ -129,52 +131,54 @@ void Rpc_entrypoint::_activation_entry()
Rpc_entrypoint &ep = *static_cast(Thread::myself());
Nova::Utcb &utcb = *(Nova::Utcb *)Thread::myself()->utcb();
- Receive_window &rcv_window = ep.native_thread().server_rcv_window;
- rcv_window.post_ipc(utcb);
+ ep.with_native_thread([&] (Native_thread &nt) {
+ Receive_window &rcv_window = nt.server_rcv_window;
+ rcv_window.post_ipc(utcb);
- /* handle ill-formed message */
- if (utcb.msg_words() < 2) {
- ep._rcv_buf.word(0) = ~0UL; /* invalid opcode */
- } else {
- copy_utcb_to_msgbuf(utcb, rcv_window, ep._rcv_buf);
- }
+ /* handle ill-formed message */
+ if (utcb.msg_words() < 2) {
+ ep._rcv_buf.word(0) = ~0UL; /* invalid opcode */
+ } else {
+ copy_utcb_to_msgbuf(utcb, rcv_window, ep._rcv_buf);
+ }
- Ipc_unmarshaller unmarshaller(ep._rcv_buf);
+ Ipc_unmarshaller unmarshaller(ep._rcv_buf);
- Rpc_opcode opcode(0);
- unmarshaller.extract(opcode);
+ Rpc_opcode opcode(0);
+ unmarshaller.extract(opcode);
- /* default return value */
- Rpc_exception_code exc = Rpc_exception_code(Rpc_exception_code::INVALID_OBJECT);
+ /* default return value */
+ Rpc_exception_code exc = Rpc_exception_code(Rpc_exception_code::INVALID_OBJECT);
- /* in case of a portal cleanup call we are done here - just reply */
- if (ep._cap.local_name() == (long)id_pt) {
- if (!rcv_window.prepare_rcv_window(utcb))
+ /* in case of a portal cleanup call we are done here - just reply */
+ if (ep._cap.local_name() == (long)id_pt) {
+ if (!rcv_window.prepare_rcv_window(utcb))
+ warning("out of capability selectors for handling server requests");
+
+ ep._rcv_buf.reset();
+ reply(utcb, exc, ep._snd_buf);
+ }
+
+ /* atomically lookup and lock referenced object */
+ auto lambda = [&] (Rpc_object_base *obj)
+ {
+ if (!obj) {
+ error("could not look up server object, return from call id_pt=", id_pt);
+ return;
+ }
+
+ /* dispatch request */
+ ep._snd_buf.reset();
+ exc = obj->dispatch(opcode, unmarshaller, ep._snd_buf);
+ };
+ ep.apply(id_pt, lambda);
+
+ if (!rcv_window.prepare_rcv_window(*(Nova::Utcb *)ep.utcb()))
warning("out of capability selectors for handling server requests");
ep._rcv_buf.reset();
reply(utcb, exc, ep._snd_buf);
- }
-
- /* atomically lookup and lock referenced object */
- auto lambda = [&] (Rpc_object_base *obj)
- {
- if (!obj) {
- error("could not look up server object, return from call id_pt=", id_pt);
- return;
- }
-
- /* dispatch request */
- ep._snd_buf.reset();
- exc = obj->dispatch(opcode, unmarshaller, ep._snd_buf);
- };
- ep.apply(id_pt, lambda);
-
- if (!rcv_window.prepare_rcv_window(*(Nova::Utcb *)ep.utcb()))
- warning("out of capability selectors for handling server requests");
-
- ep._rcv_buf.reset();
- reply(utcb, exc, ep._snd_buf);
+ });
}
@@ -202,28 +206,33 @@ Rpc_entrypoint::Rpc_entrypoint(Pd_session *pd_session, size_t stack_size,
_pd_session(*pd_session)
{
/* set magic value evaluated by thread_nova.cc to start a local thread */
- if (native_thread().ec_sel == Native_thread::INVALID_INDEX) {
- native_thread().ec_sel = Native_thread::INVALID_INDEX - 1;
- native_thread().initial_ip = (addr_t)&_activation_entry;
- }
+ with_native_thread([&] (Native_thread &nt) {
+ if (nt.ec_valid())
+ return;
+
+ nt.ec_sel = Native_thread::INVALID_INDEX - 1;
+ nt.initial_ip = (addr_t)&_activation_entry;
+ });
/* required to create a 'local' EC */
Thread::start();
/* create cleanup portal */
- _cap = _alloc_rpc_cap(_pd_session,
- Capability_space::import(native_thread().ec_sel),
- (addr_t)_activation_entry);
+ with_native_thread([&] (Native_thread &nt) {
+ _cap = _alloc_rpc_cap(_pd_session, Capability_space::import(nt.ec_sel),
+ (addr_t)_activation_entry); });
if (!_cap.valid()) {
error("failed to allocate RPC cap for new entrypoint");
return;
}
- Receive_window &rcv_window = Thread::native_thread().server_rcv_window;
+ with_native_thread([&] (Native_thread &nt) {
+ Receive_window &rcv_window = nt.server_rcv_window;
- /* prepare portal receive window of new thread */
- if (!rcv_window.prepare_rcv_window(*(Nova::Utcb *)&_stack->utcb()))
- error("failed to prepare receive window for RPC entrypoint");
+ /* prepare portal receive window of new thread */
+ if (!rcv_window.prepare_rcv_window(*(Nova::Utcb *)&_stack->utcb()))
+ error("failed to prepare receive window for RPC entrypoint");
+ });
}
diff --git a/repos/base-nova/src/lib/base/thread_start.cc b/repos/base-nova/src/lib/base/thread_start.cc
index 964aa23a9b..bf3dac9102 100644
--- a/repos/base-nova/src/lib/base/thread_start.cc
+++ b/repos/base-nova/src/lib/base/thread_start.cc
@@ -55,8 +55,6 @@ static Thread_capability main_thread_cap(Thread_capability main_cap = { })
*/
void Thread::_thread_start()
{
- using namespace Genode;
-
/* catch any exception at this point and try to print an error message */
try {
Thread::myself()->entry();
@@ -83,24 +81,23 @@ void Thread::_thread_start()
** Thread base **
*****************/
-void Thread::_init_platform_thread(size_t weight, Type type)
+void Thread::_init_native_thread(Stack &stack, size_t weight, Type type)
{
- using namespace Nova;
+ Native_thread &nt = stack.native_thread();
/*
* Allocate capability selectors for the thread's execution context,
* running semaphore and exception handler portals.
*/
- native_thread().ec_sel = Native_thread::INVALID_INDEX;
/* for main threads the member initialization differs */
if (type == MAIN) {
_thread_cap = main_thread_cap();
- native_thread().exc_pt_sel = 0;
- native_thread().ec_sel = Nova::EC_SEL_THREAD;
+ nt.exc_pt_sel = 0;
+ nt.ec_sel = Nova::EC_SEL_THREAD;
- request_native_ec_cap(PT_SEL_PAGE_FAULT, native_thread().ec_sel);
+ request_native_ec_cap(Nova::PT_SEL_PAGE_FAULT, nt.ec_sel);
return;
}
@@ -113,12 +110,12 @@ void Thread::_init_platform_thread(size_t weight, Type type)
* 'Cpu_session::kill_thread()' and is not able to revoke the UTCB
* afterwards.
*/
- Rights rwx(true, true, true);
- addr_t utcb = reinterpret_cast(&_stack->utcb());
- revoke(Mem_crd(utcb >> 12, 0, rwx));
+ Nova::Rights rwx(true, true, true);
+ addr_t utcb = reinterpret_cast(&stack.utcb());
+ Nova::revoke(Nova::Mem_crd(utcb >> 12, 0, rwx));
- native_thread().exc_pt_sel = cap_map().insert(NUM_INITIAL_PT_LOG2);
- if (native_thread().exc_pt_sel == Native_thread::INVALID_INDEX) {
+ nt.exc_pt_sel = cap_map().insert(Nova::NUM_INITIAL_PT_LOG2);
+ if (nt.exc_pt_sel == Native_thread::INVALID_INDEX) {
error("failed allocate exception-portal selector for new thread");
return;
}
@@ -134,88 +131,87 @@ void Thread::_init_platform_thread(size_t weight, Type type)
}
-void Thread::_deinit_platform_thread()
+void Thread::_deinit_native_thread(Stack &stack)
{
- using namespace Nova;
+ Native_thread &nt = stack.native_thread();
- if (native_thread().ec_sel != Native_thread::INVALID_INDEX) {
- revoke(Obj_crd(native_thread().ec_sel, 0));
- }
+ if (nt.ec_valid())
+ Nova::revoke(Nova::Obj_crd(nt.ec_sel, 0));
/* de-announce thread */
_thread_cap.with_result(
[&] (Thread_capability cap) { _cpu_session->kill_thread(cap); },
[&] (Cpu_session::Create_thread_error) { });
- cap_map().remove(native_thread().exc_pt_sel, NUM_INITIAL_PT_LOG2);
+ cap_map().remove(nt.exc_pt_sel, Nova::NUM_INITIAL_PT_LOG2);
}
Thread::Start_result Thread::start()
{
- if (native_thread().ec_sel < Native_thread::INVALID_INDEX - 1) {
- error("Thread::start failed due to invalid exception portal selector");
- return Start_result::DENIED;
- }
+ return with_native_thread([&] (Native_thread &nt) {
- if (_thread_cap.failed())
- return Start_result::DENIED;
+ if (nt.ec_sel < Native_thread::INVALID_INDEX - 1) {
+ error("Thread::start failed due to invalid exception portal selector");
+ return Start_result::DENIED;
+ }
- /*
- * Default: create global thread - ec.sel == INVALID_INDEX
- * create local thread - ec.sel == INVALID_INDEX - 1
- */
- bool global = native_thread().ec_sel == Native_thread::INVALID_INDEX;
+ if (_thread_cap.failed())
+ return Start_result::DENIED;
- using namespace Genode;
+ /*
+ * Default: create global thread - ec.sel == INVALID_INDEX
+ * create local thread - ec.sel == INVALID_INDEX - 1
+ */
+ bool global = nt.ec_sel == Native_thread::INVALID_INDEX;
- /* create EC at core */
+ /* create EC at core */
- try {
- Cpu_session::Native_cpu::Thread_type thread_type;
+ try {
+ Cpu_session::Native_cpu::Thread_type thread_type;
+
+ if (global)
+ thread_type = Cpu_session::Native_cpu::Thread_type::GLOBAL;
+ else
+ thread_type = Cpu_session::Native_cpu::Thread_type::LOCAL;
+
+ Cpu_session::Native_cpu::Exception_base exception_base { nt.exc_pt_sel };
+
+ Nova_native_cpu_client native_cpu(_cpu_session->native_cpu());
+ native_cpu.thread_type(cap(), thread_type, exception_base);
+ } catch (...) {
+ error("Thread::start failed to set thread type");
+ return Start_result::DENIED;
+ }
+
+ /* local thread have no start instruction pointer - set via portal entry */
+ addr_t thread_ip = global ? reinterpret_cast(_thread_start) : nt.initial_ip;
+
+ Cpu_thread_client cpu_thread(cap());
+ cpu_thread.start(thread_ip, _stack->top());
+
+ /* request native EC thread cap */
+ nt.ec_sel = nt.exc_pt_sel + Nova::EC_SEL_THREAD;
+
+ /*
+ * Requested ec cap that is used for recall and
+ * creation of portals (Native_pd::alloc_rpc_cap).
+ */
+ request_native_ec_cap(nt.exc_pt_sel + Nova::PT_SEL_PAGE_FAULT,
+ nt.ec_sel);
+
+ /* default: we don't accept any mappings or translations */
+ Nova::Utcb &utcb = *(Nova::Utcb *)Thread::utcb();
+ utcb.crd_rcv = Nova::Obj_crd();
+ utcb.crd_xlt = Nova::Obj_crd();
if (global)
- thread_type = Cpu_session::Native_cpu::Thread_type::GLOBAL;
- else
- thread_type = Cpu_session::Native_cpu::Thread_type::LOCAL;
+ /* request creation of SC to let thread run*/
+ cpu_thread.resume();
- Cpu_session::Native_cpu::Exception_base exception_base { native_thread().exc_pt_sel };
+ return Start_result::OK;
- Nova_native_cpu_client native_cpu(_cpu_session->native_cpu());
- native_cpu.thread_type(cap(), thread_type, exception_base);
- } catch (...) {
- error("Thread::start failed to set thread type");
- return Start_result::DENIED;
- }
-
- /* local thread have no start instruction pointer - set via portal entry */
- addr_t thread_ip = global ? reinterpret_cast(_thread_start) : native_thread().initial_ip;
-
- Cpu_thread_client cpu_thread(cap());
- cpu_thread.start(thread_ip, _stack->top());
-
- /* request native EC thread cap */
- native_thread().ec_sel = native_thread().exc_pt_sel + Nova::EC_SEL_THREAD;
-
- /*
- * Requested ec cap that is used for recall and
- * creation of portals (Native_pd::alloc_rpc_cap).
- */
- request_native_ec_cap(native_thread().exc_pt_sel + Nova::PT_SEL_PAGE_FAULT,
- native_thread().ec_sel);
-
- using namespace Nova;
-
- /* default: we don't accept any mappings or translations */
- Utcb * utcb_obj = reinterpret_cast(utcb());
- utcb_obj->crd_rcv = Obj_crd();
- utcb_obj->crd_xlt = Obj_crd();
-
- if (global)
- /* request creation of SC to let thread run*/
- cpu_thread.resume();
-
- return Start_result::OK;
+ }, [&] { return Start_result::DENIED; });
}
diff --git a/repos/base-nova/src/lib/base/vm.cc b/repos/base-nova/src/lib/base/vm.cc
index 6f57fba4ea..f5c3e0f038 100644
--- a/repos/base-nova/src/lib/base/vm.cc
+++ b/repos/base-nova/src/lib/base/vm.cc
@@ -655,12 +655,13 @@ void Nova_vcpu::with_state(auto const &fn)
static void nova_reply(Thread &myself, Nova::Utcb &utcb, auto &&... args)
{
- Receive_window &rcv_window = myself.native_thread().server_rcv_window;
+ myself.with_native_thread([&] (Native_thread &nt) {
- /* reset receive window to values expected by RPC server code */
- rcv_window.prepare_rcv_window(utcb);
+ /* reset receive window to values expected by RPC server code */
+ nt.server_rcv_window.prepare_rcv_window(utcb);
- Nova::reply(myself.stack_top(), args...);
+ Nova::reply(myself.stack_top(), args...);
+ });
}
@@ -697,19 +698,23 @@ Signal_context_capability Nova_vcpu::_create_exit_handler(Pd_session &pd,
uint16_t exit_reason,
Nova::Mtd mtd)
{
- Thread *tep = reinterpret_cast(&handler.rpc_ep());
+ Thread *ep = reinterpret_cast(&handler.rpc_ep());
- Native_capability thread_cap = Capability_space::import(tep->native_thread().ec_sel);
+ return ep->with_native_thread([&] (Native_thread &nt) {
- Nova_native_pd_client native_pd { pd.native_pd() };
+ Native_capability thread_cap = Capability_space::import(nt.ec_sel);
- Native_capability vm_exit_cap =
- native_pd.alloc_rpc_cap(thread_cap, (addr_t)Nova_vcpu::_exit_entry, mtd.value());
+ Nova_native_pd_client native_pd { pd.native_pd() };
- Badge const badge { vcpu_id, exit_reason };
- native_pd.imprint_rpc_cap(vm_exit_cap, badge.value());
+ Native_capability vm_exit_cap =
+ native_pd.alloc_rpc_cap(thread_cap, (addr_t)Nova_vcpu::_exit_entry, mtd.value());
- return reinterpret_cap_cast(vm_exit_cap);
+ Badge const badge { vcpu_id, exit_reason };
+ native_pd.imprint_rpc_cap(vm_exit_cap, badge.value());
+
+ return reinterpret_cap_cast(vm_exit_cap);
+
+ }, [&] { return Signal_context_capability(); });
}
diff --git a/repos/base-nova/src/test/nova/main.cc b/repos/base-nova/src/test/nova/main.cc
index 060b5ce4c3..09a71cde80 100644
--- a/repos/base-nova/src/test/nova/main.cc
+++ b/repos/base-nova/src/test/nova/main.cc
@@ -227,8 +227,9 @@ void test_revoke(Genode::Env &env)
* as used before by copy_session_cap
*/
Genode::Thread * myself = Genode::Thread::myself();
- request_native_ec_cap(myself->native_thread().exc_pt_sel + Nova::PT_SEL_PAGE_FAULT,
- copy_session_cap.local_name());
+ myself->with_native_thread([&] (Native_thread &nt) {
+ request_native_ec_cap(nt.exc_pt_sel + Nova::PT_SEL_PAGE_FAULT,
+ copy_session_cap.local_name()); });
/* check whether the requested cap before is valid and placed well */
crd_ses = Nova::Obj_crd(copy_session_cap.local_name(), 0);
@@ -319,33 +320,37 @@ void test_pat(Genode::Env &env)
touch_read_write(reinterpret_cast( memory + offset));
}
+ Nova::Rights const all(true, true, true);
+
/*
* Establish memory mapping with evilly wrong mapping attributes
*/
Nova_native_pd_client native_pd { env.pd().native_pd() };
Thread * thread = reinterpret_cast(&ep);
- Native_capability const thread_cap
- = Capability_space::import(thread->native_thread().ec_sel);
- Untyped_capability const pt =
- native_pd.alloc_rpc_cap(thread_cap, (addr_t)portal_entry, 0 /* MTD */);
+ thread->with_native_thread([&] (Native_thread &nt) {
- Nova::Rights const all(true, true, true);
- Nova::Mem_crd const rcv_crd(memory_remap >> PAGE_4K, DS_ORDER, all);
- Nova::Mem_crd const snd_crd(memory_wc >> PAGE_4K, DS_ORDER, all);
- Nova::Crd const old_crd = utcb.crd_rcv;
+ Native_capability const thread_cap = Capability_space::import(nt.ec_sel);
- utcb.crd_rcv = rcv_crd;
- utcb.set_msg_word(1);
- utcb.msg()[0] = snd_crd.value();
+ Untyped_capability const pt =
+ native_pd.alloc_rpc_cap(thread_cap, (addr_t)portal_entry, 0 /* MTD */);
- uint8_t const res = Nova::call(pt.local_name());
- utcb.crd_rcv = old_crd;
+ Nova::Mem_crd const rcv_crd(memory_remap >> PAGE_4K, DS_ORDER, all);
+ Nova::Mem_crd const snd_crd(memory_wc >> PAGE_4K, DS_ORDER, all);
+ Nova::Crd const old_crd = utcb.crd_rcv;
- if (res != Nova::NOVA_OK) {
- Genode::error("establishing memory failed ", res);
- failed++;
- }
+ utcb.crd_rcv = rcv_crd;
+ utcb.set_msg_word(1);
+ utcb.msg()[0] = snd_crd.value();
+
+ uint8_t const res = Nova::call(pt.local_name());
+ utcb.crd_rcv = old_crd;
+
+ if (res != Nova::NOVA_OK) {
+ Genode::error("establishing memory failed ", res);
+ failed++;
+ }
+ });
/* sanity check - touch re-mapped area */
for (auto offset = 0; offset < DS_SIZE; offset += (1 << PAGE_4K))
@@ -488,20 +493,23 @@ class Pager : private Genode::Thread {
touch_read(reinterpret_cast(_ds_mem));
/* request creation of a 'local' EC */
- Thread::native_thread().ec_sel = Native_thread::INVALID_INDEX - 1;
- Thread::start();
+ with_native_thread([&] (Native_thread &nt) {
- Genode::warning("pager: created");
+ nt.ec_sel = Native_thread::INVALID_INDEX - 1;
- Native_capability thread_cap =
- Capability_space::import(Thread::native_thread().ec_sel);
+ Thread::start();
- Genode::Nova_native_pd_client native_pd(env.pd().native_pd());
- Nova::Mtd mtd (Nova::Mtd::QUAL | Nova::Mtd::EIP | Nova::Mtd::ESP);
- Genode::addr_t entry = reinterpret_cast(page_fault);
+ Genode::warning("pager: created");
- _call_to_map = native_pd.alloc_rpc_cap(thread_cap, entry,
- mtd.value());
+ Native_capability thread_cap = Capability_space::import(nt.ec_sel);
+
+ Genode::Nova_native_pd_client native_pd(env.pd().native_pd());
+ Nova::Mtd mtd (Nova::Mtd::QUAL | Nova::Mtd::EIP | Nova::Mtd::ESP);
+ Genode::addr_t entry = reinterpret_cast(page_fault);
+
+ _call_to_map = native_pd.alloc_rpc_cap(thread_cap, entry,
+ mtd.value());
+ });
}
Native_capability call_to_map() { return _call_to_map; }
@@ -700,11 +708,14 @@ Main::Main(Env &env) : env(env)
};
addr_t sel_pd = cap_map().insert();
- addr_t sel_ec = myself->native_thread().ec_sel;
+ addr_t sel_ec = Native_thread::INVALID_INDEX;
addr_t sel_cap = cap_map().insert();
addr_t handler = 0UL;
uint8_t res = 0;
+ myself->with_native_thread([&] (Native_thread &nt) {
+ sel_ec = nt.ec_sel; });
+
Nova::Mtd mtd(Nova::Mtd::ALL);
if (sel_cap == ~0UL || sel_ec == ~0UL || sel_cap == ~0UL) {
@@ -721,9 +732,10 @@ Main::Main(Env &env) : env(env)
/* changing the badge of one of the portal must fail */
for (unsigned i = 0; i < (1U << Nova::NUM_INITIAL_PT_LOG2); i++) {
- addr_t sel_exc = myself->native_thread().exc_pt_sel + i;
- res = Nova::pt_ctrl(sel_exc, 0xbadbad);
- check(res, "pt_ctrl ", i);
+ myself->with_native_thread([&] (Native_thread &nt) {
+ res = Nova::pt_ctrl(nt.exc_pt_sel + i, 0xbadbad);
+ check(res, "pt_ctrl ", i);
+ });
}
/* test PAT kernel feature */
diff --git a/repos/base-nova/src/timer/nova/main.cc b/repos/base-nova/src/timer/nova/main.cc
index dea30c022a..a72e925060 100644
--- a/repos/base-nova/src/timer/nova/main.cc
+++ b/repos/base-nova/src/timer/nova/main.cc
@@ -104,7 +104,9 @@ class Timer::Device
static Sel init_signal_sem(Thread &thread)
{
- auto const exc_base = thread.native_thread().exc_pt_sel;
+ addr_t exc_base = Native_thread::INVALID_INDEX;
+ thread.with_native_thread([&] (Native_thread &nt) {
+ exc_base = nt.exc_pt_sel; });
request_signal_sm_cap(exc_base + Nova::PT_SEL_PAGE_FAULT,
exc_base + Nova::SM_SEL_SIGNAL);
diff --git a/repos/base-okl4/src/core/pager.cc b/repos/base-okl4/src/core/pager.cc
index 148bb1003c..a079f7998d 100644
--- a/repos/base-okl4/src/core/pager.cc
+++ b/repos/base-okl4/src/core/pager.cc
@@ -144,7 +144,9 @@ void Ipc_pager::acknowledge_wakeup()
Untyped_capability Pager_entrypoint::_pager_object_cap(unsigned long badge)
{
- return Capability_space::import(native_thread().l4id, Rpc_obj_key(badge));
+ return with_native_thread(
+ [&] (Native_thread &nt) { return Capability_space::import(nt.l4id, Rpc_obj_key(badge)); },
+ [&] { return Untyped_capability(); });
}
diff --git a/repos/base-okl4/src/core/thread_start.cc b/repos/base-okl4/src/core/thread_start.cc
index ec27f499e1..57df1a6d5c 100644
--- a/repos/base-okl4/src/core/thread_start.cc
+++ b/repos/base-okl4/src/core/thread_start.cc
@@ -35,18 +35,19 @@ void Thread::_thread_start()
Thread::Start_result Thread::start()
{
- /* create and start platform thread */
- native_thread().pt = new (Core::platform_specific().thread_slab())
- Core::Platform_thread(Core::platform_specific().core_pd(), _stack->name().string());
-
- native_thread().pt->start((void *)_thread_start, stack_top());
+ with_native_thread([&] (Native_thread &nt) {
+ nt.pt = new (Core::platform_specific().thread_slab())
+ Core::Platform_thread(Core::platform_specific().core_pd(),
+ _stack->name().string());
+ nt.pt->start((void *)_thread_start, stack_top());
+ });
return Start_result::OK;
}
-void Thread::_deinit_platform_thread()
+void Thread::_deinit_native_thread(Stack &stack)
{
/* destruct platform thread */
- destroy(Core::platform_specific().thread_slab(), native_thread().pt);
+ destroy(Core::platform_specific().thread_slab(), stack.native_thread().pt);
}
diff --git a/repos/base-okl4/src/include/base/internal/lock_helper.h b/repos/base-okl4/src/include/base/internal/lock_helper.h
index 00bdd5462a..d8103affad 100644
--- a/repos/base-okl4/src/include/base/internal/lock_helper.h
+++ b/repos/base-okl4/src/include/base/internal/lock_helper.h
@@ -33,6 +33,18 @@ static inline void thread_yield() { Okl4::L4_Yield(); }
extern Okl4::L4_ThreadId_t main_thread_tid;
+
+static inline Okl4::L4_ThreadId_t okl4_tid(Genode::Thread *thread_ptr)
+{
+ if (!thread_ptr)
+ return main_thread_tid;
+
+ return thread_ptr->with_native_thread(
+ [&] (Genode::Native_thread &nt) { return nt.l4id; },
+ [&] { return Okl4::L4_ThreadId_t { }; });
+}
+
+
/**
* Custom ExchangeRegisters wrapper for waking up a thread
*
@@ -42,20 +54,17 @@ extern Okl4::L4_ThreadId_t main_thread_tid;
*
* \return true if the thread was in blocking state
*/
-static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_base)
+static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_ptr)
{
using namespace Okl4;
- L4_Word_t dummy;
- L4_ThreadId_t dummy_id;
+ L4_Word_t dummy;
+ L4_ThreadId_t dummy_id;
L4_ThreadState_t state;
- Okl4::L4_ThreadId_t tid = thread_base ?
- thread_base->native_thread().l4id :
- main_thread_tid;
-
- L4_ExchangeRegisters(tid, L4_ExReg_Resume + L4_ExReg_AbortIPC, 0, 0, 0,
- 0, L4_nilthread, &state.raw, &dummy, &dummy, &dummy,
+ L4_ExchangeRegisters(okl4_tid(thread_ptr),
+ L4_ExReg_Resume + L4_ExReg_AbortIPC, 0, 0, 0, 0,
+ L4_nilthread, &state.raw, &dummy, &dummy, &dummy,
&dummy, &dummy_id);
return L4_ThreadWasHalted(state);
@@ -65,24 +74,18 @@ static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_base)
/**
* Yield CPU time to the specified thread
*/
-static inline void thread_switch_to(Genode::Thread *thread_base)
+static inline void thread_switch_to(Genode::Thread *thread_ptr)
{
- Okl4::L4_ThreadId_t tid = thread_base ?
- thread_base->native_thread().l4id :
- main_thread_tid;
- Okl4::L4_ThreadSwitch(tid);
+ Okl4::L4_ThreadSwitch(okl4_tid(thread_ptr));
}
/**
* Unconditionally block the calling thread
*/
-static inline void thread_stop_myself(Genode::Thread *myself)
+static inline void thread_stop_myself(Genode::Thread *thread_ptr)
{
- Okl4::L4_ThreadId_t tid = myself ?
- myself->native_thread().l4id :
- main_thread_tid;
- Okl4::L4_Stop(tid);
+ Okl4::L4_Stop(okl4_tid(thread_ptr));
}
#endif /* _INCLUDE__BASE__INTERNAL__LOCK_HELPER_H_ */
diff --git a/repos/base-okl4/src/include/base/internal/native_thread.h b/repos/base-okl4/src/include/base/internal/native_thread.h
index bd9c0668f0..d6d5894c7f 100644
--- a/repos/base-okl4/src/include/base/internal/native_thread.h
+++ b/repos/base-okl4/src/include/base/internal/native_thread.h
@@ -15,6 +15,7 @@
#define _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_
/* Genode includes */
+#include
#include
/* base-internal includes */
@@ -22,22 +23,24 @@
namespace Core { class Platform_thread; }
-
namespace Genode { struct Native_thread; }
-struct Genode::Native_thread
+struct Genode::Native_thread : Noncopyable
{
- Okl4::L4_ThreadId_t l4id;
+ Okl4::L4_ThreadId_t l4id { };
/**
* Only used in core
*
- * For 'Thread' objects created within core, 'pt' points to
- * the physical thread object, which is going to be destroyed
- * on destruction of the 'Thread'.
+ * For 'Thread' objects created within core, 'pt' points to the physical
+ * thread object, which is going to be destroyed on destruction of the
+ * 'Thread'.
*/
- Core::Platform_thread *pt;
+
+ struct { Core::Platform_thread *pt = nullptr; };
+
+ Native_thread() { }
};
#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_ */
diff --git a/repos/base-okl4/src/lib/base/thread_bootstrap.cc b/repos/base-okl4/src/lib/base/thread_bootstrap.cc
index aa01bd65b1..eaf006189e 100644
--- a/repos/base-okl4/src/lib/base/thread_bootstrap.cc
+++ b/repos/base-okl4/src/lib/base/thread_bootstrap.cc
@@ -17,10 +17,10 @@
#include
/* base-internal includes */
-#include
#include
#include
#include
+#include
using namespace Genode;
@@ -81,16 +81,17 @@ void Genode::prepare_init_main_thread()
void Thread::_thread_bootstrap()
{
- native_thread().l4id.raw = Okl4::copy_uregister_to_utcb();
+ with_native_thread([&] (Native_thread &nt) {
+ nt.l4id.raw = Okl4::copy_uregister_to_utcb(); });
}
-void Thread::_init_platform_thread(size_t, Type type)
+void Thread::_init_native_thread(Stack &stack, size_t, Type type)
{
if (type == NORMAL)
return;
- native_thread().l4id.raw = main_thread_tid.raw;
+ stack.native_thread().l4id.raw = main_thread_tid.raw;
_thread_cap = main_thread_cap();
}
diff --git a/repos/base-pistachio/src/core/pager.cc b/repos/base-pistachio/src/core/pager.cc
index 1fd1bb210b..b8ea10a9fc 100644
--- a/repos/base-pistachio/src/core/pager.cc
+++ b/repos/base-pistachio/src/core/pager.cc
@@ -130,7 +130,9 @@ void Ipc_pager::acknowledge_wakeup()
Untyped_capability Pager_entrypoint::_pager_object_cap(unsigned long badge)
{
- return Capability_space::import(native_thread().l4id, Rpc_obj_key(badge));
+ return with_native_thread(
+ [&] (Native_thread &nt) { return Capability_space::import(nt.l4id, Rpc_obj_key(badge)); },
+ [&] { return Untyped_capability(); });
}
diff --git a/repos/base-pistachio/src/core/thread_start.cc b/repos/base-pistachio/src/core/thread_start.cc
index 6232548265..283cd4ab79 100644
--- a/repos/base-pistachio/src/core/thread_start.cc
+++ b/repos/base-pistachio/src/core/thread_start.cc
@@ -36,21 +36,22 @@ void Thread::_thread_start()
Thread::Start_result Thread::start()
{
- /* create and start platform thread */
- native_thread().pt = new (platform().core_mem_alloc())
- Platform_thread(platform_specific().core_pd(), _stack->name().string());
+ return with_native_thread(
+ [&] (Native_thread &nt) {
+ nt.pt = new (platform().core_mem_alloc())
+ Platform_thread(platform_specific().core_pd(), _stack->name().string());
- native_thread().pt->pager(platform_specific().core_pager());
- native_thread().l4id = native_thread().pt->native_thread_id();
+ nt.pt->pager(platform_specific().core_pager());
+ nt.l4id = nt.pt->native_thread_id();
- native_thread().pt->start((void *)_thread_start, stack_top());
-
- return Start_result::OK;
+ nt.pt->start((void *)_thread_start, stack_top());
+ return Start_result::OK;
+ },
+ [&] { return Start_result::DENIED; });
}
-void Thread::_deinit_platform_thread()
+void Thread::_deinit_native_thread(Stack &stack)
{
- /* destruct platform thread */
- destroy(platform().core_mem_alloc(), native_thread().pt);
+ destroy(platform().core_mem_alloc(), stack.native_thread().pt);
}
diff --git a/repos/base-pistachio/src/include/base/internal/lock_helper.h b/repos/base-pistachio/src/include/base/internal/lock_helper.h
index d1fa78ed49..07c08ad494 100644
--- a/repos/base-pistachio/src/include/base/internal/lock_helper.h
+++ b/repos/base-pistachio/src/include/base/internal/lock_helper.h
@@ -33,6 +33,17 @@ extern Pistachio::L4_ThreadId_t main_thread_tid;
static inline void thread_yield() { Pistachio::L4_Yield(); }
+static inline Pistachio::L4_ThreadId_t pistachio_tid(Genode::Thread *thread_ptr)
+{
+ if (!thread_ptr)
+ return main_thread_tid;
+
+ return thread_ptr->with_native_thread(
+ [&] (Genode::Native_thread &nt) { return nt.l4id; },
+ [&] { return Pistachio::L4_ThreadId_t { }; });
+}
+
+
/**
* Custom ExchangeRegisters wrapper for waking up a thread
*
@@ -42,21 +53,17 @@ static inline void thread_yield() { Pistachio::L4_Yield(); }
*
* \return true if the thread was in blocking state
*/
-static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_base)
+static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_ptr)
{
using namespace Pistachio;
- L4_Word_t dummy;
- L4_ThreadId_t dummy_id;
+ L4_Word_t dummy;
+ L4_ThreadId_t dummy_id;
L4_ThreadState_t state;
- Pistachio::L4_ThreadId_t tid = thread_base ?
- thread_base->native_thread().l4id :
- main_thread_tid;
-
enum { RESUME = 1 << 8, CANCEL_IPC = 3 << 1 };
- L4_ExchangeRegisters(tid, RESUME | CANCEL_IPC, 0, 0, 0,
- 0, L4_nilthread, &state.raw, &dummy, &dummy, &dummy,
+ L4_ExchangeRegisters(pistachio_tid(thread_ptr), RESUME | CANCEL_IPC, 0, 0, 0, 0,
+ L4_nilthread, &state.raw, &dummy, &dummy, &dummy,
&dummy, &dummy_id);
return L4_ThreadWasHalted(state);
@@ -66,24 +73,18 @@ static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_base)
/**
* Yield CPU time to the specified thread
*/
-static inline void thread_switch_to(Genode::Thread *thread_base)
+static inline void thread_switch_to(Genode::Thread *thread_ptr)
{
- Pistachio::L4_ThreadId_t tid = thread_base ?
- thread_base->native_thread().l4id :
- main_thread_tid;
- Pistachio::L4_ThreadSwitch(tid);
+ Pistachio::L4_ThreadSwitch(pistachio_tid(thread_ptr));
}
/**
* Unconditionally block the calling thread
*/
-static inline void thread_stop_myself(Genode::Thread *myself)
+static inline void thread_stop_myself(Genode::Thread *thread_ptr)
{
- Pistachio::L4_ThreadId_t tid = myself ?
- myself->native_thread().l4id :
- main_thread_tid;
- Pistachio::L4_Stop(tid);
+ Pistachio::L4_Stop(pistachio_tid(thread_ptr));
}
#endif /* _INCLUDE__BASE__INTERNAL__LOCK_HELPER_H_ */
diff --git a/repos/base-pistachio/src/include/base/internal/native_thread.h b/repos/base-pistachio/src/include/base/internal/native_thread.h
index d867c9ede5..5ff33f59a0 100644
--- a/repos/base-pistachio/src/include/base/internal/native_thread.h
+++ b/repos/base-pistachio/src/include/base/internal/native_thread.h
@@ -15,6 +15,7 @@
#define _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_
/* Genode includes */
+#include
#include
/* base-internal includes */
@@ -25,9 +26,9 @@ namespace Genode { struct Native_thread; }
namespace Core { class Platform_thread; }
-struct Genode::Native_thread
+struct Genode::Native_thread : Noncopyable
{
- Pistachio::L4_ThreadId_t l4id;
+ Pistachio::L4_ThreadId_t l4id { };
/**
* Only used in core
@@ -36,7 +37,9 @@ struct Genode::Native_thread
* the physical thread object, which is going to be destroyed
* on destruction of the 'Thread'.
*/
- Core::Platform_thread *pt;
+ struct { Core::Platform_thread *pt = nullptr; };
+
+ Native_thread() { }
};
#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_ */
diff --git a/repos/base-pistachio/src/lib/base/thread_bootstrap.cc b/repos/base-pistachio/src/lib/base/thread_bootstrap.cc
index 36d74dcec8..496336b6e7 100644
--- a/repos/base-pistachio/src/lib/base/thread_bootstrap.cc
+++ b/repos/base-pistachio/src/lib/base/thread_bootstrap.cc
@@ -16,7 +16,7 @@
#include
/* base-internal includes */
-#include
+#include
#include
#include
@@ -49,16 +49,17 @@ void Genode::prepare_init_main_thread()
void Genode::Thread::_thread_bootstrap()
{
- native_thread().l4id = Pistachio::L4_Myself();
+ with_native_thread([&] (Native_thread &nt) {
+ nt.l4id = Pistachio::L4_Myself(); });
}
-void Genode::Thread::_init_platform_thread(size_t, Type type)
+void Genode::Thread::_init_native_thread(Stack &stack, size_t, Type type)
{
if (type == NORMAL)
return;
- native_thread().l4id = main_thread_tid;
+ stack.native_thread().l4id = main_thread_tid;
_thread_cap = main_thread_cap();
}
diff --git a/repos/base-sel4/src/core/capability_space.cc b/repos/base-sel4/src/core/capability_space.cc
index f13085c187..4f4c041f20 100644
--- a/repos/base-sel4/src/core/capability_space.cc
+++ b/repos/base-sel4/src/core/capability_space.cc
@@ -123,16 +123,19 @@ Capability_space::create_rpc_obj_cap(Native_capability ep_cap,
Native_capability Capability_space::create_ep_cap(Thread &ep_thread)
{
- Cap_sel const ep_sel(ep_thread.native_thread().ep_sel);
+ return ep_thread.with_native_thread(
+ [&] (Native_thread &nt) {
+ Cap_sel const ep_sel(nt.attr.ep_sel);
- /* entrypoint capabilities are not allocated from a PD session */
- Pd_session const *pd_session = nullptr;
+ /* entrypoint capabilities are not allocated from a PD session */
+ Pd_session const *pd_session = nullptr;
- Native_capability::Data &data =
- local_capability_space().create_capability(ep_sel, pd_session,
- Rpc_obj_key());
-
- return Native_capability(&data);
+ Native_capability::Data &data =
+ local_capability_space().create_capability(ep_sel, pd_session,
+ Rpc_obj_key());
+ return Native_capability(&data);
+ },
+ [&] { return Native_capability(); });
}
diff --git a/repos/base-sel4/src/core/pager.cc b/repos/base-sel4/src/core/pager.cc
index f2eded3b7c..f6827c44ea 100644
--- a/repos/base-sel4/src/core/pager.cc
+++ b/repos/base-sel4/src/core/pager.cc
@@ -65,19 +65,19 @@ void Ipc_pager::reply_and_wait_for_fault()
{
seL4_Word badge = Rpc_obj_key::INVALID;
- seL4_MessageInfo_t page_fault_msg_info;
+ seL4_MessageInfo_t page_fault_msg_info { };
- if (_badge) {
+ Thread::myself()->with_native_thread([&] (Native_thread &nt) {
- seL4_MessageInfo_t const reply_msg = seL4_MessageInfo_new(0, 0, 0, 0);
+ if (_badge) {
+ seL4_MessageInfo_t const reply_msg = seL4_MessageInfo_new(0, 0, 0, 0);
- page_fault_msg_info =
- seL4_ReplyRecv(Thread::myself()->native_thread().ep_sel, reply_msg, &badge);
+ page_fault_msg_info = seL4_ReplyRecv(nt.attr.ep_sel, reply_msg, &badge);
- } else {
- page_fault_msg_info =
- seL4_Recv(Thread::myself()->native_thread().ep_sel, &badge);
- }
+ } else {
+ page_fault_msg_info = seL4_Recv(nt.attr.ep_sel, &badge);
+ }
+ });
Fault_info const fault_info(page_fault_msg_info);
diff --git a/repos/base-sel4/src/core/thread_start.cc b/repos/base-sel4/src/core/thread_start.cc
index 4d4deca40c..2b83f446c2 100644
--- a/repos/base-sel4/src/core/thread_start.cc
+++ b/repos/base-sel4/src/core/thread_start.cc
@@ -30,13 +30,15 @@
using namespace Core;
-void Thread::_init_platform_thread(size_t, Type type)
+void Thread::_init_native_thread(Stack &stack, size_t, Type type)
{
- Utcb_virt const utcb_virt { (addr_t)&_stack->utcb() };
+ Native_thread &nt = stack.native_thread();
+
+ Utcb_virt const utcb_virt { (addr_t)&stack.utcb() };
if (type == MAIN) {
- native_thread().tcb_sel = seL4_CapInitThreadTCB;
- native_thread().lock_sel = INITIAL_SEL_LOCK;
+ nt.attr.tcb_sel = seL4_CapInitThreadTCB;
+ nt.attr.lock_sel = INITIAL_SEL_LOCK;
return;
}
@@ -49,15 +51,15 @@ void Thread::_init_platform_thread(size_t, Type type)
"local=%", Hex(utcb_virt.addr));
}
- native_thread().tcb_sel = thread_info.tcb_sel.value();
- native_thread().ep_sel = thread_info.ep_sel.value();
- native_thread().lock_sel = thread_info.lock_sel.value();
+ nt.attr.tcb_sel = thread_info.tcb_sel.value();
+ nt.attr.ep_sel = thread_info.ep_sel.value();
+ nt.attr.lock_sel = thread_info.lock_sel.value();
Platform &platform = platform_specific();
seL4_CNode_CapData guard = seL4_CNode_CapData_new(0, CONFIG_WORD_SIZE - 32);
seL4_CNode_CapData no_cap_data = { { 0 } };
- int const ret = seL4_TCB_SetSpace(native_thread().tcb_sel, 0,
+ int const ret = seL4_TCB_SetSpace(nt.attr.tcb_sel, 0,
platform.top_cnode().sel().value(),
guard.words[0],
seL4_CapInitThreadPD, no_cap_data.words[0]);
@@ -69,24 +71,24 @@ void Thread::_init_platform_thread(size_t, Type type)
platform.core_cnode().mint(platform.core_cnode(), unbadged_sel, lock_sel);
- native_thread().lock_sel = lock_sel.value();
+ nt.attr.lock_sel = lock_sel.value();
}
-void Thread::_deinit_platform_thread()
+void Thread::_deinit_native_thread(Stack &stack)
{
- addr_t const utcb_virt_addr = (addr_t)&_stack->utcb();
+ addr_t const utcb_virt_addr = (addr_t)&stack.utcb();
bool ret = unmap_local(utcb_virt_addr, 1);
ASSERT(ret);
int res = seL4_CNode_Delete(seL4_CapInitThreadCNode,
- native_thread().lock_sel, 32);
+ stack.native_thread().attr.lock_sel, 32);
if (res)
error(__PRETTY_FUNCTION__, ": seL4_CNode_Delete (",
- Hex(native_thread().lock_sel), ") returned ", res);
+ Hex(stack.native_thread().attr.lock_sel), ") returned ", res);
- platform_specific().core_sel_alloc().free(Cap_sel(native_thread().lock_sel));
+ platform_specific().core_sel_alloc().free(Cap_sel(stack.native_thread().attr.lock_sel));
}
@@ -99,13 +101,7 @@ void Thread::_thread_start()
}
-Thread::Start_result Thread::start()
-{
- /* write ipcbuffer address to utcb*/
- utcb()->ipcbuffer(Native_utcb::Virt { addr_t(utcb()) });
-
- start_sel4_thread(Cap_sel(native_thread().tcb_sel), (addr_t)&_thread_start,
- (addr_t)stack_top(), _affinity.xpos(), addr_t(utcb()));
+namespace {
struct Core_trace_source : public Core::Trace::Source::Info_accessor,
private Core::Trace::Control,
@@ -123,14 +119,15 @@ Thread::Start_result Thread::start()
seL4_IPCBuffer &ipc_buffer = *reinterpret_cast(myself.utcb());
uint64_t const * const buf = reinterpret_cast(ipc_buffer.msg);
- seL4_BenchmarkGetThreadUtilisation(_thread.native_thread().tcb_sel);
+ _thread.with_native_thread([&] (Native_thread &nt) {
+ seL4_BenchmarkGetThreadUtilisation(nt.attr.tcb_sel); });
+
uint64_t const thread_time = buf[BENCHMARK_TCB_UTILISATION];
return { Session_label("core"), _thread.name(),
- Trace::Execution_time(thread_time, 0), _thread._affinity };
+ Genode::Trace::Execution_time(thread_time, 0), _thread.affinity() };
}
-
Core_trace_source(Core::Trace::Source_registry ®istry, Thread &t)
:
Core::Trace::Control(),
@@ -139,9 +136,26 @@ Thread::Start_result Thread::start()
registry.insert(this);
}
};
+}
- new (platform().core_mem_alloc())
- Core_trace_source(Core::Trace::sources(), *this);
+
+Thread::Start_result Thread::start()
+{
+ if (!_stack)
+ return Start_result::DENIED;
+
+ Stack &stack = *_stack;
+
+ /* write ipcbuffer address to utcb*/
+ utcb()->ipcbuffer(Native_utcb::Virt { addr_t(utcb()) });
+
+ start_sel4_thread(Cap_sel(stack.native_thread().attr.tcb_sel),
+ (addr_t)&_thread_start, stack.top(),
+ _affinity.xpos(), addr_t(utcb()));
+ try {
+ new (platform().core_mem_alloc())
+ Core_trace_source(Core::Trace::sources(), *this);
+ } catch (...) { }
return Start_result::OK;
}
diff --git a/repos/base-sel4/src/include/base/internal/kernel_debugger.h b/repos/base-sel4/src/include/base/internal/kernel_debugger.h
index 3c1d2e6334..36e17a5679 100644
--- a/repos/base-sel4/src/include/base/internal/kernel_debugger.h
+++ b/repos/base-sel4/src/include/base/internal/kernel_debugger.h
@@ -32,7 +32,8 @@ static inline void kernel_debugger_panic(char const *msg)
{
kernel_debugger_outstring(msg);
kernel_debugger_outstring("\n");
- seL4_TCB_Suspend(Genode::Thread::myself()->native_thread().tcb_sel);
+ Genode::Thread::myself()->with_native_thread([&] (Genode::Native_thread &nt) {
+ seL4_TCB_Suspend(nt.attr.tcb_sel); });
}
#endif /* _INCLUDE__BASE__INTERNAL__KERNEL_DEBUGGER_H_ */
diff --git a/repos/base-sel4/src/include/base/internal/lock_helper.h b/repos/base-sel4/src/include/base/internal/lock_helper.h
index ebbbc4295e..0225c6d88e 100644
--- a/repos/base-sel4/src/include/base/internal/lock_helper.h
+++ b/repos/base-sel4/src/include/base/internal/lock_helper.h
@@ -31,28 +31,28 @@ static inline void thread_switch_to(Genode::Thread *)
}
-static inline bool thread_check_stopped_and_restart(Genode::Thread *thread)
+static inline unsigned sel4_lock_sel(Genode::Thread *thread_ptr)
{
- unsigned lock_sel = Genode::INITIAL_SEL_LOCK; /* main thread */
+ if (!thread_ptr)
+ return Genode::INITIAL_SEL_LOCK; /* main thread */
- if (thread)
- lock_sel = thread->native_thread().lock_sel;
+ return thread_ptr->with_native_thread(
+ [&] (Genode::Native_thread &nt) { return nt.attr.lock_sel; },
+ [&] () -> unsigned { return Genode::INITIAL_SEL_LOCK; });
+}
- seL4_Signal(lock_sel);
+static inline bool thread_check_stopped_and_restart(Genode::Thread *thread_ptr)
+{
+ seL4_Signal(sel4_lock_sel(thread_ptr));
return true;
}
-static inline void thread_stop_myself(Genode::Thread *myself)
+static inline void thread_stop_myself(Genode::Thread *myself_ptr)
{
- unsigned lock_sel = Genode::INITIAL_SEL_LOCK; /* main thread */
-
- if (myself)
- lock_sel = myself->native_thread().lock_sel;
-
seL4_Word sender = ~0U;
- seL4_Wait(lock_sel, &sender);
+ seL4_Wait(sel4_lock_sel(myself_ptr), &sender);
}
#endif /* _INCLUDE__BASE__INTERNAL__LOCK_HELPER_H_ */
diff --git a/repos/base-sel4/src/include/base/internal/native_thread.h b/repos/base-sel4/src/include/base/internal/native_thread.h
index 8c32dd7907..26598be2e7 100644
--- a/repos/base-sel4/src/include/base/internal/native_thread.h
+++ b/repos/base-sel4/src/include/base/internal/native_thread.h
@@ -14,16 +14,17 @@
#ifndef _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_
#define _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_
+#include
#include
namespace Genode { struct Native_thread; }
-struct Genode::Native_thread
+
+struct Genode::Native_thread : Noncopyable
{
- unsigned tcb_sel = 0;
- unsigned ep_sel = 0;
- unsigned rcv_sel = 0;
- unsigned lock_sel = 0;
+ struct Attr { unsigned tcb_sel, ep_sel, rcv_sel, lock_sel; } attr { };
+
+ Native_thread() { }
};
#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_ */
diff --git a/repos/base-sel4/src/lib/base/capability_space.cc b/repos/base-sel4/src/lib/base/capability_space.cc
index a7705a398e..6249cd7b07 100644
--- a/repos/base-sel4/src/lib/base/capability_space.cc
+++ b/repos/base-sel4/src/lib/base/capability_space.cc
@@ -95,11 +95,15 @@ namespace {
Native_capability Capability_space::create_ep_cap(Thread &ep_thread)
{
- Cap_sel const ep_sel = Cap_sel(ep_thread.native_thread().ep_sel);
+ return ep_thread.with_native_thread(
+ [&] (Native_thread &nt) {
+ Cap_sel const ep_sel = Cap_sel(nt.attr.ep_sel);
- Native_capability::Data *data =
- &local_capability_space().create_capability(ep_sel, Rpc_obj_key());
- return Native_capability(data);
+ Native_capability::Data *data =
+ &local_capability_space().create_capability(ep_sel, Rpc_obj_key());
+ return Native_capability(data);
+ },
+ [&] { return Native_capability(); });
}
diff --git a/repos/base-sel4/src/lib/base/ipc.cc b/repos/base-sel4/src/lib/base/ipc.cc
index f4c79cf5a1..717411aacc 100644
--- a/repos/base-sel4/src/lib/base/ipc.cc
+++ b/repos/base-sel4/src/lib/base/ipc.cc
@@ -39,10 +39,17 @@ enum {
};
+static unsigned &main_rcv_sel()
+{
+ static unsigned _main_rcv_sel = Capability_space::alloc_rcv_sel();
+ return _main_rcv_sel;
+}
+
+
/**
- * Return reference to receive selector of the calling thread
+ * Call 'fn' with a reference to the receive selector of the calling thread
*/
-static unsigned &rcv_sel()
+static void with_rcv_sel_ref(auto const &fn)
{
/*
* When the function is called at the very early initialization phase, we
@@ -50,12 +57,21 @@ static unsigned &rcv_sel()
* Thread object of the main thread does not exist yet. During this
* phase, we return a reference to the 'main_rcv_sel' variable.
*/
- if (Thread::myself()) {
- return Thread::myself()->native_thread().rcv_sel;
- }
+ Thread * const myself_ptr = Thread::myself();
+ if (!myself_ptr)
+ fn(main_rcv_sel());
+ else
+ myself_ptr->with_native_thread(
+ [&] (Native_thread &nt) { fn(nt.attr.rcv_sel); },
+ [&] { ASSERT(false); /* thread w/o stack cannot execute */ });
+}
- static unsigned main_rcv_sel = Capability_space::alloc_rcv_sel();
- return main_rcv_sel;
+
+static void allocate_and_define_rcv_sel()
+{
+ with_rcv_sel_ref([&] (unsigned &rcv_sel) {
+ if (!rcv_sel)
+ rcv_sel = Capability_space::alloc_rcv_sel(); });
}
@@ -253,34 +269,37 @@ static void decode_seL4_message(seL4_MessageInfo_t const &msg_info,
Native_capability arg_cap = Capability_space::lookup(rpc_obj_key);
- if (arg_cap.valid()) {
+ with_rcv_sel_ref([&] (unsigned &rcv_sel_ref) {
- /*
- * Discard the received selector and keep using the already
- * present one.
- *
- * XXX We'd need to find out if both the received and the
- * looked-up selector refer to the same endpoint.
- * Unfortunaltely, seL4 lacks such a comparison operation.
- */
+ if (arg_cap.valid()) {
- Capability_space::reset_sel(rcv_sel());
+ /*
+ * Discard the received selector and keep using the already
+ * present one.
+ *
+ * XXX We'd need to find out if both the received and the
+ * looked-up selector refer to the same endpoint.
+ * Unfortunaltely, seL4 lacks such a comparison operation.
+ */
- dst_msg.insert(arg_cap);
+ Capability_space::reset_sel(rcv_sel_ref);
- } else {
+ dst_msg.insert(arg_cap);
- Capability_space::Ipc_cap_data const
- ipc_cap_data(rpc_obj_key, rcv_sel());
+ } else {
- dst_msg.insert(Capability_space::import(ipc_cap_data));
+ Capability_space::Ipc_cap_data const
+ ipc_cap_data(rpc_obj_key, rcv_sel_ref);
- /*
- * Since we keep using the received selector, we need to
- * allocate a fresh one for the next incoming delegation.
- */
- rcv_sel() = Capability_space::alloc_rcv_sel();
- }
+ dst_msg.insert(Capability_space::import(ipc_cap_data));
+
+ /*
+ * Since we keep using the received selector, we need to
+ * allocate a fresh one for the next incoming delegation.
+ */
+ rcv_sel_ref = Capability_space::alloc_rcv_sel();
+ }
+ });
}
curr_sel4_cap_idx++;
}
@@ -300,9 +319,7 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
kernel_debugger_panic("IPC destination is invalid");
}
- /* allocate and define receive selector */
- if (!rcv_sel())
- rcv_sel() = Capability_space::alloc_rcv_sel();
+ allocate_and_define_rcv_sel();
rcv_msg.reset();
@@ -330,9 +347,7 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
void Genode::ipc_reply(Native_capability, Rpc_exception_code exc,
Msgbuf_base &snd_msg)
{
- /* allocate and define receive selector */
- if (!rcv_sel())
- rcv_sel() = Capability_space::alloc_rcv_sel();
+ allocate_and_define_rcv_sel();
/**
* Do not use Genode primitives after this point until the return which may
@@ -352,29 +367,30 @@ Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &,
Msgbuf_base &reply_msg,
Msgbuf_base &request_msg)
{
- /* allocate and define receive selector */
- if (!rcv_sel())
- rcv_sel() = Capability_space::alloc_rcv_sel();
+ allocate_and_define_rcv_sel();
- seL4_CPtr const dest = Thread::myself()->native_thread().ep_sel;
seL4_Word badge = 0;
- if (exc.value == Rpc_exception_code::INVALID_OBJECT)
- reply_msg.reset();
+ Thread::myself()->with_native_thread([&] (Native_thread &nt) {
- request_msg.reset();
+ seL4_CPtr const dest = nt.attr.ep_sel;
- /**
- * Do not use Genode primitives after this point until the return which may
- * alter the content of the IPCBuffer, e.g. Lock or RPC.
- */
+ if (exc.value == Rpc_exception_code::INVALID_OBJECT)
+ reply_msg.reset();
- seL4_MessageInfo_t const reply_msg_info = new_seL4_message(reply_msg);
- seL4_SetMR(MR_IDX_EXC_CODE, exc.value);
- seL4_MessageInfo_t const req = seL4_ReplyRecv(dest, reply_msg_info, &badge);
+ request_msg.reset();
- decode_seL4_message(req, request_msg);
+ /**
+ * Do not use Genode primitives after this point until the return which may
+ * alter the content of the IPCBuffer, e.g. Lock or RPC.
+ */
+ seL4_MessageInfo_t const reply_msg_info = new_seL4_message(reply_msg);
+ seL4_SetMR(MR_IDX_EXC_CODE, exc.value);
+ seL4_MessageInfo_t const req = seL4_ReplyRecv(dest, reply_msg_info, &badge);
+
+ decode_seL4_message(req, request_msg);
+ });
return Rpc_request(Native_capability(), badge);
}
diff --git a/repos/base-sel4/src/lib/base/thread_bootstrap.cc b/repos/base-sel4/src/lib/base/thread_bootstrap.cc
index 035b612d58..af3c9ccc82 100644
--- a/repos/base-sel4/src/lib/base/thread_bootstrap.cc
+++ b/repos/base-sel4/src/lib/base/thread_bootstrap.cc
@@ -31,12 +31,14 @@ void Genode::prepare_init_main_thread() { }
** Thread **
************/
-void Genode::Thread::_thread_bootstrap()
+void Genode::Thread::_thread_bootstrap()
{
- if (native_thread().ep_sel == 0) {
- native_thread().ep_sel = (unsigned)_stack->utcb().ep_sel();
- native_thread().lock_sel = (unsigned)_stack->utcb().lock_sel();
- }
+ with_native_thread([&] (Native_thread &nt) {
+ if (nt.attr.ep_sel == 0) {
+ nt.attr.ep_sel = (unsigned)_stack->utcb().ep_sel();
+ nt.attr.lock_sel = (unsigned)_stack->utcb().lock_sel();
+ }
+ });
}
diff --git a/repos/base-sel4/src/lib/base/thread_init.cc b/repos/base-sel4/src/lib/base/thread_init.cc
index 1da467661a..aba78aa634 100644
--- a/repos/base-sel4/src/lib/base/thread_init.cc
+++ b/repos/base-sel4/src/lib/base/thread_init.cc
@@ -13,22 +13,20 @@
/* Genode includes */
#include
-#include
+#include
#include
using namespace Genode;
-void Thread::_init_platform_thread(size_t, Type type)
+void Thread::_init_native_thread(Stack &stack, size_t, Type type)
{
- /**
+ /*
* Reset to default values. The default values trigger initial allocations
* and associations the thread, like IPCbuffer in ipc.cc.
*/
- native_thread() = Native_thread();
+ stack.native_thread().attr = { };
- if (type == MAIN) {
- native_thread().lock_sel = INITIAL_SEL_LOCK;
- return;
- }
+ if (type == MAIN)
+ stack.native_thread().attr.lock_sel = INITIAL_SEL_LOCK;
}
diff --git a/repos/base/include/base/thread.h b/repos/base/include/base/thread.h
index 0ae686895d..8ee6395bec 100644
--- a/repos/base/include/base/thread.h
+++ b/repos/base/include/base/thread.h
@@ -84,7 +84,7 @@ class Genode::Thread
/**
* Hook for platform-specific destructor supplements
*/
- void _deinit_platform_thread();
+ void _deinit_native_thread(Stack &);
/*
* Noncopyable
@@ -125,7 +125,7 @@ class Genode::Thread
/**
* Pointer to kernel-specific meta data
*/
- Native_thread *_native_thread = nullptr;
+ Native_thread *_native_thread_ptr = nullptr;
/**
* Blockade used for synchronizing the finalization of the thread
@@ -163,7 +163,7 @@ class Genode::Thread
* \param weight weighting regarding the CPU session quota
* \param type enables selection of special initialization
*/
- void _init_platform_thread(size_t weight, Type type);
+ void _init_native_thread(Stack &, size_t weight, Type type);
void _init_cpu_session_and_trace_control();
@@ -330,9 +330,26 @@ class Genode::Thread
}
/**
- * Return kernel-specific thread meta data
+ * Call 'fn' with kernel-specific 'Native_thread &' as argument,
+ * or 'invalid_fn' if the thread has not been successfully constructed
*/
- Native_thread &native_thread();
+ auto with_native_thread(auto const &fn,
+ auto const &invalid_fn) const -> decltype(invalid_fn())
+ {
+ if (_native_thread_ptr) {
+ Native_thread &native_thread = *_native_thread_ptr;
+ return fn(native_thread);
+ }
+ return invalid_fn();
+ }
+
+ /**
+ * Conditionally call 'fn' with kernel-specific 'Native_thread &'
+ */
+ void with_native_thread(auto const &fn) const
+ {
+ with_native_thread(fn, [&] { });
+ }
/**
* Return top of primary stack
diff --git a/repos/base/src/lib/base/thread.cc b/repos/base/src/lib/base/thread.cc
index b8ebd7d83b..dd6916642e 100644
--- a/repos/base/src/lib/base/thread.cc
+++ b/repos/base/src/lib/base/thread.cc
@@ -201,11 +201,6 @@ void Thread::free_secondary_stack(void* stack_addr)
}
-Native_thread &Thread::native_thread() {
-
- return _stack->native_thread(); }
-
-
void *Thread::stack_top() const { return (void *)_stack->top(); }
@@ -250,7 +245,8 @@ Thread::Thread(size_t weight, const char *name, size_t stack_size,
_trace_control(nullptr),
_stack(_alloc_stack(stack_size, name, type == MAIN))
{
- _init_platform_thread(weight, type);
+ _native_thread_ptr = &_stack->native_thread();
+ _init_native_thread(*_stack, weight, type);
}
@@ -308,7 +304,8 @@ Thread::~Thread()
sleep_forever();
}
- _deinit_platform_thread();
+ _deinit_native_thread(*_stack);
+
_free_stack(_stack);
cxx_free_tls(this);
diff --git a/repos/base/src/lib/base/thread_start.cc b/repos/base/src/lib/base/thread_start.cc
index 5b6d619850..5c1e6148ee 100644
--- a/repos/base/src/lib/base/thread_start.cc
+++ b/repos/base/src/lib/base/thread_start.cc
@@ -64,7 +64,7 @@ void Thread::_thread_start()
** Thread **
************/
-void Thread::_deinit_platform_thread()
+void Thread::_deinit_native_thread(Stack &)
{
if (!_cpu_session) {
error("Thread::_cpu_session unexpectedly not defined");
@@ -81,8 +81,13 @@ Thread::Start_result Thread::start()
{
_init_cpu_session_and_trace_control();
+ if (!_stack)
+ return Start_result::DENIED;
+
+ Stack &stack = *_stack;
+
/* create thread at core */
- addr_t const utcb = (addr_t)&_stack->utcb();
+ addr_t const utcb = (addr_t)&stack.utcb();
_thread_cap = _cpu_session->create_thread(pd_session_cap(), name(), _affinity,
Weight(), utcb);
@@ -90,7 +95,7 @@ Thread::Start_result Thread::start()
[&] (Thread_capability cap) {
/* start execution at initial instruction pointer and stack pointer */
- Cpu_thread_client(cap).start((addr_t)_thread_start, _stack->top());
+ Cpu_thread_client(cap).start((addr_t)_thread_start, stack.top());
return Start_result::OK;
},
[&] (Cpu_session::Create_thread_error) { return Start_result::DENIED; });
diff --git a/repos/ports/include/vmm/vcpu_dispatcher.h b/repos/ports/include/vmm/vcpu_dispatcher.h
index 73d6103c58..a213ac7407 100644
--- a/repos/ports/include/vmm/vcpu_dispatcher.h
+++ b/repos/ports/include/vmm/vcpu_dispatcher.h
@@ -79,7 +79,9 @@ class Vmm::Vcpu_dispatcher : public T
using namespace Genode;
/* request creation of a 'local' EC */
- T::native_thread().ec_sel = Native_thread::INVALID_INDEX - 1;
+ T::with_native_thread([&] (Native_thread &nt) {
+ nt.ec_sel = Native_thread::INVALID_INDEX - 1; });
+
T::start();
}
@@ -95,25 +97,32 @@ class Vmm::Vcpu_dispatcher : public T
*/
void (*entry)() = &_portal_entry;
- /* create the portal at the desired selector index (EV) */
- Native_capability thread_cap =
- Capability_space::import(T::native_thread().ec_sel);
+ Untyped_capability handler { };
- Untyped_capability handler =
- retry(
- [&] () {
- /* manually define selector used for RPC result */
- Thread::myself()->native_thread().client_rcv_sel = exc_base + EV;
- return _native_pd.alloc_rpc_cap(thread_cap, (addr_t)entry,
- mtd.value());
- },
- [&] () {
- Thread::myself()->native_thread().reset_client_rcv_sel();
- _env.parent().upgrade(Parent::Env::pd(), "ram_quota=16K");
- });
+ T::with_native_thread([&] (Native_thread &nt) {
- /* revert selector allocation to automatic mode of operation */
- Thread::myself()->native_thread().reset_client_rcv_sel();
+ /* create the portal at the desired selector index (EV) */
+ Native_capability thread_cap =
+ Capability_space::import(nt.ec_sel);
+
+ Thread::myself()->with_native_thread([&] (Native_thread &myself_nt) {
+
+ handler = retry(
+ [&] () {
+ /* manually define selector used for RPC result */
+ myself_nt.client_rcv_sel = exc_base + EV;
+ return _native_pd.alloc_rpc_cap(thread_cap, (addr_t)entry,
+ mtd.value());
+ },
+ [&] () {
+ myself_nt.reset_client_rcv_sel();
+ _env.parent().upgrade(Parent::Env::pd(), "ram_quota=16K");
+ });
+
+ /* revert selector allocation to automatic mode of operation */
+ myself_nt.reset_client_rcv_sel();
+ });
+ });
return handler.valid() && (exc_base + EV == (addr_t)handler.local_name());
}
diff --git a/repos/ports/include/vmm/vcpu_thread.h b/repos/ports/include/vmm/vcpu_thread.h
index 9d2353e252..cc19fcfdd3 100644
--- a/repos/ports/include/vmm/vcpu_thread.h
+++ b/repos/ports/include/vmm/vcpu_thread.h
@@ -112,9 +112,9 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
* Translate vcpu_vm thread cap via current executing thread,
* which is used to lookup current PD to delegate VM-exit portals.
*/
- addr_t const current = Thread::myself()->native_thread().exc_pt_sel
- + Nova::PT_SEL_PAGE_FAULT;
- translate_remote_pager(current, vcpu_vm.local_name());
+ Thread::myself()->with_native_thread([&] (Native_thread &nt) {
+ addr_t const current = nt.exc_pt_sel + Nova::PT_SEL_PAGE_FAULT;
+ translate_remote_pager(current, vcpu_vm.local_name()); });
/* start vCPU in separate PD */
cpu_thread.start(0, 0);
diff --git a/repos/ports/src/virtualbox5/spec/nova/sup.cc b/repos/ports/src/virtualbox5/spec/nova/sup.cc
index aaa7b98bd0..040b830328 100644
--- a/repos/ports/src/virtualbox5/spec/nova/sup.cc
+++ b/repos/ports/src/virtualbox5/spec/nova/sup.cc
@@ -725,10 +725,14 @@ void genode_update_tsc(void (*update_func)(void), Genode::uint64_t update_us)
Trace::Timestamp wakeup_absolute = Trace::timestamp();
/* initialize first time in context of running thread */
- auto const &exc_base = Thread::myself()->native_thread().exc_pt_sel;
- request_signal_sm_cap(exc_base + Nova::PT_SEL_PAGE_FAULT,
- exc_base + Nova::SM_SEL_SIGNAL);
- Genode::addr_t const sem = exc_base + SM_SEL_SIGNAL;
+ Genode::addr_t const sem = Thread::myself()->with_native_thread(
+ [&] (Native_thread &nt) {
+ auto const &exc_base = nt.exc_pt_sel;
+ request_signal_sm_cap(exc_base + Nova::PT_SEL_PAGE_FAULT,
+ exc_base + Nova::SM_SEL_SIGNAL);
+ return exc_base + SM_SEL_SIGNAL;
+ },
+ [&] () -> Genode::addr_t { return Native_thread::INVALID_INDEX; });
for (;;) {
update_func();