diff mbox

[08/10] coroutine: process the coroutines woken by child when child yield

Message ID 1333442297-18932-8-git-send-email-laijs@cn.fujitsu.com
State New
Headers show

Commit Message

Lai Jiangshan April 3, 2012, 8:38 a.m. UTC
If the child wake up someone, process them.

It would the child complete its works if woken coroutine release the locks
that the child needs.

It may help for the cache, if the child wake up some someone, they are
probably accessing the same data.

Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
---
 qemu-coroutine.c |   29 +++++++++++++++++++++++------
 1 files changed, 23 insertions(+), 6 deletions(-)

Comments

Kevin Wolf April 5, 2012, 12:43 p.m. UTC | #1
Am 03.04.2012 10:38, schrieb Lai Jiangshan:
> If the child wake up someone, process them.
> 
> It would the child complete its works if woken coroutine release the locks
> that the child needs.
> 
> It may help for the cache, if the child wake up some someone, they are
> probably accessing the same data.
> 
> Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>

Are you very sure that this is correct, particularly with respect to
reentrancy of nested coroutines? This is why this has become a bottom
half in the first place (instead of directly reentering the unlocked
coroutine in qemu_co_mutex_unlock), and it's not completely clear to me
if the problem doesn't exist when you do it after a coroutine has exited
instead of in an BH.

I'd be very careful with such changes.

Kevin
diff mbox

Patch

diff --git a/qemu-coroutine.c b/qemu-coroutine.c
index c67d557..ce6b3af 100644
--- a/qemu-coroutine.c
+++ b/qemu-coroutine.c
@@ -22,17 +22,25 @@  static QTAILQ_HEAD(, Coroutine) co_runnable_queue =
     QTAILQ_HEAD_INITIALIZER(co_runnable_queue);
 static QEMUBH* co_runnable_bh;
 
-static void qemu_co_process_runnable(void *opaque)
+static void coroutine_enter(Coroutine *self, Coroutine *co, void *opaque);
+static void process_runnable(Coroutine *self)
 {
     Coroutine *next;
 
-    trace_qemu_co_process_runnable();
     while ((next = QTAILQ_FIRST(&co_runnable_queue))) {
         QTAILQ_REMOVE(&co_runnable_queue, next, co_queue_next);
-        qemu_coroutine_enter(next, NULL);
+        coroutine_enter(self, next, NULL);
     }
 }
 
+static void qemu_co_process_runnable(void *opaque)
+{
+    Coroutine *self = qemu_coroutine_self();
+
+    trace_qemu_co_process_runnable();
+    process_runnable(self);
+}
+
 void qemu_co_runnable_schedule(Coroutine *co)
 {
     QTAILQ_INSERT_TAIL(&co_runnable_queue, co, co_queue_next);
@@ -69,10 +77,8 @@  static void coroutine_swap(Coroutine *from, Coroutine *to)
     }
 }
 
-void qemu_coroutine_enter(Coroutine *co, void *opaque)
+static void coroutine_enter(Coroutine *self, Coroutine *co, void *opaque)
 {
-    Coroutine *self = qemu_coroutine_self();
-
     trace_qemu_coroutine_enter(self, co, opaque);
 
     if (co->caller) {
@@ -85,6 +91,17 @@  void qemu_coroutine_enter(Coroutine *co, void *opaque)
     coroutine_swap(self, co);
 }
 
+void qemu_coroutine_enter(Coroutine *co, void *opaque)
+{
+    Coroutine *self = qemu_coroutine_self();
+    typeof(co_runnable_queue) snap = co_runnable_queue;
+
+    QTAILQ_INIT(&co_runnable_queue);
+    coroutine_enter(self, co, opaque);
+    process_runnable(self);
+    co_runnable_queue = snap;
+}
+
 void coroutine_fn qemu_coroutine_yield(void)
 {
     Coroutine *self = qemu_coroutine_self();