Ignore:
File:
1 edited

Legend:

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

    r490d17e0 r7f958c4  
    9898        mcs_node * next = advance(l.queue, &n);
    9999        if(next) post(next->sem);
    100 }
    101 
    102 //-----------------------------------------------------------------------------
    103 // MCS Spin Lock
    104 // - No recursive acquisition
    105 // - Needs to be released by owner
    106 
    107 struct mcs_spin_node {
    108         mcs_spin_node * volatile next;
    109         bool locked:1;
    110 };
    111 
    112 struct mcs_spin_queue {
    113         mcs_spin_node * volatile tail;
    114 };
    115 
    116 static inline void ?{}(mcs_spin_node & this) { this.next = 0p; this.locked = true; }
    117 
    118 static inline mcs_spin_node * volatile & ?`next ( mcs_spin_node * node ) {
    119         return node->next;
    120 }
    121 
    122 struct mcs_spin_lock {
    123         mcs_spin_queue queue;
    124 };
    125 
    126 static inline void lock(mcs_spin_lock & l, mcs_spin_node & n) {
    127         mcs_spin_node * prev = __atomic_exchange_n(&l.queue.tail, &n, __ATOMIC_SEQ_CST);
    128         if(prev != 0p) {
    129                 prev->next = &n;
    130                 while(n.locked) Pause();
    131         }
    132 }
    133 
    134 static inline void unlock(mcs_spin_lock & l, mcs_spin_node & n) {
    135         mcs_spin_node * n_ptr = &n;
    136         if (!__atomic_compare_exchange_n(&l.queue.tail, &n_ptr, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ) {
    137                 while (n.next == 0p) {}
    138                 n.next->locked = false;
    139         }
    140 }
    141 
    142 //-----------------------------------------------------------------------------
    143 // CLH Spinlock
    144 // - No recursive acquisition
    145 // - Needs to be released by owner
    146 
    147 struct clh_lock {
    148         volatile bool * volatile tail;
    149 };
    150 
    151 static inline void  ?{}( clh_lock & this ) { this.tail = malloc(); *this.tail = true; }
    152 static inline void ^?{}( clh_lock & this ) { free(this.tail); }
    153 
    154 static inline void lock(clh_lock & l) {
    155         thread$ * curr_thd = active_thread();
    156         *(curr_thd->clh_node) = false;
    157         volatile bool * prev = __atomic_exchange_n((bool **)(&l.tail), (bool *)(curr_thd->clh_node), __ATOMIC_SEQ_CST);
    158         while(!__atomic_load_n(prev, __ATOMIC_ACQUIRE)) Pause();
    159         curr_thd->clh_prev = prev;
    160 }
    161 
    162 static inline void unlock(clh_lock & l) {
    163         thread$ * curr_thd = active_thread();
    164         __atomic_store_n(curr_thd->clh_node, true, __ATOMIC_RELEASE);
    165         curr_thd->clh_node = curr_thd->clh_prev;
    166100}
    167101
     
    271205// Fast Block Lock
    272206
    273 // minimal blocking lock
     207// High efficiency minimal blocking lock
    274208// - No reacquire for cond var
    275209// - No recursive acquisition
    276210// - No ownership
    277211struct fast_block_lock {
     212        // Spin lock used for mutual exclusion
     213        __spinlock_t lock;
     214
    278215        // List of blocked threads
    279216        dlist( thread$ ) blocked_threads;
    280217
    281         // Spin lock used for mutual exclusion
    282         __spinlock_t lock;
    283 
    284         // flag showing if lock is held
    285218        bool held:1;
    286 
    287         #ifdef __CFA_DEBUG__
    288         // for deadlock detection
    289         struct thread$ * owner;
    290         #endif
    291219};
    292220
     
    303231static inline void lock(fast_block_lock & this) with(this) {
    304232        lock( lock __cfaabi_dbg_ctx2 );
    305 
    306         #ifdef __CFA_DEBUG__
    307         assert(!(held && owner == active_thread()));
    308         #endif
    309233        if (held) {
    310234                insert_last( blocked_threads, *active_thread() );
     
    314238        }
    315239        held = true;
    316         #ifdef __CFA_DEBUG__
    317         owner = active_thread();
    318         #endif
    319240        unlock( lock );
    320241}
     
    325246        thread$ * t = &try_pop_front( blocked_threads );
    326247        held = ( t ? true : false );
    327         #ifdef __CFA_DEBUG__
    328         owner = ( t ? t : 0p );
    329         #endif
    330248        unpark( t );
    331249        unlock( lock );
     
    335253static inline size_t on_wait(fast_block_lock & this) { unlock(this); return 0; }
    336254static inline void on_wakeup(fast_block_lock & this, size_t recursion ) { }
    337 
    338 //-----------------------------------------------------------------------------
    339 // simple_owner_lock
    340 
    341 // pthread owner lock
    342 // - reacquire for cond var
    343 // - recursive acquisition
    344 // - ownership
    345 struct simple_owner_lock {
    346         // List of blocked threads
    347         dlist( thread$ ) blocked_threads;
    348 
    349         // Spin lock used for mutual exclusion
    350         __spinlock_t lock;
    351 
    352         // owner showing if lock is held
    353         struct thread$ * owner;
    354 
    355         size_t recursion_count;
    356 };
    357 
    358 static inline void  ?{}( simple_owner_lock & this ) with(this) {
    359         lock{};
    360         blocked_threads{};
    361         owner = 0p;
    362         recursion_count = 0;
    363 }
    364 static inline void ^?{}( simple_owner_lock & this ) {}
    365 static inline void ?{}( simple_owner_lock & this, simple_owner_lock this2 ) = void;
    366 static inline void ?=?( simple_owner_lock & this, simple_owner_lock this2 ) = void;
    367 
    368 //-----------------------------------------------------------------------------
    369 // Spin Queue Lock
    370 
    371 // - No reacquire for cond var
    372 // - No recursive acquisition
    373 // - No ownership
    374 // - spin lock with no locking/atomics in unlock
    375 struct spin_queue_lock {
    376         // Spin lock used for mutual exclusion
    377         mcs_spin_lock lock;
    378 
    379         // flag showing if lock is held
    380         bool held:1;
    381 
    382         #ifdef __CFA_DEBUG__
    383         // for deadlock detection
    384         struct thread$ * owner;
    385         #endif
    386 };
    387 
    388 static inline void  ?{}( spin_queue_lock & this ) with(this) {
    389         lock{};
    390         held = false;
    391 }
    392 static inline void ^?{}( spin_queue_lock & this ) {}
    393 static inline void ?{}( spin_queue_lock & this, spin_queue_lock this2 ) = void;
    394 static inline void ?=?( spin_queue_lock & this, spin_queue_lock this2 ) = void;
    395 
    396 // if this is called recursively IT WILL DEADLOCK!!!!!
    397 static inline void lock(spin_queue_lock & this) with(this) {
    398         mcs_spin_node node;
    399         #ifdef __CFA_DEBUG__
    400         assert(!(held && owner == active_thread()));
    401         #endif
    402         lock( lock, node );
    403         while(held) Pause();
    404         held = true;
    405         unlock( lock, node );
    406         #ifdef __CFA_DEBUG__
    407         owner = active_thread();
    408         #endif
    409 }
    410 
    411 static inline void unlock(spin_queue_lock & this) with(this) {
    412         #ifdef __CFA_DEBUG__
    413         owner = 0p;
    414         #endif
    415         held = false;
    416 }
    417 
    418 static inline void on_notify(spin_queue_lock & this, struct thread$ * t ) { unpark(t); }
    419 static inline size_t on_wait(spin_queue_lock & this) { unlock(this); return 0; }
    420 static inline void on_wakeup(spin_queue_lock & this, size_t recursion ) { }
    421 
    422 
    423 //-----------------------------------------------------------------------------
    424 // MCS Block Spin Lock
    425 
    426 // - No reacquire for cond var
    427 // - No recursive acquisition
    428 // - No ownership
    429 // - Blocks but first node spins (like spin queue but blocking for not first thd)
    430 struct mcs_block_spin_lock {
    431         // Spin lock used for mutual exclusion
    432         mcs_lock lock;
    433 
    434         // flag showing if lock is held
    435         bool held:1;
    436 
    437         #ifdef __CFA_DEBUG__
    438         // for deadlock detection
    439         struct thread$ * owner;
    440         #endif
    441 };
    442 
    443 static inline void  ?{}( mcs_block_spin_lock & this ) with(this) {
    444         lock{};
    445         held = false;
    446 }
    447 static inline void ^?{}( mcs_block_spin_lock & this ) {}
    448 static inline void ?{}( mcs_block_spin_lock & this, mcs_block_spin_lock this2 ) = void;
    449 static inline void ?=?( mcs_block_spin_lock & this, mcs_block_spin_lock this2 ) = void;
    450 
    451 // if this is called recursively IT WILL DEADLOCK!!!!!
    452 static inline void lock(mcs_block_spin_lock & this) with(this) {
    453         mcs_node node;
    454         #ifdef __CFA_DEBUG__
    455         assert(!(held && owner == active_thread()));
    456         #endif
    457         lock( lock, node );
    458         while(held) Pause();
    459         held = true;
    460         unlock( lock, node );
    461         #ifdef __CFA_DEBUG__
    462         owner = active_thread();
    463         #endif
    464 }
    465 
    466 static inline void unlock(mcs_block_spin_lock & this) with(this) {
    467         #ifdef __CFA_DEBUG__
    468         owner = 0p;
    469         #endif
    470         held = false;
    471 }
    472 
    473 static inline void on_notify(mcs_block_spin_lock & this, struct thread$ * t ) { unpark(t); }
    474 static inline size_t on_wait(mcs_block_spin_lock & this) { unlock(this); return 0; }
    475 static inline void on_wakeup(mcs_block_spin_lock & this, size_t recursion ) { }
    476 
    477 //-----------------------------------------------------------------------------
    478 // Block Spin Lock
    479 
    480 // - No reacquire for cond var
    481 // - No recursive acquisition
    482 // - No ownership
    483 // - Blocks but first node spins (like spin queue but blocking for not first thd)
    484 struct block_spin_lock {
    485         // Spin lock used for mutual exclusion
    486         fast_block_lock lock;
    487 
    488         // flag showing if lock is held
    489         bool held:1;
    490 
    491         #ifdef __CFA_DEBUG__
    492         // for deadlock detection
    493         struct thread$ * owner;
    494         #endif
    495 };
    496 
    497 static inline void  ?{}( block_spin_lock & this ) with(this) {
    498         lock{};
    499         held = false;
    500 }
    501 static inline void ^?{}( block_spin_lock & this ) {}
    502 static inline void ?{}( block_spin_lock & this, block_spin_lock this2 ) = void;
    503 static inline void ?=?( block_spin_lock & this, block_spin_lock this2 ) = void;
    504 
    505 // if this is called recursively IT WILL DEADLOCK!!!!!
    506 static inline void lock(block_spin_lock & this) with(this) {
    507         #ifdef __CFA_DEBUG__
    508         assert(!(held && owner == active_thread()));
    509         #endif
    510         lock( lock );
    511         while(held) Pause();
    512         held = true;
    513         unlock( lock );
    514         #ifdef __CFA_DEBUG__
    515         owner = active_thread();
    516         #endif
    517 }
    518 
    519 static inline void unlock(block_spin_lock & this) with(this) {
    520         #ifdef __CFA_DEBUG__
    521         owner = 0p;
    522         #endif
    523         held = false;
    524 }
    525 
    526 static inline void on_notify(block_spin_lock & this, struct thread$ * t ) { unpark(t); }
    527 static inline size_t on_wait(block_spin_lock & this) { unlock(this); return 0; }
    528 static inline void on_wakeup(block_spin_lock & this, size_t recursion ) { }
    529255
    530256//-----------------------------------------------------------------------------
Note: See TracChangeset for help on using the changeset viewer.