From 0b64328944dc14f6a1fd8c0a97809b4f8dde35bd Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Tue, 28 Jan 2014 14:30:36 +0100 Subject: [PATCH] base: setup thread object for main thread in CRT0 For a main thread a thread object is created by the CRT0 before _main gets called so that _main can already run in a generic environment that, e.g., catches stack overflows as a page-fault instead of corrupting the BSS. Additionally dynamic programs have only one CRT0 - the one of the LDSO - which does the initialization for both LDSO and program. ref #989 --- base-codezero/lib/mk/base-common.mk | 9 +- .../src/base/thread/thread_bootstrap.cc | 71 ++++++++++ base-codezero/src/base/thread/thread_start.cc | 3 - base-codezero/src/core/thread_start.cc | 4 - base-codezero/src/platform/main_bootstrap.cc | 81 ----------- base-fiasco/lib/mk/base-common.mk | 11 +- .../src/base/thread/thread_bootstrap.cc | 41 ++++++ base-fiasco/src/core/thread_start.cc | 3 - base-fiasco/src/platform/main_bootstrap.cc | 14 -- base-foc/include/base/cap_alloc.h | 6 + base-foc/include/base/cap_map.h | 9 +- base-foc/lib/mk/base-common.inc | 6 +- base-foc/src/base/thread/thread.cc | 42 ++++-- base-foc/src/base/thread/thread_bootstrap.cc | 30 ++++ base-foc/src/base/thread/thread_start.cc | 26 +++- base-foc/src/core/thread_start.cc | 2 +- base-foc/src/platform/main_bootstrap.cc | 41 ------ base-hw/lib/mk/base-common.mk | 8 +- base-hw/src/base/thread/thread_bootstrap.cc | 75 +++++++++- base-hw/src/base/thread_support.cc | 3 - base-hw/src/core/arm/crt0.s | 5 - base-hw/src/core/kernel/kernel.cc | 2 + base-hw/src/core/thread.cc | 2 +- base-hw/src/platform/main_bootstrap.cc | 42 ------ base-linux/include/rm_session/client.h | 3 + base-linux/lib/mk/base-common.mk | 8 +- base-linux/src/base/env/platform_env.cc | 4 + base-linux/src/base/env/platform_env.h | 14 +- base-linux/src/base/thread/thread_env.cc | 49 +++++++ base-linux/src/base/thread/thread_linux.cc | 13 +- base-linux/src/core/thread_linux.cc | 2 +- base-linux/src/platform/lx_hybrid.cc | 2 +- base-linux/src/platform/main_bootstrap.cc | 61 -------- base-nova/include/base/cap_map.h | 2 +- base-nova/lib/mk/base-common.inc | 6 +- base-nova/lib/mk/base.mk | 3 +- base-nova/src/base/env/main_thread.cc | 31 ----- base-nova/src/base/thread/thread_context.cc | 91 +++++++++++- base-nova/src/base/thread/thread_nova.cc | 12 +- base-nova/src/core/platform_thread.cc | 2 +- base-nova/src/core/target.inc | 2 - base-nova/src/core/thread_start.cc | 16 ++- base-nova/src/platform/main_bootstrap.cc | 71 ---------- base-okl4/lib/mk/base-common.mk | 9 +- base-okl4/src/base/thread/thread_bootstrap.cc | 70 +++++++++- base-okl4/src/core/thread_start.cc | 3 - base-okl4/src/platform/main_bootstrap.cc | 62 --------- base-pistachio/lib/mk/base-common.mk | 9 +- .../src/base/thread/thread_bootstrap.cc | 31 ++++- base-pistachio/src/core/thread_start.cc | 3 - base-pistachio/src/platform/main_bootstrap.cc | 36 ----- base/include/base/env.h | 14 -- base/include/base/thread.h | 49 +++++-- base/lib/mk/startup.inc | 2 + base/mk/dep_lib.mk | 9 ++ base/mk/lib.mk | 8 +- base/mk/prg.mk | 8 +- base/src/base/env/platform_env.h | 30 +++- base/src/base/env/reinitialize.cc | 55 ++++++-- base/src/base/thread/thread.cc | 43 ++++-- base/src/base/thread/thread_start.cc | 3 - base/src/core/include/core_env.h | 5 +- base/src/platform/_main.cc | 42 +----- base/src/platform/arm/crt0.s | 61 +++++--- base/src/platform/init_main_thread.cc | 130 ++++++++++++++++++ base/src/platform/x86_32/crt0.s | 85 ++++++++---- base/src/platform/x86_64/crt0.s | 89 ++++++++---- libports/lib/mk/ffat_block.mk | 2 - os/lib/mk/startup_dyn.mk | 5 + os/src/lib/ldso/arm/crt0.s | 36 ++++- os/src/lib/ldso/include/arm/call_main.h | 39 ++++-- os/src/lib/ldso/include/x86_32/call_main.h | 44 ++++-- os/src/lib/ldso/include/x86_64/call_main.h | 44 ++++-- os/src/lib/ldso/target.inc | 2 +- os/src/lib/ldso/thread.cc | 24 ++++ os/src/lib/ldso/x86_32/crt0.s | 58 +++++--- os/src/lib/ldso/x86_64/crt0.s | 46 +++++-- os/src/platform/genode_dyn.ld | 7 +- ports/lib/mk/libc_noux.mk | 2 + ports/src/lib/libc_noux/plugin.cc | 29 ++-- 80 files changed, 1299 insertions(+), 823 deletions(-) delete mode 100644 base-codezero/src/platform/main_bootstrap.cc create mode 100644 base-fiasco/src/base/thread/thread_bootstrap.cc delete mode 100644 base-fiasco/src/platform/main_bootstrap.cc delete mode 100644 base-foc/src/platform/main_bootstrap.cc delete mode 100644 base-hw/src/platform/main_bootstrap.cc create mode 100644 base-linux/src/base/thread/thread_env.cc delete mode 100644 base-linux/src/platform/main_bootstrap.cc delete mode 100644 base-nova/src/base/env/main_thread.cc delete mode 100644 base-nova/src/platform/main_bootstrap.cc delete mode 100644 base-okl4/src/platform/main_bootstrap.cc delete mode 100644 base-pistachio/src/platform/main_bootstrap.cc create mode 100644 base/src/platform/init_main_thread.cc create mode 100644 os/lib/mk/startup_dyn.mk create mode 100644 os/src/lib/ldso/thread.cc diff --git a/base-codezero/lib/mk/base-common.mk b/base-codezero/lib/mk/base-common.mk index 67d97ab9e..b63958767 100644 --- a/base-codezero/lib/mk/base-common.mk +++ b/base-codezero/lib/mk/base-common.mk @@ -6,7 +6,7 @@ LIBS += cxx l4 startup -SRC_CC += cap_copy.cc main_bootstrap.cc +SRC_CC += cap_copy.cc SRC_CC += ipc/ipc.cc ipc/pager.cc ipc/ipc_marshal_cap.cc SRC_CC += pager/pager.cc pager/common.cc SRC_CC += avl_tree/avl_tree.cc @@ -28,7 +28,6 @@ INC_DIR += $(REP_DIR)/src/base/lock INC_DIR += $(BASE_DIR)/src/base/thread INC_DIR += $(REP_DIR)/include/codezero/dummies -vpath main_bootstrap.cc $(REP_DIR)/src/platform -vpath cap_copy.cc $(BASE_DIR)/src/platform -vpath %.cc $(REP_DIR)/src/base -vpath %.cc $(BASE_DIR)/src/base +vpath cap_copy.cc $(BASE_DIR)/src/platform +vpath %.cc $(REP_DIR)/src/base +vpath %.cc $(BASE_DIR)/src/base diff --git a/base-codezero/src/base/thread/thread_bootstrap.cc b/base-codezero/src/base/thread/thread_bootstrap.cc index 19be3612a..8a34574ac 100644 --- a/base-codezero/src/base/thread/thread_bootstrap.cc +++ b/base-codezero/src/base/thread/thread_bootstrap.cc @@ -1,6 +1,7 @@ /* * \brief Thread bootstrap code * \author Christian Prochaska + * \author Martin Stein * \date 2013-02-15 */ @@ -13,13 +14,83 @@ /* Genode includes */ #include +#include +#include /* Codezero includes */ #include +Genode::Native_thread_id main_thread_tid; +Codezero::l4_mutex main_thread_running_lock; + + +/***************************** + ** Startup library support ** + *****************************/ + +void prepare_init_main_thread() +{ + /* initialize codezero environment */ + Codezero::__l4_init(); + + /* provide kernel identification of thread through temporary environment */ + main_thread_tid = Codezero::thread_myself(); +} + +void prepare_reinit_main_thread() { prepare_init_main_thread(); } + + +/**************************** + ** Codezero libl4 support ** + ****************************/ + +/* + * Unfortunately, the function 'exregs_print_registers' in 'exregs.c' refers to + * 'memset'. Because we do not want to link core against a C library, we have to + * resolve this function here. + */ +extern "C" void *memset(void *s, int c, Genode::size_t n) __attribute__((weak)); +extern "C" void *memset(void *s, int c, Genode::size_t n) +{ + return Genode::memset(s, c, n); +} + + +/* + * Same problem as for 'memset'. The 'printf' symbol is referenced from + * 'mutex.c' and 'exregs.c' of Codezero's libl4. + */ +extern "C" int printf(const char *format, ...) __attribute__((weak)); +extern "C" int printf(const char *format, ...) +{ + va_list list; + va_start(list, format); + Genode::vprintf(format, list); + va_end(list); + return 0; +} + + +/***************** + ** Thread_base ** + *****************/ void Genode::Thread_base::_thread_bootstrap() { Codezero::l4_mutex_init(utcb()->running_lock()); Codezero::l4_mutex_lock(utcb()->running_lock()); /* block on first mutex lock */ } + + +void Genode::Thread_base::_init_platform_thread(Type type) +{ + if (type == NORMAL) { return; } + + /* adjust values whose computation differs for a main thread */ + _tid.l4id = main_thread_tid; + _thread_cap = Genode::env()->parent()->main_thread_cap(); + + /* get first mutex lock (normally done by _thread_bootstrap) */ + Codezero::l4_mutex_init(utcb()->running_lock()); + Codezero::l4_mutex_lock(utcb()->running_lock()); +} diff --git a/base-codezero/src/base/thread/thread_start.cc b/base-codezero/src/base/thread/thread_start.cc index 44c42df9c..e02a81853 100644 --- a/base-codezero/src/base/thread/thread_start.cc +++ b/base-codezero/src/base/thread/thread_start.cc @@ -39,9 +39,6 @@ void Thread_base::_thread_start() ** Thread base ** *****************/ -void Thread_base::_init_platform_thread() { } - - void Thread_base::_deinit_platform_thread() { env()->cpu_session()->kill_thread(_thread_cap); diff --git a/base-codezero/src/core/thread_start.cc b/base-codezero/src/core/thread_start.cc index af14b8150..dc45ffcb5 100644 --- a/base-codezero/src/core/thread_start.cc +++ b/base-codezero/src/core/thread_start.cc @@ -27,10 +27,6 @@ enum { verbose_thread_start = true }; using namespace Genode; - -void Thread_base::_init_platform_thread() { } - - void Thread_base::_deinit_platform_thread() { } diff --git a/base-codezero/src/platform/main_bootstrap.cc b/base-codezero/src/platform/main_bootstrap.cc deleted file mode 100644 index aca3889f3..000000000 --- a/base-codezero/src/platform/main_bootstrap.cc +++ /dev/null @@ -1,81 +0,0 @@ -/* - * \brief Platform-specific helper functions for the _main() function - * \author Norman Feske - * \author Christian Helmuth - * \date 2009-10-02 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include -#include -#include - -/* Codezero includes */ -#include - - -/**************************** - ** Codezero libl4 support ** - ****************************/ - -/* - * Unfortunately, the function 'exregs_print_registers' in 'exregs.c' refers to - * 'memset'. Because we do not want to link core against a C library, we have to - * resolve this function here. - */ -extern "C" void *memset(void *s, int c, Genode::size_t n) __attribute__((weak)); -extern "C" void *memset(void *s, int c, Genode::size_t n) -{ - return Genode::memset(s, c, n); -} - - -/* - * Same problem as for 'memset'. The 'printf' symbol is referenced from - * 'mutex.c' and 'exregs.c' of Codezero's libl4. - */ -extern "C" int printf(const char *format, ...) __attribute__((weak)); -extern "C" int printf(const char *format, ...) -{ - va_list list; - va_start(list, format); - Genode::vprintf(format, list); - va_end(list); - return 0; -} - - -/************************** - ** Startup-code helpers ** - **************************/ - -namespace Genode { void platform_main_bootstrap(); } - - -Genode::Native_thread_id main_thread_tid; -Codezero::l4_mutex main_thread_running_lock; - - -void Genode::platform_main_bootstrap() -{ - static struct Bootstrap - { - Bootstrap() - { - Codezero::__l4_init(); - - main_thread_tid = Codezero::thread_myself(); - - Codezero::l4_mutex_init(&main_thread_running_lock); - Codezero::l4_mutex_lock(&main_thread_running_lock); /* block on first mutex lock */ - } - } bootstrap; -} diff --git a/base-fiasco/lib/mk/base-common.mk b/base-fiasco/lib/mk/base-common.mk index 8244261eb..c410304b3 100644 --- a/base-fiasco/lib/mk/base-common.mk +++ b/base-fiasco/lib/mk/base-common.mk @@ -6,7 +6,7 @@ LIBS += cxx startup -SRC_CC += cap_copy.cc main_bootstrap.cc +SRC_CC += cap_copy.cc SRC_CC += ipc/ipc.cc ipc/pager.cc ipc/ipc_marshal_cap.cc SRC_CC += pager/pager.cc pager/common.cc SRC_CC += avl_tree/avl_tree.cc @@ -20,12 +20,11 @@ SRC_CC += elf/elf_binary.cc SRC_CC += lock/lock.cc SRC_CC += signal/signal.cc signal/common.cc SRC_CC += server/server.cc server/common.cc -SRC_CC += thread/thread.cc thread/thread_bootstrap_empty.cc thread/trace.cc +SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc INC_DIR += $(REP_DIR)/src/base/lock INC_DIR += $(BASE_DIR)/src/base/thread -vpath main_bootstrap.cc $(REP_DIR)/src/platform -vpath cap_copy.cc $(BASE_DIR)/src/platform -vpath %.cc $(REP_DIR)/src/base -vpath %.cc $(BASE_DIR)/src/base +vpath cap_copy.cc $(BASE_DIR)/src/platform +vpath %.cc $(REP_DIR)/src/base +vpath %.cc $(BASE_DIR)/src/base diff --git a/base-fiasco/src/base/thread/thread_bootstrap.cc b/base-fiasco/src/base/thread/thread_bootstrap.cc new file mode 100644 index 000000000..d100895ed --- /dev/null +++ b/base-fiasco/src/base/thread/thread_bootstrap.cc @@ -0,0 +1,41 @@ +/* + * \brief Platform specific thread initialization + * \author Martin Stein + * \date 2014-01-06 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include +#include + +using namespace Genode; + + +/***************************** + ** Startup library support ** + *****************************/ + +void prepare_init_main_thread() { } + +void prepare_reinit_main_thread() { } + + +/***************** + ** Thread_base ** + *****************/ + +void Thread_base::_thread_bootstrap() { } + + +void Thread_base::_init_platform_thread(Type type) +{ + if (type == NORMAL) { return; } + _thread_cap = Genode::env()->parent()->main_thread_cap(); +} diff --git a/base-fiasco/src/core/thread_start.cc b/base-fiasco/src/core/thread_start.cc index b2d065e7f..666edb8f9 100644 --- a/base-fiasco/src/core/thread_start.cc +++ b/base-fiasco/src/core/thread_start.cc @@ -53,9 +53,6 @@ void Thread_base::cancel_blocking() } -void Thread_base::_init_platform_thread() { } - - void Thread_base::_deinit_platform_thread() { /* destruct platform thread */ diff --git a/base-fiasco/src/platform/main_bootstrap.cc b/base-fiasco/src/platform/main_bootstrap.cc deleted file mode 100644 index 40d58d8b1..000000000 --- a/base-fiasco/src/platform/main_bootstrap.cc +++ /dev/null @@ -1,14 +0,0 @@ -/* - * \brief Platform-specific helper functions for the _main() function - * \author Christian Prochaska - * \date 2009-08-05 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -namespace Genode { void platform_main_bootstrap() { /* dummy */ } } diff --git a/base-foc/include/base/cap_alloc.h b/base-foc/include/base/cap_alloc.h index d774fbdc6..42fb407e2 100644 --- a/base-foc/include/base/cap_alloc.h +++ b/base-foc/include/base/cap_alloc.h @@ -17,6 +17,7 @@ #include #include #include +#include namespace Genode { @@ -124,6 +125,11 @@ namespace Genode { bool static_idx(Cap_index *idx) { return ((T*)idx) < &_indices[START_IDX]; } + + void reinit() + { + construct_at >(this); + } }; } diff --git a/base-foc/include/base/cap_map.h b/base-foc/include/base/cap_map.h index 48308e789..c6571e4d0 100644 --- a/base-foc/include/base/cap_map.h +++ b/base-foc/include/base/cap_map.h @@ -146,6 +146,11 @@ namespace Genode * \param idx pointer to the Cap_index object in question */ virtual bool static_idx(Cap_index *idx) = 0; + + /** + * Redo construction of the object + */ + virtual void reinit() = 0; }; @@ -196,7 +201,9 @@ namespace Genode * to save entries in the capability space, and prevent leaks of * them. */ - class Capability_map : Noncopyable + class Capability_map + : + private Noncopyable { private: diff --git a/base-foc/lib/mk/base-common.inc b/base-foc/lib/mk/base-common.inc index 2a537a84a..fedf554e9 100644 --- a/base-foc/lib/mk/base-common.inc +++ b/base-foc/lib/mk/base-common.inc @@ -6,7 +6,6 @@ LIBS += cxx syscall startup -SRC_CC += main_bootstrap.cc SRC_CC += ipc/ipc.cc ipc/pager.cc SRC_CC += pager/pager.cc pager/common.cc SRC_CC += avl_tree/avl_tree.cc @@ -27,8 +26,7 @@ INC_DIR += $(REP_DIR)/src/base/lock INC_DIR += $(BASE_DIR)/src/base/lock INC_DIR += $(BASE_DIR)/src/base/thread -vpath main_bootstrap.cc $(REP_DIR)/src/platform -vpath %.cc $(REP_DIR)/src/base -vpath %.cc $(BASE_DIR)/src/base +vpath %.cc $(REP_DIR)/src/base +vpath %.cc $(BASE_DIR)/src/base # vi: set ft=make : diff --git a/base-foc/src/base/thread/thread.cc b/base-foc/src/base/thread/thread.cc index f569c6fc6..a6f78a4ab 100644 --- a/base-foc/src/base/thread/thread.cc +++ b/base-foc/src/base/thread/thread.cc @@ -51,24 +51,35 @@ addr_t Thread_base::Context_allocator::addr_to_base(void *addr) size_t Thread_base::Context_allocator::base_to_idx(addr_t base) { - return (base - Native_config::context_area_virtual_base()) / - Native_config::context_virtual_size(); + /* the first context isn't managed through the indices */ + return ((base - Native_config::context_area_virtual_base()) / + Native_config::context_virtual_size()) - 1; } addr_t Thread_base::Context_allocator::idx_to_base(size_t idx) { + /* the first context isn't managed through the indices */ return Native_config::context_area_virtual_base() + + Native_config::context_virtual_size() + idx * Native_config::context_virtual_size(); } -Thread_base::Context *Thread_base::Context_allocator::alloc(Thread_base *thread_base) +Thread_base::Context * +Thread_base::Context_allocator::alloc(Thread_base *thread_base, bool main_thread) { Lock::Guard _lock_guard(_threads_lock); - try { - return base_to_context(idx_to_base(_alloc.alloc())); + addr_t base; + if (main_thread) { + /* the main-thread context isn't managed by '_alloc' */ + base = Native_config::context_area_virtual_base(); + } else { + /* contexts besides main-thread context are managed by '_alloc' */ + base = idx_to_base(_alloc.alloc()); + } + return base_to_context(base); } catch(Bit_allocator::Out_of_indices) { return 0; } @@ -78,8 +89,13 @@ Thread_base::Context *Thread_base::Context_allocator::alloc(Thread_base *thread_ void Thread_base::Context_allocator::free(Context *context) { Lock::Guard _lock_guard(_threads_lock); + addr_t const base = addr_to_base(context); - _alloc.free(base_to_idx(addr_to_base(context))); + /* the main-thread context isn't managed by '_alloc' */ + if (base == Native_config::context_area_virtual_base()) { return; } + + /* contexts besides main-thread context are managed by '_alloc' */ + _alloc.free(base_to_idx(base)); } @@ -94,7 +110,8 @@ Thread_base::Context_allocator *Thread_base::_context_allocator() } -Thread_base::Context *Thread_base::_alloc_context(size_t stack_size) +Thread_base::Context * +Thread_base::_alloc_context(size_t stack_size, bool main_thread) { /* * Synchronize context list when creating new threads from multiple threads @@ -105,7 +122,7 @@ Thread_base::Context *Thread_base::_alloc_context(size_t stack_size) Lock::Guard _lock_guard(alloc_lock); /* allocate thread context */ - Context *context = _context_allocator()->alloc(this); + Context *context = _context_allocator()->alloc(this, main_thread); if (!context) throw Context_alloc_failed(); @@ -201,7 +218,7 @@ void Thread_base::join() void* Thread_base::alloc_secondary_stack(char const *name, size_t stack_size) { - Context *context = _alloc_context(stack_size); + Context *context = _alloc_context(stack_size, false); strncpy(context->name, name, sizeof(context->name)); return (void *)context->stack_top(); } @@ -214,13 +231,14 @@ void Thread_base::free_secondary_stack(void* stack_addr) } -Thread_base::Thread_base(const char *name, size_t stack_size) +Thread_base::Thread_base(const char *name, size_t stack_size, Type const type) : - _context(_alloc_context(stack_size)), + _context(type == REINITIALIZED_MAIN ? + _context : _alloc_context(stack_size, type == MAIN)), _join_lock(Lock::LOCKED) { strncpy(_context->name, name, sizeof(_context->name)); - _init_platform_thread(); + _init_platform_thread(type); } diff --git a/base-foc/src/base/thread/thread_bootstrap.cc b/base-foc/src/base/thread/thread_bootstrap.cc index baf90a025..25a521e0e 100644 --- a/base-foc/src/base/thread/thread_bootstrap.cc +++ b/base-foc/src/base/thread/thread_bootstrap.cc @@ -1,6 +1,7 @@ /* * \brief Fiasco.OC specific thread bootstrap code * \author Stefan Kalkowski + * \author Martin Stein * \date 2011-01-20 */ @@ -11,9 +12,38 @@ * under the terms of the GNU General Public License version 2. */ +/* Genode includes */ +#include #include +/***************************** + ** Startup library support ** + *****************************/ + +void prepare_init_main_thread() +{ + using namespace Genode; + enum { THREAD_CAP_ID = 1 }; + Cap_index * ci(cap_map()->insert(THREAD_CAP_ID, Fiasco::MAIN_THREAD_CAP)); + Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE] = (unsigned long)ci; + Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_THREAD_OBJ] = 0; +} + + +void prepare_reinit_main_thread() +{ + using namespace Genode; + construct_at(cap_map()); + cap_idx_alloc()->reinit(); + prepare_init_main_thread(); +} + + +/***************** + ** Thread_base ** + *****************/ + void Genode::Thread_base::_thread_bootstrap() { } diff --git a/base-foc/src/base/thread/thread_start.cc b/base-foc/src/base/thread/thread_start.cc index 041512155..605196d38 100644 --- a/base-foc/src/base/thread/thread_start.cc +++ b/base-foc/src/base/thread/thread_start.cc @@ -2,6 +2,7 @@ * \brief Fiasco-specific implementation of the non-core startup Thread API * \author Norman Feske * \author Stefan Kalkowski + * \author Martin Stein * \date 2010-01-19 */ @@ -38,15 +39,26 @@ void Thread_base::_deinit_platform_thread() } -void Genode::Thread_base::_init_platform_thread() +void Thread_base::_init_platform_thread(Type type) { - /* create thread at core */ - char buf[48]; - name(buf, sizeof(buf)); - _thread_cap = env()->cpu_session()->create_thread(buf); + if (type == NORMAL) + { + /* create thread at core */ + char buf[48]; + name(buf, sizeof(buf)); + _thread_cap = env()->cpu_session()->create_thread(buf); - /* assign thread to protection domain */ - env()->pd_session()->bind_thread(_thread_cap); + /* assign thread to protection domain */ + env()->pd_session()->bind_thread(_thread_cap); + return; + } + /* adjust values whose computation differs for a main thread */ + _tid = Fiasco::MAIN_THREAD_CAP; + _thread_cap = env()->parent()->main_thread_cap(); + + /* make thread object known to the Fiasco environment */ + addr_t const t = (addr_t)this; + Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_THREAD_OBJ] = t; } diff --git a/base-foc/src/core/thread_start.cc b/base-foc/src/core/thread_start.cc index 6f865fced..efbafe02c 100644 --- a/base-foc/src/core/thread_start.cc +++ b/base-foc/src/core/thread_start.cc @@ -35,7 +35,7 @@ void Thread_base::_deinit_platform_thread() } -void Genode::Thread_base::_init_platform_thread() { } +void Thread_base::_init_platform_thread(Type) { } void Thread_base::start() diff --git a/base-foc/src/platform/main_bootstrap.cc b/base-foc/src/platform/main_bootstrap.cc deleted file mode 100644 index 0a4ac3afe..000000000 --- a/base-foc/src/platform/main_bootstrap.cc +++ /dev/null @@ -1,41 +0,0 @@ -/* - * \brief Platform-specific helper functions for the _main() function - * \author Christian Prochaska - * \author Christian Helmuth - * \date 2009-08-05 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include -#include - -namespace Fiasco { -#include -} - - -namespace Genode { void platform_main_bootstrap(); } - - -void Genode::platform_main_bootstrap() -{ - static struct Bootstrap - { - enum { MAIN_THREAD_CAP_ID = 1 }; - - Bootstrap() - { - Cap_index *i(cap_map()->insert(MAIN_THREAD_CAP_ID, Fiasco::MAIN_THREAD_CAP)); - Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE] = (unsigned long) i; - Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_THREAD_OBJ] = 0; - } - } bootstrap; -} diff --git a/base-hw/lib/mk/base-common.mk b/base-hw/lib/mk/base-common.mk index d4af1afcd..add6e4176 100644 --- a/base-hw/lib/mk/base-common.mk +++ b/base-hw/lib/mk/base-common.mk @@ -6,7 +6,6 @@ LIBS += cxx kernel_interface -SRC_CC += main_bootstrap.cc SRC_CC += ipc.cc ipc/ipc_marshal_cap.cc SRC_CC += avl_tree/avl_tree.cc SRC_CC += allocator/slab.cc @@ -21,10 +20,9 @@ SRC_CC += signal/signal.cc signal/common.cc SRC_CC += server/server.cc server/common.cc SRC_CC += thread/thread_bootstrap.cc thread/trace.cc -INC_DIR += $(REP_DIR)/src/base/lock +INC_DIR += $(REP_DIR)/src/base/lock INC_DIR += $(BASE_DIR)/src/base/lock INC_DIR += $(BASE_DIR)/src/base/thread -vpath main_bootstrap.cc $(REP_DIR)/src/platform -vpath %.cc $(REP_DIR)/src/base -vpath %.cc $(BASE_DIR)/src/base +vpath %.cc $(REP_DIR)/src/base +vpath %.cc $(BASE_DIR)/src/base diff --git a/base-hw/src/base/thread/thread_bootstrap.cc b/base-hw/src/base/thread/thread_bootstrap.cc index bdae1927f..2642874f4 100644 --- a/base-hw/src/base/thread/thread_bootstrap.cc +++ b/base-hw/src/base/thread/thread_bootstrap.cc @@ -1,6 +1,6 @@ /* - * \brief Thread bootstrap code - * \author Christian Prochaska + * \brief Thread initialization + * \author Martin stein * \date 2013-02-15 */ @@ -13,13 +13,82 @@ /* Genode includes */ #include +#include /* base-hw includes */ #include +using namespace Genode; -void Genode::Thread_base::_thread_bootstrap() +Ram_dataspace_capability _main_thread_utcb_ds; + +Native_thread_id _main_thread_id; + +namespace Genode { Rm_session * env_context_area_rm_session(); } + + +/************************** + ** Native types support ** + **************************/ + +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; +} + + +/***************************** + ** Startup library support ** + *****************************/ + +void prepare_init_main_thread() +{ + using namespace Genode; + + /* + * Make data from the startup info persistantly available by copying it + * before the UTCB gets polluted by the following function calls. + */ + Native_utcb * const utcb = Thread_base::myself()->utcb(); + _main_thread_id = utcb->start_info()->thread_id(); + _main_thread_utcb_ds = + reinterpret_cap_cast(utcb->start_info()->utcb_ds()); +} + + +void prepare_reinit_main_thread() { prepare_init_main_thread(); } + + +/***************** + ** Thread_base ** + *****************/ + +void Thread_base::_thread_bootstrap() { Native_utcb * const utcb = Thread_base::myself()->utcb(); _tid.thread_id = utcb->start_info()->thread_id(); } + + +void Thread_base::_init_platform_thread(Type type) +{ + /* nothing platform specific to do if this is not a special thread */ + if (type == NORMAL) { return; } + + /* if we got reinitialized we have to get rid of the old UTCB */ + size_t const utcb_size = sizeof(Native_utcb); + addr_t const context_area = Native_config::context_area_virtual_base(); + addr_t const utcb_new = (addr_t)&_context->utcb - context_area; + Rm_session * const rm = env_context_area_rm_session(); + if (type == REINITIALIZED_MAIN) { rm->detach(utcb_new); } + + /* remap initial main-thread UTCB according to context-area spec */ + try { rm->attach_at(_main_thread_utcb_ds, utcb_new, utcb_size); } + catch(...) { + PERR("failed to re-map UTCB"); + while (1) ; + } + /* adjust initial object state in case of a main thread */ + tid().thread_id = _main_thread_id; +} diff --git a/base-hw/src/base/thread_support.cc b/base-hw/src/base/thread_support.cc index 226e4f3d2..2703183b6 100644 --- a/base-hw/src/base/thread_support.cc +++ b/base-hw/src/base/thread_support.cc @@ -26,9 +26,6 @@ namespace Genode { Rm_session * env_context_area_rm_session(); } ** Thread_base ** *****************/ -void Thread_base::_init_platform_thread() { } - - Native_utcb * Thread_base::utcb() { if (this) { return &_context->utcb; } diff --git a/base-hw/src/core/arm/crt0.s b/base-hw/src/core/arm/crt0.s index 6663893a6..83962d256 100644 --- a/base-hw/src/core/arm/crt0.s +++ b/base-hw/src/core/arm/crt0.s @@ -60,11 +60,6 @@ /* catch erroneous kernel return */ 3: b 3b - /* handle for dynamic symbol objects */ - .align 3 - .global __dso_handle - __dso_handle: .long 0 - .section .bss /* kernel stack */ diff --git a/base-hw/src/core/kernel/kernel.cc b/base-hw/src/core/kernel/kernel.cc index aab5efae4..4a7113e6a 100644 --- a/base-hw/src/core/kernel/kernel.cc +++ b/base-hw/src/core/kernel/kernel.cc @@ -41,6 +41,7 @@ using namespace Kernel; /* get core configuration */ extern Genode::Native_utcb * _main_thread_utcb; +extern Genode::Native_thread_id _main_thread_id; extern int _kernel_stack_high; extern "C" void CORE_MAIN(); @@ -249,6 +250,7 @@ extern "C" void kernel() /* start thread with stack pointer at the top of stack */ static Native_utcb utcb; static Thread t(Priority::MAX, "core"); + _main_thread_id = t.id(); _main_thread_utcb = &utcb; _main_thread_utcb->start_info()->init(t.id(), Genode::Native_capability()); t.ip = (addr_t)CORE_MAIN;; diff --git a/base-hw/src/core/thread.cc b/base-hw/src/core/thread.cc index 72cce376c..4a1b1c63b 100644 --- a/base-hw/src/core/thread.cc +++ b/base-hw/src/core/thread.cc @@ -53,7 +53,7 @@ void Thread_base::_thread_start() } -Thread_base::Thread_base(const char * const label, size_t const stack_size) +Thread_base::Thread_base(const char * const label, size_t const stack_size, Type) { _tid.platform_thread = new (platform()->core_mem_alloc()) Platform_thread(stack_size, Kernel::core_id(), label); diff --git a/base-hw/src/platform/main_bootstrap.cc b/base-hw/src/platform/main_bootstrap.cc deleted file mode 100644 index 1ba940bf3..000000000 --- a/base-hw/src/platform/main_bootstrap.cc +++ /dev/null @@ -1,42 +0,0 @@ -/* - * \brief Platform-specific helper functions for the _main() function - * \author Martin Stein - * \author Christian Helmuth - * \date 2010-09-13 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include - -using namespace Genode; - -namespace Genode { void platform_main_bootstrap(); } - -Native_thread_id _main_thread_id; - - -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() -{ - /* go save against multiple calls e.g. for programs with dynamic linker */ - static bool main_thread_id_valid = 0; - if (!main_thread_id_valid) { - Native_utcb * const utcb = Thread_base::myself()->utcb(); - _main_thread_id = utcb->start_info()->thread_id(); - main_thread_id_valid = 1; - } -} diff --git a/base-linux/include/rm_session/client.h b/base-linux/include/rm_session/client.h index c60cf07e4..42fcc5af9 100644 --- a/base-linux/include/rm_session/client.h +++ b/base-linux/include/rm_session/client.h @@ -14,6 +14,7 @@ #ifndef _INCLUDE__RM_SESSION__CLIENT_H_ #define _INCLUDE__RM_SESSION__CLIENT_H_ +/* Genode includes */ #include namespace Genode { @@ -22,6 +23,8 @@ namespace Genode { { Rm_session_capability const _cap; + typedef Rm_session Rpc_interface; + /** * Return pointer to locally implemented RM session * diff --git a/base-linux/lib/mk/base-common.mk b/base-linux/lib/mk/base-common.mk index b96cf8726..9ae7d5509 100644 --- a/base-linux/lib/mk/base-common.mk +++ b/base-linux/lib/mk/base-common.mk @@ -6,7 +6,6 @@ LIBS += syscall -SRC_CC += main_bootstrap.cc SRC_CC += ipc/ipc.cc SRC_CC += avl_tree/avl_tree.cc SRC_CC += allocator/slab.cc @@ -20,7 +19,7 @@ SRC_CC += lock/lock.cc SRC_CC += env/rm_session_mmap.cc env/debug.cc SRC_CC += signal/signal.cc signal/common.cc SRC_CC += server/server.cc server/common.cc -SRC_CC += thread/trace.cc +SRC_CC += thread/trace.cc thread/thread_env.cc INC_DIR += $(REP_DIR)/src/base/lock $(BASE_DIR)/src/base/lock INC_DIR += $(REP_DIR)/src/base/ipc @@ -28,6 +27,5 @@ INC_DIR += $(REP_DIR)/src/base/env $(BASE_DIR)/src/base/env INC_DIR += $(REP_DIR)/src/platform $(BASE_DIR)/src/platform INC_DIR += $(BASE_DIR)/src/base/thread -vpath main_bootstrap.cc $(REP_DIR)/src/platform -vpath %.cc $(REP_DIR)/src/base -vpath %.cc $(BASE_DIR)/src/base +vpath %.cc $(REP_DIR)/src/base +vpath %.cc $(BASE_DIR)/src/base diff --git a/base-linux/src/base/env/platform_env.cc b/base-linux/src/base/env/platform_env.cc index df6d7ec80..36318a992 100644 --- a/base-linux/src/base/env/platform_env.cc +++ b/base-linux/src/base/env/platform_env.cc @@ -154,6 +154,10 @@ Platform_env::Local_parent &Platform_env::_parent() } +void Platform_env::reinit(Native_capability::Dst, long) { } +void Platform_env::reinit_main_thread(Rm_session_capability &) { } + + Platform_env::Platform_env() : Platform_env_base(static_cap_cast(_parent().session("Env::ram_session", "")), diff --git a/base-linux/src/base/env/platform_env.h b/base-linux/src/base/env/platform_env.h index 0f74d7e61..7d3a18978 100644 --- a/base-linux/src/base/env/platform_env.h +++ b/base-linux/src/base/env/platform_env.h @@ -432,13 +432,15 @@ namespace Genode { */ ~Platform_env() { _parent().exit(0); } - /** - * Reload parent capability and reinitialize environment resources + /* + * Support functions for implementing fork on Noux. + * + * Not supported on Linux. + * + * See the documentation in 'base/src/base/env/platform_env.h' */ - void reload_parent_cap(Capability::Dst, long) - { - /* not supported on Linux */ - } + void reinit(Native_capability::Dst, long); + void reinit_main_thread(Rm_session_capability &); /************************************* diff --git a/base-linux/src/base/thread/thread_env.cc b/base-linux/src/base/thread/thread_env.cc new file mode 100644 index 000000000..20b4db054 --- /dev/null +++ b/base-linux/src/base/thread/thread_env.cc @@ -0,0 +1,49 @@ +/* + * \brief Thread-environment support common to all programs + * \author Martin Stein + * \date 2013-12-13 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include +#include + +using namespace Genode; + +extern addr_t * __initial_sp; + +/* + * Define 'lx_environ' pointer. + */ +char **lx_environ; + +/** + * Natively aligned memory location used in the lock implementation + */ +int main_thread_futex_counter __attribute__((aligned(sizeof(addr_t)))); + + +/***************************** + ** Startup library support ** + *****************************/ + +void prepare_init_main_thread() +{ + /* + * Initialize the 'lx_environ' pointer + * + * environ = &argv[argc + 1] + * __initial_sp[0] = argc (always 1 in Genode) + * __initial_sp[1] = argv[0] + * __initial_sp[2] = NULL + * __initial_sp[3] = environ + */ + lx_environ = (char**)&__initial_sp[3]; +} diff --git a/base-linux/src/base/thread/thread_linux.cc b/base-linux/src/base/thread/thread_linux.cc index 94046d1e1..ba8ad4d42 100644 --- a/base-linux/src/base/thread/thread_linux.cc +++ b/base-linux/src/base/thread/thread_linux.cc @@ -1,6 +1,7 @@ /* * \brief Implementation of the Thread API via Linux threads * \author Norman Feske + * \author Martin Stein * \date 2006-06-13 */ @@ -23,6 +24,7 @@ using namespace Genode; +extern int main_thread_futex_counter; static void empty_signal_handler(int) { } @@ -67,9 +69,16 @@ void Thread_base::_thread_start() } -void Thread_base::_init_platform_thread() +void Thread_base::_init_platform_thread(Type type) { - _thread_cap = env()->cpu_session()->create_thread(_context->name); + /* for normal threads create an object at the CPU session */ + if (type == NORMAL) { + _thread_cap = env()->cpu_session()->create_thread(_context->name); + return; + } + /* adjust initial object state for main threads */ + tid().futex_counter = main_thread_futex_counter; + _thread_cap = env()->parent()->main_thread_cap(); } diff --git a/base-linux/src/core/thread_linux.cc b/base-linux/src/core/thread_linux.cc index 8e1ddcc94..b4ae6dd45 100644 --- a/base-linux/src/core/thread_linux.cc +++ b/base-linux/src/core/thread_linux.cc @@ -46,7 +46,7 @@ void Thread_base::_thread_start() } -void Thread_base::_init_platform_thread() { } +void Thread_base::_init_platform_thread(Type) { } void Thread_base::_deinit_platform_thread() { } diff --git a/base-linux/src/platform/lx_hybrid.cc b/base-linux/src/platform/lx_hybrid.cc index cf70b1144..8fb9f220e 100644 --- a/base-linux/src/platform/lx_hybrid.cc +++ b/base-linux/src/platform/lx_hybrid.cc @@ -401,7 +401,7 @@ void Thread_base::join() } -Thread_base::Thread_base(const char *name, size_t stack_size) +Thread_base::Thread_base(const char *name, size_t stack_size, Type) { _tid.meta_data = new (env()->heap()) Thread_meta_data_created(this); diff --git a/base-linux/src/platform/main_bootstrap.cc b/base-linux/src/platform/main_bootstrap.cc deleted file mode 100644 index 67cfecf41..000000000 --- a/base-linux/src/platform/main_bootstrap.cc +++ /dev/null @@ -1,61 +0,0 @@ -/* - * \brief Platform-specific helper functions for the _main() function - * \author Christian Prochaska - * \author Christian Helmuth - * \date 2009-08-05 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include - - -namespace Genode { void platform_main_bootstrap(); } - - -/* - * Define 'lx_environ' pointer. - */ -char **lx_environ; - - -/** - * Natively aligned memory location used in the lock implementation - */ -int main_thread_futex_counter __attribute__((aligned(sizeof(Genode::addr_t)))); - - -/** - * Initial value of SP register (in crt0) - */ -extern Genode::addr_t *__initial_sp; - - -/** - * Platform-specific bootstrap - */ -void Genode::platform_main_bootstrap() -{ - static struct Bootstrap - { - Bootstrap() - { - /* - * Initialize the 'lx_environ' pointer - * - * environ = &argv[argc + 1] - * __initial_sp[0] = argc (always 1 in Genode) - * __initial_sp[1] = argv[0] - * __initial_sp[2] = NULL - * __initial_sp[3] = environ - */ - lx_environ = (char**)&__initial_sp[3]; - } - } bootstrap; -} diff --git a/base-nova/include/base/cap_map.h b/base-nova/include/base/cap_map.h index 9493b6d30..31c8d3a15 100644 --- a/base-nova/include/base/cap_map.h +++ b/base-nova/include/base/cap_map.h @@ -102,7 +102,7 @@ namespace Genode { }; - class Capability_map : Noncopyable + class Capability_map : private Noncopyable { private: diff --git a/base-nova/lib/mk/base-common.inc b/base-nova/lib/mk/base-common.inc index 99f94cfec..66d3581f6 100644 --- a/base-nova/lib/mk/base-common.inc +++ b/base-nova/lib/mk/base-common.inc @@ -6,7 +6,6 @@ LIBS += cxx startup -SRC_CC += main_bootstrap.cc SRC_CC += ipc/ipc.cc ipc/pager.cc SRC_CC += avl_tree/avl_tree.cc SRC_CC += allocator/slab.cc @@ -26,8 +25,7 @@ INC_DIR += $(REP_DIR)/src/base/lock INC_DIR += $(BASE_DIR)/src/base/lock INC_DIR += $(BASE_DIR)/src/base/thread -vpath main_bootstrap.cc $(REP_DIR)/src/platform -vpath %.cc $(REP_DIR)/src/base -vpath %.cc $(BASE_DIR)/src/base +vpath %.cc $(REP_DIR)/src/base +vpath %.cc $(BASE_DIR)/src/base # vi: set ft=make : diff --git a/base-nova/lib/mk/base.mk b/base-nova/lib/mk/base.mk index 97c8cc911..a59981a15 100644 --- a/base-nova/lib/mk/base.mk +++ b/base-nova/lib/mk/base.mk @@ -7,8 +7,7 @@ LIBS += base-common SRC_CC += console/log_console.cc -SRC_CC += env/env.cc env/main_thread.cc \ - env/context_area.cc env/reinitialize.cc +SRC_CC += env/env.cc env/context_area.cc env/reinitialize.cc SRC_CC += thread/thread_nova.cc INC_DIR += $(BASE_DIR)/src/base/env diff --git a/base-nova/src/base/env/main_thread.cc b/base-nova/src/base/env/main_thread.cc deleted file mode 100644 index 5d944042b..000000000 --- a/base-nova/src/base/env/main_thread.cc +++ /dev/null @@ -1,31 +0,0 @@ -/* - * \brief Information about the main thread - * \author Norman Feske - * \author Alexander Boettcher - * \date 2010-01-19 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include - -/* NOVA includes */ -#include - -using namespace Genode; - -Native_utcb *main_thread_utcb() -{ - return reinterpret_cast( - Native_config::context_area_virtual_base() + - Native_config::context_area_virtual_size() - Nova::PAGE_SIZE_BYTE); -} - - -addr_t main_thread_running_semaphore() { return Nova::SM_SEL_EC; } diff --git a/base-nova/src/base/thread/thread_context.cc b/base-nova/src/base/thread/thread_context.cc index 26e3d6972..fc5c97765 100644 --- a/base-nova/src/base/thread/thread_context.cc +++ b/base-nova/src/base/thread/thread_context.cc @@ -1,6 +1,8 @@ /* * \brief Thread-context specific part of the thread library * \author Norman Feske + * \author Alexander Boettcher + * \author Martin Stein * \date 2010-01-19 * * This part of the thread library is required by the IPC framework @@ -14,13 +16,98 @@ * under the terms of the GNU General Public License version 2. */ +/* Genode includes */ +#include +#include #include +/* base-nova includes */ +#include + using namespace Genode; +extern addr_t __initial_sp; -Native_utcb *main_thread_utcb(); +/******************* + ** local helpers ** + *******************/ + +Native_utcb * main_thread_utcb() +{ + using namespace Genode; + return reinterpret_cast( + Native_config::context_area_virtual_base() + + Native_config::context_virtual_size() - Nova::PAGE_SIZE_BYTE); +} + + +addr_t main_thread_running_semaphore() { return Nova::SM_SEL_EC; } + + +class Initial_cap_range : public Cap_range +{ + private: + + enum { CAP_RANGE_START = 4096 }; + + public: + + Initial_cap_range() : Cap_range(CAP_RANGE_START) { } +}; + + +Initial_cap_range * initial_cap_range() +{ + static Initial_cap_range s; + return &s; +} + + +/***************************** + ** Startup library support ** + *****************************/ + +void prepare_init_main_thread() +{ + using namespace Genode; + + cap_map()->insert(initial_cap_range()); + + /* for Core we can't perform the following code so early */ + if (!__initial_sp) { + + enum { CAP_RANGES = 16 }; + + unsigned index = initial_cap_range()->base() + + initial_cap_range()->elements(); + + static char local[CAP_RANGES][sizeof(Cap_range)]; + + for (unsigned i = 0; i < CAP_RANGES; i++) { + + Cap_range * range = reinterpret_cast(local[i]); + *range = Cap_range(index); + + cap_map()->insert(range); + + index = range->base() + range->elements(); + } + } +} + +void prepare_reinit_main_thread() +{ + using namespace Genode; + construct_at(cap_map()); + construct_at(initial_cap_range()); + prepare_init_main_thread(); +} + + +/***************** + ** Thread_base ** + *****************/ Native_utcb *Thread_base::utcb() { @@ -34,5 +121,3 @@ Native_utcb *Thread_base::utcb() return &_context->utcb; } - - diff --git a/base-nova/src/base/thread/thread_nova.cc b/base-nova/src/base/thread/thread_nova.cc index 9aff42922..575cb0bf0 100644 --- a/base-nova/src/base/thread/thread_nova.cc +++ b/base-nova/src/base/thread/thread_nova.cc @@ -66,7 +66,7 @@ void Thread_base::_thread_start() ** Thread base ** *****************/ -void Thread_base::_init_platform_thread() +void Thread_base::_init_platform_thread(Type type) { using namespace Nova; @@ -74,7 +74,15 @@ void Thread_base::_init_platform_thread() * Allocate capability selectors for the thread's execution context, * running semaphore and exception handler portals. */ - _tid.ec_sel = Native_thread::INVALID_INDEX; + _tid.ec_sel = Native_thread::INVALID_INDEX; + + /* for main threads the member initialization differs */ + if (type == MAIN || type == REINITIALIZED_MAIN) { + _thread_cap = env()->parent()->main_thread_cap(); + _tid.exc_pt_sel = 0; + return; + } + _tid.exc_pt_sel = cap_map()->insert(NUM_INITIAL_PT_LOG2); if (_tid.exc_pt_sel == Native_thread::INVALID_INDEX) throw Cpu_session::Thread_creation_failed(); diff --git a/base-nova/src/core/platform_thread.cc b/base-nova/src/core/platform_thread.cc index 49d7d71dd..db33e6c73 100644 --- a/base-nova/src/core/platform_thread.cc +++ b/base-nova/src/core/platform_thread.cc @@ -106,7 +106,7 @@ int Platform_thread::start(void *ip, void *sp) if (!is_vcpu()) { pd_utcb = Native_config::context_area_virtual_base() + - Native_config::context_area_virtual_size() - get_page_size(); + Native_config::context_virtual_size() - get_page_size(); addr_t remap_src[] = { _pd->parent_pt_sel() }; addr_t remap_dst[] = { PT_SEL_PARENT }; diff --git a/base-nova/src/core/target.inc b/base-nova/src/core/target.inc index 3939d0bb8..9d0a1cece 100644 --- a/base-nova/src/core/target.inc +++ b/base-nova/src/core/target.inc @@ -27,7 +27,6 @@ SRC_CC = main.cc \ signal_source_component.cc \ trace_session_component.cc \ core_rm_session.cc \ - main_thread.cc \ context_area.cc \ echo.cc \ dump_alloc.cc \ @@ -59,5 +58,4 @@ vpath platform_services.cc $(GEN_CORE_DIR)/x86 vpath context_area.cc $(GEN_CORE_DIR) vpath core_printf.cc $(BASE_DIR)/src/base/console vpath %.cc $(REP_DIR)/src/core -vpath main_thread.cc $(REP_DIR)/src/base/env vpath pager.cc $(REP_DIR)/src/base/pager diff --git a/base-nova/src/core/thread_start.cc b/base-nova/src/core/thread_start.cc index 631af0fde..51e9ad8f2 100644 --- a/base-nova/src/core/thread_start.cc +++ b/base-nova/src/core/thread_start.cc @@ -27,7 +27,7 @@ using namespace Genode; -void Thread_base::_init_platform_thread() +void Thread_base::_init_platform_thread(Type type) { /* * This function is called for constructing server activations and pager @@ -36,6 +36,20 @@ void Thread_base::_init_platform_thread() */ using namespace Nova; + if (type == MAIN) + { + /* set EC selector according to NOVA spec */ + _tid.ec_sel = Platform_pd::pd_core_sel() + 1; + + /* + * Exception base of first thread in core is 0. We have to set + * it here so that Thread_base code finds the semaphore of the + * main thread. + */ + _tid.exc_pt_sel = 0; + + return; + } _tid.ec_sel = cap_map()->insert(1); _tid.exc_pt_sel = cap_map()->insert(NUM_INITIAL_PT_LOG2); addr_t pd_sel = Platform_pd::pd_core_sel(); diff --git a/base-nova/src/platform/main_bootstrap.cc b/base-nova/src/platform/main_bootstrap.cc deleted file mode 100644 index 2d6ce3f79..000000000 --- a/base-nova/src/platform/main_bootstrap.cc +++ /dev/null @@ -1,71 +0,0 @@ -/* - * \brief Platform-specific helper functions for the _main() function - * \author Norman Feske - * \author Sebastian Sumpf - * \date 2009-12-28 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include - -#include - -namespace Genode { void platform_main_bootstrap(); } - -enum { CAP_RANGE_START = 4096 }; - -Genode::Cap_range * initial_range() -{ - static Genode::Cap_range range(CAP_RANGE_START); - return ⦥ -} - -extern "C" Genode::addr_t __initial_sp; - -void Genode::platform_main_bootstrap() -{ - static struct Bootstrap - { - Bootstrap() - { - cap_map()->insert(initial_range()); - - /* for Core we can't perform the following code so early */ - if (__initial_sp) - return; - - unsigned index = initial_range()->base() + initial_range()->elements(); - -/* - printf("initial selector range [0x%8lx:0x%8lx)\n", - initial_range()->base(), initial_range()->base() + - initial_range()->elements()); -*/ - - for (unsigned i = 0; i < 16; i++) { - - Ram_dataspace_capability ds = env()->ram_session()->alloc(4096); - addr_t local = env()->rm_session()->attach(ds); - - Cap_range * range = reinterpret_cast(local); - *range = Cap_range(index); - - cap_map()->insert(range); - -/* - printf("add cap selector range [0x%8lx:0x%8lx)\n", - range->base(), range->base() + range->elements()); -*/ - - index = range->base() + range->elements(); - } - } - } bootstrap; -} diff --git a/base-okl4/lib/mk/base-common.mk b/base-okl4/lib/mk/base-common.mk index 07c390ace..c410304b3 100644 --- a/base-okl4/lib/mk/base-common.mk +++ b/base-okl4/lib/mk/base-common.mk @@ -6,7 +6,7 @@ LIBS += cxx startup -SRC_CC += cap_copy.cc main_bootstrap.cc +SRC_CC += cap_copy.cc SRC_CC += ipc/ipc.cc ipc/pager.cc ipc/ipc_marshal_cap.cc SRC_CC += pager/pager.cc pager/common.cc SRC_CC += avl_tree/avl_tree.cc @@ -25,7 +25,6 @@ SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc INC_DIR += $(REP_DIR)/src/base/lock INC_DIR += $(BASE_DIR)/src/base/thread -vpath main_bootstrap.cc $(REP_DIR)/src/platform -vpath cap_copy.cc $(BASE_DIR)/src/platform -vpath %.cc $(REP_DIR)/src/base -vpath %.cc $(BASE_DIR)/src/base +vpath cap_copy.cc $(BASE_DIR)/src/platform +vpath %.cc $(REP_DIR)/src/base +vpath %.cc $(BASE_DIR)/src/base diff --git a/base-okl4/src/base/thread/thread_bootstrap.cc b/base-okl4/src/base/thread/thread_bootstrap.cc index 4807a7692..e0cdb88d1 100644 --- a/base-okl4/src/base/thread/thread_bootstrap.cc +++ b/base-okl4/src/base/thread/thread_bootstrap.cc @@ -1,6 +1,7 @@ /* * \brief Default thread bootstrap code * \author Norman Feske + * \author Martin Stein * \date 2009-04-02 */ @@ -11,19 +12,74 @@ * under the terms of the GNU General Public License version 2. */ +/* Genode includes */ #include -namespace Okl4 { extern "C" { -#include -#include -} } - -namespace Okl4 { - extern L4_Word_t copy_uregister_to_utcb(void); +/* OKL4 includes */ +namespace Okl4 +{ + extern "C" { + #include + #include + } } +Genode::Native_thread_id main_thread_tid; + + +/******************* + ** local helpers ** + *******************/ + +namespace Okl4 +{ + /* + * Read global thread ID from user-defined handle and store it + * into a designated UTCB entry. + */ + L4_Word_t copy_uregister_to_utcb() + { + using namespace Okl4; + + L4_Word_t my_global_id = L4_UserDefinedHandle(); + __L4_TCR_Set_ThreadWord(Genode::UTCB_TCR_THREAD_WORD_MYSELF, + my_global_id); + return my_global_id; + } +} + + +/***************************** + ** Startup library support ** + *****************************/ + +void prepare_init_main_thread() +{ + /* copy thread ID to utcb */ + main_thread_tid.raw = Okl4::copy_uregister_to_utcb(); + + /* adjust main-thread ID if this is the main thread of core */ + if (main_thread_tid.raw == 0) { + main_thread_tid.raw = Okl4::L4_rootserver.raw; + } +} + + +void prepare_reinit_main_thread() { prepare_init_main_thread(); } + + +/***************** + ** Thread_base ** + *****************/ void Genode::Thread_base::_thread_bootstrap() { _tid.l4id.raw = Okl4::copy_uregister_to_utcb(); } + + +void Genode::Thread_base::_init_platform_thread(Type type) +{ + if (type == NORMAL) { return; } + _tid.l4id.raw = main_thread_tid.raw; +} diff --git a/base-okl4/src/core/thread_start.cc b/base-okl4/src/core/thread_start.cc index 7649b24f3..9a8d89a46 100644 --- a/base-okl4/src/core/thread_start.cc +++ b/base-okl4/src/core/thread_start.cc @@ -50,9 +50,6 @@ void Thread_base::cancel_blocking() } -void Thread_base::_init_platform_thread() { } - - void Thread_base::_deinit_platform_thread() { /* destruct platform thread */ diff --git a/base-okl4/src/platform/main_bootstrap.cc b/base-okl4/src/platform/main_bootstrap.cc deleted file mode 100644 index b328ce4f8..000000000 --- a/base-okl4/src/platform/main_bootstrap.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* - * \brief Platform-specific helper functions for the _main() function - * \author Christian Prochaska - * \author Christian Helmuth - * \date 2009-08-05 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include - -/* OKL4-specific includes and definitions */ -namespace Okl4 { extern "C" { -#include -#include -} } - - -namespace Okl4 { - - /* - * Read global thread ID from user-defined handle and store it - * into a designated UTCB entry. - */ - L4_Word_t copy_uregister_to_utcb() - { - using namespace Okl4; - - L4_Word_t my_global_id = L4_UserDefinedHandle(); - __L4_TCR_Set_ThreadWord(Genode::UTCB_TCR_THREAD_WORD_MYSELF, - my_global_id); - return my_global_id; - } -} - - -namespace Genode { void platform_main_bootstrap(); } - - -Genode::Native_thread_id main_thread_tid; - - -void Genode::platform_main_bootstrap() -{ - static struct Bootstrap - { - Bootstrap() - { - /* copy thread ID to utcb */ - main_thread_tid.raw = Okl4::copy_uregister_to_utcb(); - - if (main_thread_tid.raw == 0) /* core */ - main_thread_tid.raw = Okl4::L4_rootserver.raw; - } - } bootstrap; -} diff --git a/base-pistachio/lib/mk/base-common.mk b/base-pistachio/lib/mk/base-common.mk index 141e0dd0c..320e7540b 100644 --- a/base-pistachio/lib/mk/base-common.mk +++ b/base-pistachio/lib/mk/base-common.mk @@ -6,7 +6,7 @@ LIBS += cxx startup -SRC_CC += cap_copy.cc main_bootstrap.cc +SRC_CC += cap_copy.cc SRC_CC += ipc/ipc.cc ipc/pager.cc ipc/ipc_marshal_cap.cc SRC_CC += pager/pager.cc pager/common.cc SRC_CC += avl_tree/avl_tree.cc @@ -25,7 +25,6 @@ SRC_CC += thread/thread.cc thread/trace.cc thread/thread_bootstrap.cc INC_DIR += $(REP_DIR)/src/base/lock INC_DIR += $(BASE_DIR)/src/base/thread -vpath main_bootstrap.cc $(REP_DIR)/src/platform -vpath cap_copy.cc $(BASE_DIR)/src/platform -vpath %.cc $(REP_DIR)/src/base -vpath %.cc $(BASE_DIR)/src/base +vpath cap_copy.cc $(BASE_DIR)/src/platform +vpath %.cc $(REP_DIR)/src/base +vpath %.cc $(BASE_DIR)/src/base diff --git a/base-pistachio/src/base/thread/thread_bootstrap.cc b/base-pistachio/src/base/thread/thread_bootstrap.cc index 2bc0cbd57..f6941728f 100644 --- a/base-pistachio/src/base/thread/thread_bootstrap.cc +++ b/base-pistachio/src/base/thread/thread_bootstrap.cc @@ -15,11 +15,38 @@ #include /* Pistachio includes */ -namespace Pistachio { -#include +namespace Pistachio +{ + #include } +Genode::Native_thread_id main_thread_tid; + + +/***************************** + ** Startup library support ** + *****************************/ + +void prepare_init_main_thread() +{ + main_thread_tid = Pistachio::L4_Myself(); +} + +void prepare_reinit_main_thread() { prepare_init_main_thread(); } + + +/***************** + ** Thread_base ** + *****************/ + void Genode::Thread_base::_thread_bootstrap() { _tid.l4id = Pistachio::L4_Myself(); } + + +void Genode::Thread_base::_init_platform_thread(Type type) +{ + if (type == NORMAL) { return; } + _tid.l4id = main_thread_tid; +} diff --git a/base-pistachio/src/core/thread_start.cc b/base-pistachio/src/core/thread_start.cc index b2d065e7f..666edb8f9 100644 --- a/base-pistachio/src/core/thread_start.cc +++ b/base-pistachio/src/core/thread_start.cc @@ -53,9 +53,6 @@ void Thread_base::cancel_blocking() } -void Thread_base::_init_platform_thread() { } - - void Thread_base::_deinit_platform_thread() { /* destruct platform thread */ diff --git a/base-pistachio/src/platform/main_bootstrap.cc b/base-pistachio/src/platform/main_bootstrap.cc deleted file mode 100644 index 5d14099b1..000000000 --- a/base-pistachio/src/platform/main_bootstrap.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * \brief Platform-specific helper functions for the _main() function - * \author Christian Prochaska - * \author Christian Helmuth - * \date 2009-08-05 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include - -/* Pistachio includes */ -namespace Pistachio { -#include -} - - -namespace Genode { void platform_main_bootstrap(); } - - -Genode::Native_thread_id main_thread_tid; - - -void Genode::platform_main_bootstrap() -{ - static struct Bootstrap - { - Bootstrap() { main_thread_tid = Pistachio::L4_Myself(); } - } bootstrap; -} diff --git a/base/include/base/env.h b/base/include/base/env.h index 80e48e436..733550ade 100644 --- a/base/include/base/env.h +++ b/base/include/base/env.h @@ -73,20 +73,6 @@ namespace Genode { * Heap backed by the ram_session of the environment. */ virtual Allocator *heap() = 0; - - /** - * Reload parent capability and reinitialize environment resources - * - * This function is solely used for implementing fork semantics. - * After forking a process, the new child process is executed - * within a copy of the address space of the forking process. - * Thereby, the new process inherits the original 'env' object of - * the forking process, which is meaningless in the context of the - * new process. By calling this function, the new process is able - * to reinitialize its 'env' with meaningful capabilities obtained - * via its updated parent capability. - */ - virtual void reload_parent_cap(Capability::Dst, long) = 0; }; extern Env *env(); diff --git a/base/include/base/thread.h b/base/include/base/thread.h index 47db0df41..4f1799a7b 100644 --- a/base/include/base/thread.h +++ b/base/include/base/thread.h @@ -185,11 +185,13 @@ namespace Genode { /** * Allocate thread context for specified thread * - * \param thread thread for which to allocate the new context - * \return virtual address of new thread context, or - * 0 if the allocation failed + * \param thread thread for which to allocate the new context + * \param main_thread wether to alloc for the main thread + * + * \return virtual address of new thread context, or + * 0 if the allocation failed */ - Context *alloc(Thread_base *thread); + Context *alloc(Thread_base *thread, bool main_thread); /** * Release thread context @@ -224,8 +226,11 @@ namespace Genode { /** * Allocate and locally attach a new thread context + * + * \param stack_size size of this threads stack + * \param main_thread wether this is the main thread */ - Context *_alloc_context(size_t stack_size); + Context *_alloc_context(size_t stack_size, bool main_thread); /** * Detach and release thread context of the thread @@ -246,11 +251,6 @@ namespace Genode { */ static void _thread_start(); - /** - * Hook for platform-specific constructor supplements - */ - void _init_platform_thread(); - /** * Hook for platform-specific destructor supplements */ @@ -285,6 +285,14 @@ namespace Genode { */ Genode::Lock _join_lock; + /** + * Thread type + * + * Some threads need special treatment at construction. This enum + * is solely used to distinguish them at construction. + */ + enum Type { NORMAL, MAIN, REINITIALIZED_MAIN }; + private: Trace::Logger _trace_logger; @@ -296,6 +304,13 @@ namespace Genode { */ static Trace::Logger *_logger(); + /** + * Hook for platform-specific constructor supplements + * + * \param main_thread wether this is the main thread + */ + void _init_platform_thread(Type type); + public: /** @@ -303,6 +318,7 @@ namespace Genode { * * \param name thread name for debugging * \param stack_size stack size + * \param type enables selection of special construction * * \throw Stack_too_large * \throw Stack_alloc_failed @@ -313,8 +329,14 @@ namespace Genode { * stack size is internally used by the framework for storing * thread-context information such as the thread's name (see * 'struct Context'). + * + * FIXME: With type = Forked_main_thread the whole + * Context::_alloc_context call gets skipped but we should + * at least set Context::ds_cap in a way that it references + * the dataspace of the already attached stack. */ - Thread_base(const char *name, size_t stack_size); + Thread_base(const char *name, size_t stack_size, + Type type = NORMAL); /** * Destructor @@ -448,9 +470,10 @@ namespace Genode { * Constructor * * \param name thread name (for debugging) + * \param type enables selection of special construction */ - explicit Thread(const char *name) - : Thread_base(name, STACK_SIZE) { } + explicit Thread(const char *name, Type type = NORMAL) + : Thread_base(name, STACK_SIZE, type) { } }; } diff --git a/base/lib/mk/startup.inc b/base/lib/mk/startup.inc index 21a8aecb1..06c1d2bbb 100644 --- a/base/lib/mk/startup.inc +++ b/base/lib/mk/startup.inc @@ -1,8 +1,10 @@ SRC_S += crt0.s SRC_CC += _main.cc +SRC_CC += init_main_thread.cc REP_INC_DIR += src/platform LIBS += syscall vpath _main.cc $(BASE_DIR)/src/platform +vpath init_main_thread.cc $(BASE_DIR)/src/platform diff --git a/base/mk/dep_lib.mk b/base/mk/dep_lib.mk index e9035303b..da0504669 100644 --- a/base/mk/dep_lib.mk +++ b/base/mk/dep_lib.mk @@ -84,6 +84,15 @@ LIBS += $(BASE_LIBS) else LIBS := $(filter-out $(BASE_LIBS),$(LIBS)) LIBS += $(DYNAMIC_LINKER) + +# +# Ensure that startup_dyn is build for the dynamic programs that depend on a +# shared library. They add it to their dependencies as replacement for the +# static-case startup as soon as they recognize that they are dynamic. +# The current library in contrast filters-out startup_dyn from its +# dependencies before they get merged. +# +LIBS += startup_dyn endif diff --git a/base/mk/lib.mk b/base/mk/lib.mk index 018520dd3..296f7fdb8 100644 --- a/base/mk/lib.mk +++ b/base/mk/lib.mk @@ -125,9 +125,15 @@ $(LIB_A): $(OBJECTS) $(VERBOSE)$(AR) -rc $@ $(OBJECTS) # -# Prevent linkage of startup code against shared libraries except for ld.lib.so +# Prevent linkage of startup_dyn as we added it only in order that it gets +# build for the dynamic programs. # ifdef SHARED_LIB +override DEPS := $(filter-out startup_dyn.lib,$(DEPS)) + +# +# Prevent linkage of startup code against shared libraries except for ld.lib.so +# ifneq ($(LIB),ld) override DEPS := $(filter-out startup.lib,$(DEPS)) endif diff --git a/base/mk/prg.mk b/base/mk/prg.mk index 7e8b17a29..898a074d1 100644 --- a/base/mk/prg.mk +++ b/base/mk/prg.mk @@ -120,9 +120,13 @@ LD_CMD += -Wl,--dynamic-linker=$(DYNAMIC_LINKER).lib.so \ -Wl,--eh-frame-hdr # -# Filter out the base libraries since they will be provided by the ldso.library +# Filter out the base libraries since they will be provided by the LDSO +# library and the startup library as the CRT0 part of program startup is +# done by LDSO already. As replacement for the startup library startup_dyn +# is used. The startup_dyn build is triggered by any shared library without +# merging it to the library. # -FILTER_DEPS := $(filter-out $(BASE_LIBS),$(DEPS:.lib=)) +FILTER_DEPS := $(filter-out $(BASE_LIBS) startup,$(DEPS:.lib=)) startup_dyn SHARED_LIBS += $(LIB_CACHE_DIR)/$(DYNAMIC_LINKER)/$(DYNAMIC_LINKER).lib.so # diff --git a/base/src/base/env/platform_env.h b/base/src/base/env/platform_env.h index 375574958..0cbabbb44 100644 --- a/base/src/base/env/platform_env.h +++ b/base/src/base/env/platform_env.h @@ -23,7 +23,7 @@ /* Genode includes */ #include #include -#include +#include /* local includes */ #include @@ -36,7 +36,9 @@ namespace Genode { } -struct Genode::Expanding_rm_session_client : Upgradeable_client +struct Genode::Expanding_rm_session_client +: + Upgradeable_client { Expanding_rm_session_client(Rm_session_capability cap) : Upgradeable_client(cap) { } @@ -139,7 +141,29 @@ class Genode::Platform_env : public Genode::Env, public Emergency_ram_reserve _emergency_ram_ds(_resources.ram.alloc(_emergency_ram_size())) { } - void reload_parent_cap(Native_capability::Dst, long); + /** + * Reload parent capability and reinitialize environment resources + * + * This function is solely used for implementing fork semantics. + * After forking a process, the new child process is executed + * within a copy of the address space of the forking process. + * Thereby, the new process inherits the original 'env' object of + * the forking process, which is meaningless in the context of the + * new process. By calling this function, the new process is able + * to reinitialize its 'env' with meaningful capabilities obtained + * via its updated parent capability. + */ + void reinit(Native_capability::Dst, long); + + /** + * Reinitialize main-thread object + * + * \param context_area_rm new RM session of the context area + * + * This function is solely used for implementing fork semantics + * as provided by the Noux environment. + */ + void reinit_main_thread(Rm_session_capability &); /************************************* diff --git a/base/src/base/env/reinitialize.cc b/base/src/base/env/reinitialize.cc index aa67e6f65..db8636c79 100644 --- a/base/src/base/env/reinitialize.cc +++ b/base/src/base/env/reinitialize.cc @@ -1,6 +1,7 @@ /* * \brief Environment reinitialization * \author Norman Feske + * \author Martin Stein * \date 2012-02-16 */ @@ -11,12 +12,28 @@ * under the terms of the GNU General Public License version 2. */ +/* env includes */ #include + +/* Genode includes */ +#include #include +#include + +void prepare_reinit_main_thread(); + +void reinit_main_thread(); + +namespace Genode +{ + extern bool inhibit_tracing; + + Rm_session * env_context_area_rm_session(); +} -void Genode::Platform_env::reload_parent_cap(Native_capability::Dst dst, - long local_name) +void Genode::Platform_env::reinit(Native_capability::Dst dst, + long local_name) { /* * This function is unused during the normal operation of Genode. It is @@ -32,21 +49,26 @@ void Genode::Platform_env::reload_parent_cap(Native_capability::Dst dst, * provided by the actual parent. */ + /* avoid RPCs by the tracing framework as long as we have no valid env */ + inhibit_tracing = true; + + /* do platform specific preparation */ + prepare_reinit_main_thread(); + /* * Patch new parent capability into the original location as specified by * the linker script. */ Native_capability::Raw *raw = (Native_capability::Raw *)(&_parent_cap); - - raw->dst = dst; - raw->local_name = local_name; + raw->dst = dst; + raw->local_name = local_name; /* * Re-initialize 'Platform_env' members */ - static_cast(_parent_client) = Parent_client(Genode::parent_cap()); - - _resources = Resources(_parent_client); + Expanding_parent_client * const p = &_parent_client; + construct_at(p, parent_cap(), *this); + construct_at(&_resources, _parent_client); /* * Keep information about dynamically allocated memory but use the new @@ -57,3 +79,20 @@ void Genode::Platform_env::reload_parent_cap(Native_capability::Dst dst, */ _heap.reassign_resources(&_resources.ram, &_resources.rm); } + + +void +Genode::Platform_env:: +reinit_main_thread(Rm_session_capability & context_area_rm) +{ + /* reinitialize context area RM session */ + Rm_session * const rms = env_context_area_rm_session(); + Rm_session_client * const rmc = dynamic_cast(rms); + construct_at(rmc, context_area_rm); + + /* re-enable tracing */ + inhibit_tracing = false; + + /* reinitialize main-thread object */ + ::reinit_main_thread(); +} diff --git a/base/src/base/thread/thread.cc b/base/src/base/thread/thread.cc index 8c9092689..43ccda3c0 100644 --- a/base/src/base/thread/thread.cc +++ b/base/src/base/thread/thread.cc @@ -51,24 +51,34 @@ addr_t Thread_base::Context_allocator::addr_to_base(void *addr) size_t Thread_base::Context_allocator::base_to_idx(addr_t base) { - return (base - Native_config::context_area_virtual_base()) / - Native_config::context_virtual_size(); + /* the first context isn't managed through the indices */ + return ((base - Native_config::context_area_virtual_base()) / + Native_config::context_virtual_size()) - 1; } addr_t Thread_base::Context_allocator::idx_to_base(size_t idx) { + /* the first context isn't managed through the indices */ return Native_config::context_area_virtual_base() + - idx * Native_config::context_virtual_size(); + (idx + 1) * Native_config::context_virtual_size(); } -Thread_base::Context *Thread_base::Context_allocator::alloc(Thread_base *thread_base) +Thread_base::Context * +Thread_base::Context_allocator::alloc(Thread_base *thread_base, bool main_thread) { Lock::Guard _lock_guard(_threads_lock); - try { - return base_to_context(idx_to_base(_alloc.alloc())); + addr_t base; + if (main_thread) { + /* the main-thread context isn't managed by '_alloc' */ + base = Native_config::context_area_virtual_base(); + } else { + /* contexts besides main-thread context are managed by '_alloc' */ + base = idx_to_base(_alloc.alloc()); + } + return base_to_context(base); } catch(Bit_allocator::Out_of_indices) { return 0; } @@ -78,8 +88,13 @@ Thread_base::Context *Thread_base::Context_allocator::alloc(Thread_base *thread_ void Thread_base::Context_allocator::free(Context *context) { Lock::Guard _lock_guard(_threads_lock); + addr_t const base = addr_to_base(context); - _alloc.free(base_to_idx(addr_to_base(context))); + /* the main-thread context isn't managed by '_alloc' */ + if (base == Native_config::context_area_virtual_base()) { return; } + + /* contexts besides main-thread context are managed by '_alloc' */ + _alloc.free(base_to_idx(base)); } @@ -94,7 +109,8 @@ Thread_base::Context_allocator *Thread_base::_context_allocator() } -Thread_base::Context *Thread_base::_alloc_context(size_t stack_size) +Thread_base::Context * +Thread_base::_alloc_context(size_t stack_size, bool main_thread) { /* * Synchronize context list when creating new threads from multiple threads @@ -105,7 +121,7 @@ Thread_base::Context *Thread_base::_alloc_context(size_t stack_size) Lock::Guard _lock_guard(alloc_lock); /* allocate thread context */ - Context *context = _context_allocator()->alloc(this); + Context *context = _context_allocator()->alloc(this, main_thread); if (!context) throw Context_alloc_failed(); @@ -213,7 +229,7 @@ void Thread_base::join() void* Thread_base::alloc_secondary_stack(char const *name, size_t stack_size) { - Context *context = _alloc_context(stack_size); + Context *context = _alloc_context(stack_size, false); strncpy(context->name, name, sizeof(context->name)); return (void *)context->stack_top(); } @@ -226,13 +242,14 @@ void Thread_base::free_secondary_stack(void* stack_addr) } -Thread_base::Thread_base(const char *name, size_t stack_size) +Thread_base::Thread_base(const char *name, size_t stack_size, Type type) : - _context(_alloc_context(stack_size)), + _context(type == REINITIALIZED_MAIN ? + _context : _alloc_context(stack_size, type == MAIN)), _join_lock(Lock::LOCKED) { strncpy(_context->name, name, sizeof(_context->name)); - _init_platform_thread(); + _init_platform_thread(type); } diff --git a/base/src/base/thread/thread_start.cc b/base/src/base/thread/thread_start.cc index d17363d47..443390920 100644 --- a/base/src/base/thread/thread_start.cc +++ b/base/src/base/thread/thread_start.cc @@ -36,9 +36,6 @@ void Thread_base::_thread_start() ** Thread base ** *****************/ -void Thread_base::_init_platform_thread() { } - - void Thread_base::_deinit_platform_thread() { env()->cpu_session()->kill_thread(_thread_cap); diff --git a/base/src/core/include/core_env.h b/base/src/core/include/core_env.h index ed95eb332..750e9f45c 100644 --- a/base/src/core/include/core_env.h +++ b/base/src/core/include/core_env.h @@ -22,6 +22,7 @@ #include #include #include +#include /* core includes */ #include @@ -174,7 +175,9 @@ namespace Genode { return 0; } - void reload_parent_cap(Capability::Dst, long) { } + void reinit(Capability::Dst, long) { } + + void reinit_main_thread(Rm_session_capability &) { } }; diff --git a/base/src/platform/_main.cc b/base/src/platform/_main.cc index 900b3a56c..9a8178885 100644 --- a/base/src/platform/_main.cc +++ b/base/src/platform/_main.cc @@ -31,13 +31,8 @@ using namespace Genode; extern int main(int argc, char **argv, char **envp); -extern void init_exception_handling(); /* implemented in base/cxx */ - -namespace Genode { - Rm_session *env_context_area_rm_session(); - void platform_main_bootstrap(); -} +namespace Genode { Rm_session *env_context_area_rm_session(); } enum { ATEXIT_SIZE = 256 }; @@ -46,6 +41,8 @@ enum { ATEXIT_SIZE = 256 }; ** C++ stuff ** ***************/ +void * __dso_handle = 0; + enum Atexit_fn_type { ATEXIT_FN_EMPTY, ATEXIT_FN_STD, ATEXIT_FN_CXA }; struct atexit_fn @@ -229,11 +226,6 @@ namespace Genode { extern bool inhibit_tracing; } */ extern "C" int _main() { - platform_main_bootstrap(); - - /* call env() explicitly to setup the environment */ - (void*)env(); - /* * Allow exit handlers to be registered. * @@ -244,34 +236,6 @@ extern "C" int _main() */ atexit_enable(); - /* initialize exception handling */ - init_exception_handling(); - - /* - * We create the thread-context area as early as possible to prevent other - * mappings from occupying the predefined virtual-memory region. - */ - env_context_area_rm_session(); - - /* - * Trigger first exception. This step has two purposes. - * First, it enables us to detect problems related to exception handling as - * early as possible. If there are problems with the C++ support library, - * it is much easier to debug them at this early stage. Otherwise problems - * with half-working exception handling cause subtle failures that are hard - * to interpret. - * - * Second, the C++ support library allocates data structures lazily on the - * first occurrence of an exception. This allocation traverses into - * Genode's heap and, in some corner cases, consumes several KB of stack. - * This is usually not a problem when the first exception is triggered from - * the main thread but it becomes an issue when the first exception is - * thrown from the context of a thread with a specially tailored (and - * otherwise sufficient) stack size. By throwing an exception here, we - * mitigate this issue by eagerly performing those allocations. - */ - try { throw 1; } catch (...) { } - /* call constructors for static objects */ void (**func)(); for (func = &_ctors_end; func != &_ctors_start; (*--func)()); diff --git a/base/src/platform/arm/crt0.s b/base/src/platform/arm/crt0.s index 391ae0a2e..33e52e180 100644 --- a/base/src/platform/arm/crt0.s +++ b/base/src/platform/arm/crt0.s @@ -1,6 +1,7 @@ /** * \brief Startup code for Genode applications on ARM * \author Norman Feske + * \author Martin Stein * \date 2007-04-28 */ @@ -11,34 +12,58 @@ * under the terms of the GNU General Public License version 2. */ -/*--- .text (program code) -------------------------*/ + +/************************** + ** .text (program code) ** + **************************/ + .section ".text.crt0" - .globl _start -_start: + /* program entry-point */ + .global _start + _start: - ldr r4, .initial_sp + /* make initial value of some registers available to higher-level code */ + ldr r4, =__initial_sp str sp, [r4] - ldr sp, .stack_high - b _main + /* + * Install initial temporary environment that is replaced later by the + * environment that init_main_thread creates. + */ + ldr sp, =_stack_high -.initial_sp: .word __initial_sp -.stack_high: .word _stack_high + /* create proper environment for main thread */ + bl init_main_thread - .globl __dso_handle -__dso_handle: .long 0 + /* apply environment that was created by init_main_thread */ + ldr sp, =init_main_thread_result + ldr sp, [sp] + + /* jump into init C code instead of calling it as it should never return */ + b _main + + +/********************************* + ** .bss (non-initialized data) ** + *********************************/ -/*--- .bss (non-initialized data) ------------------*/ .section ".bss" + /* stack of the temporary initial environment */ .p2align 4 - .globl _stack_low -_stack_low: - .space 128*1024 - .globl _stack_high -_stack_high: + .global _stack_low + _stack_low: + .space 128 * 1024 + .global _stack_high + _stack_high: /* initial value of the SP register */ - .globl __initial_sp -__initial_sp: .space 4 + .global __initial_sp + __initial_sp: + .space 4 + + /* return value of init_main_thread */ + .global init_main_thread_result + init_main_thread_result: + .space 4 diff --git a/base/src/platform/init_main_thread.cc b/base/src/platform/init_main_thread.cc new file mode 100644 index 000000000..596b0401b --- /dev/null +++ b/base/src/platform/init_main_thread.cc @@ -0,0 +1,130 @@ +/* + * \brief Setup the thread environment of a programs first thread + * \author Christian Helmuth + * \author Christian Prochaska + * \author Martin Stein + * \date 2013-12-04 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include +#include +#include +#include + +using namespace Genode; + +extern addr_t init_main_thread_result; + +extern void init_exception_handling(); + +namespace Genode { Rm_session * env_context_area_rm_session(); } + +void prepare_init_main_thread(); + +enum { MAIN_THREAD_STACK_SIZE = 16UL * 1024 * sizeof(Genode::addr_t) }; + +/** + * The first thread in a program + */ +class Main_thread : public Thread +{ + public: + + /** + * Constructor + * + * \param reinit wether this is called for reinitialization + */ + Main_thread(bool reinit) + : + Thread("main", reinit ? REINITIALIZED_MAIN : MAIN) + { } + + /********************** + ** Thread interface ** + **********************/ + + void entry() { } +}; + + +Main_thread * main_thread() +{ + static Main_thread s(false); + return &s; +} + + +/** + * Create a thread object for the main thread + * + * \return stack pointer of the new environment via init_main_thread_result + * + * This function must be called only once per program and before the _main + * function. It can be called as soon as a temporary environment provides + * some stack space and inter-process communication. At this stage, global + * static objects are not registered for implicit destruction at program exit. + */ +extern "C" void init_main_thread() +{ + /* do platform specific preparation */ + prepare_init_main_thread(); + + /* + * Explicitly setup program environment at this point to ensure that its + * destructor won't be registered for the atexit routine. + */ + (void*)env(); + + /* initialize exception handling */ + init_exception_handling(); + + /* + * We create the thread-context area as early as possible to prevent other + * mappings from occupying the predefined virtual-memory region. + */ + env_context_area_rm_session(); + + /* + * Trigger first exception. This step has two purposes. + * First, it enables us to detect problems related to exception handling as + * early as possible. If there are problems with the C++ support library, + * it is much easier to debug them at this early stage. Otherwise problems + * with half-working exception handling cause subtle failures that are hard + * to interpret. + * + * Second, the C++ support library allocates data structures lazily on the + * first occurrence of an exception. This allocation traverses into + * Genode's heap and, in some corner cases, consumes several KB of stack. + * This is usually not a problem when the first exception is triggered from + * the main thread but it becomes an issue when the first exception is + * thrown from the context of a thread with a specially tailored (and + * otherwise sufficient) stack size. By throwing an exception here, we + * mitigate this issue by eagerly performing those allocations. + */ + try { throw 1; } catch (...) { } + + /* create a thread object for the main thread */ + main_thread(); + + /** + * The new stack pointer enables the caller to switch from its current + * environment to the those that the thread object provides. + */ + addr_t sp = reinterpret_cast(main_thread()->stack_top()); + init_main_thread_result = sp; +} + + +/** + * Reinitialize main-thread object according to a reinitialized environment + */ +void reinit_main_thread() { construct_at(main_thread(), true); } diff --git a/base/src/platform/x86_32/crt0.s b/base/src/platform/x86_32/crt0.s index 47afb98b0..c10a0e6f8 100644 --- a/base/src/platform/x86_32/crt0.s +++ b/base/src/platform/x86_32/crt0.s @@ -1,6 +1,7 @@ /** * \brief Startup code for Genode applications * \author Christian Helmuth + * \author Martin Stein * \date 2009-08-12 */ @@ -11,53 +12,79 @@ * under the terms of the GNU General Public License version 2. */ -/*--- .text (program code) -------------------------*/ - .text - .global _start -_start: +/************************** + ** .text (program code) ** + **************************/ + +.text + + /* program entry-point */ + .global _start + _start: + + /* make initial value of some registers available to higher-level code */ mov %esp, __initial_sp mov %eax, __initial_ax mov %edi, __initial_di - /* XXX Switch to our own stack. */ + /* + * Install initial temporary environment that is replaced later by the + * environment that init_main_thread creates. + */ leal _stack_high, %esp - /* Clear the base pointer so that stack backtraces will work. */ + /* create proper environment for the main thread */ + call init_main_thread + + /* apply environment that was created by init_main_thread */ + movl init_main_thread_result, %esp + + /* clear the base pointer in order that stack backtraces will work */ xor %ebp,%ebp - /* Jump into init C code */ - call _main + /* jump into init C code instead of calling it as it should never return */ + jmp _main - /* We should never get here since _main does not return */ -1: int $3 - jmp 2f - .ascii "_main() returned." -2: jmp 1b - .globl __dso_handle -__dso_handle: .long 0 +/********************************** + ** .eh_frame (exception frames) ** + **********************************/ -/*--- .eh_frame (exception frames) -----------------*/ /* - .section .eh_frame,"aw" +.section .eh_frame,"aw" + .global __EH_FRAME_BEGIN__ -__EH_FRAME_BEGIN__: + __EH_FRAME_BEGIN__: */ -/*--- .bss (non-initialized data) ------------------*/ - .bss + +/********************************* + ** .bss (non-initialized data) ** + *********************************/ + +.bss + + /* stack of the temporary initial environment */ .p2align 4 .global _stack_low -_stack_low: - .space 64*1024 + _stack_low: + .space 64 * 1024 .global _stack_high -_stack_high: + _stack_high: /* initial value of the ESP, EAX and EDI register */ - .globl __initial_sp - .globl __initial_ax - .globl __initial_di -__initial_sp: .space 4 -__initial_ax: .space 4 -__initial_di: .space 4 + .global __initial_sp + __initial_sp: + .space 4 + .global __initial_ax + __initial_ax: + .space 4 + .global __initial_di + __initial_di: + .space 4 + + /* return value of init_main_thread */ + .global init_main_thread_result + init_main_thread_result: + .space 4 diff --git a/base/src/platform/x86_64/crt0.s b/base/src/platform/x86_64/crt0.s index 898faa6c9..de28595ca 100644 --- a/base/src/platform/x86_64/crt0.s +++ b/base/src/platform/x86_64/crt0.s @@ -1,6 +1,7 @@ /** * \brief Startup code for Genode 64Bit applications * \author Sebastian Sumpf + * \author Martin Stein * \date 2011-05-11 */ @@ -11,60 +12,90 @@ * under the terms of the GNU General Public License version 2. */ -/*--- .text (program code) -------------------------*/ - .text + +/************************** + ** .text (program code) ** + **************************/ + +.text + + /* program entry-point */ .global _start + _start: -_start: - + /* make initial value of some registers available to higher-level code */ movq __initial_ax@GOTPCREL(%rip), %rbx movq %rax, (%rbx) - movq __initial_di@GOTPCREL(%rip), %rbx movq %rdi, (%rbx) - movq __initial_sp@GOTPCREL(%rip), %rax movq %rsp, (%rax) - /* XXX Switch to our own stack. */ + /* + * Install initial temporary environment that is replaced later by the + * environment that init_main_thread creates. + */ leaq _stack_high@GOTPCREL(%rip),%rax movq (%rax), %rsp - /* Clear the base pointer so that stack backtraces will work. */ - xorq %rbp,%rbp + /* create proper environment for the main thread */ + call init_main_thread - /* Jump into init C code */ - call _main + /* apply environment that was created by init_main_thread */ + movq init_main_thread_result@GOTPCREL(%rip), %rax + movq (%rax), %rsp - /* We should never get here since _main does not return */ -1: int $3 - jmp 2f - .ascii "_main() returned." -2: jmp 1b + /* clear the base pointer in order that stack backtraces will work */ + xorq %rbp, %rbp - .globl __dso_handle -__dso_handle: .quad 0 + /* + * We jump into initial C code instead of calling it as it should never + * return on the one hand and because the alignment of the stack pointer + * that init_main_thread returned expects a jump at the other hand. The + * latter matters because GCC expects the initial stack pointer to be + * aligned to 16 byte for at least the handling of floating points. + */ + jmp _main + + +/********************************** + ** .eh_frame (exception frames) ** + **********************************/ -/*--- .eh_frame (exception frames) -----------------*/ /* - .section .eh_frame,"aw" +.section .eh_frame,"aw" + .global __EH_FRAME_BEGIN__ -__EH_FRAME_BEGIN__: + __EH_FRAME_BEGIN__: */ -/*--- .bss (non-initialized data) ------------------*/ - .bss + +/********************************* + ** .bss (non-initialized data) ** + *********************************/ + +.bss + + /* stack of the temporary initial environment */ .p2align 8 .global _stack_low -_stack_low: - .space 64*1024 + _stack_low: + .space 64 * 1024 .global _stack_high -_stack_high: + _stack_high: /* initial value of the RSP, RAX and RDI register */ .globl __initial_sp + __initial_sp: + .space 8 .globl __initial_ax + __initial_ax: + .space 8 .globl __initial_di -__initial_sp: .space 8 -__initial_ax: .space 8 -__initial_di: .space 8 + __initial_di: + .space 8 + + /* return value of init_main_thread */ + .globl init_main_thread_result + init_main_thread_result: + .space 8 diff --git a/libports/lib/mk/ffat_block.mk b/libports/lib/mk/ffat_block.mk index 863b2465a..3b69f0410 100644 --- a/libports/lib/mk/ffat_block.mk +++ b/libports/lib/mk/ffat_block.mk @@ -7,8 +7,6 @@ INC_DIR += $(REP_DIR)/src/lib/ffat/contrib SRC_C = ff.c ccsbcs.c SRC_CC = diskio_block.cc -LIBS = base - vpath % $(REP_DIR)/src/lib/ffat/ vpath % $(REP_DIR)/contrib/ff007e/src vpath % $(REP_DIR)/contrib/ff007e/src/option diff --git a/os/lib/mk/startup_dyn.mk b/os/lib/mk/startup_dyn.mk new file mode 100644 index 000000000..071947c57 --- /dev/null +++ b/os/lib/mk/startup_dyn.mk @@ -0,0 +1,5 @@ +SRC_CC += _main.cc + +REP_INC_DIR += src/platform + +vpath _main.cc $(BASE_DIR)/src/platform diff --git a/os/src/lib/ldso/arm/crt0.s b/os/src/lib/ldso/arm/crt0.s index 0de856d11..62d930fc5 100644 --- a/os/src/lib/ldso/arm/crt0.s +++ b/os/src/lib/ldso/arm/crt0.s @@ -1,6 +1,7 @@ /** * \brief Startup code for Genode applications on ARM * \author Norman Feske + * \author Martin Stein * \date 2007-04-28 */ @@ -11,19 +12,40 @@ * under the terms of the GNU General Public License version 2. */ -/*--- .text (program code) -------------------------*/ + +/************************** + ** .text (program code) ** + **************************/ + .section ".text.crt0" + /* linker entry-point */ .globl _start_ldso -_start_ldso: + _start_ldso: - ldr r2, .initial_sp + /* make initial value of some registers available to higher-level code */ + ldr r2, =__initial_sp str sp, [r2] - ldr sp, .stack_high + /* + * Install initial temporary environment that is replaced later by the + * environment that init_main_thread creates. + */ + ldr sp, =_stack_high + + /* let init_rtld relocate linker */ bl init_rtld - b _main - .initial_sp: .word __initial_sp - .stack_high: .word _stack_high + /* create proper environment for the main thread */ + bl init_main_thread + /* apply environment that was created by init_main_thread */ + ldr sp, =init_main_thread_result + ldr sp, [sp] + + /* call init C code */ + bl _main + + /* this should never be reached since _main should never return */ + _catch_main_return: + b _catch_main_return diff --git a/os/src/lib/ldso/include/arm/call_main.h b/os/src/lib/ldso/include/arm/call_main.h index 20bb350c1..a26f731fc 100644 --- a/os/src/lib/ldso/include/arm/call_main.h +++ b/os/src/lib/ldso/include/arm/call_main.h @@ -1,6 +1,7 @@ /* * \brief Call main function (ARM specific) * \author Sebastian Sumpf + * \author Martin Stein * \date 2011-05-05 */ @@ -13,20 +14,32 @@ #ifndef _ARM__CALL_MAIN_H_ #define _ARM__CALL_MAIN_H_ -/** - * Restore SP from initial sp and jump to entry function - */ -void call_main(void (*func)(void)) -{ - extern long __initial_sp; +void * my_stack_top(); +void set_program_var(const char *, const void *); - asm volatile ("mov %%sp, %0;" - "bx %1;" - : - : "r" (__initial_sp), - "r" (func) - : "memory" - ); +extern void * __initial_sp; + +/** + * Call program _main with the environment that its CRT0 would have created + * + * \param _main_fp pointer to _main function of dynamic program + */ +void call_main(void (*_main_fp)(void)) +{ + /* make initial value of some registers available to dynamic program */ + set_program_var("__initial_sp", __initial_sp); + + /* + * We could also do a call but that would enable the the program main to + * return to LDSO wich isn't desired. This means also that not resetting + * the SP to stack top as we do would waste stack memory for dead LDSO + * frames. + */ + asm volatile ("mov sp, %[sp];" + "bx %[ip];" + :: [sp] "r" (my_stack_top()), + [ip] "r" (_main_fp) + : "memory"); } #endif /* _ARM__CALL_MAIN_H_ */ diff --git a/os/src/lib/ldso/include/x86_32/call_main.h b/os/src/lib/ldso/include/x86_32/call_main.h index ab22c8c9b..e122b42f6 100644 --- a/os/src/lib/ldso/include/x86_32/call_main.h +++ b/os/src/lib/ldso/include/x86_32/call_main.h @@ -1,6 +1,7 @@ /* * \brief Call main function (X86 specific) * \author Sebastian Sumpf + * \author Martin Stein * \date 2011-05-02 */ @@ -13,20 +14,37 @@ #ifndef _X86_32__CALL_MAIN_H_ #define _X86_32__CALL_MAIN_H_ -/** - * Restore SP from initial sp and jump to entry function - */ -void call_main(void (*func)(void)) -{ - extern long __initial_sp; +void * my_stack_top(); +void set_program_var(const char *, const void *); - asm volatile ("mov %0, %%esp;" - "jmp *%1;" - : - : "r" (__initial_sp), - "r" (func) - : "memory" - ); +extern void * __initial_sp; +extern void * __initial_ax; +extern void * __initial_di; + +/** + * Call program _main with the environment that its CRT0 would have created + * + * \param _main_fp pointer to _main function of dynamic program + */ +void call_main(void (*_main_fp)(void)) +{ + /* make initial value of some registers available to dynamic program */ + set_program_var("__initial_sp", __initial_sp); + set_program_var("__initial_ax", __initial_ax); + set_program_var("__initial_di", __initial_di); + + /* + * We could also do a call but that would enable the the program main to + * return to LDSO wich isn't desired. This means also that not resetting + * the SP to stack top as we do would waste stack memory for dead LDSO + * frames. + */ + asm volatile ("mov %[sp], %%esp;" + "xor %%ebp, %%ebp;" + "jmp *%[ip];" + :: [sp] "r" (my_stack_top()), + [ip] "r" (_main_fp) + : "memory"); } #endif /* _X86_32__CALL_MAIN_H_ */ diff --git a/os/src/lib/ldso/include/x86_64/call_main.h b/os/src/lib/ldso/include/x86_64/call_main.h index 9252abe93..0e2b07dbc 100644 --- a/os/src/lib/ldso/include/x86_64/call_main.h +++ b/os/src/lib/ldso/include/x86_64/call_main.h @@ -1,6 +1,7 @@ /* * \brief Call main function (X86 64 bit specific) * \author Sebastian Sumpf + * \author Martin Stein * \date 2011-05-011 */ @@ -13,20 +14,37 @@ #ifndef _X86_64__CALL_MAIN_H_ #define _X86_64__CALL_MAIN_H_ -/** - * Restore SP from initial sp and jump to entry function - */ -void call_main(void (*func)(void)) -{ - extern long __initial_sp; +void * my_stack_top(); +void set_program_var(const char *, const void *); - asm volatile ("movq %0, %%rsp;" - "jmpq *%1;" - : - : "r" (__initial_sp), - "r" (func) - : "memory" - ); +extern void * __initial_sp; +extern void * __initial_ax; +extern void * __initial_di; + +/** + * Call program _main with the environment that its CRT0 would have created + * + * \param _main_fp pointer to _main function of dynamic program + */ +void call_main(void (*_main_fp)(void)) +{ + /* make initial value of some registers available to dynamic program */ + set_program_var("__initial_sp", __initial_sp); + set_program_var("__initial_ax", __initial_ax); + set_program_var("__initial_di", __initial_di); + + /* + * We could also do a call but that would enable the the program main to + * return to LDSO wich isn't desired. This means also that not resetting + * the SP to stack top as we do would waste stack memory for dead LDSO + * frames. + */ + asm volatile ("movq %[sp], %%rsp;" + "xorq %%rbp, %%rbp;" + "jmpq *%[ip];" + :: [sp] "r" (my_stack_top()), + [ip] "r" (_main_fp) + : "memory"); } #endif /* _X86_64__CALL_MAIN_H_ */ diff --git a/os/src/lib/ldso/target.inc b/os/src/lib/ldso/target.inc index 74e580226..f6c40583c 100644 --- a/os/src/lib/ldso/target.inc +++ b/os/src/lib/ldso/target.inc @@ -7,7 +7,7 @@ SRC_S = rtld_start.S SRC_C = reloc.c rtld.c map_object.c xmalloc.c debug.c main.c \ ldso_types.c rtld_dummies.c platform.c SRC_CC = stdio.cc stdlib.cc file.cc err.cc string.cc lock.cc \ - test.cc environ.cc + test.cc environ.cc thread.cc INC_DIR += $(DIR)/ \ $(DIR)/contrib \ diff --git a/os/src/lib/ldso/thread.cc b/os/src/lib/ldso/thread.cc new file mode 100644 index 000000000..88672aae7 --- /dev/null +++ b/os/src/lib/ldso/thread.cc @@ -0,0 +1,24 @@ +/* + * \brief Thread related C helpers + * \author Martin Stein + * \date 2013-12-13 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include + + +/** + * Return top end of the stack of the calling thread + */ +extern "C" void * my_stack_top() +{ + return Genode::Thread_base::myself()->stack_top(); +} diff --git a/os/src/lib/ldso/x86_32/crt0.s b/os/src/lib/ldso/x86_32/crt0.s index 75d2d0539..f2245ba80 100644 --- a/os/src/lib/ldso/x86_32/crt0.s +++ b/os/src/lib/ldso/x86_32/crt0.s @@ -2,6 +2,7 @@ * \brief Startup code for ld.lib.so (x86-32) * \author Christian Helmuth * \author Sebastian Sumpf + * \author Martin Stein * \date 2011-05-03 */ @@ -12,39 +13,60 @@ * under the terms of the GNU General Public License version 2. */ -/*--- .text (program code) -------------------------*/ - .text + +/************************** + ** .text (program code) ** + **************************/ + +.text + + /* linker entry-point */ .global _start_ldso + _start_ldso: -_start_ldso: - - /* initialize GOT pointer in EBX */ -3: - /* The follwing statement causes a text relocation which will be ignored by - * ldso itself, this is necessary since we don't have a valid stack pointer at - * this moment so a 'call' in order to retrieve our IP and thus calculate the - * GOT-position in the traditional manner is not possible on x86 + /* + * Initialize GOT pointer in EBX. + * + * The follwing statement causes a text relocation which will be ignored + * by ldso itself, this is necessary since we don't have a valid stack + * pointer at this moment so a 'call' in order to retrieve our IP and thus + * calculate the GOT-position in the traditional manner is not possible on + * x86. */ + 3: movl $., %ebx addl $_GLOBAL_OFFSET_TABLE_ + (. - 3b) , %ebx + /* make initial value of some registers available to higher-level code */ movl %esp, __initial_sp@GOTOFF(%ebx) + movl %eax, __initial_ax@GOTOFF(%ebx) + movl %edi, __initial_di@GOTOFF(%ebx) - /* XXX Switch to our own stack. */ + /* + * Install initial temporary environment that is replaced later by the + * environment that init_main_thread creates. + */ leal _stack_high@GOTOFF(%ebx), %esp - /* relocate ldso */ + /* let init_rtld relocate LDSO */ call init_rtld - /* Clear the base pointer so that stack backtraces will work. */ + /* create proper environment for the main thread */ + call init_main_thread + + /* apply environment that was created by init_main_thread */ + movl init_main_thread_result, %esp + + /* clear the base pointer so that stack backtraces will work */ xor %ebp,%ebp - /* Jump into init C code */ + /* jump into init C code */ call _main - /* We should never get here since _main does not return */ -1: int $3 + /* we should never get here since _main does not return */ + 1: + int $3 jmp 2f .ascii "_main() returned." -2: jmp 1b - + 2: + jmp 1b diff --git a/os/src/lib/ldso/x86_64/crt0.s b/os/src/lib/ldso/x86_64/crt0.s index 26ddb562b..28650d895 100644 --- a/os/src/lib/ldso/x86_64/crt0.s +++ b/os/src/lib/ldso/x86_64/crt0.s @@ -2,6 +2,7 @@ * \brief Startup code for ldso 64Bit version * \author Christian Helmuth * \author Sebastian Sumpf + * \author Martin Stein * \date 2011-05-10 */ @@ -12,32 +13,55 @@ * under the terms of the GNU General Public License version 2. */ -/*--- .text (program code) -------------------------*/ - .text +/************************** + ** .text (program code) ** + **************************/ + +.text + + /* linker entry-point */ .globl _start_ldso -_start_ldso: + _start_ldso: - /* initialize GLOBAL OFFSET TABLE */ + /* initialize global offset table */ leaq _GLOBAL_OFFSET_TABLE_(%rip),%r15 - + + /* make initial value of some registers available to higher-level code */ + movq __initial_ax@GOTPCREL(%rip), %rbx + movq %rax, (%rbx) + movq __initial_di@GOTPCREL(%rip), %rbx + movq %rdi, (%rbx) movq __initial_sp@GOTPCREL(%rip), %rax movq %rsp, (%rax) - /* XXX Switch to our own stack. */ + /* + * Install initial temporary environment that is replaced later by the + * environment that init_main_thread creates. + */ leaq _stack_high@GOTPCREL(%rip),%rax movq (%rax), %rsp + /* let init_rtld relocate LDSO */ call init_rtld - /* Clear the base pointer so that stack backtraces will work. */ + /* create proper environment for the main thread */ + call init_main_thread + + /* apply environment that was created by init_main_thread */ + movq init_main_thread_result@GOTPCREL(%rip), %rax + movq (%rax), %rsp + + /* clear the base pointer so that stack backtraces will work */ xorq %rbp,%rbp - /* Jump into init C code */ + /* jump into init C code */ call _main - /* We should never get here since _main does not return */ -1: int $3 + /* we should never get here since _main does not return */ + 1: + int $3 jmp 2f .ascii "_main() returned." -2: jmp 1b + 2: + jmp 1b diff --git a/os/src/platform/genode_dyn.ld b/os/src/platform/genode_dyn.ld index d412d3539..bd07adca3 100644 --- a/os/src/platform/genode_dyn.ld +++ b/os/src/platform/genode_dyn.ld @@ -11,7 +11,12 @@ * under the terms of the GNU General Public License version 2. */ -ENTRY(_start) + +/* + * Program doesn't need to startup with CRT0 as LDSO has done this + * initialization during its own CRT0 already. + */ +ENTRY(_main) PHDRS { diff --git a/ports/lib/mk/libc_noux.mk b/ports/lib/mk/libc_noux.mk index 9b1806b8f..38c75a5a7 100644 --- a/ports/lib/mk/libc_noux.mk +++ b/ports/lib/mk/libc_noux.mk @@ -4,6 +4,8 @@ LIBS += libc REP_INC_DIR += src/lib/libc +INC_DIR += $(BASE_DIR)/src/base/env/ + vpath %.cc $(REP_DIR)/src/lib/libc_noux SHARED_LIB = yes diff --git a/ports/src/lib/libc_noux/plugin.cc b/ports/src/lib/libc_noux/plugin.cc index c5f132dca..e44f0c1fa 100644 --- a/ports/src/lib/libc_noux/plugin.cc +++ b/ports/src/lib/libc_noux/plugin.cc @@ -12,12 +12,14 @@ */ /* Genode includes */ +#include #include #include #include #include #include #include +#include /* noux includes */ #include @@ -60,9 +62,6 @@ enum { verbose = false }; enum { verbose_signals = false }; -void *operator new (size_t, void *ptr) { return ptr; } - - class Noux_connection { private: @@ -79,13 +78,6 @@ class Noux_connection Noux_connection() : _sysio(_obtain_sysio()) { } - void reconnect() - { - new (&_connection) Noux_connection; - Genode::env()->rm_session()->detach(_sysio); - _sysio = _obtain_sysio(); - } - /** * Return the capability of the local context-area RM session */ @@ -495,11 +487,22 @@ extern "C" void stdout_reconnect(); /* provided by 'log_console.cc' */ */ extern "C" void fork_trampoline() { - Genode::env()->reload_parent_cap(new_parent.dst, new_parent.local_name); + /* reinitialize environment */ + using namespace Genode; + Platform_env * const platform_env = dynamic_cast(env()); + platform_env->reinit(new_parent.dst, new_parent.local_name); + /* reinitialize standard-output connection */ stdout_reconnect(); - noux_connection()->reconnect(); + /* reinitialize noux connection */ + construct_at(noux_connection()); + + /* reinitialize main-thread object which implies reinit of context area */ + auto context_area_rm = noux_connection()->context_area_rm_session(); + platform_env->reinit_main_thread(context_area_rm); + + /* apply processor state that the forker had when he did the fork */ longjmp(fork_jmp_buf, 1); } @@ -507,7 +510,7 @@ extern "C" void fork_trampoline() extern "C" pid_t fork(void) { /* stack used for executing 'fork_trampoline' */ - enum { STACK_SIZE = 1024 }; + enum { STACK_SIZE = 8 * 1024 }; static long stack[STACK_SIZE]; if (setjmp(fork_jmp_buf)) {