hw: simplify Kernel::new_thread

Don't set priority and label in platform thread and then communicate this
core object via Kernel::new_thread but communicate priority and label directly.
This way kernel doesn't need to know anymore what a platform thread is.

ref #953
This commit is contained in:
Martin Stein 2013-11-18 15:31:54 +01:00 committed by Norman Feske
parent 210216e5e1
commit 99c649c42f
6 changed files with 99 additions and 107 deletions

View File

@ -20,7 +20,6 @@
namespace Genode namespace Genode
{ {
class Native_utcb; class Native_utcb;
class Platform_thread;
class Platform_pd; class Platform_pd;
class Tlb; class Tlb;
} }
@ -30,7 +29,6 @@ namespace Kernel
typedef Genode::Tlb Tlb; typedef Genode::Tlb Tlb;
typedef Genode::addr_t addr_t; typedef Genode::addr_t addr_t;
typedef Genode::size_t size_t; typedef Genode::size_t size_t;
typedef Genode::Platform_thread Platform_thread;
typedef Genode::Platform_pd Platform_pd; typedef Genode::Platform_pd Platform_pd;
typedef Genode::Native_utcb Native_utcb; typedef Genode::Native_utcb Native_utcb;
@ -200,21 +198,22 @@ namespace Kernel
/** /**
* Create a new thread that is stopped initially * Create kernel object that acts as thread that isn't executed initially
* *
* \param dst physical base of an appropriate portion of memory * \param p memory donation for the new kernel thread object
* that is thereupon allocated to the kernel * \param priority scheduling priority of the new thread
* \param pt assigned platform thread * \param label debugging label of the new thread
* *
* \retval >0 ID of the new thread * \retval >0 kernel name of the new thread
* \retval 0 if no new thread was created * \retval 0 failed
* *
* Restricted to core threads. Regaining of the supplied memory can be done * Restricted to core threads.
* through 'delete_thread'.
*/ */
inline int new_thread(void * const dst, Platform_thread * const pt) inline int new_thread(void * const p, unsigned const priority,
char const * const label)
{ {
return call(Call_id::NEW_THREAD, (Call_arg)dst, (Call_arg)pt); return call((Call_arg)Call_id::NEW_THREAD, (Call_arg)p, (Call_arg)priority,
(Call_arg)label);
} }

View File

