- File:
-
- 1 edited
-
libcfa/src/concurrency/locks.hfa (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/locks.hfa
r7f958c4 r490d17e0 101 101 102 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; 166 } 167 168 //----------------------------------------------------------------------------- 103 169 // Linear backoff Spinlock 104 170 struct linear_backoff_then_block_lock { … … 205 271 // Fast Block Lock 206 272 207 // High efficiencyminimal blocking lock273 // minimal blocking lock 208 274 // - No reacquire for cond var 209 275 // - No recursive acquisition 210 276 // - No ownership 211 277 struct fast_block_lock { 278 // List of blocked threads 279 dlist( thread$ ) blocked_threads; 280 212 281 // Spin lock used for mutual exclusion 213 282 __spinlock_t lock; 214 283 215 // List of blocked threads 216 dlist( thread$ ) blocked_threads; 217 284 // flag showing if lock is held 218 285 bool held:1; 286 287 #ifdef __CFA_DEBUG__ 288 // for deadlock detection 289 struct thread$ * owner; 290 #endif 219 291 }; 220 292 … … 231 303 static inline void lock(fast_block_lock & this) with(this) { 232 304 lock( lock __cfaabi_dbg_ctx2 ); 305 306 #ifdef __CFA_DEBUG__ 307 assert(!(held && owner == active_thread())); 308 #endif 233 309 if (held) { 234 310 insert_last( blocked_threads, *active_thread() ); … … 238 314 } 239 315 held = true; 316 #ifdef __CFA_DEBUG__ 317 owner = active_thread(); 318 #endif 240 319 unlock( lock ); 241 320 } … … 246 325 thread$ * t = &try_pop_front( blocked_threads ); 247 326 held = ( t ? true : false ); 327 #ifdef __CFA_DEBUG__ 328 owner = ( t ? t : 0p ); 329 #endif 248 330 unpark( t ); 249 331 unlock( lock ); … … 253 335 static inline size_t on_wait(fast_block_lock & this) { unlock(this); return 0; } 254 336 static 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 ) { } 255 529 256 530 //-----------------------------------------------------------------------------
Note:
See TracChangeset
for help on using the changeset viewer.