2013-10-07 15:37:58 +02:00
|
|
|
/*
|
2015-08-24 15:35:54 +02:00
|
|
|
* \brief Kernel back-end for execution contexts in userland
|
2013-10-07 15:37:58 +02:00
|
|
|
* \author Martin Stein
|
hw: restrict processor broadcast to TLB flushing
Removes the generic processor broadcast function call. By now, that call
was used for cross processor TLB maintance operations only. When core/kernel
gets its memory mapped on demand, and unmapped again, the previous cross
processor flush routine doesn't work anymore, because of a hen-egg problem.
The previous cross processor broadcast is realized using a thread constructed
by core running on top of each processor core. When constructing threads in
core, a dataspace for its thread context is constructed. Each constructed
RAM dataspace gets attached, zeroed out, and detached again. The detach
routine requires a TLB flush operation executed on each processor core.
Instead of executing a thread on each processor core, now a thread waiting
for a global TLB flush is removed from the scheduler queue, and gets attached
to a TLB flush queue of each processor. The processor local queue gets checked
whenever the kernel is entered. The last processor, which executed the TLB
flush, re-attaches the blocked thread to its scheduler queue again.
To ease uo the above described mechanism, a platform thread is now directly
associated with a platform pd object, instead of just associate it with the
kernel pd's id.
Ref #723
2014-04-28 20:36:00 +02:00
|
|
|
* \author Stefan Kalkowski
|
2013-10-07 15:37:58 +02:00
|
|
|
* \date 2013-09-15
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2013-2017 Genode Labs GmbH
|
2013-10-07 15:37:58 +02: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.
|
2013-10-07 15:37:58 +02:00
|
|
|
*/
|
|
|
|
|
2013-10-16 13:10:54 +02:00
|
|
|
/* Genode includes */
|
|
|
|
#include <base/thread_state.h>
|
2015-03-27 14:05:55 +01:00
|
|
|
#include <cpu_session/cpu_session.h>
|
2015-05-19 14:18:40 +02:00
|
|
|
#include <util/construct_at.h>
|
2013-11-14 12:07:07 +01:00
|
|
|
|
2016-01-20 18:27:18 +01:00
|
|
|
/* base-internal includes */
|
|
|
|
#include <base/internal/unmanaged_singleton.h>
|
2016-03-08 16:59:43 +01:00
|
|
|
#include <base/internal/native_utcb.h>
|
2016-11-07 18:00:24 +01:00
|
|
|
#include <base/internal/crt0.h>
|
2016-01-20 18:27:18 +01:00
|
|
|
|
2013-10-07 15:37:58 +02:00
|
|
|
/* core includes */
|
2017-02-21 13:46:59 +01:00
|
|
|
#include <hw/assert.h>
|
2017-10-05 16:11:24 +02:00
|
|
|
#include <kernel/cpu.h>
|
2013-10-16 13:10:54 +02:00
|
|
|
#include <kernel/kernel.h>
|
2013-10-07 15:37:58 +02:00
|
|
|
#include <kernel/thread.h>
|
2013-12-17 18:10:02 +01:00
|
|
|
#include <kernel/irq.h>
|
2016-10-10 16:22:43 +02:00
|
|
|
#include <kernel/log.h>
|
2015-05-19 14:18:40 +02:00
|
|
|
#include <map_local.h>
|
2013-10-07 15:37:58 +02:00
|
|
|
#include <platform_pd.h>
|
2013-12-17 18:10:02 +01:00
|
|
|
#include <pic.h>
|
2013-10-07 15:37:58 +02:00
|
|
|
|
2015-05-19 14:18:40 +02:00
|
|
|
extern "C" void _core_start(void);
|
|
|
|
|
2013-10-07 15:37:58 +02:00
|
|
|
using namespace Kernel;
|
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
|
2018-11-26 11:18:57 +01:00
|
|
|
Thread::Pd_update::Pd_update(Thread & caller, Pd & pd, unsigned cnt)
|
|
|
|
: caller(caller), pd(pd), cnt(cnt)
|
|
|
|
{
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
cpu_pool().work_list().insert(&_le);
|
2018-11-26 11:18:57 +01:00
|
|
|
caller._become_inactive(AWAITS_RESTART);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Thread::Destroy::Destroy(Thread & caller, Thread & to_delete)
|
|
|
|
: caller(caller), thread_to_destroy(to_delete)
|
|
|
|
{
|
|
|
|
thread_to_destroy._cpu->work_list().insert(&_le);
|
|
|
|
caller._become_inactive(AWAITS_RESTART);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Thread::Destroy::execute()
|
|
|
|
{
|
|
|
|
thread_to_destroy.~Thread();
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
cpu_pool().executing_cpu().work_list().remove(&_le);
|
2018-11-26 11:18:57 +01:00
|
|
|
caller._restart();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-25 18:57:58 +02:00
|
|
|
void Thread_fault::print(Genode::Output &out) const
|
|
|
|
{
|
|
|
|
Genode::print(out, "ip=", Genode::Hex(ip));
|
|
|
|
Genode::print(out, " fault-addr=", Genode::Hex(addr));
|
|
|
|
Genode::print(out, " type=");
|
|
|
|
switch (type) {
|
|
|
|
case WRITE: Genode::print(out, "write-fault"); return;
|
|
|
|
case EXEC: Genode::print(out, "exec-fault"); return;
|
|
|
|
case PAGE_MISSING: Genode::print(out, "no-page"); return;
|
|
|
|
case UNKNOWN: Genode::print(out, "unknown"); return;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
void Thread::_signal_context_kill_pending()
|
|
|
|
{
|
2014-11-18 15:38:15 +01:00
|
|
|
assert(_state == ACTIVE);
|
|
|
|
_become_inactive(AWAITS_SIGNAL_CONTEXT_KILL);
|
2013-10-16 20:53:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Thread::_signal_context_kill_done()
|
|
|
|
{
|
|
|
|
assert(_state == AWAITS_SIGNAL_CONTEXT_KILL);
|
|
|
|
user_arg_0(0);
|
2014-11-18 15:38:15 +01:00
|
|
|
_become_active();
|
2013-10-16 20:53:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-06 00:12:43 +01:00
|
|
|
void Thread::_signal_context_kill_failed()
|
|
|
|
{
|
|
|
|
assert(_state == AWAITS_SIGNAL_CONTEXT_KILL);
|
|
|
|
user_arg_0(-1);
|
2014-11-18 15:38:15 +01:00
|
|
|
_become_active();
|
2013-12-06 00:12:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
void Thread::_await_signal(Signal_receiver * const receiver)
|
|
|
|
{
|
2014-11-18 15:38:15 +01:00
|
|
|
_become_inactive(AWAITS_SIGNAL);
|
2013-10-16 20:53:59 +02:00
|
|
|
_signal_receiver = receiver;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Thread::_receive_signal(void * const base, size_t const size)
|
|
|
|
{
|
2015-05-19 14:18:40 +02:00
|
|
|
assert(_state == AWAITS_SIGNAL);
|
2016-03-18 22:53:25 +01:00
|
|
|
Genode::memcpy(utcb()->data(), base, size);
|
2014-11-18 15:38:15 +01:00
|
|
|
_become_active();
|
2013-10-16 20:53:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-04 13:41:04 +02:00
|
|
|
void Thread::_send_request_succeeded()
|
2013-10-16 20:53:59 +02:00
|
|
|
{
|
2014-04-04 13:41:04 +02:00
|
|
|
assert(_state == AWAITS_IPC);
|
|
|
|
user_arg_0(0);
|
2014-12-01 15:10:33 +01:00
|
|
|
_state = ACTIVE;
|
|
|
|
if (!Cpu_job::own_share_active()) { _activate_used_shares(); }
|
2013-10-16 20:53:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-04 13:41:04 +02:00
|
|
|
void Thread::_send_request_failed()
|
2013-10-16 20:53:59 +02:00
|
|
|
{
|
2014-04-04 13:41:04 +02:00
|
|
|
assert(_state == AWAITS_IPC);
|
|
|
|
user_arg_0(-1);
|
2014-12-01 15:10:33 +01:00
|
|
|
_state = ACTIVE;
|
|
|
|
if (!Cpu_job::own_share_active()) { _activate_used_shares(); }
|
2014-04-04 13:41:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Thread::_await_request_succeeded()
|
|
|
|
{
|
|
|
|
assert(_state == AWAITS_IPC);
|
|
|
|
user_arg_0(0);
|
2014-11-18 15:38:15 +01:00
|
|
|
_become_active();
|
2014-04-04 13:41:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Thread::_await_request_failed()
|
|
|
|
{
|
|
|
|
assert(_state == AWAITS_IPC);
|
|
|
|
user_arg_0(-1);
|
2014-11-18 15:38:15 +01:00
|
|
|
_become_active();
|
2013-10-16 20:53:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-01 15:10:33 +01:00
|
|
|
void Thread::_deactivate_used_shares()
|
|
|
|
{
|
|
|
|
Cpu_job::_deactivate_own_share();
|
|
|
|
Ipc_node::for_each_helper([&] (Ipc_node * const h) {
|
|
|
|
static_cast<Thread *>(h)->_deactivate_used_shares(); });
|
|
|
|
}
|
|
|
|
|
|
|
|
void Thread::_activate_used_shares()
|
|
|
|
{
|
|
|
|
Cpu_job::_activate_own_share();
|
|
|
|
Ipc_node::for_each_helper([&] (Ipc_node * const h) {
|
|
|
|
static_cast<Thread *>(h)->_activate_used_shares(); });
|
|
|
|
}
|
2013-10-16 20:53:59 +02:00
|
|
|
|
2014-11-18 15:38:15 +01:00
|
|
|
void Thread::_become_active()
|
2013-10-16 20:53:59 +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
|
|
|
if (_state != ACTIVE && !_paused) { _activate_used_shares(); }
|
2014-11-18 15:38:15 +01:00
|
|
|
_state = ACTIVE;
|
2013-10-16 20:53:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-11-18 15:38:15 +01:00
|
|
|
void Thread::_become_inactive(State const s)
|
2013-12-17 18:10:02 +01: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
|
|
|
if (_state == ACTIVE && !_paused) { _deactivate_used_shares(); }
|
2013-12-17 18:10:02 +01:00
|
|
|
_state = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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 Thread::_die() { _become_inactive(DEAD); }
|
2013-10-16 20:53:59 +02:00
|
|
|
|
|
|
|
|
2014-12-01 15:10:33 +01:00
|
|
|
Cpu_job * Thread::helping_sink() {
|
|
|
|
return static_cast<Thread *>(Ipc_node::helping_sink()); }
|
|
|
|
|
|
|
|
|
2015-03-27 14:05:55 +01:00
|
|
|
size_t Thread::_core_to_kernel_quota(size_t const quota) const
|
|
|
|
{
|
|
|
|
using Genode::Cpu_session;
|
|
|
|
using Genode::sizet_arithm_t;
|
2017-03-23 03:06:53 +01:00
|
|
|
size_t const ticks = _cpu->us_to_ticks(Kernel::cpu_quota_us);
|
|
|
|
return Cpu_session::quota_lim_downscale<sizet_arithm_t>(quota, ticks);
|
2015-03-27 14:05:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-14 15:14:41 +01:00
|
|
|
void Thread::_call_new_thread()
|
2013-10-16 13:10:54 +02:00
|
|
|
{
|
2015-05-19 14:18:40 +02:00
|
|
|
void * const p = (void *)user_arg_1();
|
|
|
|
unsigned const priority = user_arg_2();
|
|
|
|
unsigned const quota = _core_to_kernel_quota(user_arg_3());
|
|
|
|
char const * const label = (char *)user_arg_4();
|
|
|
|
Core_object<Thread> * co =
|
|
|
|
Genode::construct_at<Core_object<Thread> >(p, priority, quota, label);
|
|
|
|
user_arg_0(co->core_capid());
|
2013-10-16 13:10:54 +02:00
|
|
|
}
|
|
|
|
|
2013-11-14 17:29:34 +01:00
|
|
|
|
2017-08-30 11:59:35 +02:00
|
|
|
void Thread::_call_new_core_thread()
|
|
|
|
{
|
|
|
|
void * const p = (void *)user_arg_1();
|
|
|
|
char const * const label = (char *)user_arg_2();
|
|
|
|
Core_object<Thread> * co =
|
|
|
|
Genode::construct_at<Core_object<Thread> >(p, label);
|
|
|
|
user_arg_0(co->core_capid());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-20 09:22:02 +01:00
|
|
|
void Thread::_call_thread_quota()
|
|
|
|
{
|
|
|
|
Thread * const thread = (Thread *)user_arg_1();
|
2015-03-27 14:05:55 +01:00
|
|
|
thread->Cpu_job::quota(_core_to_kernel_quota(user_arg_2()));
|
2015-03-20 09:22:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-14 15:14:41 +01:00
|
|
|
void Thread::_call_start_thread()
|
2013-10-16 13:10:54 +02:00
|
|
|
{
|
2014-10-10 16:13:52 +02:00
|
|
|
/* lookup CPU */
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Cpu & cpu = cpu_pool().cpu(user_arg_2());
|
2015-05-19 14:18:40 +02:00
|
|
|
user_arg_0(0);
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Thread &thread = *(Thread *)user_arg_1();
|
2015-04-01 10:23:38 +02:00
|
|
|
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
assert(thread._state == AWAITS_START);
|
2015-05-19 14:18:40 +02:00
|
|
|
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
thread.affinity(cpu);
|
2015-05-19 14:18:40 +02:00
|
|
|
|
|
|
|
/* join protection domain */
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
thread._pd = (Pd *) user_arg_3();
|
|
|
|
thread.Ipc_node::_init(*(Native_utcb *)user_arg_4(), *this);
|
|
|
|
thread._become_active();
|
2013-10-16 13:10:54 +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
|
|
|
void Thread::_call_pause_thread()
|
|
|
|
{
|
|
|
|
Thread &thread = *reinterpret_cast<Thread*>(user_arg_1());
|
|
|
|
if (thread._state == ACTIVE && !thread._paused) {
|
|
|
|
thread._deactivate_used_shares(); }
|
2014-03-16 16:00:55 +01: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
|
|
|
thread._paused = true;
|
|
|
|
}
|
2014-03-16 16:00:55 +01:00
|
|
|
|
2013-10-16 13:10:54 +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
|
|
|
void Thread::_call_resume_thread()
|
|
|
|
{
|
|
|
|
Thread &thread = *reinterpret_cast<Thread*>(user_arg_1());
|
|
|
|
if (thread._state == ACTIVE && thread._paused) {
|
|
|
|
thread._activate_used_shares(); }
|
2013-10-16 13:10:54 +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
|
|
|
thread._paused = false;
|
|
|
|
}
|
2014-03-25 16:34:20 +01: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
|
|
|
void Thread::_call_stop_thread()
|
2014-03-25 16:34:20 +01: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
|
|
|
assert(_state == ACTIVE);
|
|
|
|
_become_inactive(AWAITS_RESTART);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Thread::_call_restart_thread()
|
|
|
|
{
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Thread *thread_ptr = pd().cap_tree().find<Thread>(user_arg_1());
|
2015-05-19 14:18:40 +02:00
|
|
|
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
if (!thread_ptr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Thread &thread = *thread_ptr;
|
|
|
|
|
|
|
|
if (!_core && (&pd() != &thread.pd())) {
|
2016-10-10 16:22:43 +02:00
|
|
|
warning(*this, ": failed to lookup thread ", (unsigned)user_arg_1(),
|
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
|
|
|
" to restart it");
|
|
|
|
_die();
|
|
|
|
return;
|
|
|
|
}
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
user_arg_0(thread._restart());
|
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 Thread::_restart()
|
|
|
|
{
|
|
|
|
assert(_state == ACTIVE || _state == AWAITS_RESTART);
|
|
|
|
if (_state != AWAITS_RESTART) { return false; }
|
|
|
|
_become_active();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Thread::_call_cancel_thread_blocking()
|
|
|
|
{
|
|
|
|
reinterpret_cast<Thread*>(user_arg_1())->_cancel_blocking();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Thread::_cancel_blocking()
|
|
|
|
{
|
|
|
|
switch (_state) {
|
|
|
|
case AWAITS_RESTART:
|
|
|
|
_become_active();
|
|
|
|
return;
|
|
|
|
case AWAITS_IPC:
|
|
|
|
Ipc_node::cancel_waiting();
|
|
|
|
return;
|
|
|
|
case AWAITS_SIGNAL:
|
|
|
|
Signal_handler::cancel_waiting();
|
|
|
|
user_arg_0(-1);
|
|
|
|
_become_active();
|
|
|
|
return;
|
|
|
|
case AWAITS_SIGNAL_CONTEXT_KILL:
|
|
|
|
Signal_context_killer::cancel_waiting();
|
|
|
|
return;
|
|
|
|
case ACTIVE:
|
|
|
|
return;
|
|
|
|
case DEAD:
|
|
|
|
Genode::error("can't cancel blocking of dead thread");
|
|
|
|
return;
|
|
|
|
case AWAITS_START:
|
|
|
|
Genode::error("can't cancel blocking of not yet started thread");
|
2013-10-16 13:10:54 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-14 15:14:41 +01:00
|
|
|
void Thread::_call_yield_thread()
|
2013-10-16 13:10:54 +02:00
|
|
|
{
|
2014-10-09 14:24:27 +02:00
|
|
|
Cpu_job::_yield();
|
2013-10-16 13:10:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-26 11:18:57 +01:00
|
|
|
void Thread::_call_delete_thread()
|
|
|
|
{
|
|
|
|
Thread * to_delete = reinterpret_cast<Thread*>(user_arg_1());
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete a thread immediately if it has no cpu assigned yet,
|
|
|
|
* or it is assigned to this cpu, or the assigned cpu did not scheduled it.
|
|
|
|
*/
|
|
|
|
if (!to_delete->_cpu ||
|
|
|
|
(to_delete->_cpu->id() == Cpu::executing_id() ||
|
|
|
|
&to_delete->_cpu->scheduled_job() != to_delete)) {
|
|
|
|
_call_delete<Thread>();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct a cross-cpu work item and send an IPI
|
|
|
|
*/
|
|
|
|
_destroy.construct(*this, *to_delete);
|
|
|
|
to_delete->_cpu->trigger_ip_interrupt();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-21 11:35:33 +01:00
|
|
|
void Thread::_call_await_request_msg()
|
2013-10-16 13:10:54 +02:00
|
|
|
{
|
2015-05-19 14:18:40 +02:00
|
|
|
if (Ipc_node::await_request(user_arg_1())) {
|
2014-03-27 12:28:53 +01:00
|
|
|
user_arg_0(0);
|
|
|
|
return;
|
|
|
|
}
|
2014-11-18 15:38:15 +01:00
|
|
|
_become_inactive(AWAITS_IPC);
|
2013-10-16 13:10:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-18 12:20:04 +02:00
|
|
|
void Thread::_call_timeout()
|
|
|
|
{
|
|
|
|
_timeout_sigid = user_arg_2();
|
|
|
|
Cpu_job::timeout(this, user_arg_1());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Thread::_call_timeout_age_us()
|
|
|
|
{
|
|
|
|
user_arg_0(Cpu_job::timeout_age_us(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Thread::_call_timeout_max_us()
|
|
|
|
{
|
|
|
|
user_arg_0(Cpu_job::timeout_max_us());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Thread::timeout_triggered()
|
|
|
|
{
|
|
|
|
Signal_context * const c =
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
pd().cap_tree().find<Signal_context>(_timeout_sigid);
|
2016-10-10 16:22:43 +02:00
|
|
|
if (!c || c->submit(1))
|
|
|
|
Genode::warning(*this, ": failed to submit timeout signal");
|
2016-05-18 12:20:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-21 11:35:33 +01:00
|
|
|
void Thread::_call_send_request_msg()
|
2013-10-16 13:10:54 +02:00
|
|
|
{
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Object_identity_reference * oir = pd().cap_tree().find(user_arg_1());
|
2015-05-19 14:18:40 +02:00
|
|
|
Thread * const dst = (oir) ? oir->object<Thread>() : nullptr;
|
2013-10-17 00:41:14 +02:00
|
|
|
if (!dst) {
|
2016-10-10 16:22:43 +02:00
|
|
|
Genode::warning(*this, ": cannot send to unknown recipient ",
|
|
|
|
(unsigned)user_arg_1());
|
2014-11-18 15:38:15 +01:00
|
|
|
_become_inactive(AWAITS_IPC);
|
2013-10-17 00:41:14 +02:00
|
|
|
return;
|
|
|
|
}
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
bool const help = Cpu_job::_helping_possible(*dst);
|
2015-05-19 14:18:40 +02:00
|
|
|
oir = oir->find(dst->pd());
|
|
|
|
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Ipc_node::send_request(*dst, oir ? oir->capid() : cap_id_invalid(),
|
2015-05-19 14:18:40 +02:00
|
|
|
help, user_arg_2());
|
2014-12-01 15:10:33 +01:00
|
|
|
_state = AWAITS_IPC;
|
|
|
|
if (!help || !dst->own_share_active()) { _deactivate_used_shares(); }
|
2013-10-16 13:10:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-21 11:35:33 +01:00
|
|
|
void Thread::_call_send_reply_msg()
|
2013-10-16 20:53:59 +02:00
|
|
|
{
|
2015-05-19 14:18:40 +02:00
|
|
|
Ipc_node::send_reply();
|
|
|
|
bool const await_request_msg = user_arg_2();
|
2013-11-21 11:35:33 +01:00
|
|
|
if (await_request_msg) { _call_await_request_msg(); }
|
2013-11-21 12:04:21 +01:00
|
|
|
else { user_arg_0(0); }
|
2013-11-14 15:14:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-01 15:28:13 +01:00
|
|
|
void Thread::_call_pager()
|
2013-11-14 15:14:41 +01:00
|
|
|
{
|
|
|
|
/* override event route */
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Thread &thread = *(Thread *)user_arg_1();
|
|
|
|
thread._pager = pd().cap_tree().find<Signal_context>(user_arg_2());
|
2013-11-14 15:14:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-10 16:22:43 +02:00
|
|
|
void Thread::_call_print_char() { Kernel::log((char)user_arg_1()); }
|
2013-10-16 13:10:54 +02:00
|
|
|
|
|
|
|
|
2013-11-14 15:14:41 +01:00
|
|
|
void Thread::_call_await_signal()
|
2013-10-16 13:10:54 +02:00
|
|
|
{
|
2017-02-24 14:29:29 +01:00
|
|
|
/* cancel if another thread set our "cancel next await signal" bit */
|
|
|
|
if (_cancel_next_await_signal) {
|
|
|
|
user_arg_0(-1);
|
|
|
|
_cancel_next_await_signal = false;
|
|
|
|
return;
|
|
|
|
}
|
2013-10-16 13:10:54 +02:00
|
|
|
/* lookup receiver */
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Signal_receiver * const r = pd().cap_tree().find<Signal_receiver>(user_arg_1());
|
2013-10-16 13:10:54 +02:00
|
|
|
if (!r) {
|
2016-10-10 16:22:43 +02:00
|
|
|
Genode::warning(*this, ": cannot await, unknown signal receiver ",
|
|
|
|
(unsigned)user_arg_1());
|
2013-10-16 13:10:54 +02:00
|
|
|
user_arg_0(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* register handler at the receiver */
|
|
|
|
if (r->add_handler(this)) {
|
2016-10-10 16:22:43 +02:00
|
|
|
Genode::warning("failed to register handler at signal receiver");
|
2013-10-16 13:10:54 +02:00
|
|
|
user_arg_0(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
user_arg_0(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-24 14:29:29 +01:00
|
|
|
void Thread::_call_cancel_next_await_signal()
|
|
|
|
{
|
|
|
|
/* kill the caller if the capability of the target thread is invalid */
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Thread * const thread = pd().cap_tree().find<Thread>(user_arg_1());
|
|
|
|
if (!thread || (&pd() != &thread->pd())) {
|
2017-02-24 14:29:29 +01:00
|
|
|
error(*this, ": failed to lookup thread ", (unsigned)user_arg_1());
|
|
|
|
_die();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* resume the target thread directly if it blocks for signals */
|
|
|
|
if (thread->_state == AWAITS_SIGNAL) {
|
|
|
|
thread->_cancel_blocking();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* if not, keep in mind to cancel its next signal blocking */
|
|
|
|
thread->_cancel_next_await_signal = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-14 15:14:41 +01:00
|
|
|
void Thread::_call_submit_signal()
|
2013-10-16 13:10:54 +02:00
|
|
|
{
|
|
|
|
/* lookup signal context */
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Signal_context * const c = pd().cap_tree().find<Signal_context>(user_arg_1());
|
2013-10-16 13:10:54 +02:00
|
|
|
if(!c) {
|
2016-10-10 16:22:43 +02:00
|
|
|
Genode::warning(*this, ": cannot submit unknown signal context");
|
2013-10-16 13:10:54 +02:00
|
|
|
user_arg_0(-1);
|
|
|
|
return;
|
|
|
|
}
|
2015-05-19 14:18:40 +02:00
|
|
|
|
2013-10-16 13:10:54 +02:00
|
|
|
/* trigger signal context */
|
|
|
|
if (c->submit(user_arg_2())) {
|
2016-10-10 16:22:43 +02:00
|
|
|
Genode::warning("failed to submit signal context");
|
2013-10-16 13:10:54 +02:00
|
|
|
user_arg_0(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
user_arg_0(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-14 15:14:41 +01:00
|
|
|
void Thread::_call_ack_signal()
|
2013-10-16 13:10:54 +02:00
|
|
|
{
|
|
|
|
/* lookup signal context */
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Signal_context * const c = pd().cap_tree().find<Signal_context>(user_arg_1());
|
2013-10-16 13:10:54 +02:00
|
|
|
if (!c) {
|
2016-10-10 16:22:43 +02:00
|
|
|
Genode::warning(*this, ": cannot ack unknown signal context");
|
2013-10-16 13:10:54 +02:00
|
|
|
return;
|
|
|
|
}
|
2015-05-19 14:18:40 +02:00
|
|
|
|
2013-10-16 13:10:54 +02:00
|
|
|
/* acknowledge */
|
|
|
|
c->ack();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-06 00:12:43 +01:00
|
|
|
void Thread::_call_kill_signal_context()
|
|
|
|
{
|
|
|
|
/* lookup signal context */
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Signal_context * const c = pd().cap_tree().find<Signal_context>(user_arg_1());
|
2013-12-06 00:12:43 +01:00
|
|
|
if (!c) {
|
2016-10-10 16:22:43 +02:00
|
|
|
Genode::warning(*this, ": cannot kill unknown signal context");
|
2013-12-06 00:12:43 +01:00
|
|
|
user_arg_0(-1);
|
|
|
|
return;
|
|
|
|
}
|
2015-05-19 14:18:40 +02:00
|
|
|
|
2013-12-06 00:12:43 +01:00
|
|
|
/* kill signal context */
|
|
|
|
if (c->kill(this)) {
|
2016-10-10 16:22:43 +02:00
|
|
|
Genode::warning("failed to kill signal context");
|
2013-12-06 00:12:43 +01:00
|
|
|
user_arg_0(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-17 15:41:47 +01:00
|
|
|
void Thread::_call_new_irq()
|
|
|
|
{
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Signal_context * const c = pd().cap_tree().find<Signal_context>(user_arg_3());
|
2015-03-17 15:41:47 +01:00
|
|
|
if (!c) {
|
2016-10-10 16:22:43 +02:00
|
|
|
Genode::warning(*this, ": invalid signal context for interrupt");
|
2015-03-17 15:41:47 +01:00
|
|
|
user_arg_0(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
new ((void *)user_arg_1()) User_irq(user_arg_2(), *c);
|
|
|
|
user_arg_0(0);
|
|
|
|
}
|
2015-04-03 17:22:16 +02:00
|
|
|
|
|
|
|
|
2015-04-28 12:56:59 +02:00
|
|
|
void Thread::_call_ack_irq() {
|
|
|
|
reinterpret_cast<User_irq*>(user_arg_1())->enable(); }
|
|
|
|
|
|
|
|
|
2015-05-19 14:18:40 +02:00
|
|
|
void Thread::_call_new_obj()
|
|
|
|
{
|
|
|
|
/* lookup thread */
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Object_identity_reference * ref = pd().cap_tree().find(user_arg_2());
|
2015-05-19 14:18:40 +02:00
|
|
|
Thread * thread = ref ? ref->object<Thread>() : nullptr;
|
|
|
|
if (!thread ||
|
|
|
|
(static_cast<Core_object<Thread>*>(thread)->capid() != ref->capid())) {
|
|
|
|
if (thread)
|
2016-10-10 16:22:43 +02:00
|
|
|
Genode::warning("faked thread", thread);
|
2015-05-19 14:18:40 +02:00
|
|
|
user_arg_0(cap_id_invalid());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
using Thread_identity = Core_object_identity<Thread>;
|
|
|
|
Thread_identity * coi =
|
|
|
|
Genode::construct_at<Thread_identity>((void *)user_arg_1(), *thread);
|
|
|
|
user_arg_0(coi->core_capid());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Thread::_call_delete_obj()
|
|
|
|
{
|
|
|
|
using Object = Core_object_identity<Thread>;
|
|
|
|
reinterpret_cast<Object*>(user_arg_1())->~Object();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-01 14:50:14 +01:00
|
|
|
void Thread::_call_ack_cap()
|
|
|
|
{
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Object_identity_reference * oir = pd().cap_tree().find(user_arg_1());
|
2015-12-01 14:50:14 +01:00
|
|
|
if (oir) oir->remove_from_utcb();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-19 14:18:40 +02:00
|
|
|
void Thread::_call_delete_cap()
|
|
|
|
{
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Object_identity_reference * oir = pd().cap_tree().find(user_arg_1());
|
2015-12-01 14:50:14 +01:00
|
|
|
if (!oir) return;
|
|
|
|
|
|
|
|
if (oir->in_utcb()) return;
|
|
|
|
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
destroy(pd().platform_pd().capability_slab(), oir);
|
2015-05-19 14:18:40 +02:00
|
|
|
}
|
2015-04-03 17:22:16 +02:00
|
|
|
|
|
|
|
|
2018-11-26 11:18:57 +01:00
|
|
|
void Kernel::Thread::_call_update_pd()
|
|
|
|
{
|
|
|
|
Pd * const pd = (Pd *) user_arg_1();
|
|
|
|
unsigned cnt = 0;
|
|
|
|
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
cpu_pool().for_each_cpu([&] (Cpu & cpu) {
|
2018-11-26 11:18:57 +01:00
|
|
|
/* if a cpu needs to update increase the counter */
|
|
|
|
if (pd->update(cpu)) cnt++; });
|
|
|
|
|
|
|
|
/* insert the work item in the list if there are outstanding cpus */
|
|
|
|
if (cnt) _pd_update.construct(*this, *pd, cnt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-26 11:00:01 +01:00
|
|
|
void Thread::_call()
|
2013-10-16 13:10:54 +02:00
|
|
|
{
|
2015-05-19 14:18:40 +02:00
|
|
|
try {
|
|
|
|
|
2014-03-25 17:23:33 +01:00
|
|
|
/* switch over unrestricted kernel calls */
|
|
|
|
unsigned const call_id = user_arg_0();
|
|
|
|
switch (call_id) {
|
2017-02-24 14:29:29 +01:00
|
|
|
case call_id_update_data_region(): _call_update_data_region(); return;
|
|
|
|
case call_id_update_instr_region(): _call_update_instr_region(); return;
|
|
|
|
case call_id_stop_thread(): _call_stop_thread(); return;
|
|
|
|
case call_id_restart_thread(): _call_restart_thread(); return;
|
|
|
|
case call_id_yield_thread(): _call_yield_thread(); return;
|
|
|
|
case call_id_send_request_msg(): _call_send_request_msg(); return;
|
|
|
|
case call_id_send_reply_msg(): _call_send_reply_msg(); return;
|
|
|
|
case call_id_await_request_msg(): _call_await_request_msg(); return;
|
|
|
|
case call_id_kill_signal_context(): _call_kill_signal_context(); return;
|
|
|
|
case call_id_submit_signal(): _call_submit_signal(); return;
|
|
|
|
case call_id_await_signal(): _call_await_signal(); return;
|
|
|
|
case call_id_cancel_next_await_signal(): _call_cancel_next_await_signal(); return;
|
|
|
|
case call_id_ack_signal(): _call_ack_signal(); return;
|
|
|
|
case call_id_print_char(): _call_print_char(); return;
|
|
|
|
case call_id_ack_cap(): _call_ack_cap(); return;
|
|
|
|
case call_id_delete_cap(): _call_delete_cap(); return;
|
|
|
|
case call_id_timeout(): _call_timeout(); return;
|
|
|
|
case call_id_timeout_age_us(): _call_timeout_age_us(); return;
|
|
|
|
case call_id_timeout_max_us(): _call_timeout_max_us(); return;
|
os/timer: interpolate time via timestamps
Previously, the Genode::Timer::curr_time always used the
Timer_session::elapsed_ms RPC as back end. Now, Genode::Timer reads
this remote time only in a periodic fashion independently from the calls
to Genode::Timer::curr_time. If now one calls Genode::Timer::curr_time,
the function takes the last read remote time value and adapts it using
the timestamp difference since the remote-time read. The conversion
factor from timestamps to time is estimated on every remote-time read
using the last read remote-time value and the timestamp difference since
the last remote time read.
This commit also re-works the timeout test. The test now has two stages.
In the first stage, it tests fast polling of the
Genode::Timer::curr_time. This stage checks the error between locally
interpolated and timer-driver time as well as wether the locally
interpolated time is monotone and sufficiently homogeneous. In the
second stage several periodic and one-shot timeouts are scheduled at
once. This stage checks if the timeouts trigger sufficiently precise.
This commit adds the new Kernel::time syscall to base-hw. The syscall is
solely used by the Genode::Timer on base-hw as substitute for the
timestamp. This is because on ARM, the timestamp function uses the ARM
performance counter that stops counting when the WFI (wait for
interrupt) instruction is active. This instruction, however is used by
the base-hw idle contexts that get active when no user thread needs to
be scheduled. Thus, the ARM performance counter is not a good choice for
time interpolation and we use the kernel internal time instead.
With this commit, the timeout library becomes a basic library. That means
that it is linked against the LDSO which then provides it to the program it
serves. Furthermore, you can't use the timeout library anymore without the
LDSO because through the kernel-dependent LDSO make-files we can achieve a
kernel-dependent timeout implementation.
This commit introduces a structured Duration type that shall successively
replace the use of Microseconds, Milliseconds, and integer types for duration
values.
Open issues:
* The timeout test fails on Raspberry PI because of precision errors in the
first stage. However, this does not render the framework unusable in general
on the RPI but merely is an issue when speaking of microseconds precision.
* If we run on ARM with another Kernel than HW the timestamp speed may
continuously vary from almost 0 up to CPU speed. The Timer, however,
only uses interpolation if the timestamp speed remained stable (12.5%
tolerance) for at least 3 observation periods. Currently, one period is
100ms, so its 300ms. As long as this is not the case,
Timer_session::elapsed_ms is called instead.
Anyway, it might happen that the CPU load was stable for some time so
interpolation becomes active and now the timestamp speed drops. In the
worst case, we would now have 100ms of slowed down time. The bad thing
about it would be, that this also affects the timeout of the period.
Thus, it might "freeze" the local time for more than 100ms.
On the other hand, if the timestamp speed suddenly raises after some
stable time, interpolated time can get too fast. This would shorten the
period but nonetheless may result in drifting away into the far future.
Now we would have the problem that we can't deliver the real time
anymore until it has caught up because the output of Timer::curr_time
shall be monotone. So, effectively local time might "freeze" again for
more than 100ms.
It would be a solution to not use the Trace::timestamp on ARM w/o HW but
a function whose return value causes the Timer to never use
interpolation because of its stability policy.
Fixes #2400
2017-04-22 00:52:23 +02:00
|
|
|
case call_id_time(): user_arg_0(Cpu_job::time()); return;
|
2014-03-25 17:23:33 +01:00
|
|
|
default:
|
|
|
|
/* check wether this is a core thread */
|
2017-08-30 11:59:35 +02:00
|
|
|
if (!_core) {
|
2016-10-10 16:22:43 +02:00
|
|
|
Genode::warning(*this, ": not entitled to do kernel call");
|
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
|
|
|
_die();
|
2014-03-25 17:23:33 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* switch over kernel calls that are restricted to core */
|
|
|
|
switch (call_id) {
|
2015-03-19 14:53:48 +01:00
|
|
|
case call_id_new_thread(): _call_new_thread(); return;
|
2017-08-30 11:59:35 +02:00
|
|
|
case call_id_new_core_thread(): _call_new_core_thread(); return;
|
2015-03-20 09:22:02 +01:00
|
|
|
case call_id_thread_quota(): _call_thread_quota(); return;
|
2018-11-26 11:18:57 +01:00
|
|
|
case call_id_delete_thread(): _call_delete_thread(); return;
|
2015-03-19 14:53:48 +01:00
|
|
|
case call_id_start_thread(): _call_start_thread(); return;
|
|
|
|
case call_id_resume_thread(): _call_resume_thread(); return;
|
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
|
|
|
case call_id_cancel_thread_blocking(): _call_cancel_thread_blocking(); return;
|
2017-03-01 15:28:13 +01:00
|
|
|
case call_id_thread_pager(): _call_pager(); return;
|
2015-03-19 14:53:48 +01:00
|
|
|
case call_id_update_pd(): _call_update_pd(); return;
|
2015-05-19 14:18:40 +02:00
|
|
|
case call_id_new_pd():
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
_call_new<Pd>(*(Hw::Page_table *) user_arg_2(),
|
|
|
|
*(Genode::Platform_pd *) user_arg_3());
|
2015-05-19 14:18:40 +02:00
|
|
|
return;
|
|
|
|
case call_id_delete_pd(): _call_delete<Pd>(); return;
|
|
|
|
case call_id_new_signal_receiver(): _call_new<Signal_receiver>(); return;
|
|
|
|
case call_id_new_signal_context():
|
2017-08-21 15:34:27 +02:00
|
|
|
_call_new<Signal_context>((Signal_receiver*) user_arg_2(), user_arg_3());
|
2015-05-19 14:18:40 +02:00
|
|
|
return;
|
|
|
|
case call_id_delete_signal_context(): _call_delete<Signal_context>(); return;
|
|
|
|
case call_id_delete_signal_receiver(): _call_delete<Signal_receiver>(); return;
|
2015-03-19 14:53:48 +01:00
|
|
|
case call_id_new_vm(): _call_new_vm(); return;
|
|
|
|
case call_id_delete_vm(): _call_delete_vm(); return;
|
|
|
|
case call_id_run_vm(): _call_run_vm(); return;
|
|
|
|
case call_id_pause_vm(): _call_pause_vm(); return;
|
|
|
|
case call_id_pause_thread(): _call_pause_thread(); return;
|
2015-04-03 17:22:16 +02:00
|
|
|
case call_id_new_irq(): _call_new_irq(); return;
|
2015-05-19 14:18:40 +02:00
|
|
|
case call_id_delete_irq(): _call_delete<Irq>(); return;
|
2015-04-28 12:56:59 +02:00
|
|
|
case call_id_ack_irq(): _call_ack_irq(); return;
|
2015-05-19 14:18:40 +02:00
|
|
|
case call_id_new_obj(): _call_new_obj(); return;
|
|
|
|
case call_id_delete_obj(): _call_delete_obj(); return;
|
2013-10-16 13:10:54 +02:00
|
|
|
default:
|
2016-10-10 16:22:43 +02:00
|
|
|
Genode::warning(*this, ": unknown kernel call");
|
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
|
|
|
_die();
|
2014-03-25 17:23:33 +01:00
|
|
|
return;
|
2013-10-16 13:10:54 +02:00
|
|
|
}
|
2015-05-19 14:18:40 +02:00
|
|
|
} catch (Genode::Allocator::Out_of_memory &e) { user_arg_0(-2); }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-25 18:57:58 +02:00
|
|
|
void Thread::_mmu_exception()
|
|
|
|
{
|
|
|
|
_become_inactive(AWAITS_RESTART);
|
|
|
|
Cpu::mmu_fault(*regs, _fault);
|
|
|
|
_fault.ip = regs->ip;
|
|
|
|
|
|
|
|
if (_fault.type == Thread_fault::UNKNOWN) {
|
|
|
|
Genode::error(*this, " raised unhandled MMU fault ", _fault);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_core)
|
|
|
|
Genode::error(*this, " raised a fault, which should never happen ",
|
|
|
|
_fault);
|
|
|
|
|
|
|
|
if (_pager) _pager->submit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-24 15:35:54 +02:00
|
|
|
Thread::Thread(unsigned const priority, unsigned const quota,
|
2017-08-30 11:59:35 +02:00
|
|
|
char const * const label, bool core)
|
2015-08-24 15:35:54 +02:00
|
|
|
:
|
2017-10-25 18:57:58 +02:00
|
|
|
Cpu_job(priority, quota), _state(AWAITS_START),
|
2017-10-06 12:02:36 +02:00
|
|
|
_signal_receiver(0), _label(label), _core(core), regs(core) { }
|
2015-08-24 15:35:54 +02:00
|
|
|
|
|
|
|
|
2016-10-10 16:22:43 +02:00
|
|
|
void Thread::print(Genode::Output &out) const
|
|
|
|
{
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Genode::print(out, _pd ? _pd->platform_pd().label() : "?");
|
2016-10-10 16:22:43 +02:00
|
|
|
Genode::print(out, " -> ");
|
|
|
|
Genode::print(out, label());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-02 11:56:06 +01:00
|
|
|
Genode::uint8_t __initial_stack_base[DEFAULT_STACK_SIZE];
|
|
|
|
|
|
|
|
|
2015-05-19 14:18:40 +02:00
|
|
|
/*****************
|
|
|
|
** Core_thread **
|
|
|
|
*****************/
|
|
|
|
|
|
|
|
Core_thread::Core_thread()
|
2017-08-30 11:59:35 +02:00
|
|
|
: Core_object<Thread>("core")
|
2015-05-19 14:18:40 +02:00
|
|
|
{
|
2016-11-07 18:00:24 +01:00
|
|
|
using namespace Genode;
|
2015-05-19 14:18:40 +02:00
|
|
|
|
|
|
|
static Native_utcb * const utcb =
|
2016-11-07 18:00:24 +01:00
|
|
|
unmanaged_singleton<Native_utcb, get_page_size()>();
|
|
|
|
static addr_t const utcb_phys = Platform::core_phys_addr((addr_t)utcb);
|
2015-05-19 14:18:40 +02:00
|
|
|
|
|
|
|
/* map UTCB */
|
2016-11-07 18:00:24 +01:00
|
|
|
Genode::map_local(utcb_phys, (addr_t)utcb_main_thread(),
|
|
|
|
sizeof(Native_utcb) / get_page_size());
|
2015-05-19 14:18:40 +02:00
|
|
|
|
2015-06-08 15:24:43 +02:00
|
|
|
utcb->cap_add(core_capid());
|
2015-05-19 14:18:40 +02:00
|
|
|
utcb->cap_add(cap_id_invalid());
|
|
|
|
utcb->cap_add(cap_id_invalid());
|
|
|
|
|
|
|
|
/* start thread with stack pointer at the top of stack */
|
2017-06-30 12:00:27 +02:00
|
|
|
regs->sp = (addr_t)&__initial_stack_base[0] + DEFAULT_STACK_SIZE;
|
|
|
|
regs->ip = (addr_t)&_core_start;
|
2015-05-19 14:18:40 +02:00
|
|
|
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
affinity(cpu_pool().primary_cpu());
|
2015-05-19 14:18:40 +02:00
|
|
|
_utcb = utcb;
|
base/core: use references instead of pointers
This patch replaces the former prominent use of pointers by references
wherever feasible. This has the following benefits:
* The contract between caller and callee becomes more obvious. When
passing a reference, the contract says that the argument cannot be
a null pointer. The caller is responsible to ensure that. Therefore,
the use of reference eliminates the need to add defensive null-pointer
checks at the callee site, which sometimes merely exist to be on the
safe side. The bottom line is that the code becomes easier to follow.
* Reference members must be initialized via an object initializer,
which promotes a programming style that avoids intermediate object-
construction states. Within core, there are still a few pointers
as member variables left though. E.g., caused by the late association
of 'Platform_thread' objects with their 'Platform_pd' objects.
* If no pointers are present as member variables, we don't need to
manually provide declarations of a private copy constructor and
an assignment operator to avoid -Weffc++ errors "class ... has
pointer data members [-Werror=effc++]".
This patch also changes a few system bindings on NOVA and Fiasco.OC,
e.g., the return value of the global 'cap_map' accessor has become a
reference. Hence, the patch touches a few places outside of core.
Fixes #3135
2019-01-24 22:00:01 +01:00
|
|
|
Thread::_pd = &core_pd();
|
2015-05-19 14:18:40 +02:00
|
|
|
_become_active();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Thread & Core_thread::singleton()
|
|
|
|
{
|
|
|
|
static Core_thread ct;
|
|
|
|
return ct;
|
2013-11-11 16:55:30 +01:00
|
|
|
}
|