hw: get rid of Kernel::current_thread_id

Every thread receives a startup message from its creator through the initial
state of its userland thread-context. The thread-startup code remembers the
kernel name of the new thread by reading this message before the userland
thread-context gets polluted. This way, Kernel::current_thread_id becomes
unnecessary.

fix #953
This commit is contained in:
Martin Stein 2013-11-19 15:13:24 +01:00 committed by Norman Feske
parent b5e92653bf
commit b694045bd9
13 changed files with 180 additions and 150 deletions

View File

@ -28,8 +28,8 @@ namespace Genode
struct Native_thread
{
Native_thread_id tid;
Platform_thread *pt;
Platform_thread * platform_thread;
Native_thread_id thread_id;
};
typedef int Native_connection_state;
@ -38,13 +38,12 @@ namespace Genode
enum { MIN_MAPPING_SIZE_LOG2 = 12 };
/**
* Get kernel-object identifier of the current thread
* Return kernel thread-name of the caller
*/
inline Native_thread_id thread_get_my_native_id()
{ return Kernel::current_thread_id(); }
Native_thread_id thread_get_my_native_id();
/**
* Get the thread ID, wich is handled as invalid by the kernel
* Return an invalid kernel thread-name
*/
inline Native_thread_id thread_invalid_id() { return 0; }
@ -59,8 +58,9 @@ namespace Genode
struct Type
{
enum Id {
INVALID = 0,
IPC = 1,
INVALID = 0,
STARTUP = 1,
IPC = 2,
};
};
@ -78,48 +78,14 @@ namespace Genode
};
/**
* Describes a userland-thread-context region
* Message that is communicated from a thread creator to the new thread
*/
struct Native_utcb
{
union {
uint8_t data[1 << MIN_MAPPING_SIZE_LOG2];
Msg msg;
Ipc_msg ipc_msg;
};
class Startup_msg;
void call_wait_for_request(void * & buf_base, size_t & buf_size)
{
msg.type = Msg::Type::INVALID;
buf_base = base();
buf_size = size();
}
void call_request_and_wait(void * & msg_base, size_t & msg_size,
void * & buf_base, size_t & buf_size)
{
msg.type = Msg::Type::IPC;
msg_base = ipc_msg_base();
msg_size = ipc_msg_size();
buf_base = base();
buf_size = size();
}
void call_reply(void * & msg_base, size_t & msg_size)
{
msg.type = Msg::Type::IPC;
msg_base = ipc_msg_base();
msg_size = ipc_msg_size();
}
size_t size() { return sizeof(data) / sizeof(data[0]); }
void * base() { return &data; }
addr_t top() { return (addr_t)base() + size(); }
void * ipc_msg_base() { return &ipc_msg; }
size_t ipc_msg_size() { return ipc_msg_header_size() + ipc_msg.size; }
size_t ipc_msg_max_size() { return top() - (addr_t)&ipc_msg; }
size_t ipc_msg_header_size() { return (addr_t)ipc_msg.data - (addr_t)&ipc_msg; }
};
/**
* Memory region that is exclusive to every thread and known by the kernel
*/
struct Native_utcb;
struct Cap_dst_policy
{
@ -145,7 +111,7 @@ namespace Genode
typedef Native_capability_tpl<Cap_dst_policy> Native_capability;
/**
* A coherent address region
* Coherent address region
*/
struct Native_region
{
@ -170,5 +136,76 @@ namespace Genode
struct Native_pd_args { };
}
class Genode::Startup_msg : public Msg
{
private:
Native_thread_id _thread_id;
public:
/**
* Set-up valid startup message
*
* \param thread_id kernel name of the thread that is started
*/
void init(Native_thread_id const thread_id)
{
_thread_id = thread_id;
type = Msg::Type::STARTUP;
}
/**
* Return kernel name of started thread message-type-save
*/
Native_thread_id thread_id() const
{
if (type == Msg::Type::STARTUP) { return _thread_id; }
return thread_invalid_id();
}
};
struct Genode::Native_utcb
{
union {
uint8_t data[1 << MIN_MAPPING_SIZE_LOG2];
Msg msg;
Ipc_msg ipc_msg;
Startup_msg startup_msg;
};
void call_wait_for_request(void * & buf_base, size_t & buf_size)
{
msg.type = Msg::Type::INVALID;
buf_base = base();
buf_size = size();
}
void call_request_and_wait(void * & msg_base, size_t & msg_size,
void * & buf_base, size_t & buf_size)
{
msg.type = Msg::Type::IPC;
msg_base = ipc_msg_base();
msg_size = ipc_msg_size();
buf_base = base();
buf_size = size();
}
void call_reply(void * & msg_base, size_t & msg_size)
{
msg.type = Msg::Type::IPC;
msg_base = ipc_msg_base();
msg_size = ipc_msg_size();
}
size_t size() { return sizeof(data) / sizeof(data[0]); }
void * base() { return &data; }
addr_t top() { return (addr_t)base() + size(); }
void * ipc_msg_base() { return &ipc_msg; }
size_t ipc_msg_size() { return ipc_msg_header_size() + ipc_msg.size; }
size_t ipc_msg_max_size() { return top() - (addr_t)&ipc_msg; }
size_t ipc_msg_header_size() { return (addr_t)ipc_msg.data - (addr_t)&ipc_msg; }
};
#endif /* _BASE__NATIVE_TYPES_H_ */

View File

@ -43,29 +43,28 @@ namespace Kernel
START_THREAD = 2,
PAUSE_THREAD = 3,
RESUME_THREAD = 4,
CURRENT_THREAD_ID = 5,
YIELD_THREAD = 6,
ACCESS_THREAD_REGS = 7,
ROUTE_THREAD_EVENT = 8,
UPDATE_PD = 9,
UPDATE_REGION = 10,
NEW_PD = 11,
KILL_PD = 12,
REQUEST_AND_WAIT = 13,
REPLY = 14,
WAIT_FOR_REQUEST = 15,
NEW_SIGNAL_RECEIVER = 16,
NEW_SIGNAL_CONTEXT = 17,
KILL_SIGNAL_CONTEXT = 18,
KILL_SIGNAL_RECEIVER = 19,
SUBMIT_SIGNAL = 20,
AWAIT_SIGNAL = 21,
SIGNAL_PENDING = 22,
ACK_SIGNAL = 23,
NEW_VM = 24,
RUN_VM = 25,
PAUSE_VM = 26,
PRINT_CHAR = 27,
YIELD_THREAD = 5,
ACCESS_THREAD_REGS = 6,
ROUTE_THREAD_EVENT = 7,
UPDATE_PD = 8,
UPDATE_REGION = 9,
NEW_PD = 10,
KILL_PD = 11,
REQUEST_AND_WAIT = 12,
REPLY = 13,
WAIT_FOR_REQUEST = 14,
NEW_SIGNAL_RECEIVER = 15,
NEW_SIGNAL_CONTEXT = 16,
KILL_SIGNAL_CONTEXT = 17,
KILL_SIGNAL_RECEIVER = 18,
SUBMIT_SIGNAL = 19,
AWAIT_SIGNAL = 20,
SIGNAL_PENDING = 21,
ACK_SIGNAL = 22,
NEW_VM = 23,
RUN_VM = 24,
PAUSE_VM = 25,
PRINT_CHAR = 26,
};
};
@ -295,15 +294,6 @@ namespace Kernel
}
/**
* Get the thread ID of the current thread
*/
inline int current_thread_id()
{
return call(Call_id::CURRENT_THREAD_ID);
}
/**
* Set or unset the handler of an event a kernel thread-object triggers
*

View File

@ -1,5 +1,5 @@
/*
* \brief Helper functions for the Lock implementation
* \brief Helper functions for the lock implementation
* \author Martin Stein
* \date 2011-01-02
*/
@ -11,55 +11,56 @@
* under the terms of the GNU General Public License version 2.
*/
#ifndef _SRC__BASE__LOCK__LOCK_HELPER_H_
#define _SRC__BASE__LOCK__LOCK_HELPER_H_
#ifndef _LOCK_HELPER_H_
#define _LOCK_HELPER_H_
/* Genode includes */
#include <base/native_types.h>
#include <base/thread.h>
extern Genode::Native_thread_id main_thread_tid;
extern Genode::Native_thread_id _main_thread_id;
/**
* Yield CPU to any other thread
* Yield execution time-slice of current thread
*/
static inline void thread_yield()
{ Kernel::yield_thread(); }
static inline void thread_yield() { Kernel::yield_thread(); }
/**
* Yield CPU to a specified thread 't'
* Return kernel name of thread t
*/
static inline void
thread_switch_to(Genode::Thread_base *thread_base)
static inline Genode::Native_thread_id
native_thread_id(Genode::Thread_base * const t)
{
Genode::Native_thread_id t = thread_base ?
thread_base->tid().tid :
main_thread_tid;
Kernel::yield_thread(t);
return t ? t->tid().thread_id : _main_thread_id;
}
/**
* Resume another thread 't' and return if it were paused or not
* Yield execution time-slice of current thread to thread t
*/
static inline void thread_switch_to(Genode::Thread_base * const t)
{
Kernel::yield_thread(native_thread_id(t));
}
/**
* Resume thread t and return wether t was paused or not
*/
static inline bool
thread_check_stopped_and_restart(Genode::Thread_base *thread_base)
thread_check_stopped_and_restart(Genode::Thread_base * const t)
{
Genode::Native_thread_id t = thread_base ?
thread_base->tid().tid :
main_thread_tid;
return Kernel::resume_thread(t) == 0;
return Kernel::resume_thread(native_thread_id(t)) == 0;
}
/**
* Exclude ourselves from CPU scheduling for now
* Pause execution of current thread
*/
static inline void thread_stop_myself() { Kernel::pause_thread(); }
#endif /* _SRC__BASE__LOCK__LOCK_HELPER_H_ */
#endif /* _LOCK_HELPER_H_ */

