Changeset 6b33e89 for libcfa/src/concurrency/coroutine.cfa
- Timestamp:
- Apr 25, 2025, 7:39:09 AM (8 months ago)
- Branches:
- master
- Children:
- 65bd3c2
- Parents:
- b195498
- File:
-
- 1 edited
-
libcfa/src/concurrency/coroutine.cfa (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/coroutine.cfa
rb195498 r6b33e89 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Sep 18 21:47:12 202313 // Update Count : 2512 // Last Modified On : Fri Apr 25 06:48:19 2025 13 // Update Count : 31 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 last = 0p;130 this.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 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) { 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 ) { 156 155 coroutine$ * src = active_coroutine(); 157 156 coroutine$ * dst = &this; … … 174 173 // Part of the Public API 175 174 // Not inline since only ever called once per coroutine 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);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 ); 180 179 181 180 this->state = Primed; 182 resume( cor);181 resume( cor ); 183 182 } 184 183 185 184 static [void *, size_t] __stack_alloc( size_t storageSize ) { 186 185 const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment 187 assert( __page_size != 0l);186 assert( __page_size != 0l ); 188 187 size_t size = libCeiling( storageSize, 16 ) + stack_data_size; 189 size = ceiling( size, __page_size);188 size = ceiling( size, __page_size ); 190 189 191 190 // If we are running debug, we also need to allocate a guardpage to catch stack overflows. … … 193 192 #if CFA_COROUTINE_USE_MMAP 194 193 storage = mmap(0p, size + __page_size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 195 if (storage == ((void*)-1)) {194 if (storage == ((void*)-1)) { 196 195 abort( "coroutine stack creation : internal error, mmap failure, error(%d) %s.", errno, strerror( errno ) ); 197 196 } … … 227 226 size_t size = ((intptr_t)this->storage->base) - ((intptr_t)this->storage->limit) + sizeof(__stack_t); 228 227 storage = (void *)(((intptr_t)storage) - __page_size); 229 if (munmap(storage, size + __page_size) == -1) {228 if (munmap(storage, size + __page_size) == -1) { 230 229 abort( "coroutine stack destruction : internal error, munmap failure, error(%d) %s.", errno, strerror( errno ) ); 231 230 } … … 248 247 void * storage; 249 248 size_t size; 250 if ( ! this->storage ) {249 if ( ! this->storage ) { 251 250 userStack = false; 252 251 [storage, size] = __stack_alloc( create_size ); … … 302 301 athrd->corctx_flag = false; 303 302 304 if (cor->state == Primed) {303 if (cor->state == Primed) { 305 304 __cfactx_suspend(); 306 305 } … … 317 316 318 317 void defaultResumeAtHandler( exception_t * except ) { 319 __cfaehm_allocate_exception( except );320 __cfaehm_begin_unwind( (void(*)(exception_t *))defaultTerminationHandler );318 __cfaehm_allocate_exception( except ); 319 __cfaehm_begin_unwind( (void(*)(exception_t *))defaultTerminationHandler ); 321 320 } 322 321 … … 328 327 329 328 bool poll( coroutine$ * cor ) libcfa_public { 330 nonlocal_exception * nl_ex = pop_ehm_head( cor );331 332 // if no exceptions return false333 if ( nl_ex == 0p ) return false;334 335 // otherwise loop and throwResume all pending exceptions336 while ( nl_ex != 0p ){329 nonlocal_exception * nl_ex = pop_ehm_head( cor ); 330 331 // if no exceptions return false 332 if ( nl_ex == 0p ) return false; 333 334 // otherwise loop and throwResume all pending exceptions 335 for ( ; nl_ex != 0p; nl_ex = pop_ehm_head( cor ) ) { 337 336 ehm_cleanup ex_holder{ nl_ex->the_exception }; 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; 337 free( nl_ex ); 338 __cfaehm_throw_resume( ex_holder.ex , defaultResumeAtHandler ); 339 } 340 341 return true; 345 342 } 346 343 … … 354 351 // user facing ehm operations 355 352 forall(T & | is_coroutine(T)) { 356 // enable/disable non-local exceptions357 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 exceptions361 bool poll( T & cor ) libcfa_public { return poll( get_coroutine( cor ) ); }362 363 // poll iff nonlocal ehm is enabled364 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; }353 // enable/disable non-local exceptions 354 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 exceptions 358 bool poll( T & cor ) libcfa_public { return poll( get_coroutine( cor ) ); } 359 360 // poll iff nonlocal ehm is enabled 361 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; } 368 365 } 369 366 … … 371 368 forall(exceptT *, T & | ehm_resume_at( exceptT, T )) 372 369 void resumeAt( T & receiver, exceptT & ex ) libcfa_public { 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 );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 ); 381 378 } 382 379 383 380 forall(exceptT * | { void $throwResume(exceptT &); }) 384 381 void resumeAt( coroutine$ * receiver, exceptT & ex ) libcfa_public { 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 );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 ); 392 389 } 393 390
Note:
See TracChangeset
for help on using the changeset viewer.