From f1af8e371da6c75c81eb99c81711b896aa448f74 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Mon, 22 Jul 2013 09:14:40 +0200 Subject: [PATCH] nova: unify code for normal and server threads --- base-nova/src/base/server/server.cc | 61 ++++-------------------- base-nova/src/base/thread/thread_nova.cc | 22 ++++++--- 2 files changed, 24 insertions(+), 59 deletions(-) diff --git a/base-nova/src/base/server/server.cc b/base-nova/src/base/server/server.cc index a4aa0a4b2..327196332 100644 --- a/base-nova/src/base/server/server.cc +++ b/base-nova/src/base/server/server.cc @@ -206,68 +206,23 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, _delay_start(Lock::LOCKED), _cap_session(cap_session) { - /* - * Create thread if we aren't running in core. - * - * For core this code can't be performed since the sessions aren't - * setup in the early bootstrap phase of core. In core the thread - * is created 'manually'. - */ + /* when not running in core set the affinity via cpu session */ if (_tid.ec_sel == Native_thread::INVALID_INDEX) { - /* create new pager object and assign it to the new thread */ - _pager_cap = env()->rm_session()->add_client(_thread_cap); - if (!_pager_cap.valid()) - throw Cpu_session::Thread_creation_failed(); - if (env()->cpu_session()->set_pager(_thread_cap, _pager_cap)) - throw Cpu_session::Thread_creation_failed(); - - /* place new thread on the specified CPU, if specified */ + /* place new thread on the specified CPU */ if (location.valid()) env()->cpu_session()->affinity(_thread_cap, location); - addr_t thread_sp = (addr_t)&_context->stack[-4]; - - Thread_state state; - state.sel_exc_base = _tid.exc_pt_sel; - - try { env()->cpu_session()->state(_thread_cap, state); } - catch(...) { throw Cpu_session::Thread_creation_failed(); } - if (env()->cpu_session()->start(_thread_cap, 0, thread_sp)) - throw Cpu_session::Thread_creation_failed(); - - for (unsigned i = 0; i < Nova::PT_SEL_PARENT; i++) - request_event_portal(_pager_cap, _tid.exc_pt_sel, i); - - request_event_portal(_pager_cap, _tid.exc_pt_sel, - Nova::PT_SEL_STARTUP); - request_event_portal(_pager_cap, _tid.exc_pt_sel, - Nova::SM_SEL_EC); - request_event_portal(_pager_cap, _tid.exc_pt_sel, - Nova::PT_SEL_RECALL); - - /* - * Request native thread cap, _thread_cap only a token. - * The native thread cap is required to attach new rpc objects - * (to create portals bound to the ec) - */ - Genode::Nova_cpu_connection cpu; - Native_capability ec_cap = cpu.native_cap(_thread_cap); - if (!ec_cap.valid()) - throw Cpu_session::Thread_creation_failed(); - _tid.ec_sel = ec_cap.local_name(); - + /* magic value evaluated by thread_nova.cc to start a local thread */ + _tid.ec_sel = Native_thread::INVALID_INDEX - 1; } else { - - /* tell thread starting code to use a specific CPU */ + /* tell affinity CPU in 'core' via stack */ reinterpret_cast(stack_top())[-1] = location; - - /* - * Required for core threads (creates local EC) - */ - Thread_base::start(); } + /* required to create a 'local' EC */ + Thread_base::start(); + /* create cleanup portal */ _cap = _cap_session->alloc(Native_capability(_tid.ec_sel), (addr_t)_activation_entry); diff --git a/base-nova/src/base/thread/thread_nova.cc b/base-nova/src/base/thread/thread_nova.cc index db98dfaea..7f1db2042 100644 --- a/base-nova/src/base/thread/thread_nova.cc +++ b/base-nova/src/base/thread/thread_nova.cc @@ -127,9 +127,15 @@ void Thread_base::_deinit_platform_thread() void Thread_base::start() { - if (_tid.ec_sel != ~0UL) + if (_tid.ec_sel < Native_thread::INVALID_INDEX - 1) throw Cpu_session::Thread_creation_failed(); + /* + * Default: create global thread - ec.sel == INVALID_INDEX + * create local thread - ec.sel == INVALID_INDEX - 1 + */ + bool global = _tid.ec_sel == Native_thread::INVALID_INDEX; + using namespace Genode; /* create new pager object and assign it to the new thread */ @@ -142,16 +148,19 @@ void Thread_base::start() /* create EC at core */ addr_t thread_sp = reinterpret_cast(&_context->stack[-4]); - thread_sp &= ~0xf; /* align initial stack to 16 byte boundary */ + thread_sp &= ~0xfUL; /* align initial stack to 16 byte boundary */ Thread_state state; state.sel_exc_base = _tid.exc_pt_sel; state.is_vcpu = _tid.is_vcpu; + /* local thread have no start instruction pointer - set via portal entry */ + addr_t thread_ip = global ? reinterpret_cast(_thread_start) : 0; + try { env()->cpu_session()->state(_thread_cap, state); } catch (...) { throw Cpu_session::Thread_creation_failed(); } - if (env()->cpu_session()->start(_thread_cap, (addr_t)_thread_start, - thread_sp)) + + if (env()->cpu_session()->start(_thread_cap, thread_ip, thread_sp)) throw Cpu_session::Thread_creation_failed(); /* request native EC thread cap */ @@ -178,8 +187,9 @@ void Thread_base::start() utcb_obj->crd_xlt = Obj_crd(); } - /* request creation of SC to let thread run*/ - env()->cpu_session()->resume(_thread_cap); + if (global) + /* request creation of SC to let thread run*/ + env()->cpu_session()->resume(_thread_cap); }