View File

@ -20,5 +20,6 @@
void Genode::Thread_base::_thread_bootstrap()
{
_tid.tid = Kernel::current_thread_id();
Native_utcb * const utcb = Thread_base::myself()->utcb();
_tid.thread_id = utcb->startup_msg.thread_id();
}

View File

@ -21,20 +21,20 @@ using namespace Genode;
extern Native_utcb * __initial_sp;
namespace Genode { Rm_session *env_context_area_rm_session(); }
namespace Genode { Rm_session * env_context_area_rm_session(); }
/*****************
** Thread_base **
*****************/
void Thread_base::_init_platform_thread() { }
Native_utcb * Thread_base::utcb()
{
/* this is a main thread, so CRT0 provides UTCB through '_main_utcb' */
if (!this) return __initial_sp;
/* otherwise we have a valid thread base */
return &_context->utcb;
if (this) { return &_context->utcb; }
return __initial_sp;
}
@ -47,19 +47,16 @@ void Thread_base::_thread_start()
}
void Thread_base::_init_platform_thread() { }
void Thread_base::_deinit_platform_thread()
{
/* detach UTCB */
/* detach userland thread-context */
size_t const size = sizeof(_context->utcb);
addr_t utcb = Context_allocator::addr_to_base(_context) +
Native_config::context_virtual_size() - size -
Native_config::context_area_virtual_base();
env_context_area_rm_session()->detach(utcb);
/* destroy object at the CPU session */
/* destroy server object */
env()->cpu_session()->kill_thread(_thread_cap);
if (_pager_cap.valid()) {
env()->rm_session()->remove_client(_pager_cap);
@ -69,7 +66,7 @@ void Thread_base::_deinit_platform_thread()
void Thread_base::start()
{
/* create thread at core */
/* create server object */
char buf[48];
name(buf, sizeof(buf));
Cpu_session * cpu = env()->cpu_session();
@ -78,11 +75,11 @@ void Thread_base::start()
/* assign thread to protection domain */
env()->pd_session()->bind_thread(_thread_cap);
/* create new pager object and assign it to the new thread */
/* create pager object and assign it to the thread */
_pager_cap = env()->rm_session()->add_client(_thread_cap);
env()->cpu_session()->set_pager(_thread_cap, _pager_cap);
/* attach UTCB */
/* attach userland thread-context */
try {
Ram_dataspace_capability ds = env()->cpu_session()->utcb(_thread_cap);
size_t const size = sizeof(_context->utcb);
@ -91,7 +88,7 @@ void Thread_base::start()
Native_config::context_area_virtual_base();
env_context_area_rm_session()->attach_at(ds, dst, size);
} catch (...) {
PERR("%s: Failed to attach UTCB", __PRETTY_FUNCTION__);
PERR("failed to attach userland thread-context");
sleep_forever();
}
/* start thread with its initial IP and aligned SP */
@ -105,4 +102,3 @@ void Thread_base::cancel_blocking()
{
env()->cpu_session()->cancel_blocking(_thread_cap);
}

View File

@ -75,6 +75,6 @@
/* main-thread UTCB-pointer for the Genode thread-API */
.align 3
.global _main_utcb
_main_utcb: .long 0
.global _main_thread_utcb
_main_thread_utcb: .long 0

View File

@ -182,7 +182,7 @@ namespace Genode {
size_t stack_size() const { return _stack_size; }
Native_utcb * utcb_phys() const { return _utcb_phys; }
Native_utcb * utcb_virt() const { return _utcb_virt; }
Ram_dataspace_capability utcb() const { return _utcb; }

View File

@ -38,7 +38,7 @@
using namespace Kernel;
/* get core configuration */
extern Genode::Native_utcb * _main_utcb;
extern Genode::Native_utcb * _main_thread_utcb;
extern int _kernel_stack_high;
extern "C" void CORE_MAIN();
@ -232,8 +232,9 @@ extern "C" void kernel()
/* start thread with stack pointer at the top of stack */
static Native_utcb utcb;
_main_utcb = &utcb;
static Thread t(Priority::MAX, "core");
_main_thread_utcb = &utcb;
_main_thread_utcb->startup_msg.init(t.id());
t.ip = (addr_t)CORE_MAIN;;
t.sp = (addr_t)s + STACK_SIZE;
t.init(0, core_id(), &utcb, 1);

View File

@ -449,9 +449,6 @@ void Thread::_call_yield_thread()
}
void Thread::_call_current_thread_id() { user_arg_0((Call_ret)id()); }
void Thread::_call_wait_for_request()
{
void * buf_base;
@ -870,7 +867,6 @@ void Thread::_call()
case Call_id::START_THREAD: _call_start_thread(); return;
case Call_id::PAUSE_THREAD: _call_pause_thread(); return;
case Call_id::RESUME_THREAD: _call_resume_thread(); return;
case Call_id::CURRENT_THREAD_ID: _call_current_thread_id(); return;
case Call_id::YIELD_THREAD: _call_yield_thread(); return;
case Call_id::REQUEST_AND_WAIT: _call_request_and_wait(); return;
case Call_id::REPLY: _call_reply(); return;

View File

@ -190,7 +190,6 @@ class Kernel::Thread
void _call_pause_thread();
void _call_resume_thread();
void _call_yield_thread();
void _call_current_thread_id();
void _call_wait_for_request();
void _call_request_and_wait();
void _call_reply();

View File

@ -190,7 +190,7 @@ int Platform_thread::start(void * const ip, void * const sp,
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 write_values[] = {
(addr_t)ip,
_main_thread ? (addr_t)_utcb_virt : (addr_t)sp
};
@ -198,8 +198,9 @@ int Platform_thread::start(void * const ip, void * const sp,
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);
/* start executing new thread */
_utcb_phys->startup_msg.init(_id);
_tlb = Kernel::start_thread(_id, cpu_id, _pd_id, _utcb_phys);
if (!_tlb) {
PERR("failed to start thread");
return -1;

View File

@ -22,18 +22,16 @@
using namespace Genode;
extern Genode::Native_utcb * _main_utcb;
extern Genode::Native_utcb * _main_thread_utcb;
namespace Kernel { unsigned core_id(); }
Native_utcb * Thread_base::utcb()
{
/* this is the main thread */
if (!this) { return _main_utcb; }
/* this isn't the main thread */
return _tid.pt->utcb_phys();
if (this) { return _tid.platform_thread->utcb_virt(); }
return _main_thread_utcb;
}
@ -57,9 +55,10 @@ void Thread_base::_thread_start()
Thread_base::Thread_base(const char *name, size_t stack_size)
: _list_element(this)
:
_list_element(this)
{
_tid.pt = new (platform()->core_mem_alloc())
_tid.platform_thread = new (platform()->core_mem_alloc())
Platform_thread(name, stack_size, Kernel::core_id());
}
@ -74,7 +73,7 @@ Thread_base::~Thread_base()
void Thread_base::start()
{
/* allocate stack memory that fullfills the constraints for core stacks */
size_t const size = _tid.pt->stack_size();
size_t const size = _tid.platform_thread->stack_size();
if (size > (1 << CORE_STACK_ALIGNM_LOG2) - sizeof(Core_thread_id)) {
PERR("stack size does not fit stack alignment of core");
return;
@ -92,7 +91,7 @@ void Thread_base::start()
/* start thread with stack pointer at the top of stack */
void * sp = (void *)((addr_t)base + size);
void * ip = (void *)&_thread_start;
if (_tid.pt->start(ip, sp)) {
if (_tid.platform_thread->start(ip, sp)) {
PERR("failed to start thread");
alloc->free(base, size);
return;
@ -106,5 +105,8 @@ void Thread_base::join()
}
void Thread_base::cancel_blocking() { _tid.pt->cancel_blocking(); }
void Thread_base::cancel_blocking()
{
_tid.platform_thread->cancel_blocking();
}

View File

@ -14,18 +14,24 @@
/* Genode includes */
#include <base/native_types.h>
#include <base/thread.h>
using namespace Genode;
namespace Genode { void platform_main_bootstrap(); }
Native_thread_id _main_thread_id;
Genode::Native_thread_id main_thread_tid;
Native_thread_id Genode::thread_get_my_native_id()
{
Thread_base * const t = Thread_base::myself();
return t ? t->tid().thread_id : _main_thread_id;
}
void Genode::platform_main_bootstrap()
{
static struct Bootstrap
{
Bootstrap() { main_thread_tid = Kernel::current_thread_id(); }
} bootstrap;
Native_utcb * const utcb = Thread_base::myself()->utcb();
_main_thread_id = utcb->startup_msg.thread_id();
}