base-hw: double list without inheritance

Ref #3308
This commit is contained in:
Martin Stein 2019-12-23 23:01:20 +01:00 committed by Christian Helmuth
parent a753b6ce46
commit eef7b5e168
8 changed files with 110 additions and 158 deletions

View File

@ -52,7 +52,6 @@ SRC_CC += pager.cc
SRC_CC += _main.cc
SRC_CC += kernel/cpu.cc
SRC_CC += kernel/cpu_scheduler.cc
SRC_CC += kernel/double_list.cc
SRC_CC += kernel/init.cc
SRC_CC += kernel/ipc_node.cc
SRC_CC += kernel/irq.cc

View File

@ -18,14 +18,14 @@
using namespace Kernel;
void Cpu_scheduler::_reset(Claim * const c) {
_share(c)->_claim = _share(c)->_quota; }
void Cpu_scheduler::_reset(Claim &c) {
_share(&c)->_claim = _share(&c)->_quota; }
void Cpu_scheduler::_reset_claims(unsigned const p)
{
_rcl[p].for_each([&] (Claim * const c) { _reset(c); });
_ucl[p].for_each([&] (Claim * const c) { _reset(c); });
_rcl[p].for_each([&] (Claim &c) { _reset(c); });
_ucl[p].for_each([&] (Claim &c) { _reset(c); });
}

View File

@ -30,12 +30,22 @@ namespace Kernel
/**
* Scheduling context that has quota and priority (low-latency)
*/
class Cpu_claim : public Double_list_item { };
class Cpu_claim : public Double_list_item<Cpu_claim> {
public:
Cpu_claim() : Double_list_item<Cpu_claim>(*this) {}
};
/**
* Scheduling context that has no quota or priority (best effort)
*/
class Cpu_fill : public Double_list_item { };
class Cpu_fill : public Double_list_item<Cpu_fill> {
public:
Cpu_fill() : Double_list_item<Cpu_fill>(*this) {}
};
/**
* Scheduling context that is both claim and fill
@ -114,12 +124,12 @@ class Kernel::Cpu_scheduler
{
private:
typedef Cpu_share Share;
typedef Cpu_fill Fill;
typedef Cpu_claim Claim;
typedef Double_list_typed<Claim> Claim_list;
typedef Double_list_typed<Fill> Fill_list;
typedef Cpu_priority Prio;
typedef Cpu_share Share;
typedef Cpu_fill Fill;
typedef Cpu_claim Claim;
typedef Double_list<Claim> Claim_list;
typedef Double_list<Fill> Fill_list;
typedef Cpu_priority Prio;
Claim_list _rcl[Prio::MAX + 1]; /* ready claims */
Claim_list _ucl[Prio::MAX + 1]; /* unready claims */
@ -141,7 +151,7 @@ class Kernel::Cpu_scheduler
template <typename T>
static Share * _share(T * const t) { return static_cast<Share *>(t); }
static void _reset(Claim * const c);
static void _reset(Claim &c);
void _reset_claims(unsigned const p);
void _next_round();

View File

@ -1,86 +0,0 @@
/*
* \brief List of double connected items
* \author Martin Stein
* \date 2012-11-30
*/
/*
* Copyright (C) 2012-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.
*/
/* core includes */
#include <kernel/double_list.h>
using namespace Kernel;
void Double_list::_connect_neighbors(Item * const i)
{
i->_prev->_next = i->_next;
i->_next->_prev = i->_prev;
}
void Double_list::_to_tail(Item * const i)
{
if (i == _tail) { return; }
_connect_neighbors(i);
i->_prev = _tail;
i->_next = 0;
_tail->_next = i;
_tail = i;
}
Double_list::Double_list(): _head(0), _tail(0) { }
void Double_list::to_tail(Item * const i)
{
if (i == _head) { head_to_tail(); }
else { _to_tail(i); }
}
void Double_list::insert_tail(Item * const i)
{
if (_tail) { _tail->_next = i; }
else { _head = i; }
i->_prev = _tail;
i->_next = 0;
_tail = i;
}
void Double_list::insert_head(Item * const i)
{
if (_head) { _head->_prev = i; }
else { _tail = i; }
i->_next = _head;
i->_prev = 0;
_head = i;
}
void Double_list::remove(Item * const i)
{
if (i == _tail) { _tail = i->_prev; }
else { i->_next->_prev = i->_prev; }
if (i == _head) { _head = i->_next; }
else { i->_prev->_next = i->_next; }
}
void Double_list::head_to_tail()
{
if (!_head || _head == _tail) { return; }
_head->_prev = _tail;
_tail->_next = _head;
_head = _head->_next;
_head->_prev = 0;
_tail = _tail->_next;
_tail->_next = 0;
}

View File

