Re: [ccan] [PATCHv2 2/2] generator: Rewrite to use coroutine module

2016-12-02 Thread Rusty Russell
David Gibson  writes:
> Use the new coroutine module to abstract away our dependence on
> ucontext.

These both look great!

Cheers,
Rusty.
___
ccan mailing list
ccan@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/ccan


[ccan] [PATCHv2 2/2] generator: Rewrite to use coroutine module

2016-12-01 Thread David Gibson
Use the new coroutine module to abstract away our dependence on
ucontext.

Signed-off-by: David Gibson 
---
 ccan/generator/_info   |  9 ++---
 ccan/generator/generator.c | 39 ++--
 ccan/generator/generator.h | 49 ++
 3 files changed, 41 insertions(+), 56 deletions(-)

diff --git a/ccan/generator/_info b/ccan/generator/_info
index 11753a5..489b9dd 100644
--- a/ccan/generator/_info
+++ b/ccan/generator/_info
@@ -2,6 +2,8 @@
 #include 
 #include 
 
+#include 
+
 /**
  * generator - generators for C
  *
@@ -56,18 +58,19 @@ int main(int argc, char *argv[])
 
if (strcmp(argv[1], "depends") == 0) {
printf("ccan/build_assert\n");
-   printf("ccan/ptrint\n");
printf("ccan/alignof\n");
+   printf("ccan/coroutine\n");
printf("ccan/cppmagic\n");
printf("ccan/compiler\n");
return 0;
}
 
if (strcmp(argv[1], "ported") == 0) {
-#if HAVE_UCONTEXT
+#if COROUTINE_AVAILABLE
printf("\n");
+   return 1;
 #else
-   printf("Needs ucontext support\n");
+   printf("Needs coroutine support\n");
 #endif
}
 
diff --git a/ccan/generator/generator.c b/ccan/generator/generator.c
index d217665..656cbe7 100644
--- a/ccan/generator/generator.c
+++ b/ccan/generator/generator.c
@@ -10,10 +10,18 @@
 #define DEFAULT_STATE_SIZE 8192
 #define STATE_ALIGNALIGNOF(struct generator_)
 
-void *generator_new_(generator_wrapper_ *fn, size_t retsize)
+static size_t generator_metasize(size_t retsize)
+{
+   retsize = (retsize + STATE_ALIGN) & ~(STATE_ALIGN - 1);
+   return sizeof(struct generator_) + retsize;
+}
+
+void *generator_new_(void (*fn)(void *), size_t retsize)
 {
char *base;
size_t size = DEFAULT_STATE_SIZE;
+   size_t metasize = generator_metasize(retsize);
+   struct coroutine_stack *stack;
void *ret;
struct generator_ *gen;
 
@@ -22,33 +30,26 @@ void *generator_new_(generator_wrapper_ *fn, size_t retsize)
abort();
 
retsize = (retsize + STATE_ALIGN) & ~(STATE_ALIGN - 1);
-   ret = base + size - retsize;
-   gen = (struct generator_ *)ret - 1;
+
+   stack = coroutine_stack_init(base, size, metasize);
+   gen = coroutine_stack_to_metadata(stack, metasize);
+   ret = gen + 1;
 
gen->base = base;
gen->complete = false;
 
-   getcontext(&gen->gen);
-
-   gen->gen.uc_stack.ss_sp = gen->base;
-   gen->gen.uc_stack.ss_size = (char *)gen - base;
-
-   if (HAVE_POINTER_SAFE_MAKECONTEXT) {
-   makecontext(&gen->gen, (void *)fn, 1, ret);
-   } else {
-   ptrdiff_t si = ptr2int(ret);
-   ptrdiff_t mask = (1UL << (sizeof(int) * 8)) - 1;
-   int lo = si & mask;
-   int hi = si >> (sizeof(int) * 8);
-
-   makecontext(&gen->gen, (void *)fn, 2, lo, hi);
-   }
+   coroutine_init(&gen->gen, fn, ret, stack);
 
return ret;
 }
 
-void generator_free_(void *ret)
+void generator_free_(void *ret, size_t retsize)
 {
struct generator_ *gen = generator_state_(ret);
+   size_t metasize = generator_metasize(retsize);
+   struct coroutine_stack *stack;
+
+   stack = coroutine_stack_from_metadata(gen, metasize);
+   coroutine_stack_release(stack);
free(gen->base);
 }
diff --git a/ccan/generator/generator.h b/ccan/generator/generator.h
index 121f14a..7122f55 100644
--- a/ccan/generator/generator.h
+++ b/ccan/generator/generator.h
@@ -3,10 +3,6 @@
 #define CCAN_GENERATOR_H
 #include "config.h"
 
-#if !HAVE_UCONTEXT
-#error Generators require working ucontext.h functions
-#endif
-
 #if !HAVE_TYPEOF
 #error Generators require typeof
 #endif
@@ -18,20 +14,22 @@
 #include 
 #include 
 #include 
-#include 
 
-#include 
-#include 
 #include 
 #include 
+#include 
+
+#if !COROUTINE_AVAILABLE
+#error Generators require coroutines
+#endif
 
 /*
  * Internals - included just for the use of inlines and macros
  */
 
 struct generator_ {
-   ucontext_t gen;
-   ucontext_t caller;
+   struct coroutine_state gen;
+   struct coroutine_state caller;
bool complete;
void *base;
 };
@@ -51,15 +49,8 @@ struct generator_incomplete_;
 #define generator_rtype_(gen_) \
typeof((*(gen_))((struct generator_incomplete_ *)NULL))
 
-#if HAVE_POINTER_SAFE_MAKECONTEXT
-#define generator_wrapper_args_()  void *ret
-#else
-#define generator_wrapper_args_()  int lo, int hi
-#endif
-typedef void generator_wrapper_(generator_wrapper_args_());
-
-void *generator_new_(generator_wrapper_ *fn, size_t retsize);
-void generator_free_(void *ret);
+void *generator_new_(void (*fn)(void *), size_t retsize);
+void generator_free_(void *ret, size_t retsize);
 
 /*
  * API
@@ -128,22 +119,15 @@ void generator_free_(void *ret);
 #define