thread: move Thread_base::myself() to separate file

The thread library (thread.cc) in base-foc shared 95% of the code with
the generic implementation except myself(). Therefore, its
implementation is now separated from the other generic sources into
myself.cc, which allows base-foc to use a foc-specific primitive to
enable our base libraries in L4Linux.

Issue #1491
This commit is contained in:
Christian Helmuth 2015-04-28 17:42:07 +02:00
parent 55c0a947e4
commit 98def2488a
15 changed files with 76 additions and 244 deletions

View File

@ -20,7 +20,7 @@ SRC_CC += elf/elf_binary.cc
SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc
SRC_CC += thread/thread.cc thread/myself.cc thread/thread_bootstrap.cc thread/trace.cc
SRC_CC += thread/context_allocator.cc env/utcb.cc
SRC_CC += lock/cmpxchg.cc

View File

@ -21,6 +21,7 @@ SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc
SRC_CC += thread/myself.cc
SRC_CC += thread/context_allocator.cc
INC_DIR += $(REP_DIR)/src/base/lock

View File

@ -21,6 +21,7 @@ SRC_CC += env/spin_lock.cc env/cap_map.cc
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc
SRC_CC += thread/myself.cc
SRC_CC += thread/context_allocator.cc
INC_DIR += $(REP_DIR)/src/base/lock

View File

@ -0,0 +1,24 @@
/*
* \brief Implementation of the Thread API (foc-specific myself())
* \author Norman Feske
* \date 2015-04-28
*/
/*
* Copyright (C) 2015 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>
Genode::Thread_base *Genode::Thread_base::myself()
{
using namespace Fiasco;
return reinterpret_cast<Thread_base*>(l4_utcb_tcr()->user[UTCB_TCR_THREAD_OBJ]);
}

View File

@ -1,211 +0,0 @@
/*
* \brief Implementation of the Thread API
* \author Norman Feske
* \date 2010-01-11
*/
/*
* 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.
*/
#include <base/thread.h>
#include <base/env.h>
#include <base/snprintf.h>
#include <util/string.h>
#include <util/misc_math.h>
using namespace Genode;
/**
* Return the managed dataspace holding the thread context area
*
* This function is provided by the process environment.
*/
namespace Genode {
Rm_session *env_context_area_rm_session();
Ram_session *env_context_area_ram_session();
}
void Thread_base::Context::stack_size(size_t const size)
{
/* check if the stack needs to be enhanced */
size_t const stack_size = (addr_t)_stack - stack_base;
if (stack_size >= size) { return; }
/* check if the stack enhancement fits the context region */
enum {
CONTEXT_SIZE = Native_config::context_virtual_size(),
CONTEXT_AREA_BASE = Native_config::context_area_virtual_base(),
UTCB_SIZE = sizeof(Native_utcb),
PAGE_SIZE_LOG2 = 12,
PAGE_SIZE = (1UL << PAGE_SIZE_LOG2),
};
addr_t const context_base = Context_allocator::addr_to_base(this);
size_t const ds_size = align_addr(size - stack_size, PAGE_SIZE_LOG2);
if (stack_base - ds_size < context_base) { throw Stack_too_large(); }
/* allocate and attach backing store for the stack enhancement */
addr_t const ds_addr = stack_base - ds_size - CONTEXT_AREA_BASE;
try {
Ram_session * const ram = env_context_area_ram_session();
Ram_dataspace_capability const ds_cap = ram->alloc(ds_size);
Rm_session * const rm = env_context_area_rm_session();
void * const attach_addr = rm->attach_at(ds_cap, ds_addr, ds_size);
if (ds_addr != (addr_t)attach_addr) { throw Stack_alloc_failed(); }
}
catch (Ram_session::Alloc_failed) { throw Stack_alloc_failed(); }
/* update context information */
stack_base -= ds_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
*
* XXX: remove interim fix
*/
static Lock alloc_lock;
Lock::Guard _lock_guard(alloc_lock);
/* allocate thread context */
Context *context = _context_allocator()->alloc(this, main_thread);
if (!context)
throw Context_alloc_failed();
/* determine size of dataspace to allocate for context members and stack */
enum { PAGE_SIZE_LOG2 = 12 };
size_t ds_size = align_addr(stack_size, PAGE_SIZE_LOG2);
if (stack_size >= Native_config::context_virtual_size() -
sizeof(Native_utcb) - (1UL << PAGE_SIZE_LOG2))
throw Stack_too_large();
/*
* Calculate base address of the stack
*
* The stack is always located at the top of the context.
*/
addr_t ds_addr = Context_allocator::addr_to_base(context) +
Native_config::context_virtual_size() -
ds_size;
/* add padding for UTCB if defined for the platform */
if (sizeof(Native_utcb) >= (1 << PAGE_SIZE_LOG2))
ds_addr -= sizeof(Native_utcb);
/* allocate and attach backing store for the stack */
Ram_dataspace_capability ds_cap;
try {
ds_cap = env_context_area_ram_session()->alloc(ds_size);
addr_t attach_addr = ds_addr - Native_config::context_area_virtual_base();
if (attach_addr != (addr_t)env_context_area_rm_session()->attach_at(ds_cap, attach_addr, ds_size))
throw Stack_alloc_failed();
}
catch (Ram_session::Alloc_failed) { throw Stack_alloc_failed(); }
/*
* Now the thread context is backed by memory, so it is safe to access its
* members.
*
* We need to initialize the context object's memory with zeroes,
* otherwise the ds_cap isn't invalid. That would cause trouble
* when the assignment operator of Native_capability is used.
*/
memset(context, 0, sizeof(Context) - sizeof(Context::utcb));
context->thread_base = this;
context->stack_base = ds_addr;
context->ds_cap = ds_cap;
/*
* The value at the top of the stack might get interpreted as return
* address of the thread start function by GDB, so we set it to 0.
*/
*(addr_t*)context->stack_top() = 0;
return context;
}
void Thread_base::_free_context(Context* context)
{
addr_t ds_addr = context->stack_base - Native_config::context_area_virtual_base();
Ram_dataspace_capability ds_cap = context->ds_cap;
/* call de-constructor explicitly before memory gets detached */
context->~Context();
Genode::env_context_area_rm_session()->detach((void *)ds_addr);
Genode::env_context_area_ram_session()->free(ds_cap);
/* context area ready for reuse */
_context_allocator()->free(context);
}
void Thread_base::name(char *dst, size_t dst_len)
{
snprintf(dst, min(dst_len, (size_t)Context::NAME_LEN), "%s", _context->name);
}
Thread_base *Thread_base::myself()
{
using namespace Fiasco;
return reinterpret_cast<Thread_base*>(l4_utcb_tcr()->user[UTCB_TCR_THREAD_OBJ]);
}
void Thread_base::join()
{
_join_lock.lock();
}
void* Thread_base::alloc_secondary_stack(char const *name, size_t stack_size)
{
Context *context = _alloc_context(stack_size, false);
strncpy(context->name, name, sizeof(context->name));
return (void *)context->stack_top();
}
void Thread_base::free_secondary_stack(void* stack_addr)
{
addr_t base = Context_allocator::addr_to_base(stack_addr);
_free_context(Context_allocator::base_to_context(base));
}
Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size,
Type const type, Cpu_session *cpu_session)
:
_cpu_session(cpu_session),
_context(type == REINITIALIZED_MAIN ?
_context : _alloc_context(stack_size, type == MAIN)),
_join_lock(Lock::LOCKED)
{
strncpy(_context->name, name, sizeof(_context->name));
_init_platform_thread(weight, type);
}
Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size,
Type type)
: Thread_base(weight, name, stack_size, type, nullptr) { }
Thread_base::~Thread_base()
{
_deinit_platform_thread();
_free_context(_context);
}

