nova: unify code for normal and server threads
This commit is contained in:
parent
5fe29e8e4a
commit
f1af8e371d
|
@ -206,68 +206,23 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size,
|
||||||
_delay_start(Lock::LOCKED),
|
_delay_start(Lock::LOCKED),
|
||||||
_cap_session(cap_session)
|
_cap_session(cap_session)
|
||||||
{
|
{
|
||||||
/*
|
/* when not running in core set the affinity via cpu 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'.
|
|
||||||
*/
|
|
||||||
if (_tid.ec_sel == Native_thread::INVALID_INDEX) {
|
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))
|
/* place new thread on the specified CPU */
|
||||||
throw Cpu_session::Thread_creation_failed();
|
|
||||||
|
|
||||||
/* place new thread on the specified CPU, if specified */
|
|
||||||
if (location.valid())
|
if (location.valid())
|
||||||
env()->cpu_session()->affinity(_thread_cap, location);
|
env()->cpu_session()->affinity(_thread_cap, location);
|
||||||
|
|
||||||
addr_t thread_sp = (addr_t)&_context->stack[-4];
|
/* magic value evaluated by thread_nova.cc to start a local thread */
|
||||||
|
_tid.ec_sel = Native_thread::INVALID_INDEX - 1;
|
||||||
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();
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
/* tell affinity CPU in 'core' via stack */
|
||||||
/* tell thread starting code to use a specific CPU */
|
|
||||||
reinterpret_cast<Affinity::Location *>(stack_top())[-1] = location;
|
reinterpret_cast<Affinity::Location *>(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 */
|
/* create cleanup portal */
|
||||||
_cap = _cap_session->alloc(Native_capability(_tid.ec_sel),
|
_cap = _cap_session->alloc(Native_capability(_tid.ec_sel),
|
||||||
(addr_t)_activation_entry);
|
(addr_t)_activation_entry);
|
||||||
|
|
|
@ -127,9 +127,15 @@ void Thread_base::_deinit_platform_thread()
|
||||||
|
|
||||||
void Thread_base::start()
|
void Thread_base::start()
|
||||||
{
|
{
|
||||||
if (_tid.ec_sel != ~0UL)
|
if (_tid.ec_sel < Native_thread::INVALID_INDEX - 1)
|
||||||
throw Cpu_session::Thread_creation_failed();
|
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;
|
using namespace Genode;
|
||||||
|
|
||||||
/* create new pager object and assign it to the new thread */
|
/* create new pager object and assign it to the new thread */
|
||||||
|
@ -142,16 +148,19 @@ void Thread_base::start()
|
||||||
|
|
||||||
/* create EC at core */
|
/* create EC at core */
|
||||||
addr_t thread_sp = reinterpret_cast<addr_t>(&_context->stack[-4]);
|
addr_t thread_sp = reinterpret_cast<addr_t>(&_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;
|
Thread_state state;
|
||||||
state.sel_exc_base = _tid.exc_pt_sel;
|
state.sel_exc_base = _tid.exc_pt_sel;
|
||||||
state.is_vcpu = _tid.is_vcpu;
|
state.is_vcpu = _tid.is_vcpu;
|
||||||
|
|
||||||
|
/* local thread have no start instruction pointer - set via portal entry */
|
||||||
|
addr_t thread_ip = global ? reinterpret_cast<addr_t>(_thread_start) : 0;
|
||||||
|
|
||||||
try { env()->cpu_session()->state(_thread_cap, state); }
|
try { env()->cpu_session()->state(_thread_cap, state); }
|
||||||
catch (...) { throw Cpu_session::Thread_creation_failed(); }
|
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();
|
throw Cpu_session::Thread_creation_failed();
|
||||||
|
|
||||||
/* request native EC thread cap */
|
/* request native EC thread cap */
|
||||||
|
@ -178,8 +187,9 @@ void Thread_base::start()
|
||||||
utcb_obj->crd_xlt = Obj_crd();
|
utcb_obj->crd_xlt = Obj_crd();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* request creation of SC to let thread run*/
|
if (global)
|
||||||
env()->cpu_session()->resume(_thread_cap);
|
/* request creation of SC to let thread run*/
|
||||||
|
env()->cpu_session()->resume(_thread_cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue