base: remove 'Native_thread' from public API

Issue #1832
This commit is contained in:
Norman Feske
2016-03-11 17:32:43 +01:00
committed by Christian Helmuth
parent dc0ebba1ec
commit da5d182ad3
77 changed files with 659 additions and 333 deletions

View File

@@ -20,39 +20,6 @@
namespace Genode {
/**
* Native thread contains more thread-local data than just the ID
*/
struct Native_thread
{
/*
* Unfortunately, both - PID and TID - are needed for lx_tgkill()
*/
unsigned int tid = 0; /* Native thread ID type as returned by the
'clone' system call */
unsigned int pid = 0; /* process ID (resp. thread-group ID) */
bool is_ipc_server = false;
/**
* Natively aligned memory location used in the lock implementation
*/
int futex_counter __attribute__((aligned(sizeof(Genode::addr_t)))) = 0;
struct Meta_data;
/**
* Opaque pointer to additional thread-specific meta data
*
* This pointer is used by hybrid Linux/Genode programs to maintain
* POSIX-thread-related meta data. For non-hybrid Genode programs, it
* remains unused.
*/
Meta_data *meta_data = nullptr;
Native_thread() { }
};
struct Cap_dst_policy
{
struct Dst

View File

@@ -36,6 +36,7 @@
/* base-internal includes */
#include <base/internal/socket_descriptor_registry.h>
#include <base/internal/native_thread.h>
/* Linux includes */
#include <linux_syscalls.h>
@@ -509,7 +510,7 @@ Ipc_istream::~Ipc_istream()
*/
Thread_base *thread = Thread_base::myself();
if (thread)
thread->tid().is_ipc_server = false;
thread->native_thread().is_ipc_server = false;
}
destroy_server_socket_pair(_rcv_cs);
@@ -641,7 +642,7 @@ Ipc_server::Ipc_server(Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
* may call 'sleep_forever()', which instantiates 'Ipc_server'.
*/
if (thread && thread->tid().is_ipc_server) {
if (thread && thread->native_thread().is_ipc_server) {
PRAW("[%d] unexpected multiple instantiation of Ipc_server by one thread",
lx_gettid());
struct Ipc_server_multiple_instance { };
@@ -650,7 +651,7 @@ Ipc_server::Ipc_server(Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
if (thread) {
_rcv_cs = server_socket_pair();
thread->tid().is_ipc_server = true;
thread->native_thread().is_ipc_server = true;
}
/* override capability initialization performed by 'Ipc_istream' */

View File

@@ -58,7 +58,7 @@ void Thread_base::_thread_start()
/* inform core about the new thread and process ID of the new thread */
Linux_cpu_session *cpu = dynamic_cast<Linux_cpu_session *>(thread->_cpu_session);
if (cpu)
cpu->thread_id(thread->cap(), thread->tid().pid, thread->tid().tid);
cpu->thread_id(thread->cap(), thread->native_thread().pid, thread->native_thread().tid);
/* wakeup 'start' function */
startup_lock().unlock();
@@ -84,7 +84,7 @@ void Thread_base::_init_platform_thread(size_t weight, Type type)
return;
}
/* adjust initial object state for main threads */
tid().futex_counter = main_thread_futex_counter;
native_thread().futex_counter = main_thread_futex_counter;
_thread_cap = env()->parent()->main_thread_cap();
}
@@ -106,7 +106,7 @@ void Thread_base::_deinit_platform_thread()
for (;;) {
/* destroy thread locally */
int ret = lx_tgkill(_tid.pid, _tid.tid, LX_SIGCANCEL);
int ret = lx_tgkill(native_thread().pid, native_thread().tid, LX_SIGCANCEL);
if (ret < 0) break;
@@ -138,8 +138,8 @@ void Thread_base::start()
threadlib_initialized = true;
}
_tid.tid = lx_create_thread(Thread_base::_thread_start, stack_top(), this);
_tid.pid = lx_getpid();
native_thread().tid = lx_create_thread(Thread_base::_thread_start, stack_top(), this);
native_thread().pid = lx_getpid();
/* wait until the 'thread_start' function got entered */
startup_lock().lock();

View File

@@ -15,6 +15,9 @@
#include <base/lock.h>
#include <linux_dataspace/client.h>
/* base-internal includes */
#include <base/internal/native_thread.h>
/* local includes */
#include "platform.h"
#include "core_env.h"
@@ -157,7 +160,7 @@ namespace Genode {
Native_connection_state server_socket_pair()
{
return create_server_socket_pair(Thread_base::myself()->tid().tid);
return create_server_socket_pair(Thread_base::myself()->native_thread().tid);
}
void destroy_server_socket_pair(Native_connection_state const &ncs)

View File

@@ -15,6 +15,9 @@
#include <base/thread.h>
#include <base/sleep.h>
/* base-internal includes */
#include <base/internal/native_thread.h>
/* Linux syscall bindings */
#include <linux_syscalls.h>
@@ -54,8 +57,8 @@ void Thread_base::_deinit_platform_thread() { }
void Thread_base::start()
{
_tid.tid = lx_create_thread(Thread_base::_thread_start, stack_top(), this);
_tid.pid = lx_getpid();
native_thread().tid = lx_create_thread(Thread_base::_thread_start, stack_top(), this);
native_thread().pid = lx_getpid();
}

View File

@@ -41,7 +41,7 @@ static inline void thread_yield()
static inline bool thread_check_stopped_and_restart(Genode::Thread_base *thread_base)
{
const int *futex_counter_ptr = thread_base ?
&thread_base->tid().futex_counter :
&thread_base->native_thread().futex_counter :
&main_thread_futex_counter;
return lx_futex(futex_counter_ptr, LX_FUTEX_WAKE, 1);
}
@@ -62,7 +62,7 @@ static inline void thread_stop_myself()
*/
Genode::Thread_base *myself = Genode::Thread_base::myself();
const int *futex_counter_ptr = myself ?
&myself->tid().futex_counter :
&myself->native_thread().futex_counter :
&main_thread_futex_counter;
lx_futex(futex_counter_ptr, LX_FUTEX_WAIT, 0);
}

View File

@@ -0,0 +1,51 @@
/*
* \brief Kernel-specific thread meta data
* \author Norman Feske
* \date 2016-03-11
*/
/*
* Copyright (C) 2016 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.
*/
#ifndef _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_
#define _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_
#include <base/stdint.h>
namespace Genode { struct Native_thread; }
struct Genode::Native_thread
{
/*
* Unfortunately, both - PID and TID - are needed for lx_tgkill()
*/
unsigned int tid = 0; /* Native thread ID type as returned by the
'clone' system call */
unsigned int pid = 0; /* process ID (resp. thread-group ID) */
bool is_ipc_server = false;
/**
* Natively aligned memory location used in the lock implementation
*/
int futex_counter __attribute__((aligned(sizeof(Genode::addr_t)))) = 0;
struct Meta_data;
/**
* Opaque pointer to additional thread-specific meta data
*
* This pointer is used by hybrid Linux/Genode programs to maintain
* POSIX-thread-related meta data. For non-hybrid Genode programs, it
* remains unused.
*/
Meta_data *meta_data = nullptr;
Native_thread() { }
};
#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_ */

View File

@@ -11,11 +11,14 @@
* under the terms of the GNU General Public License version 2.
*/
//#include <base/crt0.h>
/* Genode includes */
#include <base/printf.h>
#include <linux_syscalls.h>
#include <linux_cpu_session/linux_cpu_session.h>
/* base-internal includes */
#include <base/internal/native_thread.h>
extern "C" int raw_write_str(const char *str);
@@ -134,8 +137,20 @@ static pthread_key_t tls_key()
namespace Genode {
/**
* Meta data tied to the thread via the pthread TLS mechanism
*/
struct Native_thread::Meta_data
{
/**
* Linux-specific thread meta data
*
* For non-hybrid programs, this information is located at the
* 'Stack'. But the POSIX threads of hybrid programs have no 'Stack'
* object. So we have to keep the meta data here.
*/
Native_thread native_thread;
/**
* Filled out by 'thread_start' function in the stack of the new
* thread
@@ -152,7 +167,10 @@ namespace Genode {
*
* \param thread associated 'Thread_base' object
*/
Meta_data(Thread_base *thread) : thread_base(thread) { }
Meta_data(Thread_base *thread) : thread_base(thread)
{
native_thread.meta_data = this;
}
/**
* Used to block the constructor until the new thread has initialized
@@ -174,8 +192,8 @@ namespace Genode {
virtual void joined() = 0;
};
/*
* Thread meta data for a thread created by Genode
/**
* Thread meta data for a thread created by Genode
*/
class Thread_meta_data_created : public Native_thread::Meta_data
{
@@ -238,8 +256,8 @@ namespace Genode {
}
};
/*
* Thread meta data for an adopted thread
/**
* Thread meta data for an adopted thread
*/
class Thread_meta_data_adopted : public Native_thread::Meta_data
{
@@ -320,7 +338,7 @@ static void adopt_thread(Native_thread::Meta_data *meta_data)
/*
* Initialize thread meta data
*/
Native_thread &native_thread = meta_data->thread_base->tid();
Native_thread &native_thread = meta_data->thread_base->native_thread();
native_thread.tid = lx_gettid();
native_thread.pid = lx_getpid();
}
@@ -375,19 +393,18 @@ Thread_base *Thread_base::myself()
* thread, which is not what we want. For the allocation, we use glibc
* malloc because 'Genode::env()->heap()->alloc()' uses IPC.
*
* XXX Both the 'Thread_base' and 'Threadm_meta_data' objects are never
* freed.
* XXX Both the 'Thread_base' and 'Native_thread::Meta_data' objects are
* never freed.
*/
Thread_base *thread = (Thread_base *)malloc(sizeof(Thread_base));
memset(thread, 0, sizeof(*thread));
Native_thread::Meta_data *meta_data = new Thread_meta_data_adopted(thread);
/*
* Initialize 'Thread_base::_tid' using the default constructor of
* 'Native_thread'. This marks the client and server sockets as
* uninitialized and prompts the IPC framework to create those as needed.
* Initialize 'Thread_base::_native_thread' to point to the default-
* constructed 'Native_thread' (part of 'Meta_data').
*/
meta_data->thread_base->tid() = Native_thread();
meta_data->thread_base->_native_thread = &meta_data->native_thread;
adopt_thread(meta_data);
return thread;
@@ -399,37 +416,42 @@ void Thread_base::start()
/*
* Unblock thread that is supposed to slumber in 'thread_start'.
*/
_tid.meta_data->started();
native_thread().meta_data->started();
}
void Thread_base::join()
{
_tid.meta_data->wait_for_join();
native_thread().meta_data->wait_for_join();
}
Native_thread &Thread_base::native_thread() { return *_native_thread; }
Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size,
Type type, Cpu_session * cpu_sess)
: _cpu_session(cpu_sess)
{
_tid.meta_data = new (env()->heap()) Thread_meta_data_created(this);
Native_thread::Meta_data *meta_data =
new (env()->heap()) Thread_meta_data_created(this);
int const ret = pthread_create(&_tid.meta_data->pt, 0, thread_start,
_tid.meta_data);
_native_thread = &meta_data->native_thread;
int const ret = pthread_create(&meta_data->pt, 0, thread_start, meta_data);
if (ret) {
PERR("pthread_create failed (returned %d, errno=%d)",
ret, errno);
destroy(env()->heap(), _tid.meta_data);
destroy(env()->heap(), meta_data);
throw Out_of_stack_space();
}
_tid.meta_data->wait_for_construction();
native_thread().meta_data->wait_for_construction();
Linux_cpu_session *cpu = cpu_session(_cpu_session);
_thread_cap = cpu->create_thread(weight, name);
cpu->thread_id(_thread_cap, _tid.pid, _tid.tid);
cpu->thread_id(_thread_cap, native_thread().pid, native_thread().tid);
}
@@ -447,22 +469,22 @@ void Thread_base::cancel_blocking()
Thread_base::~Thread_base()
{
bool const needs_join = (pthread_cancel(_tid.meta_data->pt) == 0);
bool const needs_join = (pthread_cancel(native_thread().meta_data->pt) == 0);
if (needs_join) {
int const ret = pthread_join(_tid.meta_data->pt, 0);
int const ret = pthread_join(native_thread().meta_data->pt, 0);
if (ret)
PWRN("pthread_join unexpectedly returned with %d (errno=%d)",
ret, errno);
}
Thread_meta_data_created *meta_data =
dynamic_cast<Thread_meta_data_created *>(_tid.meta_data);
dynamic_cast<Thread_meta_data_created *>(native_thread().meta_data);
if (meta_data)
destroy(env()->heap(), meta_data);
_tid.meta_data = 0;
_native_thread = nullptr;
/* inform core about the killed thread */
cpu_session(_cpu_session)->kill_thread(_thread_cap);