Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/coroutine.cfa

    r6b33e89 r5251c6b  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Apr 25 06:48:19 2025
    13 // Update Count     : 31
     12// Last Modified On : Mon Sep 18 21:47:12 2023
     13// Update Count     : 25
    1414//
    1515
     
    8282// helper for popping from coroutine's ehm buffer
    8383static 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;
    8888}
    8989
     
    9797
    9898void __stack_prepare( __stack_info_t * this, size_t create_size );
    99 static void __stack_clean( __stack_info_t * this );
     99static void __stack_clean  ( __stack_info_t * this );
    100100
    101101//-----------------------------------------------------------------------------
     
    105105
    106106        // Did we get a piece of storage ?
    107         if ( this.storage || storageSize != 0 ) {
     107        if (this.storage || storageSize != 0) {
    108108                // We either got a piece of storage or the user asked for a specific size
    109109                // Immediately create the stack
     
    128128        state = Start;
    129129        starter = 0p;
    130         this.last = 0p;
     130        last = 0p;
    131131        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
     137void ^?{}(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) {
    155156                coroutine$ * src = active_coroutine();
    156157                coroutine$ * dst = &this;
     
    173174// Part of the Public API
    174175// 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 );
     176forall(T & | is_coroutine(T) | { EHM_DEFAULT_VTABLE(CoroutineCancelled(T)); })
     177void prime(T& cor) libcfa_public {
     178        coroutine$* this = get_coroutine(cor);
     179        assert(this->state == Start);
    179180
    180181        this->state = Primed;
    181         resume( cor );
     182        resume(cor);
    182183}
    183184
    184185static [void *, size_t] __stack_alloc( size_t storageSize ) {
    185186        const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
    186         assert( __page_size != 0l );
     187        assert(__page_size != 0l);
    187188        size_t size = libCeiling( storageSize, 16 ) + stack_data_size;
    188         size = ceiling( size, __page_size );
     189        size = ceiling(size, __page_size);
    189190
    190191        // If we are running debug, we also need to allocate a guardpage to catch stack overflows.
     
    192193        #if CFA_COROUTINE_USE_MMAP
    193194                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)) {
    195196                        abort( "coroutine stack creation : internal error, mmap failure, error(%d) %s.", errno, strerror( errno ) );
    196197                }
     
    226227                size_t size = ((intptr_t)this->storage->base) - ((intptr_t)this->storage->limit) + sizeof(__stack_t);
    227228                storage = (void *)(((intptr_t)storage) - __page_size);
    228                 if (munmap(storage, size + __page_size) == -1) {
     229                if(munmap(storage, size + __page_size) == -1) {
    229230                        abort( "coroutine stack destruction : internal error, munmap failure, error(%d) %s.", errno, strerror( errno ) );
    230231                }
     
    247248        void * storage;
    248249        size_t size;
    249         if ( ! this->storage ) {
     250        if ( !this->storage ) {
    250251                userStack = false;
    251252                [storage, size] = __stack_alloc( create_size );
     
    301302                athrd->corctx_flag = false;
    302303
    303                 if (cor->state == Primed) {
     304                if(cor->state == Primed) {
    304305                        __cfactx_suspend();
    305306                }
     
    316317
    317318void 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 );
    320321}
    321322
     
    327328
    328329bool poll( coroutine$ * cor ) libcfa_public {
    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 ) ) {
     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 ){
    336337                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;
    342345}
    343346
     
    351354// user facing ehm operations
    352355forall(T & | is_coroutine(T)) {
    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; }
     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; }
    365368}
    366369
     
    368371forall(exceptT *, T & | ehm_resume_at( exceptT, T ))
    369372void 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 );
    378381}
    379382
    380383forall(exceptT * | { void $throwResume(exceptT &); })
    381384void 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 );
    389392}
    390393
Note: See TracChangeset for help on using the changeset viewer.