mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-18 07:08:18 +00:00
Thread API cleanup
This patch cleans up the thread API and comes with the following noteworthy changes: - Introduced Cpu_session::Weight type that replaces a formerly used plain integer value to prevent the accidental mix-up of arguments. - The enum definition of Cpu_session::DEFAULT_WEIGHT moved to Cpu_session::Weight::DEFAULT_WEIGHT - New Thread constructor that takes a 'Env &' as first argument. The original constructors are now marked as deprecated. For the common use case where the default 'Weight' and 'Affinity' are used, a shortcut is provided. In the long term, those two constructors should be the only ones to remain. - The former 'Thread<>' class template has been renamed to 'Thread_deprecated'. - The former 'Thread_base' class is now called 'Thread'. - The new 'name()' accessor returns the thread's name as 'Name' object as centrally defined via 'Cpu_session::Name'. It is meant to replace the old-fashioned 'name' method that takes a buffer and size as arguments. - Adaptation of the thread test to the new API Issue #1954
This commit is contained in:
committed by
Christian Helmuth
parent
7b73d1d823
commit
fd401bdf53
@ -35,27 +35,27 @@ void Cpu_thread_component::update_exception_sigh()
|
||||
|
||||
|
||||
Thread_capability Cpu_session_component::create_thread(Capability<Pd_session> pd_cap,
|
||||
size_t weight,
|
||||
Name const &name,
|
||||
Affinity::Location affinity,
|
||||
Weight weight,
|
||||
addr_t utcb)
|
||||
{
|
||||
Trace::Thread_name thread_name(name.string());
|
||||
|
||||
Cpu_thread_component *thread = 0;
|
||||
|
||||
if (weight == 0) {
|
||||
if (weight.value == 0) {
|
||||
PWRN("Thread %s: Bad weight 0, using %i instead.",
|
||||
name.string(), DEFAULT_WEIGHT);
|
||||
weight = DEFAULT_WEIGHT;
|
||||
name.string(), Weight::DEFAULT_WEIGHT);
|
||||
weight = Weight();
|
||||
}
|
||||
if (weight > QUOTA_LIMIT) {
|
||||
if (weight.value > QUOTA_LIMIT) {
|
||||
PWRN("Thread %s: Oversized weight %zu, using %i instead.",
|
||||
name.string(), weight, QUOTA_LIMIT);
|
||||
weight = QUOTA_LIMIT;
|
||||
name.string(), weight.value, QUOTA_LIMIT);
|
||||
weight = Weight(QUOTA_LIMIT);
|
||||
}
|
||||
Lock::Guard thread_list_lock_guard(_thread_list_lock);
|
||||
_incr_weight(weight);
|
||||
_incr_weight(weight.value);
|
||||
|
||||
/*
|
||||
* Create thread associated with its protection domain
|
||||
@ -69,7 +69,7 @@ Thread_capability Cpu_session_component::create_thread(Capability<Pd_session> pd
|
||||
thread = new (&_thread_alloc)
|
||||
Cpu_thread_component(
|
||||
cap(), *_thread_ep, *_pager_ep, *pd, _trace_control_area,
|
||||
weight, _weight_to_quota(weight),
|
||||
weight, _weight_to_quota(weight.value),
|
||||
_thread_affinity(affinity), _label, thread_name,
|
||||
_priority, utcb, _default_exception_handler);
|
||||
};
|
||||
|
@ -60,7 +60,7 @@ namespace Genode {
|
||||
Pager_entrypoint &_pager_ep;
|
||||
Capability<Pd_session> _pd;
|
||||
Region_map_component &_address_space_region_map;
|
||||
size_t const _weight;
|
||||
Cpu_session::Weight const _weight;
|
||||
Session_label const _session_label;
|
||||
Thread_name const _name;
|
||||
Platform_thread _platform_thread;
|
||||
@ -116,7 +116,8 @@ namespace Genode {
|
||||
* \param pager_ep pager entrypoint used for handling the page
|
||||
* faults of the thread
|
||||
* \param pd PD session where the thread is executed
|
||||
* \param weight weighting regarding the CPU session quota
|
||||
* \param weight scheduling weight relative to the other
|
||||
* threads of the same CPU session
|
||||
* \param quota initial quota counter-value of the weight
|
||||
* \param labal label of the threads session
|
||||
* \param name name for the thread
|
||||
@ -124,24 +125,25 @@ namespace Genode {
|
||||
* \param utcb user-local UTCB base
|
||||
* \param sigh initial exception handler
|
||||
*/
|
||||
Cpu_thread_component(Cpu_session_capability cpu_session_cap,
|
||||
Rpc_entrypoint &ep,
|
||||
Pager_entrypoint &pager_ep,
|
||||
Pd_session_component &pd,
|
||||
Trace::Control_area &trace_control_area,
|
||||
size_t const weight,
|
||||
size_t const quota,
|
||||
Affinity::Location affinity,
|
||||
Session_label const &label,
|
||||
Thread_name const &name,
|
||||
unsigned priority, addr_t utcb,
|
||||
Cpu_thread_component(Cpu_session_capability cpu_session_cap,
|
||||
Rpc_entrypoint &ep,
|
||||
Pager_entrypoint &pager_ep,
|
||||
Pd_session_component &pd,
|
||||
Trace::Control_area &trace_control_area,
|
||||
Cpu_session::Weight weight,
|
||||
size_t quota,
|
||||
Affinity::Location location,
|
||||
Session_label const &label,
|
||||
Thread_name const &name,
|
||||
unsigned priority,
|
||||
addr_t utcb,
|
||||
Signal_context_capability sigh)
|
||||
:
|
||||
_ep(ep), _pager_ep(pager_ep), _pd(pd.cap()),
|
||||
_address_space_region_map(pd.address_space_region_map()),
|
||||
_weight(weight),
|
||||
_session_label(label), _name(name),
|
||||
_platform_thread(quota, name.string(), priority, affinity, utcb),
|
||||
_platform_thread(quota, name.string(), priority, location, utcb),
|
||||
_bound_to_pd(_bind_to_pd(pd)),
|
||||
_sigh(sigh),
|
||||
_trace_control_slot(trace_control_area),
|
||||
@ -195,7 +197,7 @@ namespace Genode {
|
||||
|
||||
Trace::Source *trace_source() { return &_trace_source; }
|
||||
|
||||
size_t weight() const { return _weight; }
|
||||
size_t weight() const { return _weight.value; }
|
||||
|
||||
void sigh(Signal_context_capability sigh)
|
||||
{
|
||||
@ -340,8 +342,8 @@ namespace Genode {
|
||||
** CPU session interface **
|
||||
***************************/
|
||||
|
||||
Thread_capability create_thread(Capability<Pd_session>, size_t, Name const &,
|
||||
Affinity::Location, addr_t) override;
|
||||
Thread_capability create_thread(Capability<Pd_session>, Name const &,
|
||||
Affinity::Location, Weight, addr_t) override;
|
||||
Ram_dataspace_capability utcb(Thread_capability thread) override;
|
||||
void kill_thread(Thread_capability) override;
|
||||
int start(Thread_capability, addr_t, addr_t) override;
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
namespace Genode { class Irq_object; }
|
||||
|
||||
class Genode::Irq_object : public Thread<4096> {
|
||||
class Genode::Irq_object : public Thread_deprecated<4096> {
|
||||
|
||||
private:
|
||||
|
||||
|
@ -141,7 +141,7 @@ class Genode::Pager_object : public Object_pool<Pager_object>::Entry
|
||||
|
||||
|
||||
class Genode::Pager_entrypoint : public Object_pool<Pager_object>,
|
||||
public Thread<PAGER_EP_STACK_SIZE>
|
||||
public Thread_deprecated<PAGER_EP_STACK_SIZE>
|
||||
{
|
||||
private:
|
||||
|
||||
@ -161,7 +161,7 @@ class Genode::Pager_entrypoint : public Object_pool<Pager_object>,
|
||||
*/
|
||||
Pager_entrypoint(Rpc_cap_factory &cap_factory)
|
||||
:
|
||||
Thread<PAGER_EP_STACK_SIZE>("pager_ep"),
|
||||
Thread_deprecated<PAGER_EP_STACK_SIZE>("pager_ep"),
|
||||
_cap_factory(cap_factory)
|
||||
{ start(); }
|
||||
|
||||
|
@ -22,6 +22,9 @@
|
||||
#include <rom_session/connection.h>
|
||||
#include <cpu_session/connection.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/globals.h>
|
||||
|
||||
/* core includes */
|
||||
#include <platform.h>
|
||||
#include <core_env.h>
|
||||
@ -195,7 +198,7 @@ class Core_child : public Child_policy
|
||||
* the creation of regular threads within core is unsupported.
|
||||
*/
|
||||
|
||||
namespace Genode { void init_signal_thread() { } }
|
||||
namespace Genode { void init_signal_thread(Env &) { } }
|
||||
|
||||
|
||||
/*******************
|
||||
|
@ -40,13 +40,13 @@ struct Genode::Expanding_cpu_session_client : Upgradeable_client<Genode::Cpu_ses
|
||||
{ }
|
||||
|
||||
Thread_capability
|
||||
create_thread(Pd_session_capability pd, size_t quota, Name const &name,
|
||||
Affinity::Location location, addr_t utcb)
|
||||
create_thread(Pd_session_capability pd, Name const &name,
|
||||
Affinity::Location location, Weight weight, addr_t utcb) override
|
||||
{
|
||||
return retry<Cpu_session::Out_of_metadata>(
|
||||
[&] () {
|
||||
return Cpu_session_client::create_thread(pd, quota, name,
|
||||
location, utcb); },
|
||||
return Cpu_session_client::create_thread(pd, name, location,
|
||||
weight, utcb); },
|
||||
[&] () { upgrade_ram(8*1024); });
|
||||
}
|
||||
};
|
||||
|
@ -21,11 +21,12 @@ namespace Genode {
|
||||
|
||||
class Region_map;
|
||||
class Ram_session;
|
||||
class Env;
|
||||
|
||||
extern Region_map *env_stack_area_region_map;
|
||||
extern Ram_session *env_stack_area_ram_session;
|
||||
|
||||
void init_signal_thread();
|
||||
void init_signal_thread(Env &);
|
||||
void init_log();
|
||||
}
|
||||
|
||||
|
@ -30,14 +30,14 @@
|
||||
* data shared between the user-level thread and the kernel. It is typically
|
||||
* used for transferring IPC message payload or for system-call arguments.
|
||||
* The additional stack members are a reference to the corresponding
|
||||
* 'Thread_base' object and the name of the thread.
|
||||
* 'Thread' object and the name of the thread.
|
||||
*
|
||||
* The stack area is a virtual memory area, initially not backed by real
|
||||
* memory. When a new thread is created, an empty slot gets assigned to the new
|
||||
* thread and populated with memory pages for the stack and thread-specific
|
||||
* data. Note that this memory is allocated from the RAM session of the
|
||||
* component environment and not accounted for when using the 'sizeof()'
|
||||
* operand on a 'Thread_base' object.
|
||||
* operand on a 'Thread' object.
|
||||
*
|
||||
* A thread may be associated with more than one stack. Additional secondary
|
||||
* stacks can be associated with a thread, and used for user level scheduling.
|
||||
@ -58,6 +58,7 @@
|
||||
#include <base/native_types.h> /* for 'Native_utcb' */
|
||||
#include <cpu/consts.h>
|
||||
#include <ram_session/ram_session.h> /* for 'Ram_dataspace_capability' type */
|
||||
#include <cpu_session/cpu_session.h> /* for 'Cpu_session::Name' type */
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/native_utcb.h>
|
||||
@ -75,7 +76,7 @@ class Genode::Stack
|
||||
{
|
||||
public:
|
||||
|
||||
typedef String<64> Name;
|
||||
typedef Cpu_session::Name Name;
|
||||
|
||||
private:
|
||||
|
||||
@ -93,9 +94,9 @@ class Genode::Stack
|
||||
Name const _name;
|
||||
|
||||
/**
|
||||
* Pointer to corresponding 'Thread_base' object
|
||||
* Pointer to corresponding 'Thread' object
|
||||
*/
|
||||
Thread_base &_thread;
|
||||
Thread &_thread;
|
||||
|
||||
/**
|
||||
* Virtual address of the start of the stack
|
||||
@ -135,7 +136,7 @@ class Genode::Stack
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Stack(Name const &name, Thread_base &thread, addr_t base,
|
||||
Stack(Name const &name, Thread &thread, addr_t base,
|
||||
Ram_dataspace_capability ds_cap)
|
||||
:
|
||||
_name(name), _thread(thread), _base(base), _ds_cap(ds_cap)
|
||||
@ -179,9 +180,9 @@ class Genode::Stack
|
||||
Name name() const { return _name; }
|
||||
|
||||
/**
|
||||
* Return 'Thread_base' object of the stack's thread
|
||||
* Return 'Thread' object of the stack's thread
|
||||
*/
|
||||
Thread_base &thread() { return _thread; }
|
||||
Thread &thread() { return _thread; }
|
||||
|
||||
/**
|
||||
* Return dataspace used as the stack's backing storage
|
||||
|
@ -59,7 +59,7 @@ class Genode::Stack_allocator
|
||||
* \return virtual address of new stack, or
|
||||
* 0 if the allocation failed
|
||||
*/
|
||||
Stack *alloc(Thread_base *thread, bool main_thread);
|
||||
Stack *alloc(Thread *thread, bool main_thread);
|
||||
|
||||
/**
|
||||
* Release stack
|
||||
|
@ -167,7 +167,7 @@ Child::Process::Initial_thread::Initial_thread(Cpu_session &cpu,
|
||||
char const *name)
|
||||
:
|
||||
cpu(cpu),
|
||||
cap(cpu.create_thread(pd, Cpu_session::DEFAULT_WEIGHT, name))
|
||||
cap(cpu.create_thread(pd, name, Affinity::Location(), Cpu_session::Weight()))
|
||||
{ }
|
||||
|
||||
|
||||
|
@ -12,11 +12,14 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/entrypoint.h>
|
||||
#include <base/component.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <util/retry.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/globals.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
@ -27,7 +30,6 @@ namespace Genode {
|
||||
|
||||
extern bool inhibit_tracing;
|
||||
void call_global_static_constructors();
|
||||
void init_signal_thread();
|
||||
void destroy_signal_thread();
|
||||
|
||||
extern void (*call_component_construct)(Genode::Env &);
|
||||
@ -76,7 +78,7 @@ void Entrypoint::_process_incoming_signals()
|
||||
/* execute fork magic in noux plugin */
|
||||
_suspended_callback();
|
||||
|
||||
init_signal_thread();
|
||||
init_signal_thread(_env);
|
||||
_rpc_ep.construct(&_env.pd(), Component::stack_size(), Component::name());
|
||||
_signal_proxy_cap = manage(_signal_proxy);
|
||||
_sig_rec.construct();
|
||||
@ -155,7 +157,7 @@ Entrypoint::Entrypoint(Env &env)
|
||||
_rpc_ep(&env.pd(), Component::stack_size(), Component::name())
|
||||
{
|
||||
/* initialize signalling after initializing but before calling the entrypoint */
|
||||
init_signal_thread();
|
||||
init_signal_thread(_env);
|
||||
|
||||
/*
|
||||
* Invoke Component::construct function in the context of the entrypoint.
|
||||
@ -186,6 +188,6 @@ Entrypoint::Entrypoint(Env &env, size_t stack_size, char const *name)
|
||||
_env(env),
|
||||
_rpc_ep(&env.pd(), stack_size, name)
|
||||
{
|
||||
_signal_proxy_thread.construct(*this);
|
||||
_signal_proxy_thread.construct(env, *this);
|
||||
}
|
||||
|
||||
|
@ -21,13 +21,13 @@
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
static inline Genode::Thread_base *invalid_thread_base()
|
||||
static inline Genode::Thread *invalid_thread_base()
|
||||
{
|
||||
return (Genode::Thread_base*)~0;
|
||||
return (Genode::Thread*)~0;
|
||||
}
|
||||
|
||||
|
||||
static inline bool thread_base_valid(Genode::Thread_base *thread_base)
|
||||
static inline bool thread_base_valid(Genode::Thread *thread_base)
|
||||
{
|
||||
return (thread_base != invalid_thread_base());
|
||||
}
|
||||
@ -62,7 +62,7 @@ void Cancelable_lock::Applicant::wake_up()
|
||||
|
||||
void Cancelable_lock::lock()
|
||||
{
|
||||
Applicant myself(Thread_base::myself());
|
||||
Applicant myself(Thread::myself());
|
||||
|
||||
spinlock_lock(&_spinlock_state);
|
||||
|
||||
|
@ -60,7 +60,7 @@ void Rpc_entrypoint::activate()
|
||||
|
||||
bool Rpc_entrypoint::is_myself() const
|
||||
{
|
||||
return (Thread_base::myself() == this);
|
||||
return (Thread::myself() == this);
|
||||
}
|
||||
|
||||
|
||||
@ -68,13 +68,13 @@ Rpc_entrypoint::Rpc_entrypoint(Pd_session *pd_session, size_t stack_size,
|
||||
char const *name, bool start_on_construction,
|
||||
Affinity::Location location)
|
||||
:
|
||||
Thread_base(Cpu_session::DEFAULT_WEIGHT, name, stack_size, location),
|
||||
Thread(Cpu_session::Weight::DEFAULT_WEIGHT, name, stack_size, location),
|
||||
_cap(Untyped_capability()),
|
||||
_cap_valid(Lock::LOCKED), _delay_start(Lock::LOCKED),
|
||||
_delay_exit(Lock::LOCKED),
|
||||
_pd_session(*pd_session)
|
||||
{
|
||||
Thread_base::start();
|
||||
Thread::start();
|
||||
_block_until_cap_valid();
|
||||
|
||||
if (start_on_construction)
|
||||
|
@ -11,6 +11,7 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/retry.h>
|
||||
#include <base/env.h>
|
||||
#include <base/signal.h>
|
||||
@ -20,11 +21,12 @@
|
||||
#include <signal_source/client.h>
|
||||
#include <util/volatile_object.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/globals.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
enum { STACK_SIZE = 4*1024*sizeof(addr_t) };
|
||||
|
||||
class Signal_handler_thread : Thread<STACK_SIZE>, Lock
|
||||
class Signal_handler_thread : Thread, Lock
|
||||
{
|
||||
private:
|
||||
|
||||
@ -44,13 +46,15 @@ class Signal_handler_thread : Thread<STACK_SIZE>, Lock
|
||||
Signal_receiver::dispatch_signals(&(*_signal_source));
|
||||
}
|
||||
|
||||
enum { STACK_SIZE = 4*1024*sizeof(addr_t) };
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Signal_handler_thread()
|
||||
: Thread<STACK_SIZE>("signal handler"), Lock(Lock::LOCKED)
|
||||
Signal_handler_thread(Env &env)
|
||||
: Thread(env, "signal handler", STACK_SIZE), Lock(Lock::LOCKED)
|
||||
{
|
||||
start();
|
||||
|
||||
@ -92,10 +96,10 @@ namespace Genode {
|
||||
* We allow this function to be overridden in to enable core to omit the
|
||||
* creation of the signal thread.
|
||||
*/
|
||||
void init_signal_thread() __attribute__((weak));
|
||||
void init_signal_thread()
|
||||
void init_signal_thread(Env &env) __attribute__((weak));
|
||||
void init_signal_thread(Env &env)
|
||||
{
|
||||
signal_handler_thread().construct();
|
||||
signal_handler_thread().construct(env);
|
||||
}
|
||||
|
||||
void destroy_signal_thread()
|
||||
|
@ -45,7 +45,7 @@ addr_t Stack_allocator::idx_to_base(size_t idx)
|
||||
|
||||
|
||||
Stack *
|
||||
Stack_allocator::alloc(Thread_base *thread_base, bool main_thread)
|
||||
Stack_allocator::alloc(Thread *thread_base, bool main_thread)
|
||||
{
|
||||
if (main_thread)
|
||||
/* the main-thread stack is the first one */
|
||||
|
@ -52,7 +52,7 @@ void Stack::size(size_t const size)
|
||||
addr_t const stack_slot_base = Stack_allocator::addr_to_base(this);
|
||||
size_t const ds_size = align_addr(size - stack_size, PAGE_SIZE_LOG2);
|
||||
if (_base - ds_size < stack_slot_base)
|
||||
throw Thread_base::Stack_too_large();
|
||||
throw Thread::Stack_too_large();
|
||||
|
||||
/* allocate and attach backing store for the stack enhancement */
|
||||
addr_t const ds_addr = _base - ds_size - stack_area_virtual_base();
|
||||
@ -63,10 +63,10 @@ void Stack::size(size_t const size)
|
||||
void * const attach_addr = rm->attach_at(ds_cap, ds_addr, ds_size);
|
||||
|
||||
if (ds_addr != (addr_t)attach_addr)
|
||||
throw Thread_base::Out_of_stack_space();
|
||||
throw Thread::Out_of_stack_space();
|
||||
}
|
||||
catch (Ram_session::Alloc_failed) {
|
||||
throw Thread_base::Stack_alloc_failed();
|
||||
throw Thread::Stack_alloc_failed();
|
||||
}
|
||||
|
||||
/* update stack information */
|
||||
@ -75,7 +75,7 @@ void Stack::size(size_t const size)
|
||||
|
||||
|
||||
Stack *
|
||||
Thread_base::_alloc_stack(size_t stack_size, char const *name, bool main_thread)
|
||||
Thread::_alloc_stack(size_t stack_size, char const *name, bool main_thread)
|
||||
{
|
||||
/*
|
||||
* Synchronize stack list when creating new threads from multiple threads
|
||||
@ -134,7 +134,7 @@ Thread_base::_alloc_stack(size_t stack_size, char const *name, bool main_thread)
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::_free_stack(Stack *stack)
|
||||
void Thread::_free_stack(Stack *stack)
|
||||
{
|
||||
addr_t ds_addr = stack->base() - stack_area_virtual_base();
|
||||
Ram_dataspace_capability ds_cap = stack->ds_cap();
|
||||
@ -150,63 +150,66 @@ void Thread_base::_free_stack(Stack *stack)
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::name(char *dst, size_t dst_len)
|
||||
void Thread::name(char *dst, size_t dst_len)
|
||||
{
|
||||
snprintf(dst, dst_len, "%s", _stack->name().string());
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::join() { _join_lock.lock(); }
|
||||
Thread::Name Thread::name() const { return _stack->name(); }
|
||||
|
||||
|
||||
void *Thread_base::alloc_secondary_stack(char const *name, size_t stack_size)
|
||||
void Thread::join() { _join_lock.lock(); }
|
||||
|
||||
|
||||
void *Thread::alloc_secondary_stack(char const *name, size_t stack_size)
|
||||
{
|
||||
Stack *stack = _alloc_stack(stack_size, name, false);
|
||||
return (void *)stack->top();
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::free_secondary_stack(void* stack_addr)
|
||||
void Thread::free_secondary_stack(void* stack_addr)
|
||||
{
|
||||
addr_t base = Stack_allocator::addr_to_base(stack_addr);
|
||||
_free_stack(Stack_allocator::base_to_stack(base));
|
||||
}
|
||||
|
||||
|
||||
Native_thread &Thread_base::native_thread() {
|
||||
Native_thread &Thread::native_thread() {
|
||||
|
||||
return _stack->native_thread(); }
|
||||
|
||||
|
||||
void *Thread_base::stack_top() const { return (void *)_stack->top(); }
|
||||
void *Thread::stack_top() const { return (void *)_stack->top(); }
|
||||
|
||||
|
||||
void *Thread_base::stack_base() const { return (void*)_stack->base(); }
|
||||
void *Thread::stack_base() const { return (void*)_stack->base(); }
|
||||
|
||||
|
||||
void Thread_base::stack_size(size_t const size) { _stack->size(size); }
|
||||
void Thread::stack_size(size_t const size) { _stack->size(size); }
|
||||
|
||||
|
||||
size_t Thread_base::stack_virtual_size()
|
||||
size_t Thread::stack_virtual_size()
|
||||
{
|
||||
return Genode::stack_virtual_size();
|
||||
}
|
||||
|
||||
|
||||
addr_t Thread_base::stack_area_virtual_base()
|
||||
addr_t Thread::stack_area_virtual_base()
|
||||
{
|
||||
return Genode::stack_area_virtual_base();
|
||||
}
|
||||
|
||||
|
||||
size_t Thread_base::stack_area_virtual_size()
|
||||
size_t Thread::stack_area_virtual_size()
|
||||
{
|
||||
return Genode::stack_area_virtual_size();
|
||||
}
|
||||
|
||||
|
||||
Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size,
|
||||
Type type, Cpu_session *cpu_session, Affinity::Location affinity)
|
||||
Thread::Thread(size_t weight, const char *name, size_t stack_size,
|
||||
Type type, Cpu_session *cpu_session, Affinity::Location affinity)
|
||||
:
|
||||
_cpu_session(cpu_session),
|
||||
_affinity(affinity),
|
||||
@ -225,14 +228,25 @@ Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size,
|
||||
}
|
||||
|
||||
|
||||
Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size,
|
||||
Type type, Affinity::Location affinity)
|
||||
: Thread_base(weight, name, stack_size, type, nullptr, affinity) { }
|
||||
Thread::Thread(size_t weight, const char *name, size_t stack_size,
|
||||
Type type, Affinity::Location affinity)
|
||||
: Thread(weight, name, stack_size, type, nullptr, affinity) { }
|
||||
|
||||
|
||||
Thread_base::~Thread_base()
|
||||
Thread::Thread(Env &env, Name const &name, size_t stack_size, Location location,
|
||||
Weight weight, Cpu_session &cpu)
|
||||
: Thread(weight.value, name.string(), stack_size, NORMAL,
|
||||
&cpu == &env.cpu() ? nullptr : &cpu, location)
|
||||
{ }
|
||||
|
||||
|
||||
Thread::Thread(Env &env, Name const &name, size_t stack_size)
|
||||
: Thread(env, name, stack_size, Location(), Weight(), env.cpu()) { }
|
||||
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
if (Thread_base::myself() == this) {
|
||||
if (Thread::myself() == this) {
|
||||
PERR("thread '%s' tried to self de-struct - sleeping forever.",
|
||||
_stack->name().string());
|
||||
sleep_forever();
|
||||
|
@ -15,4 +15,4 @@
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
void Thread_base::_thread_bootstrap() { }
|
||||
void Thread::_thread_bootstrap() { }
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <base/internal/stack_area.h>
|
||||
|
||||
|
||||
Genode::Thread_base *Genode::Thread_base::myself()
|
||||
Genode::Thread *Genode::Thread::myself()
|
||||
{
|
||||
int dummy = 0; /* used for determining the stack pointer */
|
||||
|
||||
|
@ -26,20 +26,20 @@ using namespace Genode;
|
||||
/**
|
||||
* Entry point entered by new threads
|
||||
*/
|
||||
void Thread_base::_thread_start()
|
||||
void Thread::_thread_start()
|
||||
{
|
||||
Thread_base::myself()->_thread_bootstrap();
|
||||
Thread_base::myself()->entry();
|
||||
Thread_base::myself()->_join_lock.unlock();
|
||||
Thread::myself()->_thread_bootstrap();
|
||||
Thread::myself()->entry();
|
||||
Thread::myself()->_join_lock.unlock();
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Thread base **
|
||||
*****************/
|
||||
/************
|
||||
** Thread **
|
||||
************/
|
||||
|
||||
void Thread_base::_deinit_platform_thread()
|
||||
void Thread::_deinit_platform_thread()
|
||||
{
|
||||
if (!_cpu_session)
|
||||
_cpu_session = env()->cpu_session();
|
||||
@ -48,19 +48,16 @@ void Thread_base::_deinit_platform_thread()
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::start()
|
||||
void Thread::start()
|
||||
{
|
||||
/* if no cpu session is given, use it from the environment */
|
||||
/* if no CPU session is given, use it from the environment */
|
||||
if (!_cpu_session)
|
||||
_cpu_session = env()->cpu_session();
|
||||
|
||||
/* create thread at core */
|
||||
char buf[48];
|
||||
name(buf, sizeof(buf));
|
||||
enum { WEIGHT = Cpu_session::DEFAULT_WEIGHT };
|
||||
addr_t const utcb = (addr_t)&_stack->utcb();
|
||||
_thread_cap = _cpu_session->create_thread(env()->pd_session_cap(),
|
||||
WEIGHT, buf, _affinity, utcb);
|
||||
_thread_cap = _cpu_session->create_thread(env()->pd_session_cap(), name(),
|
||||
_affinity, Weight(), utcb);
|
||||
if (!_thread_cap.valid())
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
|
||||
@ -69,7 +66,7 @@ void Thread_base::start()
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::cancel_blocking()
|
||||
void Thread::cancel_blocking()
|
||||
{
|
||||
_cpu_session->cancel_blocking(_thread_cap);
|
||||
}
|
||||
|
@ -163,9 +163,9 @@ Trace::Logger::Logger()
|
||||
{ }
|
||||
|
||||
|
||||
/*****************
|
||||
** Thread_base **
|
||||
*****************/
|
||||
/************
|
||||
** Thread **
|
||||
************/
|
||||
|
||||
/**
|
||||
* return logger instance for the main thread **
|
||||
@ -180,12 +180,12 @@ static Trace::Logger *main_trace_logger()
|
||||
static Trace::Control *main_trace_control;
|
||||
|
||||
|
||||
Trace::Logger *Thread_base::_logger()
|
||||
Trace::Logger *Thread::_logger()
|
||||
{
|
||||
if (inhibit_tracing)
|
||||
return 0;
|
||||
|
||||
Thread_base * const myself = Thread_base::myself();
|
||||
Thread * const myself = Thread::myself();
|
||||
|
||||
Trace::Logger * const logger = myself ? &myself->_trace_logger
|
||||
: main_trace_logger();
|
||||
|
@ -19,4 +19,4 @@
|
||||
#include <base/internal/native_utcb.h>
|
||||
|
||||
|
||||
Genode::Native_utcb *Genode::Thread_base::utcb() { return &_stack->utcb(); }
|
||||
Genode::Native_utcb *Genode::Thread::utcb() { return &_stack->utcb(); }
|
||||
|
@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/log.h>
|
||||
#include <base/stdint.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/thread.h>
|
||||
@ -23,14 +23,14 @@ using namespace Genode;
|
||||
|
||||
extern "C" void __cxa_pure_virtual()
|
||||
{
|
||||
PWRN("cxa pure virtual function called, return addr is %p",
|
||||
__builtin_return_address(0));
|
||||
Genode::warning("cxa pure virtual function called, return addr is ",
|
||||
__builtin_return_address(0));
|
||||
}
|
||||
|
||||
|
||||
extern "C" void __pure_virtual()
|
||||
{
|
||||
PWRN("pure virtual function called");
|
||||
Genode::warning("pure virtual function called");
|
||||
}
|
||||
|
||||
|
||||
@ -103,15 +103,16 @@ extern "C" __attribute__((weak)) void raise()
|
||||
|
||||
extern "C" void *abort(void)
|
||||
{
|
||||
Genode::Thread_base * myself = Genode::Thread_base::myself();
|
||||
char thread_name[64] = { "unknown" };
|
||||
Genode::Thread const * const myself = Genode::Thread::myself();
|
||||
Thread::Name name = "unknown";
|
||||
|
||||
if (myself)
|
||||
myself->name(thread_name, sizeof(thread_name));
|
||||
PWRN("abort called - thread: '%s'", thread_name);
|
||||
name = myself->name();
|
||||
|
||||
Genode::warning("abort called - thread: ", name.string());
|
||||
|
||||
/* Notify the parent of failure */
|
||||
if (!strcmp("main", thread_name, sizeof(thread_name)))
|
||||
if (name != "main")
|
||||
env()->parent()->exit(1);
|
||||
|
||||
sleep_forever();
|
||||
@ -125,7 +126,7 @@ extern "C" void *fputc(void) {
|
||||
|
||||
|
||||
extern "C" void *fputs(const char *s, void *) {
|
||||
PWRN("C++ runtime: %s", s);
|
||||
Genode::warning("C++ runtime: ", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -166,7 +167,7 @@ void *memset(void *s, int c, size_t n)
|
||||
|
||||
|
||||
extern "C" void *stderr(void) {
|
||||
PWRN("stderr - not yet implemented");
|
||||
Genode::warning("stderr - not yet implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -180,7 +181,7 @@ FILE *__stderrp;
|
||||
|
||||
extern "C" void *strcat(void)
|
||||
{
|
||||
PWRN("strcat - not yet implemented");
|
||||
Genode::warning("strcat - not yet implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -214,7 +215,7 @@ extern "C" int strcmp(const char *s1, const char *s2)
|
||||
*/
|
||||
extern "C" int sprintf(char *str, const char *format, ...)
|
||||
{
|
||||
PWRN("sprintf - not implemented");
|
||||
Genode::warning("sprintf - not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -225,5 +226,5 @@ extern "C" int sprintf(char *str, const char *format, ...)
|
||||
|
||||
extern "C" __attribute__((weak)) void __stack_chk_fail_local(void)
|
||||
{
|
||||
PERR("Violated stack boundary");
|
||||
Genode::error("Violated stack boundary");
|
||||
}
|
||||
|
@ -567,9 +567,9 @@ void Component::construct(Genode::Env &env)
|
||||
try {
|
||||
if (Genode::config()->xml_node().attribute("ld_verbose").has_value("yes")) {
|
||||
PINF(" %lx .. %lx: stack area",
|
||||
Genode::Thread_base::stack_area_virtual_base(),
|
||||
Genode::Thread_base::stack_area_virtual_base() +
|
||||
Genode::Thread_base::stack_area_virtual_size() - 1);
|
||||
Genode::Thread::stack_area_virtual_base(),
|
||||
Genode::Thread::stack_area_virtual_base() +
|
||||
Genode::Thread::stack_area_virtual_size() - 1);
|
||||
dump_link_map(Elf_object::obj_list()->head());
|
||||
}
|
||||
} catch (...) { }
|
||||
|
@ -44,7 +44,7 @@ void init_rtld() { }
|
||||
/**
|
||||
* The first thread in a program
|
||||
*/
|
||||
class Main_thread : public Thread<MAIN_THREAD_STACK_SIZE>
|
||||
class Main_thread : public Thread_deprecated<MAIN_THREAD_STACK_SIZE>
|
||||
{
|
||||
public:
|
||||
|
||||
@ -55,7 +55,7 @@ class Main_thread : public Thread<MAIN_THREAD_STACK_SIZE>
|
||||
*/
|
||||
Main_thread(bool reinit)
|
||||
:
|
||||
Thread("main", reinit ? REINITIALIZED_MAIN : MAIN)
|
||||
Thread_deprecated("main", reinit ? REINITIALIZED_MAIN : MAIN)
|
||||
{ }
|
||||
|
||||
/**********************
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
enum { STACK_SIZE = sizeof(long)*1024, COUNT_VALUE = 10 * 1024 * 1024 };
|
||||
|
||||
struct Spinning_thread : Genode::Thread<STACK_SIZE>
|
||||
struct Spinning_thread : Genode::Thread_deprecated<STACK_SIZE>
|
||||
{
|
||||
Genode::Affinity::Location const _location;
|
||||
|
||||
@ -50,10 +50,10 @@ struct Spinning_thread : Genode::Thread<STACK_SIZE>
|
||||
|
||||
Spinning_thread(Genode::Affinity::Location location, char const *name)
|
||||
:
|
||||
Genode::Thread<STACK_SIZE>(name), _location(location), cnt(0ULL),
|
||||
Genode::Thread_deprecated<STACK_SIZE>(name), _location(location), cnt(0ULL),
|
||||
barrier(Genode::Lock::LOCKED)
|
||||
{
|
||||
Genode::env()->cpu_session()->affinity(Thread_base::cap(), location);
|
||||
Genode::env()->cpu_session()->affinity(Thread::cap(), location);
|
||||
start();
|
||||
}
|
||||
};
|
||||
|
@ -39,7 +39,7 @@ class Sync_signal_transmitter : public Signal_transmitter
|
||||
}
|
||||
};
|
||||
|
||||
class Fpu_user : public Thread<4 * 1024>
|
||||
class Fpu_user : public Thread_deprecated<4 * 1024>
|
||||
{
|
||||
private:
|
||||
|
||||
@ -56,7 +56,7 @@ class Fpu_user : public Thread<4 * 1024>
|
||||
|
||||
public:
|
||||
|
||||
Fpu_user() : Thread("fpu_user"), _x(0), _st(0) { }
|
||||
Fpu_user() : Thread_deprecated("fpu_user"), _x(0), _st(0) { }
|
||||
|
||||
void start(float const x, Sync_signal_transmitter * const st)
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ enum {
|
||||
/**
|
||||
* Region-manager fault handler resolves faults by attaching new dataspaces
|
||||
*/
|
||||
class Local_fault_handler : public Thread<4096>
|
||||
class Local_fault_handler : public Thread_deprecated<4096>
|
||||
{
|
||||
private:
|
||||
|
||||
@ -50,7 +50,7 @@ class Local_fault_handler : public Thread<4096>
|
||||
|
||||
Local_fault_handler(Region_map ®ion_map, Signal_receiver &receiver)
|
||||
:
|
||||
Thread("local_fault_handler"),
|
||||
Thread_deprecated("local_fault_handler"),
|
||||
_region_map(region_map), _receiver(receiver)
|
||||
{ }
|
||||
|
||||
|
@ -14,8 +14,12 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <base/log.h>
|
||||
#include <base/thread.h>
|
||||
#include <base/env.h>
|
||||
#include <base/component.h>
|
||||
#include <base/heap.h>
|
||||
#include <os/config.h>
|
||||
#include <util/volatile_object.h>
|
||||
#include <cpu_session/connection.h>
|
||||
|
||||
|
||||
@ -27,27 +31,34 @@ using namespace Genode;
|
||||
*********************************/
|
||||
|
||||
template <int CHILDREN>
|
||||
struct Helper : Thread<0x2000>
|
||||
struct Helper : Thread
|
||||
{
|
||||
void *child[CHILDREN];
|
||||
|
||||
Helper() : Thread<0x2000>("helper") { }
|
||||
enum { STACK_SIZE = 0x2000 };
|
||||
|
||||
Env &_env;
|
||||
|
||||
Helper(Env &env) : Thread(env, "helper", STACK_SIZE), _env(env) { }
|
||||
|
||||
void *stack() const { return _stack; }
|
||||
|
||||
void entry()
|
||||
{
|
||||
Helper helper[CHILDREN];
|
||||
Lazy_volatile_object<Helper> helper[CHILDREN];
|
||||
|
||||
for (unsigned i = 0; i < CHILDREN; ++i)
|
||||
child[i] = helper[i].stack();
|
||||
helper[i].construct(_env);
|
||||
|
||||
for (unsigned i = 0; i < CHILDREN; ++i)
|
||||
child[i] = helper[i]->stack();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static void test_stack_alloc()
|
||||
static void test_stack_alloc(Env &env)
|
||||
{
|
||||
printf("running '%s'\n", __func__);
|
||||
log("running '", __func__, "'");
|
||||
|
||||
/*
|
||||
* Create HELPER threads, which concurrently create CHILDREN threads each.
|
||||
@ -55,15 +66,16 @@ static void test_stack_alloc()
|
||||
*/
|
||||
enum { HELPER = 10, CHILDREN = 9 };
|
||||
|
||||
Helper<CHILDREN> helper[HELPER];
|
||||
Lazy_volatile_object<Helper<CHILDREN> > helper[HELPER];
|
||||
|
||||
for (unsigned i = 0; i < HELPER; ++i) helper[i].start();
|
||||
for (unsigned i = 0; i < HELPER; ++i) helper[i].join();
|
||||
for (unsigned i = 0; i < HELPER; ++i) helper[i].construct(env);
|
||||
for (unsigned i = 0; i < HELPER; ++i) helper[i]->start();
|
||||
for (unsigned i = 0; i < HELPER; ++i) helper[i]->join();
|
||||
|
||||
if (0)
|
||||
for (unsigned i = 0; i < HELPER; ++i)
|
||||
for (unsigned j = 0; j < CHILDREN; ++j)
|
||||
printf("%p [%d.%d]\n", helper[i].child[j], i, j);
|
||||
log(helper[i]->child[j], " [", i, ".", j, "]");
|
||||
}
|
||||
|
||||
|
||||
@ -92,13 +104,15 @@ static void test_stack_alignment_varargs(char const *format, ...)
|
||||
static void log_stack_address(char const *who)
|
||||
{
|
||||
long dummy;
|
||||
printf("%s stack @ %p\n", who, &dummy);
|
||||
log(who, " stack @ ", &dummy);
|
||||
}
|
||||
|
||||
|
||||
struct Stack_helper : Thread<0x2000>
|
||||
struct Stack_helper : Thread
|
||||
{
|
||||
Stack_helper() : Thread<0x2000>("stack_helper") { }
|
||||
enum { STACK_SIZE = 0x2000 };
|
||||
|
||||
Stack_helper(Env &env) : Thread(env, "stack_helper", STACK_SIZE) { }
|
||||
|
||||
void entry()
|
||||
{
|
||||
@ -108,11 +122,11 @@ struct Stack_helper : Thread<0x2000>
|
||||
};
|
||||
|
||||
|
||||
static void test_stack_alignment()
|
||||
static void test_stack_alignment(Env &env)
|
||||
{
|
||||
printf("running '%s'\n", __func__);
|
||||
log("running '", __func__, "'");
|
||||
|
||||
Stack_helper helper;
|
||||
Stack_helper helper(env);
|
||||
|
||||
helper.start();
|
||||
helper.join();
|
||||
@ -128,16 +142,16 @@ static void test_stack_alignment()
|
||||
|
||||
static void test_main_thread()
|
||||
{
|
||||
printf("running '%s'\n", __func__);
|
||||
log("running '", __func__, "'");
|
||||
|
||||
/* check wether my thread object exists */
|
||||
Thread_base * myself = Genode::Thread_base::myself();
|
||||
Thread * myself = Thread::myself();
|
||||
if (!myself) { throw -1; }
|
||||
printf("thread base %p\n", myself);
|
||||
log("thread base ", myself);
|
||||
|
||||
/* check whether my stack is inside the first stack region */
|
||||
addr_t const stack_slot_base = Thread_base::stack_area_virtual_base();
|
||||
addr_t const stack_slot_size = Thread_base::stack_area_virtual_size();
|
||||
addr_t const stack_slot_base = Thread::stack_area_virtual_base();
|
||||
addr_t const stack_slot_size = Thread::stack_area_virtual_size();
|
||||
addr_t const stack_slot_top = stack_slot_base + stack_slot_size;
|
||||
|
||||
addr_t const stack_top = (addr_t)myself->stack_top();
|
||||
@ -148,15 +162,15 @@ static void test_main_thread()
|
||||
if (stack_base >= stack_slot_top) { throw -4; }
|
||||
if (stack_base < stack_slot_base) { throw -5; }
|
||||
|
||||
printf("thread stack top %p\n", myself->stack_top());
|
||||
printf("thread stack bottom %p\n", myself->stack_base());
|
||||
log("thread stack top ", myself->stack_top());
|
||||
log("thread stack bottom ", myself->stack_base());
|
||||
|
||||
/* check wether my stack pointer is inside my stack */
|
||||
unsigned dummy = 0;
|
||||
addr_t const sp = (addr_t)&dummy;
|
||||
if (sp >= stack_top) { throw -6; }
|
||||
if (sp < stack_base) { throw -7; }
|
||||
printf("thread stack pointer %p\n", (void *)sp);
|
||||
log("thread stack pointer ", (void *)sp);
|
||||
}
|
||||
|
||||
|
||||
@ -164,56 +178,63 @@ static void test_main_thread()
|
||||
** Using cpu-session for thread creation *
|
||||
******************************************/
|
||||
|
||||
struct Cpu_helper : Thread<0x2000>
|
||||
struct Cpu_helper : Thread
|
||||
{
|
||||
Cpu_helper(const char * name, Cpu_session * cpu)
|
||||
: Thread<0x2000>(name, cpu) { }
|
||||
enum { STACK_SIZE = 0x2000 };
|
||||
|
||||
Env &_env;
|
||||
|
||||
Cpu_helper(Env &env, const char * name, Cpu_session &cpu)
|
||||
:
|
||||
Thread(env, name, STACK_SIZE, Thread::Location(), Thread::Weight(), cpu),
|
||||
_env(env)
|
||||
{ }
|
||||
|
||||
void entry()
|
||||
{
|
||||
char name[64];
|
||||
Thread_base::name(name, sizeof(name));
|
||||
printf("%s : _cpu_session=0x%p env()->cpu_session()=0x%p\n",
|
||||
name, _cpu_session, env()->cpu_session());
|
||||
log(Thread::name().string(), " : _cpu_session=", _cpu_session,
|
||||
" env.cpu()=", &_env.cpu());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static void test_cpu_session()
|
||||
static void test_cpu_session(Env &env)
|
||||
{
|
||||
printf("running '%s'\n", __func__);
|
||||
log("running '", __func__, "'");
|
||||
|
||||
Cpu_helper thread0("prio high ", env()->cpu_session());
|
||||
Cpu_helper thread0(env, "prio high ", env.cpu());
|
||||
thread0.start();
|
||||
thread0.join();
|
||||
|
||||
Cpu_connection con1("prio middle", Cpu_session::PRIORITY_LIMIT / 4);
|
||||
Cpu_helper thread1("prio middle", &con1);
|
||||
Cpu_helper thread1(env, "prio middle", con1);
|
||||
thread1.start();
|
||||
thread1.join();
|
||||
|
||||
Cpu_connection con2("prio low", Cpu_session::PRIORITY_LIMIT / 2);
|
||||
Cpu_helper thread2("prio low ", &con2);
|
||||
Cpu_helper thread2(env, "prio low ", con2);
|
||||
thread2.start();
|
||||
thread2.join();
|
||||
}
|
||||
|
||||
|
||||
struct Pause_helper : Thread<0x1000>
|
||||
struct Pause_helper : Thread
|
||||
{
|
||||
volatile unsigned loop = 0;
|
||||
volatile bool beep = false;
|
||||
|
||||
Pause_helper(const char * name, Cpu_session * cpu)
|
||||
: Thread<0x1000>(name, cpu) { }
|
||||
enum { STACK_SIZE = 0x1000 };
|
||||
|
||||
Pause_helper(Env &env, const char * name, Cpu_session &cpu)
|
||||
: Thread(env, name, STACK_SIZE, Thread::Location(), Thread::Weight(), cpu) { }
|
||||
|
||||
void entry()
|
||||
{
|
||||
while (1) {
|
||||
/**
|
||||
* Don't use printf here, since this thread becomes "paused".
|
||||
* If it is holding the lock of the printf backend being paused,
|
||||
* all other threads of this task trying to do printf will
|
||||
/*
|
||||
* Don't log here, since this thread becomes "paused".
|
||||
* If it is holding the lock of the log backend being paused, all
|
||||
* other threads of this task trying to print log messages will
|
||||
* block - looks like a deadlock.
|
||||
*/
|
||||
// printf("stop me if you can\n");
|
||||
@ -228,25 +249,26 @@ struct Pause_helper : Thread<0x1000>
|
||||
}
|
||||
};
|
||||
|
||||
static void test_pause_resume()
|
||||
{
|
||||
printf("running '%s'\n", __func__);
|
||||
|
||||
Pause_helper thread("pause", env()->cpu_session());
|
||||
static void test_pause_resume(Env &env)
|
||||
{
|
||||
log("running '", __func__, "'");
|
||||
|
||||
Pause_helper thread(env, "pause", env.cpu());
|
||||
thread.start();
|
||||
|
||||
while (thread.loop < 1) { }
|
||||
|
||||
Thread_state state;
|
||||
|
||||
printf("--- pausing ---\n");
|
||||
env()->cpu_session()->pause(thread.cap());
|
||||
log("--- pausing ---");
|
||||
env.cpu().pause(thread.cap());
|
||||
unsigned loop_paused = thread.loop;
|
||||
printf("--- paused ---\n");
|
||||
log("--- paused ---");
|
||||
|
||||
printf("--- reading thread state ---\n");
|
||||
log("--- reading thread state ---");
|
||||
try {
|
||||
state = env()->cpu_session()->state(thread.cap());
|
||||
state = env.cpu().state(thread.cap());
|
||||
} catch (Cpu_session::State_access_failed) {
|
||||
throw -10;
|
||||
}
|
||||
@ -254,47 +276,50 @@ static void test_pause_resume()
|
||||
throw -11;
|
||||
|
||||
thread.beep = true;
|
||||
printf("--- resuming thread ---\n");
|
||||
env()->cpu_session()->resume(thread.cap());
|
||||
log("--- resuming thread ---");
|
||||
env.cpu().resume(thread.cap());
|
||||
|
||||
while (thread.loop == loop_paused) { }
|
||||
|
||||
printf("--- thread resumed ---\n");
|
||||
log("--- thread resumed ---");
|
||||
thread.join();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Test to check that core as the used kernel behaves well if up to the
|
||||
* supported Genode maximum threads are created.
|
||||
*/
|
||||
static void test_create_as_many_threads()
|
||||
static void test_create_as_many_threads(Env &env)
|
||||
{
|
||||
printf("running '%s'\n", __func__);
|
||||
log("running '", __func__, "'");
|
||||
|
||||
addr_t const max = Thread_base::stack_area_virtual_size() /
|
||||
Thread_base::stack_virtual_size();
|
||||
addr_t const max = Thread::stack_area_virtual_size() /
|
||||
Thread::stack_virtual_size();
|
||||
|
||||
Cpu_helper * threads[max];
|
||||
static char thread_name[8];
|
||||
|
||||
Heap heap(env.ram(), env.rm());
|
||||
|
||||
unsigned i = 0;
|
||||
try {
|
||||
for (; i < max; i++) {
|
||||
try {
|
||||
snprintf(thread_name, sizeof(thread_name), "%u", i + 1);
|
||||
threads[i] = new (env()->heap()) Cpu_helper(thread_name, env()->cpu_session());
|
||||
threads[i] = new (heap) Cpu_helper(env, thread_name, env.cpu());
|
||||
threads[i]->start();
|
||||
threads[i]->join();
|
||||
} catch (Cpu_session::Thread_creation_failed) {
|
||||
throw "Thread_creation_failed";
|
||||
} catch (Thread_base::Out_of_stack_space) {
|
||||
} catch (Thread::Out_of_stack_space) {
|
||||
throw "Out_of_stack_space";
|
||||
}
|
||||
}
|
||||
} catch (const char * ex) {
|
||||
PINF("created %u threads before I got '%s'", i, ex);
|
||||
for (unsigned j = i; j > 0; j--) {
|
||||
destroy(env()->heap(), threads[j - 1]);
|
||||
destroy(heap, threads[j - 1]);
|
||||
threads[j - 1] = nullptr;
|
||||
}
|
||||
return;
|
||||
@ -307,18 +332,33 @@ static void test_create_as_many_threads()
|
||||
throw -21;
|
||||
}
|
||||
|
||||
int main()
|
||||
|
||||
char const *Component::name() { return "test-thread"; }
|
||||
|
||||
|
||||
size_t Component::stack_size() { return 16*1024*sizeof(long); }
|
||||
|
||||
|
||||
void Component::construct(Env &env)
|
||||
{
|
||||
printf("--- thread test started ---\n");
|
||||
log("--- thread test started ---");
|
||||
|
||||
Xml_node config = Genode::config()->xml_node();
|
||||
|
||||
try {
|
||||
test_stack_alloc();
|
||||
test_stack_alignment();
|
||||
test_stack_alloc(env);
|
||||
test_stack_alignment(env);
|
||||
test_main_thread();
|
||||
test_cpu_session();
|
||||
test_pause_resume();
|
||||
test_create_as_many_threads();
|
||||
test_cpu_session(env);
|
||||
|
||||
if (config.has_sub_node("pause_resume"))
|
||||
test_pause_resume(env);
|
||||
|
||||
test_create_as_many_threads(env);
|
||||
} catch (int error) {
|
||||
return error;
|
||||
Genode::error("error ", error);
|
||||
throw;
|
||||
}
|
||||
|
||||
log("--- test completed successfully ---");
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
TARGET = test-thread
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
||||
LIBS = base config
|
||||
|
@ -143,7 +143,7 @@ static void test_weak_pointer_tracking()
|
||||
*******************************************/
|
||||
|
||||
template <typename O>
|
||||
struct Destruct_thread : Genode::Thread<4096>
|
||||
struct Destruct_thread : Genode::Thread_deprecated<4096>
|
||||
{
|
||||
O *obj;
|
||||
|
||||
@ -155,7 +155,7 @@ struct Destruct_thread : Genode::Thread<4096>
|
||||
PLOG("thread: destruction completed, job done");
|
||||
}
|
||||
|
||||
Destruct_thread(O *obj) : Thread("object_destructor"), obj(obj) { }
|
||||
Destruct_thread(O *obj) : Thread_deprecated("object_destructor"), obj(obj) { }
|
||||
};
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user