diff options
Diffstat (limited to 'coroutine/copy/Context.h')
-rw-r--r-- | coroutine/copy/Context.h | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/coroutine/copy/Context.h b/coroutine/copy/Context.h new file mode 100644 index 0000000000..a62efa4e8a --- /dev/null +++ b/coroutine/copy/Context.h @@ -0,0 +1,79 @@ +/* + * This file is part of the "Coroutine" project and released under the MIT License. + * + * Created by Samuel Williams on 27/6/2019. + * Copyright, 2019, by Samuel Williams. All rights reserved. +*/ + +#pragma once + +#include <assert.h> +#include <stddef.h> +#include <setjmp.h> +#include <string.h> +#include <stdlib.h> +#include <alloca.h> + +#define COROUTINE __attribute__((noreturn)) void + +// This stack copying implementation which uses a private stack for each coroutine, including the main one. +#define COROUTINE_PRIVATE_STACK + +struct coroutine_context +{ + // Private stack: + void *stack; + size_t size, used; + + // The top (or bottom) of the currently executing stack: + void *base; + + jmp_buf state; + + struct coroutine_context *from; +}; + +typedef COROUTINE(*coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); + +int coroutine_save_stack(struct coroutine_context * context); +COROUTINE coroutine_restore_stack(struct coroutine_context *context); + +// @param stack The private stack area memory allocation (pointer to lowest address). +// @param size The size of the private stack area. +// @param base A stack pointer to the base of the main stack. On x86 hardware, this is the upper extent of the region that will be copied to the private stack. +static inline void coroutine_initialize_main(struct coroutine_context *context, void *stack, size_t size, void *base) { + context->stack = stack; + context->size = size; + context->used = 0; + + assert(base); + context->base = base; + + context->from = NULL; +} + +// @param start The start function to invoke. +static inline void coroutine_initialize( + struct coroutine_context *context, + coroutine_start start, + void *stack, + size_t size, + void *base +) { + assert(start && stack && size >= 1024); + + coroutine_initialize_main(context, stack, size, base); + + if (coroutine_save_stack(context)) { + start(context->from, context); + } +} + +struct coroutine_context *coroutine_transfer(struct coroutine_context *current, register struct coroutine_context *target); + +static inline void coroutine_destroy(struct coroutine_context *context) +{ + context->stack = NULL; + context->size = 0; + context->from = NULL; +} |