Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/locks.hfa

    r6b33e89 ra6b48f6  
    1111// Created On       : Thu Jan 21 19:46:50 2021
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Fri Apr 25 07:14:16 2025
    14 // Update Count     : 22
     13// Last Modified On : Tue Dec 24 09:36:52 2024
     14// Update Count     : 16
    1515//
    1616
     
    5656
    5757static inline void pre_park_then_park( __cfa_pre_park pp_fn, void * pp_datum ) {
    58         pp_fn( pp_datum );
    59         park();
     58    pp_fn( pp_datum );
     59    park();
    6060}
    6161
     
    6363
    6464#define DEFAULT_ON_NOTIFY( lock_type ) \
    65         static inline void on_notify( lock_type & /*this*/, thread$ * t ){ unpark( t ); }
     65    static inline void on_notify( lock_type & /*this*/, thread$ * t ){ unpark( t ); }
    6666
    6767#define DEFAULT_ON_WAIT( lock_type ) \
    68         static inline size_t on_wait( lock_type & this, __cfa_pre_park pp_fn, void * pp_datum ) { \
    69                 unlock( this ); \
    70                 pre_park_then_park( pp_fn, pp_datum ); \
    71                 return 0; \
    72         }
     68    static inline size_t on_wait( lock_type & this, __cfa_pre_park pp_fn, void * pp_datum ) { \
     69        unlock( this ); \
     70        pre_park_then_park( pp_fn, pp_datum ); \
     71        return 0; \
     72    }
    7373
    7474// on_wakeup impl if lock should be reacquired after waking up
    7575#define DEFAULT_ON_WAKEUP_REACQ( lock_type ) \
    76         static inline void on_wakeup( lock_type & this, size_t /*recursion*/ ) { lock( this ); }
     76    static inline void on_wakeup( lock_type & this, size_t /*recursion*/ ) { lock( this ); }
    7777
    7878// on_wakeup impl if lock will not be reacquired after waking up
    7979#define DEFAULT_ON_WAKEUP_NO_REACQ( lock_type ) \
    80         static inline void on_wakeup( lock_type & /*this*/, size_t /*recursion*/ ) {}
     80    static inline void on_wakeup( lock_type & /*this*/, size_t /*recursion*/ ) {}
    8181
    8282
     
    142142static inline void ?{}( mcs_node & this ) { this.next = 0p; }
    143143
    144 static inline mcs_node * volatile & next( mcs_node * node ) {
     144static inline mcs_node * volatile & ?`next ( mcs_node * node ) {
    145145        return node->next;
    146146}
     
    156156
    157157static inline void unlock( mcs_lock & l, mcs_node & n ) {
    158         mcs_node * nxt = advance( l.queue, &n );
    159         if ( nxt ) post( nxt->sem );
     158        mcs_node * next = advance( l.queue, &n );
     159        if ( next ) post( next->sem );
    160160}
    161161
     
    181181
    182182static inline void lock( mcs_spin_lock & l, mcs_spin_node & n ) {
    183         n.locked = true;
     183    n.locked = true;
    184184
    185185        #if defined( __ARM_ARCH )
     
    187187        #endif
    188188
    189         mcs_spin_node * prev_val = __atomic_exchange_n( &l.queue.tail, &n, __ATOMIC_SEQ_CST );
    190         if ( prev_val == 0p ) return;
    191         prev_val->next = &n;
     189        mcs_spin_node * prev = __atomic_exchange_n( &l.queue.tail, &n, __ATOMIC_SEQ_CST );
     190        if ( prev == 0p ) return;
     191        prev->next = &n;
    192192       
    193193        #if defined( __ARM_ARCH )
     
    234234// to use for FUTEX_WAKE and FUTEX_WAIT (other futex calls will need more params)
    235235static inline int futex( int *uaddr, int futex_op, int val ) {
    236         return syscall( SYS_futex, uaddr, futex_op, val, NULL, NULL, 0 );
     236    return syscall( SYS_futex, uaddr, futex_op, val, NULL, NULL, 0 );
    237237}
    238238
     
    271271static inline void unlock( futex_mutex & this ) with( this ) {
    272272        // if uncontended do atomic unlock and then return
    273         if ( __atomic_exchange_n( &val, 0, __ATOMIC_RELEASE ) == 1 ) return;
     273    if ( __atomic_exchange_n( &val, 0, __ATOMIC_RELEASE ) == 1 ) return;
    274274       
    275275        // otherwise threads are blocked so we must wake one
     
    311311        int state, init_state;
    312312
    313         // speculative grab
    314         state = internal_exchange( this, 1 );
    315         if ( ! state ) return;                                                          // state == 0
    316         init_state = state;
    317         for () {
    318                 for ( 4 ) {
    319                         while ( ! val ) {                                                       // lock unlocked
    320                                 state = 0;
    321                                 if ( internal_try_lock( this, state, init_state ) ) return;
    322                         }
    323                         for ( 30 ) Pause();
    324                 }
    325 
    326                 while ( ! val ) {                                                               // lock unlocked
    327                         state = 0;
    328                         if ( internal_try_lock( this, state, init_state ) ) return;
    329                 }
    330                 sched_yield();
    331                
    332                 // if not in contended state, set to be in contended state
    333                 state = internal_exchange( this, 2 );
    334                 if ( ! state ) return;                                                  // state == 0
    335                 init_state = 2;
    336                 futex( (int*)&val, FUTEX_WAIT, 2 );                             // if val is not 2 this returns with EWOULDBLOCK
    337         }
     313    // speculative grab
     314    state = internal_exchange( this, 1 );
     315    if ( ! state ) return;                                                              // state == 0
     316    init_state = state;
     317    for () {
     318        for ( 4 ) {
     319            while ( ! val ) {                                                   // lock unlocked
     320                state = 0;
     321                if ( internal_try_lock( this, state, init_state ) ) return;
     322            }
     323            for ( 30 ) Pause();
     324        }
     325
     326        while ( ! val ) {                                                               // lock unlocked
     327            state = 0;
     328            if ( internal_try_lock( this, state, init_state ) ) return;
     329        }
     330        sched_yield();
     331       
     332        // if not in contended state, set to be in contended state
     333        state = internal_exchange( this, 2 );
     334        if ( ! state ) return;                                                  // state == 0
     335        init_state = 2;
     336        futex( (int*)&val, FUTEX_WAIT, 2 );                             // if val is not 2 this returns with EWOULDBLOCK
     337    }
    338338}
    339339
    340340static inline void unlock( go_mutex & this ) with( this ) {
    341341        // if uncontended do atomic unlock and then return
    342         if ( __atomic_exchange_n( &val, 0, __ATOMIC_RELEASE ) == 1 ) return;
     342    if ( __atomic_exchange_n( &val, 0, __ATOMIC_RELEASE ) == 1 ) return;
    343343       
    344344        // otherwise threads are blocked so we must wake one
     
    384384
    385385static inline bool block( exp_backoff_then_block_lock & this ) with( this ) {
    386         lock( spinlock __cfaabi_dbg_ctx2 );
    387         if ( __atomic_load_n( &lock_value, __ATOMIC_SEQ_CST ) != 2 ) {
    388                 unlock( spinlock );
    389                 return true;
    390         }
    391         insert_last( blocked_threads, *active_thread() );
    392         unlock( spinlock );
     386    lock( spinlock __cfaabi_dbg_ctx2 );
     387    if ( __atomic_load_n( &lock_value, __ATOMIC_SEQ_CST ) != 2 ) {
     388        unlock( spinlock );
     389        return true;
     390    }
     391    insert_last( blocked_threads, *active_thread() );
     392    unlock( spinlock );
    393393        park( );
    394394        return true;
     
    415415
    416416static inline void unlock( exp_backoff_then_block_lock & this ) with( this ) {
    417         if ( __atomic_exchange_n( &lock_value, 0, __ATOMIC_RELEASE ) == 1 ) return;
    418         lock( spinlock __cfaabi_dbg_ctx2 );
    419         thread$ * t = &remove_first( blocked_threads );
    420         unlock( spinlock );
    421         unpark( t );
     417    if ( __atomic_exchange_n( &lock_value, 0, __ATOMIC_RELEASE ) == 1 ) return;
     418    lock( spinlock __cfaabi_dbg_ctx2 );
     419    thread$ * t = &try_pop_front( blocked_threads );
     420    unlock( spinlock );
     421    unpark( t );
    422422}
    423423
     
    469469        lock( lock __cfaabi_dbg_ctx2 );
    470470        /* paranoid */ verifyf( held != false, "Attempt to release lock %p that isn't held", &this );
    471         thread$ * t = &remove_first( blocked_threads );
     471        thread$ * t = &try_pop_front( blocked_threads );
    472472        held = ( t ? true : false );
    473473        unpark( t );
     
    476476
    477477static inline void on_notify( fast_block_lock & this, struct thread$ * t ) with( this ) {
    478         lock( lock __cfaabi_dbg_ctx2 );
    479         insert_last( blocked_threads, *t );
    480         unlock( lock );
     478    lock( lock __cfaabi_dbg_ctx2 );
     479    insert_last( blocked_threads, *t );
     480    unlock( lock );
    481481}
    482482DEFAULT_ON_WAIT( fast_block_lock )
     
    521521
    522522        if ( owner != 0p ) {
    523                 select_node node;
     523        select_node node;
    524524                insert_last( blocked_threads, node );
    525525                unlock( lock );
     
    533533
    534534static inline void pop_node( simple_owner_lock & this ) with( this ) {
    535         __handle_waituntil_OR( blocked_threads );
    536         select_node * node = &remove_first( blocked_threads );
    537         if ( node ) {
    538                 owner = node->blocked_thread;
    539                 recursion_count = 1;
    540                 // if ( ! node->clause_status || __make_select_node_available( *node ) ) unpark( node->blocked_thread );
    541                 wake_one( blocked_threads, *node );
    542         } else {
    543                 owner = 0p;
    544                 recursion_count = 0;
    545         }
     535    __handle_waituntil_OR( blocked_threads );
     536    select_node * node = &try_pop_front( blocked_threads );
     537    if ( node ) {
     538        owner = node->blocked_thread;
     539        recursion_count = 1;
     540        // if ( ! node->clause_status || __make_select_node_available( *node ) ) unpark( node->blocked_thread );
     541        wake_one( blocked_threads, *node );
     542    } else {
     543        owner = 0p;
     544        recursion_count = 0;
     545    }
    546546}
    547547
     
    582582        pop_node( this );
    583583
    584         select_node node;
    585         active_thread()->link_node = (void *)&node;
     584    select_node node;
     585    active_thread()->link_node = (void *)&node;
    586586        unlock( lock );
    587587
    588         pre_park_then_park( pp_fn, pp_datum );
     588    pre_park_then_park( pp_fn, pp_datum );
    589589
    590590        return ret;
     
    595595// waituntil() support
    596596static inline bool register_select( simple_owner_lock & this, select_node & node ) with( this ) {
    597         lock( lock __cfaabi_dbg_ctx2 );
    598 
    599         // check if we can complete operation. If so race to establish winner in special OR case
    600         if ( ! node.park_counter && ( owner == active_thread() || owner == 0p ) ) {
    601                 if ( ! __make_select_node_available( node ) ) { // we didn't win the race so give up on registering
    602                         unlock( lock );
    603                         return false;
    604                 }
    605         }
    606 
    607         if ( owner == active_thread() ) {
     597    lock( lock __cfaabi_dbg_ctx2 );
     598
     599    // check if we can complete operation. If so race to establish winner in special OR case
     600    if ( ! node.park_counter && ( owner == active_thread() || owner == 0p ) ) {
     601        if ( ! __make_select_node_available( node ) ) { // we didn't win the race so give up on registering
     602           unlock( lock );
     603           return false;
     604        }
     605    }
     606
     607    if ( owner == active_thread() ) {
    608608                recursion_count++;
    609                 if ( node.park_counter ) __make_select_node_available( node );
    610                 unlock( lock );
     609        if ( node.park_counter ) __make_select_node_available( node );
     610        unlock( lock );
    611611                return true;
    612612        }
    613613
    614         if ( owner != 0p ) {
     614    if ( owner != 0p ) {
    615615                insert_last( blocked_threads, node );
    616616                unlock( lock );
    617617                return false;
    618618        }
    619        
     619   
    620620        owner = active_thread();
    621621        recursion_count = 1;
    622622
    623         if ( node.park_counter ) __make_select_node_available( node );
    624         unlock( lock );
    625         return true;
     623    if ( node.park_counter ) __make_select_node_available( node );
     624    unlock( lock );
     625    return true;
    626626}
    627627
    628628static inline bool unregister_select( simple_owner_lock & this, select_node & node ) with( this ) {
    629         lock( lock __cfaabi_dbg_ctx2 );
    630         if ( isListed( node ) ) {
    631                 remove( node );
    632                 unlock( lock );
    633                 return false;
    634         }
    635 
    636         if ( owner == active_thread() ) {
    637                 recursion_count--;
    638                 if ( recursion_count == 0 ) {
    639                         pop_node( this );
    640                 }
    641         }
    642         unlock( lock );
    643         return false;
     629    lock( lock __cfaabi_dbg_ctx2 );
     630    if ( node`isListed ) {
     631        remove( node );
     632        unlock( lock );
     633        return false;
     634    }
     635
     636    if ( owner == active_thread() ) {
     637        recursion_count--;
     638        if ( recursion_count == 0 ) {
     639            pop_node( this );
     640        }
     641    }
     642    unlock( lock );
     643    return false;
    644644}
    645645
Note: See TracChangeset for help on using the changeset viewer.