[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] Add SCHEDOP_block_on



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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.