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

238 lines
7.6 KiB
C
Raw Normal View History

2012-08-08 17:12:10 +02:00
/*
* \brief Core-specific instance of the CPU session/thread interfaces
* \author Christian Helmuth
\author Norman Feske
2012-08-08 17:12:10 +02:00
* \author Alexander Boettcher
* \date 2006-07-17
*/
/*
2013-01-10 21:44:47 +01:00
* Copyright (C) 2006-2013 Genode Labs GmbH
2012-08-08 17:12:10 +02: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__CPU_SESSION_COMPONENT_H_
#define _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_
/* Genode includes */
#include <util/list.h>
#include <base/allocator_guard.h>
#include <base/tslab.h>
#include <base/lock.h>
#include <base/pager.h>
#include <base/rpc_server.h>
#include <nova_cpu_session/nova_cpu_session.h>
/* core includes */
#include <platform_thread.h>
#include <trace/control_area.h>
#include <trace/source_registry.h>
2012-08-08 17:12:10 +02:00
namespace Genode {
/**
* RPC interface of CPU thread
*
* We make 'Cpu_thread' a RPC object only to be able to lookup CPU threads
* from thread capabilities supplied as arguments to CPU-session functions.
* A CPU thread does not provide an actual RPC interface.
*/
struct Cpu_thread
{
GENODE_RPC_INTERFACE();
};
class Cpu_thread_component : public Rpc_object<Cpu_thread>,
public List<Cpu_thread_component>::Element
{
public:
typedef Trace::Session_label Session_label;
typedef Trace::Thread_name Thread_name;
2012-08-08 17:12:10 +02:00
private:
Thread_name const _name;
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
Signal_context_capability _sigh; /* exception handler */
unsigned const _trace_control_index;
Trace::Source _trace_source;
2012-08-08 17:12:10 +02:00
public:
thread API & CPU session: accounting of CPU quota In the init configuration one can configure the donation of CPU time via 'resource' tags that have the attribute 'name' set to "CPU" and the attribute 'quantum' set to the percentage of CPU quota that init shall donate. The pattern is the same as when donating RAM quota. ! <start name="test"> ! <resource name="CPU" quantum="75"/> ! </start> This would cause init to try donating 75% of its CPU quota to the child "test". Init and core do not preserve CPU quota for their own requirements by default as it is done with RAM quota. The CPU quota that a process owns can be applied through the thread constructor. The constructor has been enhanced by an argument that indicates the percentage of the programs CPU quota that shall be granted to the new thread. So 'Thread(33, "test")' would cause the backing CPU session to try to grant 33% of the programs CPU quota to the thread "test". By now, the CPU quota of a thread can't be altered after construction. Constructing a thread with CPU quota 0 doesn't mean the thread gets never scheduled but that the thread has no guaranty to receive CPU time. Such threads have to live with excess CPU time. Threads that already existed in the official repositories of Genode were adapted in the way that they receive a quota of 0. This commit also provides a run test 'cpu_quota' in base-hw (the only kernel that applies the CPU-quota scheme currently). The test basically runs three threads with different physical CPU quota. The threads simply count for 30 seconds each and the test then checks wether the counter values relate to the CPU-quota distribution. fix #1275
2014-10-16 11:15:46 +02:00
Cpu_thread_component(size_t, Session_label const &label,
Thread_name const &name,
unsigned priority, addr_t utcb,
Signal_context_capability sigh,
unsigned trace_control_index,
Trace::Control &trace_control)
:
_name(name),
_platform_thread(name.string(), priority, utcb), _bound(false),
_sigh(sigh), _trace_control_index(trace_control_index),
_trace_source(label, _name, trace_control)
{
update_exception_sigh();
}
2012-08-08 17:12:10 +02:00
/************************
** Accessor functions **
************************/
Platform_thread *platform_thread() { return &_platform_thread; }
bool bound() const { return _bound; }
void bound(bool b) { _bound = b; }
Trace::Source *trace_source() { return &_trace_source; }
thread API & CPU session: accounting of CPU quota In the init configuration one can configure the donation of CPU time via 'resource' tags that have the attribute 'name' set to "CPU" and the attribute 'quantum' set to the percentage of CPU quota that init shall donate. The pattern is the same as when donating RAM quota. ! <start name="test"> ! <resource name="CPU" quantum="75"/> ! </start> This would cause init to try donating 75% of its CPU quota to the child "test". Init and core do not preserve CPU quota for their own requirements by default as it is done with RAM quota. The CPU quota that a process owns can be applied through the thread constructor. The constructor has been enhanced by an argument that indicates the percentage of the programs CPU quota that shall be granted to the new thread. So 'Thread(33, "test")' would cause the backing CPU session to try to grant 33% of the programs CPU quota to the thread "test". By now, the CPU quota of a thread can't be altered after construction. Constructing a thread with CPU quota 0 doesn't mean the thread gets never scheduled but that the thread has no guaranty to receive CPU time. Such threads have to live with excess CPU time. Threads that already existed in the official repositories of Genode were adapted in the way that they receive a quota of 0. This commit also provides a run test 'cpu_quota' in base-hw (the only kernel that applies the CPU-quota scheme currently). The test basically runs three threads with different physical CPU quota. The threads simply count for 30 seconds each and the test then checks wether the counter values relate to the CPU-quota distribution. fix #1275
2014-10-16 11:15:46 +02:00
size_t quota() { return 0; }
void sigh(Signal_context_capability sigh)
{
_sigh = sigh;
update_exception_sigh();
}
/**
* Propagate exception handler to platform thread
*/
void update_exception_sigh();
/**
* Return index within the CPU-session's trace control area
*/
unsigned trace_control_index() const { return _trace_control_index; }
2012-08-08 17:12:10 +02:00
};
class Cpu_session_component : public Rpc_object<Nova_cpu_session>
{
public:
typedef Cpu_thread_component::Session_label Session_label;
2012-08-08 17:12:10 +02:00
private:
/**
* Allocator used for managing the CPU threads associated with the
* CPU session
*/
typedef Tslab<Cpu_thread_component, 1024> Cpu_thread_allocator;
Session_label _label;
thread API & CPU session: accounting of CPU quota In the init configuration one can configure the donation of CPU time via 'resource' tags that have the attribute 'name' set to "CPU" and the attribute 'quantum' set to the percentage of CPU quota that init shall donate. The pattern is the same as when donating RAM quota. ! <start name="test"> ! <resource name="CPU" quantum="75"/> ! </start> This would cause init to try donating 75% of its CPU quota to the child "test". Init and core do not preserve CPU quota for their own requirements by default as it is done with RAM quota. The CPU quota that a process owns can be applied through the thread constructor. The constructor has been enhanced by an argument that indicates the percentage of the programs CPU quota that shall be granted to the new thread. So 'Thread(33, "test")' would cause the backing CPU session to try to grant 33% of the programs CPU quota to the thread "test". By now, the CPU quota of a thread can't be altered after construction. Constructing a thread with CPU quota 0 doesn't mean the thread gets never scheduled but that the thread has no guaranty to receive CPU time. Such threads have to live with excess CPU time. Threads that already existed in the official repositories of Genode were adapted in the way that they receive a quota of 0. This commit also provides a run test 'cpu_quota' in base-hw (the only kernel that applies the CPU-quota scheme currently). The test basically runs three threads with different physical CPU quota. The threads simply count for 30 seconds each and the test then checks wether the counter values relate to the CPU-quota distribution. fix #1275
2014-10-16 11:15:46 +02:00
Rpc_entrypoint *_session_ep;
2012-08-08 17:12:10 +02:00
Rpc_entrypoint *_thread_ep;
Pager_entrypoint *_pager_ep;
Allocator_guard _md_alloc; /* guarded meta-data allocator */
Cpu_thread_allocator _thread_alloc; /* meta-data allocator */
Lock _thread_alloc_lock; /* protect allocator access */
2012-08-08 17:12:10 +02:00
List<Cpu_thread_component> _thread_list;
Lock _thread_list_lock; /* protect thread list */
unsigned _priority; /* priority of threads
created with this
session */
Affinity::Location _location; /* CPU affinity of this
session */
Trace::Source_registry &_trace_sources;
Trace::Control_area _trace_control_area;
thread API & CPU session: accounting of CPU quota In the init configuration one can configure the donation of CPU time via 'resource' tags that have the attribute 'name' set to "CPU" and the attribute 'quantum' set to the percentage of CPU quota that init shall donate. The pattern is the same as when donating RAM quota. ! <start name="test"> ! <resource name="CPU" quantum="75"/> ! </start> This would cause init to try donating 75% of its CPU quota to the child "test". Init and core do not preserve CPU quota for their own requirements by default as it is done with RAM quota. The CPU quota that a process owns can be applied through the thread constructor. The constructor has been enhanced by an argument that indicates the percentage of the programs CPU quota that shall be granted to the new thread. So 'Thread(33, "test")' would cause the backing CPU session to try to grant 33% of the programs CPU quota to the thread "test". By now, the CPU quota of a thread can't be altered after construction. Constructing a thread with CPU quota 0 doesn't mean the thread gets never scheduled but that the thread has no guaranty to receive CPU time. Such threads have to live with excess CPU time. Threads that already existed in the official repositories of Genode were adapted in the way that they receive a quota of 0. This commit also provides a run test 'cpu_quota' in base-hw (the only kernel that applies the CPU-quota scheme currently). The test basically runs three threads with different physical CPU quota. The threads simply count for 30 seconds each and the test then checks wether the counter values relate to the CPU-quota distribution. fix #1275
2014-10-16 11:15:46 +02:00
Cpu_session_component * _ref;
size_t _used;
size_t _quota;
List<Cpu_session_component> _ref_members;
Lock _ref_members_lock;
size_t _global_to_local(size_t const q) const { return 0; }
size_t _avail() { return 0; }
void _deinit_ref_account();
void _deinit_threads();
size_t _local_to_global(size_t) const { return 0; }
void _insuff_for_consume(size_t);
int _insuff_for_transfer(size_t);
int _transfer_back(size_t) { return -1; }
int _transfer_forth(Cpu_session_component *, size_t) { return -1; }
void _insert_ref_member(Cpu_session_component *) { }
void _remove_ref_member(Cpu_session_component *) { }
void _unsync_remove_ref_member(Cpu_session_component *) { }
/**
* Exception handler that will be invoked unless overridden by a
* call of 'Cpu_session::exception_handler'.
*/
Signal_context_capability _default_exception_handler;
2012-08-08 17:12:10 +02:00
/**
* Raw thread-killing functionality
*
* This function is called from the 'kill_thread' function and
* the destructor. Each these functions grab the list lock
* by themselves and call this function to perform the actual
* killing.
*/
void _unsynchronized_kill_thread(Cpu_thread_component *thread);
public:
/**
* Constructor
*/
thread API & CPU session: accounting of CPU quota In the init configuration one can configure the donation of CPU time via 'resource' tags that have the attribute 'name' set to "CPU" and the attribute 'quantum' set to the percentage of CPU quota that init shall donate. The pattern is the same as when donating RAM quota. ! <start name="test"> ! <resource name="CPU" quantum="75"/> ! </start> This would cause init to try donating 75% of its CPU quota to the child "test". Init and core do not preserve CPU quota for their own requirements by default as it is done with RAM quota. The CPU quota that a process owns can be applied through the thread constructor. The constructor has been enhanced by an argument that indicates the percentage of the programs CPU quota that shall be granted to the new thread. So 'Thread(33, "test")' would cause the backing CPU session to try to grant 33% of the programs CPU quota to the thread "test". By now, the CPU quota of a thread can't be altered after construction. Constructing a thread with CPU quota 0 doesn't mean the thread gets never scheduled but that the thread has no guaranty to receive CPU time. Such threads have to live with excess CPU time. Threads that already existed in the official repositories of Genode were adapted in the way that they receive a quota of 0. This commit also provides a run test 'cpu_quota' in base-hw (the only kernel that applies the CPU-quota scheme currently). The test basically runs three threads with different physical CPU quota. The threads simply count for 30 seconds each and the test then checks wether the counter values relate to the CPU-quota distribution. fix #1275
2014-10-16 11:15:46 +02:00
Cpu_session_component(Rpc_entrypoint *session_ep,
Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc,
Trace::Source_registry &trace_sources,
thread API & CPU session: accounting of CPU quota In the init configuration one can configure the donation of CPU time via 'resource' tags that have the attribute 'name' set to "CPU" and the attribute 'quantum' set to the percentage of CPU quota that init shall donate. The pattern is the same as when donating RAM quota. ! <start name="test"> ! <resource name="CPU" quantum="75"/> ! </start> This would cause init to try donating 75% of its CPU quota to the child "test". Init and core do not preserve CPU quota for their own requirements by default as it is done with RAM quota. The CPU quota that a process owns can be applied through the thread constructor. The constructor has been enhanced by an argument that indicates the percentage of the programs CPU quota that shall be granted to the new thread. So 'Thread(33, "test")' would cause the backing CPU session to try to grant 33% of the programs CPU quota to the thread "test". By now, the CPU quota of a thread can't be altered after construction. Constructing a thread with CPU quota 0 doesn't mean the thread gets never scheduled but that the thread has no guaranty to receive CPU time. Such threads have to live with excess CPU time. Threads that already existed in the official repositories of Genode were adapted in the way that they receive a quota of 0. This commit also provides a run test 'cpu_quota' in base-hw (the only kernel that applies the CPU-quota scheme currently). The test basically runs three threads with different physical CPU quota. The threads simply count for 30 seconds each and the test then checks wether the counter values relate to the CPU-quota distribution. fix #1275
2014-10-16 11:15:46 +02:00
const char *args, Affinity const &affinity,
size_t quota);
2012-08-08 17:12:10 +02:00
/**
* Destructor
*/
~Cpu_session_component();
/**
* Register quota donation at allocator guard
*/
void upgrade_ram_quota(size_t ram_quota) { _md_alloc.upgrade(ram_quota); }
2012-08-08 17:12:10 +02:00
/***************************
** CPU session interface **
***************************/
thread API & CPU session: accounting of CPU quota In the init configuration one can configure the donation of CPU time via 'resource' tags that have the attribute 'name' set to "CPU" and the attribute 'quantum' set to the percentage of CPU quota that init shall donate. The pattern is the same as when donating RAM quota. ! <start name="test"> ! <resource name="CPU" quantum="75"/> ! </start> This would cause init to try donating 75% of its CPU quota to the child "test". Init and core do not preserve CPU quota for their own requirements by default as it is done with RAM quota. The CPU quota that a process owns can be applied through the thread constructor. The constructor has been enhanced by an argument that indicates the percentage of the programs CPU quota that shall be granted to the new thread. So 'Thread(33, "test")' would cause the backing CPU session to try to grant 33% of the programs CPU quota to the thread "test". By now, the CPU quota of a thread can't be altered after construction. Constructing a thread with CPU quota 0 doesn't mean the thread gets never scheduled but that the thread has no guaranty to receive CPU time. Such threads have to live with excess CPU time. Threads that already existed in the official repositories of Genode were adapted in the way that they receive a quota of 0. This commit also provides a run test 'cpu_quota' in base-hw (the only kernel that applies the CPU-quota scheme currently). The test basically runs three threads with different physical CPU quota. The threads simply count for 30 seconds each and the test then checks wether the counter values relate to the CPU-quota distribution. fix #1275
2014-10-16 11:15:46 +02:00
Thread_capability create_thread(size_t, Name const &, addr_t);
2012-08-08 17:12:10 +02:00
Ram_dataspace_capability utcb(Thread_capability thread);
void kill_thread(Thread_capability);
int set_pager(Thread_capability, Pager_capability);
int start(Thread_capability, addr_t, addr_t);
void pause(Thread_capability thread_cap);
void resume(Thread_capability thread_cap);
void single_step(Thread_capability thread_cap, bool enable);
2012-08-08 17:12:10 +02:00
void cancel_blocking(Thread_capability);
int name(Thread_capability, char *, size_t);
Thread_state state(Thread_capability);
void state(Thread_capability, Thread_state const &);
2012-08-08 17:12:10 +02:00
void exception_handler(Thread_capability, Signal_context_capability);
Affinity::Space affinity_space() const;
void affinity(Thread_capability, Affinity::Location);
Dataspace_capability trace_control();
unsigned trace_control_index(Thread_capability);
Dataspace_capability trace_buffer(Thread_capability);
Dataspace_capability trace_policy(Thread_capability);
thread API & CPU session: accounting of CPU quota In the init configuration one can configure the donation of CPU time via 'resource' tags that have the attribute 'name' set to "CPU" and the attribute 'quantum' set to the percentage of CPU quota that init shall donate. The pattern is the same as when donating RAM quota. ! <start name="test"> ! <resource name="CPU" quantum="75"/> ! </start> This would cause init to try donating 75% of its CPU quota to the child "test". Init and core do not preserve CPU quota for their own requirements by default as it is done with RAM quota. The CPU quota that a process owns can be applied through the thread constructor. The constructor has been enhanced by an argument that indicates the percentage of the programs CPU quota that shall be granted to the new thread. So 'Thread(33, "test")' would cause the backing CPU session to try to grant 33% of the programs CPU quota to the thread "test". By now, the CPU quota of a thread can't be altered after construction. Constructing a thread with CPU quota 0 doesn't mean the thread gets never scheduled but that the thread has no guaranty to receive CPU time. Such threads have to live with excess CPU time. Threads that already existed in the official repositories of Genode were adapted in the way that they receive a quota of 0. This commit also provides a run test 'cpu_quota' in base-hw (the only kernel that applies the CPU-quota scheme currently). The test basically runs three threads with different physical CPU quota. The threads simply count for 30 seconds each and the test then checks wether the counter values relate to the CPU-quota distribution. fix #1275
2014-10-16 11:15:46 +02:00
int ref_account(Cpu_session_capability c);
int transfer_quota(Cpu_session_capability c, size_t q);
size_t used();
size_t quota();
2012-08-08 17:12:10 +02:00
/******************************
2012-08-08 17:12:10 +02:00
** NOVA specific extensions **
******************************/
2012-08-08 17:12:10 +02:00
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_sync(Thread_capability);
2012-08-08 17:12:10 +02:00
};
}
#endif /* _CORE__INCLUDE__CPU_SESSION_COMPONENT_H_ */