This patch adds a facility to block on a particular event channel, for
when a domain needs to block, but cannot enable interrupts. A domain
uses the call something like this:
while (1) {
clear_evtchn_pending(evtchn);
if (check_for_data(evtchn))
break;
HYPERVISOR_block_on(evtchn);
}
The clear of the pending is needed to ensure that any subsequent calls
to block_on() don't return immediately.
regards,
john
# HG changeset patch
# User john.levon@xxxxxxx
# Node ID 15aea7d020cd13b1f13692518f10051e401962df
# Parent fbeb0a5b7219630839986cf4cdb1b813618cbdce
Add SCHEDOP_block_on.
Signed-off-by: John Levon <john.levon@xxxxxxx>
diff -r fbeb0a5b7219 -r 15aea7d020cd docs/src/interface.tex
--- a/docs/src/interface.tex Thu Mar 9 16:24:57 2006 +0000
+++ b/docs/src/interface.tex Thu Mar 9 21:55:15 2006 -0800
@@ -1721,13 +1721,17 @@
\hypercall{sched\_op(unsigned long op)}
Request scheduling operation from hypervisor. The options are: {\it
-SCHEDOP\_yield}, {\it SCHEDOP\_block}, and {\it SCHEDOP\_shutdown}.
-{\it yield} keeps the calling domain runnable but may cause a
-reschedule if other domains are runnable. {\it block} removes the
-calling domain from the run queue and cause is to sleeps until an
-event is delivered to it. {\it shutdown} is used to end the domain's
-execution; the caller can additionally specify whether the domain
-should reboot, halt or suspend.
+SCHEDOP\_yield}, {\it SCHEDOP\_block}, {\it SCHEDOP\_block\_on} and
+{\it SCHEDOP\_shutdown}. {\it yield} keeps the calling vcpu runnable
+but may cause a reschedule if other vcpus are runnable. {\it block}
+enables event delivery, removes the calling vcpu from the run queue,
+and causes it to sleep until an event is delivered to it.
+{\it block\_on} causes the calling vcpu to sleep until any event is
+delivered. It takes an event channel argument, which is checked to
+see if it's pending; if it is, then the vcpu does not sleep.
+{\it shutdown} is used to end the domain's execution; the caller
+can additionally specify whether the domain should reboot, halt or
+suspend.
\end{quote}
To aid the implementation of a process scheduler within a guest OS,
diff -r fbeb0a5b7219 -r 15aea7d020cd xen/common/schedule.c
--- a/xen/common/schedule.c Thu Mar 9 16:24:57 2006 +0000
+++ b/xen/common/schedule.c Thu Mar 9 21:55:15 2006 -0800
@@ -249,7 +249,7 @@
}
/* Block the currently-executing domain until a pertinent event occurs. */
-static long do_block(void)
+static void do_block(void)
{
struct vcpu *v = current;
@@ -258,6 +258,32 @@
/* Check for events /after/ blocking: avoids wakeup waiting race. */
if ( event_pending(v) )
+ {
+ clear_bit(_VCPUF_blocked, &v->vcpu_flags);
+ }
+ else
+ {
+ TRACE_2D(TRC_SCHED_BLOCK, v->domain->domain_id, v->vcpu_id);
+ __enter_scheduler();
+ }
+}
+
+/*
+ * Block the currently-executing domain without enabling interrupts, for a
+ * particular evtchn. Whilst we check for a particular evtchn, /any/ event
+ * will wake us up again.
+ */
+static long do_block_on(unsigned long evtchn)
+{
+ struct vcpu *v = current;
+
+ if ( evtchn >= MAX_EVTCHNS )
+ return -EINVAL;
+
+ set_bit(_VCPUF_blocked, &v->vcpu_flags);
+
+ /* Check for event /after/ blocking: avoids wakeup waiting race. */
+ if ( evtchn_pending(v->domain->shared_info, evtchn) )
{
clear_bit(_VCPUF_blocked, &v->vcpu_flags);
}
@@ -292,7 +318,13 @@
case SCHEDOP_block:
{
- ret = do_block();
+ do_block();
+ break;
+ }
+
+ case SCHEDOP_block_on:
+ {
+ ret = do_block_on(arg);
break;
}
diff -r fbeb0a5b7219 -r 15aea7d020cd xen/include/public/sched.h
--- a/xen/include/public/sched.h Thu Mar 9 16:24:57 2006 +0000
+++ b/xen/include/public/sched.h Thu Mar 9 21:55:15 2006 -0800
@@ -38,6 +38,16 @@
#define SCHEDOP_shutdown 2
/*
+ * Block execution of this VCPU until an event is received for processing,
+ * without clearing the upcall mask; a subsequent pending event will not be
+ * delivered, but will still wake up the domain. This is intended for use in
+ * polling loops when "interrupts" are disabled. It takes one argument; that of
+ * a channel to check for pending events before sleeping.
+ * @arg == evtchn.
+ */
+#define SCHEDOP_block_on 3
+
+/*
* Reason codes for SCHEDOP_shutdown. These may be interpreted by controller
* software to determine the appropriate action. For the most part, Xen does
* not care about the shutdown code.
diff -r fbeb0a5b7219 -r 15aea7d020cd xen/include/xen/event.h
--- a/xen/include/xen/event.h Thu Mar 9 16:24:57 2006 +0000
+++ b/xen/include/xen/event.h Thu Mar 9 21:55:15 2006 -0800
@@ -14,6 +14,16 @@
#include <xen/smp.h>
#include <asm/bitops.h>
#include <asm/event.h>
+
+/*
+ * If the vcpu has events masked, we should unblock it even if the event
+ * channel is already pending.
+ */
+static inline void evtchn_check_unblock(struct vcpu *v)
+{
+ if ( v->vcpu_info->evtchn_upcall_mask && (v->vcpu_flags & VCPUF_blocked) )
+ vcpu_unblock(v);
+}
/*
* EVENT-CHANNEL NOTIFICATIONS
@@ -35,6 +45,10 @@
!test_and_set_bit(0, &v->vcpu_info->evtchn_upcall_pending) )
{
evtchn_notify(v);
+ }
+ else
+ {
+ evtchn_check_unblock(v);
}
}
@@ -69,4 +83,7 @@
/* Bind a local event-channel port to the specified VCPU. */
extern long evtchn_bind_vcpu(unsigned int port, unsigned int vcpu_id);
+#define evtchn_pending(s, e) \
+ (test_bit((e), &(s)->evtchn_pending[0]))
+
#endif /* __XEN_EVENT_H__ */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|