From b694045bd9771f32bb5544bf63f4bb59dedfc9a6 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Tue, 19 Nov 2013 15:13:24 +0100 Subject: [PATCH] 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 --- base-hw/include/base/native_types.h | 135 +++++++++++++------- base-hw/include/kernel/interface.h | 54 ++++---- base-hw/src/base/lock/lock_helper.h | 47 +++---- base-hw/src/base/thread/thread_bootstrap.cc | 3 +- base-hw/src/base/thread_support.cc | 28 ++-- base-hw/src/core/arm/crt0.s | 4 +- base-hw/src/core/include/platform_thread.h | 2 +- base-hw/src/core/kernel/kernel.cc | 5 +- base-hw/src/core/kernel/thread.cc | 4 - base-hw/src/core/kernel/thread.h | 1 - base-hw/src/core/platform_thread.cc | 7 +- base-hw/src/core/thread.cc | 24 ++-- base-hw/src/platform/main_bootstrap.cc | 16 ++- 13 files changed, 180 insertions(+), 150 deletions(-) diff --git a/base-hw/include/base/native_types.h b/base-hw/include/base/native_types.h index 96d2014a6..5479ac78f 100644 --- a/base-hw/include/base/native_types.h +++ b/base-hw/include/base/native_types.h @@ -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 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_ */ diff --git a/base-hw/include/kernel/interface.h b/base-hw/include/kernel/interface.h index cfdc6aad1..0801495fa 100644 --- a/base-hw/include/kernel/interface.h +++ b/base-hw/include/kernel/interface.h @@ -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 * diff --git a/base-hw/src/base/lock/lock_helper.h b/base-hw/src/base/lock/lock_helper.h index 7fcd246a0..e10f36664 100644 --- a/base-hw/src/base/lock/lock_helper.h +++ b/base-hw/src/base/lock/lock_helper.h @@ -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 #include - -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_ */ diff --git a/base-hw/src/base/thread/thread_bootstrap.cc b/base-hw/src/base/thread/thread_bootstrap.cc index 4da07f008..e753726f6 100644 --- a/base-hw/src/base/thread/thread_bootstrap.cc +++ b/base-hw/src/base/thread/thread_bootstrap.cc @@ -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(); } diff --git a/base-hw/src/base/thread_support.cc b/base-hw/src/base/thread_support.cc index 3292c89c6..be8cfcb5d 100644 --- a/base-hw/src/base/thread_support.cc +++ b/base-hw/src/base/thread_support.cc @@ -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); } - diff --git a/base-hw/src/core/arm/crt0.s b/base-hw/src/core/arm/crt0.s index ea7029643..6663893a6 100644 --- a/base-hw/src/core/arm/crt0.s +++ b/base-hw/src/core/arm/crt0.s @@ -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 diff --git a/base-hw/src/core/include/platform_thread.h b/base-hw/src/core/include/platform_thread.h index a34798586..660262582 100644 --- a/base-hw/src/core/include/platform_thread.h +++ b/base-hw/src/core/include/platform_thread.h @@ -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; } diff --git a/base-hw/src/core/kernel/kernel.cc b/base-hw/src/core/kernel/kernel.cc index f3fd33ff3..e48b36709 100644 --- a/base-hw/src/core/kernel/kernel.cc +++ b/base-hw/src/core/kernel/kernel.cc @@ -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); diff --git a/base-hw/src/core/kernel/thread.cc b/base-hw/src/core/kernel/thread.cc index b29181cf8..850e0209c 100644 --- a/base-hw/src/core/kernel/thread.cc +++ b/base-hw/src/core/kernel/thread.cc @@ -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; diff --git a/base-hw/src/core/kernel/thread.h b/base-hw/src/core/kernel/thread.h index 1e3174fcc..a02d345bc 100644 --- a/base-hw/src/core/kernel/thread.h +++ b/base-hw/src/core/kernel/thread.h @@ -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(); diff --git a/base-hw/src/core/platform_thread.cc b/base-hw/src/core/platform_thread.cc index e75ceb4c1..1baba9a90 100644 --- a/base-hw/src/core/platform_thread.cc +++ b/base-hw/src/core/platform_thread.cc @@ -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; diff --git a/base-hw/src/core/thread.cc b/base-hw/src/core/thread.cc index 975ac42c2..a97bb96f1 100644 --- a/base-hw/src/core/thread.cc +++ b/base-hw/src/core/thread.cc @@ -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(); +} diff --git a/base-hw/src/platform/main_bootstrap.cc b/base-hw/src/platform/main_bootstrap.cc index 3b1328b8c..69f9fb0e1 100644 --- a/base-hw/src/platform/main_bootstrap.cc +++ b/base-hw/src/platform/main_bootstrap.cc @@ -14,18 +14,24 @@ /* Genode includes */ #include +#include +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(); }