2 // Copyright 2018 Sen Han <00hnes@gmail.com>
3 // Modifications copyright 2025 Bruce Hill <bruce@bruce-hill.com>
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
29 #ifdef ACO_USE_VALGRIND
30 #include <valgrind/valgrind.h>
37 #define ACO_VERSION_MAJOR 2
38 #define ACO_VERSION_MINOR 0
39 #define ACO_VERSION_PATCH 0
42 #define ACO_REG_IDX_RETADDR 0
43 #define ACO_REG_IDX_SP 1
44 #define ACO_REG_IDX_BP 2
45 #define ACO_REG_IDX_ARG1 0
46 #define ACO_REG_IDX_FPU 6
48 #define ACO_REG_IDX_RETADDR 4
49 #define ACO_REG_IDX_SP 5
50 #define ACO_REG_IDX_BP 7
51 #define ACO_REG_IDX_EDI 8
52 #define ACO_REG_IDX_FPU 8
54 #error "platform not supported yet"
61 // max copy size in bytes
63 // copy from shared stack to this saved stack
65 // copy from this saved stack to shared stack
70 typedef struct aco_s aco_t;
81 bool guard_page_enabled;
85 #ifdef ACO_USE_VALGRIND
86 unsigned long valgrind_stk_id;
90 typedef void (*aco_cofuncp_t)(void *);
93 // cpu registers' state
95 #ifdef ACO_CONFIG_SHARE_FPU_MXCSR_ENV
101 #ifdef ACO_CONFIG_SHARE_FPU_MXCSR_ENV
107 #error "platform not supported yet"
115 aco_saved_stack_t saved_stack;
116 aco_shared_stack_t *shared_stack;
119 #define aco_likely(x) (__builtin_expect(!!(x), 1))
121 #define aco_unlikely(x) (__builtin_expect(!!(x), 0))
123 #define aco_assert(EX) ((aco_likely(EX)) ? ((void)0) : (abort()))
125 #define aco_assertptr(ptr) ((aco_likely((ptr) != NULL)) ? ((void)0) : (abort()))
127 #if defined(aco_attr_no_asan)
128 #error "aco_attr_no_asan already defined"
130 #if defined(ACO_USE_ASAN)
131 #if defined(__has_feature)
132 #if __has_feature(__address_sanitizer__)
133 #define aco_attr_no_asan __attribute__((__no_sanitize_address__))
136 #if defined(__SANITIZE_ADDRESS__) && !defined(aco_attr_no_asan)
137 #define aco_attr_no_asan __attribute__((__no_sanitize_address__))
140 #ifndef aco_attr_no_asan
141 #define aco_attr_no_asan
144 void aco_runtime_test(void);
146 void aco_set_allocator(void *(*alloc)(size_t), void (*dealloc)(void *));
148 void aco_thread_init(aco_cofuncp_t last_word_co_fp);
150 void aco_yield_asm(aco_t *from_co, aco_t *to_co) __asm__("aco_yield_asm"); // asm
152 void aco_save_fpucw_mxcsr(void *p) __asm__("aco_save_fpucw_mxcsr"); // asm
154 void aco_funcp_protector_asm(void) __asm__("aco_funcp_protector_asm"); // asm
156 void aco_funcp_protector(void);
158 aco_shared_stack_t *aco_shared_stack_new(size_t sz);
160 aco_shared_stack_t *aco_shared_stack_new2(size_t sz, bool guard_page_enabled);
162 void aco_shared_stack_destroy(aco_shared_stack_t *sstk);
164 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);
166 // aco's Global Thread Local Storage variable `co`
168 #error "TinyCC doesn't support thread-local storage!"
170 extern __thread aco_t *aco_gtls_co;
173 aco_attr_no_asan void aco_resume(aco_t *resume_co);
175 // void aco_yield1(aco_t* yield_co);
176 #define aco_yield1(yield_co) \
178 aco_assertptr((yield_co)); \
179 aco_assertptr((yield_co)->main_co); \
180 aco_yield_asm((yield_co), (yield_co)->main_co); \
183 #define aco_yield() aco_yield1(aco_gtls_co)
185 #define aco_get_arg() (aco_gtls_co->arg)
187 #define aco_get_co() \
193 void aco_destroy(aco_t *co);
195 #define aco_is_main_co(co) ({ ((co)->main_co) == NULL; })
197 #define aco_exit1(co) \
199 (co)->is_finished = true; \
200 aco_assert((co)->shared_stack->owner == (co)); \
201 (co)->shared_stack->owner = NULL; \
202 (co)->shared_stack->align_validsz = 0; \
207 #define aco_exit() aco_exit1(aco_gtls_co)
209 void aco_exit_fn(void *);