diff options
Diffstat (limited to 'examples/coroutines')
| -rw-r--r-- | examples/coroutines/aco.c | 434 | ||||
| -rw-r--r-- | examples/coroutines/aco.h | 168 |
2 files changed, 283 insertions, 319 deletions
diff --git a/examples/coroutines/aco.c b/examples/coroutines/aco.c index 6057466f..258efe28 100644 --- a/examples/coroutines/aco.c +++ b/examples/coroutines/aco.c @@ -16,193 +16,194 @@ #define _GNU_SOURCE #include "aco.h" -#include <stdio.h> #include <stdint.h> +#include <stdio.h> #ifndef public -#define public __attribute__ ((visibility ("default"))) +#define public __attribute__((visibility("default"))) #endif -#define aco_size_t_safe_add_assert(a,b) aco_assert((a)+(b) >= (a)) +#define aco_size_t_safe_add_assert(a, b) aco_assert((a) + (b) >= (a)) -static void aco_default_protector_last_word(void*); +static void aco_default_protector_last_word(void *); -void* (*aco_alloc_fn)(size_t) = malloc; -void (*aco_dealloc_fn)(void*) = free; +void *(*aco_alloc_fn)(size_t) = malloc; +void (*aco_dealloc_fn)(void *) = free; -#define aco_alloc(size) ({ \ - void *_ptr = aco_alloc_fn(size); \ - if (aco_unlikely((_ptr) == NULL)) { \ - fprintf(stderr, "Aborting: failed to allocate memory: %s:%d:%s\n", \ - __FILE__, __LINE__, __PRETTY_FUNCTION__); \ - abort(); \ - } \ - _ptr; \ -}) +#define aco_alloc(size) \ + ({ \ + void *_ptr = aco_alloc_fn(size); \ + if (aco_unlikely((_ptr) == NULL)) { \ + fprintf(stderr, "Aborting: failed to allocate memory: %s:%d:%s\n", __FILE__, __LINE__, \ + __PRETTY_FUNCTION__); \ + abort(); \ + } \ + _ptr; \ + }) // aco's Global Thread Local Storage variable `co` -public __thread aco_t* aco_gtls_co; +public +__thread aco_t *aco_gtls_co; static __thread aco_cofuncp_t aco_gtls_last_word_fp = aco_default_protector_last_word; #ifdef __i386__ - static __thread void* aco_gtls_fpucw_mxcsr[2]; -#elif __x86_64__ - static __thread void* aco_gtls_fpucw_mxcsr[1]; +static __thread void *aco_gtls_fpucw_mxcsr[2]; +#elif __x86_64__ +static __thread void *aco_gtls_fpucw_mxcsr[1]; #else - #error "platform not supporteded yet" +#error "platform not supporteded yet" #endif -public void aco_runtime_test(void) { +public +void aco_runtime_test(void) { #ifdef __i386__ - _Static_assert(sizeof(void*) == 4, "require 'sizeof(void*) == 4'"); -#elif __x86_64__ - _Static_assert(sizeof(void*) == 8, "require 'sizeof(void*) == 8'"); + _Static_assert(sizeof(void *) == 4, "require 'sizeof(void*) == 4'"); +#elif __x86_64__ + _Static_assert(sizeof(void *) == 8, "require 'sizeof(void*) == 8'"); _Static_assert(sizeof(__uint128_t) == 16, "require 'sizeof(__uint128_t) == 16'"); #else - #error "platform not supporteded yet" +#error "platform not supporteded yet" #endif _Static_assert(sizeof(int) >= 4, "require 'sizeof(int) >= 4'"); aco_assert(sizeof(int) >= 4); - _Static_assert(sizeof(int) <= sizeof(size_t), - "require 'sizeof(int) <= sizeof(size_t)'"); + _Static_assert(sizeof(int) <= sizeof(size_t), "require 'sizeof(int) <= sizeof(size_t)'"); aco_assert(sizeof(int) <= sizeof(size_t)); } #ifdef __x86_64__ static inline void aco_fast_memcpy(void *dst, const void *src, size_t sz) { - if (((uintptr_t)src & 0x0f) != 0 - || ((uintptr_t)dst & 0x0f) != 0 - || (sz & 0x0f) != 0x08 - || (sz >> 4) > 8) { + if (((uintptr_t)src & 0x0f) != 0 || ((uintptr_t)dst & 0x0f) != 0 || (sz & 0x0f) != 0x08 || (sz >> 4) > 8) { memcpy(dst, src, sz); return; } - __uint128_t xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7; + __uint128_t xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; switch (sz >> 4) { - case 0: - break; - case 1: - xmm0 = *((__uint128_t*)src + 0); - *((__uint128_t*)dst + 0) = xmm0; - break; - case 2: - xmm0 = *((__uint128_t*)src + 0); - xmm1 = *((__uint128_t*)src + 1); - *((__uint128_t*)dst + 0) = xmm0; - *((__uint128_t*)dst + 1) = xmm1; - break; - case 3: - xmm0 = *((__uint128_t*)src + 0); - xmm1 = *((__uint128_t*)src + 1); - xmm2 = *((__uint128_t*)src + 2); - *((__uint128_t*)dst + 0) = xmm0; - *((__uint128_t*)dst + 1) = xmm1; - *((__uint128_t*)dst + 2) = xmm2; - break; - case 4: - xmm0 = *((__uint128_t*)src + 0); - xmm1 = *((__uint128_t*)src + 1); - xmm2 = *((__uint128_t*)src + 2); - xmm3 = *((__uint128_t*)src + 3); - *((__uint128_t*)dst + 0) = xmm0; - *((__uint128_t*)dst + 1) = xmm1; - *((__uint128_t*)dst + 2) = xmm2; - *((__uint128_t*)dst + 3) = xmm3; - break; - case 5: - xmm0 = *((__uint128_t*)src + 0); - xmm1 = *((__uint128_t*)src + 1); - xmm2 = *((__uint128_t*)src + 2); - xmm3 = *((__uint128_t*)src + 3); - xmm4 = *((__uint128_t*)src + 4); - *((__uint128_t*)dst + 0) = xmm0; - *((__uint128_t*)dst + 1) = xmm1; - *((__uint128_t*)dst + 2) = xmm2; - *((__uint128_t*)dst + 3) = xmm3; - *((__uint128_t*)dst + 4) = xmm4; - break; - case 6: - xmm0 = *((__uint128_t*)src + 0); - xmm1 = *((__uint128_t*)src + 1); - xmm2 = *((__uint128_t*)src + 2); - xmm3 = *((__uint128_t*)src + 3); - xmm4 = *((__uint128_t*)src + 4); - xmm5 = *((__uint128_t*)src + 5); - *((__uint128_t*)dst + 0) = xmm0; - *((__uint128_t*)dst + 1) = xmm1; - *((__uint128_t*)dst + 2) = xmm2; - *((__uint128_t*)dst + 3) = xmm3; - *((__uint128_t*)dst + 4) = xmm4; - *((__uint128_t*)dst + 5) = xmm5; - break; - case 7: - xmm0 = *((__uint128_t*)src + 0); - xmm1 = *((__uint128_t*)src + 1); - xmm2 = *((__uint128_t*)src + 2); - xmm3 = *((__uint128_t*)src + 3); - xmm4 = *((__uint128_t*)src + 4); - xmm5 = *((__uint128_t*)src + 5); - xmm6 = *((__uint128_t*)src + 6); - *((__uint128_t*)dst + 0) = xmm0; - *((__uint128_t*)dst + 1) = xmm1; - *((__uint128_t*)dst + 2) = xmm2; - *((__uint128_t*)dst + 3) = xmm3; - *((__uint128_t*)dst + 4) = xmm4; - *((__uint128_t*)dst + 5) = xmm5; - *((__uint128_t*)dst + 6) = xmm6; - break; - case 8: - xmm0 = *((__uint128_t*)src + 0); - xmm1 = *((__uint128_t*)src + 1); - xmm2 = *((__uint128_t*)src + 2); - xmm3 = *((__uint128_t*)src + 3); - xmm4 = *((__uint128_t*)src + 4); - xmm5 = *((__uint128_t*)src + 5); - xmm6 = *((__uint128_t*)src + 6); - xmm7 = *((__uint128_t*)src + 7); - *((__uint128_t*)dst + 0) = xmm0; - *((__uint128_t*)dst + 1) = xmm1; - *((__uint128_t*)dst + 2) = xmm2; - *((__uint128_t*)dst + 3) = xmm3; - *((__uint128_t*)dst + 4) = xmm4; - *((__uint128_t*)dst + 5) = xmm5; - *((__uint128_t*)dst + 6) = xmm6; - *((__uint128_t*)dst + 7) = xmm7; - break; + case 0: break; + case 1: + xmm0 = *((__uint128_t *)src + 0); + *((__uint128_t *)dst + 0) = xmm0; + break; + case 2: + xmm0 = *((__uint128_t *)src + 0); + xmm1 = *((__uint128_t *)src + 1); + *((__uint128_t *)dst + 0) = xmm0; + *((__uint128_t *)dst + 1) = xmm1; + break; + case 3: + xmm0 = *((__uint128_t *)src + 0); + xmm1 = *((__uint128_t *)src + 1); + xmm2 = *((__uint128_t *)src + 2); + *((__uint128_t *)dst + 0) = xmm0; + *((__uint128_t *)dst + 1) = xmm1; + *((__uint128_t *)dst + 2) = xmm2; + break; + case 4: + xmm0 = *((__uint128_t *)src + 0); + xmm1 = *((__uint128_t *)src + 1); + xmm2 = *((__uint128_t *)src + 2); + xmm3 = *((__uint128_t *)src + 3); + *((__uint128_t *)dst + 0) = xmm0; + *((__uint128_t *)dst + 1) = xmm1; + *((__uint128_t *)dst + 2) = xmm2; + *((__uint128_t *)dst + 3) = xmm3; + break; + case 5: + xmm0 = *((__uint128_t *)src + 0); + xmm1 = *((__uint128_t *)src + 1); + xmm2 = *((__uint128_t *)src + 2); + xmm3 = *((__uint128_t *)src + 3); + xmm4 = *((__uint128_t *)src + 4); + *((__uint128_t *)dst + 0) = xmm0; + *((__uint128_t *)dst + 1) = xmm1; + *((__uint128_t *)dst + 2) = xmm2; + *((__uint128_t *)dst + 3) = xmm3; + *((__uint128_t *)dst + 4) = xmm4; + break; + case 6: + xmm0 = *((__uint128_t *)src + 0); + xmm1 = *((__uint128_t *)src + 1); + xmm2 = *((__uint128_t *)src + 2); + xmm3 = *((__uint128_t *)src + 3); + xmm4 = *((__uint128_t *)src + 4); + xmm5 = *((__uint128_t *)src + 5); + *((__uint128_t *)dst + 0) = xmm0; + *((__uint128_t *)dst + 1) = xmm1; + *((__uint128_t *)dst + 2) = xmm2; + *((__uint128_t *)dst + 3) = xmm3; + *((__uint128_t *)dst + 4) = xmm4; + *((__uint128_t *)dst + 5) = xmm5; + break; + case 7: + xmm0 = *((__uint128_t *)src + 0); + xmm1 = *((__uint128_t *)src + 1); + xmm2 = *((__uint128_t *)src + 2); + xmm3 = *((__uint128_t *)src + 3); + xmm4 = *((__uint128_t *)src + 4); + xmm5 = *((__uint128_t *)src + 5); + xmm6 = *((__uint128_t *)src + 6); + *((__uint128_t *)dst + 0) = xmm0; + *((__uint128_t *)dst + 1) = xmm1; + *((__uint128_t *)dst + 2) = xmm2; + *((__uint128_t *)dst + 3) = xmm3; + *((__uint128_t *)dst + 4) = xmm4; + *((__uint128_t *)dst + 5) = xmm5; + *((__uint128_t *)dst + 6) = xmm6; + break; + case 8: + xmm0 = *((__uint128_t *)src + 0); + xmm1 = *((__uint128_t *)src + 1); + xmm2 = *((__uint128_t *)src + 2); + xmm3 = *((__uint128_t *)src + 3); + xmm4 = *((__uint128_t *)src + 4); + xmm5 = *((__uint128_t *)src + 5); + xmm6 = *((__uint128_t *)src + 6); + xmm7 = *((__uint128_t *)src + 7); + *((__uint128_t *)dst + 0) = xmm0; + *((__uint128_t *)dst + 1) = xmm1; + *((__uint128_t *)dst + 2) = xmm2; + *((__uint128_t *)dst + 3) = xmm3; + *((__uint128_t *)dst + 4) = xmm4; + *((__uint128_t *)dst + 5) = xmm5; + *((__uint128_t *)dst + 6) = xmm6; + *((__uint128_t *)dst + 7) = xmm7; + break; } - *((uint64_t*)((uintptr_t)dst + sz - 8)) = *((uint64_t*)((uintptr_t)src + sz - 8)); + *((uint64_t *)((uintptr_t)dst + sz - 8)) = *((uint64_t *)((uintptr_t)src + sz - 8)); } #endif -void aco_default_protector_last_word(void*_) { - aco_t* co = aco_get_co(); +void aco_default_protector_last_word(void *_) { + aco_t *co = aco_get_co(); // do some log about the offending `co` - fprintf(stderr,"error: aco_default_protector_last_word triggered\n"); - fprintf(stderr, "error: co:%p should call `aco_exit()` instead of direct " - "`return` in co_fp:%p to finish its execution\n", co, (void*)co->fp); + fprintf(stderr, "error: aco_default_protector_last_word triggered\n"); + fprintf(stderr, + "error: co:%p should call `aco_exit()` instead of direct " + "`return` in co_fp:%p to finish its execution\n", + co, (void *)co->fp); aco_assert(0); } -public void aco_set_allocator(void* (*alloc)(size_t), void (*dealloc)(void*)) -{ +public +void aco_set_allocator(void *(*alloc)(size_t), void (*dealloc)(void *)) { aco_alloc_fn = alloc; aco_dealloc_fn = dealloc; } -public void aco_thread_init(aco_cofuncp_t last_word_co_fp) { +public +void aco_thread_init(aco_cofuncp_t last_word_co_fp) { aco_save_fpucw_mxcsr(aco_gtls_fpucw_mxcsr); - if ((void*)last_word_co_fp != NULL) - aco_gtls_last_word_fp = last_word_co_fp; + if ((void *)last_word_co_fp != NULL) aco_gtls_last_word_fp = last_word_co_fp; } // This function `aco_funcp_protector` should never be // called. If it's been called, that means the offending // `co` didn't call aco_exit(co) instead of `return` to // finish its execution. -public void aco_funcp_protector(void) { - if ((void*)(aco_gtls_last_word_fp) != NULL) { +public +void aco_funcp_protector(void) { + if ((void *)(aco_gtls_last_word_fp) != NULL) { aco_gtls_last_word_fp(NULL); } else { aco_default_protector_last_word(NULL); @@ -210,11 +211,11 @@ public void aco_funcp_protector(void) { aco_assert(0); } -public aco_shared_stack_t* aco_shared_stack_new(size_t sz) { - return aco_shared_stack_new2(sz, 1); -} +public +aco_shared_stack_t *aco_shared_stack_new(size_t sz) { return aco_shared_stack_new2(sz, 1); } -public aco_shared_stack_t* aco_shared_stack_new2(size_t sz, bool guard_page_enabled) { +public +aco_shared_stack_t *aco_shared_stack_new2(size_t sz, bool guard_page_enabled) { if (sz == 0) { sz = 1024 * 1024 * 2; } @@ -253,52 +254,48 @@ public aco_shared_stack_t* aco_shared_stack_new2(size_t sz, bool guard_page_enab } } - aco_shared_stack_t* p = aco_alloc(sizeof(aco_shared_stack_t)); + aco_shared_stack_t *p = aco_alloc(sizeof(aco_shared_stack_t)); memset(p, 0, sizeof(aco_shared_stack_t)); if (guard_page_enabled) { - p->real_ptr = mmap( - NULL, sz, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 - ); + p->real_ptr = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (aco_unlikely(p->real_ptr == MAP_FAILED)) { - fprintf(stderr, "Aborting: failed to allocate memory: %s:%d:%s\n", - __FILE__, __LINE__, __PRETTY_FUNCTION__); + fprintf(stderr, "Aborting: failed to allocate memory: %s:%d:%s\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); abort(); } p->guard_page_enabled = true; aco_assert(0 == mprotect(p->real_ptr, u_pgsz, PROT_READ)); - p->ptr = (void*)(((uintptr_t)p->real_ptr) + u_pgsz); + p->ptr = (void *)(((uintptr_t)p->real_ptr) + u_pgsz); p->real_sz = sz; aco_assert(sz >= (u_pgsz << 1)); p->sz = sz - u_pgsz; } else { - //p->guard_page_enabled = 0; + // p->guard_page_enabled = 0; p->sz = sz; p->ptr = aco_alloc(sz); } p->owner = NULL; #ifdef ACO_USE_VALGRIND - p->valgrind_stk_id = VALGRIND_STACK_REGISTER( - p->ptr, (void*)((uintptr_t)p->ptr + p->sz) - ); + p->valgrind_stk_id = VALGRIND_STACK_REGISTER(p->ptr, (void *)((uintptr_t)p->ptr + p->sz)); #endif #if defined(__i386__) || defined(__x86_64__) - uintptr_t u_p = (uintptr_t)(p->sz - (sizeof(void*) << 1) + (uintptr_t)p->ptr); + uintptr_t u_p = (uintptr_t)(p->sz - (sizeof(void *) << 1) + (uintptr_t)p->ptr); u_p = (u_p >> 4) << 4; - p->align_highptr = (void*)u_p; - p->align_retptr = (void*)(u_p - sizeof(void*)); - *((void**)(p->align_retptr)) = (void*)(aco_funcp_protector_asm); - aco_assert(p->sz > (16 + (sizeof(void*) << 1) + sizeof(void*))); - p->align_limit = p->sz - 16 - (sizeof(void*) << 1); + p->align_highptr = (void *)u_p; + p->align_retptr = (void *)(u_p - sizeof(void *)); + *((void **)(p->align_retptr)) = (void *)(aco_funcp_protector_asm); + aco_assert(p->sz > (16 + (sizeof(void *) << 1) + sizeof(void *))); + p->align_limit = p->sz - 16 - (sizeof(void *) << 1); #else - #error "platform not supporteded yet" +#error "platform not supporteded yet" #endif return p; } -public void aco_shared_stack_destroy(aco_shared_stack_t* sstk) { +public +void aco_shared_stack_destroy(aco_shared_stack_t *sstk) { aco_assert(sstk != NULL && sstk->ptr != NULL); #ifdef ACO_USE_VALGRIND VALGRIND_STACK_DEREGISTER(sstk->valgrind_stk_id); @@ -314,11 +311,10 @@ public void aco_shared_stack_destroy(aco_shared_stack_t* sstk) { if (aco_dealloc_fn != NULL) aco_dealloc_fn(sstk); } -public aco_t* aco_create( - aco_t* main_co, aco_shared_stack_t* shared_stack, - size_t saved_stack_sz, aco_cofuncp_t fp, void* arg -) { - aco_t* p = aco_alloc(sizeof(aco_t)); +public +aco_t *aco_create(aco_t *main_co, aco_shared_stack_t *shared_stack, size_t saved_stack_sz, aco_cofuncp_t fp, + void *arg) { + aco_t *p = aco_alloc(sizeof(aco_t)); memset(p, 0, sizeof(aco_t)); if (main_co != NULL) { // non-main co @@ -327,21 +323,21 @@ public aco_t* aco_create( #ifdef __i386__ // POSIX.1-2008 (IEEE Std 1003.1-2008) - General Information - Data Types - Pointer Types // http://pubs.opengroup.org/onlinepubs/9699919799.2008edition/functions/V2_chap02.html#tag_15_12_03 - p->reg[ACO_REG_IDX_RETADDR] = (void*)fp; + p->reg[ACO_REG_IDX_RETADDR] = (void *)fp; // push retaddr p->reg[ACO_REG_IDX_SP] = p->shared_stack->align_retptr; - #ifndef ACO_CONFIG_SHARE_FPU_MXCSR_ENV - p->reg[ACO_REG_IDX_FPU] = aco_gtls_fpucw_mxcsr[0]; - p->reg[ACO_REG_IDX_FPU + 1] = aco_gtls_fpucw_mxcsr[1]; - #endif -#elif __x86_64__ - p->reg[ACO_REG_IDX_RETADDR] = (void*)fp; +#ifndef ACO_CONFIG_SHARE_FPU_MXCSR_ENV + p->reg[ACO_REG_IDX_FPU] = aco_gtls_fpucw_mxcsr[0]; + p->reg[ACO_REG_IDX_FPU + 1] = aco_gtls_fpucw_mxcsr[1]; +#endif +#elif __x86_64__ + p->reg[ACO_REG_IDX_RETADDR] = (void *)fp; p->reg[ACO_REG_IDX_SP] = p->shared_stack->align_retptr; - #ifndef ACO_CONFIG_SHARE_FPU_MXCSR_ENV - p->reg[ACO_REG_IDX_FPU] = aco_gtls_fpucw_mxcsr[0]; - #endif +#ifndef ACO_CONFIG_SHARE_FPU_MXCSR_ENV + p->reg[ACO_REG_IDX_FPU] = aco_gtls_fpucw_mxcsr[0]; +#endif #else - #error "platform not supporteded yet" +#error "platform not supporteded yet" #endif p->main_co = main_co; p->arg = arg; @@ -354,7 +350,7 @@ public aco_t* aco_create( #if defined(__i386__) || defined(__x86_64__) p->saved_stack.valid_sz = 0; #else - #error "platform not supporteded yet" +#error "platform not supporteded yet" #endif return p; } else { // main co @@ -368,35 +364,20 @@ public aco_t* aco_create( aco_assert(0); } -public aco_attr_no_asan -void aco_resume(aco_t* resume_co) { - aco_assert(resume_co != NULL && resume_co->main_co != NULL - && !resume_co->is_finished - ); +public +aco_attr_no_asan void aco_resume(aco_t *resume_co) { + aco_assert(resume_co != NULL && resume_co->main_co != NULL && !resume_co->is_finished); if (resume_co->shared_stack->owner != resume_co) { if (resume_co->shared_stack->owner != NULL) { - aco_t* owner_co = resume_co->shared_stack->owner; + aco_t *owner_co = resume_co->shared_stack->owner; aco_assert(owner_co->shared_stack == resume_co->shared_stack); #if defined(__i386__) || defined(__x86_64__) - aco_assert( - ( - (uintptr_t)(owner_co->shared_stack->align_retptr) - >= - (uintptr_t)(owner_co->reg[ACO_REG_IDX_SP]) - ) - && - ( - (uintptr_t)(owner_co->shared_stack->align_highptr) - - - (uintptr_t)(owner_co->shared_stack->align_limit) - <= - (uintptr_t)(owner_co->reg[ACO_REG_IDX_SP]) - ) - ); + aco_assert(((uintptr_t)(owner_co->shared_stack->align_retptr) >= (uintptr_t)(owner_co->reg[ACO_REG_IDX_SP])) + && ((uintptr_t)(owner_co->shared_stack->align_highptr) + - (uintptr_t)(owner_co->shared_stack->align_limit) + <= (uintptr_t)(owner_co->reg[ACO_REG_IDX_SP]))); owner_co->saved_stack.valid_sz = - (uintptr_t)(owner_co->shared_stack->align_retptr) - - - (uintptr_t)(owner_co->reg[ACO_REG_IDX_SP]); + (uintptr_t)(owner_co->shared_stack->align_retptr) - (uintptr_t)(owner_co->reg[ACO_REG_IDX_SP]); if (owner_co->saved_stack.sz < owner_co->saved_stack.valid_sz) { if (aco_dealloc_fn != NULL) aco_dealloc_fn(owner_co->saved_stack.ptr); owner_co->saved_stack.ptr = NULL; @@ -412,19 +393,12 @@ void aco_resume(aco_t* resume_co) { // TODO: optimize the performance penalty of memcpy function call // for very short memory span if (owner_co->saved_stack.valid_sz > 0) { - #ifdef __x86_64__ - aco_fast_memcpy( - owner_co->saved_stack.ptr, - owner_co->reg[ACO_REG_IDX_SP], - owner_co->saved_stack.valid_sz - ); - #else - memcpy( - owner_co->saved_stack.ptr, - owner_co->reg[ACO_REG_IDX_SP], - owner_co->saved_stack.valid_sz - ); - #endif +#ifdef __x86_64__ + aco_fast_memcpy(owner_co->saved_stack.ptr, owner_co->reg[ACO_REG_IDX_SP], + owner_co->saved_stack.valid_sz); +#else + memcpy(owner_co->saved_stack.ptr, owner_co->reg[ACO_REG_IDX_SP], owner_co->saved_stack.valid_sz); +#endif owner_co->saved_stack.ct_save++; } if (owner_co->saved_stack.valid_sz > owner_co->saved_stack.max_cpsz) { @@ -433,36 +407,30 @@ void aco_resume(aco_t* resume_co) { owner_co->shared_stack->owner = NULL; owner_co->shared_stack->align_validsz = 0; #else - #error "platform not supporteded yet" +#error "platform not supporteded yet" #endif } aco_assert(resume_co->shared_stack->owner == NULL); #if defined(__i386__) || defined(__x86_64__) - aco_assert( - resume_co->saved_stack.valid_sz - <= - resume_co->shared_stack->align_limit - sizeof(void*) - ); + aco_assert(resume_co->saved_stack.valid_sz <= resume_co->shared_stack->align_limit - sizeof(void *)); // TODO: optimize the performance penalty of memcpy function call // for very short memory span if (resume_co->saved_stack.valid_sz > 0) { - void *dst = (void*)( - (uintptr_t)(resume_co->shared_stack->align_retptr) - - resume_co->saved_stack.valid_sz); - #ifdef __x86_64__ + void *dst = (void *)((uintptr_t)(resume_co->shared_stack->align_retptr) - resume_co->saved_stack.valid_sz); +#ifdef __x86_64__ aco_fast_memcpy(dst, resume_co->saved_stack.ptr, resume_co->saved_stack.valid_sz); - #else +#else memcpy(dst, resume_co->saved_stack.ptr, resume_co->saved_stack.valid_sz); - #endif +#endif resume_co->saved_stack.ct_restore++; } if (resume_co->saved_stack.valid_sz > resume_co->saved_stack.max_cpsz) { resume_co->saved_stack.max_cpsz = resume_co->saved_stack.valid_sz; } - resume_co->shared_stack->align_validsz = resume_co->saved_stack.valid_sz + sizeof(void*); + resume_co->shared_stack->align_validsz = resume_co->saved_stack.valid_sz + sizeof(void *); resume_co->shared_stack->owner = resume_co; #else - #error "platform not supporteded yet" +#error "platform not supporteded yet" #endif } aco_gtls_co = resume_co; @@ -470,7 +438,8 @@ void aco_resume(aco_t* resume_co) { aco_gtls_co = resume_co->main_co; } -public void aco_destroy(aco_t* co) { +public +void aco_destroy(aco_t *co) { aco_assertptr(co); if (aco_is_main_co(co)) { if (aco_dealloc_fn != NULL) aco_dealloc_fn(co); @@ -479,14 +448,11 @@ public void aco_destroy(aco_t* co) { co->shared_stack->owner = NULL; co->shared_stack->align_validsz = 0; } - if (aco_dealloc_fn != NULL) - aco_dealloc_fn(co->saved_stack.ptr); + if (aco_dealloc_fn != NULL) aco_dealloc_fn(co->saved_stack.ptr); co->saved_stack.ptr = NULL; - if (aco_dealloc_fn != NULL) - aco_dealloc_fn(co); + if (aco_dealloc_fn != NULL) aco_dealloc_fn(co); } } -public void aco_exit_fn(void*_) { - aco_exit(); -} +public +void aco_exit_fn(void *_) { aco_exit(); } diff --git a/examples/coroutines/aco.h b/examples/coroutines/aco.h index 80d5542b..6bdfb4dc 100644 --- a/examples/coroutines/aco.h +++ b/examples/coroutines/aco.h @@ -26,7 +26,7 @@ #include <unistd.h> #ifdef ACO_USE_VALGRIND - #include <valgrind/valgrind.h> +#include <valgrind/valgrind.h> #endif #ifdef __cplusplus @@ -38,30 +38,30 @@ extern "C" { #define ACO_VERSION_PATCH 0 #ifdef __i386__ - #define ACO_REG_IDX_RETADDR 0 - #define ACO_REG_IDX_SP 1 - #define ACO_REG_IDX_BP 2 - #define ACO_REG_IDX_ARG1 0 - #define ACO_REG_IDX_FPU 6 +#define ACO_REG_IDX_RETADDR 0 +#define ACO_REG_IDX_SP 1 +#define ACO_REG_IDX_BP 2 +#define ACO_REG_IDX_ARG1 0 +#define ACO_REG_IDX_FPU 6 #elif __x86_64__ - #define ACO_REG_IDX_RETADDR 4 - #define ACO_REG_IDX_SP 5 - #define ACO_REG_IDX_BP 7 - #define ACO_REG_IDX_EDI 8 - #define ACO_REG_IDX_FPU 8 +#define ACO_REG_IDX_RETADDR 4 +#define ACO_REG_IDX_SP 5 +#define ACO_REG_IDX_BP 7 +#define ACO_REG_IDX_EDI 8 +#define ACO_REG_IDX_FPU 8 #else - #error "platform not supported yet" +#error "platform not supported yet" #endif typedef struct { - void* ptr; + void *ptr; size_t sz; size_t valid_sz; // max copy size in bytes size_t max_cpsz; // copy from shared stack to this saved stack size_t ct_save; - // copy from this saved stack to shared stack + // copy from this saved stack to shared stack size_t ct_restore; } aco_saved_stack_t; @@ -69,16 +69,16 @@ struct aco_s; typedef struct aco_s aco_t; typedef struct { - void* ptr; + void *ptr; size_t sz; - void* align_highptr; - void* align_retptr; + void *align_highptr; + void *align_retptr; size_t align_validsz; size_t align_limit; - aco_t* owner; + aco_t *owner; bool guard_page_enabled; - void* real_ptr; + void *real_ptr; size_t real_sz; #ifdef ACO_USE_VALGRIND @@ -86,128 +86,126 @@ typedef struct { #endif } aco_shared_stack_t; -typedef void (*aco_cofuncp_t)(void*); +typedef void (*aco_cofuncp_t)(void *); struct aco_s { // cpu registers' state #ifdef __i386__ - #ifdef ACO_CONFIG_SHARE_FPU_MXCSR_ENV - void* reg[6]; - #else - void* reg[8]; - #endif +#ifdef ACO_CONFIG_SHARE_FPU_MXCSR_ENV + void *reg[6]; +#else + void *reg[8]; +#endif #elif __x86_64__ - #ifdef ACO_CONFIG_SHARE_FPU_MXCSR_ENV - void* reg[8]; - #else - void* reg[9]; - #endif +#ifdef ACO_CONFIG_SHARE_FPU_MXCSR_ENV + void *reg[8]; +#else + void *reg[9]; +#endif #else - #error "platform not supported yet" +#error "platform not supported yet" #endif - aco_t* main_co; - void* arg; - bool is_finished; + aco_t *main_co; + void *arg; + bool is_finished; aco_cofuncp_t fp; - - aco_saved_stack_t saved_stack; - aco_shared_stack_t* shared_stack; + + aco_saved_stack_t saved_stack; + aco_shared_stack_t *shared_stack; }; #define aco_likely(x) (__builtin_expect(!!(x), 1)) #define aco_unlikely(x) (__builtin_expect(!!(x), 0)) -#define aco_assert(EX) ((aco_likely(EX))?((void)0):(abort())) +#define aco_assert(EX) ((aco_likely(EX)) ? ((void)0) : (abort())) -#define aco_assertptr(ptr) ((aco_likely((ptr) != NULL))?((void)0):(abort())) +#define aco_assertptr(ptr) ((aco_likely((ptr) != NULL)) ? ((void)0) : (abort())) #if defined(aco_attr_no_asan) - #error "aco_attr_no_asan already defined" +#error "aco_attr_no_asan already defined" #endif #if defined(ACO_USE_ASAN) - #if defined(__has_feature) - #if __has_feature(__address_sanitizer__) - #define aco_attr_no_asan \ - __attribute__((__no_sanitize_address__)) - #endif - #endif - #if defined(__SANITIZE_ADDRESS__) && !defined(aco_attr_no_asan) - #define aco_attr_no_asan \ - __attribute__((__no_sanitize_address__)) - #endif +#if defined(__has_feature) +#if __has_feature(__address_sanitizer__) +#define aco_attr_no_asan __attribute__((__no_sanitize_address__)) +#endif +#endif +#if defined(__SANITIZE_ADDRESS__) && !defined(aco_attr_no_asan) +#define aco_attr_no_asan __attribute__((__no_sanitize_address__)) +#endif #endif #ifndef aco_attr_no_asan - #define aco_attr_no_asan +#define aco_attr_no_asan #endif void aco_runtime_test(void); -void aco_set_allocator(void* (*alloc)(size_t), void (*dealloc)(void*)); +void aco_set_allocator(void *(*alloc)(size_t), void (*dealloc)(void *)); void aco_thread_init(aco_cofuncp_t last_word_co_fp); -void aco_yield_asm(aco_t* from_co, aco_t* to_co) __asm__("aco_yield_asm"); // asm +void aco_yield_asm(aco_t *from_co, aco_t *to_co) __asm__("aco_yield_asm"); // asm -void aco_save_fpucw_mxcsr(void* p) __asm__("aco_save_fpucw_mxcsr"); // asm +void aco_save_fpucw_mxcsr(void *p) __asm__("aco_save_fpucw_mxcsr"); // asm void aco_funcp_protector_asm(void) __asm__("aco_funcp_protector_asm"); // asm void aco_funcp_protector(void); -aco_shared_stack_t* aco_shared_stack_new(size_t sz); +aco_shared_stack_t *aco_shared_stack_new(size_t sz); -aco_shared_stack_t* aco_shared_stack_new2(size_t sz, bool guard_page_enabled); +aco_shared_stack_t *aco_shared_stack_new2(size_t sz, bool guard_page_enabled); -void aco_shared_stack_destroy(aco_shared_stack_t* sstk); +void aco_shared_stack_destroy(aco_shared_stack_t *sstk); -aco_t* aco_create( - aco_t* main_co, - aco_shared_stack_t* shared_stack, - size_t saved_stack_sz, - aco_cofuncp_t fp, void* arg -); +aco_t *aco_create(aco_t *main_co, aco_shared_stack_t *shared_stack, size_t saved_stack_sz, aco_cofuncp_t fp, void *arg); // aco's Global Thread Local Storage variable `co` #ifdef __TINYC__ - #error "TinyCC doesn't support thread-local storage!" +#error "TinyCC doesn't support thread-local storage!" #else -extern __thread aco_t* aco_gtls_co; +extern __thread aco_t *aco_gtls_co; #endif -aco_attr_no_asan -void aco_resume(aco_t* resume_co); +aco_attr_no_asan void aco_resume(aco_t *resume_co); -//void aco_yield1(aco_t* yield_co); -#define aco_yield1(yield_co) do { \ - aco_assertptr((yield_co)); \ - aco_assertptr((yield_co)->main_co); \ - aco_yield_asm((yield_co), (yield_co)->main_co); \ -} while (0) +// void aco_yield1(aco_t* yield_co); +#define aco_yield1(yield_co) \ + do { \ + aco_assertptr((yield_co)); \ + aco_assertptr((yield_co)->main_co); \ + aco_yield_asm((yield_co), (yield_co)->main_co); \ + } while (0) #define aco_yield() aco_yield1(aco_gtls_co) #define aco_get_arg() (aco_gtls_co->arg) -#define aco_get_co() ({(void)0; aco_gtls_co;}) +#define aco_get_co() \ + ({ \ + (void)0; \ + aco_gtls_co; \ + }) -void aco_destroy(aco_t* co); +void aco_destroy(aco_t *co); -#define aco_is_main_co(co) ({((co)->main_co) == NULL;}) +#define aco_is_main_co(co) ({ ((co)->main_co) == NULL; }) -#define aco_exit1(co) do { \ - (co)->is_finished = true; \ - aco_assert((co)->shared_stack->owner == (co)); \ - (co)->shared_stack->owner = NULL; \ - (co)->shared_stack->align_validsz = 0; \ - aco_yield1((co)); \ - aco_assert(0); \ -} while (0) +#define aco_exit1(co) \ + do { \ + (co)->is_finished = true; \ + aco_assert((co)->shared_stack->owner == (co)); \ + (co)->shared_stack->owner = NULL; \ + (co)->shared_stack->align_validsz = 0; \ + aco_yield1((co)); \ + aco_assert(0); \ + } while (0) #define aco_exit() aco_exit1(aco_gtls_co) -void aco_exit_fn(void*); +void aco_exit_fn(void *); #ifdef __cplusplus } |
