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
This commit is contained in:
Martin Stein 2014-10-16 11:15:46 +02:00 committed by Christian Helmuth
parent f60e2af21f
commit 8f9355b360
79 changed files with 898 additions and 187 deletions

View File

@ -82,7 +82,7 @@ void Genode::Thread_base::_thread_bootstrap()
}
void Genode::Thread_base::_init_platform_thread(Type type)
void Genode::Thread_base::_init_platform_thread(size_t, Type type)
{
if (type == NORMAL) { return; }

View File

@ -55,7 +55,7 @@ void Thread_base::start()
/* create thread at core */
char buf[48];
name(buf, sizeof(buf));
_thread_cap = _cpu_session->create_thread(buf);
_thread_cap = _cpu_session->create_thread(0, buf);
/* assign thread to protection domain */
env()->pd_session()->bind_thread(_thread_cap);

View File

@ -60,7 +60,7 @@ namespace Genode {
/**
* Constructor
*/
Platform_thread(const char *name = 0, unsigned priority = 0,
Platform_thread(size_t, const char *name = 0, unsigned priority = 0,
addr_t utcb = 0, int thread_id = THREAD_INVALID);
/**

View File

@ -98,7 +98,7 @@ Weak_ptr<Address_space> Platform_thread::address_space()
}
Platform_thread::Platform_thread(const char *name, unsigned, addr_t,
Platform_thread::Platform_thread(size_t, const char *name, unsigned, addr_t,
int thread_id)
: _tid(THREAD_INVALID)
{

View File

@ -98,7 +98,8 @@ void Thread_base::_thread_start()
void Thread_base::start()
{
/* create and start platform thread */
_tid.pt = new(platform()->core_mem_alloc()) Platform_thread(_context->name);
_tid.pt = new(platform()->core_mem_alloc())
Platform_thread(0, _context->name);
_tid.l4id = create_thread(1, stack_top(), (void *)&_thread_start);

View File

@ -34,7 +34,7 @@ void prepare_reinit_main_thread() { }
void Thread_base::_thread_bootstrap() { }
void Thread_base::_init_platform_thread(Type type)
void Thread_base::_init_platform_thread(size_t, Type type)
{
if (type == NORMAL) { return; }
_thread_cap = Genode::env()->parent()->main_thread_cap();

View File

@ -53,7 +53,7 @@ namespace Genode {
/**
* Constructor
*/
Platform_thread(const char *name = 0, unsigned priority = 0,
Platform_thread(size_t, const char *name = 0, unsigned priority = 0,
addr_t utcb = 0, int thread_id = THREAD_INVALID);
/**

View File

@ -145,7 +145,7 @@ Platform::Sigma0 *Platform::sigma0()
Platform::Core_pager::Core_pager(Platform_pd *core_pd)
:
Platform_thread("core.pager"), Pager_object(0, Affinity::Location())
Platform_thread(0, "core.pager"), Pager_object(0, Affinity::Location())
{
Platform_thread::pager(sigma0());
@ -496,7 +496,8 @@ Platform::Platform() :
* We setup the thread object for thread0 in core pd using a special
* interface that allows us to specify the lthread number.
*/
Platform_thread *core_thread = new(core_mem_alloc()) Platform_thread("core.main", myself.id.lthread);
Platform_thread *core_thread = new(core_mem_alloc())
Platform_thread(0, "core.main", myself.id.lthread);
core_thread->pager(sigma0());
_core_pd->bind_thread(core_thread);

View File

@ -151,7 +151,8 @@ Weak_ptr<Address_space> Platform_thread::address_space()
}
Platform_thread::Platform_thread(const char *name, unsigned, addr_t, int thread_id)
Platform_thread::Platform_thread(size_t, const char *name, unsigned, addr_t,
int thread_id)
: _thread_id(thread_id), _l4_thread_id(L4_INVALID_ID), _pager(0)
{
strncpy(_name, name, sizeof(_name));

View File

@ -34,7 +34,8 @@ void Thread_base::_thread_start()
void Thread_base::start()
{
/* create and start platform thread */
_tid.pt = new(platform()->core_mem_alloc()) Platform_thread(_context->name);
_tid.pt = new(platform()->core_mem_alloc())
Platform_thread(0, _context->name);
platform_specific()->core_pd()->bind_thread(_tid.pt);

View File

@ -25,8 +25,8 @@ namespace Genode {
explicit Foc_cpu_session_client(Cpu_session_capability session)
: Rpc_client<Foc_cpu_session>(static_cap_cast<Foc_cpu_session>(session)) { }
Thread_capability create_thread(Name const &name, addr_t utcb = 0) {
return call<Rpc_create_thread>(name, utcb); }
Thread_capability create_thread(size_t, Name const &name, addr_t utcb = 0) {
return call<Rpc_create_thread>(0, name, utcb); }
Ram_dataspace_capability utcb(Thread_capability thread) {
return call<Rpc_utcb>(thread); }
@ -93,6 +93,16 @@ namespace Genode {
Native_capability alloc_irq() {
return call<Rpc_alloc_irq>(); }
int ref_account(Cpu_session_capability session) {
return call<Rpc_ref_account>(session); }
int transfer_quota(Cpu_session_capability session, size_t amount) {
return call<Rpc_transfer_quota>(session, amount); }
size_t quota() { return call<Rpc_quota>(); }
size_t used() { return call<Rpc_used>(); }
};
}

View File

@ -186,8 +186,8 @@ void Thread_base::free_secondary_stack(void* stack_addr)
}
Thread_base::Thread_base(const char *name, size_t stack_size, Type const type,
Cpu_session *cpu_session)
Thread_base::Thread_base(size_t, const char *name, size_t stack_size,
Type const type, Cpu_session *cpu_session)
:
_cpu_session(cpu_session),
_context(type == REINITIALIZED_MAIN ?
@ -195,12 +195,13 @@ Thread_base::Thread_base(const char *name, size_t stack_size, Type const type,
_join_lock(Lock::LOCKED)
{
strncpy(_context->name, name, sizeof(_context->name));
_init_platform_thread(type);
_init_platform_thread(0, type);
}
Thread_base::Thread_base(const char *name, size_t stack_size, Type type)
: Thread_base(name, stack_size, type, nullptr) { }
Thread_base::Thread_base(size_t, const char *name, size_t stack_size,
Type type)
: Thread_base(0, name, stack_size, type, nullptr) { }
Thread_base::~Thread_base()

View File

@ -39,7 +39,7 @@ void Thread_base::_deinit_platform_thread()
}
void Thread_base::_init_platform_thread(Type type)
void Thread_base::_init_platform_thread(size_t, Type type)
{
/* if no cpu session is given, use it from the environment */
if (!_cpu_session)
@ -50,7 +50,7 @@ void Thread_base::_init_platform_thread(Type type)
/* create thread at core */
char buf[48];
name(buf, sizeof(buf));
_thread_cap = _cpu_session->create_thread(buf);
_thread_cap = _cpu_session->create_thread(0, buf);
/* assign thread to protection domain */
env()->pd_session()->bind_thread(_thread_cap);

View File

@ -64,7 +64,7 @@ namespace Genode {
public:
Cpu_thread_component(Session_label const &label,
Cpu_thread_component(size_t, Session_label const &label,
Thread_name const &name,
unsigned priority, addr_t utcb,
Signal_context_capability sigh,
@ -88,6 +88,7 @@ namespace Genode {
bool bound() const { return _bound; }
void bound(bool b) { _bound = b; }
Trace::Source *trace_source() { return &_trace_source; }
size_t quota() { return 0; }
void sigh(Signal_context_capability sigh)
{
@ -122,6 +123,7 @@ namespace Genode {
typedef Tslab<Cpu_thread_component, 1024> Cpu_thread_allocator;
Session_label _label;
Rpc_entrypoint *_session_ep;
Rpc_entrypoint *_thread_ep;
Pager_entrypoint *_pager_ep;
Allocator_guard _md_alloc; /* guarded meta-data allocator */
@ -136,6 +138,24 @@ namespace Genode {
session */
Trace::Source_registry &_trace_sources;
Trace::Control_area _trace_control_area;
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
@ -158,11 +178,13 @@ namespace Genode {
/**
* Constructor
*/
Cpu_session_component(Rpc_entrypoint *thread_ep,
Cpu_session_component(Rpc_entrypoint *session_ep,
Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc,
Trace::Source_registry &trace_sources,
const char *args, Affinity const &affinity);
const char *args, Affinity const &affinity,
size_t quota);
/**
* Destructor
@ -179,7 +201,7 @@ namespace Genode {
** CPU session interface **
***************************/
Thread_capability create_thread(Name const &, addr_t);
Thread_capability create_thread(size_t, Name const &, addr_t);
Ram_dataspace_capability utcb(Thread_capability thread);
void kill_thread(Thread_capability);
Thread_capability first();
@ -200,6 +222,10 @@ namespace Genode {
unsigned trace_control_index(Thread_capability);
Dataspace_capability trace_buffer(Thread_capability);
Dataspace_capability trace_policy(Thread_capability);
int ref_account(Cpu_session_capability c);
int transfer_quota(Cpu_session_capability c, size_t q);
size_t used();
size_t quota();
/***********************************

View File

@ -35,7 +35,7 @@ void Thread_base::_deinit_platform_thread()
}
void Thread_base::_init_platform_thread(Type) { }
void Thread_base::_init_platform_thread(size_t, Type) { }
void Thread_base::start()

View File

@ -17,7 +17,7 @@
using namespace Genode;
void Thread_base::_init_platform_thread() { }
void Thread_base::_init_platform_thread(size_t, Type) { }
void Thread_base::_deinit_platform_thread() { }
void Thread_base::start() { }
void Thread_base::cancel_blocking() { }

View File

@ -0,0 +1,161 @@
#
# Build
#
build "core init drivers/timer test/cpu_quota"
#
# Boot image
#
create_boot_directory
install_config {
<config prio_levels="4">
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="CAP"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="SIGNAL"/>
</parent-provides>
<default-route>
<any-service><parent/><any-child/></any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="10M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="init_1" priority="-1">
<binary name="init"/>
<resource name="RAM" quantum="10M"/>
<resource name="CPU" quantum="10"/>
<config prio_levels="2">
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="CAP"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="SIGNAL"/>
<service name="Timer"/>
</parent-provides>
<default-route>
<any-service><parent/><any-child/></any-service>
</default-route>
<!-- should receive 10 % of the CPU time -->
<start name="test_slow" priority="-1">
<binary name="test-cpu_quota"/>
<resource name="RAM" quantum="10M"/>
<resource name="CPU" quantum="50"/>
</start>
</config>
</start>
<start name="init_2" priority="-2">
<binary name="init"/>
<resource name="RAM" quantum="100M"/>
<resource name="CPU" quantum="80"/>
<config>
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="CPU"/>
<service name="RM"/>
<service name="CAP"/>
<service name="PD"/>
<service name="LOG"/>
<service name="SIGNAL"/>
<service name="Timer"/>
</parent-provides>
<default-route>
<any-service><parent/></any-service>
</default-route>
<!-- should receive 25 % of the CPU time -->
<start name="test_middle">
<binary name="test-cpu_quota"/>
<resource name="RAM" quantum="10M"/>
<resource name="CPU" quantum="25"/>
</start>
<!-- should receive 65 % of the CPU time -->
<start name="test_fast">
<binary name="test-cpu_quota"/>
<resource name="RAM" quantum="10M"/>
<resource name="CPU" quantum="75"/>
</start>
</config>
</start>
</config>
}
build_boot_image "core init timer test-cpu_quota"
#
# Execution
#
append qemu_args "-nographic -m 64"
run_genode_until "test.*\n.*test.*\n.*test.*\n" 60
#
# Conclusion
#
set slow_opt 0.10
set middle_opt 0.25
set fast_opt 0.65
set err 0.02
regexp {[0-9]+} [regexp -inline {slow.*[0-9]+} $output] slow_cnt
regexp {[0-9]+} [regexp -inline {middle.*[0-9]+} $output] middle_cnt
regexp {[0-9]+} [regexp -inline {fast.*[0-9]+} $output] fast_cnt
set total_cnt [expr $fast_cnt + $middle_cnt + $slow_cnt]
set slow_fac [expr $slow_cnt / double($total_cnt) ]
set middle_fac [expr $middle_cnt / double($total_cnt) ]
set fast_fac [expr $fast_cnt / double($total_cnt) ]
set failed 0
if {[expr $slow_fac > $slow_opt + $err || $slow_fac < $slow_opt - $err]} {
set is_pc [expr round($slow_fac * 10000) / 100]
set opt_pc [expr round($slow_opt * 10000) / 100]
puts stderr "Error: Slow counter received $is_pc% of the CPU time."
puts stderr " Should receive $opt_pc%."
set failed 1
}
if {[expr $middle_fac > $middle_opt + $err || $middle_fac < $middle_opt - $err]} {
set is_pc [expr round($middle_fac * 10000) / 100]
set opt_pc [expr round($middle_opt * 10000) / 100]
puts stderr "Error: Middle counter received $is_pc% of the CPU time."
puts stderr " Should receive $opt_pc%."
set failed 1
}
if {[expr $fast_fac > $fast_opt + $err || $fast_fac < $fast_opt - $err]} {
set is_pc [expr round($fast_fac * 10000) / 100]
set opt_pc [expr round($fast_opt * 10000) / 100]
puts stderr "Error: Fast counter received $is_pc% of the CPU time."
puts stderr " Should receive $opt_pc%."
set failed 1
}
if {$failed} {
exit -1
} else {
puts "Test succeeded"
}

View File

@ -36,7 +36,7 @@ Native_utcb * main_thread_utcb() { return UTCB_MAIN_THREAD; }
** Thread_base **
*****************/
void Thread_base::_init_platform_thread(Type type)
void Thread_base::_init_platform_thread(size_t quota, Type type)
{
if (!_cpu_session) { _cpu_session = env()->cpu_session(); }
if (type == NORMAL) {
@ -44,7 +44,7 @@ void Thread_base::_init_platform_thread(Type type)
/* create server object */
char buf[48];
name(buf, sizeof(buf));
_thread_cap = _cpu_session->create_thread(buf, (addr_t)&_context->utcb);
_thread_cap = _cpu_session->create_thread(quota, buf, (addr_t)&_context->utcb);
return;
}
/* if we got reinitialized we have to get rid of the old UTCB */

View File

@ -98,16 +98,17 @@ namespace Kernel
*
* \param p memory donation for the new kernel thread object
* \param priority scheduling priority of the new thread
* \param quota CPU-time quota of the new thread in milliseconds
* \param label debugging label of the new thread
*
* \retval >0 kernel name of the new thread
* \retval 0 failed
*/
inline unsigned new_thread(void * const p, unsigned const priority,
char const * const label)
size_t const quota, char const * const label)
{
return call(call_id_new_thread(), (Call_arg)p, (Call_arg)priority,
(Call_arg)label);
(Call_arg)quota, (Call_arg)label);
}

View File

@ -136,9 +136,10 @@ class Kernel::Cpu_job : public Cpu_share
virtual void proceed(unsigned const id) = 0;
/**
* Construct a job with scheduling priority 'p'
* Construct a job with scheduling priority 'p' and time quota 'q'
*/
Cpu_job(Cpu_priority const p) : Cpu_share(p, 0), _cpu(0) { }
Cpu_job(Cpu_priority const p, unsigned const q)
: Cpu_share(p, q), _cpu(0) { }
/**
* Destructor
@ -313,6 +314,12 @@ class Kernel::Cpu_pool
* Return object of primary CPU
*/
Cpu * primary_cpu() const { return cpu(Cpu::primary_id()); }
/*
* Accessors
*/
Timer * timer() { return &_timer; }
};
#endif /* _KERNEL__CPU_H_ */

View File

@ -270,9 +270,11 @@ class Kernel::Thread
* Constructor
*
* \param priority scheduling priority
* \param quota CPU-time quota
* \param label debugging label
*/
Thread(unsigned const priority, char const * const label);
Thread(unsigned const priority, unsigned const quota,
char const * const label);
/**
* Prepare thread to get scheduled the first time

View File

@ -59,7 +59,7 @@ class Kernel::Vm : public Object<Vm, MAX_VMS, Vm_ids, vm_ids, vm_pool>,
*/
Vm(void * const state, Signal_context * const context)
:
Cpu_job(Cpu_priority::min), _state((Vm_state * const)state),
Cpu_job(Cpu_priority::min, 0), _state((Vm_state * const)state),
_context(context)
{ affinity(cpu_pool()->primary_cpu()); }

View File

@ -75,6 +75,12 @@ namespace Genode {
*/
bool _attaches_utcb_by_itself();
static size_t _generic_to_platform_quota(size_t const q)
{
assert(Kernel::cpu_quota_ms <= Cpu_session::QUOTA_LIMIT);
return (q * Kernel::cpu_quota_ms) >> 15;
}
public:
/**
@ -88,12 +94,13 @@ namespace Genode {
/**
* Constructor for threads outside of core
*
* \param quota CPU quota that shall be granted to the thread
* \param label debugging label
* \param virt_prio unscaled processor-scheduling priority
* \param utcb core local pointer to userland thread-context
*/
Platform_thread(const char * const label, unsigned const virt_prio,
addr_t const utcb);
Platform_thread(size_t const quota, const char * const label,
unsigned const virt_prio, addr_t const utcb);
/**
* Destructor

View File

@ -120,7 +120,7 @@ void Cpu_job::affinity(Cpu * const cpu)
** Cpu_idle **
**************/
Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::min)
Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::min, 0)
{
Cpu_job::cpu(cpu);
cpu_exception = RESET;

View File

@ -253,7 +253,7 @@ void init_kernel_mp_primary()
/* start thread with stack pointer at the top of stack */
static Native_utcb utcb;
static Thread t(Cpu_priority::max, "core");
static Thread t(Cpu_priority::max, 0, "core");
_main_thread_id = t.id();
_main_thread_utcb = &utcb;
_main_thread_utcb->start_info()->init(t.id(), Genode::Native_capability());

View File

@ -145,9 +145,10 @@ void Thread::_unschedule(State const s)
}
Thread::Thread(unsigned const priority, char const * const label)
Thread::Thread(unsigned const priority, unsigned const quota,
char const * const label)
:
Cpu_job(priority), Thread_base(this), _state(AWAITS_START), _pd(0),
Cpu_job(priority, quota), Thread_base(this), _state(AWAITS_START), _pd(0),
_utcb_phys(0), _signal_receiver(0), _label(label)
{ cpu_exception = RESET; }
@ -268,8 +269,9 @@ void Thread::_call_new_thread()
/* create new thread */
void * const p = (void *)user_arg_1();
unsigned const priority = user_arg_2();
char const * const label = (char *)user_arg_3();
Thread * const t = new (p) Thread(priority, label);
unsigned const quota = cpu_pool()->timer()->ms_to_tics(user_arg_3());
char const * const label = (char *)user_arg_4();
Thread * const t = new (p) Thread(priority, quota, label);
user_arg_0(t->id());
}

View File

@ -92,7 +92,7 @@ void Pager_activation_base::ep(Pager_entrypoint * const ep) { _ep = ep; }
Pager_activation_base::Pager_activation_base(char const * const name,
size_t const stack_size)
:
Thread_base(name, stack_size), _cap_valid(Lock::LOCKED), _ep(0)
Thread_base(0, name, stack_size), _cap_valid(Lock::LOCKED), _ep(0)
{ }

View File

@ -102,7 +102,7 @@ Platform_thread::Platform_thread(const char * const label,
/* create kernel object */
constexpr unsigned prio = Kernel::Cpu_priority::max;
_id = Kernel::new_thread(_kernel_thread, prio, _label);
_id = Kernel::new_thread(_kernel_thread, prio, 0, _label);
if (!_id) {
PERR("failed to create kernel object");
throw Cpu_session::Thread_creation_failed();
@ -110,7 +110,7 @@ Platform_thread::Platform_thread(const char * const label,
}
Platform_thread::Platform_thread(const char * const label,
Platform_thread::Platform_thread(size_t quota, const char * const label,
unsigned const virt_prio,
addr_t const utcb)
:
@ -139,7 +139,8 @@ Platform_thread::Platform_thread(const char * const label,
/* create kernel object */
constexpr unsigned max_prio = Kernel::Cpu_priority::max;
auto const phys_prio = Cpu_session::scale_priority(max_prio, virt_prio);
_id = Kernel::new_thread(_kernel_thread, phys_prio, _label);
quota = _generic_to_platform_quota(quota);
_id = Kernel::new_thread(_kernel_thread, phys_prio, quota, _label);
if (!_id) {
PERR("failed to create kernel object");
throw Cpu_session::Thread_creation_failed();

View File

@ -50,7 +50,7 @@ void Thread_base::_deinit_platform_thread()
}
void Thread_base::_init_platform_thread(Type type)
void Thread_base::_init_platform_thread(size_t, Type type)
{
/* create platform thread */
_tid.platform_thread = new (platform()->core_mem_alloc())

View File

@ -0,0 +1,63 @@
/*
* \brief Diversified test of the Register and MMIO framework
* \author Martin Stein
* \date 2012-01-09
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* 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 <base/thread.h>
#include <base/env.h>
#include <base/sleep.h>
#include <timer_session/connection.h>
using namespace Genode;
class My_thread : public Thread<8 * 1024>
{
private:
Signal_receiver * const _sigr;
bool volatile _stop;
public:
My_thread(Signal_receiver * const sigr)
: Thread(Cpu_session::pc_to_quota(100), "counter"),
_sigr(sigr), _stop(0) { }
void entry()
{
_sigr->wait_for_signal();
unsigned volatile i = 0;
while(!_stop) { i++; }
printf("%u\n", i);
sleep_forever();
}
void stop() { _stop = 1; }
};
int main()
{
Timer::Connection timer;
Signal_receiver sigr;
Signal_context sigx;
Signal_context_capability sigc = sigr.manage(&sigx);
Signal_transmitter sigt(sigc);
My_thread thread(&sigr);
thread.start();
timer.msleep(3000);
sigt.submit();
timer.msleep(30000);
thread.stop();
sleep_forever();
}

View File

@ -0,0 +1,14 @@
#
# \brief Test static configuration of CPU-time distribution
# \author Martin Stein
# \date 2014-10-13
#
# Set program name
TARGET = test-cpu_quota
# Add C++ sources
SRC_CC += main.cc
# Add libraries
LIBS += base

View File

@ -24,8 +24,8 @@ namespace Genode {
explicit Linux_cpu_session_client(Capability<Linux_cpu_session> session)
: Rpc_client<Linux_cpu_session>(session) { }
Thread_capability create_thread(Name const &name, addr_t utcb = 0) {
return call<Rpc_create_thread>(name, utcb); }
Thread_capability create_thread(size_t, Name const &name, addr_t utcb = 0) {
return call<Rpc_create_thread>(0, name, utcb); }
Ram_dataspace_capability utcb(Thread_capability thread) {
return call<Rpc_utcb>(thread); }
@ -78,6 +78,15 @@ namespace Genode {
Dataspace_capability trace_policy(Thread_capability thread) {
return call<Rpc_trace_policy>(thread); }
int ref_account(Cpu_session_capability session) {
return call<Rpc_ref_account>(session); }
int transfer_quota(Cpu_session_capability session, size_t amount) {
return call<Rpc_transfer_quota>(session, amount); }
size_t quota() { return call<Rpc_quota>(); }
size_t used() { return call<Rpc_used>(); }
/*****************************
* Linux-specific extension **

View File

@ -43,10 +43,10 @@ struct Genode::Expanding_cpu_session_client
Expanding_cpu_session_client(Genode::Capability<Linux_cpu_session> cap)
: Upgradeable_client<Genode::Linux_cpu_session_client>(cap) { }
Thread_capability create_thread(Name const &name, addr_t utcb)
Thread_capability create_thread(size_t, Name const &name, addr_t utcb)
{
return retry<Cpu_session::Out_of_metadata>(
[&] () { return Linux_cpu_session_client::create_thread(name, utcb); },
[&] () { return Linux_cpu_session_client::create_thread(0, name, utcb); },
[&] () { upgrade_ram(8*1024); });
}
};

View File

@ -80,7 +80,7 @@ Process::Process(Dataspace_capability elf_data_ds_cap,
* thread. Those information will be provided to core by the constructor of
* the 'Platform_env' of the new process.
*/
_thread0_cap = _cpu_session_client.create_thread(name);
_thread0_cap = _cpu_session_client.create_thread(0, name);
Linux_pd_session_client lx_pd(static_cap_cast<Linux_pd_session>(_pd.cap()));

View File

@ -69,7 +69,7 @@ void Thread_base::_thread_start()
}
void Thread_base::_init_platform_thread(Type type)
void Thread_base::_init_platform_thread(size_t, Type type)
{
/* if no cpu session is given, use it from the environment */
if (!_cpu_session)
@ -77,7 +77,7 @@ void Thread_base::_init_platform_thread(Type type)
/* for normal threads create an object at the CPU session */
if (type == NORMAL) {
_thread_cap = _cpu_session->create_thread(_context->name);
_thread_cap = _cpu_session->create_thread(0, _context->name);
return;
}
/* adjust initial object state for main threads */

View File

@ -63,7 +63,7 @@ namespace Genode {
public:
Cpu_thread_component(Session_label const &label,
Cpu_thread_component(size_t, Session_label const &label,
Thread_name const &name,
unsigned priority, addr_t utcb,
Signal_context_capability sigh,
@ -87,6 +87,7 @@ namespace Genode {
bool bound() const { return _bound; }
void bound(bool b) { _bound = b; }
Trace::Source *trace_source() { return &_trace_source; }
size_t quota() { return 0; }
void sigh(Signal_context_capability sigh)
{
@ -115,6 +116,7 @@ namespace Genode {
private:
Session_label _label;
Rpc_entrypoint *_session_ep;
Rpc_entrypoint *_thread_ep;
Pager_entrypoint *_pager_ep;
Allocator_guard _md_alloc; /* guarded meta-data allocator */
@ -129,6 +131,24 @@ namespace Genode {
session */
Trace::Source_registry &_trace_sources;
Trace::Control_area _trace_control_area;
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
@ -151,11 +171,13 @@ namespace Genode {
/**
* Constructor
*/
Cpu_session_component(Rpc_entrypoint *thread_ep,
Cpu_session_component(Rpc_entrypoint *session_ep,
Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc,
Trace::Source_registry &trace_sources,
const char *args, Affinity const &affinity);
const char *args, Affinity const &affinity,
size_t quota);
/**
* Destructor
@ -172,7 +194,7 @@ namespace Genode {
** CPU session interface **
***************************/
Thread_capability create_thread(Name const &, addr_t);
Thread_capability create_thread(size_t, Name const &, addr_t);
Ram_dataspace_capability utcb(Thread_capability thread);
void kill_thread(Thread_capability);
int set_pager(Thread_capability, Pager_capability);
@ -190,6 +212,10 @@ namespace Genode {
unsigned trace_control_index(Thread_capability);
Dataspace_capability trace_buffer(Thread_capability);
Dataspace_capability trace_policy(Thread_capability);
int ref_account(Cpu_session_capability c);
int transfer_quota(Cpu_session_capability c, size_t q);
size_t used();
size_t quota();
/*******************************

View File

@ -46,7 +46,7 @@ void Thread_base::_thread_start()
}
void Thread_base::_init_platform_thread(Type) { }
void Thread_base::_init_platform_thread(size_t, Type) { }
void Thread_base::_deinit_platform_thread() { }

View File

@ -401,8 +401,8 @@ void Thread_base::join()
}
Thread_base::Thread_base(const char *name, size_t stack_size, Type type,
Cpu_session * cpu_sess)
Thread_base::Thread_base(size_t, const char *name, size_t stack_size,
Type type, Cpu_session * cpu_sess)
: _cpu_session(cpu_sess)
{
_tid.meta_data = new (env()->heap()) Thread_meta_data_created(this);
@ -420,13 +420,13 @@ Thread_base::Thread_base(const char *name, size_t stack_size, Type type,
Linux_cpu_session *cpu = cpu_session(_cpu_session);
_thread_cap = cpu->create_thread(name);
_thread_cap = cpu->create_thread(0, name);
cpu->thread_id(_thread_cap, _tid.pid, _tid.tid);
}
Thread_base::Thread_base(const char *name, size_t stack_size, Type type)
: Thread_base(name, stack_size, type, env()->cpu_session()) { }
Thread_base::Thread_base(size_t, const char *name, size_t stack_size, Type type)
: Thread_base(0, name, stack_size, type, env()->cpu_session()) { }
void Thread_base::cancel_blocking()
{

View File

@ -28,8 +28,8 @@ namespace Genode {
explicit Cpu_session_client(Cpu_session_capability session)
: Rpc_client<Nova_cpu_session>(static_cap_cast<Nova_cpu_session>(session)) { }
Thread_capability create_thread(Name const &name, addr_t utcb = 0) {
return call<Rpc_create_thread>(name, utcb); }
Thread_capability create_thread(size_t, Name const &name, addr_t utcb = 0) {
return call<Rpc_create_thread>(0, name, utcb); }
Ram_dataspace_capability utcb(Thread_capability thread) {
return call<Rpc_utcb>(thread); }
@ -88,6 +88,16 @@ namespace Genode {
Dataspace_capability trace_policy(Thread_capability thread) {
return call<Rpc_trace_policy>(thread); }
int ref_account(Cpu_session_capability session) {
return call<Rpc_ref_account>(session); }
int transfer_quota(Cpu_session_capability session, size_t amount) {
return call<Rpc_transfer_quota>(session, amount); }
size_t quota() { return call<Rpc_quota>(); }
size_t used() { return call<Rpc_used>(); }
private:
Native_capability pause_sync(Thread_capability target) {

View File

@ -332,7 +332,7 @@ static uint8_t create_portal(addr_t pt, addr_t pd, addr_t ec, Mtd mtd,
Pager_object::Pager_object(unsigned long badge, Affinity::Location location)
:
Thread_base("pager:", PF_HANDLER_STACK_SIZE),
Thread_base(0, "pager:", PF_HANDLER_STACK_SIZE),
_badge(reinterpret_cast<unsigned long>(_context->name + 6)),
_client_exc_vcpu(Native_thread::INVALID_INDEX)
{

View File

@ -195,7 +195,7 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size,
const char *name, bool start_on_construction,
Affinity::Location location)
:
Thread_base(name, stack_size),
Thread_base(0, name, stack_size),
_curr_obj(start_on_construction ? 0 : (Rpc_object_base *)~0UL),
_delay_start(Lock::LOCKED),
_cap_session(cap_session)

View File

@ -65,7 +65,7 @@ void Thread_base::_thread_start()
** Thread base **
*****************/
void Thread_base::_init_platform_thread(Type type)
void Thread_base::_init_platform_thread(size_t, Type type)
{
using namespace Nova;
@ -102,7 +102,7 @@ void Thread_base::_init_platform_thread(Type type)
char buf[48];
name(buf, sizeof(buf));
_thread_cap = _cpu_session->create_thread(buf);
_thread_cap = _cpu_session->create_thread(0, buf);
if (!_thread_cap.valid())
throw Cpu_session::Thread_creation_failed();

View File

@ -64,7 +64,7 @@ namespace Genode {
public:
Cpu_thread_component(Session_label const &label,
Cpu_thread_component(size_t, Session_label const &label,
Thread_name const &name,
unsigned priority, addr_t utcb,
Signal_context_capability sigh,
@ -88,6 +88,7 @@ namespace Genode {
bool bound() const { return _bound; }
void bound(bool b) { _bound = b; }
Trace::Source *trace_source() { return &_trace_source; }
size_t quota() { return 0; }
void sigh(Signal_context_capability sigh)
{
@ -122,6 +123,7 @@ namespace Genode {
typedef Tslab<Cpu_thread_component, 1024> Cpu_thread_allocator;
Session_label _label;
Rpc_entrypoint *_session_ep;
Rpc_entrypoint *_thread_ep;
Pager_entrypoint *_pager_ep;
Allocator_guard _md_alloc; /* guarded meta-data allocator */
@ -136,6 +138,24 @@ namespace Genode {
session */
Trace::Source_registry &_trace_sources;
Trace::Control_area _trace_control_area;
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
@ -158,11 +178,13 @@ namespace Genode {
/**
* Constructor
*/
Cpu_session_component(Rpc_entrypoint *thread_ep,
Cpu_session_component(Rpc_entrypoint *session_ep,
Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc,
Trace::Source_registry &trace_sources,
const char *args, Affinity const &affinity);
const char *args, Affinity const &affinity,
size_t quota);
/**
* Destructor
@ -179,7 +201,7 @@ namespace Genode {
** CPU session interface **
***************************/
Thread_capability create_thread(Name const &, addr_t);
Thread_capability create_thread(size_t, Name const &, addr_t);
Ram_dataspace_capability utcb(Thread_capability thread);
void kill_thread(Thread_capability);
int set_pager(Thread_capability, Pager_capability);
@ -198,6 +220,10 @@ namespace Genode {
unsigned trace_control_index(Thread_capability);
Dataspace_capability trace_buffer(Thread_capability);
Dataspace_capability trace_policy(Thread_capability);
int ref_account(Cpu_session_capability c);
int transfer_quota(Cpu_session_capability c, size_t q);
size_t used();
size_t quota();
/******************************

View File

@ -49,7 +49,7 @@ class Irq_thread : public Thread_base
public:
Irq_thread(char const *name) : Thread_base(name, 1024 * sizeof(addr_t)) { }
Irq_thread(char const *name) : Thread_base(0, name, 1024 * sizeof(addr_t)) { }
/**
* Create global EC, associate it to SC

View File

@ -27,7 +27,7 @@
using namespace Genode;
void Thread_base::_init_platform_thread(Type type)
void Thread_base::_init_platform_thread(size_t, Type type)
{
/*
* This function is called for constructing server activations and pager

View File

@ -79,7 +79,7 @@ void Genode::Thread_base::_thread_bootstrap()
}
void Genode::Thread_base::_init_platform_thread(Type type)
void Genode::Thread_base::_init_platform_thread(size_t, Type type)
{
if (type == NORMAL) { return; }
_tid.l4id.raw = main_thread_tid.raw;

View File

@ -48,7 +48,7 @@ namespace Genode {
/**
* Constructor
*/
Platform_thread(const char *name = 0,
Platform_thread(size_t, const char *name = 0,
unsigned priority = 0, addr_t utcb = 0,
int thread_id = THREAD_INVALID);

View File

@ -302,7 +302,7 @@ Platform::Platform() :
* not destroy this task, it should be no problem.
*/
Platform_thread *core_thread =
new(&_thread_slab) Platform_thread("core.main");
new(&_thread_slab) Platform_thread(0, "core.main");
core_thread->set_l4_thread_id(Okl4::L4_rootserver);

View File

@ -178,7 +178,7 @@ Weak_ptr<Address_space> Platform_thread::address_space()
}
Platform_thread::Platform_thread(const char *name, unsigned prio, addr_t, int thread_id)
Platform_thread::Platform_thread(size_t, const char *name, unsigned prio, addr_t, int thread_id)
: _thread_id(thread_id), _l4_thread_id(L4_nilthread), _platform_pd(0),
_priority(prio), _pager(0)
{

View File

@ -35,7 +35,7 @@ void Thread_base::start()
{
/* create and start platform thread */
_tid.pt = new(platform_specific()->thread_slab())
Platform_thread(_context->name);
Platform_thread(0, _context->name);
platform_specific()->core_pd()->bind_thread(_tid.pt);

View File

@ -46,7 +46,7 @@ void Genode::Thread_base::_thread_bootstrap()
}
void Genode::Thread_base::_init_platform_thread(Type type)
void Genode::Thread_base::_init_platform_thread(size_t, Type type)
{
if (type == NORMAL) { return; }
_tid.l4id = main_thread_tid;

View File

@ -55,7 +55,7 @@ namespace Genode {
/**
* Constructor
*/
Platform_thread(const char *name = 0, unsigned priority = 0,
Platform_thread(size_t, const char *name = 0, unsigned priority = 0,
addr_t utcb = 0, int thread_id = THREAD_INVALID);
/**

View File

@ -214,7 +214,7 @@ Platform::Sigma0 *Platform::sigma0()
Platform::Core_pager::Core_pager(Platform_pd *core_pd)
:
Platform_thread("core.pager"), Pager_object(0, Affinity::Location())
Platform_thread(0, "core.pager"), Pager_object(0, Affinity::Location())
{
Platform_thread::pager(sigma0());
@ -665,7 +665,7 @@ Platform::Platform() :
* thread_id of first task. But since we do not destroy this
* task, it should be no problem.
*/
static Platform_thread core_thread("core.main");
static Platform_thread core_thread(0, "core.main");
core_thread.set_l4_thread_id(Pistachio::L4_MyGlobalId());
core_thread.pager(sigma0());

View File

@ -243,7 +243,8 @@ Weak_ptr<Address_space> Platform_thread::address_space()
}
Platform_thread::Platform_thread(const char *name, unsigned prio, addr_t, int id)
Platform_thread::Platform_thread(size_t, const char *name, unsigned prio,
addr_t, int id)
: _thread_id(id), _l4_thread_id(L4_nilthread), _priority(prio), _pager(0)
{
strncpy(_name, name, sizeof(_name));

View File

@ -34,7 +34,8 @@ void Thread_base::_thread_start()
void Thread_base::start()
{
/* create and start platform thread */
_tid.pt = new(platform()->core_mem_alloc()) Platform_thread(_context->name);
_tid.pt = new(platform()->core_mem_alloc())
Platform_thread(0, _context->name);
platform_specific()->core_pd()->bind_thread(_tid.pt);

View File

@ -136,7 +136,7 @@ namespace Genode {
public:
Pager_activation_base(const char *name, size_t stack_size) :
Thread_base(name, stack_size),
Thread_base(0, name, stack_size),
_cap(Native_capability()), _ep(0), _cap_valid(Lock::LOCKED) { }
/**

View File

@ -326,15 +326,17 @@ namespace Genode {
/**
* Hook for platform-specific constructor supplements
*
* \param main_thread whether this is the main thread
* \param quota CPU quota that shall be granted to the thread
* \param type enables selection of special initialization
*/
void _init_platform_thread(Type type);
void _init_platform_thread(size_t quota, Type type);
public:
/**
* Constructor
*
* \param quota CPU quota that shall be granted to the thread
* \param name thread name for debugging
* \param stack_size stack size
* \param type enables selection of special construction
@ -354,12 +356,13 @@ namespace Genode {
* at least set Context::ds_cap in a way that it references
* the dataspace of the already attached stack.
*/
Thread_base(const char *name, size_t stack_size,
Thread_base(size_t quota, const char *name, size_t stack_size,
Type type = NORMAL);
/**
* Constructor
*
* \param quota CPU quota that shall be granted to the thread
* \param name thread name for debugging
* \param stack_size stack size
* \param type enables selection of special construction
@ -369,8 +372,8 @@ namespace Genode {
* \throw Stack_alloc_failed
* \throw Context_alloc_failed
*/
Thread_base(const char *name, size_t stack_size, Type type,
Cpu_session *);
Thread_base(size_t quota, const char *name, size_t stack_size,
Type type, Cpu_session *);
/**
* Destructor
@ -513,20 +516,36 @@ namespace Genode {
/**
* Constructor
*
* \param name thread name (for debugging)
* \param type enables selection of special construction
* \param quota CPU quota that shall be granted to the thread
* \param name thread name (for debugging)
* \param type enables selection of special construction
*/
explicit Thread(const char *name, Type type = NORMAL)
: Thread_base(name, STACK_SIZE, type) { }
explicit Thread(size_t quota, const char *name, Type type = NORMAL)
: Thread_base(quota, name, STACK_SIZE, type) { }
/**
* Constructor
*
* \param quota CPU quota that shall be granted to the thread
* \param name thread name (for debugging)
* \param cpu_session thread created via specific cpu session
*/
explicit Thread(size_t quota, const char *name, Cpu_session * cpu_session)
: Thread_base(quota, name, STACK_SIZE, Type::NORMAL, cpu_session)
{ }
/**
* Shortcut for 'Thread(0, name, type)'
*/
explicit Thread(const char *name, Type type = NORMAL)
: Thread_base(0, name, STACK_SIZE, type) { }
/**
* Shortcut for 'Thread(0, name, cpu_session)'
*/
explicit Thread(const char *name, Cpu_session * cpu_session)
: Thread_base(name, STACK_SIZE, Type::NORMAL, cpu_session) { }
: Thread_base(0, name, STACK_SIZE, Type::NORMAL, cpu_session)
{ }
};
}

View File

@ -15,8 +15,11 @@
#define _INCLUDE__CPU_SESSION__CAPABILITY_H_
#include <base/capability.h>
#include <cpu_session/cpu_session.h>
namespace Genode { typedef Capability<Cpu_session> Cpu_session_capability; }
namespace Genode
{
class Cpu_session;
typedef Capability<Cpu_session> Cpu_session_capability;
}
#endif /* _INCLUDE__CPU_SESSION__CAPABILITY_H_ */

View File

@ -24,8 +24,9 @@ namespace Genode {
explicit Cpu_session_client(Cpu_session_capability session)
: Rpc_client<Cpu_session>(session) { }
Thread_capability create_thread(Name const &name, addr_t utcb = 0) {
return call<Rpc_create_thread>(name, utcb); }
Thread_capability
create_thread(size_t quota, Name const &name, addr_t utcb = 0) {
return call<Rpc_create_thread>(quota, name, utcb); }
Ram_dataspace_capability utcb(Thread_capability thread) {
return call<Rpc_utcb>(thread); }
@ -77,6 +78,16 @@ namespace Genode {
Dataspace_capability trace_policy(Thread_capability thread) {
return call<Rpc_trace_policy>(thread); }
int ref_account(Cpu_session_capability session) {
return call<Rpc_ref_account>(session); }
int transfer_quota(Cpu_session_capability session, size_t amount) {
return call<Rpc_transfer_quota>(session, amount); }
size_t quota() { return call<Rpc_quota>(); }
size_t used() { return call<Rpc_used>(); }
};
}

View File

@ -29,6 +29,7 @@
#ifndef _INCLUDE__CPU_SESSION__CPU_SESSION_H_
#define _INCLUDE__CPU_SESSION__CPU_SESSION_H_
#include <cpu_session/capability.h>
#include <base/stdint.h>
#include <base/exception.h>
#include <base/thread_state.h>
@ -50,12 +51,15 @@ namespace Genode {
class Thread_creation_failed : public Exception { };
class State_access_failed : public Exception { };
class Quota_exceeded : public Thread_creation_failed { };
class Out_of_metadata : public Exception { };
static const char *service_name() { return "CPU"; }
enum { THREAD_NAME_LEN = 48 };
enum { PRIORITY_LIMIT = 1 << 16 };
enum { QUOTA_LIMIT_LOG2 = 15 };
enum { QUOTA_LIMIT = 1 << QUOTA_LIMIT_LOG2 };
enum { DEFAULT_PRIORITY = 0 };
typedef Rpc_in_buffer<THREAD_NAME_LEN> Name;
@ -65,13 +69,16 @@ namespace Genode {
/**
* Create a new thread
*
* \param name name for the thread
* \param utcb Base of the UTCB that will be used by the thread
* \return capability representing the new thread
* \throw Thread_creation_failed
* \throw Out_of_metadata
* \param quota CPU quota that shall be granted to the thread
* \param name name for the thread
* \param utcb Base of the UTCB that will be used by the thread
* \return capability representing the new thread
* \throw Thread_creation_failed
* \throw Out_of_metadata
* \throw Quota_exceeded
*/
virtual Thread_capability create_thread(Name const &name,
virtual Thread_capability create_thread(size_t quota,
Name const &name,
addr_t utcb = 0) = 0;
/**
@ -254,6 +261,56 @@ namespace Genode {
*/
virtual Dataspace_capability trace_policy(Thread_capability thread) = 0;
/**
* Define reference account for the CPU session
*
* \param cpu_session reference account
*
* \return 0 on success
*
* Each CPU session requires another CPU session as reference
* account to transfer quota to and from. The reference account can
* be defined only once.
*/
virtual int ref_account(Cpu_session_capability cpu_session) = 0;
/**
* Transfer quota to another CPU session
*
* \param cpu_session receiver of quota donation
* \param amount amount of quota to donate
* \return 0 on success
*
* Quota can only be transfered if the specified CPU session is
* either the reference account for this session or vice versa.
*/
virtual int transfer_quota(Cpu_session_capability cpu_session,
size_t amount) = 0;
/**
* Return current quota limit
*/
virtual size_t quota() = 0;
/**
* Return amount of used quota
*/
virtual size_t used() = 0;
/**
* Return amount of available quota
*/
size_t avail()
{
size_t q = quota(), u = used();
return q > u ? q - u : 0;
}
/**
* Transform percentage of CPU utilization into CPU quota
*/
static size_t pc_to_quota(size_t const pc) {
return (pc << QUOTA_LIMIT_LOG2) / 100; }
/*********************
** RPC declaration **
@ -261,7 +318,7 @@ namespace Genode {
GENODE_RPC_THROW(Rpc_create_thread, Thread_capability, create_thread,
GENODE_TYPE_LIST(Thread_creation_failed, Out_of_metadata),
Name const &, addr_t);
size_t, Name const &, addr_t);
GENODE_RPC(Rpc_utcb, Ram_dataspace_capability, utcb, Thread_capability);
GENODE_RPC(Rpc_kill_thread, void, kill_thread, Thread_capability);
GENODE_RPC(Rpc_set_pager, int, set_pager, Thread_capability, Pager_capability);
@ -284,6 +341,10 @@ namespace Genode {
GENODE_RPC(Rpc_trace_control_index, unsigned, trace_control_index, Thread_capability);
GENODE_RPC(Rpc_trace_buffer, Dataspace_capability, trace_buffer, Thread_capability);
GENODE_RPC(Rpc_trace_policy, Dataspace_capability, trace_policy, Thread_capability);
GENODE_RPC(Rpc_ref_account, int, ref_account, Cpu_session_capability);
GENODE_RPC(Rpc_transfer_quota, int, transfer_quota, Cpu_session_capability, size_t);
GENODE_RPC(Rpc_quota, size_t, quota);
GENODE_RPC(Rpc_used, size_t, used);
/*
* 'GENODE_RPC_INTERFACE' declaration done manually
@ -311,8 +372,12 @@ namespace Genode {
Meta::Type_tuple<Rpc_trace_control_index,
Meta::Type_tuple<Rpc_trace_buffer,
Meta::Type_tuple<Rpc_trace_policy,
Meta::Type_tuple<Rpc_ref_account,
Meta::Type_tuple<Rpc_transfer_quota,
Meta::Type_tuple<Rpc_quota,
Meta::Type_tuple<Rpc_used,
Meta::Empty>
> > > > > > > > > > > > > > > > > Rpc_functions;
> > > > > > > > > > > > > > > > > > > > > Rpc_functions;
};
}

View File

@ -78,10 +78,12 @@ struct Genode::Expanding_cpu_session_client : Upgradeable_client<Genode::Cpu_ses
(static_cap_cast<Genode::Cpu_session_client::Rpc_interface>(cap))
{ }
Thread_capability create_thread(Name const &name, addr_t utcb)
Thread_capability
create_thread(size_t quota, Name const &name, addr_t utcb)
{
return retry<Cpu_session::Out_of_metadata>(
[&] () { return Cpu_session_client::create_thread(name, utcb); },
[&] () {
return Cpu_session_client::create_thread(quota, name, utcb); },
[&] () { upgrade_ram(8*1024); });
}
};

View File

@ -198,7 +198,7 @@ Process::Process(Dataspace_capability elf_ds_cap,
/* create thread0 */
try {
_thread0_cap = _cpu_session_client.create_thread(name);
_thread0_cap = _cpu_session_client.create_thread(0, name);
} catch (Cpu_session::Thread_creation_failed) {
PERR("Creation of thread0 failed");
throw THREAD_FAIL;

View File

@ -102,7 +102,7 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size,
char const *name, bool start_on_construction,
Affinity::Location location)
:
Thread_base(name, stack_size),
Thread_base(0, name, stack_size),
_cap(Untyped_capability()),
_curr_obj(0), _cap_valid(Lock::LOCKED), _delay_start(Lock::LOCKED),
_delay_exit(Lock::LOCKED),

View File

@ -191,8 +191,8 @@ void Thread_base::free_secondary_stack(void* stack_addr)
}
Thread_base::Thread_base(const char *name, size_t stack_size, Type type,
Cpu_session *cpu_session)
Thread_base::Thread_base(size_t quota, const char *name, size_t stack_size,
Type type, Cpu_session *cpu_session)
:
_cpu_session(cpu_session),
_context(type == REINITIALIZED_MAIN ?
@ -200,12 +200,13 @@ Thread_base::Thread_base(const char *name, size_t stack_size, Type type,
_join_lock(Lock::LOCKED)
{
strncpy(_context->name, name, sizeof(_context->name));
_init_platform_thread(type);
_init_platform_thread(quota, type);
}
Thread_base::Thread_base(const char *name, size_t stack_size, Type type)
: Thread_base(name, stack_size, type, nullptr) { }
Thread_base::Thread_base(size_t quota, const char *name, size_t stack_size,
Type type)
: Thread_base(quota, name, stack_size, type, nullptr) { }
Thread_base::~Thread_base()

View File

@ -54,7 +54,7 @@ void Thread_base::start()
/* create thread at core */
char buf[48];
name(buf, sizeof(buf));
_thread_cap = _cpu_session->create_thread(buf, (addr_t)&_context->utcb);
_thread_cap = _cpu_session->create_thread(0, buf, (addr_t)&_context->utcb);
/* assign thread to protection domain */
env()->pd_session()->bind_thread(_thread_cap);

View File

@ -24,6 +24,7 @@
using namespace Genode;
static constexpr bool verbose = false;
void Cpu_thread_component::update_exception_sigh()
{
@ -32,9 +33,14 @@ void Cpu_thread_component::update_exception_sigh()
};
Thread_capability Cpu_session_component::create_thread(Name const &name,
addr_t utcb)
Thread_capability Cpu_session_component::create_thread(size_t quota,
Name const &name,
addr_t utcb)
{
/* check for sufficient quota */
quota = _local_to_global(quota);
if (quota > avail()) { _insuff_for_consume(quota); }
unsigned trace_control_index = 0;
if (!_trace_control_area.alloc(trace_control_index))
throw Out_of_metadata();
@ -47,12 +53,14 @@ Thread_capability Cpu_session_component::create_thread(Name const &name,
Cpu_thread_component *thread = 0;
try {
Lock::Guard slab_lock_guard(_thread_alloc_lock);
thread = new(&_thread_alloc) Cpu_thread_component(_label,
thread_name,
_priority, utcb,
_default_exception_handler,
trace_control_index,
*trace_control);
thread = new(&_thread_alloc)
Cpu_thread_component(
quota, _label, thread_name, _priority, utcb,
_default_exception_handler, trace_control_index,
*trace_control);
/* account quota */
_used += quota;
/* set default affinity defined by CPU session */
thread->platform_thread()->affinity(_location);
@ -78,6 +86,8 @@ void Cpu_session_component::_unsynchronized_kill_thread(Cpu_thread_component *th
unsigned const trace_control_index = thread->trace_control_index();
_used -= thread->quota();
Lock::Guard lock_guard(_thread_alloc_lock);
destroy(&_thread_alloc, thread);
@ -280,13 +290,54 @@ static size_t remaining_session_ram_quota(char const *args)
}
Cpu_session_component::Cpu_session_component(Rpc_entrypoint *thread_ep,
int Cpu_session_component::transfer_quota(Cpu_session_capability c, size_t q)
{
/* lookup targeted CPU-session */
Object_pool<Cpu_session_component>::Guard s(_session_ep->lookup_and_lock(c));
if (!s) { return -1; }
/* translate quota argument and check limits */
q = _local_to_global(q);
if (q > avail()) { return _insuff_for_transfer(q); }
/* transfer quota to targeted CPU-session */
if (s->_ref == this) { return _transfer_forth(s, q); }
if (s == _ref) { return _transfer_back(q); }
return -2;
}
int Cpu_session_component::ref_account(Cpu_session_capability c)
{
/*
* Ensure that the ref account is set only once
*
* FIXME Add check for cycles along the tree of reference accounts
*/
if (_ref) { return -2; }
/* lookup targeted CPU-session */
Object_pool<Cpu_session_component>::Guard s(_session_ep->lookup_and_lock(c));
if (!s) { return -1; }
if (s == this) { return -3; }
/* establish ref-account relation from targeted CPU-session to us */
_ref = s;
_ref->_insert_ref_member(this);
return 0;
}
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,
Affinity const &affinity)
Affinity const &affinity,
size_t quota)
:
_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),
@ -294,7 +345,7 @@ Cpu_session_component::Cpu_session_component(Rpc_entrypoint *thread_ep,
/* map affinity to a location within the physical affinity space */
_location(affinity.scale_to(platform()->affinity_space())),
_trace_sources(trace_sources)
_trace_sources(trace_sources), _ref(0), _used(0), _quota(quota)
{
/* remember session label */
char buf[Session_label::size()];
@ -312,6 +363,34 @@ Cpu_session_component::Cpu_session_component(Rpc_entrypoint *thread_ep,
Cpu_session_component::~Cpu_session_component()
{
_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_back(_quota);
/* 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()
{
Lock::Guard lock_guard(_thread_list_lock);
@ -326,6 +405,32 @@ Cpu_session_component::~Cpu_session_component()
}
int Cpu_session_component::_insuff_for_transfer(size_t const q)
{
if (verbose) {
PWRN("Insufficient CPU quota for transfer: %s", _label.string());
PWRN(" avail %zu", _avail());
PWRN(" needed %zu", q);
}
return -3;
}
void Cpu_session_component::_insuff_for_consume(size_t const q)
{
if (verbose) {
PWRN("Insufficient CPU quota for consumption: %s", _label.string());
PWRN(" avail %zu", _avail());
PWRN(" needed %zu", q);
}
throw Quota_exceeded();
}
size_t Cpu_session_component::used() { return _global_to_local(_used); }
size_t Cpu_session_component::quota() { return _global_to_local(_quota); }
/****************************
** Trace::Source_registry **
****************************/

View File

@ -43,8 +43,11 @@ namespace Genode {
throw Root::Quota_exceeded();
return new (md_alloc())
Cpu_session_component(_thread_ep, _pager_ep, _md_alloc,
_trace_sources, args, affinity); }
Cpu_session_component(
Root_component<Cpu_session_component>::ep(),
_thread_ep, _pager_ep, _md_alloc, _trace_sources,
args, affinity, 0);
}
void _upgrade_session(Cpu_session_component *cpu, const char *args)
{
@ -68,8 +71,8 @@ namespace Genode {
Trace::Source_registry &trace_sources)
:
Root_component<Cpu_session_component>(session_ep, md_alloc),
_thread_ep(thread_ep), _pager_ep(pager_ep), _md_alloc(md_alloc),
_trace_sources(trace_sources)
_thread_ep(thread_ep), _pager_ep(pager_ep),
_md_alloc(md_alloc), _trace_sources(trace_sources)
{ }
};
}

View File

@ -53,6 +53,7 @@ namespace Genode {
private:
size_t const _quota;
Thread_name const _name;
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
@ -62,16 +63,17 @@ namespace Genode {
public:
Cpu_thread_component(Session_label const &label,
Cpu_thread_component(size_t quota, 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),
_quota(quota), _name(name),
_platform_thread(quota, name.string(), priority, utcb),
_bound(false), _sigh(sigh),
_trace_control_index(trace_control_index),
_trace_source(label, _name, trace_control)
{
update_exception_sigh();
@ -86,6 +88,7 @@ namespace Genode {
bool bound() const { return _bound; }
void bound(bool b) { _bound = b; }
Trace::Source *trace_source() { return &_trace_source; }
size_t quota() const { return _quota; }
void sigh(Signal_context_capability sigh)
{
@ -105,7 +108,8 @@ namespace Genode {
};
class Cpu_session_component : public Rpc_object<Cpu_session>
class Cpu_session_component : public Rpc_object<Cpu_session>,
public List<Cpu_session_component>::Element
{
public:
@ -114,6 +118,7 @@ namespace Genode {
private:
Session_label _label;
Rpc_entrypoint * const _session_ep;
Rpc_entrypoint *_thread_ep;
Pager_entrypoint *_pager_ep;
Allocator_guard _md_alloc; /* guarded meta-data allocator */
@ -129,6 +134,70 @@ namespace Genode {
Trace::Source_registry &_trace_sources;
Trace::Control_area _trace_control_area;
/*
* Members for quota accounting
*/
Cpu_session_component * _ref;
size_t _used;
size_t _quota;
List<Cpu_session_component> _ref_members;
Lock _ref_members_lock;
/*
* Utilities for quota accounting
*/
size_t _avail() { return _quota - _used; }
size_t _local_to_global(size_t const q) const {
return (q * _quota) >> Cpu_session::QUOTA_LIMIT_LOG2; }
size_t _global_to_local(size_t const q) const {
if (!_quota) { return 0; }
return (q << Cpu_session::QUOTA_LIMIT_LOG2) / _quota; }
int _insuff_for_transfer(size_t const q);
void _insuff_for_consume(size_t const q);
int _transfer_back(size_t const q)
{
_quota -= q;
_ref->_used -= q;
return 0;
}
int _transfer_forth(Cpu_session_component * const s, size_t const q)
{
s->_quota += q;
_used += q;
return 0;
}
void _insert_ref_member(Cpu_session_component * const s)
{
Lock::Guard lock_guard(_ref_members_lock);
_ref_members.insert(s);
s->_ref = this;
}
void _unsync_remove_ref_member(Cpu_session_component * const s)
{
s->_ref = 0;
_ref_members.remove(s);
}
void _remove_ref_member(Cpu_session_component * const s)
{
Lock::Guard lock_guard(_ref_members_lock);
_unsync_remove_ref_member(s);
}
void _deinit_ref_account();
void _deinit_threads();
/**
* Exception handler that will be invoked unless overridden by a
* call of 'Cpu_session::exception_handler'.
@ -150,11 +219,13 @@ namespace Genode {
/**
* Constructor
*/
Cpu_session_component(Rpc_entrypoint *thread_ep,
Cpu_session_component(Rpc_entrypoint *session_ep,
Rpc_entrypoint *thread_ep,
Pager_entrypoint *pager_ep,
Allocator *md_alloc,
Trace::Source_registry &trace_sources,
const char *args, Affinity const &affinity);
const char *args, Affinity const &affinity,
size_t quota);
/**
* Destructor
@ -171,7 +242,7 @@ namespace Genode {
** CPU session interface **
***************************/
Thread_capability create_thread(Name const &, addr_t);
Thread_capability create_thread(size_t, Name const &, addr_t);
Ram_dataspace_capability utcb(Thread_capability thread);
void kill_thread(Thread_capability);
int set_pager(Thread_capability, Pager_capability);
@ -189,6 +260,10 @@ namespace Genode {
unsigned trace_control_index(Thread_capability);
Dataspace_capability trace_buffer(Thread_capability);
Dataspace_capability trace_policy(Thread_capability);
int ref_account(Cpu_session_capability c);
int transfer_quota(Cpu_session_capability c, size_t q);
size_t used();
size_t quota();
};
}

View File

@ -266,7 +266,16 @@ int main()
= static_cap_cast<Ram_session>(ram_root.session("ram_quota=32K", Affinity()));
Ram_session_client(init_ram_session_cap).ref_account(env()->ram_session_cap());
/* create CPU session for init and transfer all of the CPU quota to it */
constexpr size_t cpu_quota = Cpu_session::QUOTA_LIMIT;
static Cpu_session_component
cpu(e, e, rm_root.pager_ep(), &sliced_heap, trace_sources,
"label=\"core\"", Affinity(), cpu_quota);
Cpu_session_capability cpu_cap = core_env()->entrypoint()->manage(&cpu);
Cpu_connection init_cpu("init");
init_cpu.ref_account(cpu_cap);
cpu.transfer_quota(init_cpu, cpu_quota);
Rm_connection init_rm;
/* transfer all left memory to init, but leave some memory left for core */

View File

@ -41,7 +41,7 @@ extern "C" {
pthread(pthread_attr_t attr, void *(*start_routine) (void *),
void *arg, size_t stack_size, char const * name,
Genode::Cpu_session * cpu)
: Thread_base(name, stack_size, Type::NORMAL, cpu),
: Thread_base(0, name, stack_size, Type::NORMAL, cpu),
_attr(attr),
_start_routine(start_routine),
_arg(arg)

View File

@ -94,36 +94,11 @@ namespace Init {
}
inline Genode::size_t read_ram_quota(Genode::Xml_node start_node)
{
Genode::Number_of_bytes ram_quota = 0;
try {
Genode::Xml_node rsc = start_node.sub_node("resource");
for (;; rsc = rsc.next("resource")) {
try {
if (rsc.attribute("name").has_value("RAM")) {
rsc.attribute("quantum").value(&ram_quota);
}
} catch (...) { }
}
} catch (...) { }
/*
* If the configured quota exceeds our own quota, we donate
* all remaining quota to the child but we need to count in
* our allocation of the child meta data from the heap.
* Hence, we preserve some of our own quota.
*/
if (ram_quota > avail_slack_ram_quota()) {
ram_quota = avail_slack_ram_quota();
if (config_verbose)
Genode::printf("Warning: Specified quota exceeds available quota.\n"
" Proceeding with a quota of %zu bytes.\n",
(Genode::size_t)ram_quota);
}
return ram_quota;
}
/**
* Return amount of CPU time that is currently unused
*/
static inline Genode::size_t avail_slack_cpu_quota() {
return Genode::env()->cpu_session()->avail(); }
/**
@ -411,15 +386,65 @@ namespace Init {
Pd_args(Genode::Xml_node start_node);
} _pd_args;
struct Read_quota
{
void warn_unsuff_quota(Genode::size_t const avail)
{
using namespace Genode;
if (!config_verbose) { return; }
Genode::printf("Warning: Specified quota exceeds available quota.\n");
Genode::printf(" Proceeding with a quota of %zu.\n", avail);
}
Read_quota(Genode::Xml_node start_node, Genode::size_t & ram_quota,
Genode::size_t & cpu_quota)
{
Genode::Number_of_bytes ram_bytes = 0;
Genode::size_t cpu_percent = 0;
try {
Genode::Xml_node rsc = start_node.sub_node("resource");
for (;; rsc = rsc.next("resource")) {
try {
if (rsc.attribute("name").has_value("RAM")) {
rsc.attribute("quantum").value(&ram_bytes);
} else if (rsc.attribute("name").has_value("CPU")) {
rsc.attribute("quantum").value(&cpu_percent); }
} catch (...) { }
}
} catch (...) { }
ram_quota = ram_bytes;
cpu_quota = Genode::Cpu_session::pc_to_quota(cpu_percent);
/*
* If the configured RAM quota exceeds our own quota, we donate
* all remaining quota to the child but we need to count in
* our allocation of the child meta data from the heap.
* Hence, we preserve some of our own quota.
*/
Genode::size_t const ram_avail = avail_slack_ram_quota();
if (ram_quota > ram_avail) {
ram_quota = ram_avail;
warn_unsuff_quota(ram_avail);
}
Genode::size_t const cpu_avail = avail_slack_cpu_quota();
if (cpu_quota > cpu_avail) {
cpu_quota = cpu_avail;
warn_unsuff_quota(cpu_avail);
}
}
};
/**
* Resources assigned to the child
*/
struct Resources
struct Resources : Read_quota
{
long prio_levels_log2;
long priority;
Genode::Affinity affinity;
Genode::size_t ram_quota;
Genode::size_t cpu_quota;
Genode::Ram_connection ram;
Genode::Cpu_connection cpu;
Genode::Rm_connection rm;
@ -428,11 +453,11 @@ namespace Init {
long prio_levels_log2,
Genode::Affinity::Space const &affinity_space)
:
Read_quota(start_node, ram_quota, cpu_quota),
prio_levels_log2(prio_levels_log2),
priority(read_priority(start_node)),
affinity(affinity_space,
read_affinity_location(affinity_space, start_node)),
ram_quota(read_ram_quota(start_node)),
ram(label),
cpu(label,
priority*(Genode::Cpu_session::PRIORITY_LIMIT >> prio_levels_log2),
@ -449,6 +474,9 @@ namespace Init {
ram.ref_account(Genode::env()->ram_session_cap());
Genode::env()->ram_session()->transfer_quota(ram.cap(), ram_quota);
cpu.ref_account(Genode::env()->cpu_session_cap());
Genode::env()->cpu_session()->transfer_quota(cpu.cap(), cpu_quota);
}
} _resources;

View File

@ -57,7 +57,7 @@ namespace Genode {
*/
Irq_activation(int irq_number, Irq_handler &handler, size_t stack_size)
:
Thread_base(_create_thread_name(irq_number), stack_size),
Thread_base(0, _create_thread_name(irq_number), stack_size),
_number(irq_number), _connection(irq_number), _handler(handler)
{
start();

View File

@ -50,7 +50,7 @@ namespace L4lx {
Genode::size_t stack_size,
Genode::addr_t vcpu_state,
unsigned cpu_nr)
: Genode::Thread_base(str, stack_size),
: Genode::Thread_base(0, str, stack_size),
_lock(Genode::Cancelable_lock::LOCKED),
_func(func),
_data(data ? *data : 0),

View File

@ -61,7 +61,7 @@ class Vmm::Vcpu_dispatcher : public T
Cpu_session * cpu_session,
Genode::Affinity::Location location)
:
T("vCPU dispatcher", stack_size),
T(0, "vCPU dispatcher", stack_size),
_cap(cap)
{
using namespace Genode;

View File

@ -62,7 +62,7 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
{
using namespace Genode;
Thread_capability vcpu_vm = _cpu_session->create_thread("vCPU");
Thread_capability vcpu_vm = _cpu_session->create_thread(0, "vCPU");
/* assign thread to protection domain */
_pd_session.bind_thread(vcpu_vm);
@ -109,7 +109,7 @@ class Vmm::Vcpu_same_pd : public Vmm::Vcpu_thread, Genode::Thread_base
Vcpu_same_pd(size_t stack_size, Cpu_session * cpu_session,
Genode::Affinity::Location location)
:
Thread_base("vCPU", stack_size, Type::NORMAL, cpu_session)
Thread_base(0, "vCPU", stack_size, Type::NORMAL, cpu_session)
{
/* release pre-allocated selectors of Thread */
Genode::cap_map()->remove(tid().exc_pt_sel, Nova::NUM_INITIAL_PT_LOG2);

View File

@ -63,10 +63,10 @@ Thread_capability Cpu_session_component::thread_cap(unsigned long lwpid)
}
Thread_capability Cpu_session_component::create_thread(Cpu_session::Name const &name, addr_t utcb)
Thread_capability Cpu_session_component::create_thread(size_t, Cpu_session::Name const &name, addr_t utcb)
{
Thread_capability thread_cap =
_parent_cpu_session.create_thread(name.string(), utcb);
_parent_cpu_session.create_thread(0, name.string(), utcb);
if (thread_cap.valid()) {
Thread_info *thread_info = new (env()->heap()) Thread_info(thread_cap, new_lwpid++);
@ -238,3 +238,11 @@ Cpu_session_component::Cpu_session_component(Signal_receiver *exception_signal_r
Cpu_session_component::~Cpu_session_component()
{
}
size_t Cpu_session_component::quota() { return 0; }
size_t Cpu_session_component::used() { return 0; }
int Cpu_session_component::ref_account(Cpu_session_capability) { return -1; }
int Cpu_session_component::transfer_quota(Cpu_session_capability, size_t) { return -1; }

View File

@ -56,7 +56,7 @@ class Cpu_session_component : public Rpc_object<Cpu_session>
** CPU session interface **
***************************/
Thread_capability create_thread(Name const &, addr_t);
Thread_capability create_thread(size_t, Name const &, addr_t);
Ram_dataspace_capability utcb(Thread_capability thread);
void kill_thread(Thread_capability);
int set_pager(Thread_capability, Pager_capability);
@ -76,6 +76,10 @@ class Cpu_session_component : public Rpc_object<Cpu_session>
unsigned trace_control_index(Thread_capability);
Dataspace_capability trace_buffer(Thread_capability);
Dataspace_capability trace_policy(Thread_capability);
int ref_account(Cpu_session_capability c);
int transfer_quota(Cpu_session_capability c, size_t q);
size_t used();
size_t quota();
};
#endif /* _CPU_SESSION_COMPONENT_H_ */

View File

@ -71,7 +71,8 @@ namespace Noux {
** Cpu_session interface **
***************************/
Thread_capability create_thread(Name const &name, addr_t utcb)
Thread_capability create_thread(size_t, Name const &name,
addr_t utcb)
{
/*
* Prevent any attempt to create more than the main
@ -82,7 +83,7 @@ namespace Noux {
while (1);
return Thread_capability();
}
_main_thread = _cpu.create_thread(name, utcb);
_main_thread = _cpu.create_thread(0, name, utcb);
return _main_thread;
}
@ -145,6 +146,11 @@ namespace Noux {
Dataspace_capability trace_policy(Thread_capability thread) {
return _cpu.trace_policy(thread); }
size_t quota() { return 0; }
size_t used() { return 0; }
int ref_account(Cpu_session_capability) { return -1; }
int transfer_quota(Cpu_session_capability, size_t) { return -1; }
};
}

View File

@ -49,7 +49,7 @@ namespace Genode {
size_t stack_size,
Thread_entry *thread_entry)
:
Thread_base(name, stack_size),
Thread_base(0, name, stack_size),
_thread_entry(thread_entry)
{
/* start Genode thread */