2012-11-30 14:08:42 +01:00
|
|
|
/*
|
2013-10-07 14:56:31 +02:00
|
|
|
* \brief Kernel backend for execution contexts in userland
|
2012-11-30 14:08:42 +01:00
|
|
|
* \author Martin Stein
|
|
|
|
* \date 2012-11-30
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2012-2017 Genode Labs GmbH
|
2012-11-30 14:08:42 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2012-11-30 14:08:42 +01:00
|
|
|
*/
|
|
|
|
|
2017-04-12 10:06:29 +02:00
|
|
|
#ifndef _CORE__KERNEL__THREAD_H_
|
|
|
|
#define _CORE__KERNEL__THREAD_H_
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2018-11-26 11:18:57 +01:00
|
|
|
#include <base/signal.h>
|
|
|
|
#include <util/reconstructible.h>
|
|
|
|
|
2012-11-30 14:08:42 +01:00
|
|
|
/* core includes */
|
2017-10-06 12:02:36 +02:00
|
|
|
#include <cpu.h>
|
2018-11-26 11:18:57 +01:00
|
|
|
#include <kernel/cpu_context.h>
|
|
|
|
#include <kernel/inter_processor_work.h>
|
2013-09-09 15:20:30 +02:00
|
|
|
#include <kernel/signal_receiver.h>
|
|
|
|
#include <kernel/ipc_node.h>
|
2015-05-19 14:18:40 +02:00
|
|
|
#include <kernel/object.h>
|
2013-05-14 22:40:30 +02:00
|
|
|
|
2012-11-30 14:08:42 +01:00
|
|
|
namespace Kernel
|
|
|
|
{
|
2017-10-25 18:57:58 +02:00
|
|
|
struct Thread_fault;
|
2013-09-09 15:20:30 +02:00
|
|
|
class Thread;
|
2015-05-19 14:18:40 +02:00
|
|
|
class Core_thread;
|
2013-09-09 15:20:30 +02:00
|
|
|
}
|
|
|
|
|
2017-10-25 18:57:58 +02:00
|
|
|
|
|
|
|
struct Kernel::Thread_fault
|
|
|
|
{
|
|
|
|
enum Type { WRITE, EXEC, PAGE_MISSING, UNKNOWN };
|
|
|
|
|
|
|
|
addr_t ip = 0;
|
|
|
|
addr_t addr = 0;
|
|
|
|
Type type = UNKNOWN;
|
|
|
|
|
|
|
|
void print(Genode::Output &out) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-08-24 15:35:54 +02:00
|
|
|
/**
|
|
|
|
* Kernel back-end for userland execution-contexts
|
|
|
|
*/
|
2013-09-09 15:20:30 +02:00
|
|
|
class Kernel::Thread
|
2015-08-24 15:35:54 +02:00
|
|
|
:
|
2018-11-26 11:18:57 +01:00
|
|
|
public Kernel::Object, public Cpu_job,
|
2016-05-18 12:20:04 +02:00
|
|
|
public Ipc_node, public Signal_context_killer, public Signal_handler,
|
|
|
|
private Timeout
|
2013-09-09 15:20:30 +02:00
|
|
|
{
|
Follow practices suggested by "Effective C++"
The patch adjust the code of the base, base-<kernel>, and os repository.
To adapt existing components to fix violations of the best practices
suggested by "Effective C++" as reported by the -Weffc++ compiler
argument. The changes follow the patterns outlined below:
* A class with virtual functions can no longer publicly inherit base
classed without a vtable. The inherited object may either be moved
to a member variable, or inherited privately. The latter would be
used for classes that inherit 'List::Element' or 'Avl_node'. In order
to enable the 'List' and 'Avl_tree' to access the meta data, the
'List' must become a friend.
* Instead of adding a virtual destructor to abstract base classes,
we inherit the new 'Interface' class, which contains a virtual
destructor. This way, single-line abstract base classes can stay
as compact as they are now. The 'Interface' utility resides in
base/include/util/interface.h.
* With the new warnings enabled, all member variables must be explicitly
initialized. Basic types may be initialized with '='. All other types
are initialized with braces '{ ... }' or as class initializers. If
basic types and non-basic types appear in a row, it is nice to only
use the brace syntax (also for basic types) and align the braces.
* If a class contains pointers as members, it must now also provide a
copy constructor and assignment operator. In the most cases, one
would make them private, effectively disallowing the objects to be
copied. Unfortunately, this warning cannot be fixed be inheriting
our existing 'Noncopyable' class (the compiler fails to detect that
the inheriting class cannot be copied and still gives the error).
For now, we have to manually add declarations for both the copy
constructor and assignment operator as private class members. Those
declarations should be prepended with a comment like this:
/*
* Noncopyable
*/
Thread(Thread const &);
Thread &operator = (Thread const &);
In the future, we should revisit these places and try to replace
the pointers with references. In the presence of at least one
reference member, the compiler would no longer implicitly generate
a copy constructor. So we could remove the manual declaration.
Issue #465
2017-12-21 15:42:15 +01:00
|
|
|
private:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Noncopyable
|
|
|
|
*/
|
|
|
|
Thread(Thread const &);
|
|
|
|
Thread &operator = (Thread const &);
|
|
|
|
|
2018-11-26 11:18:57 +01:00
|
|
|
/**
|
|
|
|
* An update of page-table entries that requires architecture-wise
|
|
|
|
* maintainance operations, e.g., a TLB invalidation needs
|
|
|
|
* cross-cpu synchronization
|
|
|
|
*/
|
|
|
|
struct Pd_update : Inter_processor_work
|
|
|
|
{
|
|
|
|
Thread & caller; /* the caller gets blocked until all finished */
|
|
|
|
Pd & pd; /* the corresponding pd */
|
|
|
|
unsigned cnt; /* count of cpus left */
|
|
|
|
|
|
|
|
Pd_update(Thread & caller, Pd & pd, unsigned cnt);
|
|
|
|
|
|
|
|
/************************************
|
|
|
|
** Inter_processor_work interface **
|
|
|
|
************************************/
|
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
void execute() override;
|
2018-11-26 11:18:57 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The destruction of a thread still active on another cpu
|
|
|
|
* needs cross-cpu synchronization
|
|
|
|
*/
|
|
|
|
struct Destroy : Inter_processor_work
|
|
|
|
{
|
|
|
|
Thread & caller; /* the caller gets blocked till the end */
|
|
|
|
Thread & thread_to_destroy; /* thread to be destroyed */
|
|
|
|
|
|
|
|
Destroy(Thread & caller, Thread & to_destroy);
|
|
|
|
|
|
|
|
/************************************
|
|
|
|
** Inter_processor_work interface **
|
|
|
|
************************************/
|
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
void execute() override;
|
2018-11-26 11:18:57 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
friend void Pd_update::execute();
|
|
|
|
friend void Destroy::execute();
|
|
|
|
|
2017-10-06 12:02:36 +02:00
|
|
|
protected:
|
2013-09-09 15:20:30 +02:00
|
|
|
|
hw: clean up scheduling-readiness syscalls
This cleans up the syscalls that are mainly used to control the
scheduling readiness of a thread. The different use cases and
requirements were somehow mixed together in the previous interface. The
new syscall set is:
1) pause_thread and resume_thread
They don't affect the state of the thread (IPC, signalling, etc.) but
merely decide wether the thread is allowed for scheduling or not, the
so-called pause state. The pause state is orthogonal to the thread state
and masks it when it comes to scheduling. In contrast to the stopped
state, which is described in "stop_thread and restart_thread", the
thread state and the UTCB content of a thread may change while in the
paused state. However, the register state of a thread doesn't change
while paused. The "pause" and "resume" syscalls are both core-restricted
and may target any thread. They are used as back end for the CPU session
calls "pause" and "resume". The "pause/resume" feature is made for
applications like the GDB monitor that transparently want to stop and
continue the execution of a thread no matter what state the thread is
in.
2) stop_thread and restart_thread
The stop syscall can only be used on a thread in the non-blocking
("active") thread state. The thread then switches to the "stopped"
thread state in wich it explicitely waits for a restart. The restart
syscall can only be used on a thread in the "stopped" or the "active"
thread state. The thread then switches back to the "active" thread state
and the syscall returns whether the thread was stopped. Both syscalls
are not core-restricted. "Stop" always targets the calling thread while
"restart" may target any thread in the same PD as the caller. Thread
state and UTCB content of a thread don't change while in the stopped
state. The "stop/restart" feature is used when an active thread wants to
wait for an event that is not known to the kernel. Actually the syscalls
are used when waiting for locks and on thread exit.
3) cancel_thread_blocking
Does cleanly cancel a cancelable blocking thread state (IPC, signalling,
stopped). The thread whose blocking was cancelled goes back to the
"active" thread state. It may receive a syscall return value that
reflects the cancellation. This syscall doesn't affect the pause state
of the thread which means that it may still not get scheduled. The
syscall is core-restricted and may target any thread.
4) yield_thread
Does its best that a thread is scheduled as few as possible in the
current scheduling super-period without touching the thread or pause
state. In the next superperiod, however, the thread is scheduled
"normal" again. The syscall is not core-restricted and always targets
the caller.
Fixes #2104
2016-09-15 17:23:06 +02:00
|
|
|
enum { START_VERBOSE = 0 };
|
|
|
|
|
2013-05-22 14:41:47 +02:00
|
|
|
enum State
|
|
|
|
{
|
2014-11-18 15:38:15 +01:00
|
|
|
ACTIVE = 1,
|
2013-10-16 13:10:54 +02:00
|
|
|
AWAITS_START = 2,
|
|
|
|
AWAITS_IPC = 3,
|
hw: clean up scheduling-readiness syscalls
This cleans up the syscalls that are mainly used to control the
scheduling readiness of a thread. The different use cases and
requirements were somehow mixed together in the previous interface. The
new syscall set is:
1) pause_thread and resume_thread
They don't affect the state of the thread (IPC, signalling, etc.) but
merely decide wether the thread is allowed for scheduling or not, the
so-called pause state. The pause state is orthogonal to the thread state
and masks it when it comes to scheduling. In contrast to the stopped
state, which is described in "stop_thread and restart_thread", the
thread state and the UTCB content of a thread may change while in the
paused state. However, the register state of a thread doesn't change
while paused. The "pause" and "resume" syscalls are both core-restricted
and may target any thread. They are used as back end for the CPU session
calls "pause" and "resume". The "pause/resume" feature is made for
applications like the GDB monitor that transparently want to stop and
continue the execution of a thread no matter what state the thread is
in.
2) stop_thread and restart_thread
The stop syscall can only be used on a thread in the non-blocking
("active") thread state. The thread then switches to the "stopped"
thread state in wich it explicitely waits for a restart. The restart
syscall can only be used on a thread in the "stopped" or the "active"
thread state. The thread then switches back to the "active" thread state
and the syscall returns whether the thread was stopped. Both syscalls
are not core-restricted. "Stop" always targets the calling thread while
"restart" may target any thread in the same PD as the caller. Thread
state and UTCB content of a thread don't change while in the stopped
state. The "stop/restart" feature is used when an active thread wants to
wait for an event that is not known to the kernel. Actually the syscalls
are used when waiting for locks and on thread exit.
3) cancel_thread_blocking
Does cleanly cancel a cancelable blocking thread state (IPC, signalling,
stopped). The thread whose blocking was cancelled goes back to the
"active" thread state. It may receive a syscall return value that
reflects the cancellation. This syscall doesn't affect the pause state
of the thread which means that it may still not get scheduled. The
syscall is core-restricted and may target any thread.
4) yield_thread
Does its best that a thread is scheduled as few as possible in the
current scheduling super-period without touching the thread or pause
state. In the next superperiod, however, the thread is scheduled
"normal" again. The syscall is not core-restricted and always targets
the caller.
Fixes #2104
2016-09-15 17:23:06 +02:00
|
|
|
AWAITS_RESTART = 4,
|
2013-11-14 13:29:47 +01:00
|
|
|
AWAITS_SIGNAL = 5,
|
|
|
|
AWAITS_SIGNAL_CONTEXT_KILL = 6,
|
hw: clean up scheduling-readiness syscalls
This cleans up the syscalls that are mainly used to control the
scheduling readiness of a thread. The different use cases and
requirements were somehow mixed together in the previous interface. The
new syscall set is:
1) pause_thread and resume_thread
They don't affect the state of the thread (IPC, signalling, etc.) but
merely decide wether the thread is allowed for scheduling or not, the
so-called pause state. The pause state is orthogonal to the thread state
and masks it when it comes to scheduling. In contrast to the stopped
state, which is described in "stop_thread and restart_thread", the
thread state and the UTCB content of a thread may change while in the
paused state. However, the register state of a thread doesn't change
while paused. The "pause" and "resume" syscalls are both core-restricted
and may target any thread. They are used as back end for the CPU session
calls "pause" and "resume". The "pause/resume" feature is made for
applications like the GDB monitor that transparently want to stop and
continue the execution of a thread no matter what state the thread is
in.
2) stop_thread and restart_thread
The stop syscall can only be used on a thread in the non-blocking
("active") thread state. The thread then switches to the "stopped"
thread state in wich it explicitely waits for a restart. The restart
syscall can only be used on a thread in the "stopped" or the "active"
thread state. The thread then switches back to the "active" thread state
and the syscall returns whether the thread was stopped. Both syscalls
are not core-restricted. "Stop" always targets the calling thread while
"restart" may target any thread in the same PD as the caller. Thread
state and UTCB content of a thread don't change while in the stopped
state. The "stop/restart" feature is used when an active thread wants to
wait for an event that is not known to the kernel. Actually the syscalls
are used when waiting for locks and on thread exit.
3) cancel_thread_blocking
Does cleanly cancel a cancelable blocking thread state (IPC, signalling,
stopped). The thread whose blocking was cancelled goes back to the
"active" thread state. It may receive a syscall return value that
reflects the cancellation. This syscall doesn't affect the pause state
of the thread which means that it may still not get scheduled. The
syscall is core-restricted and may target any thread.
4) yield_thread
Does its best that a thread is scheduled as few as possible in the
current scheduling super-period without touching the thread or pause
state. In the next superperiod, however, the thread is scheduled
"normal" again. The syscall is not core-restricted and always targets
the caller.
Fixes #2104
2016-09-15 17:23:06 +02:00
|
|
|
DEAD = 7,
|
2013-05-22 14:41:47 +02:00
|
|
|
};
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2017-03-01 15:28:13 +01:00
|
|
|
Signal_context * _pager = nullptr;
|
Follow practices suggested by "Effective C++"
The patch adjust the code of the base, base-<kernel>, and os repository.
To adapt existing components to fix violations of the best practices
suggested by "Effective C++" as reported by the -Weffc++ compiler
argument. The changes follow the patterns outlined below:
* A class with virtual functions can no longer publicly inherit base
classed without a vtable. The inherited object may either be moved
to a member variable, or inherited privately. The latter would be
used for classes that inherit 'List::Element' or 'Avl_node'. In order
to enable the 'List' and 'Avl_tree' to access the meta data, the
'List' must become a friend.
* Instead of adding a virtual destructor to abstract base classes,
we inherit the new 'Interface' class, which contains a virtual
destructor. This way, single-line abstract base classes can stay
as compact as they are now. The 'Interface' utility resides in
base/include/util/interface.h.
* With the new warnings enabled, all member variables must be explicitly
initialized. Basic types may be initialized with '='. All other types
are initialized with braces '{ ... }' or as class initializers. If
basic types and non-basic types appear in a row, it is nice to only
use the brace syntax (also for basic types) and align the braces.
* If a class contains pointers as members, it must now also provide a
copy constructor and assignment operator. In the most cases, one
would make them private, effectively disallowing the objects to be
copied. Unfortunately, this warning cannot be fixed be inheriting
our existing 'Noncopyable' class (the compiler fails to detect that
the inheriting class cannot be copied and still gives the error).
For now, we have to manually add declarations for both the copy
constructor and assignment operator as private class members. Those
declarations should be prepended with a comment like this:
/*
* Noncopyable
*/
Thread(Thread const &);
Thread &operator = (Thread const &);
In the future, we should revisit these places and try to replace
the pointers with references. In the presence of at least one
reference member, the compiler would no longer implicitly generate
a copy constructor. So we could remove the manual declaration.
Issue #465
2017-12-21 15:42:15 +01:00
|
|
|
Thread_fault _fault { };
|
2015-08-24 15:35:54 +02:00
|
|
|
State _state;
|
|
|
|
Signal_receiver * _signal_receiver;
|
|
|
|
char const * const _label;
|
2016-05-18 12:20:04 +02:00
|
|
|
capid_t _timeout_sigid = 0;
|
hw: clean up scheduling-readiness syscalls
This cleans up the syscalls that are mainly used to control the
scheduling readiness of a thread. The different use cases and
requirements were somehow mixed together in the previous interface. The
new syscall set is:
1) pause_thread and resume_thread
They don't affect the state of the thread (IPC, signalling, etc.) but
merely decide wether the thread is allowed for scheduling or not, the
so-called pause state. The pause state is orthogonal to the thread state
and masks it when it comes to scheduling. In contrast to the stopped
state, which is described in "stop_thread and restart_thread", the
thread state and the UTCB content of a thread may change while in the
paused state. However, the register state of a thread doesn't change
while paused. The "pause" and "resume" syscalls are both core-restricted
and may target any thread. They are used as back end for the CPU session
calls "pause" and "resume". The "pause/resume" feature is made for
applications like the GDB monitor that transparently want to stop and
continue the execution of a thread no matter what state the thread is
in.
2) stop_thread and restart_thread
The stop syscall can only be used on a thread in the non-blocking
("active") thread state. The thread then switches to the "stopped"
thread state in wich it explicitely waits for a restart. The restart
syscall can only be used on a thread in the "stopped" or the "active"
thread state. The thread then switches back to the "active" thread state
and the syscall returns whether the thread was stopped. Both syscalls
are not core-restricted. "Stop" always targets the calling thread while
"restart" may target any thread in the same PD as the caller. Thread
state and UTCB content of a thread don't change while in the stopped
state. The "stop/restart" feature is used when an active thread wants to
wait for an event that is not known to the kernel. Actually the syscalls
are used when waiting for locks and on thread exit.
3) cancel_thread_blocking
Does cleanly cancel a cancelable blocking thread state (IPC, signalling,
stopped). The thread whose blocking was cancelled goes back to the
"active" thread state. It may receive a syscall return value that
reflects the cancellation. This syscall doesn't affect the pause state
of the thread which means that it may still not get scheduled. The
syscall is core-restricted and may target any thread.
4) yield_thread
Does its best that a thread is scheduled as few as possible in the
current scheduling super-period without touching the thread or pause
state. In the next superperiod, however, the thread is scheduled
"normal" again. The syscall is not core-restricted and always targets
the caller.
Fixes #2104
2016-09-15 17:23:06 +02:00
|
|
|
bool _paused = false;
|
2017-02-24 14:29:29 +01:00
|
|
|
bool _cancel_next_await_signal = false;
|
2017-08-30 11:59:35 +02:00
|
|
|
bool const _core = false;
|
2015-08-24 15:35:54 +02:00
|
|
|
|
2018-11-26 11:18:57 +01:00
|
|
|
Genode::Constructible<Pd_update> _pd_update {};
|
|
|
|
Genode::Constructible<Destroy> _destroy {};
|
|
|
|
|
2012-11-30 14:08:42 +01:00
|
|
|
/**
|
2013-10-16 20:53:59 +02:00
|
|
|
* Notice that another thread yielded the CPU to this thread
|
2012-11-30 14:08:42 +01:00
|
|
|
*/
|
2013-10-16 20:53:59 +02:00
|
|
|
void _receive_yielded_cpu();
|
2013-09-12 00:48:27 +02:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/**
|
2013-11-14 13:29:47 +01:00
|
|
|
* Attach or detach the handler of a thread-triggered event
|
|
|
|
*
|
|
|
|
* \param event_id kernel name of the thread event
|
|
|
|
* \param signal_context_id kernel name signal context or 0 to detach
|
|
|
|
*
|
|
|
|
* \retval 0 succeeded
|
|
|
|
* \retval -1 failed
|
|
|
|
*/
|
2015-05-19 14:18:40 +02:00
|
|
|
int _route_event(unsigned const event_id,
|
|
|
|
Signal_context * const signal_context_id);
|
2013-11-14 13:29:47 +01:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/**
|
2014-11-18 15:38:15 +01:00
|
|
|
* Switch from an inactive state to the active state
|
2013-10-16 20:53:59 +02:00
|
|
|
*/
|
2014-11-18 15:38:15 +01:00
|
|
|
void _become_active();
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2013-12-17 18:10:02 +01:00
|
|
|
/**
|
2014-11-18 15:38:15 +01:00
|
|
|
* Switch from the active state to the inactive state 's'
|
2013-12-17 18:10:02 +01:00
|
|
|
*/
|
2014-11-18 15:38:15 +01:00
|
|
|
void _become_inactive(State const s);
|
2013-12-17 18:10:02 +01:00
|
|
|
|
2014-12-01 15:10:33 +01:00
|
|
|
/**
|
|
|
|
* Activate our CPU-share and those of our helpers
|
|
|
|
*/
|
|
|
|
void _activate_used_shares();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deactivate our CPU-share and those of our helpers
|
|
|
|
*/
|
|
|
|
void _deactivate_used_shares();
|
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/**
|
|
|
|
* Suspend unrecoverably from execution
|
|
|
|
*/
|
hw: clean up scheduling-readiness syscalls
This cleans up the syscalls that are mainly used to control the
scheduling readiness of a thread. The different use cases and
requirements were somehow mixed together in the previous interface. The
new syscall set is:
1) pause_thread and resume_thread
They don't affect the state of the thread (IPC, signalling, etc.) but
merely decide wether the thread is allowed for scheduling or not, the
so-called pause state. The pause state is orthogonal to the thread state
and masks it when it comes to scheduling. In contrast to the stopped
state, which is described in "stop_thread and restart_thread", the
thread state and the UTCB content of a thread may change while in the
paused state. However, the register state of a thread doesn't change
while paused. The "pause" and "resume" syscalls are both core-restricted
and may target any thread. They are used as back end for the CPU session
calls "pause" and "resume". The "pause/resume" feature is made for
applications like the GDB monitor that transparently want to stop and
continue the execution of a thread no matter what state the thread is
in.
2) stop_thread and restart_thread
The stop syscall can only be used on a thread in the non-blocking
("active") thread state. The thread then switches to the "stopped"
thread state in wich it explicitely waits for a restart. The restart
syscall can only be used on a thread in the "stopped" or the "active"
thread state. The thread then switches back to the "active" thread state
and the syscall returns whether the thread was stopped. Both syscalls
are not core-restricted. "Stop" always targets the calling thread while
"restart" may target any thread in the same PD as the caller. Thread
state and UTCB content of a thread don't change while in the stopped
state. The "stop/restart" feature is used when an active thread wants to
wait for an event that is not known to the kernel. Actually the syscalls
are used when waiting for locks and on thread exit.
3) cancel_thread_blocking
Does cleanly cancel a cancelable blocking thread state (IPC, signalling,
stopped). The thread whose blocking was cancelled goes back to the
"active" thread state. It may receive a syscall return value that
reflects the cancellation. This syscall doesn't affect the pause state
of the thread which means that it may still not get scheduled. The
syscall is core-restricted and may target any thread.
4) yield_thread
Does its best that a thread is scheduled as few as possible in the
current scheduling super-period without touching the thread or pause
state. In the next superperiod, however, the thread is scheduled
"normal" again. The syscall is not core-restricted and always targets
the caller.
Fixes #2104
2016-09-15 17:23:06 +02:00
|
|
|
void _die();
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/**
|
|
|
|
* Handle an exception thrown by the memory management unit
|
|
|
|
*/
|
|
|
|
void _mmu_exception();
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2013-10-16 13:10:54 +02:00
|
|
|
/**
|
2013-12-17 18:10:02 +01:00
|
|
|
* Handle kernel-call request of the thread
|
2013-10-16 13:10:54 +02:00
|
|
|
*/
|
2014-03-26 11:00:01 +01:00
|
|
|
void _call();
|
2013-10-16 13:10:54 +02:00
|
|
|
|
2015-03-27 14:05:55 +01:00
|
|
|
/**
|
2017-03-23 03:06:53 +01:00
|
|
|
* Return amount of timer ticks that 'quota' is worth
|
2015-03-27 14:05:55 +01:00
|
|
|
*/
|
|
|
|
size_t _core_to_kernel_quota(size_t const quota) const;
|
|
|
|
|
hw: clean up scheduling-readiness syscalls
This cleans up the syscalls that are mainly used to control the
scheduling readiness of a thread. The different use cases and
requirements were somehow mixed together in the previous interface. The
new syscall set is:
1) pause_thread and resume_thread
They don't affect the state of the thread (IPC, signalling, etc.) but
merely decide wether the thread is allowed for scheduling or not, the
so-called pause state. The pause state is orthogonal to the thread state
and masks it when it comes to scheduling. In contrast to the stopped
state, which is described in "stop_thread and restart_thread", the
thread state and the UTCB content of a thread may change while in the
paused state. However, the register state of a thread doesn't change
while paused. The "pause" and "resume" syscalls are both core-restricted
and may target any thread. They are used as back end for the CPU session
calls "pause" and "resume". The "pause/resume" feature is made for
applications like the GDB monitor that transparently want to stop and
continue the execution of a thread no matter what state the thread is
in.
2) stop_thread and restart_thread
The stop syscall can only be used on a thread in the non-blocking
("active") thread state. The thread then switches to the "stopped"
thread state in wich it explicitely waits for a restart. The restart
syscall can only be used on a thread in the "stopped" or the "active"
thread state. The thread then switches back to the "active" thread state
and the syscall returns whether the thread was stopped. Both syscalls
are not core-restricted. "Stop" always targets the calling thread while
"restart" may target any thread in the same PD as the caller. Thread
state and UTCB content of a thread don't change while in the stopped
state. The "stop/restart" feature is used when an active thread wants to
wait for an event that is not known to the kernel. Actually the syscalls
are used when waiting for locks and on thread exit.
3) cancel_thread_blocking
Does cleanly cancel a cancelable blocking thread state (IPC, signalling,
stopped). The thread whose blocking was cancelled goes back to the
"active" thread state. It may receive a syscall return value that
reflects the cancellation. This syscall doesn't affect the pause state
of the thread which means that it may still not get scheduled. The
syscall is core-restricted and may target any thread.
4) yield_thread
Does its best that a thread is scheduled as few as possible in the
current scheduling super-period without touching the thread or pause
state. In the next superperiod, however, the thread is scheduled
"normal" again. The syscall is not core-restricted and always targets
the caller.
Fixes #2104
2016-09-15 17:23:06 +02:00
|
|
|
void _cancel_blocking();
|
|
|
|
|
|
|
|
bool _restart();
|
|
|
|
|
2013-10-16 13:10:54 +02:00
|
|
|
|
2014-03-15 01:26:53 +01:00
|
|
|
/*********************************************************
|
|
|
|
** Kernel-call back-ends, see kernel-interface headers **
|
|
|
|
*********************************************************/
|
2013-10-16 13:10:54 +02:00
|
|
|
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_new_thread();
|
2017-08-30 11:59:35 +02:00
|
|
|
void _call_new_core_thread();
|
2015-03-20 09:22:02 +01:00
|
|
|
void _call_thread_quota();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_start_thread();
|
hw: clean up scheduling-readiness syscalls
This cleans up the syscalls that are mainly used to control the
scheduling readiness of a thread. The different use cases and
requirements were somehow mixed together in the previous interface. The
new syscall set is:
1) pause_thread and resume_thread
They don't affect the state of the thread (IPC, signalling, etc.) but
merely decide wether the thread is allowed for scheduling or not, the
so-called pause state. The pause state is orthogonal to the thread state
and masks it when it comes to scheduling. In contrast to the stopped
state, which is described in "stop_thread and restart_thread", the
thread state and the UTCB content of a thread may change while in the
paused state. However, the register state of a thread doesn't change
while paused. The "pause" and "resume" syscalls are both core-restricted
and may target any thread. They are used as back end for the CPU session
calls "pause" and "resume". The "pause/resume" feature is made for
applications like the GDB monitor that transparently want to stop and
continue the execution of a thread no matter what state the thread is
in.
2) stop_thread and restart_thread
The stop syscall can only be used on a thread in the non-blocking
("active") thread state. The thread then switches to the "stopped"
thread state in wich it explicitely waits for a restart. The restart
syscall can only be used on a thread in the "stopped" or the "active"
thread state. The thread then switches back to the "active" thread state
and the syscall returns whether the thread was stopped. Both syscalls
are not core-restricted. "Stop" always targets the calling thread while
"restart" may target any thread in the same PD as the caller. Thread
state and UTCB content of a thread don't change while in the stopped
state. The "stop/restart" feature is used when an active thread wants to
wait for an event that is not known to the kernel. Actually the syscalls
are used when waiting for locks and on thread exit.
3) cancel_thread_blocking
Does cleanly cancel a cancelable blocking thread state (IPC, signalling,
stopped). The thread whose blocking was cancelled goes back to the
"active" thread state. It may receive a syscall return value that
reflects the cancellation. This syscall doesn't affect the pause state
of the thread which means that it may still not get scheduled. The
syscall is core-restricted and may target any thread.
4) yield_thread
Does its best that a thread is scheduled as few as possible in the
current scheduling super-period without touching the thread or pause
state. In the next superperiod, however, the thread is scheduled
"normal" again. The syscall is not core-restricted and always targets
the caller.
Fixes #2104
2016-09-15 17:23:06 +02:00
|
|
|
void _call_stop_thread();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_pause_thread();
|
|
|
|
void _call_resume_thread();
|
hw: clean up scheduling-readiness syscalls
This cleans up the syscalls that are mainly used to control the
scheduling readiness of a thread. The different use cases and
requirements were somehow mixed together in the previous interface. The
new syscall set is:
1) pause_thread and resume_thread
They don't affect the state of the thread (IPC, signalling, etc.) but
merely decide wether the thread is allowed for scheduling or not, the
so-called pause state. The pause state is orthogonal to the thread state
and masks it when it comes to scheduling. In contrast to the stopped
state, which is described in "stop_thread and restart_thread", the
thread state and the UTCB content of a thread may change while in the
paused state. However, the register state of a thread doesn't change
while paused. The "pause" and "resume" syscalls are both core-restricted
and may target any thread. They are used as back end for the CPU session
calls "pause" and "resume". The "pause/resume" feature is made for
applications like the GDB monitor that transparently want to stop and
continue the execution of a thread no matter what state the thread is
in.
2) stop_thread and restart_thread
The stop syscall can only be used on a thread in the non-blocking
("active") thread state. The thread then switches to the "stopped"
thread state in wich it explicitely waits for a restart. The restart
syscall can only be used on a thread in the "stopped" or the "active"
thread state. The thread then switches back to the "active" thread state
and the syscall returns whether the thread was stopped. Both syscalls
are not core-restricted. "Stop" always targets the calling thread while
"restart" may target any thread in the same PD as the caller. Thread
state and UTCB content of a thread don't change while in the stopped
state. The "stop/restart" feature is used when an active thread wants to
wait for an event that is not known to the kernel. Actually the syscalls
are used when waiting for locks and on thread exit.
3) cancel_thread_blocking
Does cleanly cancel a cancelable blocking thread state (IPC, signalling,
stopped). The thread whose blocking was cancelled goes back to the
"active" thread state. It may receive a syscall return value that
reflects the cancellation. This syscall doesn't affect the pause state
of the thread which means that it may still not get scheduled. The
syscall is core-restricted and may target any thread.
4) yield_thread
Does its best that a thread is scheduled as few as possible in the
current scheduling super-period without touching the thread or pause
state. In the next superperiod, however, the thread is scheduled
"normal" again. The syscall is not core-restricted and always targets
the caller.
Fixes #2104
2016-09-15 17:23:06 +02:00
|
|
|
void _call_cancel_thread_blocking();
|
|
|
|
void _call_restart_thread();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_yield_thread();
|
2018-11-26 11:18:57 +01:00
|
|
|
void _call_delete_thread();
|
2013-11-21 11:35:33 +01:00
|
|
|
void _call_await_request_msg();
|
|
|
|
void _call_send_request_msg();
|
|
|
|
void _call_send_reply_msg();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_update_pd();
|
2014-04-07 15:45:44 +02:00
|
|
|
void _call_update_data_region();
|
2014-04-07 16:18:43 +02:00
|
|
|
void _call_update_instr_region();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_print_char();
|
|
|
|
void _call_await_signal();
|
2017-02-24 14:29:29 +01:00
|
|
|
void _call_cancel_next_await_signal();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_submit_signal();
|
|
|
|
void _call_ack_signal();
|
2013-12-06 00:12:43 +01:00
|
|
|
void _call_kill_signal_context();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_new_vm();
|
2015-03-19 14:53:48 +01:00
|
|
|
void _call_delete_vm();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_run_vm();
|
|
|
|
void _call_pause_vm();
|
2017-03-01 15:28:13 +01:00
|
|
|
void _call_pager();
|
2015-04-03 17:22:16 +02:00
|
|
|
void _call_new_irq();
|
2015-04-28 12:56:59 +02:00
|
|
|
void _call_ack_irq();
|
2015-05-19 14:18:40 +02:00
|
|
|
void _call_new_obj();
|
|
|
|
void _call_delete_obj();
|
2015-12-01 14:50:14 +01:00
|
|
|
void _call_ack_cap();
|
2015-05-19 14:18:40 +02:00
|
|
|
void _call_delete_cap();
|
2016-05-18 12:20:04 +02:00
|
|
|
void _call_timeout();
|
|
|
|
void _call_timeout_age_us();
|
|
|
|
void _call_timeout_max_us();
|
2015-05-19 14:18:40 +02:00
|
|
|
|
|
|
|
template <typename T, typename... ARGS>
|
|
|
|
void _call_new(ARGS &&... args)
|
|
|
|
{
|
|
|
|
using Object = Core_object<T>;
|
|
|
|
void * dst = (void *)user_arg_1();
|
|
|
|
Object * o = Genode::construct_at<Object>(dst, args...);
|
|
|
|
user_arg_0(o->core_capid());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void _call_delete()
|
|
|
|
{
|
|
|
|
using Object = Core_object<T>;
|
|
|
|
reinterpret_cast<Object*>(user_arg_1())->~Object();
|
|
|
|
}
|
2013-10-16 13:10:54 +02:00
|
|
|
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/***************************
|
|
|
|
** Signal_context_killer **
|
|
|
|
***************************/
|
2013-09-09 15:20:30 +02:00
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
void _signal_context_kill_pending() override;
|
|
|
|
void _signal_context_kill_failed() override;
|
|
|
|
void _signal_context_kill_done() override;
|
2013-10-07 15:37:58 +02:00
|
|
|
|
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/********************
|
|
|
|
** Signal_handler **
|
|
|
|
********************/
|
2013-09-09 15:20:30 +02:00
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
void _await_signal(Signal_receiver * const receiver) override;
|
|
|
|
void _receive_signal(void * const base, size_t const size) override;
|
2013-09-09 15:20:30 +02:00
|
|
|
|
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/**************
|
|
|
|
** Ipc_node **
|
|
|
|
**************/
|
2013-09-06 01:36:03 +02:00
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
void _send_request_succeeded() override;
|
|
|
|
void _send_request_failed() override;
|
|
|
|
void _await_request_succeeded() override;
|
|
|
|
void _await_request_failed() override;
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
public:
|
2013-09-09 15:20:30 +02:00
|
|
|
|
2017-10-06 12:02:36 +02:00
|
|
|
Genode::Align_at<Genode::Cpu::Context> regs;
|
|
|
|
|
2013-09-09 15:20:30 +02:00
|
|
|
/**
|
2013-10-16 20:53:59 +02:00
|
|
|
* Constructor
|
|
|
|
*
|
2013-11-18 15:31:54 +01:00
|
|
|
* \param priority scheduling priority
|
2014-10-16 11:15:46 +02:00
|
|
|
* \param quota CPU-time quota
|
2013-11-18 15:31:54 +01:00
|
|
|
* \param label debugging label
|
2017-08-30 11:59:35 +02:00
|
|
|
* \param core whether it is a core thread or not
|
2013-09-09 15:20:30 +02:00
|
|
|
*/
|
2014-10-16 11:15:46 +02:00
|
|
|
Thread(unsigned const priority, unsigned const quota,
|
2017-08-30 11:59:35 +02:00
|
|
|
char const * const label, bool core = false);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor for core/kernel thread
|
|
|
|
*
|
|
|
|
* \param label debugging label
|
|
|
|
*/
|
|
|
|
Thread(char const * const label)
|
2017-10-05 16:11:24 +02:00
|
|
|
: Thread(Cpu_priority::MIN, 0, label, true) { }
|
2013-09-09 15:20:30 +02:00
|
|
|
|
2017-10-06 12:02:36 +02:00
|
|
|
|
|
|
|
/**************************
|
|
|
|
** Support for syscalls **
|
|
|
|
**************************/
|
|
|
|
|
|
|
|
void user_arg_0(Kernel::Call_arg const arg);
|
|
|
|
void user_arg_1(Kernel::Call_arg const arg);
|
|
|
|
void user_arg_2(Kernel::Call_arg const arg);
|
|
|
|
void user_arg_3(Kernel::Call_arg const arg);
|
|
|
|
void user_arg_4(Kernel::Call_arg const arg);
|
|
|
|
|
|
|
|
Kernel::Call_arg user_arg_0() const;
|
|
|
|
Kernel::Call_arg user_arg_1() const;
|
|
|
|
Kernel::Call_arg user_arg_2() const;
|
|
|
|
Kernel::Call_arg user_arg_3() const;
|
|
|
|
Kernel::Call_arg user_arg_4() const;
|
|
|
|
|
2013-09-19 16:47:38 +02:00
|
|
|
/**
|
2015-05-19 14:18:40 +02:00
|
|
|
* Syscall to create a thread
|
|
|
|
*
|
|
|
|
* \param p memory donation for the new kernel thread object
|
|
|
|
* \param priority scheduling priority of the new thread
|
|
|
|
* \param quota CPU quota of the new thread
|
|
|
|
* \param label debugging label of the new thread
|
|
|
|
*
|
|
|
|
* \retval capability id of the new kernel object
|
|
|
|
*/
|
|
|
|
static capid_t syscall_create(void * const p, unsigned const priority,
|
|
|
|
size_t const quota,
|
|
|
|
char const * const label)
|
|
|
|
{
|
|
|
|
return call(call_id_new_thread(), (Call_arg)p, (Call_arg)priority,
|
|
|
|
(Call_arg)quota, (Call_arg)label);
|
2017-08-30 11:59:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Syscall to create a core thread
|
|
|
|
*
|
|
|
|
* \param p memory donation for the new kernel thread object
|
|
|
|
* \param label debugging label of the new thread
|
|
|
|
*
|
|
|
|
* \retval capability id of the new kernel object
|
|
|
|
*/
|
|
|
|
static capid_t syscall_create(void * const p, char const * const label)
|
|
|
|
{
|
|
|
|
return call(call_id_new_core_thread(), (Call_arg)p,
|
|
|
|
(Call_arg)label);
|
2015-05-19 14:18:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Syscall to destroy a thread
|
2013-10-16 20:53:59 +02:00
|
|
|
*
|
2015-05-19 14:18:40 +02:00
|
|
|
* \param thread pointer to thread kernel object
|
2013-09-19 16:47:38 +02:00
|
|
|
*/
|
2015-05-19 14:18:40 +02:00
|
|
|
static void syscall_destroy(Thread * thread) {
|
|
|
|
call(call_id_delete_thread(), (Call_arg)thread); }
|
2013-09-19 16:47:38 +02:00
|
|
|
|
2016-10-10 16:22:43 +02:00
|
|
|
void print(Genode::Output &out) const;
|
|
|
|
|
2013-09-09 15:20:30 +02:00
|
|
|
|
2014-10-09 14:24:27 +02:00
|
|
|
/*************
|
|
|
|
** Cpu_job **
|
|
|
|
*************/
|
2013-09-09 15:20:30 +02:00
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
void exception(Cpu & cpu) override;
|
|
|
|
void proceed(Cpu & cpu) override;
|
|
|
|
Cpu_job * helping_sink() override;
|
2013-09-09 15:20:30 +02:00
|
|
|
|
|
|
|
|
2016-05-18 12:20:04 +02:00
|
|
|
/*************
|
|
|
|
** Timeout **
|
|
|
|
*************/
|
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
void timeout_triggered() override;
|
2016-05-18 12:20:04 +02:00
|
|
|
|
|
|
|
|
2013-09-09 15:20:30 +02:00
|
|
|
/***************
|
|
|
|
** Accessors **
|
|
|
|
***************/
|
|
|
|
|
2017-10-25 18:57:58 +02:00
|
|
|
char const * label() const { return _label; }
|
|
|
|
Thread_fault fault() const { return _fault; }
|
2015-05-19 14:18:40 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The first core thread in the system bootstrapped by the Kernel
|
|
|
|
*/
|
2017-10-06 12:02:36 +02:00
|
|
|
struct Kernel::Core_thread : Core_object<Kernel::Thread>
|
2015-05-19 14:18:40 +02:00
|
|
|
{
|
2017-10-06 12:02:36 +02:00
|
|
|
Core_thread();
|
2015-05-19 14:18:40 +02:00
|
|
|
|
2017-10-06 12:02:36 +02:00
|
|
|
static Thread & singleton();
|
2013-09-09 15:20:30 +02:00
|
|
|
};
|
|
|
|
|
2017-04-12 10:06:29 +02:00
|
|
|
#endif /* _CORE__KERNEL__THREAD_H_ */
|