mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-16 07:27:35 +00:00
Remove C++ exceptions from 'Thread' API
After constructed, a 'Thread' object may remain in a dysfunctional state should the stack allocation have failed. This condition is no longer reflected as a C++ exception but as result value of 'Thread::info()'. Keep 'Thread::name' as public constant because the stack is not always available for storing the name. The 'stack_top' accessor has been removed because this information is already provided by 'Thread::info()'. Issue #5245
This commit is contained in:
parent
0736db0863
commit
7e420a68a6
@ -35,26 +35,25 @@ void Thread::_thread_start()
|
||||
|
||||
Thread::Start_result Thread::start()
|
||||
{
|
||||
if (!_stack)
|
||||
return Start_result::DENIED;
|
||||
return _stack.convert<Start_result>([&] (Stack * const stack) {
|
||||
|
||||
Stack &stack = *_stack;
|
||||
Native_thread &nt = stack->native_thread();
|
||||
|
||||
Native_thread &nt = stack.native_thread();
|
||||
/* create and start platform thread */
|
||||
try {
|
||||
nt.pt = new (platform().core_mem_alloc())
|
||||
Platform_thread(platform_specific().core_pd(), name.string());
|
||||
}
|
||||
catch (...) { return Start_result::DENIED; }
|
||||
|
||||
/* create and start platform thread */
|
||||
try {
|
||||
nt.pt = new (platform().core_mem_alloc())
|
||||
Platform_thread(platform_specific().core_pd(), stack.name().string());
|
||||
}
|
||||
catch (...) { return Start_result::DENIED; }
|
||||
nt.pt->pager(platform_specific().core_pager());
|
||||
nt.l4id = nt.pt->native_thread_id();
|
||||
|
||||
nt.pt->pager(platform_specific().core_pager());
|
||||
nt.l4id = nt.pt->native_thread_id();
|
||||
nt.pt->start((void *)_thread_start, (void *)stack->top());
|
||||
|
||||
nt.pt->start((void *)_thread_start, (void *)stack.top());
|
||||
return Start_result::OK;
|
||||
|
||||
return Start_result::OK;
|
||||
}, [&] (Stack_error) { return Start_result::DENIED; });
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,11 +63,11 @@ namespace {
|
||||
addr_t const kcap = (addr_t) platform_thread.pager_object_badge();
|
||||
l4_msgtag_t res = l4_thread_stats_time(kcap, &ec_time);
|
||||
if (l4_error(res))
|
||||
Genode::error("cpu time for ", thread.name(),
|
||||
Genode::error("cpu time for ", thread.name,
|
||||
" is not available ", l4_error(res));
|
||||
}
|
||||
|
||||
return { Session_label("core"), thread.name(),
|
||||
return { Session_label("core"), thread.name,
|
||||
Genode::Trace::Execution_time(ec_time, sc_time, 10000,
|
||||
platform_thread.prio()),
|
||||
thread.affinity() };
|
||||
@ -92,7 +92,7 @@ Thread::Start_result Thread::start()
|
||||
try {
|
||||
/* create and start platform thread */
|
||||
Platform_thread &pt = *new (platform().core_mem_alloc())
|
||||
Platform_thread(_stack->name().string());
|
||||
Platform_thread(name.string());
|
||||
|
||||
platform_specific().core_pd().bind_thread(pt);
|
||||
|
||||
@ -111,15 +111,21 @@ Thread::Start_result Thread::start()
|
||||
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());
|
||||
return _stack.convert<Start_result>(
|
||||
[&] (Stack *stack) {
|
||||
pt.start((void *)_thread_start, (void *)stack->top());
|
||||
|
||||
try {
|
||||
new (platform().core_mem_alloc())
|
||||
Core_trace_source(Core::Trace::sources(), *this, pt);
|
||||
}
|
||||
catch (...) { }
|
||||
try {
|
||||
new (platform().core_mem_alloc())
|
||||
Core_trace_source(Core::Trace::sources(), *this, pt);
|
||||
}
|
||||
catch (...) { }
|
||||
|
||||
return Start_result::OK;
|
||||
},
|
||||
[&] (Stack_error) { return Start_result::DENIED; });
|
||||
}
|
||||
catch (...) { return Start_result::DENIED; }
|
||||
catch (...) { }
|
||||
|
||||
return Start_result::OK;
|
||||
return Start_result::DENIED;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ void Thread::_init_native_thread(Stack &stack, size_t weight, Type type)
|
||||
if (type == NORMAL) {
|
||||
|
||||
/* create thread at core */
|
||||
_thread_cap = _cpu_session->create_thread(pd_session_cap(), name(),
|
||||
_thread_cap = _cpu_session->create_thread(pd_session_cap(), name,
|
||||
_affinity, Weight(weight));
|
||||
return;
|
||||
}
|
||||
@ -113,9 +113,13 @@ Thread::Start_result Thread::start()
|
||||
|
||||
/* register initial IP and SP at core */
|
||||
Cpu_thread_client cpu_thread(cap);
|
||||
cpu_thread.start((addr_t)_thread_start, _stack->top());
|
||||
|
||||
return Start_result::OK;
|
||||
return _stack.convert<Start_result>(
|
||||
[&] (Stack *stack) {
|
||||
cpu_thread.start((addr_t)_thread_start, stack->top());
|
||||
return Start_result::OK;
|
||||
},
|
||||
[&] (Stack_error) { return Start_result::DENIED; });
|
||||
},
|
||||
[&] (Cpu_session::Create_thread_error) { return Start_result::DENIED; }
|
||||
);
|
||||
|
@ -20,6 +20,3 @@ Genode::Thread * Genode::Thread::myself()
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Genode::Thread::Name Genode::Thread::name() const { return "bootstrap"; }
|
||||
|
@ -51,7 +51,7 @@ namespace {
|
||||
if (nt.platform_thread)
|
||||
execution_time = nt.platform_thread->execution_time(); });
|
||||
|
||||
return { Session_label("core"), thread.name(),
|
||||
return { Session_label("core"), thread.name,
|
||||
execution_time, thread.affinity() };
|
||||
}
|
||||
|
||||
@ -69,25 +69,24 @@ namespace {
|
||||
|
||||
Thread::Start_result Thread::start()
|
||||
{
|
||||
if (!_stack)
|
||||
return Start_result::DENIED;
|
||||
return _stack.convert<Start_result>([&] (Stack * const stack) {
|
||||
|
||||
Stack &stack = *_stack;
|
||||
Native_thread &nt = stack->native_thread();
|
||||
|
||||
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());
|
||||
|
||||
/* 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;;
|
||||
|
||||
if (_thread_cap.failed())
|
||||
return Start_result::DENIED;;
|
||||
/* create trace sources for core threads */
|
||||
try {
|
||||
new (platform().core_mem_alloc()) Trace_source(Core::Trace::sources(), *this);
|
||||
} catch (...) { }
|
||||
|
||||
/* create trace sources for core threads */
|
||||
try {
|
||||
new (platform().core_mem_alloc()) Trace_source(Core::Trace::sources(), *this);
|
||||
} catch (...) { }
|
||||
return Start_result::OK;
|
||||
|
||||
return Start_result::OK;
|
||||
}, [&] (Stack_error) { return Start_result::DENIED; });
|
||||
}
|
||||
|
||||
|
||||
@ -100,8 +99,10 @@ void Thread::_deinit_native_thread(Stack &stack)
|
||||
void Thread::_init_native_thread(Stack &stack, size_t, Type type)
|
||||
{
|
||||
if (type == NORMAL) {
|
||||
stack.native_thread().platform_thread = new (platform().core_mem_alloc())
|
||||
Platform_thread(_stack->name(), stack.utcb());
|
||||
_stack.with_result([&] (Stack * const stack) {
|
||||
stack->native_thread().platform_thread = new (platform().core_mem_alloc())
|
||||
Platform_thread(name, stack->utcb());
|
||||
}, [&] (Stack_error) { });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -66,10 +66,12 @@ void Genode::prepare_init_main_thread()
|
||||
__attribute__((optimize("-fno-delete-null-pointer-checks")))
|
||||
Native_utcb *Thread::utcb()
|
||||
{
|
||||
if (this)
|
||||
return &_stack->utcb();
|
||||
if (!this)
|
||||
return utcb_main_thread();
|
||||
|
||||
return utcb_main_thread();
|
||||
return _stack.convert<Native_utcb *>(
|
||||
[&] (Stack *stack) { return &stack->utcb(); },
|
||||
[&] (Stack_error) { return utcb_main_thread(); });
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,7 +60,7 @@ void Thread::_init_native_thread(Stack &stack, size_t weight, Type type)
|
||||
/* create server object */
|
||||
addr_t const utcb = (addr_t)&stack.utcb();
|
||||
|
||||
_thread_cap = _cpu_session->create_thread(pd_session_cap(), name(), _affinity,
|
||||
_thread_cap = _cpu_session->create_thread(pd_session_cap(), name, _affinity,
|
||||
Weight(weight), utcb);
|
||||
return;
|
||||
}
|
||||
@ -107,42 +107,40 @@ void Thread::_deinit_native_thread(Stack &stack)
|
||||
|
||||
Thread::Start_result Thread::start()
|
||||
{
|
||||
if (!_stack)
|
||||
return Start_result::DENIED;
|
||||
return _stack.convert<Start_result>([&] (Stack * const stack) {
|
||||
|
||||
Stack &stack = *_stack;
|
||||
while (avail_capability_slab() < 5)
|
||||
upgrade_capability_slab();
|
||||
|
||||
while (avail_capability_slab() < 5)
|
||||
upgrade_capability_slab();
|
||||
return _thread_cap.convert<Start_result>(
|
||||
[&] (Thread_capability cap) {
|
||||
Cpu_thread_client cpu_thread(cap);
|
||||
|
||||
return _thread_cap.convert<Start_result>(
|
||||
[&] (Thread_capability cap) {
|
||||
Cpu_thread_client cpu_thread(cap);
|
||||
|
||||
/* attach UTCB at top of stack */
|
||||
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)
|
||||
+ stack_virtual_size() - size - stack_area_virtual_base(),
|
||||
.executable = { },
|
||||
.writeable = true
|
||||
}).convert<Start_result>(
|
||||
[&] (Region_map::Range) {
|
||||
/* start execution with initial IP and aligned SP */
|
||||
cpu_thread.start((addr_t)_thread_start, stack.top());
|
||||
return Start_result::OK;
|
||||
},
|
||||
[&] (Region_map::Attach_error) {
|
||||
error("failed to attach userland stack");
|
||||
return Start_result::DENIED;
|
||||
}
|
||||
);
|
||||
},
|
||||
[&] (Cpu_session::Create_thread_error) { return Start_result::DENIED; }
|
||||
);
|
||||
/* attach UTCB at top of stack */
|
||||
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)
|
||||
+ stack_virtual_size() - size - stack_area_virtual_base(),
|
||||
.executable = { },
|
||||
.writeable = true
|
||||
}).convert<Start_result>(
|
||||
[&] (Region_map::Range) {
|
||||
/* start execution with initial IP and aligned SP */
|
||||
cpu_thread.start((addr_t)_thread_start, stack->top());
|
||||
return Start_result::OK;
|
||||
},
|
||||
[&] (Region_map::Attach_error) {
|
||||
error("failed to attach userland stack");
|
||||
return Start_result::DENIED;
|
||||
}
|
||||
);
|
||||
},
|
||||
[&] (Cpu_session::Create_thread_error) { return Start_result::DENIED; }
|
||||
);
|
||||
}, [&] (Stack_error) { return Start_result::DENIED; });
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,13 +30,20 @@ static void empty_signal_handler(int) { }
|
||||
|
||||
void Thread::_thread_start()
|
||||
{
|
||||
Thread * const thread_ptr = Thread::myself();
|
||||
Thread &thread = *Thread::myself();
|
||||
|
||||
/* use primary stack as alternate stack for fatal signals (exceptions) */
|
||||
void *stack_base = (void *)thread_ptr->_stack->base();
|
||||
size_t stack_size = thread_ptr->_stack->top() - thread_ptr->_stack->base();
|
||||
thread._stack.with_result(
|
||||
[&] (Stack *stack) {
|
||||
|
||||
lx_sigaltstack(stack_base, stack_size);
|
||||
/* use primary stack as alternate stack for fatal signals (exceptions) */
|
||||
void *stack_base = (void *)stack->base();
|
||||
size_t stack_size = stack->top() - stack->base();
|
||||
|
||||
lx_sigaltstack(stack_base, stack_size);
|
||||
},
|
||||
[&] (Stack_error) {
|
||||
warning("attempt to start thread ", thread.name, " without stack"); }
|
||||
);
|
||||
|
||||
/*
|
||||
* Set signal handler such that canceled system calls get not transparently
|
||||
@ -52,8 +59,8 @@ void Thread::_thread_start()
|
||||
*/
|
||||
lx_sigsetmask(LX_SIGCHLD, false);
|
||||
|
||||
Thread::myself()->entry();
|
||||
Thread::myself()->_join.wakeup();
|
||||
thread.entry();
|
||||
thread._join.wakeup();
|
||||
sleep_forever();
|
||||
}
|
||||
|
||||
@ -66,11 +73,12 @@ void Thread::_deinit_native_thread(Stack &) { }
|
||||
|
||||
Thread::Start_result Thread::start()
|
||||
{
|
||||
return with_native_thread(
|
||||
[&] (Native_thread &nt) {
|
||||
nt.tid = lx_create_thread(Thread::_thread_start, stack_top());
|
||||
return _stack.convert<Start_result>(
|
||||
[&] (Stack *stack) {
|
||||
Native_thread &nt = stack->native_thread();
|
||||
nt.tid = lx_create_thread(Thread::_thread_start, (void *)stack->top());
|
||||
nt.pid = lx_getpid();
|
||||
return Start_result::OK;
|
||||
},
|
||||
[&] { return Start_result::DENIED; });
|
||||
[&] (Stack_error) { return Start_result::DENIED; });
|
||||
}
|
||||
|
@ -65,16 +65,22 @@ static void thread_exit_signal_handler(int) { lx_exit(0); }
|
||||
|
||||
void Thread::_thread_start()
|
||||
{
|
||||
Thread * const thread = Thread::myself();
|
||||
Thread &thread = *Thread::myself();
|
||||
|
||||
/* use primary stack as alternate stack for fatal signals (exceptions) */
|
||||
void *stack_base = (void *)thread->_stack->base();
|
||||
size_t stack_size = thread->_stack->top() - thread->_stack->base();
|
||||
thread._stack.with_result(
|
||||
[&] (Stack *stack) {
|
||||
/* use primary stack as alternate stack for fatal signals (exceptions) */
|
||||
void *stack_base = (void *)stack->base();
|
||||
size_t stack_size = stack->top() - stack->base();
|
||||
|
||||
lx_sigaltstack(stack_base, stack_size);
|
||||
if (stack_size < 0x1000)
|
||||
raw("small stack of ", stack_size, " bytes for \"", thread->name(),
|
||||
"\" may break Linux signal handling");
|
||||
lx_sigaltstack(stack_base, stack_size);
|
||||
if (stack_size < 0x1000)
|
||||
raw("small stack of ", stack_size, " bytes for \"", thread.name,
|
||||
"\" may break Linux signal handling");
|
||||
},
|
||||
[&] (Stack_error) {
|
||||
warning("attempt to start thread ", thread.name, " without stack"); }
|
||||
);
|
||||
|
||||
/*
|
||||
* Set signal handler such that canceled system calls get not
|
||||
@ -83,18 +89,18 @@ 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(), nt.pid, nt.tid);
|
||||
thread.with_native_thread([&] (Native_thread &nt) {
|
||||
Linux_native_cpu_client native_cpu(thread._cpu_session->native_cpu());
|
||||
native_cpu.thread_id(thread.cap(), nt.pid, nt.tid);
|
||||
});
|
||||
|
||||
/* wakeup 'start' function */
|
||||
startup_lock().wakeup();
|
||||
|
||||
thread->entry();
|
||||
thread.entry();
|
||||
|
||||
/* unblock caller of 'join()' */
|
||||
thread->_join.wakeup();
|
||||
thread._join.wakeup();
|
||||
|
||||
sleep_forever();
|
||||
}
|
||||
@ -180,15 +186,19 @@ Thread::Start_result Thread::start()
|
||||
threadlib_initialized = true;
|
||||
}
|
||||
|
||||
with_native_thread([&] (Native_thread &nt) {
|
||||
nt.tid = lx_create_thread(Thread::_thread_start, stack_top());
|
||||
nt.pid = lx_getpid();
|
||||
});
|
||||
return _stack.convert<Start_result>(
|
||||
[&] (Stack *stack) {
|
||||
Native_thread &nt = stack->native_thread();
|
||||
|
||||
/* wait until the 'thread_start' function got entered */
|
||||
startup_lock().block();
|
||||
nt.tid = lx_create_thread(Thread::_thread_start, (void *)stack->top());
|
||||
nt.pid = lx_getpid();
|
||||
|
||||
return Start_result::OK;
|
||||
/* wait until the 'thread_start' function got entered */
|
||||
startup_lock().block();
|
||||
|
||||
return Start_result::OK;
|
||||
},
|
||||
[&] (Stack_error) { return Start_result::DENIED; });
|
||||
}
|
||||
|
||||
|
||||
|
@ -515,7 +515,8 @@ void Thread::join()
|
||||
|
||||
Thread::Thread(size_t weight, const char *name, size_t /* stack size */,
|
||||
Type, Cpu_session * cpu_sess, Affinity::Location)
|
||||
: _cpu_session(cpu_sess), _affinity()
|
||||
:
|
||||
name(name), _cpu_session(cpu_sess), _affinity()
|
||||
{
|
||||
Native_thread::Meta_data *meta_data =
|
||||
new (global_alloc()) Thread_meta_data_created(this);
|
||||
@ -526,7 +527,7 @@ Thread::Thread(size_t weight, const char *name, size_t /* stack size */,
|
||||
if (ret) {
|
||||
error("pthread_create failed (returned ", ret, ", errno=", errno, ")");
|
||||
destroy(global_alloc(), meta_data);
|
||||
throw Out_of_stack_space();
|
||||
return;
|
||||
}
|
||||
|
||||
with_native_thread([&] (Native_thread &nt) {
|
||||
|
@ -77,5 +77,5 @@ void Ipc_pager::reply_and_wait_for_fault(addr_t sm)
|
||||
*/
|
||||
utcb.set_msg_word((_normal_ipc && _syscall_res != Nova::NOVA_OK) ? 1 : 0);
|
||||
|
||||
Nova::reply(myself.stack_top(), sm);
|
||||
Nova::reply((void *)Thread::mystack().top, sm);
|
||||
}
|
||||
|
@ -39,6 +39,10 @@ using namespace Nova;
|
||||
|
||||
static Rpc_entrypoint *_core_ep_ptr;
|
||||
|
||||
|
||||
static inline void *my_stack_top() { return (void *)Thread::mystack().top; }
|
||||
|
||||
|
||||
void Core::init_page_fault_handling(Rpc_entrypoint &ep) { _core_ep_ptr = &ep; }
|
||||
|
||||
|
||||
@ -244,7 +248,7 @@ void Pager_object::exception(uint8_t const exit_id)
|
||||
utcb.set_msg_word(0);
|
||||
utcb.mtd = mtd;
|
||||
|
||||
reply(myself.stack_top());
|
||||
reply(my_stack_top());
|
||||
}
|
||||
|
||||
|
||||
@ -308,7 +312,7 @@ void Pager_object::_recall_handler(Pager_object &obj)
|
||||
|
||||
utcb.set_msg_word(0);
|
||||
utcb.mtd = 0;
|
||||
reply(myself.stack_top());
|
||||
reply(my_stack_top());
|
||||
}
|
||||
|
||||
if (obj._state.modified) {
|
||||
@ -343,7 +347,7 @@ void Pager_object::_recall_handler(Pager_object &obj)
|
||||
obj._state_lock.release();
|
||||
|
||||
utcb.set_msg_word(0);
|
||||
reply(myself.stack_top(), sm);
|
||||
reply(my_stack_top(), sm);
|
||||
}
|
||||
|
||||
|
||||
@ -365,7 +369,7 @@ void Pager_object::_startup_handler(Pager_object &obj)
|
||||
|
||||
utcb.set_msg_word(0);
|
||||
|
||||
reply(myself.stack_top());
|
||||
reply(my_stack_top());
|
||||
}
|
||||
|
||||
|
||||
@ -378,7 +382,7 @@ void Pager_object::_invoke_handler(Pager_object &obj)
|
||||
if (utcb.msg_words() != 1) {
|
||||
utcb.mtd = 0;
|
||||
utcb.set_msg_word(0);
|
||||
reply(myself.stack_top());
|
||||
reply(my_stack_top());
|
||||
}
|
||||
|
||||
addr_t const event = utcb.msg()[0];
|
||||
@ -413,7 +417,7 @@ void Pager_object::_invoke_handler(Pager_object &obj)
|
||||
|
||||
utcb.mtd = 0;
|
||||
utcb.set_msg_word(0);
|
||||
reply(myself.stack_top());
|
||||
reply(my_stack_top());
|
||||
}
|
||||
|
||||
utcb.mtd = 0;
|
||||
@ -449,7 +453,7 @@ void Pager_object::_invoke_handler(Pager_object &obj)
|
||||
bool res = Nova::create_sm(obj.exc_pt_sel_client() + PT_SEL_STARTUP,
|
||||
platform_specific().core_pd_sel(), 0);
|
||||
if (res != Nova::NOVA_OK)
|
||||
reply(myself.stack_top());
|
||||
reply(my_stack_top());
|
||||
|
||||
obj._state.mark_signal_sm();
|
||||
}
|
||||
@ -459,7 +463,7 @@ void Pager_object::_invoke_handler(Pager_object &obj)
|
||||
(void)res;
|
||||
}
|
||||
|
||||
reply(myself.stack_top());
|
||||
reply(my_stack_top());
|
||||
}
|
||||
|
||||
|
||||
@ -879,7 +883,7 @@ void Pager_object::_oom_handler(addr_t pager_dst, addr_t pager_src,
|
||||
error("unknown OOM case - stop core pager thread");
|
||||
myself.with_native_thread([&] (Native_thread &nt) {
|
||||
utcb.set_msg_word(0);
|
||||
reply(myself.stack_top(), nt.exc_pt_sel + Nova::SM_SEL_EC);
|
||||
reply(my_stack_top(), nt.exc_pt_sel + Nova::SM_SEL_EC);
|
||||
});
|
||||
}
|
||||
|
||||
@ -887,7 +891,7 @@ void Pager_object::_oom_handler(addr_t pager_dst, addr_t pager_src,
|
||||
if (policy == STOP) {
|
||||
error("PD has insufficient kernel memory left - stop thread");
|
||||
utcb.set_msg_word(0);
|
||||
reply(myself.stack_top(), obj_dst.sel_sm_block_pause());
|
||||
reply(my_stack_top(), obj_dst.sel_sm_block_pause());
|
||||
}
|
||||
|
||||
char const * src_pd = "core";
|
||||
@ -901,7 +905,7 @@ void Pager_object::_oom_handler(addr_t pager_dst, addr_t pager_src,
|
||||
error("Unknown PD has insufficient kernel memory left - stop thread");
|
||||
myself.with_native_thread([&] (Native_thread &nt) {
|
||||
utcb.set_msg_word(0);
|
||||
reply(myself.stack_top(), nt.exc_pt_sel + Nova::SM_SEL_EC);
|
||||
reply(my_stack_top(), nt.exc_pt_sel + Nova::SM_SEL_EC);
|
||||
});
|
||||
break;
|
||||
|
||||
@ -933,7 +937,7 @@ void Pager_object::_oom_handler(addr_t pager_dst, addr_t pager_src,
|
||||
uint8_t res = obj_dst.handle_oom(transfer_from, src_pd, src_thread, policy);
|
||||
if (res == Nova::NOVA_OK)
|
||||
/* handling succeeded - continue with original IPC */
|
||||
reply(myself.stack_top());
|
||||
reply(my_stack_top());
|
||||
|
||||
/* transfer nothing */
|
||||
utcb.set_msg_word(0);
|
||||
@ -945,7 +949,7 @@ void Pager_object::_oom_handler(addr_t pager_dst, addr_t pager_src,
|
||||
/* else: caller will get blocked until RCU period is over */
|
||||
|
||||
/* block caller in semaphore */
|
||||
reply(myself.stack_top(), obj_dst.sel_sm_block_oom());
|
||||
reply(my_stack_top(), obj_dst.sel_sm_block_oom());
|
||||
}
|
||||
|
||||
|
||||
|
@ -90,25 +90,34 @@ Thread::Start_result Thread::start()
|
||||
*/
|
||||
using namespace Nova;
|
||||
|
||||
addr_t sp = _stack->top();
|
||||
Utcb &utcb = *reinterpret_cast<Utcb *>(&_stack->utcb());
|
||||
bool const ec_created = _stack.convert<bool>([&] (Stack *stack) {
|
||||
|
||||
/* create local EC */
|
||||
enum { LOCAL_THREAD = false };
|
||||
unsigned const kernel_cpu_id = platform_specific().kernel_cpu_id(_affinity);
|
||||
addr_t sp = stack->top();
|
||||
Utcb &utcb = reinterpret_cast<Utcb &>(stack->utcb());
|
||||
|
||||
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);
|
||||
/* create local EC */
|
||||
enum { LOCAL_THREAD = false };
|
||||
unsigned const kernel_cpu_id = platform_specific().kernel_cpu_id(_affinity);
|
||||
|
||||
Native_thread &nt = stack->native_thread();
|
||||
|
||||
uint8_t 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 false;
|
||||
}
|
||||
|
||||
/* default: we don't accept any mappings or translations */
|
||||
utcb.crd_rcv = Obj_crd();
|
||||
utcb.crd_xlt = Obj_crd();
|
||||
return true;
|
||||
|
||||
}, [&] (Stack_error) { return false; });
|
||||
|
||||
if (!ec_created)
|
||||
return Start_result::DENIED;
|
||||
}
|
||||
|
||||
/* default: we don't accept any mappings or translations */
|
||||
utcb.crd_rcv = Obj_crd();
|
||||
utcb.crd_xlt = Obj_crd();
|
||||
|
||||
for (unsigned i = 0; i < NUM_INITIAL_PT; i++) {
|
||||
if (i == SM_SEL_EC)
|
||||
@ -148,7 +157,7 @@ Thread::Start_result Thread::start()
|
||||
warning("ec_time for core thread failed res=", res);
|
||||
});
|
||||
|
||||
return { Session_label("core"), thread.name(),
|
||||
return { Session_label("core"), thread.name,
|
||||
Trace::Execution_time(ec_time, 0), thread._affinity };
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ static void reply(Nova::Utcb &utcb, Rpc_exception_code exc, Msgbuf_base &snd_msg
|
||||
{
|
||||
copy_msgbuf_to_utcb(utcb, snd_msg, exc.value);
|
||||
|
||||
Nova::reply(Thread::myself()->stack_top());
|
||||
Nova::reply((void *)Thread::mystack().top);
|
||||
}
|
||||
|
||||
|
||||
@ -226,13 +226,16 @@ Rpc_entrypoint::Rpc_entrypoint(Pd_session *pd_session, size_t stack_size,
|
||||
return;
|
||||
}
|
||||
|
||||
with_native_thread([&] (Native_thread &nt) {
|
||||
Receive_window &rcv_window = nt.server_rcv_window;
|
||||
_stack.with_result(
|
||||
[&] (Stack *stack) {
|
||||
Receive_window &rcv_window = stack->native_thread().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");
|
||||
},
|
||||
[&] (Stack_error) { }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -116,5 +116,7 @@ Native_utcb *Thread::utcb()
|
||||
*/
|
||||
if (this == 0) return main_thread_utcb();
|
||||
|
||||
return &_stack->utcb();
|
||||
return _stack.convert<Native_utcb *>(
|
||||
[&] (Stack *stack) { return &stack->utcb(); },
|
||||
[&] (Stack_error) { return main_thread_utcb(); });
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ void Thread::_thread_start()
|
||||
Thread::myself()->entry();
|
||||
} catch (...) {
|
||||
try {
|
||||
error("Thread '", Thread::myself()->name(), "' "
|
||||
error("Thread '", Thread::myself()->name, "' "
|
||||
"died because of an uncaught exception");
|
||||
} catch (...) {
|
||||
/* die in a noisy way */
|
||||
@ -123,7 +123,7 @@ void Thread::_init_native_thread(Stack &stack, size_t weight, Type type)
|
||||
_init_cpu_session_and_trace_control();
|
||||
|
||||
/* create thread at core */
|
||||
_cpu_session->create_thread(pd_session_cap(), name(),
|
||||
_cpu_session->create_thread(pd_session_cap(), name,
|
||||
_affinity, Weight(weight)).with_result(
|
||||
[&] (Thread_capability cap) { _thread_cap = cap; },
|
||||
[&] (Cpu_session::Create_thread_error) {
|
||||
@ -149,7 +149,9 @@ void Thread::_deinit_native_thread(Stack &stack)
|
||||
|
||||
Thread::Start_result Thread::start()
|
||||
{
|
||||
return with_native_thread([&] (Native_thread &nt) {
|
||||
return _stack.convert<Start_result>([&] (Stack *stack) {
|
||||
|
||||
Native_thread &nt = stack->native_thread();
|
||||
|
||||
if (nt.ec_sel < Native_thread::INVALID_INDEX - 1) {
|
||||
error("Thread::start failed due to invalid exception portal selector");
|
||||
@ -188,7 +190,7 @@ Thread::Start_result Thread::start()
|
||||
addr_t thread_ip = global ? reinterpret_cast<addr_t>(_thread_start) : nt.initial_ip;
|
||||
|
||||
Cpu_thread_client cpu_thread(cap());
|
||||
cpu_thread.start(thread_ip, _stack->top());
|
||||
cpu_thread.start(thread_ip, stack->top());
|
||||
|
||||
/* request native EC thread cap */
|
||||
nt.ec_sel = nt.exc_pt_sel + Nova::EC_SEL_THREAD;
|
||||
@ -211,7 +213,7 @@ Thread::Start_result Thread::start()
|
||||
|
||||
return Start_result::OK;
|
||||
|
||||
}, [&] { return Start_result::DENIED; });
|
||||
}, [&] (Stack_error) { return Start_result::DENIED; });
|
||||
}
|
||||
|
||||
|
||||
|
@ -660,7 +660,7 @@ static void nova_reply(Thread &myself, Nova::Utcb &utcb, auto &&... args)
|
||||
/* 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((void *)Thread::mystack().top, args...);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -285,7 +285,7 @@ static void portal_entry()
|
||||
SOLELY_MAP, NO_DMA, EVILLY_DONT_WRITE_COMBINE);
|
||||
(void)ok;
|
||||
|
||||
Nova::reply(myself.stack_top());
|
||||
Nova::reply((void *)Thread::mystack().top);
|
||||
}
|
||||
|
||||
void test_pat(Genode::Env &env)
|
||||
@ -478,7 +478,7 @@ class Pager : private Genode::Thread {
|
||||
bool res = utcb->append_item(crd_map, 0);
|
||||
(void)res;
|
||||
|
||||
Nova::reply(myself->stack_top());
|
||||
Nova::reply((void *)Thread::mystack().top);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -35,14 +35,19 @@ void Thread::_thread_start()
|
||||
|
||||
Thread::Start_result Thread::start()
|
||||
{
|
||||
with_native_thread([&] (Native_thread &nt) {
|
||||
return _stack.convert<Start_result>([&] (Stack * const stack) {
|
||||
|
||||
Native_thread &nt = stack->native_thread();
|
||||
|
||||
nt.pt = new (Core::platform_specific().thread_slab())
|
||||
Core::Platform_thread(Core::platform_specific().core_pd(),
|
||||
_stack->name().string());
|
||||
name.string());
|
||||
|
||||
nt.pt->start((void *)_thread_start, stack_top());
|
||||
});
|
||||
return Start_result::OK;
|
||||
nt.pt->start((void *)_thread_start, (void *)stack->top());
|
||||
|
||||
return Start_result::OK;
|
||||
|
||||
}, [&] (Stack_error) { return Start_result::DENIED; });
|
||||
}
|
||||
|
||||
|
||||
|
@ -36,18 +36,20 @@ void Thread::_thread_start()
|
||||
|
||||
Thread::Start_result Thread::start()
|
||||
{
|
||||
return with_native_thread(
|
||||
[&] (Native_thread &nt) {
|
||||
nt.pt = new (platform().core_mem_alloc())
|
||||
Platform_thread(platform_specific().core_pd(), _stack->name().string());
|
||||
return _stack.convert<Start_result>([&] (Stack * const stack) {
|
||||
|
||||
nt.pt->pager(platform_specific().core_pager());
|
||||
nt.l4id = nt.pt->native_thread_id();
|
||||
Native_thread &nt = stack->native_thread();
|
||||
|
||||
nt.pt->start((void *)_thread_start, stack_top());
|
||||
return Start_result::OK;
|
||||
},
|
||||
[&] { return Start_result::DENIED; });
|
||||
nt.pt = new (platform().core_mem_alloc())
|
||||
Platform_thread(platform_specific().core_pd(), stack->name().string());
|
||||
|
||||
nt.pt->pager(platform_specific().core_pager());
|
||||
nt.l4id = nt.pt->native_thread_id();
|
||||
|
||||
nt.pt->start((void *)_thread_start, (void *)stack->top());
|
||||
return Start_result::OK;
|
||||
|
||||
}, [&] (Stack_error) { return Start_result::DENIED; });
|
||||
}
|
||||
|
||||
|
||||
|
@ -124,7 +124,7 @@ namespace {
|
||||
|
||||
uint64_t const thread_time = buf[BENCHMARK_TCB_UTILISATION];
|
||||
|
||||
return { Session_label("core"), _thread.name(),
|
||||
return { Session_label("core"), _thread.name,
|
||||
Genode::Trace::Execution_time(thread_time, 0), _thread.affinity() };
|
||||
}
|
||||
|
||||
@ -141,30 +141,28 @@ namespace {
|
||||
|
||||
Thread::Start_result Thread::start()
|
||||
{
|
||||
if (!_stack)
|
||||
return Start_result::DENIED;
|
||||
return _stack.convert<Start_result>([&] (Stack *stack) {
|
||||
|
||||
Stack &stack = *_stack;
|
||||
/* write ipcbuffer address to utcb*/
|
||||
utcb()->ipcbuffer(Native_utcb::Virt { addr_t(utcb()) });
|
||||
|
||||
/* 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 (...) { }
|
||||
|
||||
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;
|
||||
|
||||
return Start_result::OK;
|
||||
}, [&] (Stack_error) { return Start_result::DENIED; });
|
||||
}
|
||||
|
||||
|
||||
Native_utcb *Thread::utcb()
|
||||
{
|
||||
if (!_stack)
|
||||
return nullptr;
|
||||
|
||||
return &_stack->utcb();
|
||||
return _stack.convert<Native_utcb *>(
|
||||
[] (Stack *stack) { return &stack->utcb(); },
|
||||
[] (Stack_error) { return nullptr; });
|
||||
}
|
||||
|
@ -33,12 +33,17 @@ void Genode::prepare_init_main_thread() { }
|
||||
|
||||
void Genode::Thread::_thread_bootstrap()
|
||||
{
|
||||
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();
|
||||
}
|
||||
});
|
||||
_stack.with_result(
|
||||
[&] (Stack *stack) {
|
||||
Native_thread &nt = stack->native_thread();
|
||||
|
||||
if (nt.attr.ep_sel == 0) {
|
||||
nt.attr.ep_sel = (unsigned)stack->utcb().ep_sel();
|
||||
nt.attr.lock_sel = (unsigned)stack->utcb().lock_sel();
|
||||
}
|
||||
},
|
||||
[&] (Stack_error) { }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -124,6 +124,13 @@ struct Sel4_vcpu : Genode::Thread, Noncopyable
|
||||
|
||||
seL4_VCPUContext _recent_gpr { };
|
||||
|
||||
addr_t _with_utcb(auto const &fn)
|
||||
{
|
||||
return _stack.convert<addr_t>(
|
||||
[&] (Stack *stack) { return fn(stack->utcb()); },
|
||||
[&] (Stack_error) { return 0UL; /* cannot happen */ });
|
||||
}
|
||||
|
||||
void entry() override
|
||||
{
|
||||
/* trigger that thread is up */
|
||||
@ -133,9 +140,12 @@ struct Sel4_vcpu : Genode::Thread, Noncopyable
|
||||
_wake_up.down();
|
||||
|
||||
/* get selector to read/write VMCS */
|
||||
addr_t const service = _stack->utcb().ep_sel();
|
||||
addr_t const service = _with_utcb([&] (Native_utcb &utcb) {
|
||||
return utcb.ep_sel(); });
|
||||
|
||||
/* get selector to call back a vCPU into VMM */
|
||||
_recall = _stack->utcb().lock_sel();
|
||||
_recall = _with_utcb([&] (Native_utcb &utcb) {
|
||||
return utcb.lock_sel(); });
|
||||
|
||||
Vcpu_state &state = _state;
|
||||
state.discharge();
|
||||
|
@ -487,11 +487,11 @@ class Genode::Rpc_entrypoint : Thread, public Object_pool<Rpc_object_base>
|
||||
* Check whether given stack info matches stack of the entrypoint.
|
||||
*
|
||||
* \noapi
|
||||
*
|
||||
*/
|
||||
bool myself(addr_t const ptr) const
|
||||
{
|
||||
return addr_t(stack_base()) <= ptr && ptr <= addr_t(stack_top());
|
||||
Stack_info const info = mystack();
|
||||
return info.base <= ptr && ptr <= info.top;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -41,31 +41,34 @@ class Genode::Thread
|
||||
{
|
||||
public:
|
||||
|
||||
class Out_of_stack_space : public Exception { };
|
||||
class Stack_too_large : public Exception { };
|
||||
class Stack_alloc_failed : public Exception { };
|
||||
|
||||
using Location = Affinity::Location;
|
||||
using Name = Cpu_session::Name;
|
||||
using Weight = Cpu_session::Weight;
|
||||
|
||||
enum class Stack_error { STACK_AREA_EXHAUSTED, STACK_TOO_LARGE };
|
||||
|
||||
struct Stack_info { addr_t base; addr_t top;
|
||||
addr_t libc_tls_pointer_offset; };
|
||||
|
||||
Name const name;
|
||||
|
||||
private:
|
||||
|
||||
using Alloc_stack_result = Attempt<Stack *, Stack_error>;
|
||||
|
||||
/**
|
||||
* Allocate and locally attach a new stack
|
||||
*
|
||||
* \param stack_size size of this threads stack
|
||||
* \param main_thread wether this is the main thread
|
||||
*/
|
||||
Stack *_alloc_stack(size_t stack_size, char const *name, bool main_thread);
|
||||
Alloc_stack_result _alloc_stack(size_t stack_size, Name const &name,
|
||||
bool main_thread);
|
||||
|
||||
/**
|
||||
* Detach and release stack of the thread
|
||||
*/
|
||||
void _free_stack(Stack *stack);
|
||||
void _free_stack(Stack &stack);
|
||||
|
||||
/**
|
||||
* Platform-specific thread-startup code
|
||||
@ -118,9 +121,9 @@ class Genode::Thread
|
||||
Trace::Control *_trace_control = nullptr;
|
||||
|
||||
/**
|
||||
* Pointer to primary stack
|
||||
* Primary stack
|
||||
*/
|
||||
Stack *_stack = nullptr;
|
||||
Attempt<Stack *, Stack_error> _stack = Stack_error::STACK_AREA_EXHAUSTED;
|
||||
|
||||
/**
|
||||
* Pointer to kernel-specific meta data
|
||||
@ -188,10 +191,6 @@ class Genode::Thread
|
||||
* \param name thread name (for debugging)
|
||||
* \param stack_size stack size
|
||||
*
|
||||
* \throw Stack_too_large
|
||||
* \throw Stack_alloc_failed
|
||||
* \throw Out_of_stack_space
|
||||
*
|
||||
* The stack for the new thread will be allocated from the RAM session
|
||||
* of the component environment. A small portion of the stack size is
|
||||
* internally used by the framework for storing thread-specific
|
||||
@ -218,10 +217,6 @@ class Genode::Thread
|
||||
* \param type enables selection of special construction
|
||||
* \param cpu_session capability to cpu session used for construction
|
||||
*
|
||||
* \throw Stack_too_large
|
||||
* \throw Stack_alloc_failed
|
||||
* \throw Out_of_stack_space
|
||||
*
|
||||
* \deprecated superseded by the 'Thread(Env &...' constructor
|
||||
*/
|
||||
Thread(size_t weight, const char *name, size_t stack_size,
|
||||
@ -245,10 +240,6 @@ class Genode::Thread
|
||||
* needs to interact with the environment for attaching the thread's
|
||||
* stack, the trace-control dataspace, and the thread's trace buffer
|
||||
* and policy.
|
||||
*
|
||||
* \throw Stack_too_large
|
||||
* \throw Stack_alloc_failed
|
||||
* \throw Out_of_stack_space
|
||||
*/
|
||||
Thread(Env &env, Name const &name, size_t stack_size, Location location,
|
||||
Weight weight, Cpu_session &cpu);
|
||||
@ -282,26 +273,11 @@ class Genode::Thread
|
||||
*/
|
||||
virtual Start_result start();
|
||||
|
||||
/**
|
||||
* Request name of thread
|
||||
*
|
||||
* \noapi
|
||||
* \deprecated use the 'Name name() const' method instead
|
||||
*/
|
||||
void name(char *dst, size_t dst_len);
|
||||
|
||||
/**
|
||||
* Request name of thread
|
||||
*/
|
||||
Name name() const;
|
||||
using Alloc_secondary_stack_result = Attempt<void *, Stack_error>;
|
||||
|
||||
/**
|
||||
* Add an additional stack to the thread
|
||||
*
|
||||
* \throw Stack_too_large
|
||||
* \throw Stack_alloc_failed
|
||||
* \throw Out_of_stack_space
|
||||
*
|
||||
* The stack for the new thread will be allocated from the RAM
|
||||
* session of the component environment. A small portion of the
|
||||
* stack size is internally used by the framework for storing
|
||||
@ -309,7 +285,8 @@ class Genode::Thread
|
||||
*
|
||||
* \return pointer to the new stack's top
|
||||
*/
|
||||
void* alloc_secondary_stack(char const *name, size_t stack_size);
|
||||
Alloc_secondary_stack_result alloc_secondary_stack(Name const &name,
|
||||
size_t stack_size);
|
||||
|
||||
/**
|
||||
* Remove a secondary stack from the thread
|
||||
@ -351,20 +328,6 @@ class Genode::Thread
|
||||
with_native_thread(fn, [&] { });
|
||||
}
|
||||
|
||||
/**
|
||||
* Return top of primary stack
|
||||
*
|
||||
* \return pointer just after first stack element
|
||||
*/
|
||||
void *stack_top() const;
|
||||
|
||||
/**
|
||||
* Return base of primary stack
|
||||
*
|
||||
* \return pointer to last stack element
|
||||
*/
|
||||
void *stack_base() const;
|
||||
|
||||
/**
|
||||
* Return virtual size reserved for each stack within the stack area
|
||||
*/
|
||||
@ -380,6 +343,13 @@ class Genode::Thread
|
||||
*/
|
||||
static size_t stack_area_virtual_size();
|
||||
|
||||
using Info_result = Attempt<Stack_info, Stack_error>;
|
||||
|
||||
/**
|
||||
* Return information about the thread's stack
|
||||
*/
|
||||
Info_result info() const;
|
||||
|
||||
/**
|
||||
* Return 'Thread' object corresponding to the calling thread
|
||||
*
|
||||
@ -392,15 +362,14 @@ class Genode::Thread
|
||||
*/
|
||||
static Stack_info mystack();
|
||||
|
||||
using Stack_size_result = Attempt<size_t, Stack_error>;
|
||||
|
||||
/**
|
||||
* Ensure that the stack has a given size at the minimum
|
||||
*
|
||||
* \param size minimum stack size
|
||||
*
|
||||
* \throw Stack_too_large
|
||||
* \throw Stack_alloc_failed
|
||||
*/
|
||||
void stack_size(size_t const size);
|
||||
Stack_size_result stack_size(size_t const size);
|
||||
|
||||
/**
|
||||
* Return user-level thread control block
|
||||
|
@ -262,11 +262,10 @@ _ZN6Genode6SignalC2ERKS0_ T
|
||||
_ZN6Genode6SignalD1Ev T
|
||||
_ZN6Genode6SignalD2Ev T
|
||||
_ZN6Genode6SignalaSERKS0_ T
|
||||
_ZN6Genode6Thread10stack_sizeEm T
|
||||
_ZN6Genode6Thread13native_threadEv T
|
||||
_ZN6Genode6Thread18stack_virtual_sizeEv T
|
||||
_ZN6Genode6Thread20free_secondary_stackEPv T
|
||||
_ZN6Genode6Thread21alloc_secondary_stackEPKcm T
|
||||
_ZN6Genode6Thread21alloc_secondary_stackERKNS_6StringILm32EEEm T
|
||||
_ZN6Genode6Thread23stack_area_virtual_baseEv T
|
||||
_ZN6Genode6Thread23stack_area_virtual_sizeEv T
|
||||
_ZN6Genode6Thread4joinEv T
|
||||
@ -326,6 +325,7 @@ _ZNK6Genode5Child15main_thread_capEv T
|
||||
_ZNK6Genode5Child18skipped_heartbeatsEv T
|
||||
_ZNK6Genode5Child21notify_resource_availEv T
|
||||
_ZNK6Genode6Thread10stack_baseEv T
|
||||
_ZNK6Genode6Thread4infoEv T
|
||||
_ZNK6Genode6Thread4nameEv T
|
||||
_ZNK6Genode6Thread9stack_topEv T
|
||||
_ZNK6Genode8Duration17trunc_to_plain_msEv T
|
||||
|
@ -74,7 +74,9 @@ class Genode::Stack
|
||||
{
|
||||
public:
|
||||
|
||||
using Name = Cpu_session::Name;
|
||||
using Name = Cpu_session::Name;
|
||||
using Size_result = Thread::Stack_size_result;
|
||||
using Error = Thread::Stack_error;
|
||||
|
||||
private:
|
||||
|
||||
@ -170,11 +172,9 @@ class Genode::Stack
|
||||
* Ensure that the stack has a given minimum size
|
||||
*
|
||||
* \param size minimum stack size
|
||||
*
|
||||
* \throw Stack_too_large
|
||||
* \throw Stack_alloc_failed
|
||||
* \return actually available stack size
|
||||
*/
|
||||
void size(size_t const size);
|
||||
Size_result size(size_t const size);
|
||||
|
||||
/**
|
||||
* Return kernel-specific thread meta data
|
||||
|
@ -64,7 +64,7 @@ class Genode::Stack_allocator
|
||||
/**
|
||||
* Release stack
|
||||
*/
|
||||
void free(Stack *);
|
||||
void free(Stack &);
|
||||
|
||||
/**
|
||||
* Return 'Stack' object for a given base address
|
||||
|
@ -152,7 +152,7 @@ bool Entrypoint::_wait_and_dispatch_one_io_signal(bool const dont_block)
|
||||
{
|
||||
if (!_rpc_ep->is_myself())
|
||||
warning(__func__, " called from non-entrypoint thread \"",
|
||||
Thread::myself()->name(), "\"");
|
||||
Thread::myself()->name, "\"");
|
||||
|
||||
for (;;) {
|
||||
|
||||
|
@ -60,9 +60,9 @@ Stack_allocator::alloc(Thread *, bool main_thread)
|
||||
}
|
||||
|
||||
|
||||
void Stack_allocator::free(Stack *stack)
|
||||
void Stack_allocator::free(Stack &stack)
|
||||
{
|
||||
addr_t const base = addr_to_base(stack);
|
||||
addr_t const base = addr_to_base(&stack);
|
||||
|
||||
Mutex::Guard guard(_threads_mutex);
|
||||
_alloc.free(base_to_idx(base));
|
||||
|
@ -30,11 +30,12 @@ static Region_map *local_rm_ptr;
|
||||
static Cpu_session *cpu_session_ptr;
|
||||
|
||||
|
||||
void Stack::size(size_t const size)
|
||||
Stack::Size_result Stack::size(size_t const size)
|
||||
{
|
||||
/* check if the stack needs to be enhanced */
|
||||
size_t const stack_size = (addr_t)_stack - _base;
|
||||
if (stack_size >= size) { return; }
|
||||
if (stack_size >= size)
|
||||
return stack_size;
|
||||
|
||||
/* check if the stack enhancement fits the stack region */
|
||||
enum {
|
||||
@ -45,7 +46,7 @@ void Stack::size(size_t const size)
|
||||
addr_t const stack_slot_base = Stack_allocator::addr_to_base(this);
|
||||
size_t const ds_size = align_addr(size - stack_size, PAGE_SIZE_LOG2);
|
||||
if (_base - ds_size < stack_slot_base)
|
||||
throw Thread::Stack_too_large();
|
||||
return Error::STACK_TOO_LARGE;
|
||||
|
||||
/* allocate and attach backing store for the stack enhancement */
|
||||
addr_t const ds_addr = _base - ds_size - stack_area_virtual_base();
|
||||
@ -53,41 +54,44 @@ void Stack::size(size_t const size)
|
||||
Ram_allocator &ram = *env_stack_area_ram_allocator;
|
||||
Region_map &rm = *env_stack_area_region_map;
|
||||
|
||||
ram.try_alloc(ds_size).with_result(
|
||||
return ram.try_alloc(ds_size).convert<Size_result>(
|
||||
[&] (Ram_dataspace_capability ds_cap) {
|
||||
|
||||
rm.attach(ds_cap, Region_map::Attr {
|
||||
return rm.attach(ds_cap, Region_map::Attr {
|
||||
.size = ds_size,
|
||||
.offset = 0,
|
||||
.use_at = true,
|
||||
.at = ds_addr,
|
||||
.executable = { },
|
||||
.writeable = true,
|
||||
}).with_result(
|
||||
[&] (Region_map::Range r) {
|
||||
}).convert<Size_result> (
|
||||
|
||||
[&] (Region_map::Range r) -> Size_result {
|
||||
if (r.start != ds_addr)
|
||||
throw Thread::Stack_alloc_failed();
|
||||
return Error::STACK_AREA_EXHAUSTED;
|
||||
|
||||
/* update stack information */
|
||||
_base -= ds_size;
|
||||
|
||||
return (addr_t)_stack - _base;
|
||||
},
|
||||
[&] (Region_map::Attach_error) {
|
||||
throw Thread::Stack_alloc_failed(); }
|
||||
return Error::STACK_AREA_EXHAUSTED; }
|
||||
);
|
||||
},
|
||||
[&] (Ram_allocator::Alloc_error) {
|
||||
throw Thread::Stack_alloc_failed(); }
|
||||
return Error::STACK_AREA_EXHAUSTED; }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Stack *
|
||||
Thread::_alloc_stack(size_t stack_size, char const *name, bool main_thread)
|
||||
Thread::Alloc_stack_result
|
||||
Thread::_alloc_stack(size_t stack_size, Name const &name, bool main_thread)
|
||||
{
|
||||
/* allocate stack */
|
||||
Stack *stack = Stack_allocator::stack_allocator().alloc(this, main_thread);
|
||||
if (!stack)
|
||||
throw Out_of_stack_space();
|
||||
return Stack_error::STACK_AREA_EXHAUSTED;
|
||||
|
||||
/* determine size of dataspace to allocate for the stack */
|
||||
enum { PAGE_SIZE_LOG2 = 12 };
|
||||
@ -95,7 +99,7 @@ Thread::_alloc_stack(size_t stack_size, char const *name, bool main_thread)
|
||||
|
||||
if (stack_size >= stack_virtual_size() -
|
||||
sizeof(Native_utcb) - (1UL << PAGE_SIZE_LOG2))
|
||||
throw Stack_too_large();
|
||||
return Stack_error::STACK_TOO_LARGE;
|
||||
|
||||
/*
|
||||
* Calculate base address of the stack
|
||||
@ -112,7 +116,7 @@ Thread::_alloc_stack(size_t stack_size, char const *name, bool main_thread)
|
||||
Ram_allocator &ram = *env_stack_area_ram_allocator;
|
||||
|
||||
/* allocate and attach backing store for the stack */
|
||||
return ram.try_alloc(ds_size).convert<Stack *>(
|
||||
return ram.try_alloc(ds_size).convert<Alloc_stack_result>(
|
||||
|
||||
[&] (Ram_dataspace_capability const ds_cap)
|
||||
{
|
||||
@ -125,12 +129,12 @@ Thread::_alloc_stack(size_t stack_size, char const *name, bool main_thread)
|
||||
.at = attach_addr,
|
||||
.executable = { },
|
||||
.writeable = true
|
||||
}).convert<Stack *>(
|
||||
}).convert<Alloc_stack_result>(
|
||||
|
||||
[&] (Region_map::Range const range) -> Stack * {
|
||||
[&] (Region_map::Range const range) -> Alloc_stack_result {
|
||||
if (range.start != attach_addr) {
|
||||
ram.free(ds_cap);
|
||||
throw Stack_alloc_failed();
|
||||
return Stack_error::STACK_TOO_LARGE;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -147,25 +151,25 @@ Thread::_alloc_stack(size_t stack_size, char const *name, bool main_thread)
|
||||
Abi::init_stack(stack->top());
|
||||
return stack;
|
||||
},
|
||||
[&] (Region_map::Attach_error) -> Stack * {
|
||||
[&] (Region_map::Attach_error) -> Alloc_stack_result {
|
||||
ram.free(ds_cap);
|
||||
throw Stack_alloc_failed();
|
||||
return Stack_error::STACK_AREA_EXHAUSTED;
|
||||
}
|
||||
);
|
||||
},
|
||||
[&] (Ram_allocator::Alloc_error) -> Stack * {
|
||||
throw Stack_alloc_failed(); }
|
||||
[&] (Ram_allocator::Alloc_error) -> Alloc_stack_result {
|
||||
return Stack_error::STACK_AREA_EXHAUSTED; }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void Thread::_free_stack(Stack *stack)
|
||||
void Thread::_free_stack(Stack &stack)
|
||||
{
|
||||
addr_t ds_addr = stack->base() - stack_area_virtual_base();
|
||||
Ram_dataspace_capability ds_cap = stack->ds_cap();
|
||||
addr_t ds_addr = stack.base() - stack_area_virtual_base();
|
||||
Ram_dataspace_capability ds_cap = stack.ds_cap();
|
||||
|
||||
/* call de-constructor explicitly before memory gets detached */
|
||||
stack->~Stack();
|
||||
stack.~Stack();
|
||||
|
||||
Genode::env_stack_area_region_map->detach(ds_addr);
|
||||
Genode::env_stack_area_ram_allocator->free(ds_cap);
|
||||
@ -175,47 +179,55 @@ void Thread::_free_stack(Stack *stack)
|
||||
}
|
||||
|
||||
|
||||
void Thread::name(char *dst, size_t dst_len)
|
||||
static Thread::Stack_info stack_info(Stack &stack)
|
||||
{
|
||||
copy_cstring(dst, name().string(), dst_len);
|
||||
return { stack.base(), stack.top(),
|
||||
stack_virtual_size() - stack.libc_tls_pointer_offset() };
|
||||
}
|
||||
|
||||
|
||||
Thread::Name Thread::name() const { return _stack->name(); }
|
||||
Thread::Info_result Thread::info() const
|
||||
{
|
||||
return _stack.convert<Info_result>(
|
||||
[&] (Stack *stack) { return stack_info(*stack); },
|
||||
[&] (Stack_error e) { return e; });
|
||||
}
|
||||
|
||||
|
||||
void Thread::join() { _join.block(); }
|
||||
|
||||
|
||||
void *Thread::alloc_secondary_stack(char const *name, size_t stack_size)
|
||||
Thread::Alloc_secondary_stack_result
|
||||
Thread::alloc_secondary_stack(Name const &name, size_t stack_size)
|
||||
{
|
||||
Stack *stack = _alloc_stack(stack_size, name, false);
|
||||
return (void *)stack->top();
|
||||
return _alloc_stack(stack_size, name, false).convert<Alloc_secondary_stack_result>(
|
||||
[&] (Stack *stack) { return (void *)stack->top(); },
|
||||
[&] (Stack_error e) { return e; });
|
||||
}
|
||||
|
||||
|
||||
void Thread::free_secondary_stack(void* stack_addr)
|
||||
{
|
||||
addr_t base = Stack_allocator::addr_to_base(stack_addr);
|
||||
_free_stack(Stack_allocator::base_to_stack(base));
|
||||
_free_stack(*Stack_allocator::base_to_stack(base));
|
||||
}
|
||||
|
||||
|
||||
void *Thread::stack_top() const { return (void *)_stack->top(); }
|
||||
|
||||
|
||||
void *Thread::stack_base() const { return (void*)_stack->base(); }
|
||||
|
||||
|
||||
void Thread::stack_size(size_t const size) { _stack->size(size); }
|
||||
Thread::Stack_size_result Thread::stack_size(size_t const size)
|
||||
{
|
||||
return _stack.convert<Stack_size_result>(
|
||||
[&] (Stack *stack) {
|
||||
stack->size(size);
|
||||
return stack->top() - stack->base();
|
||||
},
|
||||
[&] (Stack_error e) { return e; });
|
||||
}
|
||||
|
||||
|
||||
Thread::Stack_info Thread::mystack()
|
||||
{
|
||||
addr_t base = Stack_allocator::addr_to_base(&base);
|
||||
Stack *stack = Stack_allocator::base_to_stack(base);
|
||||
return { stack->base(), stack->top(),
|
||||
stack_virtual_size() - stack->libc_tls_pointer_offset() };
|
||||
return stack_info(*Stack_allocator::base_to_stack(base));
|
||||
}
|
||||
|
||||
|
||||
@ -240,13 +252,18 @@ size_t Thread::stack_area_virtual_size()
|
||||
Thread::Thread(size_t weight, const char *name, size_t stack_size,
|
||||
Type type, Cpu_session *cpu_session, Affinity::Location affinity)
|
||||
:
|
||||
name(name),
|
||||
_cpu_session(cpu_session),
|
||||
_affinity(affinity),
|
||||
_trace_control(nullptr),
|
||||
_stack(_alloc_stack(stack_size, name, type == MAIN))
|
||||
{
|
||||
_native_thread_ptr = &_stack->native_thread();
|
||||
_init_native_thread(*_stack, weight, type);
|
||||
_stack.with_result(
|
||||
[&] (Stack *stack) {
|
||||
_native_thread_ptr = &stack->native_thread();
|
||||
_init_native_thread(*stack, weight, type);
|
||||
},
|
||||
[&] (Stack_error) { /* error reflected by 'info()' */ });
|
||||
}
|
||||
|
||||
|
||||
@ -299,14 +316,16 @@ Thread::Thread(Env &env, Name const &name, size_t stack_size)
|
||||
Thread::~Thread()
|
||||
{
|
||||
if (Thread::myself() == this) {
|
||||
error("thread '", _stack->name().string(), "' "
|
||||
"tried to self de-struct - sleeping forever.");
|
||||
error("thread '", name, "' tried to self de-struct - sleeping forever.");
|
||||
sleep_forever();
|
||||
}
|
||||
|
||||
_deinit_native_thread(*_stack);
|
||||
|
||||
_free_stack(_stack);
|
||||
_stack.with_result(
|
||||
[&] (Stack *stack) {
|
||||
_deinit_native_thread(*stack);
|
||||
_free_stack(*stack);
|
||||
},
|
||||
[&] (Stack_error) { });
|
||||
|
||||
cxx_free_tls(this);
|
||||
|
||||
|
@ -44,7 +44,7 @@ void Thread::_thread_start()
|
||||
Thread::myself()->entry();
|
||||
} catch (...) {
|
||||
try {
|
||||
raw("Thread '", Thread::myself()->name().string(),
|
||||
raw("Thread '", Thread::myself()->name,
|
||||
"' died because of an uncaught exception");
|
||||
} catch (...) {
|
||||
/* die in a noisy way */
|
||||
@ -81,24 +81,23 @@ Thread::Start_result Thread::start()
|
||||
{
|
||||
_init_cpu_session_and_trace_control();
|
||||
|
||||
if (!_stack)
|
||||
return Start_result::DENIED;
|
||||
return _stack.convert<Start_result>([&] (Stack *stack) {
|
||||
|
||||
Stack &stack = *_stack;
|
||||
/* create thread at core */
|
||||
addr_t const utcb = (addr_t)&stack->utcb();
|
||||
|
||||
/* create thread at core */
|
||||
addr_t const utcb = (addr_t)&stack.utcb();
|
||||
_thread_cap = _cpu_session->create_thread(pd_session_cap(), name, _affinity,
|
||||
Weight(), utcb);
|
||||
return _thread_cap.convert<Start_result>(
|
||||
[&] (Thread_capability cap) {
|
||||
|
||||
_thread_cap = _cpu_session->create_thread(pd_session_cap(), name(), _affinity,
|
||||
Weight(), utcb);
|
||||
return _thread_cap.convert<Start_result>(
|
||||
[&] (Thread_capability cap) {
|
||||
/* start execution at initial instruction pointer and stack pointer */
|
||||
Cpu_thread_client(cap).start((addr_t)_thread_start, stack->top());
|
||||
return Start_result::OK;
|
||||
},
|
||||
[&] (Cpu_session::Create_thread_error) { return Start_result::DENIED; });
|
||||
|
||||
/* start execution at initial instruction pointer and stack pointer */
|
||||
Cpu_thread_client(cap).start((addr_t)_thread_start, stack.top());
|
||||
return Start_result::OK;
|
||||
},
|
||||
[&] (Cpu_session::Create_thread_error) { return Start_result::DENIED; });
|
||||
}, [&] (Stack_error) { return Start_result::DENIED; });
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,4 +19,8 @@
|
||||
#include <base/internal/native_utcb.h>
|
||||
|
||||
|
||||
Genode::Native_utcb *Genode::Thread::utcb() { return &_stack->utcb(); }
|
||||
Genode::Native_utcb *Genode::Thread::utcb()
|
||||
{
|
||||
return _stack.convert<Native_utcb *>([&] (Stack *stack) { return &stack->utcb(); },
|
||||
[&] (Stack_error) { return nullptr; });
|
||||
}
|
||||
|
@ -96,13 +96,7 @@ extern "C" __attribute__((weak)) void raise()
|
||||
|
||||
extern "C" void abort(void)
|
||||
{
|
||||
Genode::Thread const * const myself = Genode::Thread::myself();
|
||||
Genode::Thread::Name name = "unknown";
|
||||
|
||||
if (myself)
|
||||
name = myself->name();
|
||||
|
||||
Genode::warning("abort called - thread: ", name.string());
|
||||
Genode::warning("abort called - thread: ", Genode::Thread::myself()->name);
|
||||
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
@ -81,7 +81,10 @@ extern "C" void init_main_thread()
|
||||
* The new stack pointer enables the caller to switch from its current
|
||||
* environment to the those that the thread object provides.
|
||||
*/
|
||||
addr_t const sp = reinterpret_cast<addr_t>(main_thread.stack_top());
|
||||
addr_t const sp = main_thread.info().convert<addr_t>(
|
||||
[&] (Thread::Stack_info info) { return info.top; },
|
||||
[&] (Thread::Stack_error) { return 0UL; });
|
||||
|
||||
init_main_thread_result = sp;
|
||||
|
||||
/*
|
||||
|
@ -59,7 +59,12 @@ class Helper : Thread
|
||||
|
||||
Helper(Env &env) : Thread(env, "helper", STACK_SIZE), _env(env) { }
|
||||
|
||||
void *stack() const { return _stack; }
|
||||
void *stack() const
|
||||
{
|
||||
return info().convert<void *>(
|
||||
[&] (Stack_info info) { return (void *)info.top; },
|
||||
[&] (Stack_error) { return nullptr; });
|
||||
}
|
||||
|
||||
void entry() override
|
||||
{
|
||||
@ -169,16 +174,16 @@ static void test_main_thread()
|
||||
addr_t const stack_slot_size = Thread::stack_area_virtual_size();
|
||||
addr_t const stack_slot_top = stack_slot_base + stack_slot_size;
|
||||
|
||||
addr_t const stack_top = (addr_t)myself->stack_top();
|
||||
addr_t const stack_base = (addr_t)myself->stack_base();
|
||||
addr_t const stack_top = Thread::mystack().top;
|
||||
addr_t const stack_base = Thread::mystack().base;
|
||||
|
||||
if (stack_top <= stack_slot_base) { throw -2; }
|
||||
if (stack_top > stack_slot_top) { throw -3; }
|
||||
if (stack_base >= stack_slot_top) { throw -4; }
|
||||
if (stack_base < stack_slot_base) { throw -5; }
|
||||
|
||||
log("thread stack top ", myself->stack_top());
|
||||
log("thread stack bottom ", myself->stack_base());
|
||||
log("thread stack top ", (void *)stack_top);
|
||||
log("thread stack bottom ", (void *)stack_base);
|
||||
|
||||
/* check wether my stack pointer is inside my stack */
|
||||
unsigned dummy = 0;
|
||||
@ -205,8 +210,7 @@ struct Cpu_helper : Thread
|
||||
|
||||
void entry() override
|
||||
{
|
||||
log(Thread::name().string(), " : _cpu_session=", _cpu_session,
|
||||
" env.cpu()=", &_env.cpu());
|
||||
log(Thread::name, " : _cpu_session=", _cpu_session, " env.cpu()=", &_env.cpu());
|
||||
}
|
||||
};
|
||||
|
||||
@ -317,14 +321,17 @@ static void test_create_as_many_threads(Env &env)
|
||||
for (; i < max; i++) {
|
||||
try {
|
||||
threads[i] = new (heap) Cpu_helper(env, Thread::Name(i + 1), env.cpu());
|
||||
|
||||
if (threads[i]->info() == Thread::Stack_error::STACK_AREA_EXHAUSTED) {
|
||||
out_of_stack_space = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (threads[i]->start() == Thread::Start_result::DENIED) {
|
||||
denied = true;
|
||||
break;
|
||||
}
|
||||
threads[i]->join();
|
||||
} catch (Thread::Out_of_stack_space) {
|
||||
out_of_stack_space = true;
|
||||
break;
|
||||
} catch (Genode::Native_capability::Reference_count_overflow) {
|
||||
warning("Native_capability::Reference_count_overflow");
|
||||
denied = true;
|
||||
@ -371,7 +378,7 @@ struct Lock_helper : Thread
|
||||
|
||||
void entry() override
|
||||
{
|
||||
log(" thread '", name(), "' started");
|
||||
log(" thread '", name, "' started");
|
||||
|
||||
if (unlock)
|
||||
lock.wakeup();
|
||||
@ -379,12 +386,12 @@ struct Lock_helper : Thread
|
||||
lock.block();
|
||||
|
||||
if (!lock_is_free) {
|
||||
log(" thread '", name(), "' got lock but somebody else is within"
|
||||
log(" thread '", name, "' got lock but somebody else is within"
|
||||
" critical section !?");
|
||||
throw -22;
|
||||
}
|
||||
|
||||
log(" thread '", name(), "' done");
|
||||
log(" thread '", name, "' done");
|
||||
|
||||
lock.wakeup();
|
||||
}
|
||||
@ -413,7 +420,7 @@ static void test_locks(Genode::Env &env)
|
||||
|
||||
lock.block();
|
||||
|
||||
log(" thread '", Thread::myself()->name(), "' - I'm the lock holder - "
|
||||
log(" thread '", Thread::myself()->name, "' - I'm the lock holder - "
|
||||
"take lock again");
|
||||
|
||||
/* we are within the critical section - lock is not free */
|
||||
@ -467,7 +474,7 @@ struct Cxa_helper : Thread
|
||||
|
||||
void entry() override
|
||||
{
|
||||
log(" thread '", name(), "' started");
|
||||
log(" thread '", name, "' started");
|
||||
|
||||
if (sync)
|
||||
sync_startup.wakeup();
|
||||
@ -482,20 +489,20 @@ struct Cxa_helper : Thread
|
||||
};
|
||||
|
||||
if (test == 1)
|
||||
static Contention contention (name(), in_cxa, sync_startup);
|
||||
static Contention contention (name, in_cxa, sync_startup);
|
||||
else
|
||||
if (test == 2)
|
||||
static Contention contention (name(), in_cxa, sync_startup);
|
||||
static Contention contention (name, in_cxa, sync_startup);
|
||||
else
|
||||
if (test == 3)
|
||||
static Contention contention (name(), in_cxa, sync_startup);
|
||||
static Contention contention (name, in_cxa, sync_startup);
|
||||
else
|
||||
if (test == 4)
|
||||
static Contention contention (name(), in_cxa, sync_startup);
|
||||
static Contention contention (name, in_cxa, sync_startup);
|
||||
else
|
||||
throw -25;
|
||||
|
||||
log(" thread '", name(), "' done");
|
||||
log(" thread '", name, "' done");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -59,7 +59,12 @@ bool Bsd::Task::run()
|
||||
_state = STATE_RUNNING;
|
||||
Genode::Thread *th = Genode::Thread::myself();
|
||||
|
||||
_stack = th->alloc_secondary_stack(_name, _stack_size);
|
||||
_stack = th->alloc_secondary_stack(_name, _stack_size).convert<void *>(
|
||||
[&] (void *sp) { return sp; },
|
||||
[&] (Genode::Thread::Stack_error) {
|
||||
Genode::error("failed to allocate secondary stack");
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
/* switch stack and call '_func(_arg)' */
|
||||
platform_execute(_stack, (void *)_func, _arg);
|
||||
|
@ -107,7 +107,7 @@ void Scheduler::execute()
|
||||
auto const thread = Genode::Thread::myself();
|
||||
if (!_ep.rpc_ep().myself(addr_t(&thread))) {
|
||||
Genode::error("Lx_kit::Scheduler called by invalid thread/stack ",
|
||||
thread->name(), " ",
|
||||
thread->name, " ",
|
||||
Genode::Hex(thread->mystack().base), "-",
|
||||
Genode::Hex(thread->mystack().top));
|
||||
Genode::backtrace();
|
||||
|
@ -36,16 +36,19 @@ bool Task::runnable() const
|
||||
|
||||
static inline void * _alloc_stack(const char * name)
|
||||
{
|
||||
enum { STACK_SIZE = 32 * 1024 };
|
||||
Genode::Thread * th = Genode::Thread::myself();
|
||||
return th->alloc_secondary_stack(name, STACK_SIZE);
|
||||
size_t const stack_size { 32*1024 };
|
||||
return Thread::myself()->alloc_secondary_stack(name, stack_size).convert<void *>(
|
||||
[&] (void *sp) { return sp; },
|
||||
[&] (Thread::Stack_error) {
|
||||
error("lx_kit failed to allocate secondary stack");
|
||||
return nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static inline void _free_stack(void *addr)
|
||||
{
|
||||
Genode::Thread * th = Genode::Thread::myself();
|
||||
th->free_secondary_stack(addr);
|
||||
Thread::myself()->free_secondary_stack(addr);
|
||||
}
|
||||
|
||||
|
||||
|
@ -227,8 +227,10 @@ struct Libc::Kernel final : Vfs::Read_ready_response_handler,
|
||||
|
||||
addr_t _kernel_stack = Thread::mystack().top;
|
||||
|
||||
void *_user_stack = _myself.alloc_secondary_stack(_myself.name().string(),
|
||||
_config.stack_size);
|
||||
void *_user_stack =
|
||||
_myself.alloc_secondary_stack(_myself.name, _config.stack_size)
|
||||
.convert<void *>([&] (void *sp) { return sp; },
|
||||
[&] (Thread::Stack_error) { return nullptr; });
|
||||
|
||||
enum State { KERNEL, USER };
|
||||
|
||||
|
@ -96,7 +96,9 @@ struct Libc::Signal : Noncopyable
|
||||
if (!signal_stack) {
|
||||
auto myself = Thread::myself();
|
||||
if (myself)
|
||||
_signal_stack_default = { myself->alloc_secondary_stack("signal", 16 * 1024) };
|
||||
myself->alloc_secondary_stack("signal", 16 * 1024).with_result(
|
||||
[&] (void *sp) { _signal_stack_default = sp; },
|
||||
[&] (Thread::Stack_error) { });
|
||||
|
||||
signal_stack = _signal_stack_default;
|
||||
}
|
||||
|
@ -741,7 +741,7 @@ extern "C" {
|
||||
*/
|
||||
if (!_pthread_main_np()) {
|
||||
error("pthread_self() called from alien thread named ",
|
||||
"'", Thread::myself()->name().string(), "'");
|
||||
"'", Thread::myself()->name, "'");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -251,10 +251,11 @@ extern "C" int sigaltstack(stack_t const * const ss, stack_t * const old_ss)
|
||||
|
||||
} else {
|
||||
/* ss->ss_sp is ignored, ever use alloc_secondary stack */
|
||||
void * stack = myself->alloc_secondary_stack("sigaltstack",
|
||||
ss->ss_size);
|
||||
|
||||
signal.use_alternative_stack(stack);
|
||||
myself->alloc_secondary_stack("sigaltstack", ss->ss_size).with_result(
|
||||
[&] (void *sp) {
|
||||
signal.use_alternative_stack(sp); },
|
||||
[&] (Thread::Stack_error) {
|
||||
error("failed to allocate sigaltstack"); });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ static int sys_thr_self()
|
||||
|
||||
addr_t const base = Genode::Thread::stack_area_virtual_base();
|
||||
addr_t const size = Genode::Thread::stack_virtual_size();
|
||||
addr_t const stack = (addr_t)Genode::Thread::myself()->stack_base();
|
||||
addr_t const stack = Genode::Thread::mystack().base;
|
||||
|
||||
return int((stack - base) / size + 1);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ struct Genode::Backtrace
|
||||
{
|
||||
using Genode::print;
|
||||
|
||||
print(out, "backtrace \"", Thread::myself()->name(), "\"");
|
||||
print(out, "backtrace \"", Thread::myself()->name, "\"");
|
||||
|
||||
struct Addr : Hex { Addr(void *v) : Hex((addr_t)v, OMIT_PREFIX) { } };
|
||||
|
||||
|
@ -324,13 +324,13 @@ void Vmm::Vm::_handle_timer()
|
||||
}
|
||||
|
||||
if (_vcpu1.halted()) {
|
||||
log(Thread::myself()->name(), " : request pause of vcpu ", _vcpu1.id());
|
||||
log(Thread::myself()->name, " : request pause of vcpu ", _vcpu1.id());
|
||||
/* test to trigger a Genode signal even if we're already blocked */
|
||||
_vcpu1.request_intercept();
|
||||
}
|
||||
|
||||
if (_vcpu1.paused_1st()) {
|
||||
log(Thread::myself()->name(), " : request resume (A) of vcpu ", _vcpu1.id());
|
||||
log(Thread::myself()->name, " : request resume (A) of vcpu ", _vcpu1.id());
|
||||
|
||||
_vcpu1.with_state([this](Vcpu_state & state) {
|
||||
state.discharge();
|
||||
@ -340,7 +340,7 @@ void Vmm::Vm::_handle_timer()
|
||||
return true;
|
||||
});
|
||||
} else if (_vcpu1.paused_2nd()) {
|
||||
log(Thread::myself()->name(), " : request resume (B) of vcpu ", _vcpu1.id());
|
||||
log(Thread::myself()->name, " : request resume (B) of vcpu ", _vcpu1.id());
|
||||
|
||||
_vcpu1.with_state([this](Vcpu_state & state) {
|
||||
state.discharge();
|
||||
@ -357,7 +357,7 @@ void Vmm::Vm::_handle_timer()
|
||||
/* request on the next timeout to stop the jmp endless loop */
|
||||
_vcpu1.break_endless_loop();
|
||||
} else if (_vcpu1.paused_3rd()) {
|
||||
log(Thread::myself()->name(), " : request resume (C) of vcpu ", _vcpu1.id());
|
||||
log(Thread::myself()->name, " : request resume (C) of vcpu ", _vcpu1.id());
|
||||
|
||||
_vcpu1.with_state([this](Vcpu_state & state) {
|
||||
state.discharge();
|
||||
@ -398,7 +398,7 @@ void Vmm::Vcpu::_handle_vcpu_exit()
|
||||
|
||||
log("vcpu ", _id, " : ", _exit_count, ". vm exit - ",
|
||||
"reason ", Hex((unsigned)exit), " handled by '",
|
||||
Thread::myself()->name(), "'");
|
||||
Thread::myself()->name, "'");
|
||||
|
||||
switch (exit) {
|
||||
|
||||
@ -422,11 +422,11 @@ void Vmm::Vcpu::_handle_vcpu_exit()
|
||||
/* FIXME handle remote resume */
|
||||
if (id() == 2) {
|
||||
if (paused_1st()) {
|
||||
log(Thread::myself()->name(), " : request resume of vcpu ", id());
|
||||
log(Thread::myself()->name, " : request resume of vcpu ", id());
|
||||
return true;
|
||||
}
|
||||
if (paused_2nd()) {
|
||||
log(Thread::myself()->name(), " : request resume of vcpu ", id());
|
||||
log(Thread::myself()->name, " : request resume of vcpu ", id());
|
||||
|
||||
/* skip over next hlt instructions after second paused state */
|
||||
skip_instruction(state, 1*1 /* 1x hlt instruction size */);
|
||||
|
@ -96,8 +96,11 @@ class Pthread::Entrypoint : public Pthread::Emt
|
||||
{
|
||||
Genode::Thread &myself = *Genode::Thread::myself();
|
||||
|
||||
_emt_stack = myself.alloc_secondary_stack(myself.name().string(),
|
||||
_stack_size);
|
||||
_emt_stack = myself.alloc_secondary_stack(myself.name, _stack_size).convert<void *>(
|
||||
[&] (void *sp) { return sp; },
|
||||
[&] (Genode::Thread::Stack_error) {
|
||||
Genode::error("failed to allocate secondary stack for EMT");
|
||||
return nullptr; });
|
||||
|
||||
Libc::pthread_create_from_thread(&_emt_pthread, myself, _emt_stack);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user