View File

@ -24,6 +24,8 @@ SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
SRC_CC += server/server.cc
SRC_CC += server/common.cc
SRC_CC += thread/thread.cc
SRC_CC += thread/myself.cc
SRC_CC += thread/bootstrap.cc
SRC_CC += thread/trace.cc
SRC_CC += thread/context_allocator.cc

View File

@ -13,7 +13,6 @@ SRC_CC += cpu/cache.cc
SRC_CC += env/env.cc
SRC_CC += env/context_area.cc
SRC_CC += env/reinitialize.cc
SRC_CC += thread/thread.cc
SRC_CC += thread/start.cc
SRC_CC += irq/platform.cc

View File

@ -41,7 +41,6 @@ SRC_CC += rm_session_component.cc
SRC_CC += rom_session_component.cc
SRC_CC += signal_session_component.cc
SRC_CC += trace_session_component.cc
SRC_CC += thread/thread.cc
SRC_CC += thread_start.cc
SRC_CC += rm_session_support.cc
SRC_CC += pager.cc
@ -74,4 +73,3 @@ vpath boot_modules.s $(BOOT_MODULES_VPATH)
vpath % $(REP_DIR)/src/core
vpath % $(BASE_DIR)/src/core
vpath % $(BASE_DIR)/src/platform
vpath % $(BASE_DIR)/src/base

View File

