Changeset eef8dfb for libcfa/src/concurrency/coroutine.cfa
- Timestamp:
- Jan 7, 2021, 2:55:57 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 58fe85a
- Parents:
- bdfc032 (diff), 44e37ef (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/coroutine.cfa
rbdfc032 reef8dfb 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu Dec 5 14:37:29 201913 // Update Count : 1512 // Last Modified On : Tue Dec 15 12:06:04 2020 13 // Update Count : 23 14 14 // 15 15 … … 18 18 #include "coroutine.hfa" 19 19 20 extern "C" {21 20 #include <stddef.h> 22 21 #include <malloc.h> … … 24 23 #include <string.h> 25 24 #include <unistd.h> 26 // use this define to make unwind.h play nice, definetely a hack 27 #define HIDE_EXPORTS 25 #include <sys/mman.h> // mprotect 28 26 #include <unwind.h> 29 #undef HIDE_EXPORTS30 #include <sys/mman.h>31 }32 27 33 28 #include "kernel_private.hfa" 29 #include "exception.hfa" 30 #include "math.hfa" 31 32 #define CFA_COROUTINE_USE_MMAP 0 34 33 35 34 #define __CFA_INVOKE_PRIVATE__ … … 37 36 38 37 extern "C" { 39 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc*) __attribute__ ((__noreturn__));38 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct $coroutine *) __attribute__ ((__noreturn__)); 40 39 static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) __attribute__ ((__noreturn__)); 41 40 static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) { … … 47 46 48 47 //----------------------------------------------------------------------------- 48 FORALL_DATA_INSTANCE(CoroutineCancelled, (dtype coroutine_t), (coroutine_t)) 49 50 forall(dtype T) 51 void mark_exception(CoroutineCancelled(T) *) {} 52 53 forall(dtype T) 54 void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) { 55 dst->virtual_table = src->virtual_table; 56 dst->the_coroutine = src->the_coroutine; 57 dst->the_exception = src->the_exception; 58 } 59 60 forall(dtype T) 61 const char * msg(CoroutineCancelled(T) *) { 62 return "CoroutineCancelled(...)"; 63 } 64 65 // This code should not be inlined. It is the error path on resume. 66 forall(dtype T | is_coroutine(T)) 67 void __cfaehm_cancelled_coroutine( T & cor, $coroutine * desc ) { 68 verify( desc->cancellation ); 69 desc->state = Cancelled; 70 exception_t * except = __cfaehm_cancellation_exception( desc->cancellation ); 71 72 // TODO: Remove explitate vtable set once trac#186 is fixed. 73 CoroutineCancelled(T) except; 74 except.virtual_table = &get_exception_vtable(&except); 75 except.the_coroutine = &cor; 76 except.the_exception = except; 77 throwResume except; 78 79 except->virtual_table->free( except ); 80 free( desc->cancellation ); 81 desc->cancellation = 0p; 82 } 83 84 //----------------------------------------------------------------------------- 49 85 // Global state variables 50 86 51 87 // minimum feasible stack size in bytes 52 #define MinStackSize 1000 88 static const size_t MinStackSize = 1000; 53 89 extern size_t __page_size; // architecture pagesize HACK, should go in proper runtime singleton 90 extern int __map_prot; 54 91 55 92 void __stack_prepare( __stack_info_t * this, size_t create_size ); 93 void __stack_clean ( __stack_info_t * this ); 56 94 57 95 //----------------------------------------------------------------------------- … … 74 112 bool userStack = ((intptr_t)this.storage & 0x1) != 0; 75 113 if ( ! userStack && this.storage ) { 76 __attribute__((may_alias)) intptr_t * istorage = (intptr_t *)&this.storage; 77 *istorage &= (intptr_t)-1; 78 79 void * storage = this.storage->limit; 80 __cfaabi_dbg_debug_do( 81 storage = (char*)(storage) - __page_size; 82 if ( mprotect( storage, __page_size, PROT_READ | PROT_WRITE ) == -1 ) { 83 abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) ); 84 } 85 ); 86 __cfaabi_dbg_print_safe("Kernel : Deleting stack %p\n", storage); 87 free( storage ); 88 } 89 } 90 91 void ?{}( coroutine_desc & this, const char * name, void * storage, size_t storageSize ) with( this ) { 114 __stack_clean( &this ); 115 } 116 } 117 118 void ?{}( $coroutine & this, const char name[], void * storage, size_t storageSize ) with( this ) { 92 119 (this.context){0p, 0p}; 93 120 (this.stack){storage, storageSize}; … … 99 126 } 100 127 101 void ^?{}( coroutine_desc& this) {128 void ^?{}($coroutine& this) { 102 129 if(this.state != Halted && this.state != Start && this.state != Primed) { 103 coroutine_desc * src = TL_GET( this_thread )->curr_cor;104 coroutine_desc* dst = &this;130 $coroutine * src = active_coroutine(); 131 $coroutine * dst = &this; 105 132 106 133 struct _Unwind_Exception storage; … … 115 142 } 116 143 117 CoroutineCtxSwitch( src, dst );144 $ctx_switch( src, dst ); 118 145 } 119 146 } … … 123 150 forall(dtype T | is_coroutine(T)) 124 151 void prime(T& cor) { 125 coroutine_desc* this = get_coroutine(cor);152 $coroutine* this = get_coroutine(cor); 126 153 assert(this->state == Start); 127 154 … … 134 161 assert(__page_size != 0l); 135 162 size_t size = libCeiling( storageSize, 16 ) + stack_data_size; 163 size = ceiling(size, __page_size); 136 164 137 165 // If we are running debug, we also need to allocate a guardpage to catch stack overflows. 138 166 void * storage; 139 __cfaabi_dbg_debug_do( 140 storage = memalign( __page_size, size + __page_size ); 141 ); 142 __cfaabi_dbg_no_debug_do( 143 storage = (void*)malloc(size); 144 ); 145 167 #if CFA_COROUTINE_USE_MMAP 168 storage = mmap(0p, size + __page_size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 169 if(storage == ((void*)-1)) { 170 abort( "coroutine stack creation : internal error, mmap failure, error(%d) %s.", errno, strerror( errno ) ); 171 } 172 if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) { 173 abort( "coroutine stack creation : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) ); 174 } // if 175 storage = (void *)(((intptr_t)storage) + __page_size); 176 #else 177 __cfaabi_dbg_debug_do( 178 storage = memalign( __page_size, size + __page_size ); 179 ); 180 __cfaabi_dbg_no_debug_do( 181 storage = (void*)malloc(size); 182 ); 183 184 __cfaabi_dbg_debug_do( 185 if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) { 186 abort( "__stack_alloc : internal error, mprotect failure, error(%d) %s.", (int)errno, strerror( (int)errno ) ); 187 } 188 storage = (void *)(((intptr_t)storage) + __page_size); 189 ); 190 #endif 146 191 __cfaabi_dbg_print_safe("Kernel : Created stack %p of size %zu\n", storage, size); 147 __cfaabi_dbg_debug_do(148 if ( mprotect( storage, __page_size, PROT_NONE ) == -1 ) {149 abort( "__stack_alloc : internal error, mprotect failure, error(%d) %s.", (int)errno, strerror( (int)errno ) );150 }151 storage = (void *)(((intptr_t)storage) + __page_size);152 );153 192 154 193 verify( ((intptr_t)storage & (libAlign() - 1)) == 0ul ); 155 194 return [storage, size]; 195 } 196 197 void __stack_clean ( __stack_info_t * this ) { 198 size_t size = ((intptr_t)this->storage->base) - ((intptr_t)this->storage->limit) + sizeof(__stack_t); 199 void * storage = this->storage->limit; 200 201 #if CFA_COROUTINE_USE_MMAP 202 storage = (void *)(((intptr_t)storage) - __page_size); 203 if(munmap(storage, size + __page_size) == -1) { 204 abort( "coroutine stack destruction : internal error, munmap failure, error(%d) %s.", errno, strerror( errno ) ); 205 } 206 #else 207 __cfaabi_dbg_debug_do( 208 storage = (char*)(storage) - __page_size; 209 if ( mprotect( storage, __page_size, __map_prot ) == -1 ) { 210 abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) ); 211 } 212 ); 213 214 free( storage ); 215 #endif 216 __cfaabi_dbg_print_safe("Kernel : Deleting stack %p\n", storage); 156 217 } 157 218 … … 175 236 size = libFloor(create_size - stack_data_size - diff, libAlign()); 176 237 } // if 177 assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of % d bytes for a stack.", size, MinStackSize );178 179 this->storage = (__stack_t *)((intptr_t)storage + size );238 assertf( size >= MinStackSize, "Stack size %zd provides less than minimum of %zd bytes for a stack.", size, MinStackSize ); 239 240 this->storage = (__stack_t *)((intptr_t)storage + size - sizeof(__stack_t)); 180 241 this->storage->limit = storage; 181 this->storage->base = (void*)((intptr_t)storage + size); 242 this->storage->base = (void*)((intptr_t)storage + size - sizeof(__stack_t)); 243 this->storage->exception_context.top_resume = 0p; 244 this->storage->exception_context.current_exception = 0p; 182 245 __attribute__((may_alias)) intptr_t * istorage = (intptr_t*)&this->storage; 183 246 *istorage |= userStack ? 0x1 : 0x0; … … 187 250 // is not inline (We can't inline Cforall in C) 188 251 extern "C" { 189 void __ leave_coroutine( struct coroutine_desc* src ) {190 coroutine_desc* starter = src->cancellation != 0 ? src->last : src->starter;252 void __cfactx_cor_leave( struct $coroutine * src ) { 253 $coroutine * starter = src->cancellation != 0 ? src->last : src->starter; 191 254 192 255 src->state = Halted; … … 201 264 src->name, src, starter->name, starter ); 202 265 203 CoroutineCtxSwitch( src, starter );204 } 205 206 struct coroutine_desc * __finish_coroutine(void) {207 struct coroutine_desc * cor = kernelTLS.this_thread->curr_cor;266 $ctx_switch( src, starter ); 267 } 268 269 struct $coroutine * __cfactx_cor_finish(void) { 270 struct $coroutine * cor = active_coroutine(); 208 271 209 272 if(cor->state == Primed) { 210 suspend();273 __cfactx_suspend(); 211 274 } 212 275
Note:
See TracChangeset
for help on using the changeset viewer.