@ -40,7 +40,7 @@ namespace Genode {
*/ */
class Platform_thread class Platform_thread
{ {
enum { NAME_MAX_LEN = 32 }; enum { LABEL_MAX_LEN = 32 };
Thread_base * _thread_base; Thread_base * _thread_base;
size_t _stack_size; size_t _stack_size;
@ -52,9 +52,8 @@ namespace Genode {
Native_utcb * _utcb_virt; Native_utcb * _utcb_virt;
Tlb * _tlb; Tlb * _tlb;
Ram_dataspace_capability _utcb; Ram_dataspace_capability _utcb;
char _name[NAME_MAX_LEN]; char _label[LABEL_MAX_LEN];
char _kernel_thread[sizeof(Kernel::Thread)]; char _kernel_thread[sizeof(Kernel::Thread)];
unsigned _priority;
/* /*
* Wether this thread is the main thread of a program. * Wether this thread is the main thread of a program.
@ -80,14 +79,24 @@ namespace Genode {
/** /**
* Constructor for core threads * Constructor for core threads
*
* \param label debugging label
* \param thread_base Genode thread object
* \param stack_size initial size of the stack
* \param pd_id kernel name of targeted protection domain
*/ */
Platform_thread(const char * name, Thread_base * const thread_base, Platform_thread(const char * const label,
Thread_base * const thread_base,
size_t const stack_size, unsigned const pd_id); size_t const stack_size, unsigned const pd_id);
/** /**
* Constructor for threads outside of core * Constructor for threads outside of core
*
* \param label debugging label
* \param priority processor-scheduling priority
* \param utcb core local pointer to userland thread-context
*/ */
Platform_thread(const char * name, unsigned const priority, Platform_thread(const char * const label, unsigned const priority,
addr_t const utcb); addr_t const utcb);
/** /**
@ -96,13 +105,14 @@ namespace Genode {
~Platform_thread(); ~Platform_thread();
/** /**
* Join PD identified by 'pd_id' * Join a protection domain
* *
* \param pd_id ID of targeted PD * \param pd_id kernel name of targeted protection domain
* \param main_thread wether we are the main thread in this PD * \param main_thread wether thread is the first in protection domain
* \param address_space corresponding Genode address space
* *
* \retval 0 on success * \retval 0 succeeded
* \retval <0 otherwise * \retval -1 failed
*/ */
int join_pd(unsigned const pd_id, bool const main_thread, int join_pd(unsigned const pd_id, bool const main_thread,
Weak_ptr<Address_space> address_space); Weak_ptr<Address_space> address_space);
@ -166,8 +176,6 @@ namespace Genode {
** Accessors ** ** Accessors **
***************/ ***************/
inline char const * name() const { return _name; }
void pager(Pager_object * const pager); void pager(Pager_object * const pager);
Pager_object * pager(); Pager_object * pager();
@ -180,7 +188,7 @@ namespace Genode {
Thread_base * thread_base() Thread_base * thread_base()
{ {
if (!_thread_base && !main_thread()) { if (!_thread_base && !_main_thread) {
PERR("invalid thread base"); PERR("invalid thread base");
} }
return _thread_base; return _thread_base;
@ -188,15 +196,9 @@ namespace Genode {
Native_utcb * utcb_phys() const { return _utcb_phys; } Native_utcb * utcb_phys() const { return _utcb_phys; }
Native_utcb * utcb_virt() const { return _utcb_virt; }
Ram_dataspace_capability utcb() const { return _utcb; } Ram_dataspace_capability utcb() const { return _utcb; }
bool main_thread() const { return _main_thread; }
Tlb * tlb() const { return _tlb; } Tlb * tlb() const { return _tlb; }
unsigned priority() { return _priority; }
}; };
} }

View File

@ -115,7 +115,7 @@ namespace Kernel
/* create idle thread */ /* create idle thread */
static char idle_stack[DEFAULT_STACK_SIZE] static char idle_stack[DEFAULT_STACK_SIZE]
__attribute__((aligned(Cpu::DATA_ACCESS_ALIGNM))); __attribute__((aligned(Cpu::DATA_ACCESS_ALIGNM)));
static Thread idle((Platform_thread *)0); static Thread idle(Priority::MAX, "idle");
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]) };
@ -233,7 +233,7 @@ extern "C" void kernel()
/* start thread with stack pointer at the top of stack */ /* start thread with stack pointer at the top of stack */
static Native_utcb utcb; static Native_utcb utcb;
_main_utcb = &utcb; _main_utcb = &utcb;
static Thread t((Platform_thread *)0); static Thread t(Priority::MAX, "core");
t.ip = (addr_t)CORE_MAIN;; t.ip = (addr_t)CORE_MAIN;;
t.sp = (addr_t)s + STACK_SIZE; t.sp = (addr_t)s + STACK_SIZE;
t.init(0, core_id(), &utcb, 1); t.init(0, core_id(), &utcb, 1);

View File

@ -21,7 +21,6 @@
#include <kernel/kernel.h> #include <kernel/kernel.h>
#include <kernel/thread.h> #include <kernel/thread.h>
#include <kernel/vm.h> #include <kernel/vm.h>
#include <platform_thread.h>
#include <platform_pd.h> #include <platform_pd.h>
using namespace Kernel; using namespace Kernel;
@ -184,15 +183,15 @@ void Thread::_schedule()
} }
Thread::Thread(Platform_thread * const pt) Thread::Thread(unsigned const priority, char const * const label)
: :
Execution_context(pt ? pt->priority() : Priority::MAX), Execution_context(priority),
Thread_cpu_support(this), Thread_cpu_support(this),
_platform_thread(pt),
_state(AWAITS_START), _state(AWAITS_START),
_pd(0), _pd(0),
_utcb_phys(0), _utcb_phys(0),
_signal_receiver(0) _signal_receiver(0),
_label(label)
{ } { }
@ -270,16 +269,6 @@ void Thread::proceed()
} }
char const * Kernel::Thread::label() const
{
if (!platform_thread()) {
if (!_utcb_phys) { return "idle"; }
return "core";
}
return platform_thread()->name();
}
char const * Kernel::Thread::pd_label() const char const * Kernel::Thread::pd_label() const
{ {
if (_core()) { return "core"; } if (_core()) { return "core"; }
@ -335,18 +324,17 @@ void Thread::_call_kill_pd()
void Thread::_call_new_thread() void Thread::_call_new_thread()
{ {
/* check permissions */ /* check permissions */
assert(_core()); if (!_core()) {
PERR("not entitled to create thread");
/* dispatch arguments */ user_arg_0(0);
Call_arg const arg1 = user_arg_1(); return;
Call_arg const arg2 = user_arg_2(); }
/* create new thread */
/* create thread */ void * const p = (void *)user_arg_1();
Thread * const t = new ((void *)arg1) unsigned const priority = user_arg_2();
Thread((Platform_thread *)arg2); char const * const label = (char *)user_arg_3();
Thread * const t = new (p) Thread(priority, label);
/* return thread ID */ user_arg_0(t->id());
user_arg_0((Call_ret)t->id());
} }

View File

@ -22,11 +22,6 @@
#include <cpu_support.h> #include <cpu_support.h>
#include <cpu.h> #include <cpu.h>
namespace Genode
{
class Platform_thread;
}
namespace Kernel namespace Kernel
{ {
class Thread; class Thread;
@ -78,11 +73,11 @@ class Kernel::Thread
STOPPED = 8, STOPPED = 8,
}; };
Platform_thread * const _platform_thread; State _state;
State _state; Pd * _pd;
Pd * _pd; Native_utcb * _utcb_phys;
Native_utcb * _utcb_phys; Signal_receiver * _signal_receiver;
Signal_receiver * _signal_receiver; char const * const _label;
/** /**
* Notice that another thread yielded the CPU to this thread * Notice that another thread yielded the CPU to this thread
@ -255,9 +250,10 @@ class Kernel::Thread
/** /**
* Constructor * Constructor
* *
* \param platform_thread corresponding userland object * \param priority scheduling priority
* \param label debugging label
*/ */
Thread(Platform_thread * const platform_thread); Thread(unsigned const priority, char const * const label);
/** /**
* Prepare thread to get scheduled the first time * Prepare thread to get scheduled the first time
@ -283,11 +279,10 @@ class Kernel::Thread
** Accessors ** ** Accessors **
***************/ ***************/
Platform_thread * platform_thread() const { return _platform_thread; } unsigned id() const { return Object::id(); }
unsigned id() const { return Object::id(); } char const * label() const { return _label; };
char const * label() const; unsigned pd_id() const;
unsigned pd_id() const; char const * pd_label() const;
char const * pd_label() const;
}; };
#endif /* _KERNEL__THREAD_H_ */ #endif /* _KERNEL__THREAD_H_ */