@ -5,10 +5,10 @@
#
LIBS += startup cxx
SRC_CC += thread.cc thread_linux.cc
SRC_CC += thread/thread.cc thread/myself.cc thread/thread_linux.cc
vpath %.cc $(REP_DIR)/src/base/thread
vpath %.cc $(BASE_DIR)/src/base/thread
vpath %.cc $(REP_DIR)/src/base
vpath %.cc $(BASE_DIR)/src/base
include $(REP_DIR)/lib/mk/base.inc

View File

@ -23,7 +23,7 @@ SRC_CC = main.cc \
thread_linux.cc \
context_area.cc \
core_printf.cc \
thread.cc
thread.cc myself.cc
INC_DIR += $(REP_DIR)/src/core/include \
$(GEN_CORE_DIR)/include \
@ -58,5 +58,6 @@ vpath signal_source_component.cc $(GEN_CORE_DIR)
vpath trace_session_component.cc $(GEN_CORE_DIR)
vpath core_printf.cc $(BASE_DIR)/src/base/console
vpath thread.cc $(BASE_DIR)/src/base/thread
vpath myself.cc $(BASE_DIR)/src/base/thread
vpath trace.cc $(BASE_DIR)/src/base/thread
vpath %.cc $(PRG_DIR)

View File

@ -19,6 +19,7 @@ SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
SRC_CC += server/server.cc
SRC_CC += thread/thread.cc thread/thread_context.cc thread/trace.cc
SRC_CC += thread/myself.cc
SRC_CC += thread/context_allocator.cc env/cap_map.cc
INC_DIR += $(REP_DIR)/src/base/lock

View File

@ -21,6 +21,7 @@ SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc
SRC_CC += thread/myself.cc
SRC_CC += thread/context_allocator.cc
INC_DIR += $(REP_DIR)/src/base/lock

View File

@ -21,6 +21,7 @@ SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += thread/thread.cc thread/trace.cc thread/thread_bootstrap.cc
SRC_CC += thread/myself.cc
SRC_CC += thread/context_allocator.cc
INC_DIR += $(REP_DIR)/src/base/lock

View File

@ -0,0 +1,34 @@
/*
* \brief Implementation of the Thread API (generic myself())
* \author Norman Feske
* \date 2015-04-28
*/
/*
* Copyright (C) 2015 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>
Genode::Thread_base *Genode::Thread_base::myself()
{
int dummy = 0; /* used for determining the stack pointer */
/*
* If the stack pointer is outside the thread-context area, we assume that
* we are the main thread because this condition can never met by any other
* thread.
*/
addr_t sp = (addr_t)(&dummy);
if (sp < Native_config::context_area_virtual_base() ||
sp >= Native_config::context_area_virtual_base() +
Native_config::context_area_virtual_size())
return 0;
addr_t base = Context_allocator::addr_to_base(&dummy);
return Context_allocator::base_to_context(base)->thread_base;
}

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2010-2013 Genode Labs GmbH
* Copyright (C) 2010-2015 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.
@ -153,26 +153,6 @@ void Thread_base::name(char *dst, size_t dst_len)
}
Thread_base *Thread_base::myself()
{
int dummy = 0; /* used for determining the stack pointer */
/*
* If the stack pointer is outside the thread-context area, we assume that
* we are the main thread because this condition can never met by any other
* thread.
*/
addr_t sp = (addr_t)(&dummy);
if (sp < Native_config::context_area_virtual_base() ||
sp >= Native_config::context_area_virtual_base() +
Native_config::context_area_virtual_size())
return 0;
addr_t base = Context_allocator::addr_to_base(&dummy);
return Context_allocator::base_to_context(base)->thread_base;
}
void Thread_base::join() { _join_lock.lock(); }
@ -191,7 +171,7 @@ void Thread_base::free_secondary_stack(void* stack_addr)
}
Thread_base::Thread_base(size_t quota, const char *name, size_t stack_size,
Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size,
Type type, Cpu_session *cpu_session)
:
_cpu_session(cpu_session),
@ -200,13 +180,13 @@ Thread_base::Thread_base(size_t quota, const char *name, size_t stack_size,
_join_lock(Lock::LOCKED)
{
strncpy(_context->name, name, sizeof(_context->name));
_init_platform_thread(quota, type);
_init_platform_thread(weight, type);
}
Thread_base::Thread_base(size_t quota, const char *name, size_t stack_size,
Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size,
Type type)
: Thread_base(quota, name, stack_size, type, nullptr) { }
: Thread_base(weight, name, stack_size, type, nullptr) { }
Thread_base::~Thread_base()