genode/repos/base-hw/src/core/kernel/cpu_scheduler.h

224 lines
4.9 KiB
C
Raw Normal View History

/*
* \brief Schedules CPU shares for the execution time of a CPU
* \author Martin Stein
* \date 2014-10-09
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _CORE__KERNEL__CPU_SCHEDULER_H_
#define _CORE__KERNEL__CPU_SCHEDULER_H_
/* core includes */
#include <util.h>
#include <util/misc_math.h>
#include <kernel/configuration.h>
#include <kernel/double_list.h>
namespace Kernel
{
/**
* Priority of an unconsumed CPU claim versus other unconsumed CPU claims
*/
class Cpu_priority;
/**
* Scheduling context that is both claim and fill
*/
class Cpu_share;
/**
* Schedules CPU shares for the execution time of a CPU
*/
class Cpu_scheduler;
}
class Kernel::Cpu_priority
{
private:
unsigned _value;
public:
enum {
MIN = 0,
MAX = cpu_priorities - 1,
};
/**
* Construct priority with value 'v'
*/
Cpu_priority(signed const v) : _value(Genode::min(v, MAX)) { }
/*
* Standard operators
*/
Cpu_priority &operator =(signed const v)
{
_value = Genode::min(v, MAX);
return *this;
}
operator signed() const { return _value; }
};
class Kernel::Cpu_share
{
friend class Cpu_scheduler;
private:
Double_list_item<Cpu_share> _fill_item { *this };
Double_list_item<Cpu_share> _claim_item { *this };
signed const _prio;
unsigned _quota;
unsigned _claim;
unsigned _fill { 0 };
bool _ready { false };
public:
/**
* Constructor
*
* \param p claimed priority
* \param q claimed quota
*/
Cpu_share(signed const p, unsigned const q)
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
: _prio(p), _quota(q), _claim(q) { }
/*
* Accessors
*/
bool ready() const { return _ready; }
void quota(unsigned const q) { _quota = q; }
};
class Kernel::Cpu_scheduler
{
private:
typedef Cpu_share Share;
typedef Cpu_priority Prio;
Double_list<Cpu_share> _rcl[Prio::MAX + 1]; /* ready claims */
Double_list<Cpu_share> _ucl[Prio::MAX + 1]; /* unready claims */
Double_list<Cpu_share> _fills { }; /* ready fills */
Share &_idle;
Share *_head = nullptr;
unsigned _head_quota = 0;
bool _head_claims = false;
bool _head_yields = false;
unsigned const _quota;
unsigned _residual;
unsigned const _fill;
bool _need_to_schedule { true };
time_t _last_time { 0 };
template <typename F> void _for_each_prio(F f) {
for (signed p = Prio::MAX; p > Prio::MIN - 1; p--) { f(p); } }
static void _reset(Cpu_share &share);
void _reset_claims(unsigned const p);
void _next_round();
void _consumed(unsigned const q);
void _set_head(Share &s, unsigned const q, bool const c);
void _next_fill();
void _head_claimed(unsigned const r);
void _head_filled(unsigned const r);
bool _claim_for_head();
bool _fill_for_head();
unsigned _trim_consumption(unsigned &q);
/**
* Fill 's' becomes a claim due to a quota donation
*/
void _quota_introduction(Share &s);
/**
* Claim 's' looses its state as claim due to quota revokation
*/
void _quota_revokation(Share &s);
/**
* The quota of claim 's' changes to 'q'
*/
void _quota_adaption(Share &s, unsigned const q);
public:
/**
* Constructor
*
* \param i Gets scheduled with static quota when no other share
* is schedulable. Unremovable. All values get ignored.
* \param q total amount of time quota that can be claimed by shares
* \param f time-slice length of the fill round-robin
*/
Cpu_scheduler(Share &i, unsigned const q, unsigned const f);
2019-02-20 15:26:56 +01:00
bool need_to_schedule() { return _need_to_schedule; }
void timeout() { _need_to_schedule = true; }
/**
* Update head according to the consumed time
*/
void update(time_t time);
/**
* Set 's1' ready and return wether this outdates current head
*/
void ready_check(Share &s1);
/**
* Set share 's' ready
*/
void ready(Share &s);
/**
* Set share 's' unready
*/
void unready(Share &s);
/**
* Current head looses its current claim/fill for this round
*/
void yield();
/**
* Remove share 's' from scheduler
*/
void remove(Share &s);
/**
* Insert share 's' into scheduler
*/
void insert(Share &s);
/**
* Set quota of share 's' to 'q'
*/
void quota(Share &s, unsigned const q);
/*
* Accessors
*/
Share &head() const;
unsigned head_quota() const {
return Genode::min(_head_quota, _residual); }
unsigned quota() const { return _quota; }
unsigned residual() const { return _residual; }
};
#endif /* _CORE__KERNEL__CPU_SCHEDULER_H_ */