Ignore:
File:
1 edited

Legend:

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

    rbeeff61e rbd72c284  
    3030#include "time.hfa"
    3131
    32 #include "select.hfa"
    33 
    3432#include <fstream.hfa>
    3533
     
    7270static inline void   on_wakeup( single_acquisition_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
    7371static inline void   on_notify( single_acquisition_lock & this, struct thread$ * t ) { on_notify( (blocking_lock &)this, t ); }
    74 static inline bool   register_select( single_acquisition_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); }
    75 static inline bool   unregister_select( single_acquisition_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); }
    76 static inline bool   on_selected( single_acquisition_lock & this, select_node & node ) { return on_selected( (blocking_lock &)this, node ); }
    7772
    7873//----------
     
    8984static inline void   on_wakeup( owner_lock & this, size_t v ) { on_wakeup ( (blocking_lock &)this, v ); }
    9085static inline void   on_notify( owner_lock & this, struct thread$ * t ) { on_notify( (blocking_lock &)this, t ); }
    91 static inline bool   register_select( owner_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); }
    92 static inline bool   unregister_select( owner_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); }
    93 static inline bool   on_selected( owner_lock & this, select_node & node ) { return on_selected( (blocking_lock &)this, node ); }
    9486
    9587//-----------------------------------------------------------------------------
     
    188180
    189181// if this is called recursively IT WILL DEADLOCK!!!!!
    190 static inline void lock( futex_mutex & this ) with(this) {
     182static inline void lock(futex_mutex & this) with(this) {
    191183        int state;
    192184
     
    198190                for (int i = 0; i < spin; i++) Pause();
    199191        }
     192
     193        // // no contention try to acquire
     194        // if (internal_try_lock(this, state)) return;
    200195       
    201196        // if not in contended state, set to be in contended state
     
    218213
    219214static inline void on_notify( futex_mutex & f, thread$ * t){ unpark(t); }
    220 static inline size_t on_wait( futex_mutex & f ) { unlock(f); park(); return 0; }
     215static inline size_t on_wait( futex_mutex & f ) {unlock(f); return 0;}
    221216
    222217// to set recursion count after getting signalled;
     
    249244
    250245// if this is called recursively IT WILL DEADLOCK!!!!!
    251 static inline void lock( go_mutex & this ) with( this ) {
     246static inline void lock(go_mutex & this) with(this) {
    252247        int state, init_state;
    253248
     
    260255            while( !val ) { // lock unlocked
    261256                state = 0;
    262                 if ( internal_try_lock( this, state, init_state ) ) return;
     257                if (internal_try_lock(this, state, init_state)) return;
    263258            }
    264259            for (int i = 0; i < 30; i++) Pause();
     
    267262        while( !val ) { // lock unlocked
    268263            state = 0;
    269             if ( internal_try_lock( this, state, init_state ) ) return;
     264            if (internal_try_lock(this, state, init_state)) return;
    270265        }
    271266        sched_yield();
    272267       
    273268        // if not in contended state, set to be in contended state
    274         state = internal_exchange( this, 2 );
     269        state = internal_exchange(this, 2);
    275270        if ( !state ) return; // state == 0
    276271        init_state = 2;
    277         futex( (int*)&val, FUTEX_WAIT, 2 ); // if val is not 2 this returns with EWOULDBLOCK
     272        futex((int*)&val, FUTEX_WAIT, 2); // if val is not 2 this returns with EWOULDBLOCK
    278273    }
    279274}
     
    281276static inline void unlock( go_mutex & this ) with(this) {
    282277        // if uncontended do atomic unlock and then return
    283     if ( __atomic_exchange_n(&val, 0, __ATOMIC_RELEASE) == 1 ) return;
     278    if (__atomic_exchange_n(&val, 0, __ATOMIC_RELEASE) == 1) return;
    284279       
    285280        // otherwise threads are blocked so we must wake one
    286         futex( (int *)&val, FUTEX_WAKE, 1 );
    287 }
    288 
    289 static inline void on_notify( go_mutex & f, thread$ * t){ unpark( t ); }
    290 static inline size_t on_wait( go_mutex & f ) { unlock( f ); park(); return 0; }
     281        futex((int *)&val, FUTEX_WAKE, 1);
     282}
     283
     284static inline void on_notify( go_mutex & f, thread$ * t){ unpark(t); }
     285static inline size_t on_wait( go_mutex & f ) {unlock(f); return 0;}
    291286static inline void on_wakeup( go_mutex & f, size_t recursion ) {}
     287
     288//-----------------------------------------------------------------------------
     289// CLH Spinlock
     290// - No recursive acquisition
     291// - Needs to be released by owner
     292
     293struct clh_lock {
     294        volatile bool * volatile tail;
     295    volatile bool * volatile head;
     296};
     297
     298static inline void  ?{}( clh_lock & this ) { this.tail = malloc(); *this.tail = true; }
     299static inline void ^?{}( clh_lock & this ) { free(this.tail); }
     300
     301static inline void lock(clh_lock & l) {
     302        thread$ * curr_thd = active_thread();
     303        *(curr_thd->clh_node) = false;
     304        volatile bool * prev = __atomic_exchange_n((bool **)(&l.tail), (bool *)(curr_thd->clh_node), __ATOMIC_SEQ_CST);
     305        while(!__atomic_load_n(prev, __ATOMIC_SEQ_CST)) Pause();
     306    __atomic_store_n((bool **)(&l.head), (bool *)curr_thd->clh_node, __ATOMIC_SEQ_CST);
     307    curr_thd->clh_node = prev;
     308}
     309
     310static inline void unlock(clh_lock & l) {
     311        __atomic_store_n((bool *)(l.head), true, __ATOMIC_SEQ_CST);
     312}
     313
     314static inline void on_notify(clh_lock & this, struct thread$ * t ) { unpark(t); }
     315static inline size_t on_wait(clh_lock & this) { unlock(this); return 0; }
     316static inline void on_wakeup(clh_lock & this, size_t recursion ) { lock(this); }
    292317
    293318//-----------------------------------------------------------------------------
     
    312337static inline void  ^?{}( exp_backoff_then_block_lock & this ){}
    313338
    314 static inline bool internal_try_lock( exp_backoff_then_block_lock & this, size_t & compare_val ) with(this) {
     339static inline bool internal_try_lock(exp_backoff_then_block_lock & this, size_t & compare_val) with(this) {
    315340        return __atomic_compare_exchange_n(&lock_value, &compare_val, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
    316341}
    317342
    318 static inline bool try_lock( exp_backoff_then_block_lock & this ) { size_t compare_val = 0; return internal_try_lock( this, compare_val ); }
    319 
    320 static inline bool try_lock_contention( exp_backoff_then_block_lock & this ) with(this) {
    321         return !__atomic_exchange_n( &lock_value, 2, __ATOMIC_ACQUIRE );
    322 }
    323 
    324 static inline bool block( exp_backoff_then_block_lock & this ) with(this) {
     343static inline bool try_lock(exp_backoff_then_block_lock & this) { size_t compare_val = 0; return internal_try_lock(this, compare_val); }
     344
     345static inline bool try_lock_contention(exp_backoff_then_block_lock & this) with(this) {
     346        return !__atomic_exchange_n(&lock_value, 2, __ATOMIC_ACQUIRE);
     347}
     348
     349static inline bool block(exp_backoff_then_block_lock & this) with(this) {
    325350    lock( spinlock __cfaabi_dbg_ctx2 );
    326351    if (__atomic_load_n( &lock_value, __ATOMIC_SEQ_CST) != 2) {
     
    334359}
    335360
    336 static inline void lock( exp_backoff_then_block_lock & this ) with(this) {
     361static inline void lock(exp_backoff_then_block_lock & this) with(this) {
    337362        size_t compare_val = 0;
    338363        int spin = 4;
     
    353378}
    354379
    355 static inline void unlock( exp_backoff_then_block_lock & this ) with(this) {
     380static inline void unlock(exp_backoff_then_block_lock & this) with(this) {
    356381    if (__atomic_exchange_n(&lock_value, 0, __ATOMIC_RELEASE) == 1) return;
    357382    lock( spinlock __cfaabi_dbg_ctx2 );
     
    361386}
    362387
    363 static inline void on_notify( exp_backoff_then_block_lock & this, struct thread$ * t ) { unpark( t ); }
    364 static inline size_t on_wait( exp_backoff_then_block_lock & this ) { unlock( this ); park(); return 0; }
    365 static inline void on_wakeup( exp_backoff_then_block_lock & this, size_t recursion ) { lock( this ); }
     388static inline void on_notify(exp_backoff_then_block_lock & this, struct thread$ * t ) { unpark(t); }
     389static inline size_t on_wait(exp_backoff_then_block_lock & this) { unlock(this); return 0; }
     390static inline void on_wakeup(exp_backoff_then_block_lock & this, size_t recursion ) { lock(this); }
    366391
    367392//-----------------------------------------------------------------------------
     
    393418
    394419// if this is called recursively IT WILL DEADLOCK!!!!!
    395 static inline void lock( fast_block_lock & this ) with(this) {
     420static inline void lock(fast_block_lock & this) with(this) {
    396421        lock( lock __cfaabi_dbg_ctx2 );
    397422        if ( held ) {
     
    405430}
    406431
    407 static inline void unlock( fast_block_lock & this ) with(this) {
     432static inline void unlock(fast_block_lock & this) with(this) {
    408433        lock( lock __cfaabi_dbg_ctx2 );
    409434        /* paranoid */ verifyf( held != false, "Attempt to release lock %p that isn't held", &this );
     
    414439}
    415440
    416 static inline void on_notify( fast_block_lock & this, struct thread$ * t ) with(this) {
     441static inline void on_notify(fast_block_lock & this, struct thread$ * t ) with(this) {
    417442    lock( lock __cfaabi_dbg_ctx2 );
    418443    insert_last( blocked_threads, *t );
    419444    unlock( lock );
    420445}
    421 static inline size_t on_wait( fast_block_lock & this) { unlock(this); park(); return 0; }
    422 static inline void on_wakeup( fast_block_lock & this, size_t recursion ) { }
     446static inline size_t on_wait(fast_block_lock & this) { unlock(this); return 0; }
     447static inline void on_wakeup(fast_block_lock & this, size_t recursion ) { }
    423448
    424449//-----------------------------------------------------------------------------
     
    431456struct simple_owner_lock {
    432457        // List of blocked threads
    433         dlist( select_node ) blocked_threads;
     458        dlist( thread$ ) blocked_threads;
    434459
    435460        // Spin lock used for mutual exclusion
     
    452477static inline void ?=?( simple_owner_lock & this, simple_owner_lock this2 ) = void;
    453478
    454 static inline void lock( simple_owner_lock & this ) with(this) {
    455         if ( owner == active_thread() ) {
     479static inline void lock(simple_owner_lock & this) with(this) {
     480        if (owner == active_thread()) {
    456481                recursion_count++;
    457482                return;
     
    459484        lock( lock __cfaabi_dbg_ctx2 );
    460485
    461         if ( owner != 0p ) {
    462         select_node node;
    463                 insert_last( blocked_threads, node );
     486        if (owner != 0p) {
     487                insert_last( blocked_threads, *active_thread() );
    464488                unlock( lock );
    465489                park( );
     
    471495}
    472496
    473 static inline void pop_node( simple_owner_lock & this ) with(this) {
    474     __handle_waituntil_OR( blocked_threads );
    475     select_node * node = &try_pop_front( blocked_threads );
    476     if ( node ) {
    477         owner = node->blocked_thread;
    478         recursion_count = 1;
    479         // if ( !node->clause_status || __make_select_node_available( *node ) ) unpark( node->blocked_thread );
    480         wake_one( blocked_threads, *node );
    481     } else {
    482         owner = 0p;
    483         recursion_count = 0;
    484     }
    485 }
    486 
    487 static inline void unlock( simple_owner_lock & this ) with(this) {
     497// TODO: fix duplicate def issue and bring this back
     498// void pop_and_set_new_owner( simple_owner_lock & this ) with( this ) {
     499        // thread$ * t = &try_pop_front( blocked_threads );
     500        // owner = t;
     501        // recursion_count = ( t ? 1 : 0 );
     502        // unpark( t );
     503// }
     504
     505static inline void unlock(simple_owner_lock & this) with(this) {
    488506        lock( lock __cfaabi_dbg_ctx2 );
    489507        /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
     
    492510        recursion_count--;
    493511        if ( recursion_count == 0 ) {
    494                 pop_node( this );
     512                // pop_and_set_new_owner( this );
     513                thread$ * t = &try_pop_front( blocked_threads );
     514                owner = t;
     515                recursion_count = ( t ? 1 : 0 );
     516                unpark( t );
    495517        }
    496518        unlock( lock );
    497519}
    498520
    499 static inline void on_notify(simple_owner_lock & this, thread$ * t ) with(this) {
     521static inline void on_notify(simple_owner_lock & this, struct thread$ * t ) with(this) {
    500522        lock( lock __cfaabi_dbg_ctx2 );
    501523        // lock held
    502524        if ( owner != 0p ) {
    503                 insert_last( blocked_threads, *(select_node *)t->link_node );
     525                insert_last( blocked_threads, *t );
    504526        }
    505527        // lock not held
     
    512534}
    513535
    514 static inline size_t on_wait( simple_owner_lock & this ) with(this) {
     536static inline size_t on_wait(simple_owner_lock & this) with(this) {
    515537        lock( lock __cfaabi_dbg_ctx2 );
    516538        /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this );
     
    519541        size_t ret = recursion_count;
    520542
    521         pop_node( this );
    522 
    523     select_node node;
    524     active_thread()->link_node = (void *)&node;
     543        // pop_and_set_new_owner( this );
     544
     545        thread$ * t = &try_pop_front( blocked_threads );
     546        owner = t;
     547        recursion_count = ( t ? 1 : 0 );
     548        unpark( t );
     549
    525550        unlock( lock );
    526     park();
    527 
    528551        return ret;
    529552}
    530553
    531 static inline void on_wakeup( simple_owner_lock & this, size_t recursion ) with(this) { recursion_count = recursion; }
    532 
    533 // waituntil() support
    534 static inline bool register_select( simple_owner_lock & this, select_node & node ) with(this) {
    535     lock( lock __cfaabi_dbg_ctx2 );
    536 
    537     // check if we can complete operation. If so race to establish winner in special OR case
    538     if ( !node.park_counter && ( owner == active_thread() || owner == 0p ) ) {
    539         if ( !__make_select_node_available( node ) ) { // we didn't win the race so give up on registering
    540            unlock( lock );
    541            return false;
    542         }
    543     }
    544 
    545     if ( owner == active_thread() ) {
    546                 recursion_count++;
    547         if ( node.park_counter ) __make_select_node_available( node );
    548         unlock( lock );
    549                 return true;
    550         }
    551 
    552     if ( owner != 0p ) {
    553                 insert_last( blocked_threads, node );
    554                 unlock( lock );
    555                 return false;
    556         }
    557    
    558         owner = active_thread();
    559         recursion_count = 1;
    560 
    561     if ( node.park_counter ) __make_select_node_available( node );
    562     unlock( lock );
    563     return true;
    564 }
    565 
    566 static inline bool unregister_select( simple_owner_lock & this, select_node & node ) with(this) {
    567     lock( lock __cfaabi_dbg_ctx2 );
    568     if ( node`isListed ) {
    569         remove( node );
    570         unlock( lock );
    571         return false;
    572     }
    573 
    574     if ( owner == active_thread() ) {
    575         recursion_count--;
    576         if ( recursion_count == 0 ) {
    577             pop_node( this );
    578         }
    579     }
    580     unlock( lock );
    581     return false;
    582 }
    583 
    584 static inline bool on_selected( simple_owner_lock & this, select_node & node ) { return true; }
    585 
     554static inline void on_wakeup(simple_owner_lock & this, size_t recursion ) with(this) { recursion_count = recursion; }
    586555
    587556//-----------------------------------------------------------------------------
     
    609578
    610579// if this is called recursively IT WILL DEADLOCK!
    611 static inline void lock( spin_queue_lock & this ) with(this) {
     580static inline void lock(spin_queue_lock & this) with(this) {
    612581        mcs_spin_node node;
    613582        lock( lock, node );
     
    617586}
    618587
    619 static inline void unlock( spin_queue_lock & this ) with(this) {
     588static inline void unlock(spin_queue_lock & this) with(this) {
    620589        __atomic_store_n(&held, false, __ATOMIC_RELEASE);
    621590}
    622591
    623 static inline void on_notify( spin_queue_lock & this, struct thread$ * t ) {
     592static inline void on_notify(spin_queue_lock & this, struct thread$ * t ) {
    624593        unpark(t);
    625594}
    626 static inline size_t on_wait( spin_queue_lock & this ) { unlock( this ); park(); return 0; }
    627 static inline void on_wakeup( spin_queue_lock & this, size_t recursion ) { lock( this ); }
     595static inline size_t on_wait(spin_queue_lock & this) { unlock(this); return 0; }
     596static inline void on_wakeup(spin_queue_lock & this, size_t recursion ) { lock(this); }
    628597
    629598
     
    652621
    653622// if this is called recursively IT WILL DEADLOCK!!!!!
    654 static inline void lock( mcs_block_spin_lock & this ) with(this) {
     623static inline void lock(mcs_block_spin_lock & this) with(this) {
    655624        mcs_node node;
    656625        lock( lock, node );
     
    664633}
    665634
    666 static inline void on_notify( mcs_block_spin_lock & this, struct thread$ * t ) { unpark( t ); }
    667 static inline size_t on_wait( mcs_block_spin_lock & this) { unlock( this ); park(); return 0; }
    668 static inline void on_wakeup( mcs_block_spin_lock & this, size_t recursion ) {lock( this ); }
     635static inline void on_notify(mcs_block_spin_lock & this, struct thread$ * t ) { unpark(t); }
     636static inline size_t on_wait(mcs_block_spin_lock & this) { unlock(this); return 0; }
     637static inline void on_wakeup(mcs_block_spin_lock & this, size_t recursion ) {lock(this); }
    669638
    670639//-----------------------------------------------------------------------------
     
    692661
    693662// if this is called recursively IT WILL DEADLOCK!!!!!
    694 static inline void lock( block_spin_lock & this ) with(this) {
     663static inline void lock(block_spin_lock & this) with(this) {
    695664        lock( lock );
    696665        while(__atomic_load_n(&held, __ATOMIC_SEQ_CST)) Pause();
     
    699668}
    700669
    701 static inline void unlock( block_spin_lock & this ) with(this) {
     670static inline void unlock(block_spin_lock & this) with(this) {
    702671        __atomic_store_n(&held, false, __ATOMIC_RELEASE);
    703672}
    704673
    705 static inline void on_notify( block_spin_lock & this, struct thread$ * t ) with(this.lock) {
     674static inline void on_notify(block_spin_lock & this, struct thread$ * t ) with(this.lock) {
    706675        // first we acquire internal fast_block_lock
    707676        lock( lock __cfaabi_dbg_ctx2 );
     
    717686        unpark(t);
    718687}
    719 static inline size_t on_wait( block_spin_lock & this ) { unlock( this ); park(); return 0; }
    720 static inline void on_wakeup( block_spin_lock & this, size_t recursion ) with(this) {
     688static inline size_t on_wait(block_spin_lock & this) { unlock(this); return 0; }
     689static inline void on_wakeup(block_spin_lock & this, size_t recursion ) with(this) {
    721690        // now we acquire the entire block_spin_lock upon waking up
    722691        while(__atomic_load_n(&held, __ATOMIC_SEQ_CST)) Pause();
     
    745714forall(L & | is_blocking_lock(L)) {
    746715        struct info_thread;
     716
     717        // // for use by sequence
     718        // info_thread(L) *& Back( info_thread(L) * this );
     719        // info_thread(L) *& Next( info_thread(L) * this );
    747720}
    748721
Note: See TracChangeset for help on using the changeset viewer.