hw: scheduler in extra header & asserts reviewed

ref #528
This commit is contained in:
Martin Stein 2013-09-03 14:20:43 +02:00 committed by Norman Feske
parent 4a1c218fd0
commit 2c357a4f04
2 changed files with 197 additions and 201 deletions

View File

@ -0,0 +1,195 @@
/*
* \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_
/* core includes */
#include <assert.h>
namespace Kernel
{
/**
* Double connected list of objects of type T
*/
template <typename T>
class Double_list;
/**
* Round robin scheduler for objects of type T
*/
template <typename T>
class Scheduler;
}
template <typename T>
class Kernel::Double_list
{
public:
/**
* Enable deriving objects to be inserted into a double list
*/
class 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<Item *>(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<Item *>(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<T *>(_head); }
};
template <typename T>
class Kernel::Double_list<T>::Item
{
friend class Double_list<T>;
private:
Item * _next;
Item * _prev;
Double_list<T> * _list;
public:
/**
* Constructor
*/
Item() : _next(0), _prev(0), _list(0) { }
};
template <typename T>
class Kernel::Scheduler
{
public:
/**
* Capability to be item in a scheduler through inheritance
*/
class Item : public Double_list<T>::Item { };
protected:
T * const _idle;
Double_list<T> _items;
public:
/**
* Constructor
*/
Scheduler(T * const idle) : _idle(idle) { }
/**
* Get currently scheduled item
*/
T * head() const
{
T * const i = _items.head();
if (i) { return i; }
return _idle;
}
/**
* End turn of currently scheduled item
*/
void yield() { _items.head_to_tail(); }
/**
* Include 'i' in scheduling
*/
void insert(T * const i)
{
assert(i != _idle);
_items.insert_tail(i);
}
/**
* Exclude 'i' from scheduling
*/
void remove(T * const i) { _items.remove(i); }
};
#endif /* _KERNEL__SCHEDULER_H_ */

View File

@ -24,6 +24,7 @@
#include <timer.h>
#include <assert.h>
#include <kernel/configuration.h>
#include <kernel/scheduler.h>
#include <kernel/object.h>
namespace Genode
@ -42,213 +43,13 @@ namespace Kernel
template <typename T> class Fifo : public Genode::Fifo<T> { };
/**
* Double connected list
*
* \param _ENTRY_T list entry type
*/
template <typename _ENTRY_T>
class Double_list
{
private:
_ENTRY_T * _head;
_ENTRY_T * _tail;
public:
/**
* Provide 'Double_list'-entry compliance by inheritance
*/
class Entry
{
friend class Double_list<_ENTRY_T>;
private:
_ENTRY_T * _next;
_ENTRY_T * _prev;
Double_list<_ENTRY_T> * _list;
public:
/**
* Constructor
*/
Entry() : _next(0), _prev(0), _list(0) { }
/***************
** Accessors **
***************/
_ENTRY_T * next() const { return _next; }
_ENTRY_T * prev() const { return _prev; }
};
public:
/**
* Constructor
*
* Start with an empty list.
*/
Double_list(): _head(0), _tail(0) { }
/**
* Insert entry from behind into list
*/
void insert_tail(_ENTRY_T * const e)
{
/* avoid leaking lists */
if (e->Entry::_list)
e->Entry::_list->remove(e);
/* update new entry */
e->Entry::_prev = _tail;
e->Entry::_next = 0;
e->Entry::_list = this;
/* update previous entry or _head */
if (_tail) _tail->Entry::_next = e; /* List was not empty */
else _head = e; /* List was empty */
_tail = e;
}
/**
* Remove specific entry from list
*/
void remove(_ENTRY_T * const e)
{
/* sanity checks */
if (!_head || e->Entry::_list != this) return;
/* update next entry or _tail */
if (e != _tail) e->Entry::_next->Entry::_prev = e->Entry::_prev;
else _tail = e->Entry::_prev;
/* update previous entry or _head */
if (e != _head) e->Entry::_prev->Entry::_next = e->Entry::_next;
else _head = e->Entry::_next;
/* update removed entry */
e->Entry::_list = 0;
}
/**
* Remove head from list and return it
*/
_ENTRY_T * remove_head()
{
/* sanity checks */
if (!_head) return 0;
/* update _head */
_ENTRY_T * const e = _head;
_head = e->Entry::_next;
/* update next entry or _tail */
if (_head) _head->Entry::_prev = 0;
else _tail = 0;
/* update removed entry */
e->Entry::_list = 0;
return e;
}
/**
* Remove head from list and insert it at the end
*/
void head_to_tail()
{
/* sanity checks */
if (!_head || _head == _tail) return;
/* remove entry */
_ENTRY_T * const e = _head;
_head = _head->Entry::_next;
e->Entry::_next = 0;
_head->Entry::_prev = 0;
/* insert entry */
_tail->Entry::_next = e;
e->Entry::_prev = _tail;
_tail = e;
}
/***************
** Accessors **
***************/
_ENTRY_T * head() const { return _head; }
_ENTRY_T * tail() const { return _tail; }
};
/**
* Simple round robin scheduler for 'ENTRY_T' typed clients
*/
template <typename ENTRY_T>
class Scheduler
{
public:
/**
* Provides schedulability through inheritance
*/
class Entry : public Double_list<ENTRY_T>::Entry { };
protected:
/* gets scheduled when '_entries' is empty */
ENTRY_T * const _idle;
/* scheduling participants beside '_idle' */
Double_list<ENTRY_T> _entries;
public:
/**
* Constructor
*/
Scheduler(ENTRY_T * const idle)
: _idle(idle) { assert(_idle); }
/**
* Get currently scheduled entry
*/
ENTRY_T * head() const {
return _entries.head() ? _entries.head() : _idle; }
/**
* End turn of currently scheduled entry
*/
void yield() { _entries.head_to_tail(); }
/**
* Include 'e' in scheduling
*/
void insert(ENTRY_T * const e)
{
if (e == _idle) return;
_entries.insert_tail(e);
}
/**
* Exclude 'e' from scheduling
*/
void remove(ENTRY_T * const e) { _entries.remove(e); }
};
class Schedule_context;
typedef Scheduler<Schedule_context> Cpu_scheduler;
/**
* Kernel object that can be scheduled for the CPU
*/
class Schedule_context : public Cpu_scheduler::Entry
class Schedule_context : public Cpu_scheduler::Item
{
public: