2012-11-30 14:08:42 +01:00
|
|
|
/*
|
2013-10-07 14:56:31 +02:00
|
|
|
* \brief Kernel backend for execution contexts in userland
|
2012-11-30 14:08:42 +01:00
|
|
|
* \author Martin Stein
|
|
|
|
* \date 2012-11-30
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2013-01-10 21:44:47 +01:00
|
|
|
* Copyright (C) 2012-2013 Genode Labs GmbH
|
2012-11-30 14:08:42 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
#ifndef _KERNEL__THREAD_H_
|
|
|
|
#define _KERNEL__THREAD_H_
|
2012-11-30 14:08:42 +01:00
|
|
|
|
|
|
|
/* core includes */
|
2013-09-09 15:20:30 +02:00
|
|
|
#include <kernel/signal_receiver.h>
|
|
|
|
#include <kernel/ipc_node.h>
|
2014-10-10 16:13:52 +02:00
|
|
|
#include <kernel/cpu.h>
|
2014-07-14 11:44:42 +02:00
|
|
|
#include <kernel/thread_base.h>
|
2013-05-14 22:40:30 +02:00
|
|
|
|
2012-11-30 14:08:42 +01:00
|
|
|
namespace Kernel
|
|
|
|
{
|
2013-09-09 15:20:30 +02:00
|
|
|
class Thread;
|
2013-10-16 20:53:59 +02:00
|
|
|
class Pd;
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2014-02-28 17:39:16 +01:00
|
|
|
typedef Genode::Native_utcb Native_utcb;
|
2013-09-09 15:20:30 +02:00
|
|
|
|
2012-11-30 14:08:42 +01:00
|
|
|
/**
|
2013-09-09 15:20:30 +02:00
|
|
|
* Kernel backend for userland execution-contexts
|
2012-11-30 14:08:42 +01:00
|
|
|
*/
|
2013-09-09 15:20:30 +02:00
|
|
|
class Thread;
|
2013-10-07 14:56:31 +02:00
|
|
|
|
2013-10-11 12:29:40 +02:00
|
|
|
typedef Object_pool<Thread> Thread_pool;
|
2013-10-07 14:56:31 +02:00
|
|
|
|
|
|
|
Thread_pool * thread_pool();
|
2013-09-09 15:20:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
class Kernel::Thread
|
|
|
|
:
|
2014-07-15 14:51:27 +02:00
|
|
|
public Cpu::User_context,
|
2015-03-27 13:55:03 +01:00
|
|
|
public Object<Thread, thread_pool>,
|
2014-12-01 15:10:33 +01:00
|
|
|
public Cpu_domain_update, public Ipc_node, public Signal_context_killer,
|
|
|
|
public Signal_handler, public Thread_base, public Cpu_job
|
2013-09-09 15:20:30 +02:00
|
|
|
{
|
2013-11-14 13:29:47 +01:00
|
|
|
friend class Thread_event;
|
|
|
|
|
2013-09-09 15:20:30 +02:00
|
|
|
private:
|
|
|
|
|
2013-10-07 15:37:58 +02:00
|
|
|
enum { START_VERBOSE = 0 };
|
|
|
|
|
2013-05-22 14:41:47 +02:00
|
|
|
enum State
|
|
|
|
{
|
2014-11-18 15:38:15 +01:00
|
|
|
ACTIVE = 1,
|
2013-10-16 13:10:54 +02:00
|
|
|
AWAITS_START = 2,
|
|
|
|
AWAITS_IPC = 3,
|
|
|
|
AWAITS_RESUME = 4,
|
2013-11-14 13:29:47 +01:00
|
|
|
AWAITS_SIGNAL = 5,
|
|
|
|
AWAITS_SIGNAL_CONTEXT_KILL = 6,
|
2013-12-06 11:53:08 +01:00
|
|
|
STOPPED = 7,
|
2013-05-22 14:41:47 +02:00
|
|
|
};
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2013-11-18 15:31:54 +01:00
|
|
|
State _state;
|
|
|
|
Pd * _pd;
|
|
|
|
Native_utcb * _utcb_phys;
|
|
|
|
Signal_receiver * _signal_receiver;
|
|
|
|
char const * const _label;
|
2012-11-30 14:08:42 +01:00
|
|
|
|
|
|
|
/**
|
2013-10-16 20:53:59 +02:00
|
|
|
* Notice that another thread yielded the CPU to this thread
|
2012-11-30 14:08:42 +01:00
|
|
|
*/
|
2013-10-16 20:53:59 +02:00
|
|
|
void _receive_yielded_cpu();
|
2013-09-12 00:48:27 +02:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/**
|
2013-11-14 13:29:47 +01:00
|
|
|
* Attach or detach the handler of a thread-triggered event
|
|
|
|
*
|
|
|
|
* \param event_id kernel name of the thread event
|
|
|
|
* \param signal_context_id kernel name signal context or 0 to detach
|
|
|
|
*
|
|
|
|
* \retval 0 succeeded
|
|
|
|
* \retval -1 failed
|
|
|
|
*/
|
|
|
|
int _route_event(unsigned const event_id,
|
|
|
|
unsigned const signal_context_id);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Map kernel name of thread event to the corresponding member
|
|
|
|
*
|
|
|
|
* \param id kernel name of targeted thread event
|
|
|
|
*
|
|
|
|
* \retval 0 failed
|
|
|
|
* \retval >0 targeted member pointer
|
2013-10-16 20:53:59 +02:00
|
|
|
*/
|
2013-11-14 13:29:47 +01:00
|
|
|
Thread_event Thread::* _event(unsigned const id) const;
|
2013-09-12 00:48:27 +02:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/**
|
|
|
|
* Return wether this is a core thread
|
|
|
|
*/
|
|
|
|
bool _core() const;
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/**
|
2014-11-18 15:38:15 +01:00
|
|
|
* Switch from an inactive state to the active state
|
2013-10-16 20:53:59 +02:00
|
|
|
*/
|
2014-11-18 15:38:15 +01:00
|
|
|
void _become_active();
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2013-12-17 18:10:02 +01:00
|
|
|
/**
|
2014-11-18 15:38:15 +01:00
|
|
|
* Switch from the active state to the inactive state 's'
|
2013-12-17 18:10:02 +01:00
|
|
|
*/
|
2014-11-18 15:38:15 +01:00
|
|
|
void _become_inactive(State const s);
|
2013-12-17 18:10:02 +01:00
|
|
|
|
2014-12-01 15:10:33 +01:00
|
|
|
/**
|
|
|
|
* Activate our CPU-share and those of our helpers
|
|
|
|
*/
|
|
|
|
void _activate_used_shares();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deactivate our CPU-share and those of our helpers
|
|
|
|
*/
|
|
|
|
void _deactivate_used_shares();
|
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/**
|
|
|
|
* Pause execution
|
|
|
|
*/
|
|
|
|
void _pause();
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/**
|
|
|
|
* Suspend unrecoverably from execution
|
|
|
|
*/
|
|
|
|
void _stop();
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/**
|
2014-03-17 12:12:04 +01:00
|
|
|
* Cancel blocking if possible
|
2013-10-16 20:53:59 +02:00
|
|
|
*
|
2014-03-17 12:12:04 +01:00
|
|
|
* \return wether thread was in a cancelable blocking beforehand
|
2013-10-16 20:53:59 +02:00
|
|
|
*/
|
2014-03-17 12:12:04 +01:00
|
|
|
bool _resume();
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/**
|
|
|
|
* Handle an exception thrown by the memory management unit
|
|
|
|
*/
|
|
|
|
void _mmu_exception();
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2013-10-16 13:10:54 +02:00
|
|
|
/**
|
2013-12-17 18:10:02 +01:00
|
|
|
* Handle kernel-call request of the thread
|
2013-10-16 13:10:54 +02:00
|
|
|
*/
|
2014-03-26 11:00:01 +01:00
|
|
|
void _call();
|
2013-10-16 13:10:54 +02:00
|
|
|
|
2013-11-11 13:03:07 +01:00
|
|
|
/**
|
|
|
|
* Read a thread register
|
|
|
|
*
|
|
|
|
* \param id kernel name of targeted thread register
|
|
|
|
* \param value read-value buffer
|
|
|
|
*
|
|
|
|
* \retval 0 succeeded
|
|
|
|
* \retval -1 failed
|
|
|
|
*/
|
|
|
|
int _read_reg(addr_t const id, addr_t & value) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Override a thread register
|
|
|
|
*
|
|
|
|
* \param id kernel name of targeted thread register
|
|
|
|
* \param value write-value buffer
|
|
|
|
*
|
|
|
|
* \retval 0 succeeded
|
|
|
|
* \retval -1 failed
|
|
|
|
*/
|
|
|
|
int _write_reg(addr_t const id, addr_t const value);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Map kernel names of thread registers to the corresponding data
|
|
|
|
*
|
|
|
|
* \param id kernel name of thread register
|
|
|
|
*
|
|
|
|
* \retval 0 failed
|
|
|
|
* \retval >0 pointer to register content
|
|
|
|
*/
|
2013-11-14 13:29:47 +01:00
|
|
|
addr_t Thread::* _reg(addr_t const id) const;
|
2013-11-11 13:03:07 +01:00
|
|
|
|
2013-11-28 00:45:48 +01:00
|
|
|
/**
|
|
|
|
* Print table of all threads and their current activity
|
|
|
|
*/
|
|
|
|
void _print_activity_table();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Print the activity of the thread
|
2013-12-09 16:41:23 +01:00
|
|
|
*
|
|
|
|
* \param printing_thread wether this thread caused the debugging
|
2013-11-28 00:45:48 +01:00
|
|
|
*/
|
2013-12-09 16:41:23 +01:00
|
|
|
void _print_activity(bool const printing_thread);
|
2013-11-28 00:45:48 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Print the activity of the thread when it awaits a message
|
|
|
|
*/
|
|
|
|
void _print_activity_when_awaits_ipc();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Print activity info that is printed regardless of the thread state
|
|
|
|
*/
|
|
|
|
void _print_common_activity();
|
|
|
|
|
2013-10-16 13:10:54 +02:00
|
|
|
|
2014-03-15 01:26:53 +01:00
|
|
|
/*********************************************************
|
|
|
|
** Kernel-call back-ends, see kernel-interface headers **
|
|
|
|
*********************************************************/
|
2013-10-16 13:10:54 +02:00
|
|
|
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_new_pd();
|
2015-03-19 14:53:48 +01:00
|
|
|
void _call_delete_pd();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_new_thread();
|
2015-03-19 14:53:48 +01:00
|
|
|
void _call_delete_thread();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_start_thread();
|
2014-03-16 16:00:55 +01:00
|
|
|
void _call_pause_current_thread();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_pause_thread();
|
|
|
|
void _call_resume_thread();
|
2014-03-25 16:34:20 +01:00
|
|
|
void _call_resume_local_thread();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_yield_thread();
|
2013-11-21 11:35:33 +01:00
|
|
|
void _call_await_request_msg();
|
|
|
|
void _call_send_request_msg();
|
|
|
|
void _call_send_reply_msg();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_update_pd();
|
2014-04-07 15:45:44 +02:00
|
|
|
void _call_update_data_region();
|
2014-04-07 16:18:43 +02:00
|
|
|
void _call_update_instr_region();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_print_char();
|
|
|
|
void _call_new_signal_receiver();
|
|
|
|
void _call_new_signal_context();
|
|
|
|
void _call_await_signal();
|
|
|
|
void _call_signal_pending();
|
|
|
|
void _call_submit_signal();
|
|
|
|
void _call_ack_signal();
|
2013-12-06 00:12:43 +01:00
|
|
|
void _call_kill_signal_context();
|
2015-03-19 14:53:48 +01:00
|
|
|
void _call_delete_signal_context();
|
|
|
|
void _call_delete_signal_receiver();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_new_vm();
|
2015-03-19 14:53:48 +01:00
|
|
|
void _call_delete_vm();
|
2013-11-14 13:29:47 +01:00
|
|
|
void _call_run_vm();
|
|
|
|
void _call_pause_vm();
|
|
|
|
void _call_access_thread_regs();
|
|
|
|
void _call_route_thread_event();
|
2015-04-03 17:22:16 +02:00
|
|
|
void _call_new_irq();
|
|
|
|
void _call_delete_irq();
|
2013-10-16 13:10:54 +02:00
|
|
|
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/***************************
|
|
|
|
** Signal_context_killer **
|
|
|
|
***************************/
|
2013-09-09 15:20:30 +02:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
void _signal_context_kill_pending();
|
2013-12-06 00:12:43 +01:00
|
|
|
void _signal_context_kill_failed();
|
2013-10-16 20:53:59 +02:00
|
|
|
void _signal_context_kill_done();
|
2013-10-07 15:37:58 +02:00
|
|
|
|
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/********************
|
|
|
|
** Signal_handler **
|
|
|
|
********************/
|
2013-09-09 15:20:30 +02:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
void _await_signal(Signal_receiver * const receiver);
|
|
|
|
void _receive_signal(void * const base, size_t const size);
|
2013-09-09 15:20:30 +02:00
|
|
|
|
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
/**************
|
|
|
|
** Ipc_node **
|
|
|
|
**************/
|
2013-09-06 01:36:03 +02:00
|
|
|
|
2014-04-04 13:41:04 +02:00
|
|
|
void _send_request_succeeded();
|
|
|
|
void _send_request_failed();
|
|
|
|
void _await_request_succeeded();
|
|
|
|
void _await_request_failed();
|
2012-11-30 14:08:42 +01:00
|
|
|
|
2014-05-02 18:14:51 +02:00
|
|
|
|
2014-10-10 16:13:52 +02:00
|
|
|
/***********************
|
|
|
|
** Cpu_domain_update **
|
|
|
|
***********************/
|
2014-05-02 18:14:51 +02:00
|
|
|
|
2014-10-10 16:13:52 +02:00
|
|
|
void _cpu_domain_update_unblocks() { _resume(); }
|
2014-05-02 18:14:51 +02:00
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
public:
|
2013-09-09 15:20:30 +02:00
|
|
|
|
|
|
|
/**
|
2013-10-16 20:53:59 +02:00
|
|
|
* Constructor
|
|
|
|
*
|
2013-11-18 15:31:54 +01:00
|
|
|
* \param priority scheduling priority
|
2014-10-16 11:15:46 +02:00
|
|
|
* \param quota CPU-time quota
|
2013-11-18 15:31:54 +01:00
|
|
|
* \param label debugging label
|
2013-09-09 15:20:30 +02:00
|
|
|
*/
|
2014-10-16 11:15:46 +02:00
|
|
|
Thread(unsigned const priority, unsigned const quota,
|
|
|
|
char const * const label);
|
2013-09-09 15:20:30 +02:00
|
|
|
|
2013-09-19 16:47:38 +02:00
|
|
|
/**
|
2014-11-18 15:38:15 +01:00
|
|
|
* Prepare thread to get active the first time
|
2013-10-16 20:53:59 +02:00
|
|
|
*
|
2014-10-10 16:13:52 +02:00
|
|
|
* \param cpu targeted CPU
|
|
|
|
* \param pd targeted domain
|
|
|
|
* \param utcb core local pointer to userland thread-context
|
|
|
|
* \param start wether to start executing the thread
|
2013-09-19 16:47:38 +02:00
|
|
|
*/
|
2014-10-10 16:13:52 +02:00
|
|
|
void init(Cpu * const cpu, Pd * const pd, Native_utcb * const utcb,
|
|
|
|
bool const start);
|
2013-09-19 16:47:38 +02:00
|
|
|
|
2013-09-09 15:20:30 +02:00
|
|
|
|
2014-10-09 14:24:27 +02:00
|
|
|
/*************
|
|
|
|
** Cpu_job **
|
|
|
|
*************/
|
2013-09-09 15:20:30 +02:00
|
|
|
|
2014-10-10 16:13:52 +02:00
|
|
|
void exception(unsigned const cpu);
|
|
|
|
void proceed(unsigned const cpu);
|
2014-12-01 15:10:33 +01:00
|
|
|
Cpu_job * helping_sink();
|
2013-09-09 15:20:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
/***************
|
|
|
|
** Accessors **
|
|
|
|
***************/
|
|
|
|
|
2015-04-01 10:23:38 +02:00
|
|
|
unsigned id() const { return Object::id(); }
|
|
|
|
char const * label() const { return _label; }
|
2013-11-18 15:31:54 +01:00
|
|
|
char const * pd_label() const;
|
2015-04-01 10:23:38 +02:00
|
|
|
Pd * const pd() const { return _pd; }
|
2013-09-09 15:20:30 +02:00
|
|
|
};
|
|
|
|
|
2013-10-16 20:53:59 +02:00
|
|
|
#endif /* _KERNEL__THREAD_H_ */
|