diff --git a/base-linux/include/base/platform_env.h b/base-linux/include/base/platform_env.h index 54a02b64c1..de5e0975f9 100644 --- a/base-linux/include/base/platform_env.h +++ b/base-linux/include/base/platform_env.h @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include namespace Genode { @@ -341,7 +341,7 @@ namespace Genode { Ram_session_capability _ram_session_cap; Expanding_ram_session_client _ram_session_client; Cpu_session_capability _cpu_session_cap; - Cpu_session_client _cpu_session_client; + Linux_cpu_session_client _cpu_session_client; Rm_session_mmap _rm_session_mmap; Pd_session_client _pd_session_client; Heap _heap; @@ -357,7 +357,7 @@ namespace Genode { _ram_session_cap(static_cap_cast(parent()->session("Env::ram_session", ""))), _ram_session_client(_ram_session_cap), _cpu_session_cap(static_cap_cast(parent()->session("Env::cpu_session", ""))), - _cpu_session_client(_cpu_session_cap), + _cpu_session_client(static_cap_cast(parent()->session("Env::cpu_session", ""))), _rm_session_mmap(false), _pd_session_client(static_cap_cast(parent()->session("Env::pd_session", ""))), _heap(&_ram_session_client, &_rm_session_mmap) @@ -386,9 +386,9 @@ namespace Genode { Ram_session_capability ram_session_cap() { return _ram_session_cap; } Rm_session *rm_session() { return &_rm_session_mmap; } Heap *heap() { return &_heap; } - Cpu_session *cpu_session() { return &_cpu_session_client; } + Linux_cpu_session *cpu_session() { return &_cpu_session_client; } Cpu_session_capability cpu_session_cap() { return _cpu_session_cap; } - Pd_session *pd_session() { return 0; } + Pd_session *pd_session() { return &_pd_session_client; } }; } diff --git a/base-linux/include/linux_cpu_session/client.h b/base-linux/include/linux_cpu_session/client.h new file mode 100644 index 0000000000..d3f3f7920f --- /dev/null +++ b/base-linux/include/linux_cpu_session/client.h @@ -0,0 +1,82 @@ +/* + * \brief Client-side CPU session interface + * \author Norman Feske + * \date 2012-08-09 + */ + +/* + * Copyright (C) 2006-2012 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__LINUX_CPU_SESSION__CLIENT_H_ +#define _INCLUDE__LINUX_CPU_SESSION__CLIENT_H_ + +#include +#include + +namespace Genode { + + struct Linux_cpu_session_client : Rpc_client + { + explicit Linux_cpu_session_client(Capability session) + : Rpc_client(session) { } + + Thread_capability create_thread(Name const &name, addr_t utcb = 0) { + return call(name, utcb); } + + Ram_dataspace_capability utcb(Thread_capability thread) { + return call(thread); } + + void kill_thread(Thread_capability thread) { + call(thread); } + + int set_pager(Thread_capability thread, Pager_capability pager) { + return call(thread, pager); } + + int start(Thread_capability thread, addr_t ip, addr_t sp) { + return call(thread, ip, sp); } + + void pause(Thread_capability thread) { + call(thread); } + + void resume(Thread_capability thread) { + call(thread); } + + void cancel_blocking(Thread_capability thread) { + call(thread); } + + int state(Thread_capability thread, Thread_state *dst_state) { + return call(thread, dst_state); } + + void exception_handler(Thread_capability thread, Signal_context_capability handler) { + call(thread, handler); } + + void single_step(Thread_capability thread, bool enable) { + call(thread, enable); } + + unsigned num_cpus() const { + return call(); } + + void affinity(Thread_capability thread, unsigned cpu) { + call(thread, cpu); } + + + /***************************** + * Linux-specific extension ** + *****************************/ + + void thread_id(Thread_capability thread, int pid, int tid) { + call(thread, pid, tid); } + + Untyped_capability server_sd(Thread_capability thread) { + return call(thread); } + + Untyped_capability client_sd(Thread_capability thread) { + return call(thread); } + }; +} + +#endif /* _INCLUDE__CPU_SESSION__CLIENT_H_ */ diff --git a/base-linux/include/linux_cpu_session/linux_cpu_session.h b/base-linux/include/linux_cpu_session/linux_cpu_session.h new file mode 100644 index 0000000000..653350d18f --- /dev/null +++ b/base-linux/include/linux_cpu_session/linux_cpu_session.h @@ -0,0 +1,70 @@ +/* + * \brief Linux-specific extension of the CPU session interface + * \author Norman Feske + * \date 2012-08-09 + */ + +/* + * Copyright (C) 2012 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__LINUX_CPU_SESSION__LINUX_CPU_SESSION_H_ +#define _INCLUDE__LINUX_CPU_SESSION__LINUX_CPU_SESSION_H_ + +#include + +namespace Genode { + + struct Linux_cpu_session : Cpu_session + { + virtual ~Linux_cpu_session() { } + + /** + * Register Linux PID and TID of the specified thread + */ + virtual void thread_id(Thread_capability, int pid, int tid) = 0; + + /* + * If a thread plays the role of an entrypoint, core creates a bound + * socket pair for the thread and passes both makes the socket + * descriptors of both ends available to the owner of the thread's + * CPU session via the 'server_sd' and 'client_sd' function. + */ + + /** + * Request server-side socket descriptor + * + * The socket descriptor returned by this function is meant to be used + * exclusively by the server for receiving incoming requests. It should + * never leave the server process. + */ + virtual Untyped_capability server_sd(Thread_capability thread) = 0; + + /** + * Request client-side socket descriptor + * + * The returned socket descriptor enables a client to send messages to + * the thread. It is already connected to the 'server_sd' descriptor. + * In contrast to 'server_sd', the 'client_sd' is expected to be passed + * around via capability delegations. + */ + virtual Untyped_capability client_sd(Thread_capability thread) = 0; + + + /********************* + ** RPC declaration ** + *********************/ + + GENODE_RPC(Rpc_thread_id, void, thread_id, Thread_capability, int, int); + GENODE_RPC(Rpc_server_sd, Untyped_capability, server_sd, Thread_capability); + GENODE_RPC(Rpc_client_sd, Untyped_capability, client_sd, Thread_capability); + + GENODE_RPC_INTERFACE_INHERIT(Cpu_session, + Rpc_thread_id, Rpc_server_sd, Rpc_client_sd); + }; +} + +#endif /* _INCLUDE__LINUX_CPU_SESSION__LINUX_CPU_SESSION_H_ */ diff --git a/base-linux/src/base/env/platform_env.cc b/base-linux/src/base/env/platform_env.cc index 4b0f588574..54df826436 100644 --- a/base-linux/src/base/env/platform_env.cc +++ b/base-linux/src/base/env/platform_env.cc @@ -13,6 +13,7 @@ #include #include +#include using namespace Genode; @@ -95,3 +96,36 @@ unsigned long Platform_env::_get_env_ulong(const char *key) return 0; } + + +/***************************** + ** Support for IPC library ** + *****************************/ + +namespace Genode { + + Native_connection_state server_socket_pair() + { + /* + * Obtain access to Linux-specific extension of the CPU session + * interface. We can cast to the specific type because the Linux + * version of 'Platform_env' is hosting a 'Linux_cpu_client' object. + */ + Linux_cpu_session *cpu = dynamic_cast(env()->cpu_session()); + + if (!cpu) { + PERR("could not obtain Linux extension to CPU session interface"); + struct Could_not_access_linux_cpu_session { }; + throw Could_not_access_linux_cpu_session(); + } + + Native_connection_state ncs; + + Thread_base *thread = Thread_base::myself(); + if (thread) { + ncs.server_sd = cpu->server_sd(thread->cap()).dst().socket; + ncs.client_sd = cpu->client_sd(thread->cap()).dst().socket; + } + return ncs; + } +} diff --git a/base-linux/src/base/ipc/ipc.cc b/base-linux/src/base/ipc/ipc.cc index 8c3e037e7d..ba1e01a0c3 100644 --- a/base-linux/src/base/ipc/ipc.cc +++ b/base-linux/src/base/ipc/ipc.cc @@ -31,13 +31,10 @@ #include #include #include +#include +#include /* Linux includes */ -#include -#include -#include -#include - #include #include @@ -219,6 +216,20 @@ void Ipc_server::_reply_wait() } +namespace Genode { + + /* + * Helper for obtaining a bound and connected socket pair + * + * For core, the implementation is just a wrapper around + * 'lx_server_socket_pair()'. For all other processes, the implementation + * requests the socket pair from the Env::CPU session interface using a + * Linux-specific interface extension. + */ + Native_connection_state server_socket_pair(); +} + + Ipc_server::Ipc_server(Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg) : Ipc_istream(rcv_msg), @@ -238,10 +249,10 @@ Ipc_server::Ipc_server(Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg) throw Ipc_server_multiple_instance(); } - _rcv_cs = lx_server_socket_pair(Thread_base::myself()); - - if (thread) + if (thread) { + _rcv_cs = server_socket_pair(); thread->tid().is_ipc_server = true; + } /* override capability initialization performed by 'Ipc_istream' */ *static_cast(this) = diff --git a/base-linux/src/base/thread/thread_linux.cc b/base-linux/src/base/thread/thread_linux.cc index e02f579092..5625c3b5f9 100644 --- a/base-linux/src/base/thread/thread_linux.cc +++ b/base-linux/src/base/thread/thread_linux.cc @@ -16,6 +16,7 @@ #include #include #include +#include /* Linux syscall bindings */ #include @@ -50,7 +51,10 @@ static void thread_start(void *) } -void Thread_base::_init_platform_thread() { } +void Thread_base::_init_platform_thread() +{ + _thread_cap = env()->cpu_session()->create_thread(_context->name); +} void Thread_base::_deinit_platform_thread() @@ -103,14 +107,10 @@ void Thread_base::start() _tid.tid = lx_create_thread(thread_start, thread_sp, this); _tid.pid = lx_getpid(); - /* - * Inform core about the new thread by calling create_thread and encoding - * the thread's PID in the thread-name argument. - */ - char name_and_pid[Cpu_session::THREAD_NAME_LEN + 2*16]; - snprintf(name_and_pid, sizeof(name_and_pid), "%s:0x%x:0x%x", - _context->name, _tid.tid, _tid.pid); - _thread_cap = env()->cpu_session()->create_thread(name_and_pid); + /* inform core about the new thread and process ID of the new thread */ + Linux_cpu_session *cpu = dynamic_cast(env()->cpu_session()); + if (cpu) + cpu->thread_id(_thread_cap, _tid.pid, _tid.tid); } diff --git a/base-linux/src/core/cpu_session_extension.cc b/base-linux/src/core/cpu_session_extension.cc new file mode 100644 index 0000000000..22f8d21552 --- /dev/null +++ b/base-linux/src/core/cpu_session_extension.cc @@ -0,0 +1,52 @@ +/* + * \brief Linux-specific extension of the CPU session implementation + * \author Norman Feske + * \date 2012-08-09 + */ + +/* core includes */ +#include + +/* Linux includes */ +#include + +using namespace Genode; + + +void Cpu_session_component::thread_id(Thread_capability thread_cap, int pid, int tid) +{ + Lock::Guard lock_guard(_thread_list_lock); + + Cpu_thread_component *thread = _lookup_thread(thread_cap); + if (!thread) return; + + thread->platform_thread()->thread_id(pid, tid); +} + + +Untyped_capability Cpu_session_component::server_sd(Thread_capability thread_cap) +{ + Lock::Guard lock_guard(_thread_list_lock); + + Cpu_thread_component *thread = _lookup_thread(thread_cap); + if (!thread) return Untyped_capability(); + + enum { DUMMY_LOCAL_NAME = 0 }; + typedef Native_capability::Dst Dst; + return Untyped_capability(Dst(thread->platform_thread()->server_sd()), + DUMMY_LOCAL_NAME); +} + + +Untyped_capability Cpu_session_component::client_sd(Thread_capability thread_cap) +{ + Lock::Guard lock_guard(_thread_list_lock); + + Cpu_thread_component *thread = _lookup_thread(thread_cap); + if (!thread) return Untyped_capability(); + + enum { DUMMY_LOCAL_NAME = 0 }; + typedef Native_capability::Dst Dst; + return Untyped_capability(Dst(thread->platform_thread()->client_sd()), + DUMMY_LOCAL_NAME); +} diff --git a/base-linux/src/core/include/cpu_session_component.h b/base-linux/src/core/include/cpu_session_component.h new file mode 100644 index 0000000000..03c533006e --- /dev/null +++ b/base-linux/src/core/include/cpu_session_component.h @@ -0,0 +1,152 @@ +/* + * \brief Core-specific instance of the CPU session/thread interfaces + * \author Christian Helmuth + * \author Norman Feske + * \date 2006-07-17 + */ + +/* + * Copyright (C) 2006-2012 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 _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_ +#define _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include + +/* core includes */ +#include +#include + +namespace Genode { + + /** + * RPC interface of CPU thread + * + * We make 'Cpu_thread' a RPC object only to be able to lookup CPU threads + * from thread capabilities supplied as arguments to CPU-session functions. + * A CPU thread does not provide an actual RPC interface. + */ + struct Cpu_thread + { + GENODE_RPC_INTERFACE(); + }; + + + class Cpu_thread_component : public Rpc_object, + public List::Element + { + private: + + Platform_thread _platform_thread; + + bool _bound; /* pd binding flag */ + + public: + + Cpu_thread_component(const char *name, unsigned priority, + addr_t utcb) + : _platform_thread(name, priority, utcb), _bound(false) { } + + + /************************ + ** Accessor functions ** + ************************/ + + inline Platform_thread * platform_thread() { return &_platform_thread; } + inline bool bound() const { return _bound; } + inline void bound(bool b) { _bound = b; } + }; + + + class Cpu_session_component : public Rpc_object + { + private: + + Rpc_entrypoint *_thread_ep; + Pager_entrypoint *_pager_ep; + Allocator_guard _md_alloc; /* guarded meta-data allocator */ + Cpu_thread_allocator _thread_alloc; /* meta-data allocator */ + Lock _thread_alloc_lock; /* protect allocator access */ + List _thread_list; + Lock _thread_list_lock; /* protect thread list */ + unsigned _priority; /* priority of threads + created with this + session */ + + /** + * Lookup thread in CPU session by its capability + * + * \retval NULL thread capability is invalid or + * does not belong to the CPU session + */ + Cpu_thread_component *_lookup_thread(Thread_capability thread) { + return dynamic_cast + (_thread_ep->obj_by_cap(thread)); } + + /** + * Raw thread-killing functionality + * + * This function is called from the 'kill_thread' function and + * the destructor. Each these functions grab the list lock + * by themselves and call this function to perform the actual + * killing. + */ + void _unsynchronized_kill_thread(Cpu_thread_component *thread); + + public: + + /** + * Constructor + */ + Cpu_session_component(Rpc_entrypoint *thread_ep, + Pager_entrypoint *pager_ep, + Allocator *md_alloc, const char *args); + + /** + * Destructor + */ + ~Cpu_session_component(); + + + /*************************** + ** CPU session interface ** + ***************************/ + + Thread_capability create_thread(Name const &, addr_t utcb); + Ram_dataspace_capability utcb(Thread_capability thread); + void kill_thread(Thread_capability); + Thread_capability first(); + Thread_capability next(Thread_capability); + int set_pager(Thread_capability, Pager_capability); + int start(Thread_capability, addr_t, addr_t); + void pause(Thread_capability thread_cap); + void resume(Thread_capability thread_cap); + void cancel_blocking(Thread_capability); + int name(Thread_capability, char *, size_t); + int state(Thread_capability, Thread_state *); + void exception_handler(Thread_capability, Signal_context_capability); + unsigned num_cpus() const; + void affinity(Thread_capability, unsigned); + + + /******************************* + ** Linux-specific extensions ** + *******************************/ + + void thread_id(Thread_capability, int, int); + Untyped_capability server_sd(Thread_capability); + Untyped_capability client_sd(Thread_capability); + }; +} + +#endif /* _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_ */ diff --git a/base-linux/src/core/include/platform_thread.h b/base-linux/src/core/include/platform_thread.h index ab9e10e25b..f729934ce8 100644 --- a/base-linux/src/core/include/platform_thread.h +++ b/base-linux/src/core/include/platform_thread.h @@ -29,6 +29,11 @@ namespace Genode { unsigned long _pid; char _name[32]; + /** + * Unix-domain socket pair bound to the thread + */ + Native_connection_state _ncs; + public: /** @@ -60,6 +65,24 @@ namespace Genode { int state(Thread_state *state_dst) { return 0; } const char *name() { return _name; } void affinity(unsigned) { } + + /** + * Register process ID and thread ID of thread + */ + void thread_id(int pid, int tid) { _pid = pid, _tid = tid; } + + /** + * Return client-side socket descriptor + * + * For more information, please refer to the comments in + * 'linux_cpu_session/linux_cpu_session.h'. + */ + int client_sd(); + + /** + * Return server-side socket descriptor + */ + int server_sd(); }; } diff --git a/base-linux/src/core/platform.cc b/base-linux/src/core/platform.cc index 5e3f8ca57e..cd4e7ff20d 100644 --- a/base-linux/src/core/platform.cc +++ b/base-linux/src/core/platform.cc @@ -19,6 +19,7 @@ #include "core_env.h" /* Linux includes */ +#include #include #include @@ -60,3 +61,17 @@ void Core_parent::exit(int exit_value) { lx_exit_group(exit_value); } + + +/***************************** + ** Support for IPC library ** + *****************************/ + +namespace Genode { + + Native_connection_state server_socket_pair() + { + return lx_server_socket_pair(Thread_base::myself()->tid().tid); + } +} + diff --git a/base-linux/src/core/platform_thread.cc b/base-linux/src/core/platform_thread.cc index 1807aac0fe..a4c61ecbb5 100644 --- a/base-linux/src/core/platform_thread.cc +++ b/base-linux/src/core/platform_thread.cc @@ -21,6 +21,7 @@ /* Linux syscall helper */ #include +#include using namespace Genode; @@ -29,41 +30,9 @@ typedef Token Tid_token; Platform_thread::Platform_thread(const char *name, unsigned, addr_t) +: _tid(-1), _pid(-1) { - /* search for thread-id portion of thread name */ - Tid_token tok(name); - while (tok.type() != Tid_token::END && tok[0] != ':') - tok = tok.next(); - - /* tok points at the colon separator, next token is the id */ - tok = tok.next(); - - if (tok.type() == Tid_token::END) { - PWRN("Invalid format of thread name."); - return; - } - - /* convert string to thread id */ - ascii_to(tok.start(), &_tid); - - /* search for process-id portion of thread name */ - while (tok.type() != Tid_token::END && tok[0] != ':') - tok = tok.next(); - - /* tok points at the colon separator, next token is the id */ - tok = tok.next(); - - if (tok.type() == Tid_token::END) { - PWRN("Invalid format of thread name."); - return; - } - - /* convert string to process id */ - ascii_to(tok.start(), &_pid); - - /* initialize private members */ - size_t name_len = tok.start() - name; - strncpy(_name, name, min(sizeof(_name), name_len)); + strncpy(_name, name, min(sizeof(_name), strlen(name))); } @@ -84,3 +53,20 @@ void Platform_thread::resume() { PDBG("not implemented"); } + + +int Platform_thread::client_sd() +{ + /* construct socket pair on first call */ + if (_ncs.client_sd == -1) + _ncs = lx_server_socket_pair(_tid); + + return _ncs.client_sd; +} + + +int Platform_thread::server_sd() +{ + client_sd(); + return _ncs.server_sd; +} diff --git a/base-linux/src/core/target.mk b/base-linux/src/core/target.mk index 13a7feb0d4..9a972a3117 100644 --- a/base-linux/src/core/target.mk +++ b/base-linux/src/core/target.mk @@ -12,6 +12,7 @@ SRC_CC = main.cc \ ram_session_support.cc \ rom_session_component.cc \ cpu_session_component.cc \ + cpu_session_extension.cc \ cpu_session_support.cc \ pd_session_component.cc \ io_mem_session_component.cc \ diff --git a/base-linux/src/platform/linux_socket.h b/base-linux/src/platform/linux_socket.h index 735eaf6f61..99086cd1a6 100644 --- a/base-linux/src/platform/linux_socket.h +++ b/base-linux/src/platform/linux_socket.h @@ -24,6 +24,13 @@ #include #include +/* Linux includes */ +#include +#include +#include +#include + +/* Genode bindings to Linux kernel */ #include #include @@ -342,7 +349,7 @@ class Connect_failed { }; * \throw Bind_failed * \throw Connect_failed */ -static Genode::Native_connection_state lx_server_socket_pair(Genode::Thread_base *thread) +static inline Genode::Native_connection_state lx_server_socket_pair(long thread_id) { Genode::Native_connection_state ncs; @@ -350,10 +357,10 @@ static Genode::Native_connection_state lx_server_socket_pair(Genode::Thread_base * Main thread uses 'Ipc_server' for 'sleep_forever()' only. No need for * binding. */ - if (!thread) + if (thread_id == -1) return ncs; - Uds_addr addr(thread->tid().tid); + Uds_addr addr(thread_id); /* * Create server-side socket @@ -391,6 +398,12 @@ static Genode::Native_connection_state lx_server_socket_pair(Genode::Thread_base int const tid = lookup_tid_by_client_socket(ncs.client_sd); Genode::ep_sd_registry()->associate(ncs.client_sd, tid); + /* + * Wipe Unix domain socket from the file system. It will live as long as + * there exist references to it in the form of file descriptors. + */ + lx_unlink(addr.sun_path); + return ncs; } @@ -398,9 +411,9 @@ static Genode::Native_connection_state lx_server_socket_pair(Genode::Thread_base /** * Utility: Send request to server and wait for reply */ -static void lx_call(int dst_sd, - Genode::Msgbuf_base &send_msgbuf, size_t send_msg_len, - Genode::Msgbuf_base &recv_msgbuf) +static inline void lx_call(int dst_sd, + Genode::Msgbuf_base &send_msgbuf, size_t send_msg_len, + Genode::Msgbuf_base &recv_msgbuf) { int ret; Message send_msg(send_msgbuf.buf, send_msg_len); @@ -426,7 +439,8 @@ static void lx_call(int dst_sd, ret = lx_sendmsg(dst_sd, send_msg.msg(), 0); if (ret < 0) { - PRAW("lx_sendmsg failed with %d in lx_call()", ret); + PRAW("[%d] lx_sendmsg to sd %d failed with %d in lx_call()", + lx_getpid(), dst_sd, ret); throw Genode::Ipc_error(); } @@ -437,7 +451,7 @@ static void lx_call(int dst_sd, ret = lx_recvmsg(reply_channel[LOCAL_SOCKET], recv_msg.msg(), 0); if (ret < 0) { - PRAW("lx_recvmsg failed with %d in lx_call()", ret); + PRAW("[%d] lx_recvmsg failed with %d in lx_call()", lx_getpid(), ret); throw Genode::Ipc_error(); } @@ -454,8 +468,8 @@ static void lx_call(int dst_sd, * * \return socket descriptor of reply capability */ -static int lx_wait(Genode::Native_connection_state &cs, - Genode::Msgbuf_base &recv_msgbuf) +static inline int lx_wait(Genode::Native_connection_state &cs, + Genode::Msgbuf_base &recv_msgbuf) { Message msg(recv_msgbuf.buf, recv_msgbuf.size()); @@ -478,9 +492,9 @@ static int lx_wait(Genode::Native_connection_state &cs, /** * Utility: Send reply to client */ -static void lx_reply(int reply_socket, - Genode::Msgbuf_base &send_msgbuf, - size_t msg_len) +static inline void lx_reply(int reply_socket, + Genode::Msgbuf_base &send_msgbuf, + size_t msg_len) { Message msg(send_msgbuf.buf, msg_len); diff --git a/base-linux/src/platform/lx_hybrid.cc b/base-linux/src/platform/lx_hybrid.cc index 02c1d326a1..d761795e7d 100644 --- a/base-linux/src/platform/lx_hybrid.cc +++ b/base-linux/src/platform/lx_hybrid.cc @@ -14,6 +14,7 @@ #include #include #include <_main_helper.h> +#include extern "C" int raw_write_str(const char *str); @@ -59,6 +60,7 @@ __attribute__((constructor(101))) void lx_hybrid_init() char **genode_argv = 0; int genode_argc = 1; + /************ ** Thread ** ************/ @@ -159,6 +161,23 @@ namespace Genode { static void empty_signal_handler(int) { } +/** + * Return Linux-specific extension of the Env::CPU session interface + */ +Linux_cpu_session *cpu_session() +{ + Linux_cpu_session *cpu = dynamic_cast(env()->cpu_session()); + + if (!cpu) { + PERR("could not obtain Linux extension to CPU session interface"); + struct Could_not_access_linux_cpu_session { }; + throw Could_not_access_linux_cpu_session(); + } + + return cpu; +} + + static void adopt_thread(Thread_meta_data *meta_data) { /* @@ -277,6 +296,17 @@ Thread_base::Thread_base(const char *name, size_t stack_size) } _tid.meta_data->construct_lock.lock(); + + Linux_cpu_session *cpu = dynamic_cast(env()->cpu_session()); + + if (!cpu) { + PERR("could not obtain Linux extension to CPU session interface"); + struct Could_not_access_linux_cpu_session { }; + throw Could_not_access_linux_cpu_session(); + } + + _thread_cap = cpu_session()->create_thread(name); + cpu_session()->thread_id(_thread_cap, _tid.pid, _tid.tid); } @@ -305,4 +335,7 @@ Thread_base::~Thread_base() destroy(env()->heap(), _tid.meta_data); _tid.meta_data = 0; + + /* inform core about the killed thread */ + cpu_session()->kill_thread(_thread_cap); } diff --git a/base/src/base/thread/thread.cc b/base/src/base/thread/thread.cc index bcb6665e86..d8fa548605 100644 --- a/base/src/base/thread/thread.cc +++ b/base/src/base/thread/thread.cc @@ -143,10 +143,8 @@ Thread_base::Context *Thread_base::_alloc_context(size_t stack_size) ds_cap = env_context_area_ram_session()->alloc(ds_size); addr_t attach_addr = ds_addr - Native_config::context_area_virtual_base(); env_context_area_rm_session()->attach_at(ds_cap, attach_addr, ds_size); - - } catch (Ram_session::Alloc_failed) { - 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