parent
a753b6ce46
commit
eef7b5e168
|
@ -52,7 +52,6 @@ SRC_CC += pager.cc
|
||||||
SRC_CC += _main.cc
|
SRC_CC += _main.cc
|
||||||
SRC_CC += kernel/cpu.cc
|
SRC_CC += kernel/cpu.cc
|
||||||
SRC_CC += kernel/cpu_scheduler.cc
|
SRC_CC += kernel/cpu_scheduler.cc
|
||||||
SRC_CC += kernel/double_list.cc
|
|
||||||
SRC_CC += kernel/init.cc
|
SRC_CC += kernel/init.cc
|
||||||
SRC_CC += kernel/ipc_node.cc
|
SRC_CC += kernel/ipc_node.cc
|
||||||
SRC_CC += kernel/irq.cc
|
SRC_CC += kernel/irq.cc
|
||||||
|
|
|
@ -18,14 +18,14 @@
|
||||||
using namespace Kernel;
|
using namespace Kernel;
|
||||||
|
|
||||||
|
|
||||||
void Cpu_scheduler::_reset(Claim * const c) {
|
void Cpu_scheduler::_reset(Claim &c) {
|
||||||
_share(c)->_claim = _share(c)->_quota; }
|
_share(&c)->_claim = _share(&c)->_quota; }
|
||||||
|
|
||||||
|
|
||||||
void Cpu_scheduler::_reset_claims(unsigned const p)
|
void Cpu_scheduler::_reset_claims(unsigned const p)
|
||||||
{
|
{
|
||||||
_rcl[p].for_each([&] (Claim * const c) { _reset(c); });
|
_rcl[p].for_each([&] (Claim &c) { _reset(c); });
|
||||||
_ucl[p].for_each([&] (Claim * const c) { _reset(c); });
|
_ucl[p].for_each([&] (Claim &c) { _reset(c); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,12 +30,22 @@ namespace Kernel
|
||||||
/**
|
/**
|
||||||
* Scheduling context that has quota and priority (low-latency)
|
* 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)
|
* 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
|
* Scheduling context that is both claim and fill
|
||||||
|
@ -114,12 +124,12 @@ class Kernel::Cpu_scheduler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef Cpu_share Share;
|
typedef Cpu_share Share;
|
||||||
typedef Cpu_fill Fill;
|
typedef Cpu_fill Fill;
|
||||||
typedef Cpu_claim Claim;
|
typedef Cpu_claim Claim;
|
||||||
typedef Double_list_typed<Claim> Claim_list;
|
typedef Double_list<Claim> Claim_list;
|
||||||
typedef Double_list_typed<Fill> Fill_list;
|
typedef Double_list<Fill> Fill_list;
|
||||||
typedef Cpu_priority Prio;
|
typedef Cpu_priority Prio;
|
||||||
|
|
||||||
Claim_list _rcl[Prio::MAX + 1]; /* ready claims */
|
Claim_list _rcl[Prio::MAX + 1]; /* ready claims */
|
||||||
Claim_list _ucl[Prio::MAX + 1]; /* unready claims */
|
Claim_list _ucl[Prio::MAX + 1]; /* unready claims */
|
||||||
|
@ -141,7 +151,7 @@ class Kernel::Cpu_scheduler
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static Share * _share(T * const t) { return static_cast<Share *>(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 _reset_claims(unsigned const p);
|
||||||
void _next_round();
|
void _next_round();
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -19,78 +19,130 @@ namespace Kernel
|
||||||
/**
|
/**
|
||||||
* Ability to be an item in a double connected list
|
* Ability to be an item in a double connected list
|
||||||
*/
|
*/
|
||||||
|
template <typename T>
|
||||||
class Double_list_item;
|
class Double_list_item;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of double connected items
|
* List of double connected items
|
||||||
*/
|
*/
|
||||||
|
template <typename T>
|
||||||
class Double_list;
|
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
|
class Kernel::Double_list_item
|
||||||
{
|
{
|
||||||
friend class Double_list;
|
friend class Double_list<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Double_list_item * _next = nullptr;
|
Double_list_item * _next = nullptr;
|
||||||
Double_list_item * _prev = 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
|
class Kernel::Double_list
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef Double_list_item Item;
|
typedef Double_list_item<T> Item;
|
||||||
|
|
||||||
Item * _head;
|
Item * _head;
|
||||||
Item * _tail;
|
Item * _tail;
|
||||||
|
|
||||||
void _connect_neighbors(Item * const i);
|
void _connect_neighbors(Item * const i)
|
||||||
void _to_tail(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:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct empty list
|
* Construct empty list
|
||||||
*/
|
*/
|
||||||
Double_list();
|
Double_list() : _head(0), _tail(0) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move item 'i' from its current list position to the tail
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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
|
* Call function 'f' of type 'void (Item *)' for each item in the list
|
||||||
*/
|
*/
|
||||||
template <typename F> void for_each(F f) {
|
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
|
* Accessors
|
||||||
|
@ -100,30 +152,4 @@ class Kernel::Double_list
|
||||||
static Item * next(Item * const i) { return i->_next; }
|
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_ */
|
#endif /* _CORE__KERNEL__DOUBLE_LIST_H_ */
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
TARGET = test-cpu_scheduler
|
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
|
INC_DIR += $(REP_DIR)/src/core $(REP_DIR)/src/include $(BASE_DIR)/src/include
|
||||||
LIBS = base
|
LIBS = base
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
TARGET = test-double_list
|
TARGET = test-double_list
|
||||||
INC_DIR = $(REP_DIR)/src/core
|
INC_DIR = $(REP_DIR)/src/core
|
||||||
SRC_CC = test.cc double_list.cc
|
SRC_CC = test.cc
|
||||||
LIBS = base
|
LIBS = base
|
||||||
|
|
||||||
vpath double_list.cc $(REP_DIR)/src/core/kernel
|
vpath double_list.cc $(REP_DIR)/src/core/kernel
|
||||||
|
|
|
@ -24,18 +24,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using Genode::size_t;
|
using Genode::size_t;
|
||||||
using Kernel::Double_list_typed;
|
using Kernel::Double_list;
|
||||||
using Kernel::Double_list_item;
|
using Kernel::Double_list_item;
|
||||||
|
|
||||||
void * operator new(__SIZE_TYPE__, void * p) { return p; }
|
void * operator new(__SIZE_TYPE__, void * p) { return p; }
|
||||||
|
|
||||||
struct Item_load { char volatile x = 0, y = 0, z = 0; };
|
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;
|
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); }
|
void iteration() { Genode::log(_id); }
|
||||||
};
|
};
|
||||||
|
@ -44,7 +44,7 @@ struct Data
|
||||||
{
|
{
|
||||||
static constexpr unsigned nr_of_items = 9;
|
static constexpr unsigned nr_of_items = 9;
|
||||||
|
|
||||||
Double_list_typed<Item> list { };
|
Double_list<Item> list { };
|
||||||
char items[nr_of_items][sizeof(Item)];
|
char items[nr_of_items][sizeof(Item)];
|
||||||
|
|
||||||
Data()
|
Data()
|
||||||
|
@ -68,24 +68,27 @@ void done()
|
||||||
|
|
||||||
void check(unsigned i1, unsigned l)
|
void check(unsigned i1, unsigned l)
|
||||||
{
|
{
|
||||||
Item * const i2 = data()->list.head();
|
Double_list_item<Item> * const li2 = data()->list.head();
|
||||||
if (i1 && i2) {
|
if (li2) {
|
||||||
if(i1 == i2->_id) { return; }
|
Item * const i2 = &li2->payload();
|
||||||
Genode::log("head ", i2->_id, " in line ", l);
|
if (i1) {
|
||||||
done();
|
if(i1 == i2->_id) { return; }
|
||||||
} else if (i1 && !i2) {
|
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);
|
Genode::log("empty in line ", l);
|
||||||
done();
|
done();
|
||||||
} else if (!i1 && i2){
|
|
||||||
Genode::log("non-empty ", i2->_id, " in line ", l);
|
|
||||||
done();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_each()
|
void print_each()
|
||||||
{
|
{
|
||||||
Genode::log("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) {
|
Item * item(unsigned const i) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user