WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] Add SCHEDOP_block_on

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] Add SCHEDOP_block_on
From: John Levon <levon@xxxxxxxxxxxxxxxxx>
Date: Fri, 10 Mar 2006 15:34:39 +0000
Delivery-date: Fri, 10 Mar 2006 15:33:46 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.9i
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