mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 23:42:32 +00:00
hw: simplify Kernel::start_thread
Instead of writing initial thread context to the platform-thread members and then communicating this core object to kernel, core calls Kernel::access_thread_regs first to initialize thread context and then Kernel::start_thread without a platform-thread pointer. This way the frontend as well as the backend of Kernel::start_thread loose complexity and it is a first step to remove platform thread from the vocabulary of the kernel. ref #953
This commit is contained in:
parent
77f55232fd
commit
210216e5e1
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
namespace Genode
|
namespace Genode
|
||||||
{
|
{
|
||||||
|
class Native_utcb;
|
||||||
class Platform_thread;
|
class Platform_thread;
|
||||||
class Platform_pd;
|
class Platform_pd;
|
||||||
class Tlb;
|
class Tlb;
|
||||||
@ -31,6 +32,7 @@ namespace Kernel
|
|||||||
typedef Genode::size_t size_t;
|
typedef Genode::size_t size_t;
|
||||||
typedef Genode::Platform_thread Platform_thread;
|
typedef Genode::Platform_thread Platform_thread;
|
||||||
typedef Genode::Platform_pd Platform_pd;
|
typedef Genode::Platform_pd Platform_pd;
|
||||||
|
typedef Genode::Native_utcb Native_utcb;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kernel names of all kernel calls
|
* Kernel names of all kernel calls
|
||||||
@ -232,23 +234,20 @@ namespace Kernel
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start thread with a given context and let it participate in CPU scheduling
|
* Start executing a thread
|
||||||
*
|
*
|
||||||
* \param id ID of targeted thread
|
* \param thread_id kernel name of targeted thread
|
||||||
* \param ip initial instruction pointer
|
* \param cpu_id kernel name of targeted processor
|
||||||
* \param sp initial stack pointer
|
* \param pd_id kernel name of targeted protection domain
|
||||||
*
|
* \param utcb core local pointer to userland thread-context
|
||||||
* \retval >0 success, return value is the TLB of the thread
|
|
||||||
* \retval 0 the targeted thread wasn't started or was already started
|
|
||||||
* when this gets called (in both cases it remains untouched)
|
|
||||||
*
|
*
|
||||||
* Restricted to core threads.
|
* Restricted to core threads.
|
||||||
*/
|
*/
|
||||||
inline Tlb * start_thread(Platform_thread * const phys_pt, void * const ip,
|
inline Tlb * start_thread(unsigned const thread_id, unsigned const cpu_id,
|
||||||
void * const sp, unsigned const cpu_no)
|
unsigned const pd_id, Native_utcb * const utcb)
|
||||||
{
|
{
|
||||||
return (Tlb *)call(Call_id::START_THREAD, (Call_arg)phys_pt,
|
return (Tlb *)call(Call_id::START_THREAD, thread_id, cpu_id, pd_id,
|
||||||
(Call_arg)ip, (Call_arg)sp, cpu_no);
|
(Call_arg)utcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -517,61 +517,17 @@ namespace Arm
|
|||||||
unsigned user_arg_7() const { return r7; }
|
unsigned user_arg_7() const { return r7; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Part of context init that is common for all types of threads
|
* Initialize thread context
|
||||||
|
*
|
||||||
|
* \param tlb physical base of appropriate page table
|
||||||
|
* \param pd_id kernel name of appropriate protection domain
|
||||||
*/
|
*/
|
||||||
void init_thread_common(void * const instr_p,
|
void init_thread(addr_t const tlb, unsigned const pd_id)
|
||||||
addr_t const tlb,
|
|
||||||
unsigned const pd_id)
|
|
||||||
{
|
{
|
||||||
ip = (addr_t)instr_p;
|
|
||||||
cidr = pd_id;
|
cidr = pd_id;
|
||||||
section_table = tlb;
|
section_table = tlb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Init context of the first thread of core
|
|
||||||
*/
|
|
||||||
void init_core_main_thread(void * const instr_p,
|
|
||||||
void * const stack_p,
|
|
||||||
addr_t const tlb,
|
|
||||||
unsigned const pd_id)
|
|
||||||
{
|
|
||||||
sp = (addr_t)stack_p;
|
|
||||||
init_thread_common(instr_p, tlb, pd_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init context of a thread that isn't first thread of a program
|
|
||||||
*/
|
|
||||||
void init_thread(void * const instr_p,
|
|
||||||
void * const stack_p,
|
|
||||||
addr_t const tlb,
|
|
||||||
unsigned const pd_id)
|
|
||||||
{
|
|
||||||
sp = (addr_t)stack_p;
|
|
||||||
init_thread_common(instr_p, tlb, pd_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init context of the first thread of a program other than core
|
|
||||||
*/
|
|
||||||
void init_main_thread(void * const instr_p,
|
|
||||||
void * const utcb_virt,
|
|
||||||
addr_t const tlb,
|
|
||||||
unsigned const pd_id)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Normally threads receive their UTCB pointer through their
|
|
||||||
* 'Thread_base' but the first thread of a program doesn't
|
|
||||||
* have such object. Thus the kernel hands out the UTCB pointer
|
|
||||||
* through the main threads initial CPU context. 'crt0.s' then
|
|
||||||
* can save the received pointer to local mem before polluting
|
|
||||||
* the CPU context.
|
|
||||||
*/
|
|
||||||
sp = (addr_t)utcb_virt;
|
|
||||||
init_thread_common(instr_p, tlb, pd_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return if the context is in a page fault due to a translation miss
|
* Return if the context is in a page fault due to a translation miss
|
||||||
*
|
*
|
||||||
|
@ -48,8 +48,8 @@ namespace Genode {
|
|||||||
Weak_ptr<Address_space> _address_space;
|
Weak_ptr<Address_space> _address_space;
|
||||||
unsigned _id;
|
unsigned _id;
|
||||||
Rm_client * _rm_client;
|
Rm_client * _rm_client;
|
||||||
Native_utcb * _phys_utcb;
|
Native_utcb * _utcb_phys;
|
||||||
Native_utcb * _virt_utcb;
|
Native_utcb * _utcb_virt;
|
||||||
Tlb * _tlb;
|
Tlb * _tlb;
|
||||||
Ram_dataspace_capability _utcb;
|
Ram_dataspace_capability _utcb;
|
||||||
char _name[NAME_MAX_LEN];
|
char _name[NAME_MAX_LEN];
|
||||||
@ -109,8 +109,12 @@ namespace Genode {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Run this thread
|
* Run this thread
|
||||||
|
*
|
||||||
|
* \param ip initial instruction pointer
|
||||||
|
* \param sp initial stack pointer
|
||||||
|
* \param cpu_id kernel name of targeted CPU
|
||||||
*/
|
*/
|
||||||
int start(void * ip, void * sp, unsigned int cpu_no = 0);
|
int start(void * const ip, void * const sp, unsigned const cpu_id = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pause this thread
|
* Pause this thread
|
||||||
@ -182,9 +186,9 @@ namespace Genode {
|
|||||||
return _thread_base;
|
return _thread_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
Native_utcb * phys_utcb() const { return _phys_utcb; }
|
Native_utcb * utcb_phys() const { return _utcb_phys; }
|
||||||
|
|
||||||
Native_utcb * virt_utcb() const { return _virt_utcb; }
|
Native_utcb * utcb_virt() const { return _utcb_virt; }
|
||||||
|
|
||||||
Ram_dataspace_capability utcb() const { return _utcb; }
|
Ram_dataspace_capability utcb() const { return _utcb; }
|
||||||
|
|
||||||
|
@ -119,9 +119,9 @@ namespace Kernel
|
|||||||
static bool init = 0;
|
static bool init = 0;
|
||||||
if (!init) {
|
if (!init) {
|
||||||
enum { STACK_SIZE = sizeof(idle_stack)/sizeof(idle_stack[0]) };
|
enum { STACK_SIZE = sizeof(idle_stack)/sizeof(idle_stack[0]) };
|
||||||
void * const ip = (void *)&idle_main;
|
idle.ip = (addr_t)&idle_main;;
|
||||||
void * const sp = (void *)&idle_stack[STACK_SIZE];
|
idle.sp = (addr_t)&idle_stack[STACK_SIZE];;
|
||||||
idle.init(ip, sp, 0, core_id(), 0, 0, 0, 0);
|
idle.init(0, core_id(), 0, 0);
|
||||||
init = 1;
|
init = 1;
|
||||||
}
|
}
|
||||||
/* create CPU scheduler with a permanent idle thread */
|
/* create CPU scheduler with a permanent idle thread */
|
||||||
@ -231,12 +231,12 @@ extern "C" void kernel()
|
|||||||
*(Core_thread_id *)s = 0;
|
*(Core_thread_id *)s = 0;
|
||||||
|
|
||||||
/* start thread with stack pointer at the top of stack */
|
/* start thread with stack pointer at the top of stack */
|
||||||
void * const sp = (void *)((addr_t)s + STACK_SIZE);
|
|
||||||
void * const ip = (void *)CORE_MAIN;
|
|
||||||
static Native_utcb utcb;
|
static Native_utcb utcb;
|
||||||
_main_utcb = &utcb;
|
_main_utcb = &utcb;
|
||||||
static Thread t((Platform_thread *)0);
|
static Thread t((Platform_thread *)0);
|
||||||
t.init(ip, sp, 0, core_id(), &utcb, &utcb, 1, 1);
|
t.ip = (addr_t)CORE_MAIN;;
|
||||||
|
t.sp = (addr_t)s + STACK_SIZE;
|
||||||
|
t.init(0, core_id(), &utcb, 1);
|
||||||
}
|
}
|
||||||
/* kernel initialization finished */
|
/* kernel initialization finished */
|
||||||
init_platform();
|
init_platform();
|
||||||
|
@ -75,8 +75,8 @@ void Thread::_await_signal(Signal_receiver * const receiver)
|
|||||||
|
|
||||||
void Thread::_receive_signal(void * const base, size_t const size)
|
void Thread::_receive_signal(void * const base, size_t const size)
|
||||||
{
|
{
|
||||||
assert(_state == AWAITS_SIGNAL && size <= _phys_utcb->size());
|
assert(_state == AWAITS_SIGNAL && size <= _utcb_phys->size());
|
||||||
Genode::memcpy(_phys_utcb->base(), base, size);
|
Genode::memcpy(_utcb_phys->base(), base, size);
|
||||||
_schedule();
|
_schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,17 +191,14 @@ Thread::Thread(Platform_thread * const pt)
|
|||||||
_platform_thread(pt),
|
_platform_thread(pt),
|
||||||
_state(AWAITS_START),
|
_state(AWAITS_START),
|
||||||
_pd(0),
|
_pd(0),
|
||||||
_phys_utcb(0),
|
_utcb_phys(0),
|
||||||
_virt_utcb(0),
|
|
||||||
_signal_receiver(0)
|
_signal_receiver(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Thread::init(void * const ip, void * const sp, unsigned const cpu_id,
|
Thread::init(unsigned const cpu_id, unsigned const pd_id_arg,
|
||||||
unsigned const pd_id_arg, Native_utcb * const utcb_phys,
|
Native_utcb * const utcb_phys, bool const start)
|
||||||
Native_utcb * const utcb_virt, bool const main,
|
|
||||||
bool const start)
|
|
||||||
{
|
{
|
||||||
assert(_state == AWAITS_START)
|
assert(_state == AWAITS_START)
|
||||||
|
|
||||||
@ -209,19 +206,13 @@ Thread::init(void * const ip, void * const sp, unsigned const cpu_id,
|
|||||||
if (cpu_id) { PERR("multicore processing not supported"); }
|
if (cpu_id) { PERR("multicore processing not supported"); }
|
||||||
|
|
||||||
/* store thread parameters */
|
/* store thread parameters */
|
||||||
_phys_utcb = utcb_phys;
|
_utcb_phys = utcb_phys;
|
||||||
_virt_utcb = utcb_virt;
|
|
||||||
|
|
||||||
/* join protection domain */
|
/* join protection domain */
|
||||||
_pd = Pd::pool()->object(pd_id_arg);
|
_pd = Pd::pool()->object(pd_id_arg);
|
||||||
assert(_pd);
|
assert(_pd);
|
||||||
addr_t const tlb = _pd->tlb()->base();
|
addr_t const tlb = _pd->tlb()->base();
|
||||||
|
User_context::init_thread(tlb, pd_id());
|
||||||
/* initialize CPU context */
|
|
||||||
User_context * const c = static_cast<User_context *>(this);
|
|
||||||
if (!main) { c->init_thread(ip, sp, tlb, pd_id()); }
|
|
||||||
else if (!_core()) { c->init_main_thread(ip, utcb_virt, tlb, pd_id()); }
|
|
||||||
else { c->init_core_main_thread(ip, sp, tlb, pd_id()); }
|
|
||||||
|
|
||||||
/* print log message */
|
/* print log message */
|
||||||
if (START_VERBOSE) {
|
if (START_VERBOSE) {
|
||||||
@ -282,7 +273,7 @@ void Thread::proceed()
|
|||||||
char const * Kernel::Thread::label() const
|
char const * Kernel::Thread::label() const
|
||||||
{
|
{
|
||||||
if (!platform_thread()) {
|
if (!platform_thread()) {
|
||||||
if (!_phys_utcb) { return "idle"; }
|
if (!_utcb_phys) { return "idle"; }
|
||||||
return "core";
|
return "core";
|
||||||
}
|
}
|
||||||
return platform_thread()->name();
|
return platform_thread()->name();
|
||||||
@ -377,24 +368,26 @@ void Thread::_call_delete_thread()
|
|||||||
void Thread::_call_start_thread()
|
void Thread::_call_start_thread()
|
||||||
{
|
{
|
||||||
/* check permissions */
|
/* check permissions */
|
||||||
assert(_core());
|
if (!_core()) {
|
||||||
|
PERR("not entitled to start thread");
|
||||||
|
user_arg_0(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
/* dispatch arguments */
|
/* dispatch arguments */
|
||||||
Platform_thread * pt = (Platform_thread *)user_arg_1();
|
unsigned const thread_id = user_arg_1();
|
||||||
void * const ip = (void *)user_arg_2();
|
unsigned const cpu_id = user_arg_2();
|
||||||
void * const sp = (void *)user_arg_3();
|
unsigned const pd_id = user_arg_3();
|
||||||
unsigned const cpu_id = (unsigned)user_arg_4();
|
Native_utcb * const utcb = (Native_utcb *)user_arg_4();
|
||||||
|
|
||||||
/* get targeted thread */
|
|
||||||
Thread * const t = Thread::pool()->object(pt->id());
|
|
||||||
assert(t);
|
|
||||||
|
|
||||||
|
/* lookup targeted thread */
|
||||||
|
Thread * const t = Thread::pool()->object(thread_id);
|
||||||
|
if (!t) {
|
||||||
|
PERR("unknown thread");
|
||||||
|
user_arg_0(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
/* start thread */
|
/* start thread */
|
||||||
unsigned const pd_id = pt->pd_id();
|
t->init(cpu_id, pd_id, utcb, 1);
|
||||||
Native_utcb * const utcb_p = pt->phys_utcb();
|
|
||||||
Native_utcb * const utcb_v = pt->virt_utcb();
|
|
||||||
bool const main = pt->main_thread();
|
|
||||||
t->init(ip, sp, cpu_id, pd_id, utcb_p, utcb_v, main, 1);
|
|
||||||
user_arg_0((Call_ret)t->_pd->tlb());
|
user_arg_0((Call_ret)t->_pd->tlb());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,7 +468,7 @@ void Thread::_call_wait_for_request()
|
|||||||
{
|
{
|
||||||
void * buf_base;
|
void * buf_base;
|
||||||
size_t buf_size;
|
size_t buf_size;
|
||||||
_phys_utcb->call_wait_for_request(buf_base, buf_size);
|
_utcb_phys->call_wait_for_request(buf_base, buf_size);
|
||||||
Ipc_node::await_request(buf_base, buf_size);
|
Ipc_node::await_request(buf_base, buf_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,7 +485,7 @@ void Thread::_call_request_and_wait()
|
|||||||
size_t msg_size;
|
size_t msg_size;
|
||||||
void * buf_base;
|
void * buf_base;
|
||||||
size_t buf_size;
|
size_t buf_size;
|
||||||
_phys_utcb->call_request_and_wait(msg_base, msg_size,
|
_utcb_phys->call_request_and_wait(msg_base, msg_size,
|
||||||
buf_base, buf_size);
|
buf_base, buf_size);
|
||||||
Ipc_node::send_request_await_reply(dst, msg_base, msg_size,
|
Ipc_node::send_request_await_reply(dst, msg_base, msg_size,
|
||||||
buf_base, buf_size);
|
buf_base, buf_size);
|
||||||
@ -503,7 +496,7 @@ void Thread::_call_reply()
|
|||||||
{
|
{
|
||||||
void * msg_base;
|
void * msg_base;
|
||||||
size_t msg_size;
|
size_t msg_size;
|
||||||
_phys_utcb->call_reply(msg_base, msg_size);
|
_utcb_phys->call_reply(msg_base, msg_size);
|
||||||
Ipc_node::send_reply(msg_base, msg_size);
|
Ipc_node::send_reply(msg_base, msg_size);
|
||||||
bool const await_request = user_arg_1();
|
bool const await_request = user_arg_1();
|
||||||
if (await_request) { _call_wait_for_request(); }
|
if (await_request) { _call_wait_for_request(); }
|
||||||
@ -590,7 +583,7 @@ void Thread::_call_access_thread_regs()
|
|||||||
/* execute read operations */
|
/* execute read operations */
|
||||||
unsigned const reads = user_arg_2();
|
unsigned const reads = user_arg_2();
|
||||||
unsigned const writes = user_arg_3();
|
unsigned const writes = user_arg_3();
|
||||||
addr_t * const utcb = (addr_t *)_phys_utcb->base();
|
addr_t * const utcb = (addr_t *)_utcb_phys->base();
|
||||||
addr_t * const read_ids = &utcb[0];
|
addr_t * const read_ids = &utcb[0];
|
||||||
addr_t * const read_values = (addr_t *)user_arg_4();
|
addr_t * const read_values = (addr_t *)user_arg_4();
|
||||||
for (unsigned i = 0; i < reads; i++) {
|
for (unsigned i = 0; i < reads; i++) {
|
||||||
|
@ -81,8 +81,7 @@ class Kernel::Thread
|
|||||||
Platform_thread * const _platform_thread;
|
Platform_thread * const _platform_thread;
|
||||||
State _state;
|
State _state;
|
||||||
Pd * _pd;
|
Pd * _pd;
|
||||||
Native_utcb * _phys_utcb;
|
Native_utcb * _utcb_phys;
|
||||||
Native_utcb * _virt_utcb;
|
|
||||||
Signal_receiver * _signal_receiver;
|
Signal_receiver * _signal_receiver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -263,19 +262,13 @@ class Kernel::Thread
|
|||||||
/**
|
/**
|
||||||
* Prepare thread to get scheduled the first time
|
* Prepare thread to get scheduled the first time
|
||||||
*
|
*
|
||||||
* \param ip initial instruction pointer
|
* \param cpu_id kernel name of targeted processor
|
||||||
* \param sp initial stack pointer
|
* \param pd_id kernel name of target protection domain
|
||||||
* \param cpu_id target cpu
|
* \param utcb core local pointer to userland thread-context
|
||||||
* \param pd_id target protection-domain
|
* \param start wether to start executing the thread
|
||||||
* \param utcb_phys physical UTCB pointer
|
|
||||||
* \param utcb_virt virtual UTCB pointer
|
|
||||||
* \param main wether the thread is the first one in its PD
|
|
||||||
* \param start wether to start execution
|
|
||||||
*/
|
*/
|
||||||
void init(void * const ip, void * const sp, unsigned const cpu_id,
|
void init(unsigned const cpu_id, unsigned const pd_id,
|
||||||
unsigned const pd_id, Native_utcb * const utcb_phys,
|
Native_utcb * const utcb, bool const start);
|
||||||
Native_utcb * const utcb_virt, bool const main,
|
|
||||||
bool const start);
|
|
||||||
|
|
||||||
|
|
||||||
/***********************
|
/***********************
|
||||||
|
@ -46,13 +46,13 @@ Platform_thread::~Platform_thread()
|
|||||||
/* the RM client may be destructed before platform thread */
|
/* the RM client may be destructed before platform thread */
|
||||||
if (_rm_client) {
|
if (_rm_client) {
|
||||||
Rm_session_component * const rm = _rm_client->member_rm_session();
|
Rm_session_component * const rm = _rm_client->member_rm_session();
|
||||||
rm->detach(_virt_utcb);
|
rm->detach(utcb_virt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* free UTCB */
|
/* free UTCB */
|
||||||
if (_pd_id == Kernel::core_id()) {
|
if (_pd_id == Kernel::core_id()) {
|
||||||
Range_allocator * const ram = platform()->ram_alloc();
|
Range_allocator * const ram = platform()->ram_alloc();
|
||||||
ram->free((void *)_phys_utcb, sizeof(Native_utcb));
|
ram->free(utcb_phys(), sizeof(Native_utcb));
|
||||||
} else {
|
} else {
|
||||||
Ram_session_component * const ram =
|
Ram_session_component * const ram =
|
||||||
dynamic_cast<Ram_session_component *>(core_env()->ram_session());
|
dynamic_cast<Ram_session_component *>(core_env()->ram_session());
|
||||||
@ -77,7 +77,7 @@ Platform_thread::Platform_thread(const char * name,
|
|||||||
size_t const stack_size, unsigned const pd_id)
|
size_t const stack_size, unsigned const pd_id)
|
||||||
:
|
:
|
||||||
_thread_base(thread_base), _stack_size(stack_size),
|
_thread_base(thread_base), _stack_size(stack_size),
|
||||||
_pd_id(pd_id), _rm_client(0), _virt_utcb(0),
|
_pd_id(pd_id), _rm_client(0), _utcb_virt(0),
|
||||||
_priority(Kernel::Priority::MAX),
|
_priority(Kernel::Priority::MAX),
|
||||||
_main_thread(0)
|
_main_thread(0)
|
||||||
{
|
{
|
||||||
@ -85,13 +85,13 @@ Platform_thread::Platform_thread(const char * name,
|
|||||||
|
|
||||||
/* create UTCB for a core thread */
|
/* create UTCB for a core thread */
|
||||||
Range_allocator * const ram = platform()->ram_alloc();
|
Range_allocator * const ram = platform()->ram_alloc();
|
||||||
if (!ram->alloc_aligned(sizeof(Native_utcb), (void **)&_phys_utcb,
|
if (!ram->alloc_aligned(sizeof(Native_utcb), (void **)&_utcb_phys,
|
||||||
MIN_MAPPING_SIZE_LOG2).is_ok())
|
MIN_MAPPING_SIZE_LOG2).is_ok())
|
||||||
{
|
{
|
||||||
PERR("failed to allocate UTCB");
|
PERR("failed to allocate UTCB");
|
||||||
throw Cpu_session::Out_of_metadata();
|
throw Cpu_session::Out_of_metadata();
|
||||||
}
|
}
|
||||||
_virt_utcb = _phys_utcb;
|
_utcb_virt = _utcb_phys;
|
||||||
|
|
||||||
/* common constructor parts */
|
/* common constructor parts */
|
||||||
_init();
|
_init();
|
||||||
@ -102,7 +102,7 @@ Platform_thread::Platform_thread(const char * name, unsigned int priority,
|
|||||||
addr_t utcb)
|
addr_t utcb)
|
||||||
:
|
:
|
||||||
_thread_base(0), _stack_size(0), _pd_id(0), _rm_client(0),
|
_thread_base(0), _stack_size(0), _pd_id(0), _rm_client(0),
|
||||||
_virt_utcb((Native_utcb *)utcb),
|
_utcb_virt((Native_utcb *)utcb),
|
||||||
_priority(Cpu_session::scale_priority(Kernel::Priority::MAX, priority)),
|
_priority(Cpu_session::scale_priority(Kernel::Priority::MAX, priority)),
|
||||||
_main_thread(0)
|
_main_thread(0)
|
||||||
{
|
{
|
||||||
@ -121,7 +121,7 @@ Platform_thread::Platform_thread(const char * name, unsigned int priority,
|
|||||||
PERR("failed to allocate UTCB");
|
PERR("failed to allocate UTCB");
|
||||||
throw Cpu_session::Out_of_metadata();
|
throw Cpu_session::Out_of_metadata();
|
||||||
}
|
}
|
||||||
_phys_utcb = (Native_utcb *)ram->phys_addr(_utcb);
|
_utcb_phys = (Native_utcb *)ram->phys_addr(_utcb);
|
||||||
|
|
||||||
/* common constructor parts */
|
/* common constructor parts */
|
||||||
_init();
|
_init();
|
||||||
@ -155,21 +155,14 @@ void Platform_thread::_init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Platform_thread::start(void * ip, void * sp, unsigned int cpu_no)
|
int Platform_thread::start(void * const ip, void * const sp,
|
||||||
|
unsigned int const cpu_id)
|
||||||
{
|
{
|
||||||
/* must be in a PD to get started */
|
|
||||||
if (!_pd_id) {
|
|
||||||
PERR("invalid PD");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* attach UTCB if the thread can't do this by itself */
|
/* attach UTCB if the thread can't do this by itself */
|
||||||
if (!_attaches_utcb_by_itself())
|
if (!_attaches_utcb_by_itself())
|
||||||
{
|
{
|
||||||
/*
|
/* declare page aligned virtual UTCB outside the context area */
|
||||||
* Declare page aligned virtual UTCB outside the context area.
|
_utcb_virt = (Native_utcb *)((platform()->vm_start()
|
||||||
* Kernel afterwards offers this as bootstrap argument to the thread.
|
|
||||||
*/
|
|
||||||
_virt_utcb = (Native_utcb *)((platform()->vm_start()
|
|
||||||
+ platform()->vm_size() - sizeof(Native_utcb))
|
+ platform()->vm_size() - sizeof(Native_utcb))
|
||||||
& ~((1<<MIN_MAPPING_SIZE_LOG2)-1));
|
& ~((1<<MIN_MAPPING_SIZE_LOG2)-1));
|
||||||
|
|
||||||
@ -179,14 +172,28 @@ int Platform_thread::start(void * ip, void * sp, unsigned int cpu_no)
|
|||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
Rm_session_component * const rm = _rm_client->member_rm_session();
|
Rm_session_component * const rm = _rm_client->member_rm_session();
|
||||||
try { rm->attach(_utcb, 0, 0, true, _virt_utcb, 0); }
|
try { rm->attach(_utcb, 0, 0, true, _utcb_virt, 0); }
|
||||||
catch (...) {
|
catch (...) {
|
||||||
PERR("failed to attach UTCB");
|
PERR("failed to attach UTCB");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* initialize thread regisers */
|
||||||
|
typedef Kernel::Thread_reg_id Reg_id;
|
||||||
|
enum { WRITES = 2 };
|
||||||
|
addr_t * write_regs = (addr_t *)Thread_base::myself()->utcb()->base();
|
||||||
|
write_regs[0] = Reg_id::IP;
|
||||||
|
write_regs[1] = Reg_id::SP;
|
||||||
|
addr_t write_values[] = {
|
||||||
|
(addr_t)ip,
|
||||||
|
main_thread() ? (addr_t)_utcb_virt : (addr_t)sp
|
||||||
|
};
|
||||||
|
if (Kernel::access_thread_regs(id(), 0, WRITES, 0, write_values)) {
|
||||||
|
PERR("failed to initialize thread registers");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
/* let thread participate in CPU scheduling */
|
/* let thread participate in CPU scheduling */
|
||||||
_tlb = Kernel::start_thread(this, ip, sp, cpu_no);
|
_tlb = Kernel::start_thread(id(), cpu_id, _pd_id, utcb_phys());
|
||||||
if (!_tlb) {
|
if (!_tlb) {
|
||||||
PERR("failed to start thread");
|
PERR("failed to start thread");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -33,7 +33,7 @@ Native_utcb * Thread_base::utcb()
|
|||||||
if (!this) { return _main_utcb; }
|
if (!this) { return _main_utcb; }
|
||||||
|
|
||||||
/* this isn't the main thread */
|
/* this isn't the main thread */
|
||||||
return _tid.pt->phys_utcb();
|
return _tid.pt->utcb_phys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user