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_castprev; 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(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; + Sc::schedule (false, false); + break; + + default: + sys_finish(); } sys_finish();