@ -19,78 +19,130 @@ namespace Kernel
/**
* Ability to be an item in a double connected list
*/
template <typename T>
class Double_list_item;
/**
* List of double connected items
*/
template <typename T>
class Double_list;
/**
* Double list over objects of type 'T' that inherits from double-list item
*/
template <typename T> class Double_list_typed;
}
template <typename T>
class Kernel::Double_list_item
{
friend class Double_list;
friend class Double_list<T>;
private:
Double_list_item * _next = nullptr;
Double_list_item * _prev = nullptr;
T & _payload;
public:
Double_list_item(T &payload) : _payload(payload) { }
T &payload() { return _payload; }
};
template <typename T>
class Kernel::Double_list
{
private:
typedef Double_list_item Item;
typedef Double_list_item<T> Item;
Item * _head;
Item * _tail;
void _connect_neighbors(Item * const i);
void _to_tail(Item * const i);
void _connect_neighbors(Item * const i)
{
i->_prev->_next = i->_next;
i->_next->_prev = i->_prev;
}
void _to_tail(Item * const i)
{
if (i == _tail) { return; }
_connect_neighbors(i);
i->_prev = _tail;
i->_next = 0;
_tail->_next = i;
_tail = i;
}
public:
/**
* Construct empty list
*/
Double_list();
Double_list() : _head(0), _tail(0) { }
/**
* Move item 'i' from its current list position to the tail
*/
void to_tail(Item * const i);
void to_tail(Item * const i)
{
if (i == _head) { head_to_tail(); }
else { _to_tail(i); }
}
/**
* Insert item 'i' as new tail into list
*/
void insert_tail(Item * const i);
void insert_tail(Item * const i)
{
if (_tail) { _tail->_next = i; }
else { _head = i; }
i->_prev = _tail;
i->_next = 0;
_tail = i;
}
/**
* Insert item 'i' as new head into list
*/
void insert_head(Item * const i);
void insert_head(Item * const i)
{
if (_head) { _head->_prev = i; }
else { _tail = i; }
i->_next = _head;
i->_prev = 0;
_head = i;
}
/**
* Remove item 'i' from list
*/
void remove(Item * const i);
void remove(Item * const i)
{
if (i == _tail) { _tail = i->_prev; }
else { i->_next->_prev = i->_prev; }
if (i == _head) { _head = i->_next; }
else { i->_prev->_next = i->_next; }
}
/**
* Move head item of list to tail position
*/
void head_to_tail();
void head_to_tail()
{
if (!_head || _head == _tail) { return; }
_head->_prev = _tail;
_tail->_next = _head;
_head = _head->_next;
_head->_prev = 0;
_tail = _tail->_next;
_tail->_next = 0;
}
/**
* Call function 'f' of type 'void (Item *)' for each item in the list
*/
template <typename F> void for_each(F f) {
for (Item * i = _head; i; i = i->_next) { f(i); } }
for (Item * i = _head; i; i = i->_next) { f(i->payload()); } }
/*
* Accessors
@ -100,30 +152,4 @@ class Kernel::Double_list
static Item * next(Item * const i) { return i->_next; }
};
template <typename T> class Kernel::Double_list_typed : public Double_list
{
private:
typedef Double_list_item Item;
static T * _typed(Item * const i) {
return i ? static_cast<T *>(i) : 0; }
public:
/*
* 'Double_list' interface
*/
template <typename F> void for_each(F f) {
Double_list::for_each([&] (Item * const i) { f(_typed(i)); }); }
void to_tail(T * const t) { Double_list::to_tail(t); }
void insert_tail(T * const t) { Double_list::insert_tail(t); }
void insert_head(T * const t) { Double_list::insert_head(t); }
void remove(T * const t) { Double_list::remove(t); }
static T * next(T * const t) { return _typed(Double_list::next(t)); }
T * head() const { return _typed(Double_list::head()); }
};
#endif /* _CORE__KERNEL__DOUBLE_LIST_H_ */

View File

@ -5,7 +5,7 @@
#
TARGET = test-cpu_scheduler
SRC_CC = test.cc cpu_scheduler.cc double_list.cc
SRC_CC = test.cc cpu_scheduler.cc
INC_DIR += $(REP_DIR)/src/core $(REP_DIR)/src/include $(BASE_DIR)/src/include
LIBS = base

View File

@ -6,7 +6,7 @@
TARGET = test-double_list
INC_DIR = $(REP_DIR)/src/core
SRC_CC = test.cc double_list.cc
SRC_CC = test.cc
LIBS = base
vpath double_list.cc $(REP_DIR)/src/core/kernel

View File

@ -24,18 +24,18 @@
*/
using Genode::size_t;
using Kernel::Double_list_typed;
using Kernel::Double_list;
using Kernel::Double_list_item;
void * operator new(__SIZE_TYPE__, void * p) { return p; }
struct Item_load { char volatile x = 0, y = 0, z = 0; };
struct Item : Item_load, Double_list_item
struct Item : Item_load, Double_list_item<Item>
{
unsigned _id;
Item(unsigned const id) : _id(id) { x = 1; y = 2; z = 3; }
Item(unsigned const id) : Double_list_item<Item>(*this), _id(id) { x = 1; y = 2; z = 3; }
void iteration() { Genode::log(_id); }
};
@ -44,7 +44,7 @@ struct Data
{
static constexpr unsigned nr_of_items = 9;
Double_list_typed<Item> list { };
Double_list<Item> list { };
char items[nr_of_items][sizeof(Item)];
Data()
@ -68,24 +68,27 @@ void done()
void check(unsigned i1, unsigned l)
{
Item * const i2 = data()->list.head();
if (i1 && i2) {
if(i1 == i2->_id) { return; }
Genode::log("head ", i2->_id, " in line ", l);
done();
} else if (i1 && !i2) {
Double_list_item<Item> * const li2 = data()->list.head();
if (li2) {
Item * const i2 = &li2->payload();
if (i1) {
if(i1 == i2->_id) { return; }
Genode::log("head ", i2->_id, " in line ", l);
done();
} else {
Genode::log("non-empty ", i2->_id, " in line ", l);
done();
}
} else if (i1) {
Genode::log("empty in line ", l);
done();
} else if (!i1 && i2){
Genode::log("non-empty ", i2->_id, " in line ", l);
done();
}
}
void print_each()
{
Genode::log("print each");
data()->list.for_each([] (Item * const i) { i->iteration(); });
data()->list.for_each([] (Item &i) { i.iteration(); });
}
Item * item(unsigned const i) {