genode/repos/base-nova/src/core/include/platform_thread.h

185 lines
3.7 KiB
C
Raw Normal View History

2011-12-22 16:19:25 +01:00
/*
* \brief Thread facility
* \author Norman Feske
* \author Alexander Boettcher
2011-12-22 16:19:25 +01:00
* \date 2009-10-02
*/
/*
2013-01-10 21:44:47 +01:00
* Copyright (C) 2009-2013 Genode Labs GmbH
2011-12-22 16:19:25 +01:00
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _CORE__INCLUDE__PLATFORM_THREAD_H_
#define _CORE__INCLUDE__PLATFORM_THREAD_H_
/* Genode includes */
#include <thread/capability.h>
#include <base/thread_state.h>
#include <base/native_types.h>
#include <base/thread.h>
/* base-internal includes */
#include <base/internal/stack.h>
/* core includes */
#include <pager.h>
#include <address_space.h>
2011-12-22 16:19:25 +01:00
namespace Genode {
class Platform_pd;
class Platform_thread
{
private:
Platform_pd *_pd;
Pager_object *_pager;
addr_t _id_base;
addr_t _sel_exc_base;
Affinity::Location _location;
enum {
MAIN_THREAD = 0x1U,
VCPU = 0x2U,
WORKER = 0x4U,
};
uint8_t _features;
uint8_t _priority;
Stack::Name _name;
addr_t _sel_ec() const { return _id_base; }
addr_t _sel_pt_oom() const { return _id_base + 1; }
addr_t _sel_sc() const { return _id_base + 2; }
2011-12-22 16:19:25 +01:00
/* convenience function to access _feature variable */
inline bool is_main_thread() const { return _features & MAIN_THREAD; }
inline bool is_vcpu() const { return _features & VCPU; }
inline bool is_worker() const { return _features & WORKER; }
2011-12-22 16:19:25 +01:00
public:
/* invalid thread number */
enum { THREAD_INVALID = -1 };
2011-12-22 16:19:25 +01:00
/**
* Constructor
*/
Platform_thread(const char *name = 0,
unsigned priority = 0,
2012-08-08 17:12:10 +02:00
int thread_id = THREAD_INVALID);
2011-12-22 16:19:25 +01:00
/**
* Destructor
*/
~Platform_thread();
/**
* Start thread
*
* \param ip instruction pointer to start at
* \param sp stack pointer to use
2011-12-22 16:19:25 +01:00
*
* \retval 0 successful
* \retval -1 thread/vCPU could not be started
2011-12-22 16:19:25 +01:00
*/
int start(void *ip, void *sp);
2011-12-22 16:19:25 +01:00
/**
* Pause this thread
*/
NOVA: extend cpu_session with synchronous pause The kernel provides a "recall" feature issued on threads to force a thread into an exception. In the exception the current state of the thread can be obtained and its execution can be halted/paused. However, the recall exception is only delivered when the next time the thread would leave the kernel. That means the delivery is asynchronous and Genode has to wait until the exception triggered. Waiting for the exception can either be done in the cpu_session service or outside the service in the protection domain of the caller. It turned out that waiting inside the cpu_service is prone to deadlock the system. The cpu_session interface is one of many session interfaces handled by the same thread inside Core. Deadlock situation: * The caller (thread_c) to pause some thread_p manages to establish the call to the cpu_session thread_s of Core but get be interrupted before issuing the actual pause (recall) command. * Now the - to be recalled thread_p - is scheduled and tries to invoke another service of Core, like making log output. * Since the Core thread_s is handling the session request of thread_c, the kernel uses the timeslice of thread_p to help to finish the request handled by thread_s. * Thread_s issues the actual pause/recall on thread_p and blocks inside Core to wait for the recall exception to be issued. * thread_p will leave not the kernel before finishing it actual IPC with thread_s which is blocked waiting for thread_p. That is the reason why the waiting/blocking for the recall exception taking place must be done on NOVA in the context of the caller (thread_1). Introduce a pause_sync call to the cpu_session which returns a semaphore capability to the caller. The caller blocks on the semaphore and is woken up when the pager of thread_p receives the recall exception with the state of thread_p.
2012-08-24 09:29:54 +02:00
Native_capability pause();
2011-12-22 16:19:25 +01:00
/**
* Resume this thread
*/
void resume();
/**
* Cancel currently blocking operation
*/
void cancel_blocking();
/**
* Override thread state with 's'
2011-12-22 16:19:25 +01:00
*
* \throw Cpu_session::State_access_failed
*/
void state(Thread_state s);
/**
* Read thread state
2011-12-22 16:19:25 +01:00
*
* \throw Cpu_session::State_access_failed
2011-12-22 16:19:25 +01:00
*/
Thread_state state();
2011-12-22 16:19:25 +01:00
/**
* Return the address space to which the thread is bound
*/
Weak_ptr<Address_space> address_space();
2011-12-22 16:19:25 +01:00
/************************
** Accessor functions **
************************/
/**
* Set pager
*/
void pager(Pager_object *pager) { _pager = pager; }
/**
* Return pager object
*/
2011-12-22 16:19:25 +01:00
Pager_object *pager() { return _pager; }
/**
* Return identification of thread when faulting
*/
unsigned long pager_object_badge() const;
/**
* Set the executing CPU for this thread
2011-12-22 16:19:25 +01:00
*/
void affinity(Affinity::Location location);
2011-12-22 16:19:25 +01:00
/**
* Get the executing CPU for this thread
*/
Affinity::Location affinity() const;
2011-12-22 16:19:25 +01:00
/**
* Get thread name
*/
const char *name() const { return "noname"; }
/**
* Associate thread with protection domain
*/
void bind_to_pd(Platform_pd *pd, bool main_thread)
2011-12-22 16:19:25 +01:00
{
_pd = pd;
if (main_thread) _features |= MAIN_THREAD;
2011-12-22 16:19:25 +01:00
}
2012-08-08 17:12:10 +02:00
Native_capability single_step(bool on);
/**
* Set CPU quota of the thread to 'quota'
*/
void quota(size_t const quota) { /* not supported*/ }
/**
* Return execution time consumed by the thread
*/
unsigned long long execution_time() const;
2011-12-22 16:19:25 +01:00
};
}
#endif /* _CORE__INCLUDE__PLATFORM_THREAD_H_ */