mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 23:42:32 +00:00
hw: replace double_list implementation
Replace double linked list by normal Genode::List with an additional pointer to last list member to efficiently handle the scheduler share lists. Moreover, move it into the private part of the Cpu_scheduler class, the only scope where it is used anymore. Ref genodelabs/genode#5115
This commit is contained in:
parent
0055438257
commit
8e2c95e5e4
@ -1,56 +0,0 @@
|
|||||||
build { core init lib/ld test/double_list }
|
|
||||||
|
|
||||||
create_boot_directory
|
|
||||||
|
|
||||||
install_config {
|
|
||||||
<config>
|
|
||||||
<parent-provides>
|
|
||||||
<service name="LOG"/>
|
|
||||||
<service name="RM"/>
|
|
||||||
<service name="PD"/>
|
|
||||||
<service name="CPU"/>
|
|
||||||
<service name="ROM"/>
|
|
||||||
</parent-provides>
|
|
||||||
<default-route>
|
|
||||||
<any-service> <parent/> </any-service>
|
|
||||||
</default-route>
|
|
||||||
<start name="test-double_list" caps="100">
|
|
||||||
<resource name="RAM" quantum="10M"/>
|
|
||||||
</start>
|
|
||||||
</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
|
|
||||||
}
|
|
@ -82,7 +82,7 @@ void Cpu_scheduler::_head_claimed(unsigned const r)
|
|||||||
|
|
||||||
void Cpu_scheduler::_head_filled(unsigned const r)
|
void Cpu_scheduler::_head_filled(unsigned const r)
|
||||||
{
|
{
|
||||||
if (_fills.head() != &_head->_fill_item)
|
if (_fills.head() != _head)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (r)
|
if (r)
|
||||||
@ -98,17 +98,15 @@ bool Cpu_scheduler::_claim_for_head()
|
|||||||
{
|
{
|
||||||
bool result { false };
|
bool result { false };
|
||||||
_for_each_prio([&] (Cpu_priority const p, bool &cancel_for_each_prio) {
|
_for_each_prio([&] (Cpu_priority const p, bool &cancel_for_each_prio) {
|
||||||
Double_list_item<Cpu_share> *const item { _rcl[p].head() };
|
Cpu_share* const share = _rcl[p].head();
|
||||||
|
|
||||||
if (!item)
|
if (!share)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Cpu_share &share { item->payload() };
|
if (!share->_claim)
|
||||||
|
|
||||||
if (!share._claim)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_set_head(share, share._claim, 1);
|
_set_head(*share, share->_claim, 1);
|
||||||
result = true;
|
result = true;
|
||||||
cancel_for_each_prio = true;
|
cancel_for_each_prio = true;
|
||||||
});
|
});
|
||||||
@ -118,12 +116,11 @@ bool Cpu_scheduler::_claim_for_head()
|
|||||||
|
|
||||||
bool Cpu_scheduler::_fill_for_head()
|
bool Cpu_scheduler::_fill_for_head()
|
||||||
{
|
{
|
||||||
Double_list_item<Cpu_share> *const item { _fills.head() };
|
Cpu_share *const share = _fills.head();
|
||||||
if (!item)
|
if (!share)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Share &share = item->payload();
|
_set_head(*share, share->_fill, 0);
|
||||||
_set_head(share, share._fill, 0);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Schedules CPU shares for the execution time of a CPU
|
* \brief Schedules CPU shares for the execution time of a CPU
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2014-10-09
|
* \date 2014-10-09
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -16,9 +17,9 @@
|
|||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
#include <util/list.h>
|
||||||
#include <util/misc_math.h>
|
#include <util/misc_math.h>
|
||||||
#include <kernel/configuration.h>
|
#include <kernel/configuration.h>
|
||||||
#include <kernel/double_list.h>
|
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
@ -90,13 +91,15 @@ class Kernel::Cpu_share
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Double_list_item<Cpu_share> _fill_item { *this };
|
using List_element = Genode::List_element<Cpu_share>;
|
||||||
Double_list_item<Cpu_share> _claim_item { *this };
|
|
||||||
Cpu_priority const _prio;
|
List_element _fill_item { this };
|
||||||
unsigned _quota;
|
List_element _claim_item { this };
|
||||||
unsigned _claim;
|
Cpu_priority const _prio;
|
||||||
unsigned _fill { 0 };
|
unsigned _quota;
|
||||||
bool _ready { false };
|
unsigned _claim;
|
||||||
|
unsigned _fill { 0 };
|
||||||
|
bool _ready { false };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -123,22 +126,89 @@ class Kernel::Cpu_scheduler
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
class Share_list
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
using List_element = Genode::List_element<Cpu_share>;
|
||||||
|
|
||||||
|
Genode::List<List_element> _list {};
|
||||||
|
List_element *_last { nullptr };
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
template <typename F> void for_each(F const &fn)
|
||||||
|
{
|
||||||
|
for (List_element * le = _list.first(); le; le = le->next())
|
||||||
|
fn(*le->object());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F> 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_share Share;
|
||||||
typedef Cpu_priority Prio;
|
typedef Cpu_priority Prio;
|
||||||
|
|
||||||
Double_list<Cpu_share> _rcl[Prio::max() + 1]; /* ready claims */
|
Share_list _rcl[Prio::max() + 1]; /* ready claims */
|
||||||
Double_list<Cpu_share> _ucl[Prio::max() + 1]; /* unready claims */
|
Share_list _ucl[Prio::max() + 1]; /* unready claims */
|
||||||
Double_list<Cpu_share> _fills { }; /* ready fills */
|
Share_list _fills { }; /* ready fills */
|
||||||
Share &_idle;
|
Share &_idle;
|
||||||
Share *_head = nullptr;
|
Share *_head = nullptr;
|
||||||
unsigned _head_quota = 0;
|
unsigned _head_quota = 0;
|
||||||
bool _head_claims = false;
|
bool _head_claims = false;
|
||||||
bool _head_yields = false;
|
bool _head_yields = false;
|
||||||
unsigned const _quota;
|
unsigned const _quota;
|
||||||
unsigned _residual;
|
unsigned _residual;
|
||||||
unsigned const _fill;
|
unsigned const _fill;
|
||||||
bool _need_to_schedule { true };
|
bool _need_to_schedule { true };
|
||||||
time_t _last_time { 0 };
|
time_t _last_time { 0 };
|
||||||
|
|
||||||
template <typename F> void _for_each_prio(F f)
|
template <typename F> void _for_each_prio(F f)
|
||||||
{
|
{
|
||||||
|
@ -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 <typename T>
|
|
||||||
class Double_list_item;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of double connected items
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
class Double_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class Kernel::Double_list_item
|
|
||||||
{
|
|
||||||
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<T> 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 <typename F> 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_ */
|
|
@ -27,11 +27,10 @@ namespace Cpu_scheduler_test {
|
|||||||
class Cpu_scheduler;
|
class Cpu_scheduler;
|
||||||
class Main;
|
class Main;
|
||||||
|
|
||||||
|
using Share_list = List<List_element<Cpu_share>>;
|
||||||
static Cpu_share &cast(Kernel::Cpu_share &share);
|
static Cpu_share &cast(Kernel::Cpu_share &share);
|
||||||
|
|
||||||
static Cpu_share const &cast(Kernel::Cpu_share const &share);
|
static Cpu_share const &cast(Kernel::Cpu_share const &share);
|
||||||
|
|
||||||
static Double_list<Kernel::Cpu_share> &cast(Double_list<Kernel::Cpu_share> const &list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -255,13 +254,6 @@ Cpu_scheduler_test::cast(Kernel::Cpu_share const &share)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Double_list<Kernel::Cpu_share> &
|
|
||||||
Cpu_scheduler_test::cast(Double_list<Kernel::Cpu_share> const &list)
|
|
||||||
{
|
|
||||||
return *const_cast<Double_list<Kernel::Cpu_share> *>(&list);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
** Cpu_scheduler_test::Cpu_scheduler **
|
** Cpu_scheduler_test::Cpu_scheduler **
|
||||||
***************************************/
|
***************************************/
|
||||||
@ -308,7 +300,7 @@ void Cpu_scheduler_test::Cpu_scheduler::print(Output &output) const
|
|||||||
|
|
||||||
print(output, " ready: ");
|
print(output, " ready: ");
|
||||||
bool first_share { true };
|
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 (&share == _head && _head_claims) {
|
||||||
if (_need_to_schedule) {
|
if (_need_to_schedule) {
|
||||||
@ -331,7 +323,7 @@ void Cpu_scheduler_test::Cpu_scheduler::print(Output &output) const
|
|||||||
|
|
||||||
print(output, " unready: ");
|
print(output, " unready: ");
|
||||||
bool first_share { true };
|
bool first_share { true };
|
||||||
cast(_ucl[prio]).for_each([&] (Kernel::Cpu_share const &share) {
|
_ucl[prio].for_each([&] (Kernel::Cpu_share const &share) {
|
||||||
|
|
||||||
print(
|
print(
|
||||||
output, first_share ? "" : ", ", cast(share).label() , "-",
|
output, first_share ? "" : ", ", cast(share).label() , "-",
|
||||||
@ -348,7 +340,7 @@ void Cpu_scheduler_test::Cpu_scheduler::print(Output &output) const
|
|||||||
|
|
||||||
print(output, "\n fills: ");
|
print(output, "\n fills: ");
|
||||||
bool first_share { true };
|
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 (&share == _head && !_head_claims) {
|
||||||
if (_need_to_schedule) {
|
if (_need_to_schedule) {
|
||||||
|
@ -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
|
|
@ -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 <util/construct_at.h>
|
|
||||||
#include <base/component.h>
|
|
||||||
#include <base/log.h>
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <kernel/double_list.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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<Item>
|
|
||||||
{
|
|
||||||
unsigned _id;
|
|
||||||
|
|
||||||
Item(unsigned const id) : Double_list_item<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<Item> list { };
|
|
||||||
char items[nr_of_items][sizeof(Item)];
|
|
||||||
|
|
||||||
Data()
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < nr_of_items; i++) {
|
|
||||||
Genode::construct_at<Item>(&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<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<Item *>(&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
|
|
||||||
* '<ops> C(i) <doc>' 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();
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user