]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Coroutines: update coro_done to schedule an event
authorJan Maria Matejka <mq@ucw.cz>
Thu, 13 Sep 2018 11:21:09 +0000 (13:21 +0200)
committerJan Maria Matejka <mq@ucw.cz>
Fri, 14 Sep 2018 12:39:56 +0000 (14:39 +0200)
lib/coroutine.h
sysdep/unix/coroutine.c

index f3cce40c73368993fa29b713596cdf20464007dc..7b579bfe16adb970dee4db1265d603b7476ca6b7 100644 (file)
@@ -9,13 +9,15 @@
 #ifndef _BIRD_COROUTINE_H_
 #define _BIRD_COROUTINE_H_
 
+#include "lib/event.h"
+
 // The structure is completely opaque, implemented by sysdep
 typedef struct coroutine coroutine;
 
 coroutine *coro_new(struct pool *pool, void (*entry_point)(void *arg), void *arg);
 void coro_suspend(void);
 void coro_resume(coroutine *c);
-void coro_done(void *retval) NORET;
+void coro_done(event *e) NORET;
 
 struct birdsock;
 int coro_sk_read(struct birdsock *s);
index 8ffb81486b5bdda63edaca469af7578503c301e2..4d554ba379ad689747dae9ef7ca41d0fa07bdc4b 100644 (file)
@@ -35,6 +35,7 @@ struct coroutine {
   void *stack;
   void (*entry_point)(void *arg);
   void *arg;
+  event *ev;
 };
 
 static ucontext_t *main_context;
@@ -101,12 +102,14 @@ coro_new(pool *p, void (*entry_point)(void *), void *arg)
 }
 
 void
-coro_done(void *retval)
+coro_done(event *e)
 {
   ASSERT(coro_inited);
   ASSERT(coro_current);
+  if (e)
+    ev_schedule(e);
+  c->ev = e;
   coroutine *c = coro_current;
-  c->retval = retval;
   coro_suspend();
   bug("Coroutine suspend after coro_done() should never return");
 }
@@ -148,6 +151,7 @@ struct coroutine {
   pthread_t thread;
   void (*entry_point)(void *arg);
   void *arg;
+  event *ev;
   sem_t sem;
   uint flags;
 };
@@ -163,8 +167,11 @@ coro_free(resource *r)
   coroutine *c = (coroutine *) r;
   ASSERT(coro_current != c);
 
-  c->flags |= CORO_STOP;
-  coro_resume(c);
+  if (!(c->flags & CORO_DONE))
+    {
+      c->flags |= CORO_STOP;
+      coro_resume(c);
+    }
 
   ASSERT(c->flags & CORO_DONE);
   pthread_join(c->thread, NULL);
@@ -241,14 +248,17 @@ coro_check_stop(void)
 }
 
 void
-coro_done(void *retval)
+coro_done(event *e)
 {
   ASSERT(coro_inited);
   ASSERT(coro_current);
   coroutine *c = coro_current;
   c->flags |= CORO_DONE;
+  c->ev = e;
+  if (e)
+    ev_schedule(e);
   sem_post(&coro_main_sem);
-  pthread_exit(retval);
+  pthread_exit(NULL);
   bug("pthread_exit should never return");
 }