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
{
class Native_utcb;
class Platform_thread;
class Platform_pd;
class Tlb;
}
@ -30,7 +29,6 @@ namespace Kernel
typedef Genode::Tlb Tlb;
typedef Genode::addr_t addr_t;
typedef Genode::size_t size_t;
typedef Genode::Platform_thread Platform_thread;
typedef Genode::Platform_pd Platform_pd;
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
* that is thereupon allocated to the kernel
* \param pt assigned platform thread
* \param p memory donation for the new kernel thread object
* \param priority scheduling priority of the new thread
* \param label debugging label of the new thread
*
* \retval >0 ID of the new thread
* \retval 0 if no new thread was created
* \retval >0 kernel name of the new thread
* \retval 0 failed
*
* Restricted to core threads. Regaining of the supplied memory can be done
* through 'delete_thread'.
* Restricted to core threads.
*/
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
{
enum { NAME_MAX_LEN = 32 };
enum { LABEL_MAX_LEN = 32 };
Thread_base * _thread_base;
size_t _stack_size;
@ -52,9 +52,8 @@ namespace Genode {
Native_utcb * _utcb_virt;
Tlb * _tlb;
Ram_dataspace_capability _utcb;
char _name[NAME_MAX_LEN];
char _label[LABEL_MAX_LEN];
char _kernel_thread[sizeof(Kernel::Thread)];
unsigned _priority;
/*
* Wether this thread is the main thread of a program.
@ -80,14 +79,24 @@ namespace Genode {
/**
* 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);
/**
* 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);
/**
@ -96,13 +105,14 @@ namespace Genode {
~Platform_thread();
/**
* Join PD identified by 'pd_id'
* Join a protection domain
*
* \param pd_id ID of targeted PD
* \param main_thread wether we are the main thread in this PD
* \param pd_id kernel name of targeted protection domain
* \param main_thread wether thread is the first in protection domain
* \param address_space corresponding Genode address space
*
* \retval 0 on success
* \retval <0 otherwise
* \retval 0 succeeded
* \retval -1 failed
*/
int join_pd(unsigned const pd_id, bool const main_thread,
Weak_ptr<Address_space> address_space);
@ -166,8 +176,6 @@ namespace Genode {
** Accessors **
***************/
inline char const * name() const { return _name; }
void pager(Pager_object * const pager);
Pager_object * pager();
@ -180,7 +188,7 @@ namespace Genode {
Thread_base * thread_base()
{
if (!_thread_base && !main_thread()) {
if (!_thread_base && !_main_thread) {
PERR("invalid thread base");
}
return _thread_base;
@ -188,15 +196,9 @@ namespace Genode {
Native_utcb * utcb_phys() const { return _utcb_phys; }
Native_utcb * utcb_virt() const { return _utcb_virt; }
Ram_dataspace_capability utcb() const { return _utcb; }
bool main_thread() const { return _main_thread; }
Tlb * tlb() const { return _tlb; }
unsigned priority() { return _priority; }
};
}

View File

@ -115,7 +115,7 @@ namespace Kernel
/* create idle thread */
static char idle_stack[DEFAULT_STACK_SIZE]
__attribute__((aligned(Cpu::DATA_ACCESS_ALIGNM)));
static Thread idle((Platform_thread *)0);
static Thread idle(Priority::MAX, "idle");
static bool init = 0;
if (!init) {
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 */
static Native_utcb utcb;
_main_utcb = &utcb;
static Thread t((Platform_thread *)0);
static Thread t(Priority::MAX, "core");
t.ip = (addr_t)CORE_MAIN;;
t.sp = (addr_t)s + STACK_SIZE;
t.init(0, core_id(), &utcb, 1);

View File

@ -21,7 +21,6 @@
#include <kernel/kernel.h>
#include <kernel/thread.h>
#include <kernel/vm.h>
#include <platform_thread.h>
#include <platform_pd.h>
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),
_platform_thread(pt),
_state(AWAITS_START),
_pd(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
{
if (_core()) { return "core"; }
@ -335,18 +324,17 @@ void Thread::_call_kill_pd()
void Thread::_call_new_thread()
{
/* check permissions */
assert(_core());
/* dispatch arguments */
Call_arg const arg1 = user_arg_1();
Call_arg const arg2 = user_arg_2();
/* create thread */
Thread * const t = new ((void *)arg1)
Thread((Platform_thread *)arg2);
/* return thread ID */
user_arg_0((Call_ret)t->id());
if (!_core()) {
PERR("not entitled to create thread");
user_arg_0(0);
return;
}
/* create new thread */
void * const p = (void *)user_arg_1();
unsigned const priority = user_arg_2();
char const * const label = (char *)user_arg_3();
Thread * const t = new (p) Thread(priority, label);
user_arg_0(t->id());
}

View File

@ -22,11 +22,6 @@
#include <cpu_support.h>
#include <cpu.h>
namespace Genode
{
class Platform_thread;
}
namespace Kernel
{
class Thread;
@ -78,11 +73,11 @@ class Kernel::Thread
STOPPED = 8,
};
Platform_thread * const _platform_thread;
State _state;
Pd * _pd;
Native_utcb * _utcb_phys;
Signal_receiver * _signal_receiver;
State _state;
Pd * _pd;
Native_utcb * _utcb_phys;
Signal_receiver * _signal_receiver;
char const * const _label;
/**
* Notice that another thread yielded the CPU to this thread
@ -255,9 +250,10 @@ class Kernel::Thread
/**
* 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
@ -283,11 +279,10 @@ class Kernel::Thread
** Accessors **
***************/
Platform_thread * platform_thread() const { return _platform_thread; }
unsigned id() const { return Object::id(); }
char const * label() const;
unsigned pd_id() const;
char const * pd_label() const;
unsigned id() const { return Object::id(); }
char const * label() const { return _label; };
unsigned pd_id() const;
char const * pd_label() const;
};
#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
* 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 */
if (_rm_client) {
Rm_session_component * const rm = _rm_client->member_rm_session();
rm->detach(utcb_virt());
rm->detach(_utcb_virt);
}
}
/* free UTCB */
if (_pd_id == Kernel::core_id()) {
Range_allocator * const ram = platform()->ram_alloc();
ram->free(utcb_phys(), sizeof(Native_utcb));
ram->free(_utcb_phys, sizeof(Native_utcb));
} else {
Ram_session_component * const ram =
dynamic_cast<Ram_session_component *>(core_env()->ram_session());
@ -72,16 +72,19 @@ Platform_thread::~Platform_thread()
Kernel::delete_thread(_id);
}
Platform_thread::Platform_thread(const char * name,
Platform_thread::Platform_thread(const char * const label,
Thread_base * const thread_base,
size_t const stack_size, unsigned const pd_id)
:
_thread_base(thread_base), _stack_size(stack_size),
_pd_id(pd_id), _rm_client(0), _utcb_virt(0),
_priority(Kernel::Priority::MAX),
_thread_base(thread_base),
_stack_size(stack_size),
_pd_id(pd_id),
_rm_client(0),
_utcb_virt(0),
_main_thread(0)
{
strncpy(_name, name, NAME_MAX_LEN);
strncpy(_label, label, LABEL_MAX_LEN);
/* create UTCB for a core thread */
Range_allocator * const ram = platform()->ram_alloc();
@ -93,20 +96,27 @@ Platform_thread::Platform_thread(const char * name,
}
_utcb_virt = _utcb_phys;
/* common constructor parts */
_init();
/* create kernel object */
_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,
addr_t utcb)
Platform_thread::Platform_thread(const char * const label,
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),
_priority(Cpu_session::scale_priority(Kernel::Priority::MAX, priority)),
_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
@ -123,22 +133,26 @@ Platform_thread::Platform_thread(const char * name, unsigned int priority,
}
_utcb_phys = (Native_utcb *)ram->phys_addr(_utcb);
/* common constructor parts */
_init();
/* create kernel object */
_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,
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) {
PERR("already joined a PD");
PERR("thread already in another protection domain");
return -1;
}
/* denote configuration for start method */
_pd_id = pd_id;
_main_thread = main_thread;
/* join protection domain */
_pd_id = pd_id;
_main_thread = main_thread;
_address_space = address_space;
return 0;
}
@ -146,12 +160,6 @@ int Platform_thread::join_pd(unsigned const pd_id, bool const main_thread,
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;
addr_t write_values[] = {
(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)) {
PERR("failed to initialize thread registers");
return -1;
}
/* 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) {
PERR("failed to start thread");
return -1;