mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-21 18:06:50 +00:00
nova: extent ec_ctrl in kernel and base-nova
The commit switches the kernel branch to r5 and updates the syscall bindings in base-nova accordingly. Beside some cleanups, r5 extents the ec_ctrl syscall to support following features: * An EC may yield its current timeslice. The timeslice gets enqueued at the end of the run queue without refreshing the left budget of the quantum. * An EC helps with the current SC another EC. Used in Genode to implement helping over a user-level lock to avoid live-lock situation. (Think of a limited priority-inheritance mechanism.) * An EC requests a new scheduler decision. Used in Genode to transfer back the potentially helping SC to the helper EC. Issue #986
This commit is contained in:
parent
617d5ee3e6
commit
ecaf09a41b
@ -9,7 +9,7 @@ VERBOSE ?= @
|
|||||||
ECHO = @echo
|
ECHO = @echo
|
||||||
GIT_URL = https://github.com/alex-ab/NOVA.git
|
GIT_URL = https://github.com/alex-ab/NOVA.git
|
||||||
GIT_REV = HEAD
|
GIT_REV = HEAD
|
||||||
GIT_BRANCH = r4
|
GIT_BRANCH = r5
|
||||||
CONTRIB_DIR = contrib
|
CONTRIB_DIR = contrib
|
||||||
PATCHES = $(shell find patches -name '*.patch')
|
PATCHES = $(shell find patches -name '*.patch')
|
||||||
|
|
||||||
|
@ -210,9 +210,9 @@ namespace Nova {
|
|||||||
|
|
||||||
|
|
||||||
ALWAYS_INLINE
|
ALWAYS_INLINE
|
||||||
inline uint8_t ec_ctrl(Ec_op op, unsigned para = ~0UL)
|
inline uint8_t ec_ctrl(Ec_op op, mword_t ec = ~0UL, mword_t para = ~0UL)
|
||||||
{
|
{
|
||||||
return syscall_0(NOVA_EC_CTRL, op, para);
|
return syscall_1(NOVA_EC_CTRL, op, ec, para);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -173,9 +173,9 @@ namespace Nova {
|
|||||||
|
|
||||||
|
|
||||||
ALWAYS_INLINE
|
ALWAYS_INLINE
|
||||||
inline uint8_t ec_ctrl(Ec_op op, mword_t ec = ~0UL)
|
inline uint8_t ec_ctrl(Ec_op op, mword_t ec = ~0UL, mword_t para = ~0UL)
|
||||||
{
|
{
|
||||||
return syscall_0(NOVA_EC_CTRL, op, ec);
|
return syscall_1(NOVA_EC_CTRL, op, ec, para);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ namespace Nova {
|
|||||||
/**
|
/**
|
||||||
* Ec operations
|
* Ec operations
|
||||||
*/
|
*/
|
||||||
enum Ec_op { EC_RECALL = 0U, EC_YIELD = 1U };
|
enum Ec_op { EC_RECALL = 0U, EC_YIELD = 1U, EC_DONATE_SC = 2U, EC_RESCHEDULE = 3U };
|
||||||
|
|
||||||
|
|
||||||
class Descriptor
|
class Descriptor
|
||||||
|
@ -1,116 +0,0 @@
|
|||||||
diff --git a/include/sc.hpp b/include/sc.hpp
|
|
||||||
index b849a1f..b480050 100644
|
|
||||||
--- a/include/sc.hpp
|
|
||||||
+++ b/include/sc.hpp
|
|
||||||
@@ -54,7 +54,7 @@ class Sc : public Kobject, public Refcount
|
|
||||||
|
|
||||||
static unsigned prio_top CPULOCAL;
|
|
||||||
|
|
||||||
- void ready_enqueue (uint64);
|
|
||||||
+ void ready_enqueue (uint64, bool use_left = true);
|
|
||||||
void ready_dequeue (uint64);
|
|
||||||
|
|
||||||
static void free (Rcu_elem * a) {
|
|
||||||
@@ -90,7 +90,7 @@ class Sc : public Kobject, public Refcount
|
|
||||||
static void rke_handler();
|
|
||||||
|
|
||||||
NORETURN
|
|
||||||
- static void schedule (bool = false);
|
|
||||||
+ static void schedule (bool = false, bool = true);
|
|
||||||
|
|
||||||
ALWAYS_INLINE
|
|
||||||
static inline void *operator new (size_t) { return cache.alloc(); }
|
|
||||||
diff --git a/include/syscall.hpp b/include/syscall.hpp
|
|
||||||
index 59e4489..5d61f1e 100644
|
|
||||||
--- a/include/syscall.hpp
|
|
||||||
+++ b/include/syscall.hpp
|
|
||||||
@@ -138,6 +138,9 @@ class Sys_ec_ctrl : public Sys_regs
|
|
||||||
public:
|
|
||||||
ALWAYS_INLINE
|
|
||||||
inline unsigned long ec() const { return ARG_1 >> 8; }
|
|
||||||
+
|
|
||||||
+ ALWAYS_INLINE
|
|
||||||
+ inline unsigned op() const { return flags() & 0x3; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class Sys_sc_ctrl : public Sys_regs
|
|
||||||
diff --git a/src/sc.cpp b/src/sc.cpp
|
|
||||||
index 53ff07b..bc4dfa2 100644
|
|
||||||
--- a/src/sc.cpp
|
|
||||||
+++ b/src/sc.cpp
|
|
||||||
@@ -52,7 +52,7 @@ Sc::Sc (Pd *own, Ec *e, unsigned c, Sc *x) : Kobject (SC, static_cast<Space_obj
|
|
||||||
trace (TRACE_SYSCALL, "SC:%p created (EC:%p CPU:%#x P:%#x Q:%#x) - xCPU", this, e, c, prio, budget / (Lapic::freq_bus / 1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
-void Sc::ready_enqueue (uint64 t)
|
|
||||||
+void Sc::ready_enqueue (uint64 t, bool use_left)
|
|
||||||
{
|
|
||||||
assert (prio < priorities);
|
|
||||||
assert (cpu == Cpu::id);
|
|
||||||
@@ -68,13 +68,13 @@ void Sc::ready_enqueue (uint64 t)
|
|
||||||
next = list[prio];
|
|
||||||
prev = list[prio]->prev;
|
|
||||||
next->prev = prev->next = this;
|
|
||||||
- if (left)
|
|
||||||
+ if (use_left && left)
|
|
||||||
list[prio] = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
trace (TRACE_SCHEDULE, "ENQ:%p (%02u) PRIO:%#x TOP:%#x %s", this, left, prio, prio_top, prio > current->prio ? "reschedule" : "");
|
|
||||||
|
|
||||||
- if (prio > current->prio || (this != current && prio == current->prio && left))
|
|
||||||
+ if (prio > current->prio || (this != current && prio == current->prio && (use_left && left)))
|
|
||||||
Cpu::hazard |= HZD_SCHED;
|
|
||||||
|
|
||||||
if (!left)
|
|
||||||
@@ -106,7 +106,7 @@ void Sc::ready_dequeue (uint64 t)
|
|
||||||
tsc = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
-void Sc::schedule (bool suspend)
|
|
||||||
+void Sc::schedule (bool suspend, bool use_left)
|
|
||||||
{
|
|
||||||
Counter::print<1,16> (++Counter::schedule, Console_vga::COLOR_LIGHT_CYAN, SPN_SCH);
|
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ void Sc::schedule (bool suspend)
|
|
||||||
delete current;
|
|
||||||
else
|
|
||||||
if (EXPECT_TRUE (!suspend))
|
|
||||||
- current->ready_enqueue (t);
|
|
||||||
+ current->ready_enqueue (t, use_left);
|
|
||||||
|
|
||||||
Sc *sc = list[prio_top];
|
|
||||||
assert (sc);
|
|
||||||
diff --git a/src/syscall.cpp b/src/syscall.cpp
|
|
||||||
index 975d4dc..6e792b0 100644
|
|
||||||
--- a/src/syscall.cpp
|
|
||||||
+++ b/src/syscall.cpp
|
|
||||||
@@ -409,6 +412,9 @@ void Ec::sys_ec_ctrl()
|
|
||||||
{
|
|
||||||
Sys_ec_ctrl *r = static_cast<Sys_ec_ctrl *>(current->sys_regs());
|
|
||||||
|
|
||||||
+ switch (r->op()) {
|
|
||||||
+ case 0:
|
|
||||||
+{
|
|
||||||
Capability cap = Space_obj::lookup (r->ec());
|
|
||||||
if (EXPECT_FALSE (cap.obj()->type() != Kobject::EC || !(cap.prm() & 1UL << 0))) {
|
|
||||||
trace (TRACE_ERROR, "%s: Bad EC CAP (%#lx)", __func__, r->ec());
|
|
||||||
@@ -423,6 +429,18 @@ void Ec::sys_ec_ctrl()
|
|
||||||
|
|
||||||
if (Cpu::id != ec->cpu && Ec::remote (ec->cpu) == ec)
|
|
||||||
Lapic::send_ipi (ec->cpu, VEC_IPI_RKE);
|
|
||||||
+
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 1:
|
|
||||||
+ current->cont = sys_finish<Sys_regs::SUCCESS>;
|
|
||||||
+ Sc::schedule (false, false);
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ default:
|
|
||||||
+ sys_finish<Sys_regs::BAD_PAR>();
|
|
||||||
}
|
|
||||||
|
|
||||||
sys_finish<Sys_regs::SUCCESS>();
|
|
Loading…
x
Reference in New Issue
Block a user