View File

@ -28,7 +28,7 @@ bool Platform_thread::_attaches_utcb_by_itself()
* virtual context area by itself, as it is done for other threads * virtual context area by itself, as it is done for other threads
* through a sub RM-session. * through a sub RM-session.
*/ */
return _pd_id == Kernel::core_id() || !main_thread(); return _pd_id == Kernel::core_id() || !_main_thread;
} }
@ -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(utcb_virt()); 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(utcb_phys(), 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());
@ -72,16 +72,19 @@ Platform_thread::~Platform_thread()
Kernel::delete_thread(_id); Kernel::delete_thread(_id);
} }
Platform_thread::Platform_thread(const char * name,
Platform_thread::Platform_thread(const char * const label,
Thread_base * const thread_base, Thread_base * const thread_base,
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),
_pd_id(pd_id), _rm_client(0), _utcb_virt(0), _stack_size(stack_size),
_priority(Kernel::Priority::MAX), _pd_id(pd_id),
_rm_client(0),
_utcb_virt(0),
_main_thread(0) _main_thread(0)
{ {
strncpy(_name, name, NAME_MAX_LEN); strncpy(_label, label, LABEL_MAX_LEN);
/* 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();
@ -93,20 +96,27 @@ Platform_thread::Platform_thread(const char * name,
} }
_utcb_virt = _utcb_phys; _utcb_virt = _utcb_phys;
/* common constructor parts */ /* create kernel object */
_init(); _id = Kernel::new_thread(_kernel_thread, Kernel::Priority::MAX, _label);
if (!_id) {
PERR("failed to create kernel object");
throw Cpu_session::Thread_creation_failed();
}
} }
Platform_thread::Platform_thread(const char * name, unsigned int priority, Platform_thread::Platform_thread(const char * const label,
addr_t utcb) unsigned const priority,
addr_t const 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),
_utcb_virt((Native_utcb *)utcb), _utcb_virt((Native_utcb *)utcb),
_priority(Cpu_session::scale_priority(Kernel::Priority::MAX, priority)),
_main_thread(0) _main_thread(0)
{ {
strncpy(_name, name, NAME_MAX_LEN); strncpy(_label, label, LABEL_MAX_LEN);
/* /*
* Allocate UTCB backing store for a thread outside of core. Page alignment * Allocate UTCB backing store for a thread outside of core. Page alignment
@ -123,22 +133,26 @@ Platform_thread::Platform_thread(const char * name, unsigned int priority,
} }
_utcb_phys = (Native_utcb *)ram->phys_addr(_utcb); _utcb_phys = (Native_utcb *)ram->phys_addr(_utcb);
/* common constructor parts */ /* create kernel object */
_init(); _id = Kernel::new_thread(_kernel_thread, priority, _label);
if (!_id) {
PERR("failed to create kernel object");
throw Cpu_session::Thread_creation_failed();
}
} }
int Platform_thread::join_pd(unsigned const pd_id, bool const main_thread, int Platform_thread::join_pd(unsigned const pd_id, bool const main_thread,
Weak_ptr<Address_space> address_space) Weak_ptr<Address_space> address_space)
{ {
/* check if we're already in another PD */ /* check if thread is already in another protection domain */
if (_pd_id && _pd_id != pd_id) { if (_pd_id && _pd_id != pd_id) {
PERR("already joined a PD"); PERR("thread already in another protection domain");
return -1; return -1;
} }
/* denote configuration for start method */ /* join protection domain */
_pd_id = pd_id; _pd_id = pd_id;
_main_thread = main_thread; _main_thread = main_thread;
_address_space = address_space; _address_space = address_space;
return 0; return 0;
} }
@ -146,12 +160,6 @@ int Platform_thread::join_pd(unsigned const pd_id, bool const main_thread,
void Platform_thread::_init() void Platform_thread::_init()
{ {
/* create kernel object */
_id = Kernel::new_thread(_kernel_thread, this);
if (!_id) {
PERR("failed to create kernel object");
throw Cpu_session::Thread_creation_failed();
}
} }
@ -186,14 +194,14 @@ int Platform_thread::start(void * const ip, void * const sp,
write_regs[1] = Reg_id::SP; write_regs[1] = Reg_id::SP;
addr_t write_values[] = { addr_t write_values[] = {
(addr_t)ip, (addr_t)ip,
main_thread() ? (addr_t)_utcb_virt : (addr_t)sp _main_thread ? (addr_t)_utcb_virt : (addr_t)sp
}; };
if (Kernel::access_thread_regs(id(), 0, WRITES, 0, write_values)) { if (Kernel::access_thread_regs(id(), 0, WRITES, 0, write_values)) {
PERR("failed to initialize thread registers"); PERR("failed to initialize thread registers");
return -1; return -1;
} }
/* let thread participate in CPU scheduling */ /* let thread participate in CPU scheduling */
_tlb = Kernel::start_thread(id(), cpu_id, _pd_id, utcb_phys()); _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;