2011-12-22 16:19:25 +01:00
|
|
|
/*
|
|
|
|
* \brief Thread interface
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2006-04-28
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2016-01-23 14:42:55 +01:00
|
|
|
* Copyright (C) 2006-2016 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* 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__THREAD_H_
|
|
|
|
#define _INCLUDE__BASE__THREAD_H_
|
|
|
|
|
|
|
|
/* Genode includes */
|
|
|
|
#include <base/exception.h>
|
|
|
|
#include <base/lock.h>
|
|
|
|
#include <base/native_types.h>
|
2013-08-09 20:48:32 +02:00
|
|
|
#include <base/trace/logger.h>
|
2014-02-20 11:27:26 +01:00
|
|
|
#include <cpu/consts.h>
|
2013-09-06 16:20:41 +02:00
|
|
|
#include <util/string.h>
|
2014-01-24 12:06:21 +01:00
|
|
|
#include <util/bit_allocator.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
#include <ram_session/ram_session.h> /* for 'Ram_dataspace_capability' type */
|
|
|
|
#include <cpu_session/cpu_session.h> /* for 'Thread_capability' type */
|
2014-04-03 14:18:52 +02:00
|
|
|
#include <cpu_session/capability.h> /* for 'Cpu_session_capability' type */
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
namespace Genode {
|
|
|
|
|
|
|
|
class Rm_session;
|
2015-03-04 21:12:14 +01:00
|
|
|
class Thread_base;
|
2016-01-23 14:42:55 +01:00
|
|
|
class Stack;
|
2015-03-04 21:12:14 +01:00
|
|
|
template <unsigned> class Thread;
|
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
|
2015-03-04 21:12:14 +01:00
|
|
|
/**
|
|
|
|
* Concurrent control flow
|
|
|
|
*
|
|
|
|
* A 'Thread_base' object corresponds to a physical thread. The execution
|
2015-03-20 17:50:41 +01:00
|
|
|
* starts at the 'entry()' method as soon as 'start()' is called.
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
|
|
|
class Genode::Thread_base
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2016-01-23 14:42:55 +01:00
|
|
|
class Out_of_stack_space : public Exception { };
|
|
|
|
class Stack_too_large : public Exception { };
|
|
|
|
class Stack_alloc_failed : public Exception { };
|
2013-05-02 17:59:56 +02:00
|
|
|
|
2015-03-04 21:12:14 +01:00
|
|
|
private:
|
2014-02-26 16:47:54 +01:00
|
|
|
|
2015-03-04 21:12:14 +01:00
|
|
|
/**
|
2016-01-23 14:42:55 +01:00
|
|
|
* Allocate and locally attach a new stack
|
2015-03-04 21:12:14 +01:00
|
|
|
*
|
|
|
|
* \param stack_size size of this threads stack
|
|
|
|
* \param main_thread wether this is the main thread
|
|
|
|
*/
|
2016-01-23 14:42:55 +01:00
|
|
|
Stack *_alloc_stack(size_t stack_size, char const *name, bool main_thread);
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
2016-01-23 14:42:55 +01:00
|
|
|
* Detach and release stack of the thread
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
2016-01-23 14:42:55 +01:00
|
|
|
void _free_stack(Stack *stack);
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Platform-specific thread-startup code
|
|
|
|
*
|
|
|
|
* On some platforms, each new thread has to perform a startup
|
|
|
|
* protocol, e.g., waiting for a message from the kernel. This hook
|
2015-03-20 17:50:41 +01:00
|
|
|
* method allows for the implementation of such protocols.
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
|
|
|
void _thread_bootstrap();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper for thread startup
|
|
|
|
*/
|
|
|
|
static void _thread_start();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hook for platform-specific destructor supplements
|
|
|
|
*/
|
|
|
|
void _deinit_platform_thread();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Capability for this thread (set by _start())
|
|
|
|
*
|
|
|
|
* Used if thread creation involves core's CPU service.
|
|
|
|
*/
|
|
|
|
Genode::Thread_capability _thread_cap;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Capability to pager paging this thread (created by _start())
|
|
|
|
*/
|
|
|
|
Genode::Pager_capability _pager_cap;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Pointer to cpu session used for this thread
|
|
|
|
*/
|
|
|
|
Genode::Cpu_session *_cpu_session;
|
|
|
|
|
2015-07-03 16:22:35 +02:00
|
|
|
/**
|
|
|
|
* Base pointer to Trace::Control area used by this thread
|
|
|
|
*/
|
|
|
|
Trace::Control *_trace_control;
|
|
|
|
|
2015-03-04 21:12:14 +01:00
|
|
|
/**
|
2016-01-23 14:42:55 +01:00
|
|
|
* Pointer to primary stack
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
2016-01-23 14:42:55 +01:00
|
|
|
Stack *_stack;
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Physical thread ID
|
|
|
|
*/
|
|
|
|
Native_thread _tid;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Lock used for synchronizing the finalization of the thread
|
|
|
|
*/
|
|
|
|
Genode::Lock _join_lock;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Thread type
|
|
|
|
*
|
|
|
|
* Some threads need special treatment at construction. This enum
|
|
|
|
* is solely used to distinguish them at construction.
|
|
|
|
*/
|
|
|
|
enum Type { NORMAL, MAIN, REINITIALIZED_MAIN };
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
Trace::Logger _trace_logger;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return 'Trace::Logger' instance of calling thread
|
|
|
|
*
|
2015-03-20 17:50:41 +01:00
|
|
|
* This method is used by the tracing framework internally.
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
|
|
|
static Trace::Logger *_logger();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hook for platform-specific constructor supplements
|
|
|
|
*
|
2015-03-27 14:05:55 +01:00
|
|
|
* \param weight weighting regarding the CPU session quota
|
|
|
|
* \param type enables selection of special initialization
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
2015-03-27 14:05:55 +01:00
|
|
|
void _init_platform_thread(size_t weight, Type type);
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2015-03-24 21:14:44 +01:00
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* \noapi
|
|
|
|
*
|
2016-01-23 14:42:55 +01:00
|
|
|
* FIXME: With type = Forked_main_thread the stack allocation
|
|
|
|
* gets skipped but we should at least set Stack::ds_cap in a
|
|
|
|
* way that it references the dataspace of the already attached
|
|
|
|
* stack.
|
2015-03-24 21:14:44 +01:00
|
|
|
*/
|
2015-03-27 14:05:55 +01:00
|
|
|
Thread_base(size_t weight, const char *name, size_t stack_size,
|
2015-03-24 21:14:44 +01:00
|
|
|
Type type);
|
|
|
|
|
2015-03-04 21:12:14 +01:00
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
2015-03-27 14:05:55 +01:00
|
|
|
* \param weight weighting regarding the CPU session quota
|
|
|
|
* \param name thread name (for debugging)
|
2015-03-04 21:12:14 +01:00
|
|
|
* \param stack_size stack size
|
|
|
|
*
|
|
|
|
* \throw Stack_too_large
|
|
|
|
* \throw Stack_alloc_failed
|
2016-01-23 14:42:55 +01:00
|
|
|
* \throw Out_of_stack_space
|
2015-03-04 21:12:14 +01:00
|
|
|
*
|
2015-03-24 21:14:44 +01:00
|
|
|
* The stack for the new thread will be allocated from the RAM session
|
2016-01-23 14:42:55 +01:00
|
|
|
* of the component environment. A small portion of the stack size is
|
|
|
|
* internally used by the framework for storing thread-specific
|
|
|
|
* information such as the thread's name.
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
2015-03-27 14:05:55 +01:00
|
|
|
Thread_base(size_t weight, const char *name, size_t stack_size)
|
|
|
|
: Thread_base(weight, name, stack_size, NORMAL) { }
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
2015-03-24 21:14:44 +01:00
|
|
|
* Variant of the constructor that allows the use of a different
|
|
|
|
* CPU session.
|
|
|
|
*
|
|
|
|
* \noapi Using multiple CPU sessions within a single component is
|
|
|
|
* an experimental feature.
|
|
|
|
*
|
2015-03-27 14:05:55 +01:00
|
|
|
* \param weight weighting regarding the CPU session quota
|
|
|
|
* \param name thread name (for debugging)
|
2015-03-04 21:12:14 +01:00
|
|
|
* \param stack_size stack size
|
|
|
|
* \param type enables selection of special construction
|
|
|
|
* \param cpu_session capability to cpu session used for construction
|
|
|
|
*
|
|
|
|
* \throw Stack_too_large
|
|
|
|
* \throw Stack_alloc_failed
|
2016-01-23 14:42:55 +01:00
|
|
|
* \throw Out_of_stack_space
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
2015-03-27 14:05:55 +01:00
|
|
|
Thread_base(size_t weight, const char *name, size_t stack_size,
|
2015-03-04 21:12:14 +01:00
|
|
|
Type type, Cpu_session *);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destructor
|
|
|
|
*/
|
|
|
|
virtual ~Thread_base();
|
|
|
|
|
|
|
|
/**
|
2015-03-20 17:50:41 +01:00
|
|
|
* Entry method of the thread
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
|
|
|
virtual void entry() = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Start execution of the thread
|
|
|
|
*
|
2015-03-20 17:50:41 +01:00
|
|
|
* This method is virtual to enable the customization of threads
|
2015-03-04 21:12:14 +01:00
|
|
|
* used as server activation.
|
|
|
|
*/
|
|
|
|
virtual void start();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Request name of thread
|
|
|
|
*/
|
|
|
|
void name(char *dst, size_t dst_len);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add an additional stack to the thread
|
|
|
|
*
|
|
|
|
* \throw Stack_too_large
|
|
|
|
* \throw Stack_alloc_failed
|
2016-01-23 14:42:55 +01:00
|
|
|
* \throw Out_of_stack_space
|
2015-03-04 21:12:14 +01:00
|
|
|
*
|
|
|
|
* The stack for the new thread will be allocated from the RAM
|
2016-01-23 14:42:55 +01:00
|
|
|
* session of the component environment. A small portion of the
|
2015-03-04 21:12:14 +01:00
|
|
|
* stack size is internally used by the framework for storing
|
2016-01-23 14:42:55 +01:00
|
|
|
* thread-specific information such as the thread's name.
|
2015-03-04 21:12:14 +01:00
|
|
|
*
|
|
|
|
* \return pointer to the new stack's top
|
|
|
|
*/
|
|
|
|
void* alloc_secondary_stack(char const *name, size_t stack_size);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove a secondary stack from the thread
|
|
|
|
*/
|
|
|
|
void free_secondary_stack(void* stack_addr);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Request capability of thread
|
|
|
|
*/
|
|
|
|
Genode::Thread_capability cap() const { return _thread_cap; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cancel currently blocking operation
|
|
|
|
*/
|
|
|
|
void cancel_blocking();
|
|
|
|
|
|
|
|
/**
|
2015-03-20 17:50:41 +01:00
|
|
|
* Return thread ID
|
|
|
|
*
|
|
|
|
* \noapi Only to be called from platform-specific code
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
|
|
|
Native_thread & tid() { return _tid; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return top of stack
|
|
|
|
*
|
|
|
|
* \return pointer just after first stack element
|
|
|
|
*/
|
2016-01-23 14:42:55 +01:00
|
|
|
void *stack_top() const;
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return base of stack
|
|
|
|
*
|
|
|
|
* \return pointer to last stack element
|
|
|
|
*/
|
2016-01-23 14:42:55 +01:00
|
|
|
void *stack_base() const;
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return 'Thread_base' object corresponding to the calling thread
|
|
|
|
*
|
2015-03-20 17:50:41 +01:00
|
|
|
* \return pointer to caller's 'Thread_base' object
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
|
|
|
static Thread_base *myself();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ensure that the stack has a given size at the minimum
|
|
|
|
*
|
|
|
|
* \param size minimum stack size
|
|
|
|
*
|
2016-01-23 14:42:55 +01:00
|
|
|
* \throw Stack_too_large
|
|
|
|
* \throw Stack_alloc_failed
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
2016-01-23 14:42:55 +01:00
|
|
|
void stack_size(size_t const size);
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return user-level thread control block
|
|
|
|
*
|
2015-03-20 17:50:41 +01:00
|
|
|
* Note that it is safe to call this method on the result of the
|
|
|
|
* 'myself' class function. It handles the special case of 'myself'
|
|
|
|
* being 0 when called by the main thread during the component
|
|
|
|
* initialization phase.
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
|
|
|
Native_utcb *utcb();
|
|
|
|
|
|
|
|
/**
|
2015-03-20 17:50:41 +01:00
|
|
|
* Block until the thread leaves the 'entry' method
|
2015-03-04 21:12:14 +01:00
|
|
|
*
|
|
|
|
* Join must not be called more than once. Subsequent calls have
|
|
|
|
* undefined behaviour.
|
|
|
|
*/
|
|
|
|
void join();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Log null-terminated string as trace event
|
|
|
|
*/
|
|
|
|
static void trace(char const *cstring)
|
|
|
|
{
|
|
|
|
_logger()->log(cstring, strlen(cstring));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Log binary data as trace event
|
|
|
|
*/
|
|
|
|
static void trace(char const *data, size_t len)
|
|
|
|
{
|
|
|
|
_logger()->log(data, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Log trace event as defined in base/trace.h
|
|
|
|
*/
|
|
|
|
template <typename EVENT>
|
|
|
|
static void trace(EVENT const *event) { _logger()->log(event); }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <unsigned STACK_SIZE>
|
|
|
|
class Genode::Thread : public Thread_base
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
2015-03-27 14:05:55 +01:00
|
|
|
* \param weight weighting regarding the CPU session quota
|
|
|
|
* \param name thread name (for debugging)
|
|
|
|
* \param type enables selection of special construction
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
2015-03-27 14:05:55 +01:00
|
|
|
explicit Thread(size_t weight, const char *name)
|
|
|
|
: Thread_base(weight, name, STACK_SIZE, Type::NORMAL) { }
|
2015-03-24 21:14:44 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
2015-03-27 14:05:55 +01:00
|
|
|
* \param weight weighting regarding the CPU session quota
|
|
|
|
* \param name thread name (for debugging)
|
|
|
|
* \param type enables selection of special construction
|
2015-03-24 21:14:44 +01:00
|
|
|
*
|
|
|
|
* \noapi
|
|
|
|
*/
|
2015-03-27 14:05:55 +01:00
|
|
|
explicit Thread(size_t weight, const char *name, Type type)
|
|
|
|
: Thread_base(weight, name, STACK_SIZE, type) { }
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
2015-03-27 14:05:55 +01:00
|
|
|
* \param weight weighting regarding the CPU session quota
|
2015-03-04 21:12:14 +01:00
|
|
|
* \param name thread name (for debugging)
|
|
|
|
* \param cpu_session thread created via specific cpu session
|
2015-03-24 21:14:44 +01:00
|
|
|
*
|
|
|
|
* \noapi
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
2015-03-27 14:05:55 +01:00
|
|
|
explicit Thread(size_t weight, const char *name,
|
|
|
|
Cpu_session * cpu_session)
|
|
|
|
: Thread_base(weight, name, STACK_SIZE, Type::NORMAL, cpu_session) { }
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
2015-03-27 14:05:55 +01:00
|
|
|
* Shortcut for 'Thread(DEFAULT_WEIGHT, name, type)'
|
2015-03-24 21:14:44 +01:00
|
|
|
*
|
|
|
|
* \noapi
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
|
|
|
explicit Thread(const char *name, Type type = NORMAL)
|
2015-03-27 14:05:55 +01:00
|
|
|
: Thread_base(Cpu_session::DEFAULT_WEIGHT, name, STACK_SIZE, type) { }
|
2015-03-04 21:12:14 +01:00
|
|
|
|
|
|
|
/**
|
2015-03-27 14:05:55 +01:00
|
|
|
* Shortcut for 'Thread(DEFAULT_WEIGHT, name, cpu_session)'
|
2015-03-24 21:14:44 +01:00
|
|
|
*
|
|
|
|
* \noapi
|
2015-03-04 21:12:14 +01:00
|
|
|
*/
|
|
|
|
explicit Thread(const char *name, Cpu_session * cpu_session)
|
2015-03-27 14:05:55 +01:00
|
|
|
: Thread_base(Cpu_session::DEFAULT_WEIGHT, name, STACK_SIZE,
|
|
|
|
Type::NORMAL, cpu_session)
|
2015-03-04 21:12:14 +01:00
|
|
|
{ }
|
|
|
|
};
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
#endif /* _INCLUDE__BASE__THREAD_H_ */
|