genode/repos/base/src/core/cpu_session_component.cc

537 lines
14 KiB
C++
Raw Normal View History

2013-01-24 11:35:27 +01:00
/*
2011-12-22 16:19:25 +01:00
* \brief Core implementation of the CPU session/thread interfaces
* \author Christian Helmuth
* \date 2006-07-17
*
* FIXME arg_string and quota missing
*/
/*
2013-01-10 21:44:47 +01:00
* Copyright (C) 2006-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.
*/
/* Genode includes */
#include <base/printf.h>
#include <util/arg_string.h>
/* core includes */
2011-12-22 16:19:25 +01:00
#include <cpu_session_component.h>
#include <rm_session_component.h>
#include <platform_generic.h>
2011-12-22 16:19:25 +01:00
using namespace Genode;
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
static constexpr bool verbose = false;
2011-12-22 16:19:25 +01:00
void Cpu_thread_component::update_exception_sigh()
{
if (platform_thread()->pager())
platform_thread()->pager()->exception_handler(_sigh);
};
Thread_capability Cpu_session_component::create_thread(size_t weight,
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
Name const &name,
addr_t utcb)
2011-12-22 16:19:25 +01:00
{
unsigned trace_control_index = 0;
if (!_trace_control_area.alloc(trace_control_index))
throw Out_of_metadata();
Trace::Control * const trace_control =
_trace_control_area.at(trace_control_index);
Trace::Thread_name thread_name(name.string());
2011-12-22 16:19:25 +01:00
Cpu_thread_component *thread = 0;
if (weight == 0) {
PWRN("Thread %s: Bad weight 0, using %i instead.",
name.string(), DEFAULT_WEIGHT);
weight = DEFAULT_WEIGHT;
}
if (weight > QUOTA_LIMIT) {
PWRN("Thread %s: Oversized weight %zu, using %i instead.",
name.string(), weight, QUOTA_LIMIT);
weight = QUOTA_LIMIT;
}
Lock::Guard thread_list_lock_guard(_thread_list_lock);
_incr_weight(weight);
2011-12-22 16:19:25 +01:00
try {
Lock::Guard slab_lock_guard(_thread_alloc_lock);
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 = new(&_thread_alloc)
Cpu_thread_component(
weight, _weight_to_quota(weight), _label, thread_name,
_priority, utcb, _default_exception_handler,
trace_control_index, *trace_control);
/* set default affinity defined by CPU session */
thread->platform_thread()->affinity(_location);
2011-12-22 16:19:25 +01:00
} catch (Allocator::Out_of_memory) {
throw Out_of_metadata();
2011-12-22 16:19:25 +01:00
}
_thread_list.insert(thread);
_trace_sources.insert(thread->trace_source());
2011-12-22 16:19:25 +01:00
return _thread_ep->manage(thread);
}
void Cpu_session_component::_unsynchronized_kill_thread(Cpu_thread_component *thread)
{
_thread_ep->dissolve(thread);
_thread_list.remove(thread);
_trace_sources.remove(thread->trace_source());
unsigned const trace_control_index = thread->trace_control_index();
_decr_weight(thread->weight());
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
Lock::Guard lock_guard(_thread_alloc_lock);
destroy(&_thread_alloc, thread);
_trace_control_area.free(trace_control_index);
2011-12-22 16:19:25 +01:00
}
void Cpu_session_component::kill_thread(Thread_capability thread_cap)
{
auto lambda = [this] (Cpu_thread_component *thread) {
if (!thread) return;
2011-12-22 16:19:25 +01:00
Lock::Guard lock_guard(_thread_list_lock);
_unsynchronized_kill_thread(thread);
};
_thread_ep->apply(thread_cap, lambda);
2011-12-22 16:19:25 +01:00
}
int Cpu_session_component::set_pager(Thread_capability thread_cap,
Pager_capability pager_cap)
{
auto lambda = [&] (Cpu_thread_component *thread) {
if (!thread) return -1;
2011-12-22 16:19:25 +01:00
auto p_lambda = [&] (Pager_object *p) {
if (!p) return -2;
2011-12-22 16:19:25 +01:00
thread->platform_thread()->pager(p);
p->thread_cap(thread->cap());
return 0;
};
return _pager_ep->apply(pager_cap, p_lambda);
};
return _thread_ep->apply(thread_cap, lambda);
2011-12-22 16:19:25 +01:00
}
int Cpu_session_component::start(Thread_capability thread_cap,
addr_t ip, addr_t sp)
{
auto lambda = [&] (Cpu_thread_component *thread) {
if (!thread) return -1;
/*
* If an exception handler was installed prior to the call of 'set_pager',
* we need to update the pager object with the current exception handler.
*/
thread->update_exception_sigh();
return thread->platform_thread()->start((void *)ip, (void *)sp);
};
return _thread_ep->apply(thread_cap, lambda);
2011-12-22 16:19:25 +01:00
}
void Cpu_session_component::pause(Thread_capability thread_cap)
{
auto lambda = [this] (Cpu_thread_component *thread) {
if (!thread) return;
2011-12-22 16:19:25 +01:00
thread->platform_thread()->pause();
};
_thread_ep->apply(thread_cap, lambda);
2011-12-22 16:19:25 +01:00
}
void Cpu_session_component::resume(Thread_capability thread_cap)
{
auto lambda = [this] (Cpu_thread_component *thread) {
if (!thread) return;
2011-12-22 16:19:25 +01:00
thread->platform_thread()->resume();
};
_thread_ep->apply(thread_cap, lambda);
2011-12-22 16:19:25 +01:00
}
void Cpu_session_component::cancel_blocking(Thread_capability thread_cap)
{
auto lambda = [this] (Cpu_thread_component *thread) {
if (!thread) return;
2011-12-22 16:19:25 +01:00
thread->platform_thread()->cancel_blocking();
};
_thread_ep->apply(thread_cap, lambda);
2011-12-22 16:19:25 +01:00
}
Thread_state Cpu_session_component::state(Thread_capability thread_cap)
2011-12-22 16:19:25 +01:00
{
auto lambda = [this] (Cpu_thread_component *thread) {
if (!thread) throw State_access_failed();
return thread->platform_thread()->state();
};
return _thread_ep->apply(thread_cap, lambda);
}
2011-12-22 16:19:25 +01:00
void Cpu_session_component::state(Thread_capability thread_cap,
Thread_state const &state)
{
auto lambda = [&] (Cpu_thread_component *thread) {
if (!thread) throw State_access_failed();
thread->platform_thread()->state(state);
};
_thread_ep->apply(thread_cap, lambda);
2011-12-22 16:19:25 +01:00
}
void
Cpu_session_component::exception_handler(Thread_capability thread_cap,
Signal_context_capability sigh_cap)
2011-12-22 16:19:25 +01:00
{
/*
* By specifying an invalid thread capability, the caller sets the default
* exception handler for the CPU session.
*/
if (!thread_cap.valid()) {
_default_exception_handler = sigh_cap;
return;
}
/*
* If an invalid signal handler is specified for a valid thread, we revert
* the signal handler to the CPU session's default signal handler.
*/
if (!sigh_cap.valid()) {
sigh_cap = _default_exception_handler;
}
auto lambda = [&] (Cpu_thread_component *thread) {
if (!thread) return;
2011-12-22 16:19:25 +01:00
thread->sigh(sigh_cap);
};
_thread_ep->apply(thread_cap, lambda);
2011-12-22 16:19:25 +01:00
}
Affinity::Space Cpu_session_component::affinity_space() const
{
/*
* Return affinity subspace as constrained by the CPU session
* affinity.
*/
return Affinity::Space(_location.width(), _location.height());
}
void Cpu_session_component::affinity(Thread_capability thread_cap,
Affinity::Location location)
{
auto lambda = [&] (Cpu_thread_component *thread) {
if (!thread) return;
/* convert session-local location to physical location */
int const x1 = location.xpos() + _location.xpos(),
y1 = location.ypos() + _location.ypos(),
x2 = location.xpos() + location.width(),
y2 = location.ypos() + location.height();
int const clipped_x1 = max(_location.xpos(), x1),
clipped_y1 = max(_location.ypos(), y1),
clipped_x2 = max(_location.xpos() + (int)_location.width() - 1, x2),
clipped_y2 = max(_location.ypos() + (int)_location.height() - 1, y2);
thread->platform_thread()->affinity(Affinity::Location(clipped_x1, clipped_y1,
clipped_x2 - clipped_x1 + 1,
clipped_y2 - clipped_y1 + 1));
};
_thread_ep->apply(thread_cap, lambda);
}
Dataspace_capability Cpu_session_component::trace_control()
{
return _trace_control_area.dataspace();
}
unsigned Cpu_session_component::trace_control_index(Thread_capability thread_cap)
{
auto lambda = [] (Cpu_thread_component *thread) -> unsigned {
if (!thread) return 0;
return thread->trace_control_index();
};
return _thread_ep->apply(thread_cap, lambda);
}
Dataspace_capability Cpu_session_component::trace_buffer(Thread_capability thread_cap)
{
auto lambda = [this] (Cpu_thread_component *thread) {
if (!thread) return Dataspace_capability();
return thread->trace_source()->buffer();
};
return _thread_ep->apply(thread_cap, lambda);
}
Dataspace_capability Cpu_session_component::trace_policy(Thread_capability thread_cap)
{
auto lambda = [this] (Cpu_thread_component *thread) {
if (!thread) return Dataspace_capability();
return thread->trace_source()->policy();
};
return _thread_ep->apply(thread_cap, lambda);
}
static size_t remaining_session_ram_quota(char const *args)
{
/*
* We don't need to consider an underflow here because
* 'Cpu_root::_create_session' already checks for the condition.
*/
return Arg_string::find_arg(args, "ram_quota").ulong_value(0)
- Trace::Control_area::SIZE;
}
void Cpu_session_component::_transfer_quota(Cpu_session_component * const dst,
size_t const quota)
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
{
if (!quota) { return; }
_decr_quota(quota);
dst->_incr_quota(quota);
}
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 Cpu_session_component::transfer_quota(Cpu_session_capability dst_cap,
size_t amount)
{
/* lookup targeted CPU session */
auto lambda = [&] (Cpu_session_component *dst) {
if (!dst) {
PWRN("Transfer CPU quota, %s, targeted session not found",
_label.string());
return -1;
}
/* check reference relationship */
if (dst->_ref != this && dst != _ref) {
PWRN("Transfer CPU quota, %s -> %s, no reference relation",
_label.string(), dst->_label.string());
return -2;
}
/* check quota availability */
size_t const quota = quota_lim_downscale(_quota, amount);
if (quota > _quota) {
PWRN("Transfer CPU quota, %s -> %s, insufficient quota %zu, need %zu",
_label.string(), dst->_label.string(), _quota, quota);
return -3;
}
/* transfer quota */
_transfer_quota(dst, quota);
return 0;
};
return _session_ep->apply(dst_cap, lambda);
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 Cpu_session_component::ref_account(Cpu_session_capability ref_cap)
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
{
/*
* Ensure that the ref account is set only once
*
* FIXME Add check for cycles along the tree of reference accounts
*/
if (_ref) {
PWRN("Set ref account, %s, set already",
_label.string());
return -2; }
/* lookup and check targeted CPU-session */
auto lambda = [&] (Cpu_session_component *ref) {
if (!ref) {
PWRN("Set ref account, %s, targeted session not found",
_label.string());
return -1;
}
if (ref == this) {
PWRN("Set ref account, %s, self reference not allowed",
_label.string());
return -3;
}
/* establish ref-account relation from targeted CPU-session to us */
_ref = ref;
_ref->_insert_ref_member(this);
return 0;
};
return _session_ep->apply(ref_cap, lambda);
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::Cpu_session_component(Rpc_entrypoint *session_ep,
Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc,
Trace::Source_registry &trace_sources,
char const *args,
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
Affinity const &affinity,
size_t const quota)
:
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
_session_ep(session_ep),
_thread_ep(thread_ep), _pager_ep(pager_ep),
_md_alloc(md_alloc, remaining_session_ram_quota(args)),
_thread_alloc(&_md_alloc), _priority(0),
/* map affinity to a location within the physical affinity space */
_location(affinity.scale_to(platform()->affinity_space())),
_trace_sources(trace_sources), _quota(quota), _ref(0)
2011-12-22 16:19:25 +01:00
{
/* remember session label */
char buf[Session_label::size()];
Arg_string::find_arg(args, "label").string(buf, sizeof(buf), "");
_label = Session_label(buf);
2011-12-22 16:19:25 +01:00
Arg a = Arg_string::find_arg(args, "priority");
if (a.valid()) {
_priority = a.ulong_value(0);
/* clamp priority value to valid range */
_priority = min((unsigned)PRIORITY_LIMIT - 1, _priority);
}
}
Cpu_session_component::~Cpu_session_component()
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
{
_deinit_threads();
_deinit_ref_account();
}
void Cpu_session_component::_deinit_ref_account()
{
/* without a ref-account, nothing has do be done */
if (!_ref) { return; }
/* give back our remaining quota to our ref account */
_transfer_quota(_ref, _quota);
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
/* remove ref-account relation between us and our ref-account */
Cpu_session_component * const orig_ref = _ref;
_ref->_remove_ref_member(this);
/* redirect ref-account relation of ref members to our prior ref account */
Lock::Guard lock_guard(_ref_members_lock);
for (Cpu_session_component * s; (s = _ref_members.first()); ) {
_unsync_remove_ref_member(s);
orig_ref->_insert_ref_member(s);
}
}
void Cpu_session_component::_deinit_threads()
2011-12-22 16:19:25 +01:00
{
Lock::Guard lock_guard(_thread_list_lock);
/*
* We have to keep the '_thread_list_lock' during the whole destructor to
* prevent races with incoming calls of the 'create_thread' function,
* adding new threads while we are destroying them.
*/
for (Cpu_thread_component *thread; (thread = _thread_list.first()); )
_unsynchronized_kill_thread(thread);
}
void Cpu_session_component::
_update_thread_quota(Cpu_thread_component * const thread) const
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->platform_thread()->quota(_weight_to_quota(thread->weight()));
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
}
void Cpu_session_component::_incr_weight(size_t const weight)
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
{
_weight += weight;
if (_quota) { _update_each_thread_quota(); }
}
void Cpu_session_component::_decr_weight(size_t const weight)
{
_weight -= weight;
if (_quota) { _update_each_thread_quota(); }
}
void Cpu_session_component::_decr_quota(size_t const quota)
{
Lock::Guard lock_guard(_thread_list_lock);
_quota -= quota;
_update_each_thread_quota();
}
void Cpu_session_component::_incr_quota(size_t const quota)
{
Lock::Guard lock_guard(_thread_list_lock);
_quota += quota;
_update_each_thread_quota();
}
void Cpu_session_component::_update_each_thread_quota()
{
Cpu_thread_component * thread = _thread_list.first();
for (; thread; thread = thread->next()) { _update_thread_quota(thread); }
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
Cpu_session_component::_weight_to_quota(size_t const weight) const {
return (weight * _quota) / _weight; }
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
/****************************
** Trace::Source_registry **
****************************/
unsigned Trace::Source::_alloc_unique_id()
{
static Lock lock;
static unsigned cnt;
Lock::Guard guard(lock);
return cnt++;
}