X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Fgenerator%2Fgenerator.c;fp=ccan%2Fgenerator%2Fgenerator.c;h=d217665614819db7e585c41224a357f319c499a6;hb=707a8c0a899a4b645bcf778f7ea79565d6f3f13e;hp=0000000000000000000000000000000000000000;hpb=d4c7616d9ef5a55dd89ea878a07eedc7376d6973;p=ccan diff --git a/ccan/generator/generator.c b/ccan/generator/generator.c new file mode 100644 index 00000000..d2176656 --- /dev/null +++ b/ccan/generator/generator.c @@ -0,0 +1,54 @@ +/* Licensed LGPLv2.1+ - see LICENSE file for details */ +#include +#include +#include + +#include + +#include + +#define DEFAULT_STATE_SIZE 8192 +#define STATE_ALIGN ALIGNOF(struct generator_) + +void *generator_new_(generator_wrapper_ *fn, size_t retsize) +{ + char *base; + size_t size = DEFAULT_STATE_SIZE; + void *ret; + struct generator_ *gen; + + base = malloc(size); + if (!base) + abort(); + + retsize = (retsize + STATE_ALIGN) & ~(STATE_ALIGN - 1); + ret = base + size - retsize; + gen = (struct generator_ *)ret - 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); + } + + return ret; +} + +void generator_free_(void *ret) +{ + struct generator_ *gen = generator_state_(ret); + free(gen->base); +}