- File:
-
- 1 edited
-
libcfa/src/concurrency/coroutine.cfa (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/coroutine.cfa
r6b33e89 r5251c6b 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Apr 25 06:48:19 202513 // Update Count : 3112 // Last Modified On : Mon Sep 18 21:47:12 2023 13 // Update Count : 25 14 14 // 15 15 … … 82 82 // helper for popping from coroutine's ehm buffer 83 83 static nonlocal_exception * pop_ehm_head( coroutine$ * this ) { 84 lock( this->ehm_state.buffer_lock __cfaabi_dbg_ctx2 );85 nonlocal_exception * nl_ex = pop_head( this->ehm_state.ehm_buffer );86 unlock( this->ehm_state.buffer_lock );87 return nl_ex;84 lock( this->ehm_state.buffer_lock __cfaabi_dbg_ctx2 ); 85 nonlocal_exception * nl_ex = pop_head( this->ehm_state.ehm_buffer ); 86 unlock( this->ehm_state.buffer_lock ); 87 return nl_ex; 88 88 } 89 89 … … 97 97 98 98 void __stack_prepare( __stack_info_t * this, size_t create_size ); 99 static void __stack_clean ( __stack_info_t * this );99 static void __stack_clean ( __stack_info_t * this ); 100 100 101 101 //----------------------------------------------------------------------------- … … 105 105 106 106 // Did we get a piece of storage ? 107 if ( this.storage || storageSize != 0) {107 if (this.storage || storageSize != 0) { 108 108 // We either got a piece of storage or the user asked for a specific size 109 109 // Immediately create the stack … … 128 128 state = Start; 129 129 starter = 0p; 130 this.last = 0p;130 last = 0p; 131 131 cancellation = 0p; 132 ehm_state.ehm_buffer{}; 133 ehm_state.buffer_lock{}; 134 ehm_state.ehm_enabled = false; 135 } 136 137 void ^?{}( coroutine$ & this ) libcfa_public { 138 // handle any leftover pending non-local exceptions 139 nonlocal_exception * nl_ex = pop_ehm_head( &this ); 140 unsigned unhandled_ex = 0; 141 142 // if any leftover exceptions handle 143 for ( ; nl_ex != 0p; nl_ex = pop_ehm_head( &this ) ) { 144 unhandled_ex++; 145 free( nl_ex->the_exception ); 146 free( nl_ex ); 147 } 148 149 #ifdef __CFA_DEBUG__ 150 if ( unhandled_ex > 0 ) 151 printf( "Warning: Coroutine %p exited with %u pending nonlocal exceptions.\n", &this, unhandled_ex ); 152 #endif 153 154 if ( this.state != Halted && this.state != Start && this.state != Primed ) { 132 ehm_state.ehm_buffer{}; 133 ehm_state.buffer_lock{}; 134 ehm_state.ehm_enabled = false; 135 } 136 137 void ^?{}(coroutine$& this) libcfa_public { 138 // handle any leftover pending non-local exceptions 139 nonlocal_exception * nl_ex = pop_ehm_head( &this ); 140 unsigned unhandled_ex = 0; 141 142 // if any leftover exceptions handle 143 while ( nl_ex != 0p ){ 144 unhandled_ex++; 145 free( nl_ex->the_exception ); 146 free( nl_ex ); 147 nl_ex = pop_ehm_head( &this ); 148 } 149 150 #ifdef __CFA_DEBUG__ 151 if ( unhandled_ex > 0 ) 152 printf( "Warning: Coroutine %p exited with %u pending nonlocal exceptions.\n", &this, unhandled_ex ); 153 #endif 154 155 if(this.state != Halted && this.state != Start && this.state != Primed) { 155 156 coroutine$ * src = active_coroutine(); 156 157 coroutine$ * dst = &this; … … 173 174 // Part of the Public API 174 175 // Not inline since only ever called once per coroutine 175 forall( T & | is_coroutine(T) | { EHM_DEFAULT_VTABLE(CoroutineCancelled(T)); })176 void prime( T & cor) libcfa_public {177 coroutine$ * this = get_coroutine(cor);178 assert( this->state == Start);176 forall(T & | is_coroutine(T) | { EHM_DEFAULT_VTABLE(CoroutineCancelled(T)); }) 177 void prime(T& cor) libcfa_public { 178 coroutine$* this = get_coroutine(cor); 179 assert(this->state == Start); 179 180 180 181 this->state = Primed; 181 resume( cor);182 resume(cor); 182 183 } 183 184 184 185 static [void *, size_t] __stack_alloc( size_t storageSize ) { 185 186 const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment 186 assert( __page_size != 0l);187 assert(__page_size != 0l); 187 188 size_t size = libCeiling( storageSize, 16 ) + stack_data_size; 188 size = ceiling( size, __page_size);189 size = ceiling(size, __page_size); 189 190 190 191 // If we are running debug, we also need to allocate a guardpage to catch stack overflows. … … 192 193 #if CFA_COROUTINE_USE_MMAP 193 194 storage = mmap(0p, size + __page_size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 194 if (storage == ((void*)-1)) {195 if(storage == ((void*)-1)) { 195 196 abort( "coroutine stack creation : internal error, mmap failure, error(%d) %s.", errno, strerror( errno ) ); 196 197 } … … 226 227 size_t size = ((intptr_t)this->storage->base) - ((intptr_t)this->storage->limit) + sizeof(__stack_t); 227 228 storage = (void *)(((intptr_t)storage) - __page_size); 228 if (munmap(storage, size + __page_size) == -1) {229 if(munmap(storage, size + __page_size) == -1) { 229 230 abort( "coroutine stack destruction : internal error, munmap failure, error(%d) %s.", errno, strerror( errno ) ); 230 231 } … … 247 248 void * storage; 248 249 size_t size; 249 if ( ! this->storage ) {250 if ( !this->storage ) { 250 251 userStack = false; 251 252 [storage, size] = __stack_alloc( create_size ); … … 301 302 athrd->corctx_flag = false; 302 303 303 if (cor->state == Primed) {304 if(cor->state == Primed) { 304 305 __cfactx_suspend(); 305 306 } … … 316 317 317 318 void defaultResumeAtHandler( exception_t * except ) { 318 __cfaehm_allocate_exception( except );319 __cfaehm_begin_unwind( (void(*)(exception_t *))defaultTerminationHandler );319 __cfaehm_allocate_exception( except ); 320 __cfaehm_begin_unwind( (void(*)(exception_t *))defaultTerminationHandler ); 320 321 } 321 322 … … 327 328 328 329 bool poll( coroutine$ * cor ) libcfa_public { 329 nonlocal_exception * nl_ex = pop_ehm_head( cor );330 331 // if no exceptions return false332 if ( nl_ex == 0p ) return false;333 334 // otherwise loop and throwResume all pending exceptions335 for ( ; nl_ex != 0p; nl_ex = pop_ehm_head( cor ) ){330 nonlocal_exception * nl_ex = pop_ehm_head( cor ); 331 332 // if no exceptions return false 333 if ( nl_ex == 0p ) return false; 334 335 // otherwise loop and throwResume all pending exceptions 336 while ( nl_ex != 0p ){ 336 337 ehm_cleanup ex_holder{ nl_ex->the_exception }; 337 free( nl_ex ); 338 __cfaehm_throw_resume( ex_holder.ex , defaultResumeAtHandler ); 339 } 340 341 return true; 338 free( nl_ex ); 339 __cfaehm_throw_resume( ex_holder.ex , defaultResumeAtHandler ); 340 341 nl_ex = pop_ehm_head( cor ); 342 } 343 344 return true; 342 345 } 343 346 … … 351 354 // user facing ehm operations 352 355 forall(T & | is_coroutine(T)) { 353 // enable/disable non-local exceptions354 void enable_ehm( T & cor ) libcfa_public { get_coroutine( cor )->ehm_state.ehm_enabled = true; }355 void disable_ehm( T & cor ) libcfa_public { get_coroutine( cor )->ehm_state.ehm_enabled = false; }356 357 // poll for non-local exceptions358 bool poll( T & cor ) libcfa_public { return poll( get_coroutine( cor ) ); }359 360 // poll iff nonlocal ehm is enabled361 bool checked_poll( T & cor ) libcfa_public { return get_coroutine( cor )->ehm_state.ehm_enabled ? poll( cor ) : false; }362 363 coroutine$ * resumer( T & cor ) libcfa_public { return get_coroutine( cor )->last; }364 coroutine$ * first_resumer( T & cor ) libcfa_public { return get_coroutine( cor )->starter; }356 // enable/disable non-local exceptions 357 void enable_ehm( T & cor ) libcfa_public { get_coroutine( cor )->ehm_state.ehm_enabled = true; } 358 void disable_ehm( T & cor ) libcfa_public { get_coroutine( cor )->ehm_state.ehm_enabled = false; } 359 360 // poll for non-local exceptions 361 bool poll( T & cor ) libcfa_public { return poll( get_coroutine( cor ) ); } 362 363 // poll iff nonlocal ehm is enabled 364 bool checked_poll( T & cor ) libcfa_public { return get_coroutine( cor )->ehm_state.ehm_enabled ? poll( cor ) : false; } 365 366 coroutine$ * resumer( T & cor ) libcfa_public { return get_coroutine( cor )->last; } 367 coroutine$ * first_resumer( T & cor ) libcfa_public { return get_coroutine( cor )->starter; } 365 368 } 366 369 … … 368 371 forall(exceptT *, T & | ehm_resume_at( exceptT, T )) 369 372 void resumeAt( T & receiver, exceptT & ex ) libcfa_public { 370 coroutine$ * cor = get_coroutine( receiver );371 nonlocal_exception * nl_ex = alloc();372 exceptT * ex_copy = alloc();373 memcpy( ex_copy, &ex, sizeof(exceptT) );374 (*nl_ex){ (exception_t *)ex_copy };375 lock( cor->ehm_state.buffer_lock __cfaabi_dbg_ctx2 );376 append( cor->ehm_state.ehm_buffer, nl_ex );377 unlock( cor->ehm_state.buffer_lock );373 coroutine$ * cor = get_coroutine( receiver ); 374 nonlocal_exception * nl_ex = alloc(); 375 exceptT * ex_copy = alloc(); 376 memcpy( ex_copy, &ex, sizeof(exceptT) ); 377 (*nl_ex){ (exception_t *)ex_copy }; 378 lock( cor->ehm_state.buffer_lock __cfaabi_dbg_ctx2 ); 379 append( cor->ehm_state.ehm_buffer, nl_ex ); 380 unlock( cor->ehm_state.buffer_lock ); 378 381 } 379 382 380 383 forall(exceptT * | { void $throwResume(exceptT &); }) 381 384 void resumeAt( coroutine$ * receiver, exceptT & ex ) libcfa_public { 382 nonlocal_exception * nl_ex = alloc();383 exceptT * ex_copy = alloc();384 memcpy( ex_copy, &ex, sizeof(exceptT) );385 (*nl_ex){ (exception_t *)ex_copy };386 lock( receiver->ehm_state.buffer_lock __cfaabi_dbg_ctx2 );387 append( receiver->ehm_state.ehm_buffer, nl_ex );388 unlock( receiver->ehm_state.buffer_lock );385 nonlocal_exception * nl_ex = alloc(); 386 exceptT * ex_copy = alloc(); 387 memcpy( ex_copy, &ex, sizeof(exceptT) ); 388 (*nl_ex){ (exception_t *)ex_copy }; 389 lock( receiver->ehm_state.buffer_lock __cfaabi_dbg_ctx2 ); 390 append( receiver->ehm_state.ehm_buffer, nl_ex ); 391 unlock( receiver->ehm_state.buffer_lock ); 389 392 } 390 393
Note:
See TracChangeset
for help on using the changeset viewer.