/* * \brief Round-robin scheduler * \author Martin Stein * \date 2012-11-30 */ /* * 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. */ #ifndef _KERNEL__SCHEDULER_H_ #define _KERNEL__SCHEDULER_H_ /* Genode includes */ #include /* core includes */ #include #include namespace Kernel { /** * Inheritable ability for objects of type T to be item in a double list */ template class Double_list_item; /** * Double connected list for objects of type T */ template class Double_list; /** * Range save priority value */ class Priority; /** * Inheritable ability for objects of type T to be item in a scheduler */ template class Scheduler_item; /** * Round robin scheduler for objects of type T */ template class Scheduler; /** * Kernel object that can be scheduled for the CPU */ class Execution_context; typedef Scheduler Cpu_scheduler; /** * Return the systems CPU scheduler */ Cpu_scheduler * cpu_scheduler(); } template class Kernel::Double_list_item { friend class Double_list; private: Double_list_item * _next; Double_list_item * _prev; Double_list * _list; public: /** * Constructor */ Double_list_item() : _next(0), _prev(0), _list(0) { } /*************** ** Accessors ** ***************/ Double_list * list() { return _list; } }; template class Kernel::Double_list { public: typedef Double_list_item Item; private: Item * _head; Item * _tail; public: /** * Constructor */ Double_list(): _head(0), _tail(0) { } /** * Insert item 't' from behind into list */ void insert_tail(T * const t) { Item * i = static_cast(t); assert(i && !i->Item::_list); /* update new item */ i->_prev = _tail; i->_next = 0; i->_list = this; /* update rest of the list */ if (_tail) { _tail->_next = i; } else { _head = i; } _tail = i; } /** * Remove item 't' from list */ void remove(T * const t) { Item * i = static_cast(t); assert(_head && i && i->Item::_list == this); /* update next item or _tail */ if (i != _tail) { i->_next->_prev = i->_prev; } else { _tail = i->_prev; } /* update previous item or _head */ if (i != _head) { i->_prev->_next = i->_next; } else { _head = i->_next; } /* update removed item */ i->_list = 0; } /** * Remove head from list and insert it at the end */ void head_to_tail() { /* exit if nothing to do */ if (!_head || _head == _tail) { return; } /* remove head */ Item * const i = _head; _head = _head->_next; i->_next = 0; _head->_prev = 0; /* insert tail */ _tail->_next = i; i->_prev = _tail; _tail = i; } /*************** ** Accessors ** ***************/ T * head() const { return static_cast(_head); } }; class Kernel::Priority { private: unsigned _value; public: enum { MIN = 0, MAX = MAX_PRIORITY, }; /** * Constructor */ Priority(unsigned const priority) : _value(Genode::min(priority, MAX)) { } /** * Assignment operator */ Priority & operator =(unsigned const priority) { _value = Genode::min(priority, MAX); return *this; } operator unsigned() const { return _value; } }; /** * Ability to be item in a scheduler through inheritance */ template class Kernel::Scheduler_item : public Double_list::Item { private: Priority const _priority; public: /** * Constructor * * \param p scheduling priority */ Scheduler_item(Priority const p) : _priority(p) { } /*************** ** Accessors ** ***************/ Priority priority() const { return _priority; } }; template class Kernel::Scheduler { protected: T * const _idle; T * _current; Double_list _items[Priority::MAX + 1]; public: typedef Scheduler_item Item; /** * Constructor */ Scheduler(T * const idle) : _idle(idle), _current(0) { } /** * Get currently scheduled item */ T * head() { for (int i = Priority::MAX; i >= 0 ; i--) { _current = _items[i].head(); if (_current) return _current; } return _idle; } /** * End turn of currently scheduled item */ void yield() { if (!_current) return; _items[_current->priority()].head_to_tail(); } /** * Include 'i' in scheduling */ void insert(T * const i) { assert(i != _idle); _items[i->priority()].insert_tail(i); } /** * Exclude 'i' from scheduling */ void remove(T * const i) { _items[i->priority()].remove(i); } }; class Kernel::Execution_context : public Cpu_scheduler::Item { public: /** * Handle an exception that occured during execution */ virtual void handle_exception() = 0; /** * Continue execution */ virtual void proceed() = 0; /** * Constructor * * \param p scheduling priority */ Execution_context(Priority const p) : Cpu_scheduler::Item(p) { } /** * Destructor */ virtual ~Execution_context() { if (list()) { cpu_scheduler()->remove(this); } } }; #endif /* _KERNEL__SCHEDULER_H_ */