diff --git a/repos/base-hw/run/double_list.run b/repos/base-hw/run/double_list.run
deleted file mode 100644
index 56dc6176f3..0000000000
--- a/repos/base-hw/run/double_list.run
+++ /dev/null
@@ -1,56 +0,0 @@
-build { core init lib/ld test/double_list }
-
-create_boot_directory
-
-install_config {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-}
-
-build_boot_image [build_artifacts]
-
-append qemu_args " -nographic"
-
-run_genode_until "done.*\n" 10
-
-grep_output {\[init -> test-double_list\]}
-compare_output_to {
- [init -> test-double_list] print each
- [init -> test-double_list] print each
- [init -> test-double_list] 1
- [init -> test-double_list] print each
- [init -> test-double_list] 3
- [init -> test-double_list] 2
- [init -> test-double_list] 5
- [init -> test-double_list] 7
- [init -> test-double_list] 6
- [init -> test-double_list] 4
- [init -> test-double_list] 1
- [init -> test-double_list] print each
- [init -> test-double_list] 8
- [init -> test-double_list] 9
- [init -> test-double_list] 2
- [init -> test-double_list] 5
- [init -> test-double_list] 1
- [init -> test-double_list] 7
- [init -> test-double_list] 6
- [init -> test-double_list] 4
- [init -> test-double_list] 3
- [init -> test-double_list] print each
- [init -> test-double_list] 7
- [init -> test-double_list] 8
- [init -> test-double_list] done
-}
diff --git a/repos/base-hw/src/core/kernel/cpu_scheduler.cc b/repos/base-hw/src/core/kernel/cpu_scheduler.cc
index 03ef6b50ef..8cf4ab3452 100644
--- a/repos/base-hw/src/core/kernel/cpu_scheduler.cc
+++ b/repos/base-hw/src/core/kernel/cpu_scheduler.cc
@@ -82,7 +82,7 @@ void Cpu_scheduler::_head_claimed(unsigned const r)
void Cpu_scheduler::_head_filled(unsigned const r)
{
- if (_fills.head() != &_head->_fill_item)
+ if (_fills.head() != _head)
return;
if (r)
@@ -98,17 +98,15 @@ bool Cpu_scheduler::_claim_for_head()
{
bool result { false };
_for_each_prio([&] (Cpu_priority const p, bool &cancel_for_each_prio) {
- Double_list_item *const item { _rcl[p].head() };
+ Cpu_share* const share = _rcl[p].head();
- if (!item)
+ if (!share)
return;
- Cpu_share &share { item->payload() };
-
- if (!share._claim)
+ if (!share->_claim)
return;
- _set_head(share, share._claim, 1);
+ _set_head(*share, share->_claim, 1);
result = true;
cancel_for_each_prio = true;
});
@@ -118,12 +116,11 @@ bool Cpu_scheduler::_claim_for_head()
bool Cpu_scheduler::_fill_for_head()
{
- Double_list_item *const item { _fills.head() };
- if (!item)
+ Cpu_share *const share = _fills.head();
+ if (!share)
return false;
- Share &share = item->payload();
- _set_head(share, share._fill, 0);
+ _set_head(*share, share->_fill, 0);
return true;
}
diff --git a/repos/base-hw/src/core/kernel/cpu_scheduler.h b/repos/base-hw/src/core/kernel/cpu_scheduler.h
index d5c2e9934d..b6e1ae83b3 100644
--- a/repos/base-hw/src/core/kernel/cpu_scheduler.h
+++ b/repos/base-hw/src/core/kernel/cpu_scheduler.h
@@ -1,6 +1,7 @@
/*
* \brief Schedules CPU shares for the execution time of a CPU
* \author Martin Stein
+ * \author Stefan Kalkowski
* \date 2014-10-09
*/
@@ -16,9 +17,9 @@
/* core includes */
#include
+#include
#include
#include
-#include
namespace Kernel {
@@ -90,13 +91,15 @@ class Kernel::Cpu_share
private:
- Double_list_item _fill_item { *this };
- Double_list_item _claim_item { *this };
- Cpu_priority const _prio;
- unsigned _quota;
- unsigned _claim;
- unsigned _fill { 0 };
- bool _ready { false };
+ using List_element = Genode::List_element;
+
+ List_element _fill_item { this };
+ List_element _claim_item { this };
+ Cpu_priority const _prio;
+ unsigned _quota;
+ unsigned _claim;
+ unsigned _fill { 0 };
+ bool _ready { false };
public:
@@ -123,22 +126,89 @@ class Kernel::Cpu_scheduler
private:
+ class Share_list
+ {
+ private:
+
+ using List_element = Genode::List_element;
+
+ Genode::List _list {};
+ List_element *_last { nullptr };
+
+ public:
+
+ template void for_each(F const &fn)
+ {
+ for (List_element * le = _list.first(); le; le = le->next())
+ fn(*le->object());
+ }
+
+ template void for_each(F const &fn) const
+ {
+ for (List_element const * le = _list.first(); le;
+ le = le->next()) fn(*le->object());
+ }
+
+ Cpu_share* head() const {
+ return _list.first() ? _list.first()->object() : nullptr; }
+
+ void insert_head(List_element * const le)
+ {
+ _list.insert(le);
+ if (!_last) _last = le;
+ }
+
+ void insert_tail(List_element * const le)
+ {
+ _list.insert(le, _last);
+ _last = le;
+ }
+
+ void remove(List_element * const le)
+ {
+ _list.remove(le);
+
+ if (_last != le)
+ return;
+
+ _last = nullptr;
+ for (List_element * le = _list.first(); le; le = le->next())
+ _last = le;
+ }
+
+
+ void to_tail(List_element * const le)
+ {
+ remove(le);
+ insert_tail(le);
+ }
+
+ void to_head(List_element * const le)
+ {
+ remove(le);
+ insert_head(le);
+ }
+
+ void head_to_tail() {
+ to_tail(_list.first()); }
+ };
+
typedef Cpu_share Share;
typedef Cpu_priority Prio;
- Double_list _rcl[Prio::max() + 1]; /* ready claims */
- Double_list _ucl[Prio::max() + 1]; /* unready claims */
- Double_list _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 };
+ Share_list _rcl[Prio::max() + 1]; /* ready claims */
+ Share_list _ucl[Prio::max() + 1]; /* unready claims */
+ Share_list _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 void _for_each_prio(F f)
{
diff --git a/repos/base-hw/src/core/kernel/double_list.h b/repos/base-hw/src/core/kernel/double_list.h
deleted file mode 100644
index ec580f9823..0000000000
--- a/repos/base-hw/src/core/kernel/double_list.h
+++ /dev/null
@@ -1,192 +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.
- */
-
-#ifndef _CORE__KERNEL__DOUBLE_LIST_H_
-#define _CORE__KERNEL__DOUBLE_LIST_H_
-
-namespace Kernel {
-
- /**
- * Ability to be an item in a double connected list
- */
- template
- class Double_list_item;
-
- /**
- * List of double connected items
- */
- template
- class Double_list;
-}
-
-
-template
-class Kernel::Double_list_item
-{
- friend class Double_list;
-
- 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
-class Kernel::Double_list
-{
- private:
-
- typedef Double_list_item Item;
-
- Item * _head;
- Item * _tail;
-
- 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;
- }
-
- void _to_head(Item * const i)
- {
- if (i == _head)
- return;
-
- _connect_neighbors(i);
- i->_next = _head;
- i->_prev = 0;
- _head->_prev = i;
- _head = i;
- }
-
- void _tail_to_head()
- {
- if (_tail == 0 || _tail == _head)
- return;
-
- _tail->_next = _head;
- _head->_prev = _tail;
- _tail = _tail->_prev;
- _tail->_next = 0;
- _head = _head->_prev;
- _head->_prev = 0;
- }
-
- public:
-
- /**
- * Construct empty list
- */
- Double_list() : _head(0), _tail(0) { }
-
- /**
- * Move item 'i' from its current list position to the tail
- */
- void to_tail(Item * const i)
- {
- if (i == _head) { head_to_tail(); }
- else { _to_tail(i); }
- }
-
- void to_head(Item * const i)
- {
- if (i == _tail)
- _tail_to_head();
- else
- _to_head(i);
- }
-
- /**
- * Insert item 'i' as new tail into list
- */
- 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)
- {
- 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)
- {
- 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()
- {
- 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 void for_each(F f) {
- for (Item * i = _head; i; i = i->_next) { f(i->payload()); } }
-
- /*
- * Accessors
- */
-
- Item * head() const { return _head; }
- static Item * next(Item * const i) { return i->_next; }
-};
-
-#endif /* _CORE__KERNEL__DOUBLE_LIST_H_ */
diff --git a/repos/base-hw/src/test/cpu_scheduler/main.cc b/repos/base-hw/src/test/cpu_scheduler/main.cc
index d6c8e87d00..1b2829d0e4 100644
--- a/repos/base-hw/src/test/cpu_scheduler/main.cc
+++ b/repos/base-hw/src/test/cpu_scheduler/main.cc
@@ -27,11 +27,10 @@ namespace Cpu_scheduler_test {
class Cpu_scheduler;
class Main;
+ using Share_list = List>;
static Cpu_share &cast(Kernel::Cpu_share &share);
static Cpu_share const &cast(Kernel::Cpu_share const &share);
-
- static Double_list &cast(Double_list const &list);
}
@@ -255,13 +254,6 @@ Cpu_scheduler_test::cast(Kernel::Cpu_share const &share)
}
-static Double_list &
-Cpu_scheduler_test::cast(Double_list const &list)
-{
- return *const_cast *>(&list);
-}
-
-
/***************************************
** Cpu_scheduler_test::Cpu_scheduler **
***************************************/
@@ -308,7 +300,7 @@ void Cpu_scheduler_test::Cpu_scheduler::print(Output &output) const
print(output, " ready: ");
bool first_share { true };
- cast(_rcl[prio]).for_each([&] (Kernel::Cpu_share const &share) {
+ _rcl[prio].for_each([&] (Kernel::Cpu_share const &share) {
if (&share == _head && _head_claims) {
if (_need_to_schedule) {
@@ -331,7 +323,7 @@ void Cpu_scheduler_test::Cpu_scheduler::print(Output &output) const
print(output, " unready: ");
bool first_share { true };
- cast(_ucl[prio]).for_each([&] (Kernel::Cpu_share const &share) {
+ _ucl[prio].for_each([&] (Kernel::Cpu_share const &share) {
print(
output, first_share ? "" : ", ", cast(share).label() , "-",
@@ -348,7 +340,7 @@ void Cpu_scheduler_test::Cpu_scheduler::print(Output &output) const
print(output, "\n fills: ");
bool first_share { true };
- cast(_fills).for_each([&] (Kernel::Cpu_share const &share) {
+ _fills.for_each([&] (Kernel::Cpu_share const &share) {
if (&share == _head && !_head_claims) {
if (_need_to_schedule) {
diff --git a/repos/base-hw/src/test/double_list/target.mk b/repos/base-hw/src/test/double_list/target.mk
deleted file mode 100644
index 5fc7acf945..0000000000
--- a/repos/base-hw/src/test/double_list/target.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# \brief Build config for a core that tests its double-list implementation
-# \author Martin Stein
-# \date 2011-12-16
-#
-
-TARGET = test-double_list
-INC_DIR = $(REP_DIR)/src/core
-SRC_CC = test.cc
-LIBS = base
-
-vpath double_list.cc $(REP_DIR)/src/core/kernel
diff --git a/repos/base-hw/src/test/double_list/test.cc b/repos/base-hw/src/test/double_list/test.cc
deleted file mode 100644
index ae88aeb153..0000000000
--- a/repos/base-hw/src/test/double_list/test.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * \brief Test double-list implementation of the kernel
- * \author Martin Stein
- * \date 2014-09-30
- */
-
-/*
- * 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.
- */
-
-/* base includes */
-#include
-#include
-#include
-
-/* core includes */
-#include
-
-
-/*
- * Utilities
- */
-
-using Genode::size_t;
-using Kernel::Double_list;
-using Kernel::Double_list_item;
-
-
-struct Item_load { char volatile x = 0, y = 0, z = 0; };
-
-
-struct Item : Item_load, Double_list_item-
-{
- unsigned _id;
-
- Item(unsigned const id) : Double_list_item
- (*this), _id(id) { x = 1; y = 2; z = 3; }
-
- void iteration() { Genode::log(_id); }
-};
-
-
-struct Data
-{
- static constexpr unsigned nr_of_items = 9;
-
- Double_list
- list { };
- char items[nr_of_items][sizeof(Item)];
-
- Data()
- {
- for (unsigned i = 0; i < nr_of_items; i++) {
- Genode::construct_at
- (&items[i], i + 1); }
- }
-};
-
-
-Data * data()
-{
- static Data d;
- return &d;
-}
-
-
-void done()
-{
- Genode::log("done");
- while (1) ;
-}
-
-
-void check(unsigned i1, unsigned l)
-{
- Double_list_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();
- }
-}
-
-
-void print_each()
-{
- Genode::log("print each");
- data()->list.for_each([] (Item &i) { i.iteration(); });
-}
-
-
-Item * item(unsigned const i) {
- return reinterpret_cast
- (&data()->items[i - 1]); }
-
-
-/*
- * Shortcuts for all basic operations that the test consists of
- */
-
-#define C(i) check(i, __LINE__);
-#define T(i) data()->list.insert_tail(item(i));
-#define H(i) data()->list.insert_head(item(i));
-#define R(i) data()->list.remove(item(i));
-#define B(i) data()->list.to_tail(item(i));
-#define P print_each();
-#define N data()->list.head_to_tail();
-
-
-/**
- * Main routine
- */
-void Component::construct(Genode::Env &)
-{
- /*
- * Step-by-step testing
- *
- * Every line in this test is structured according to the scheme
- * ' C(i) ' where the symbols are defined as follows:
- *
- * ops Operations that affect the list structure. These are:
- *
- * T(i) insert the item with ID 'i' as tail
- * H(i) insert the item with ID 'i' as head
- * R(i) remove the item with ID 'i'
- * B(i) move the item with ID 'i' to the tail
- * N move the head to the tail
- * P print IDs of the items in the list in their list order
- *
- * C(i) check if the item with ID 'i' is head
- *
- * doc Documents the expected list content for the point after the
- * operations in the corresponding line.
- *
- * If any check in a line fails, the test prematurely stops and prints out
- * where and why it has stopped.
- */
-
- C(0) /* */
- N C(0) /* */
- P C(0) /* */
- T(1) C(1) /* 1 */
- N C(1) /* 1 */
- P N C(1) /* 1 */
- B(1) C(1) /* 1 */
- N C(1) /* 1 */
- R(1) C(0) /* */
- N C(0) /* */
- N C(0) /* */
- H(2) C(2) /* 2 */
- N C(2) /* 2 */
- N C(2) /* 2 */
- T(3) C(2) /* 2 3 */
- N C(3) /* 3 2 */
- B(2) C(3) /* 3 2 */
- N C(2) /* 2 3 */
- H(4) C(4) /* 4 2 3 */
- N C(2) /* 2 3 4 */
- N C(3) /* 3 4 2 */
- N C(4) /* 4 2 3 */
- R(4) N C(3) /* 3 2 */
- N C(2) /* 2 3 */
- T(1) C(2) /* 2 3 1 */
- N C(3) /* 3 1 2 */
- N C(1) /* 1 2 3 */
- N C(2) /* 2 3 1 */
- N C(3) /* 3 1 2 */
- R(1) C(3) /* 3 2 */
- N C(2) /* 2 3 */
- N C(3) /* 3 2 */
- B(3) C(2) /* 2 3 */
- T(4) T(1) C(2) /* 2 3 4 1 */
- N N C(4) /* 4 1 2 3 */
- N C(1) /* 1 2 3 4 */
- N N C(3) /* 3 4 1 2 */
- R(2) C(3) /* 3 4 1 */
- R(3) C(4) /* 4 1 */
- N C(1) /* 1 4 */
- N N C(1) /* 1 4 */
- T(3) T(2) C(1) /* 1 4 3 2 */
- T(5) N C(4) /* 4 3 2 5 1 */
- T(7) H(6) C(6) /* 6 4 3 2 5 1 7 */
- N C(4) /* 4 3 2 5 1 7 6 */
- B(4) C(3) /* 3 2 5 1 7 6 4 */
- B(4) N N C(5) /* 5 1 7 6 4 3 2 */
- N B(7) N C(6) /* 6 4 3 2 5 7 1*/
- N N B(1) C(3) /* 3 2 5 7 6 4 1 */
- P C(3) /* 3 2 5 7 6 4 1 */
- R(4) H(4) C(4) /* 4 3 2 5 7 6 1 */
- B(7) B(6) C(4) /* 4 3 2 5 1 7 6 */
- N N N C(5) /* 5 1 7 6 4 3 2 */
- N N N C(6) /* 6 4 3 2 5 1 7 */
- N N N C(2) /* 2 5 1 7 6 4 3 */
- T(9) N N C(1) /* 1 7 6 4 3 9 2 5 */
- N N N N C(3) /* 3 9 2 5 1 7 6 4 */
- N N N N C(1) /* 1 7 6 4 3 9 2 5 */
- N N N C(4) /* 4 3 9 2 5 1 7 6 */
- N N C(9) /* 9 2 5 1 7 6 4 3 */
- H(8) P C(8) /* 8 9 2 5 1 7 6 4 3 */
- R(8) C(9) /* 9 2 5 1 7 6 4 3 */
- R(9) C(2) /* 2 5 1 7 6 4 3 */
- R(1) N N C(7) /* 7 6 4 3 2 5 */
- N R(6) N C(3) /* 3 2 5 7 4 */
- T(8) R(3) C(2) /* 2 5 7 4 8 */
- N N R(5) C(7) /* 7 4 8 2 */
- R(2) R(4) C(7) /* 7 8 */
- N C(8) /* 8 7 */
- N P C(7) /* 7 8 */
- R(7) C(8) /* 7 8 */
- R(8) C(0) /* */
- C(0) /* */
-
- done();
-}