mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-20 06:07:59 +00:00
parent
4a1c218fd0
commit
2c357a4f04
195
base-hw/src/core/kernel/scheduler.h
Normal file
195
base-hw/src/core/kernel/scheduler.h
Normal 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_ */
|
@ -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:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user