nova: add feature to yield a thread

used by virtualbox intensively
This commit is contained in:
Alexander Boettcher 2014-01-30 10:19:17 +01:00 committed by Christian Helmuth
parent 39a7ffd233
commit dd95266235
7 changed files with 128 additions and 7 deletions

View File

@ -210,9 +210,9 @@ namespace Nova {
ALWAYS_INLINE
inline uint8_t ec_ctrl(unsigned ec)
inline uint8_t ec_ctrl(Ec_op op, unsigned para = ~0UL)
{
return syscall_0(NOVA_EC_CTRL, 0, ec);
return syscall_0(NOVA_EC_CTRL, op, para);
}

View File

@ -173,9 +173,9 @@ namespace Nova {
ALWAYS_INLINE
inline uint8_t ec_ctrl(mword_t ec)
inline uint8_t ec_ctrl(Ec_op op, mword_t ec = ~0UL)
{
return syscall_0(NOVA_EC_CTRL, 0, ec);
return syscall_0(NOVA_EC_CTRL, op, ec);
}

View File

@ -147,6 +147,11 @@ namespace Nova {
*/
enum Sem_op { SEMAPHORE_UP = 0U, SEMAPHORE_DOWN = 1U, SEMAPHORE_DOWNZERO = 0x3U };
/**
* Ec operations
*/
enum Ec_op { EC_RECALL = 0U, EC_YIELD = 1U };
class Descriptor
{

View File

@ -0,0 +1,116 @@
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>();

View File

@ -41,7 +41,7 @@ Genode::Thread_base * __attribute__((weak)) Genode::Thread_base::myself()
}
static inline void thread_yield() { }
static inline void thread_yield() { Nova::ec_ctrl(Nova::EC_YIELD); }
static inline bool thread_check_stopped_and_restart(Genode::Thread_base *thread_base)

View File

@ -296,7 +296,7 @@ void Pager_object::client_cancel_blocking()
uint8_t Pager_object::client_recall()
{
return ec_ctrl(_state.sel_client_ec);
return ec_ctrl(EC_RECALL, _state.sel_client_ec);
}

View File

@ -940,7 +940,7 @@ class Machine : public StaticReceiver<Machine>
return false;
}
}
return (Nova::ec_ctrl(msg.value + 1) == 0);
return (Nova::ec_ctrl(Nova::EC_RECALL, msg.value + 1) == 0);
case MessageHostOp::OP_VCPU_BLOCK:
{