base: setup thread object for main thread in CRT0
For a main thread a thread object is created by the CRT0 before _main gets called so that _main can already run in a generic environment that, e.g., catches stack overflows as a page-fault instead of corrupting the BSS. Additionally dynamic programs have only one CRT0 - the one of the LDSO - which does the initialization for both LDSO and program. ref #989
This commit is contained in:
parent
ba8e61653f
commit
0b64328944
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
LIBS += cxx l4 startup
|
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 += ipc/ipc.cc ipc/pager.cc ipc/ipc_marshal_cap.cc
|
||||||
SRC_CC += pager/pager.cc pager/common.cc
|
SRC_CC += pager/pager.cc pager/common.cc
|
||||||
SRC_CC += avl_tree/avl_tree.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 += $(BASE_DIR)/src/base/thread
|
||||||
INC_DIR += $(REP_DIR)/include/codezero/dummies
|
INC_DIR += $(REP_DIR)/include/codezero/dummies
|
||||||
|
|
||||||
vpath main_bootstrap.cc $(REP_DIR)/src/platform
|
vpath cap_copy.cc $(BASE_DIR)/src/platform
|
||||||
vpath cap_copy.cc $(BASE_DIR)/src/platform
|
vpath %.cc $(REP_DIR)/src/base
|
||||||
vpath %.cc $(REP_DIR)/src/base
|
vpath %.cc $(BASE_DIR)/src/base
|
||||||
vpath %.cc $(BASE_DIR)/src/base
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Thread bootstrap code
|
* \brief Thread bootstrap code
|
||||||
* \author Christian Prochaska
|
* \author Christian Prochaska
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2013-02-15
|
* \date 2013-02-15
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -13,13 +14,83 @@
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
|
#include <base/env.h>
|
||||||
|
#include <util/string.h>
|
||||||
|
|
||||||
/* Codezero includes */
|
/* Codezero includes */
|
||||||
#include <codezero/syscalls.h>
|
#include <codezero/syscalls.h>
|
||||||
|
|
||||||
|
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()
|
void Genode::Thread_base::_thread_bootstrap()
|
||||||
{
|
{
|
||||||
Codezero::l4_mutex_init(utcb()->running_lock());
|
Codezero::l4_mutex_init(utcb()->running_lock());
|
||||||
Codezero::l4_mutex_lock(utcb()->running_lock()); /* block on first mutex 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());
|
||||||
|
}
|
||||||
|
|
|
@ -39,9 +39,6 @@ void Thread_base::_thread_start()
|
||||||
** Thread base **
|
** Thread base **
|
||||||
*****************/
|
*****************/
|
||||||
|
|
||||||
void Thread_base::_init_platform_thread() { }
|
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::_deinit_platform_thread()
|
void Thread_base::_deinit_platform_thread()
|
||||||
{
|
{
|
||||||
env()->cpu_session()->kill_thread(_thread_cap);
|
env()->cpu_session()->kill_thread(_thread_cap);
|
||||||
|
|
|
@ -27,10 +27,6 @@ enum { verbose_thread_start = true };
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::_init_platform_thread() { }
|
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::_deinit_platform_thread() { }
|
void Thread_base::_deinit_platform_thread() { }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 <base/stdint.h>
|
|
||||||
#include <base/printf.h>
|
|
||||||
#include <base/thread.h>
|
|
||||||
#include <util/string.h>
|
|
||||||
|
|
||||||
/* Codezero includes */
|
|
||||||
#include <codezero/syscalls.h>
|
|
||||||
|
|
||||||
|
|
||||||
/****************************
|
|
||||||
** 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;
|
|
||||||
}
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
LIBS += cxx startup
|
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 += ipc/ipc.cc ipc/pager.cc ipc/ipc_marshal_cap.cc
|
||||||
SRC_CC += pager/pager.cc pager/common.cc
|
SRC_CC += pager/pager.cc pager/common.cc
|
||||||
SRC_CC += avl_tree/avl_tree.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 += lock/lock.cc
|
||||||
SRC_CC += signal/signal.cc signal/common.cc
|
SRC_CC += signal/signal.cc signal/common.cc
|
||||||
SRC_CC += server/server.cc server/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 += $(REP_DIR)/src/base/lock
|
||||||
INC_DIR += $(BASE_DIR)/src/base/thread
|
INC_DIR += $(BASE_DIR)/src/base/thread
|
||||||
|
|
||||||
vpath main_bootstrap.cc $(REP_DIR)/src/platform
|
vpath cap_copy.cc $(BASE_DIR)/src/platform
|
||||||
vpath cap_copy.cc $(BASE_DIR)/src/platform
|
vpath %.cc $(REP_DIR)/src/base
|
||||||
vpath %.cc $(REP_DIR)/src/base
|
vpath %.cc $(BASE_DIR)/src/base
|
||||||
vpath %.cc $(BASE_DIR)/src/base
|
|
||||||
|
|
41
base-fiasco/src/base/thread/thread_bootstrap.cc
Normal file
41
base-fiasco/src/base/thread/thread_bootstrap.cc
Normal file
|
@ -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 <base/thread.h>
|
||||||
|
#include <base/env.h>
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
|
@ -53,9 +53,6 @@ void Thread_base::cancel_blocking()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::_init_platform_thread() { }
|
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::_deinit_platform_thread()
|
void Thread_base::_deinit_platform_thread()
|
||||||
{
|
{
|
||||||
/* destruct platform thread */
|
/* destruct platform thread */
|
||||||
|
|
|
@ -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 */ } }
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <base/cap_map.h>
|
#include <base/cap_map.h>
|
||||||
#include <base/native_types.h>
|
#include <base/native_types.h>
|
||||||
#include <util/assert.h>
|
#include <util/assert.h>
|
||||||
|
#include <util/construct_at.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
|
@ -124,6 +125,11 @@ namespace Genode {
|
||||||
|
|
||||||
bool static_idx(Cap_index *idx) {
|
bool static_idx(Cap_index *idx) {
|
||||||
return ((T*)idx) < &_indices[START_IDX]; }
|
return ((T*)idx) < &_indices[START_IDX]; }
|
||||||
|
|
||||||
|
void reinit()
|
||||||
|
{
|
||||||
|
construct_at<Cap_index_allocator_tpl<T, SZ> >(this);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,11 @@ namespace Genode
|
||||||
* \param idx pointer to the Cap_index object in question
|
* \param idx pointer to the Cap_index object in question
|
||||||
*/
|
*/
|
||||||
virtual bool static_idx(Cap_index *idx) = 0;
|
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
|
* to save entries in the capability space, and prevent leaks of
|
||||||
* them.
|
* them.
|
||||||
*/
|
*/
|
||||||
class Capability_map : Noncopyable
|
class Capability_map
|
||||||
|
:
|
||||||
|
private Noncopyable
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
LIBS += cxx syscall startup
|
LIBS += cxx syscall startup
|
||||||
|
|
||||||
SRC_CC += main_bootstrap.cc
|
|
||||||
SRC_CC += ipc/ipc.cc ipc/pager.cc
|
SRC_CC += ipc/ipc.cc ipc/pager.cc
|
||||||
SRC_CC += pager/pager.cc pager/common.cc
|
SRC_CC += pager/pager.cc pager/common.cc
|
||||||
SRC_CC += avl_tree/avl_tree.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/lock
|
||||||
INC_DIR += $(BASE_DIR)/src/base/thread
|
INC_DIR += $(BASE_DIR)/src/base/thread
|
||||||
|
|
||||||
vpath main_bootstrap.cc $(REP_DIR)/src/platform
|
vpath %.cc $(REP_DIR)/src/base
|
||||||
vpath %.cc $(REP_DIR)/src/base
|
vpath %.cc $(BASE_DIR)/src/base
|
||||||
vpath %.cc $(BASE_DIR)/src/base
|
|
||||||
|
|
||||||
# vi: set ft=make :
|
# vi: set ft=make :
|
||||||
|
|
|
@ -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)
|
size_t Thread_base::Context_allocator::base_to_idx(addr_t base)
|
||||||
{
|
{
|
||||||
return (base - Native_config::context_area_virtual_base()) /
|
/* the first context isn't managed through the indices */
|
||||||
Native_config::context_virtual_size();
|
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)
|
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() +
|
return Native_config::context_area_virtual_base() +
|
||||||
|
Native_config::context_virtual_size() +
|
||||||
idx * 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);
|
Lock::Guard _lock_guard(_threads_lock);
|
||||||
|
|
||||||
try {
|
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<MAX_THREADS>::Out_of_indices) {
|
} catch(Bit_allocator<MAX_THREADS>::Out_of_indices) {
|
||||||
return 0;
|
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)
|
void Thread_base::Context_allocator::free(Context *context)
|
||||||
{
|
{
|
||||||
Lock::Guard _lock_guard(_threads_lock);
|
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
|
* 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);
|
Lock::Guard _lock_guard(alloc_lock);
|
||||||
|
|
||||||
/* allocate thread context */
|
/* allocate thread context */
|
||||||
Context *context = _context_allocator()->alloc(this);
|
Context *context = _context_allocator()->alloc(this, main_thread);
|
||||||
if (!context)
|
if (!context)
|
||||||
throw Context_alloc_failed();
|
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)
|
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));
|
strncpy(context->name, name, sizeof(context->name));
|
||||||
return (void *)context->stack_top();
|
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)
|
_join_lock(Lock::LOCKED)
|
||||||
{
|
{
|
||||||
strncpy(_context->name, name, sizeof(_context->name));
|
strncpy(_context->name, name, sizeof(_context->name));
|
||||||
_init_platform_thread();
|
_init_platform_thread(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Fiasco.OC specific thread bootstrap code
|
* \brief Fiasco.OC specific thread bootstrap code
|
||||||
* \author Stefan Kalkowski
|
* \author Stefan Kalkowski
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2011-01-20
|
* \date 2011-01-20
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -11,9 +12,38 @@
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <util/construct_at.h>
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************
|
||||||
|
** 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<Capability_map>(cap_map());
|
||||||
|
cap_idx_alloc()->reinit();
|
||||||
|
prepare_init_main_thread();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
** Thread_base **
|
||||||
|
*****************/
|
||||||
|
|
||||||
void Genode::Thread_base::_thread_bootstrap() { }
|
void Genode::Thread_base::_thread_bootstrap() { }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* \brief Fiasco-specific implementation of the non-core startup Thread API
|
* \brief Fiasco-specific implementation of the non-core startup Thread API
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
* \author Stefan Kalkowski
|
* \author Stefan Kalkowski
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2010-01-19
|
* \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 */
|
if (type == NORMAL)
|
||||||
char buf[48];
|
{
|
||||||
name(buf, sizeof(buf));
|
/* create thread at core */
|
||||||
_thread_cap = env()->cpu_session()->create_thread(buf);
|
char buf[48];
|
||||||
|
name(buf, sizeof(buf));
|
||||||
|
_thread_cap = env()->cpu_session()->create_thread(buf);
|
||||||
|
|
||||||
/* assign thread to protection domain */
|
/* assign thread to protection domain */
|
||||||
env()->pd_session()->bind_thread(_thread_cap);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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()
|
void Thread_base::start()
|
||||||
|
|
|
@ -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 <base/stdint.h>
|
|
||||||
#include <base/native_types.h>
|
|
||||||
#include <base/cap_map.h>
|
|
||||||
|
|
||||||
namespace Fiasco {
|
|
||||||
#include <l4/sys/utcb.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
LIBS += cxx kernel_interface
|
LIBS += cxx kernel_interface
|
||||||
|
|
||||||
SRC_CC += main_bootstrap.cc
|
|
||||||
SRC_CC += ipc.cc ipc/ipc_marshal_cap.cc
|
SRC_CC += ipc.cc ipc/ipc_marshal_cap.cc
|
||||||
SRC_CC += avl_tree/avl_tree.cc
|
SRC_CC += avl_tree/avl_tree.cc
|
||||||
SRC_CC += allocator/slab.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 += server/server.cc server/common.cc
|
||||||
SRC_CC += thread/thread_bootstrap.cc thread/trace.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/lock
|
||||||
INC_DIR += $(BASE_DIR)/src/base/thread
|
INC_DIR += $(BASE_DIR)/src/base/thread
|
||||||
|
|
||||||
vpath main_bootstrap.cc $(REP_DIR)/src/platform
|
vpath %.cc $(REP_DIR)/src/base
|
||||||
vpath %.cc $(REP_DIR)/src/base
|
vpath %.cc $(BASE_DIR)/src/base
|
||||||
vpath %.cc $(BASE_DIR)/src/base
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* \brief Thread bootstrap code
|
* \brief Thread initialization
|
||||||
* \author Christian Prochaska
|
* \author Martin stein
|
||||||
* \date 2013-02-15
|
* \date 2013-02-15
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -13,13 +13,82 @@
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
|
#include <base/env.h>
|
||||||
|
|
||||||
/* base-hw includes */
|
/* base-hw includes */
|
||||||
#include <kernel/interface.h>
|
#include <kernel/interface.h>
|
||||||
|
|
||||||
|
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<Ram_dataspace>(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();
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
||||||
_tid.thread_id = utcb->start_info()->thread_id();
|
_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;
|
||||||
|
}
|
||||||
|
|
|
@ -26,9 +26,6 @@ namespace Genode { Rm_session * env_context_area_rm_session(); }
|
||||||
** Thread_base **
|
** Thread_base **
|
||||||
*****************/
|
*****************/
|
||||||
|
|
||||||
void Thread_base::_init_platform_thread() { }
|
|
||||||
|
|
||||||
|
|
||||||
Native_utcb * Thread_base::utcb()
|
Native_utcb * Thread_base::utcb()
|
||||||
{
|
{
|
||||||
if (this) { return &_context->utcb; }
|
if (this) { return &_context->utcb; }
|
||||||
|
|
|
@ -60,11 +60,6 @@
|
||||||
/* catch erroneous kernel return */
|
/* catch erroneous kernel return */
|
||||||
3: b 3b
|
3: b 3b
|
||||||
|
|
||||||
/* handle for dynamic symbol objects */
|
|
||||||
.align 3
|
|
||||||
.global __dso_handle
|
|
||||||
__dso_handle: .long 0
|
|
||||||
|
|
||||||
.section .bss
|
.section .bss
|
||||||
|
|
||||||
/* kernel stack */
|
/* kernel stack */
|
||||||
|
|
|
@ -41,6 +41,7 @@ using namespace Kernel;
|
||||||
|
|
||||||
/* get core configuration */
|
/* get core configuration */
|
||||||
extern Genode::Native_utcb * _main_thread_utcb;
|
extern Genode::Native_utcb * _main_thread_utcb;
|
||||||
|
extern Genode::Native_thread_id _main_thread_id;
|
||||||
extern int _kernel_stack_high;
|
extern int _kernel_stack_high;
|
||||||
extern "C" void CORE_MAIN();
|
extern "C" void CORE_MAIN();
|
||||||
|
|
||||||
|
@ -249,6 +250,7 @@ extern "C" void kernel()
|
||||||
/* start thread with stack pointer at the top of stack */
|
/* start thread with stack pointer at the top of stack */
|
||||||
static Native_utcb utcb;
|
static Native_utcb utcb;
|
||||||
static Thread t(Priority::MAX, "core");
|
static Thread t(Priority::MAX, "core");
|
||||||
|
_main_thread_id = t.id();
|
||||||
_main_thread_utcb = &utcb;
|
_main_thread_utcb = &utcb;
|
||||||
_main_thread_utcb->start_info()->init(t.id(), Genode::Native_capability());
|
_main_thread_utcb->start_info()->init(t.id(), Genode::Native_capability());
|
||||||
t.ip = (addr_t)CORE_MAIN;;
|
t.ip = (addr_t)CORE_MAIN;;
|
||||||
|
|
|
@ -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())
|
_tid.platform_thread = new (platform()->core_mem_alloc())
|
||||||
Platform_thread(stack_size, Kernel::core_id(), label);
|
Platform_thread(stack_size, Kernel::core_id(), label);
|
||||||
|
|
|
@ -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 <base/native_types.h>
|
|
||||||
#include <base/thread.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,6 +14,7 @@
|
||||||
#ifndef _INCLUDE__RM_SESSION__CLIENT_H_
|
#ifndef _INCLUDE__RM_SESSION__CLIENT_H_
|
||||||
#define _INCLUDE__RM_SESSION__CLIENT_H_
|
#define _INCLUDE__RM_SESSION__CLIENT_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
#include <rm_session/capability.h>
|
#include <rm_session/capability.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
@ -22,6 +23,8 @@ namespace Genode {
|
||||||
{
|
{
|
||||||
Rm_session_capability const _cap;
|
Rm_session_capability const _cap;
|
||||||
|
|
||||||
|
typedef Rm_session Rpc_interface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return pointer to locally implemented RM session
|
* Return pointer to locally implemented RM session
|
||||||
*
|
*
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
LIBS += syscall
|
LIBS += syscall
|
||||||
|
|
||||||
SRC_CC += main_bootstrap.cc
|
|
||||||
SRC_CC += ipc/ipc.cc
|
SRC_CC += ipc/ipc.cc
|
||||||
SRC_CC += avl_tree/avl_tree.cc
|
SRC_CC += avl_tree/avl_tree.cc
|
||||||
SRC_CC += allocator/slab.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 += env/rm_session_mmap.cc env/debug.cc
|
||||||
SRC_CC += signal/signal.cc signal/common.cc
|
SRC_CC += signal/signal.cc signal/common.cc
|
||||||
SRC_CC += server/server.cc server/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/lock $(BASE_DIR)/src/base/lock
|
||||||
INC_DIR += $(REP_DIR)/src/base/ipc
|
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 += $(REP_DIR)/src/platform $(BASE_DIR)/src/platform
|
||||||
INC_DIR += $(BASE_DIR)/src/base/thread
|
INC_DIR += $(BASE_DIR)/src/base/thread
|
||||||
|
|
||||||
vpath main_bootstrap.cc $(REP_DIR)/src/platform
|
vpath %.cc $(REP_DIR)/src/base
|
||||||
vpath %.cc $(REP_DIR)/src/base
|
vpath %.cc $(BASE_DIR)/src/base
|
||||||
vpath %.cc $(BASE_DIR)/src/base
|
|
||||||
|
|
4
base-linux/src/base/env/platform_env.cc
vendored
4
base-linux/src/base/env/platform_env.cc
vendored
|
@ -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::Platform_env()
|
||||||
:
|
:
|
||||||
Platform_env_base(static_cap_cast<Ram_session>(_parent().session("Env::ram_session", "")),
|
Platform_env_base(static_cap_cast<Ram_session>(_parent().session("Env::ram_session", "")),
|
||||||
|
|
14
base-linux/src/base/env/platform_env.h
vendored
14
base-linux/src/base/env/platform_env.h
vendored
|
@ -432,13 +432,15 @@ namespace Genode {
|
||||||
*/
|
*/
|
||||||
~Platform_env() { _parent().exit(0); }
|
~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<Parent>::Dst, long)
|
void reinit(Native_capability::Dst, long);
|
||||||
{
|
void reinit_main_thread(Rm_session_capability &);
|
||||||
/* not supported on Linux */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
|
|
49
base-linux/src/base/thread/thread_env.cc
Normal file
49
base-linux/src/base/thread/thread_env.cc
Normal file
|
@ -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 <base/stdint.h>
|
||||||
|
#include <base/env.h>
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Implementation of the Thread API via Linux threads
|
* \brief Implementation of the Thread API via Linux threads
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2006-06-13
|
* \date 2006-06-13
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
extern int main_thread_futex_counter;
|
||||||
|
|
||||||
static void empty_signal_handler(int) { }
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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() { }
|
void Thread_base::_deinit_platform_thread() { }
|
||||||
|
|
|
@ -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);
|
_tid.meta_data = new (env()->heap()) Thread_meta_data_created(this);
|
||||||
|
|
||||||
|
|
|
@ -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 <base/thread.h>
|
|
||||||
#include <linux_syscalls.h>
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -102,7 +102,7 @@ namespace Genode {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Capability_map : Noncopyable
|
class Capability_map : private Noncopyable
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
LIBS += cxx startup
|
LIBS += cxx startup
|
||||||
|
|
||||||
SRC_CC += main_bootstrap.cc
|
|
||||||
SRC_CC += ipc/ipc.cc ipc/pager.cc
|
SRC_CC += ipc/ipc.cc ipc/pager.cc
|
||||||
SRC_CC += avl_tree/avl_tree.cc
|
SRC_CC += avl_tree/avl_tree.cc
|
||||||
SRC_CC += allocator/slab.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/lock
|
||||||
INC_DIR += $(BASE_DIR)/src/base/thread
|
INC_DIR += $(BASE_DIR)/src/base/thread
|
||||||
|
|
||||||
vpath main_bootstrap.cc $(REP_DIR)/src/platform
|
vpath %.cc $(REP_DIR)/src/base
|
||||||
vpath %.cc $(REP_DIR)/src/base
|
vpath %.cc $(BASE_DIR)/src/base
|
||||||
vpath %.cc $(BASE_DIR)/src/base
|
|
||||||
|
|
||||||
# vi: set ft=make :
|
# vi: set ft=make :
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
LIBS += base-common
|
LIBS += base-common
|
||||||
|
|
||||||
SRC_CC += console/log_console.cc
|
SRC_CC += console/log_console.cc
|
||||||
SRC_CC += env/env.cc env/main_thread.cc \
|
SRC_CC += env/env.cc env/context_area.cc env/reinitialize.cc
|
||||||
env/context_area.cc env/reinitialize.cc
|
|
||||||
SRC_CC += thread/thread_nova.cc
|
SRC_CC += thread/thread_nova.cc
|
||||||
|
|
||||||
INC_DIR += $(BASE_DIR)/src/base/env
|
INC_DIR += $(BASE_DIR)/src/base/env
|
||||||
|
|
31
base-nova/src/base/env/main_thread.cc
vendored
31
base-nova/src/base/env/main_thread.cc
vendored
|
@ -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 <base/native_types.h>
|
|
||||||
|
|
||||||
/* NOVA includes */
|
|
||||||
#include <nova/syscalls.h>
|
|
||||||
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
Native_utcb *main_thread_utcb()
|
|
||||||
{
|
|
||||||
return reinterpret_cast<Native_utcb *>(
|
|
||||||
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; }
|
|
|
@ -1,6 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* \brief Thread-context specific part of the thread library
|
* \brief Thread-context specific part of the thread library
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Alexander Boettcher
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2010-01-19
|
* \date 2010-01-19
|
||||||
*
|
*
|
||||||
* This part of the thread library is required by the IPC framework
|
* 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.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <util/construct_at.h>
|
||||||
|
#include <base/env.h>
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
|
|
||||||
|
/* base-nova includes */
|
||||||
|
#include <base/cap_map.h>
|
||||||
|
|
||||||
using namespace Genode;
|
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_utcb *>(
|
||||||
|
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<Cap_range *>(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<Capability_map>(cap_map());
|
||||||
|
construct_at<Initial_cap_range>(initial_cap_range());
|
||||||
|
prepare_init_main_thread();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
** Thread_base **
|
||||||
|
*****************/
|
||||||
|
|
||||||
Native_utcb *Thread_base::utcb()
|
Native_utcb *Thread_base::utcb()
|
||||||
{
|
{
|
||||||
|
@ -34,5 +121,3 @@ Native_utcb *Thread_base::utcb()
|
||||||
|
|
||||||
return &_context->utcb;
|
return &_context->utcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ void Thread_base::_thread_start()
|
||||||
** Thread base **
|
** Thread base **
|
||||||
*****************/
|
*****************/
|
||||||
|
|
||||||
void Thread_base::_init_platform_thread()
|
void Thread_base::_init_platform_thread(Type type)
|
||||||
{
|
{
|
||||||
using namespace Nova;
|
using namespace Nova;
|
||||||
|
|
||||||
|
@ -74,7 +74,15 @@ void Thread_base::_init_platform_thread()
|
||||||
* Allocate capability selectors for the thread's execution context,
|
* Allocate capability selectors for the thread's execution context,
|
||||||
* running semaphore and exception handler portals.
|
* 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);
|
_tid.exc_pt_sel = cap_map()->insert(NUM_INITIAL_PT_LOG2);
|
||||||
if (_tid.exc_pt_sel == Native_thread::INVALID_INDEX)
|
if (_tid.exc_pt_sel == Native_thread::INVALID_INDEX)
|
||||||
throw Cpu_session::Thread_creation_failed();
|
throw Cpu_session::Thread_creation_failed();
|
||||||
|
|
|
@ -106,7 +106,7 @@ int Platform_thread::start(void *ip, void *sp)
|
||||||
|
|
||||||
if (!is_vcpu()) {
|
if (!is_vcpu()) {
|
||||||
pd_utcb = Native_config::context_area_virtual_base() +
|
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_src[] = { _pd->parent_pt_sel() };
|
||||||
addr_t remap_dst[] = { PT_SEL_PARENT };
|
addr_t remap_dst[] = { PT_SEL_PARENT };
|
||||||
|
|
|
@ -27,7 +27,6 @@ SRC_CC = main.cc \
|
||||||
signal_source_component.cc \
|
signal_source_component.cc \
|
||||||
trace_session_component.cc \
|
trace_session_component.cc \
|
||||||
core_rm_session.cc \
|
core_rm_session.cc \
|
||||||
main_thread.cc \
|
|
||||||
context_area.cc \
|
context_area.cc \
|
||||||
echo.cc \
|
echo.cc \
|
||||||
dump_alloc.cc \
|
dump_alloc.cc \
|
||||||
|
@ -59,5 +58,4 @@ vpath platform_services.cc $(GEN_CORE_DIR)/x86
|
||||||
vpath context_area.cc $(GEN_CORE_DIR)
|
vpath context_area.cc $(GEN_CORE_DIR)
|
||||||
vpath core_printf.cc $(BASE_DIR)/src/base/console
|
vpath core_printf.cc $(BASE_DIR)/src/base/console
|
||||||
vpath %.cc $(REP_DIR)/src/core
|
vpath %.cc $(REP_DIR)/src/core
|
||||||
vpath main_thread.cc $(REP_DIR)/src/base/env
|
|
||||||
vpath pager.cc $(REP_DIR)/src/base/pager
|
vpath pager.cc $(REP_DIR)/src/base/pager
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
using namespace Genode;
|
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
|
* This function is called for constructing server activations and pager
|
||||||
|
@ -36,6 +36,20 @@ void Thread_base::_init_platform_thread()
|
||||||
*/
|
*/
|
||||||
using namespace Nova;
|
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.ec_sel = cap_map()->insert(1);
|
||||||
_tid.exc_pt_sel = cap_map()->insert(NUM_INITIAL_PT_LOG2);
|
_tid.exc_pt_sel = cap_map()->insert(NUM_INITIAL_PT_LOG2);
|
||||||
addr_t pd_sel = Platform_pd::pd_core_sel();
|
addr_t pd_sel = Platform_pd::pd_core_sel();
|
||||||
|
|
|
@ -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 <base/cap_map.h>
|
|
||||||
#include <base/env.h>
|
|
||||||
|
|
||||||
#include <base/printf.h>
|
|
||||||
|
|
||||||
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<Cap_range *>(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;
|
|
||||||
}
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
LIBS += cxx startup
|
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 += ipc/ipc.cc ipc/pager.cc ipc/ipc_marshal_cap.cc
|
||||||
SRC_CC += pager/pager.cc pager/common.cc
|
SRC_CC += pager/pager.cc pager/common.cc
|
||||||
SRC_CC += avl_tree/avl_tree.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 += $(REP_DIR)/src/base/lock
|
||||||
INC_DIR += $(BASE_DIR)/src/base/thread
|
INC_DIR += $(BASE_DIR)/src/base/thread
|
||||||
|
|
||||||
vpath main_bootstrap.cc $(REP_DIR)/src/platform
|
vpath cap_copy.cc $(BASE_DIR)/src/platform
|
||||||
vpath cap_copy.cc $(BASE_DIR)/src/platform
|
vpath %.cc $(REP_DIR)/src/base
|
||||||
vpath %.cc $(REP_DIR)/src/base
|
vpath %.cc $(BASE_DIR)/src/base
|
||||||
vpath %.cc $(BASE_DIR)/src/base
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Default thread bootstrap code
|
* \brief Default thread bootstrap code
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2009-04-02
|
* \date 2009-04-02
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -11,19 +12,74 @@
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
|
|
||||||
namespace Okl4 { extern "C" {
|
/* OKL4 includes */
|
||||||
#include <l4/utcb.h>
|
namespace Okl4
|
||||||
#include <l4/thread.h>
|
{
|
||||||
} }
|
extern "C" {
|
||||||
|
#include <l4/utcb.h>
|
||||||
namespace Okl4 {
|
#include <l4/thread.h>
|
||||||
extern L4_Word_t copy_uregister_to_utcb(void);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
void Genode::Thread_base::_thread_bootstrap()
|
||||||
{
|
{
|
||||||
_tid.l4id.raw = Okl4::copy_uregister_to_utcb();
|
_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;
|
||||||
|
}
|
||||||
|
|
|
@ -50,9 +50,6 @@ void Thread_base::cancel_blocking()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::_init_platform_thread() { }
|
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::_deinit_platform_thread()
|
void Thread_base::_deinit_platform_thread()
|
||||||
{
|
{
|
||||||
/* destruct platform thread */
|
/* destruct platform thread */
|
||||||
|
|
|
@ -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 <base/native_types.h>
|
|
||||||
|
|
||||||
/* OKL4-specific includes and definitions */
|
|
||||||
namespace Okl4 { extern "C" {
|
|
||||||
#include <l4/utcb.h>
|
|
||||||
#include <l4/thread.h>
|
|
||||||
} }
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
LIBS += cxx startup
|
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 += ipc/ipc.cc ipc/pager.cc ipc/ipc_marshal_cap.cc
|
||||||
SRC_CC += pager/pager.cc pager/common.cc
|
SRC_CC += pager/pager.cc pager/common.cc
|
||||||
SRC_CC += avl_tree/avl_tree.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 += $(REP_DIR)/src/base/lock
|
||||||
INC_DIR += $(BASE_DIR)/src/base/thread
|
INC_DIR += $(BASE_DIR)/src/base/thread
|
||||||
|
|
||||||
vpath main_bootstrap.cc $(REP_DIR)/src/platform
|
vpath cap_copy.cc $(BASE_DIR)/src/platform
|
||||||
vpath cap_copy.cc $(BASE_DIR)/src/platform
|
vpath %.cc $(REP_DIR)/src/base
|
||||||
vpath %.cc $(REP_DIR)/src/base
|
vpath %.cc $(BASE_DIR)/src/base
|
||||||
vpath %.cc $(BASE_DIR)/src/base
|
|
||||||
|
|
|
@ -15,11 +15,38 @@
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
|
|
||||||
/* Pistachio includes */
|
/* Pistachio includes */
|
||||||
namespace Pistachio {
|
namespace Pistachio
|
||||||
#include <l4/thread.h>
|
{
|
||||||
|
#include <l4/thread.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
void Genode::Thread_base::_thread_bootstrap()
|
||||||
{
|
{
|
||||||
_tid.l4id = Pistachio::L4_Myself();
|
_tid.l4id = Pistachio::L4_Myself();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Genode::Thread_base::_init_platform_thread(Type type)
|
||||||
|
{
|
||||||
|
if (type == NORMAL) { return; }
|
||||||
|
_tid.l4id = main_thread_tid;
|
||||||
|
}
|
||||||
|
|
|
@ -53,9 +53,6 @@ void Thread_base::cancel_blocking()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::_init_platform_thread() { }
|
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::_deinit_platform_thread()
|
void Thread_base::_deinit_platform_thread()
|
||||||
{
|
{
|
||||||
/* destruct platform thread */
|
/* destruct platform thread */
|
||||||
|
|
|
@ -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 <base/native_types.h>
|
|
||||||
|
|
||||||
/* Pistachio includes */
|
|
||||||
namespace Pistachio {
|
|
||||||
#include <l4/thread.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -73,20 +73,6 @@ namespace Genode {
|
||||||
* Heap backed by the ram_session of the environment.
|
* Heap backed by the ram_session of the environment.
|
||||||
*/
|
*/
|
||||||
virtual Allocator *heap() = 0;
|
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<Parent>::Dst, long) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Env *env();
|
extern Env *env();
|
||||||
|
|
|
@ -185,11 +185,13 @@ namespace Genode {
|
||||||
/**
|
/**
|
||||||
* Allocate thread context for specified thread
|
* Allocate thread context for specified thread
|
||||||
*
|
*
|
||||||
* \param thread thread for which to allocate the new context
|
* \param thread thread for which to allocate the new context
|
||||||
* \return virtual address of new thread context, or
|
* \param main_thread wether to alloc for the main thread
|
||||||
* 0 if the allocation failed
|
*
|
||||||
|
* \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
|
* Release thread context
|
||||||
|
@ -224,8 +226,11 @@ namespace Genode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate and locally attach a new thread context
|
* 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
|
* Detach and release thread context of the thread
|
||||||
|
@ -246,11 +251,6 @@ namespace Genode {
|
||||||
*/
|
*/
|
||||||
static void _thread_start();
|
static void _thread_start();
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook for platform-specific constructor supplements
|
|
||||||
*/
|
|
||||||
void _init_platform_thread();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook for platform-specific destructor supplements
|
* Hook for platform-specific destructor supplements
|
||||||
*/
|
*/
|
||||||
|
@ -285,6 +285,14 @@ namespace Genode {
|
||||||
*/
|
*/
|
||||||
Genode::Lock _join_lock;
|
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:
|
private:
|
||||||
|
|
||||||
Trace::Logger _trace_logger;
|
Trace::Logger _trace_logger;
|
||||||
|
@ -296,6 +304,13 @@ namespace Genode {
|
||||||
*/
|
*/
|
||||||
static Trace::Logger *_logger();
|
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:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -303,6 +318,7 @@ namespace Genode {
|
||||||
*
|
*
|
||||||
* \param name thread name for debugging
|
* \param name thread name for debugging
|
||||||
* \param stack_size stack size
|
* \param stack_size stack size
|
||||||
|
* \param type enables selection of special construction
|
||||||
*
|
*
|
||||||
* \throw Stack_too_large
|
* \throw Stack_too_large
|
||||||
* \throw Stack_alloc_failed
|
* \throw Stack_alloc_failed
|
||||||
|
@ -313,8 +329,14 @@ namespace Genode {
|
||||||
* stack size is internally used by the framework for storing
|
* stack size is internally used by the framework for storing
|
||||||
* thread-context information such as the thread's name (see
|
* thread-context information such as the thread's name (see
|
||||||
* 'struct Context').
|
* '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
|
* Destructor
|
||||||
|
@ -448,9 +470,10 @@ namespace Genode {
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* \param name thread name (for debugging)
|
* \param name thread name (for debugging)
|
||||||
|
* \param type enables selection of special construction
|
||||||
*/
|
*/
|
||||||
explicit Thread(const char *name)
|
explicit Thread(const char *name, Type type = NORMAL)
|
||||||
: Thread_base(name, STACK_SIZE) { }
|
: Thread_base(name, STACK_SIZE, type) { }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
SRC_S += crt0.s
|
SRC_S += crt0.s
|
||||||
SRC_CC += _main.cc
|
SRC_CC += _main.cc
|
||||||
|
SRC_CC += init_main_thread.cc
|
||||||
|
|
||||||
REP_INC_DIR += src/platform
|
REP_INC_DIR += src/platform
|
||||||
|
|
||||||
LIBS += syscall
|
LIBS += syscall
|
||||||
|
|
||||||
vpath _main.cc $(BASE_DIR)/src/platform
|
vpath _main.cc $(BASE_DIR)/src/platform
|
||||||
|
vpath init_main_thread.cc $(BASE_DIR)/src/platform
|
||||||
|
|
|
@ -84,6 +84,15 @@ LIBS += $(BASE_LIBS)
|
||||||
else
|
else
|
||||||
LIBS := $(filter-out $(BASE_LIBS),$(LIBS))
|
LIBS := $(filter-out $(BASE_LIBS),$(LIBS))
|
||||||
LIBS += $(DYNAMIC_LINKER)
|
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
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -125,9 +125,15 @@ $(LIB_A): $(OBJECTS)
|
||||||
$(VERBOSE)$(AR) -rc $@ $(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
|
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)
|
ifneq ($(LIB),ld)
|
||||||
override DEPS := $(filter-out startup.lib,$(DEPS))
|
override DEPS := $(filter-out startup.lib,$(DEPS))
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -120,9 +120,13 @@ LD_CMD += -Wl,--dynamic-linker=$(DYNAMIC_LINKER).lib.so \
|
||||||
-Wl,--eh-frame-hdr
|
-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
|
SHARED_LIBS += $(LIB_CACHE_DIR)/$(DYNAMIC_LINKER)/$(DYNAMIC_LINKER).lib.so
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
30
base/src/base/env/platform_env.h
vendored
30
base/src/base/env/platform_env.h
vendored
|
@ -23,7 +23,7 @@
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/printf.h>
|
#include <base/printf.h>
|
||||||
#include <base/env.h>
|
#include <base/env.h>
|
||||||
#include <base/heap.h>
|
#include <base/heap.h>
|
||||||
|
|
||||||
/* local includes */
|
/* local includes */
|
||||||
#include <platform_env_common.h>
|
#include <platform_env_common.h>
|
||||||
|
@ -36,7 +36,9 @@ namespace Genode {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Genode::Expanding_rm_session_client : Upgradeable_client<Genode::Rm_session_client>
|
struct Genode::Expanding_rm_session_client
|
||||||
|
:
|
||||||
|
Upgradeable_client<Genode::Rm_session_client>
|
||||||
{
|
{
|
||||||
Expanding_rm_session_client(Rm_session_capability cap)
|
Expanding_rm_session_client(Rm_session_capability cap)
|
||||||
: Upgradeable_client<Genode::Rm_session_client>(cap) { }
|
: Upgradeable_client<Genode::Rm_session_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()))
|
_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 &);
|
||||||
|
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
|
|
55
base/src/base/env/reinitialize.cc
vendored
55
base/src/base/env/reinitialize.cc
vendored
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Environment reinitialization
|
* \brief Environment reinitialization
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2012-02-16
|
* \date 2012-02-16
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -11,12 +12,28 @@
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* env includes */
|
||||||
#include <platform_env.h>
|
#include <platform_env.h>
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <util/construct_at.h>
|
||||||
#include <base/crt0.h>
|
#include <base/crt0.h>
|
||||||
|
#include <rm_session/connection.h>
|
||||||
|
|
||||||
|
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,
|
void Genode::Platform_env::reinit(Native_capability::Dst dst,
|
||||||
long local_name)
|
long local_name)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This function is unused during the normal operation of Genode. It is
|
* 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.
|
* 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
|
* Patch new parent capability into the original location as specified by
|
||||||
* the linker script.
|
* the linker script.
|
||||||
*/
|
*/
|
||||||
Native_capability::Raw *raw = (Native_capability::Raw *)(&_parent_cap);
|
Native_capability::Raw *raw = (Native_capability::Raw *)(&_parent_cap);
|
||||||
|
raw->dst = dst;
|
||||||
raw->dst = dst;
|
raw->local_name = local_name;
|
||||||
raw->local_name = local_name;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Re-initialize 'Platform_env' members
|
* Re-initialize 'Platform_env' members
|
||||||
*/
|
*/
|
||||||
static_cast<Parent_client &>(_parent_client) = Parent_client(Genode::parent_cap());
|
Expanding_parent_client * const p = &_parent_client;
|
||||||
|
construct_at<Expanding_parent_client>(p, parent_cap(), *this);
|
||||||
_resources = Resources(_parent_client);
|
construct_at<Resources>(&_resources, _parent_client);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keep information about dynamically allocated memory but use the new
|
* 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);
|
_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<Rm_session_client *>(rms);
|
||||||
|
construct_at<Rm_session_client>(rmc, context_area_rm);
|
||||||
|
|
||||||
|
/* re-enable tracing */
|
||||||
|
inhibit_tracing = false;
|
||||||
|
|
||||||
|
/* reinitialize main-thread object */
|
||||||
|
::reinit_main_thread();
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
size_t Thread_base::Context_allocator::base_to_idx(addr_t base)
|
||||||
{
|
{
|
||||||
return (base - Native_config::context_area_virtual_base()) /
|
/* the first context isn't managed through the indices */
|
||||||
Native_config::context_virtual_size();
|
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)
|
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() +
|
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);
|
Lock::Guard _lock_guard(_threads_lock);
|
||||||
|
|
||||||
try {
|
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<MAX_THREADS>::Out_of_indices) {
|
} catch(Bit_allocator<MAX_THREADS>::Out_of_indices) {
|
||||||
return 0;
|
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)
|
void Thread_base::Context_allocator::free(Context *context)
|
||||||
{
|
{
|
||||||
Lock::Guard _lock_guard(_threads_lock);
|
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
|
* 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);
|
Lock::Guard _lock_guard(alloc_lock);
|
||||||
|
|
||||||
/* allocate thread context */
|
/* allocate thread context */
|
||||||
Context *context = _context_allocator()->alloc(this);
|
Context *context = _context_allocator()->alloc(this, main_thread);
|
||||||
if (!context)
|
if (!context)
|
||||||
throw Context_alloc_failed();
|
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)
|
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));
|
strncpy(context->name, name, sizeof(context->name));
|
||||||
return (void *)context->stack_top();
|
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)
|
_join_lock(Lock::LOCKED)
|
||||||
{
|
{
|
||||||
strncpy(_context->name, name, sizeof(_context->name));
|
strncpy(_context->name, name, sizeof(_context->name));
|
||||||
_init_platform_thread();
|
_init_platform_thread(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,6 @@ void Thread_base::_thread_start()
|
||||||
** Thread base **
|
** Thread base **
|
||||||
*****************/
|
*****************/
|
||||||
|
|
||||||
void Thread_base::_init_platform_thread() { }
|
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::_deinit_platform_thread()
|
void Thread_base::_deinit_platform_thread()
|
||||||
{
|
{
|
||||||
env()->cpu_session()->kill_thread(_thread_cap);
|
env()->cpu_session()->kill_thread(_thread_cap);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <base/env.h>
|
#include <base/env.h>
|
||||||
#include <base/heap.h>
|
#include <base/heap.h>
|
||||||
#include <ram_session/client.h>
|
#include <ram_session/client.h>
|
||||||
|
#include <rm_session/capability.h>
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
|
@ -174,7 +175,9 @@ namespace Genode {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reload_parent_cap(Capability<Parent>::Dst, long) { }
|
void reinit(Capability<Parent>::Dst, long) { }
|
||||||
|
|
||||||
|
void reinit_main_thread(Rm_session_capability &) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,13 +31,8 @@
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
extern int main(int argc, char **argv, char **envp);
|
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 };
|
enum { ATEXIT_SIZE = 256 };
|
||||||
|
|
||||||
|
@ -46,6 +41,8 @@ enum { ATEXIT_SIZE = 256 };
|
||||||
** C++ stuff **
|
** C++ stuff **
|
||||||
***************/
|
***************/
|
||||||
|
|
||||||
|
void * __dso_handle = 0;
|
||||||
|
|
||||||
enum Atexit_fn_type { ATEXIT_FN_EMPTY, ATEXIT_FN_STD, ATEXIT_FN_CXA };
|
enum Atexit_fn_type { ATEXIT_FN_EMPTY, ATEXIT_FN_STD, ATEXIT_FN_CXA };
|
||||||
|
|
||||||
struct atexit_fn
|
struct atexit_fn
|
||||||
|
@ -229,11 +226,6 @@ namespace Genode { extern bool inhibit_tracing; }
|
||||||
*/
|
*/
|
||||||
extern "C" int _main()
|
extern "C" int _main()
|
||||||
{
|
{
|
||||||
platform_main_bootstrap();
|
|
||||||
|
|
||||||
/* call env() explicitly to setup the environment */
|
|
||||||
(void*)env();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allow exit handlers to be registered.
|
* Allow exit handlers to be registered.
|
||||||
*
|
*
|
||||||
|
@ -244,34 +236,6 @@ extern "C" int _main()
|
||||||
*/
|
*/
|
||||||
atexit_enable();
|
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 */
|
/* call constructors for static objects */
|
||||||
void (**func)();
|
void (**func)();
|
||||||
for (func = &_ctors_end; func != &_ctors_start; (*--func)());
|
for (func = &_ctors_end; func != &_ctors_start; (*--func)());
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* \brief Startup code for Genode applications on ARM
|
* \brief Startup code for Genode applications on ARM
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2007-04-28
|
* \date 2007-04-28
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -11,34 +12,58 @@
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*--- .text (program code) -------------------------*/
|
|
||||||
|
/**************************
|
||||||
|
** .text (program code) **
|
||||||
|
**************************/
|
||||||
|
|
||||||
.section ".text.crt0"
|
.section ".text.crt0"
|
||||||
|
|
||||||
.globl _start
|
/* program entry-point */
|
||||||
_start:
|
.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]
|
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
|
/* create proper environment for main thread */
|
||||||
.stack_high: .word _stack_high
|
bl init_main_thread
|
||||||
|
|
||||||
.globl __dso_handle
|
/* apply environment that was created by init_main_thread */
|
||||||
__dso_handle: .long 0
|
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"
|
.section ".bss"
|
||||||
|
|
||||||
|
/* stack of the temporary initial environment */
|
||||||
.p2align 4
|
.p2align 4
|
||||||
.globl _stack_low
|
.global _stack_low
|
||||||
_stack_low:
|
_stack_low:
|
||||||
.space 128*1024
|
.space 128 * 1024
|
||||||
.globl _stack_high
|
.global _stack_high
|
||||||
_stack_high:
|
_stack_high:
|
||||||
|
|
||||||
/* initial value of the SP register */
|
/* initial value of the SP register */
|
||||||
.globl __initial_sp
|
.global __initial_sp
|
||||||
__initial_sp: .space 4
|
__initial_sp:
|
||||||
|
.space 4
|
||||||
|
|
||||||
|
/* return value of init_main_thread */
|
||||||
|
.global init_main_thread_result
|
||||||
|
init_main_thread_result:
|
||||||
|
.space 4
|
||||||
|
|
130
base/src/platform/init_main_thread.cc
Normal file
130
base/src/platform/init_main_thread.cc
Normal file
|
@ -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 <util/construct_at.h>
|
||||||
|
#include <base/env.h>
|
||||||
|
#include <base/printf.h>
|
||||||
|
#include <base/thread.h>
|
||||||
|
|
||||||
|
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<MAIN_THREAD_STACK_SIZE>
|
||||||
|
{
|
||||||
|
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<addr_t>(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>(main_thread(), true); }
|
|
@ -1,6 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* \brief Startup code for Genode applications
|
* \brief Startup code for Genode applications
|
||||||
* \author Christian Helmuth
|
* \author Christian Helmuth
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2009-08-12
|
* \date 2009-08-12
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -11,53 +12,79 @@
|
||||||
* under the terms of the GNU General Public License version 2.
|
* 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 %esp, __initial_sp
|
||||||
mov %eax, __initial_ax
|
mov %eax, __initial_ax
|
||||||
mov %edi, __initial_di
|
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
|
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
|
xor %ebp,%ebp
|
||||||
|
|
||||||
/* Jump into init C code */
|
/* jump into init C code instead of calling it as it should never return */
|
||||||
call _main
|
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__
|
.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
|
.p2align 4
|
||||||
.global _stack_low
|
.global _stack_low
|
||||||
_stack_low:
|
_stack_low:
|
||||||
.space 64*1024
|
.space 64 * 1024
|
||||||
.global _stack_high
|
.global _stack_high
|
||||||
_stack_high:
|
_stack_high:
|
||||||
|
|
||||||
/* initial value of the ESP, EAX and EDI register */
|
/* initial value of the ESP, EAX and EDI register */
|
||||||
.globl __initial_sp
|
.global __initial_sp
|
||||||
.globl __initial_ax
|
__initial_sp:
|
||||||
.globl __initial_di
|
.space 4
|
||||||
__initial_sp: .space 4
|
.global __initial_ax
|
||||||
__initial_ax: .space 4
|
__initial_ax:
|
||||||
__initial_di: .space 4
|
.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
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* \brief Startup code for Genode 64Bit applications
|
* \brief Startup code for Genode 64Bit applications
|
||||||
* \author Sebastian Sumpf
|
* \author Sebastian Sumpf
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2011-05-11
|
* \date 2011-05-11
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -11,60 +12,90 @@
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*--- .text (program code) -------------------------*/
|
|
||||||
.text
|
/**************************
|
||||||
|
** .text (program code) **
|
||||||
|
**************************/
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
/* program entry-point */
|
||||||
.global _start
|
.global _start
|
||||||
|
_start:
|
||||||
|
|
||||||
_start:
|
/* make initial value of some registers available to higher-level code */
|
||||||
|
|
||||||
movq __initial_ax@GOTPCREL(%rip), %rbx
|
movq __initial_ax@GOTPCREL(%rip), %rbx
|
||||||
movq %rax, (%rbx)
|
movq %rax, (%rbx)
|
||||||
|
|
||||||
movq __initial_di@GOTPCREL(%rip), %rbx
|
movq __initial_di@GOTPCREL(%rip), %rbx
|
||||||
movq %rdi, (%rbx)
|
movq %rdi, (%rbx)
|
||||||
|
|
||||||
movq __initial_sp@GOTPCREL(%rip), %rax
|
movq __initial_sp@GOTPCREL(%rip), %rax
|
||||||
movq %rsp, (%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
|
leaq _stack_high@GOTPCREL(%rip),%rax
|
||||||
movq (%rax), %rsp
|
movq (%rax), %rsp
|
||||||
|
|
||||||
/* Clear the base pointer so that stack backtraces will work. */
|
/* create proper environment for the main thread */
|
||||||
xorq %rbp,%rbp
|
call init_main_thread
|
||||||
|
|
||||||
/* Jump into init C code */
|
/* apply environment that was created by init_main_thread */
|
||||||
call _main
|
movq init_main_thread_result@GOTPCREL(%rip), %rax
|
||||||
|
movq (%rax), %rsp
|
||||||
|
|
||||||
/* We should never get here since _main does not return */
|
/* clear the base pointer in order that stack backtraces will work */
|
||||||
1: int $3
|
xorq %rbp, %rbp
|
||||||
jmp 2f
|
|
||||||
.ascii "_main() returned."
|
|
||||||
2: jmp 1b
|
|
||||||
|
|
||||||
.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__
|
.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
|
.p2align 8
|
||||||
.global _stack_low
|
.global _stack_low
|
||||||
_stack_low:
|
_stack_low:
|
||||||
.space 64*1024
|
.space 64 * 1024
|
||||||
.global _stack_high
|
.global _stack_high
|
||||||
_stack_high:
|
_stack_high:
|
||||||
|
|
||||||
/* initial value of the RSP, RAX and RDI register */
|
/* initial value of the RSP, RAX and RDI register */
|
||||||
.globl __initial_sp
|
.globl __initial_sp
|
||||||
|
__initial_sp:
|
||||||
|
.space 8
|
||||||
.globl __initial_ax
|
.globl __initial_ax
|
||||||
|
__initial_ax:
|
||||||
|
.space 8
|
||||||
.globl __initial_di
|
.globl __initial_di
|
||||||
__initial_sp: .space 8
|
__initial_di:
|
||||||
__initial_ax: .space 8
|
.space 8
|
||||||
__initial_di: .space 8
|
|
||||||
|
/* return value of init_main_thread */
|
||||||
|
.globl init_main_thread_result
|
||||||
|
init_main_thread_result:
|
||||||
|
.space 8
|
||||||
|
|
|
@ -7,8 +7,6 @@ INC_DIR += $(REP_DIR)/src/lib/ffat/contrib
|
||||||
SRC_C = ff.c ccsbcs.c
|
SRC_C = ff.c ccsbcs.c
|
||||||
SRC_CC = diskio_block.cc
|
SRC_CC = diskio_block.cc
|
||||||
|
|
||||||
LIBS = base
|
|
||||||
|
|
||||||
vpath % $(REP_DIR)/src/lib/ffat/
|
vpath % $(REP_DIR)/src/lib/ffat/
|
||||||
vpath % $(REP_DIR)/contrib/ff007e/src
|
vpath % $(REP_DIR)/contrib/ff007e/src
|
||||||
vpath % $(REP_DIR)/contrib/ff007e/src/option
|
vpath % $(REP_DIR)/contrib/ff007e/src/option
|
||||||
|
|
5
os/lib/mk/startup_dyn.mk
Normal file
5
os/lib/mk/startup_dyn.mk
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
SRC_CC += _main.cc
|
||||||
|
|
||||||
|
REP_INC_DIR += src/platform
|
||||||
|
|
||||||
|
vpath _main.cc $(BASE_DIR)/src/platform
|
|
@ -1,6 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* \brief Startup code for Genode applications on ARM
|
* \brief Startup code for Genode applications on ARM
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2007-04-28
|
* \date 2007-04-28
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -11,19 +12,40 @@
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*--- .text (program code) -------------------------*/
|
|
||||||
|
/**************************
|
||||||
|
** .text (program code) **
|
||||||
|
**************************/
|
||||||
|
|
||||||
.section ".text.crt0"
|
.section ".text.crt0"
|
||||||
|
|
||||||
|
/* linker entry-point */
|
||||||
.globl _start_ldso
|
.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]
|
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
|
bl init_rtld
|
||||||
b _main
|
|
||||||
|
|
||||||
.initial_sp: .word __initial_sp
|
/* create proper environment for the main thread */
|
||||||
.stack_high: .word _stack_high
|
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
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Call main function (ARM specific)
|
* \brief Call main function (ARM specific)
|
||||||
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2011-05-05
|
* \date 2011-05-05
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -13,20 +14,32 @@
|
||||||
#ifndef _ARM__CALL_MAIN_H_
|
#ifndef _ARM__CALL_MAIN_H_
|
||||||
#define _ARM__CALL_MAIN_H_
|
#define _ARM__CALL_MAIN_H_
|
||||||
|
|
||||||
/**
|
void * my_stack_top();
|
||||||
* Restore SP from initial sp and jump to entry function
|
void set_program_var(const char *, const void *);
|
||||||
*/
|
|
||||||
void call_main(void (*func)(void))
|
|
||||||
{
|
|
||||||
extern long __initial_sp;
|
|
||||||
|
|
||||||
asm volatile ("mov %%sp, %0;"
|
extern void * __initial_sp;
|
||||||
"bx %1;"
|
|
||||||
:
|
/**
|
||||||
: "r" (__initial_sp),
|
* Call program _main with the environment that its CRT0 would have created
|
||||||
"r" (func)
|
*
|
||||||
: "memory"
|
* \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_ */
|
#endif /* _ARM__CALL_MAIN_H_ */
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Call main function (X86 specific)
|
* \brief Call main function (X86 specific)
|
||||||
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2011-05-02
|
* \date 2011-05-02
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -13,20 +14,37 @@
|
||||||
#ifndef _X86_32__CALL_MAIN_H_
|
#ifndef _X86_32__CALL_MAIN_H_
|
||||||
#define _X86_32__CALL_MAIN_H_
|
#define _X86_32__CALL_MAIN_H_
|
||||||
|
|
||||||
/**
|
void * my_stack_top();
|
||||||
* Restore SP from initial sp and jump to entry function
|
void set_program_var(const char *, const void *);
|
||||||
*/
|
|
||||||
void call_main(void (*func)(void))
|
|
||||||
{
|
|
||||||
extern long __initial_sp;
|
|
||||||
|
|
||||||
asm volatile ("mov %0, %%esp;"
|
extern void * __initial_sp;
|
||||||
"jmp *%1;"
|
extern void * __initial_ax;
|
||||||
:
|
extern void * __initial_di;
|
||||||
: "r" (__initial_sp),
|
|
||||||
"r" (func)
|
/**
|
||||||
: "memory"
|
* 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_ */
|
#endif /* _X86_32__CALL_MAIN_H_ */
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Call main function (X86 64 bit specific)
|
* \brief Call main function (X86 64 bit specific)
|
||||||
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2011-05-011
|
* \date 2011-05-011
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -13,20 +14,37 @@
|
||||||
#ifndef _X86_64__CALL_MAIN_H_
|
#ifndef _X86_64__CALL_MAIN_H_
|
||||||
#define _X86_64__CALL_MAIN_H_
|
#define _X86_64__CALL_MAIN_H_
|
||||||
|
|
||||||
/**
|
void * my_stack_top();
|
||||||
* Restore SP from initial sp and jump to entry function
|
void set_program_var(const char *, const void *);
|
||||||
*/
|
|
||||||
void call_main(void (*func)(void))
|
|
||||||
{
|
|
||||||
extern long __initial_sp;
|
|
||||||
|
|
||||||
asm volatile ("movq %0, %%rsp;"
|
extern void * __initial_sp;
|
||||||
"jmpq *%1;"
|
extern void * __initial_ax;
|
||||||
:
|
extern void * __initial_di;
|
||||||
: "r" (__initial_sp),
|
|
||||||
"r" (func)
|
/**
|
||||||
: "memory"
|
* 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_ */
|
#endif /* _X86_64__CALL_MAIN_H_ */
|
||||||
|
|
|
@ -7,7 +7,7 @@ SRC_S = rtld_start.S
|
||||||
SRC_C = reloc.c rtld.c map_object.c xmalloc.c debug.c main.c \
|
SRC_C = reloc.c rtld.c map_object.c xmalloc.c debug.c main.c \
|
||||||
ldso_types.c rtld_dummies.c platform.c
|
ldso_types.c rtld_dummies.c platform.c
|
||||||
SRC_CC = stdio.cc stdlib.cc file.cc err.cc string.cc lock.cc \
|
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)/ \
|
INC_DIR += $(DIR)/ \
|
||||||
$(DIR)/contrib \
|
$(DIR)/contrib \
|
||||||
|
|
24
os/src/lib/ldso/thread.cc
Normal file
24
os/src/lib/ldso/thread.cc
Normal file
|
@ -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 <base/thread.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return top end of the stack of the calling thread
|
||||||
|
*/
|
||||||
|
extern "C" void * my_stack_top()
|
||||||
|
{
|
||||||
|
return Genode::Thread_base::myself()->stack_top();
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
* \brief Startup code for ld.lib.so (x86-32)
|
* \brief Startup code for ld.lib.so (x86-32)
|
||||||
* \author Christian Helmuth
|
* \author Christian Helmuth
|
||||||
* \author Sebastian Sumpf
|
* \author Sebastian Sumpf
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2011-05-03
|
* \date 2011-05-03
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -12,39 +13,60 @@
|
||||||
* under the terms of the GNU General Public License version 2.
|
* 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
|
.global _start_ldso
|
||||||
|
_start_ldso:
|
||||||
|
|
||||||
_start_ldso:
|
/*
|
||||||
|
* Initialize GOT pointer in EBX.
|
||||||
/* initialize GOT pointer in EBX */
|
*
|
||||||
3:
|
* The follwing statement causes a text relocation which will be ignored
|
||||||
/* The follwing statement causes a text relocation which will be ignored by
|
* by ldso itself, this is necessary since we don't have a valid stack
|
||||||
* ldso itself, this is necessary since we don't have a valid stack pointer at
|
* pointer at this moment so a 'call' in order to retrieve our IP and thus
|
||||||
* this moment so a 'call' in order to retrieve our IP and thus calculate the
|
* calculate the GOT-position in the traditional manner is not possible on
|
||||||
* GOT-position in the traditional manner is not possible on x86
|
* x86.
|
||||||
*/
|
*/
|
||||||
|
3:
|
||||||
movl $., %ebx
|
movl $., %ebx
|
||||||
addl $_GLOBAL_OFFSET_TABLE_ + (. - 3b) , %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 %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
|
leal _stack_high@GOTOFF(%ebx), %esp
|
||||||
|
|
||||||
/* relocate ldso */
|
/* let init_rtld relocate LDSO */
|
||||||
call init_rtld
|
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
|
xor %ebp,%ebp
|
||||||
|
|
||||||
/* Jump into init C code */
|
/* jump into init C code */
|
||||||
call _main
|
call _main
|
||||||
|
|
||||||
/* We should never get here since _main does not return */
|
/* we should never get here since _main does not return */
|
||||||
1: int $3
|
1:
|
||||||
|
int $3
|
||||||
jmp 2f
|
jmp 2f
|
||||||
.ascii "_main() returned."
|
.ascii "_main() returned."
|
||||||
2: jmp 1b
|
2:
|
||||||
|
jmp 1b
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* \brief Startup code for ldso 64Bit version
|
* \brief Startup code for ldso 64Bit version
|
||||||
* \author Christian Helmuth
|
* \author Christian Helmuth
|
||||||
* \author Sebastian Sumpf
|
* \author Sebastian Sumpf
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2011-05-10
|
* \date 2011-05-10
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -12,32 +13,55 @@
|
||||||
* under the terms of the GNU General Public License version 2.
|
* 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
|
.globl _start_ldso
|
||||||
_start_ldso:
|
_start_ldso:
|
||||||
|
|
||||||
/* initialize GLOBAL OFFSET TABLE */
|
/* initialize global offset table */
|
||||||
leaq _GLOBAL_OFFSET_TABLE_(%rip),%r15
|
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 __initial_sp@GOTPCREL(%rip), %rax
|
||||||
movq %rsp, (%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
|
leaq _stack_high@GOTPCREL(%rip),%rax
|
||||||
movq (%rax), %rsp
|
movq (%rax), %rsp
|
||||||
|
|
||||||
|
/* let init_rtld relocate LDSO */
|
||||||
call init_rtld
|
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
|
xorq %rbp,%rbp
|
||||||
|
|
||||||
/* Jump into init C code */
|
/* jump into init C code */
|
||||||
call _main
|
call _main
|
||||||
|
|
||||||
/* We should never get here since _main does not return */
|
/* we should never get here since _main does not return */
|
||||||
1: int $3
|
1:
|
||||||
|
int $3
|
||||||
jmp 2f
|
jmp 2f
|
||||||
.ascii "_main() returned."
|
.ascii "_main() returned."
|
||||||
2: jmp 1b
|
2:
|
||||||
|
jmp 1b
|
||||||
|
|
|
@ -11,7 +11,12 @@
|
||||||
* under the terms of the GNU General Public License version 2.
|
* 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
|
PHDRS
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,8 @@ LIBS += libc
|
||||||
|
|
||||||
REP_INC_DIR += src/lib/libc
|
REP_INC_DIR += src/lib/libc
|
||||||
|
|
||||||
|
INC_DIR += $(BASE_DIR)/src/base/env/
|
||||||
|
|
||||||
vpath %.cc $(REP_DIR)/src/lib/libc_noux
|
vpath %.cc $(REP_DIR)/src/lib/libc_noux
|
||||||
|
|
||||||
SHARED_LIB = yes
|
SHARED_LIB = yes
|
||||||
|
|
|
@ -12,12 +12,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
|
#include <util/construct_at.h>
|
||||||
#include <util/misc_math.h>
|
#include <util/misc_math.h>
|
||||||
#include <util/arg_string.h>
|
#include <util/arg_string.h>
|
||||||
#include <base/printf.h>
|
#include <base/printf.h>
|
||||||
#include <rom_session/connection.h>
|
#include <rom_session/connection.h>
|
||||||
#include <base/sleep.h>
|
#include <base/sleep.h>
|
||||||
#include <dataspace/client.h>
|
#include <dataspace/client.h>
|
||||||
|
#include <platform_env.h>
|
||||||
|
|
||||||
/* noux includes */
|
/* noux includes */
|
||||||
#include <noux_session/connection.h>
|
#include <noux_session/connection.h>
|
||||||
|
@ -60,9 +62,6 @@ enum { verbose = false };
|
||||||
enum { verbose_signals = false };
|
enum { verbose_signals = false };
|
||||||
|
|
||||||
|
|
||||||
void *operator new (size_t, void *ptr) { return ptr; }
|
|
||||||
|
|
||||||
|
|
||||||
class Noux_connection
|
class Noux_connection
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -79,13 +78,6 @@ class Noux_connection
|
||||||
|
|
||||||
Noux_connection() : _sysio(_obtain_sysio()) { }
|
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
|
* 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()
|
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<Platform_env *>(env());
|
||||||
|
platform_env->reinit(new_parent.dst, new_parent.local_name);
|
||||||
|
|
||||||
|
/* reinitialize standard-output connection */
|
||||||
stdout_reconnect();
|
stdout_reconnect();
|
||||||
noux_connection()->reconnect();
|
|
||||||
|
|
||||||
|
/* reinitialize noux connection */
|
||||||
|
construct_at<Noux_connection>(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);
|
longjmp(fork_jmp_buf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,7 +510,7 @@ extern "C" void fork_trampoline()
|
||||||
extern "C" pid_t fork(void)
|
extern "C" pid_t fork(void)
|
||||||
{
|
{
|
||||||
/* stack used for executing 'fork_trampoline' */
|
/* stack used for executing 'fork_trampoline' */
|
||||||
enum { STACK_SIZE = 1024 };
|
enum { STACK_SIZE = 8 * 1024 };
|
||||||
static long stack[STACK_SIZE];
|
static long stack[STACK_SIZE];
|
||||||
|
|
||||||
if (setjmp(fork_jmp_buf)) {
|
if (setjmp(fork_jmp_buf)) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user