diff --git a/base-codezero/lib/mk/base-common.mk b/base-codezero/lib/mk/base-common.mk
index 67d97ab9e0..b63958767e 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 19be3612af..8a34574acb 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 44c42df9c6..e02a818538 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 af14b81509..dc45ffcb54 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 aca3889f39..0000000000
--- 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 8244261eb1..c410304b37 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 0000000000..d100895edd
--- /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 b2d065e7f3..666edb8f91 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 40d58d8b15..0000000000
--- 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 d774fbdc67..42fb407e28 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 48308e789a..c6571e4d08 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 2a537a84ae..fedf554e98 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 f569c6fc6b..a6f78a4ab9 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 baf90a0254..25a521e0e5 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 041512155b..605196d38d 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 6f865fcedc..efbafe02c1 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 0a4ac3afe2..0000000000
--- 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 d4af1afcda..add6e41763 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 bdae1927f3..2642874f4d 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 226e4f3d2b..2703183b6d 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 6663893a60..83962d2566 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 aab5efae47..4a7113e6a8 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 72cce376c2..4a1b1c63b3 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 1ba940bf3b..0000000000
--- 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 c60cf07e43..42fcc5af93 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 b96cf87260..9ae7d5509e 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 df6d7ec808..36318a9927 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 0f74d7e617..7d3a189783 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 0000000000..20b4db0541
--- /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 94046d1e14..ba8ad4d42b 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 8e1ddcc94d..b4ae6dd45e 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 cf70b11444..8fb9f220ef 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 67cfecf412..0000000000
--- 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 9493b6d30f..31c8d3a153 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 99f94cfec6..66d3581f60 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 97c8cc911c..a59981a15f 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 5d944042b1..0000000000
--- 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 26e3d69729..fc5c977654 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 9aff42922a..575cb0bf04 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 49d7d71ddc..db33e6c733 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 3939d0bb81..9d0a1ceced 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 631af0fdea..51e9ad8f27 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 2d6ce3f790..0000000000
--- 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 07c390ace8..c410304b37 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 4807a7692c..e0cdb88d1c 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 7649b24f3a..9a8d89a46e 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 b328ce4f82..0000000000
--- 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 141e0dd0cf..320e7540bf 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 2bc0cbd57e..f6941728f2 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 b2d065e7f3..666edb8f91 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 5d14099b12..0000000000
--- 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 80e48e436d..733550adef 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 47db0df41b..4f1799a7b4 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 21a8aecb19..06c1d2bbb8 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 e9035303bd..da05046694 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 018520dd3c..296f7fdb87 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 7e8b17a29c..898a074d1d 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 3755749582..0cbabbb440 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 aa67e6f659..db8636c794 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 8c90926891..43ccda3c0f 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 d17363d47f..4433909206 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 ed95eb3323..750e9f45c3 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 900b3a56c2..9a81788854 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 391ae0a2e4..33e52e1808 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 0000000000..596b0401ba
--- /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 47afb98b0c..c10a0e6f87 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 898faa6c9e..de28595ca2 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 863b2465a1..3b69f0410b 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 0000000000..071947c578
--- /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 0de856d11d..62d930fc57 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 20bb350c1c..a26f731fc2 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 ab22c8c9bd..e122b42f67 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 9252abe93f..0e2b07dbcd 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 74e5802264..f6c40583c7 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 0000000000..88672aae76
--- /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 75d2d0539a..f2245ba80b 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 26ddb562bd..28650d8959 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 d412d35394..bd07adca35 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 9b1806b8f5..38c75a5a71 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 c5f132dca1..e44f0c1fa4 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)) {