- File:
-
- 1 edited
-
libcfa/src/concurrency/coroutine.cfa (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/coroutine.cfa
rdd92fe9 r09f357ec 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T ue Dec 15 12:06:04 202013 // Update Count : 2312 // Last Modified On : Thu Dec 5 14:37:29 2019 13 // Update Count : 15 14 14 // 15 15 … … 18 18 #include "coroutine.hfa" 19 19 20 extern "C" { 20 21 #include <stddef.h> 21 22 #include <malloc.h> … … 23 24 #include <string.h> 24 25 #include <unistd.h> 25 #include <sys/mman.h> // mprotect 26 // use this define to make unwind.h play nice, definetely a hack 27 #define HIDE_EXPORTS 26 28 #include <unwind.h> 29 #undef HIDE_EXPORTS 30 #include <sys/mman.h> 31 } 27 32 28 33 #include "kernel_private.hfa" 29 #include "exception.hfa"30 #include "math.hfa"31 32 #define CFA_COROUTINE_USE_MMAP 033 34 34 35 #define __CFA_INVOKE_PRIVATE__ … … 36 37 37 38 extern "C" { 38 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct $coroutine*) __attribute__ ((__noreturn__));39 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc *) __attribute__ ((__noreturn__)); 39 40 static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) __attribute__ ((__noreturn__)); 40 41 static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) { … … 46 47 47 48 //----------------------------------------------------------------------------- 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 //-----------------------------------------------------------------------------85 49 // Global state variables 86 50 87 51 // minimum feasible stack size in bytes 88 static const size_t MinStackSize = 1000; 52 #define MinStackSize 1000 89 53 extern size_t __page_size; // architecture pagesize HACK, should go in proper runtime singleton 90 extern int __map_prot;91 54 92 55 void __stack_prepare( __stack_info_t * this, size_t create_size ); 93 void __stack_clean ( __stack_info_t * this );94 56 95 57 //----------------------------------------------------------------------------- … … 112 74 bool userStack = ((intptr_t)this.storage & 0x1) != 0; 113 75 if ( ! userStack && this.storage ) { 114 __stack_clean( &this ); 115 } 116 } 117 118 void ?{}( $coroutine & this, const char name[], void * storage, size_t storageSize ) with( this ) { 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 ) { 119 92 (this.context){0p, 0p}; 120 93 (this.stack){storage, storageSize}; … … 126 99 } 127 100 128 void ^?{}( $coroutine& this) {101 void ^?{}(coroutine_desc& this) { 129 102 if(this.state != Halted && this.state != Start && this.state != Primed) { 130 $coroutine * src = active_coroutine();131 $coroutine* dst = &this;103 coroutine_desc * src = TL_GET( this_thread )->curr_cor; 104 coroutine_desc * dst = &this; 132 105 133 106 struct _Unwind_Exception storage; … … 142 115 } 143 116 144 $ctx_switch( src, dst );117 CoroutineCtxSwitch( src, dst ); 145 118 } 146 119 } … … 150 123 forall(dtype T | is_coroutine(T)) 151 124 void prime(T& cor) { 152 $coroutine* this = get_coroutine(cor);125 coroutine_desc* this = get_coroutine(cor); 153 126 assert(this->state == Start); 154 127 … … 161 134 assert(__page_size != 0l); 162 135 size_t size = libCeiling( storageSize, 16 ) + stack_data_size; 163 size = ceiling(size, __page_size);164 136 165 137 // If we are running debug, we also need to allocate a guardpage to catch stack overflows. 166 138 void * storage; 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 ) ); 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 146 __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 ) ); 171 150 } 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 } // if175 151 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 191 __cfaabi_dbg_print_safe("Kernel : Created stack %p of size %zu\n", storage, size); 152 ); 192 153 193 154 verify( ((intptr_t)storage & (libAlign() - 1)) == 0ul ); 194 155 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_MMAP202 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 #else207 __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 #endif216 __cfaabi_dbg_print_safe("Kernel : Deleting stack %p\n", storage);217 156 } 218 157 … … 236 175 size = libFloor(create_size - stack_data_size - diff, libAlign()); 237 176 } // if 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));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); 241 180 this->storage->limit = storage; 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; 181 this->storage->base = (void*)((intptr_t)storage + size); 245 182 __attribute__((may_alias)) intptr_t * istorage = (intptr_t*)&this->storage; 246 183 *istorage |= userStack ? 0x1 : 0x0; … … 250 187 // is not inline (We can't inline Cforall in C) 251 188 extern "C" { 252 void __ cfactx_cor_leave( struct $coroutine* src ) {253 $coroutine* starter = src->cancellation != 0 ? src->last : src->starter;189 void __leave_coroutine( struct coroutine_desc * src ) { 190 coroutine_desc * starter = src->cancellation != 0 ? src->last : src->starter; 254 191 255 192 src->state = Halted; … … 264 201 src->name, src, starter->name, starter ); 265 202 266 $ctx_switch( src, starter );267 } 268 269 struct $coroutine * __cfactx_cor_finish(void) {270 struct $coroutine * cor = active_coroutine();203 CoroutineCtxSwitch( src, starter ); 204 } 205 206 struct coroutine_desc * __finish_coroutine(void) { 207 struct coroutine_desc * cor = kernelTLS.this_thread->curr_cor; 271 208 272 209 if(cor->state == Primed) { 273 __cfactx_suspend();210 suspend(); 274 211 } 275 212
Note:
See TracChangeset
for help on using the changeset viewer.