- File:
-
- 1 edited
-
libcfa/src/concurrency/locks.cfa (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/locks.cfa
r70a4ed5 r7d9598d8 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // locks. cfa -- LIBCFATHREAD7 // locks.hfa -- LIBCFATHREAD 8 8 // Runtime locks that used with the runtime thread system. 9 9 // … … 16 16 17 17 #define __cforall_thread__ 18 #define _GNU_SOURCE 18 19 19 20 #include "locks.hfa" … … 79 80 // lock is held by some other thread 80 81 if ( owner != 0p && owner != thrd ) { 81 select_node node; 82 insert_last( blocked_threads, node ); 82 insert_last( blocked_threads, *thrd ); 83 83 wait_count++; 84 84 unlock( lock ); 85 85 park( ); 86 return; 87 } else if ( owner == thrd && multi_acquisition ) { // multi acquisition lock is held by current thread 86 } 87 // multi acquisition lock is held by current thread 88 else if ( owner == thrd && multi_acquisition ) { 88 89 recursion_count++; 89 } else { // lock isn't held 90 unlock( lock ); 91 } 92 // lock isn't held 93 else { 90 94 owner = thrd; 91 95 recursion_count = 1; 92 }93 unlock( lock ); 96 unlock( lock ); 97 } 94 98 } 95 99 … … 114 118 } 115 119 116 static inline void pop_node( blocking_lock & this ) with( this ) { 117 __handle_waituntil_OR( blocked_threads ); 118 select_node * node = &try_pop_front( blocked_threads ); 119 if ( node ) { 120 wait_count--; 121 owner = node->blocked_thread; 122 recursion_count = 1; 123 // if ( !node->clause_status || __make_select_node_available( *node ) ) unpark( node->blocked_thread ); 124 wake_one( blocked_threads, *node ); 125 } else { 126 owner = 0p; 127 recursion_count = 0; 128 } 120 static void pop_and_set_new_owner( blocking_lock & this ) with( this ) { 121 thread$ * t = &try_pop_front( blocked_threads ); 122 owner = t; 123 recursion_count = ( t ? 1 : 0 ); 124 if ( t ) wait_count--; 125 unpark( t ); 129 126 } 130 127 … … 138 135 recursion_count--; 139 136 if ( recursion_count == 0 ) { 140 pop_ node( this );137 pop_and_set_new_owner( this ); 141 138 } 142 139 unlock( lock ); … … 151 148 // lock held 152 149 if ( owner != 0p ) { 153 insert_last( blocked_threads, * (select_node *)t->link_node);150 insert_last( blocked_threads, *t ); 154 151 wait_count++; 152 unlock( lock ); 155 153 } 156 154 // lock not held … … 159 157 recursion_count = 1; 160 158 unpark( t ); 161 }162 unlock( lock ); 163 } 164 165 size_t on_wait( blocking_lock & this , __cfa_pre_park pp_fn, void * pp_datum) with( this ) {159 unlock( lock ); 160 } 161 } 162 163 size_t on_wait( blocking_lock & this ) with( this ) { 166 164 lock( lock __cfaabi_dbg_ctx2 ); 167 165 /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this ); … … 170 168 size_t ret = recursion_count; 171 169 172 pop_node( this ); 173 174 select_node node; 175 active_thread()->link_node = (void *)&node; 170 pop_and_set_new_owner( this ); 176 171 unlock( lock ); 177 178 pre_park_then_park( pp_fn, pp_datum );179 180 172 return ret; 181 173 } … … 184 176 recursion_count = recursion; 185 177 } 186 187 // waituntil() support188 bool register_select( blocking_lock & this, select_node & node ) with(this) {189 lock( lock __cfaabi_dbg_ctx2 );190 thread$ * thrd = active_thread();191 192 // single acquisition lock is held by current thread193 /* paranoid */ verifyf( owner != thrd || multi_acquisition, "Single acquisition lock holder (%p) attempted to reacquire the lock %p resulting in a deadlock.", owner, &this );194 195 if ( !node.park_counter && ( (owner == thrd && multi_acquisition) || owner == 0p ) ) { // OR special case196 if ( !__make_select_node_available( node ) ) { // we didn't win the race so give up on registering197 unlock( lock );198 return false;199 }200 }201 202 // lock is held by some other thread203 if ( owner != 0p && owner != thrd ) {204 insert_last( blocked_threads, node );205 wait_count++;206 unlock( lock );207 return false;208 } else if ( owner == thrd && multi_acquisition ) { // multi acquisition lock is held by current thread209 recursion_count++;210 } else { // lock isn't held211 owner = thrd;212 recursion_count = 1;213 }214 215 if ( node.park_counter ) __make_select_node_available( node );216 unlock( lock );217 return true;218 }219 220 bool unregister_select( blocking_lock & this, select_node & node ) with(this) {221 lock( lock __cfaabi_dbg_ctx2 );222 if ( node`isListed ) {223 remove( node );224 wait_count--;225 unlock( lock );226 return false;227 }228 229 if ( owner == active_thread() ) {230 /* paranoid */ verifyf( recursion_count == 1 || multi_acquisition, "Thread %p attempted to unlock owner lock %p in waituntil unregister, which is not recursive but has a recursive count of %zu", active_thread(), &this, recursion_count );231 // if recursion count is zero release lock and set new owner if one is waiting232 recursion_count--;233 if ( recursion_count == 0 ) {234 pop_node( this );235 }236 }237 unlock( lock );238 return false;239 }240 241 void on_selected( blocking_lock & this, select_node & node ) {}242 178 243 179 //----------------------------------------------------------------------------- … … 376 312 int counter( condition_variable(L) & this ) with(this) { return count; } 377 313 378 static void enqueue_thread( condition_variable(L) & this, info_thread(L) * i ) with(this) {314 static size_t queue_and_get_recursion( condition_variable(L) & this, info_thread(L) * i ) with(this) { 379 315 // add info_thread to waiting queue 380 316 insert_last( blocked_threads, *i ); 381 317 count++; 382 } 383 384 static size_t block_and_get_recursion( info_thread(L) & i, __cfa_pre_park pp_fn, void * pp_datum ) { 385 size_t recursion_count = 0; 386 if ( i.lock ) // if lock was passed get recursion count to reset to after waking thread 387 recursion_count = on_wait( *i.lock, pp_fn, pp_datum ); // this call blocks 388 else 389 pre_park_then_park( pp_fn, pp_datum ); 390 return recursion_count; 391 } 392 static size_t block_and_get_recursion( info_thread(L) & i ) { return block_and_get_recursion( i, pre_park_noop, 0p ); } 318 size_t recursion_count = 0; 319 if (i->lock) { 320 // if lock was passed get recursion count to reset to after waking thread 321 recursion_count = on_wait( *i->lock ); 322 } 323 return recursion_count; 324 } 393 325 394 326 // helper for wait()'s' with no timeout 395 327 static void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) { 396 328 lock( lock __cfaabi_dbg_ctx2 ); 397 enqueue_thread( this, &i);329 size_t recursion_count = queue_and_get_recursion(this, &i); 398 330 unlock( lock ); 399 331 400 332 // blocks here 401 size_t recursion_count = block_and_get_recursion( i);333 park( ); 402 334 403 335 // resets recursion count here after waking 404 if ( i.lock ) on_wakeup( *i.lock, recursion_count);336 if (i.lock) on_wakeup(*i.lock, recursion_count); 405 337 } 406 338 … … 409 341 queue_info_thread( this, i ); 410 342 411 static void cond_alarm_register( void * node_ptr ) { register_self( (alarm_node_t *)node_ptr ); }412 413 343 // helper for wait()'s' with a timeout 414 344 static void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) { 415 345 lock( lock __cfaabi_dbg_ctx2 ); 416 enqueue_thread( this, &info);346 size_t recursion_count = queue_and_get_recursion(this, &info); 417 347 alarm_node_wrap(L) node_wrap = { t, 0`s, callback, &this, &info }; 418 348 unlock( lock ); 419 349 420 // blocks here and registers alarm node before blocking after releasing locks to avoid deadlock 421 size_t recursion_count = block_and_get_recursion( info, cond_alarm_register, (void *)(&node_wrap.alarm_node) ); 422 // park(); 350 // registers alarm outside cond lock to avoid deadlock 351 register_self( &node_wrap.alarm_node ); 352 353 // blocks here 354 park(); 423 355 424 356 // unregisters alarm so it doesn't go off if this happens first … … 426 358 427 359 // resets recursion count here after waking 428 if ( info.lock ) on_wakeup( *info.lock, recursion_count);360 if (info.lock) on_wakeup(*info.lock, recursion_count); 429 361 } 430 362 … … 486 418 info_thread( L ) i = { active_thread(), info, &l }; 487 419 insert_last( blocked_threads, i ); 488 size_t recursion_count = on_wait( *i.lock , pre_park_noop, 0p ); // blocks here489 //park( );420 size_t recursion_count = on_wait( *i.lock ); 421 park( ); 490 422 on_wakeup(*i.lock, recursion_count); 491 423 } … … 528 460 bool empty ( pthread_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty; } 529 461 462 static size_t queue_and_get_recursion( pthread_cond_var(L) & this, info_thread(L) * i ) with(this) { 463 // add info_thread to waiting queue 464 insert_last( blocked_threads, *i ); 465 size_t recursion_count = 0; 466 recursion_count = on_wait( *i->lock ); 467 return recursion_count; 468 } 469 530 470 static void queue_info_thread_timeout( pthread_cond_var(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) { 531 471 lock( lock __cfaabi_dbg_ctx2 ); 532 insert_last( blocked_threads, info);472 size_t recursion_count = queue_and_get_recursion(this, &info); 533 473 pthread_alarm_node_wrap(L) node_wrap = { t, 0`s, callback, &this, &info }; 534 474 unlock( lock ); 535 475 536 // blocks here and registers alarm node before blocking after releasing locks to avoid deadlock 537 size_t recursion_count = block_and_get_recursion( info, cond_alarm_register, (void *)(&node_wrap.alarm_node) ); 538 539 // unregisters alarm so it doesn't go off if signal happens first 476 // registers alarm outside cond lock to avoid deadlock 477 register_self( &node_wrap.alarm_node ); 478 479 // blocks here 480 park(); 481 482 // unregisters alarm so it doesn't go off if this happens first 540 483 unregister_self( &node_wrap.alarm_node ); 541 484 542 485 // resets recursion count here after waking 543 if ( info.lock ) on_wakeup( *info.lock, recursion_count);486 if (info.lock) on_wakeup(*info.lock, recursion_count); 544 487 } 545 488 … … 551 494 lock( lock __cfaabi_dbg_ctx2 ); 552 495 info_thread( L ) i = { active_thread(), info, &l }; 553 insert_last( blocked_threads, i ); 554 unlock( lock ); 555 556 // blocks here 557 size_t recursion_count = block_and_get_recursion( i ); 558 559 on_wakeup( *i.lock, recursion_count ); 496 size_t recursion_count = queue_and_get_recursion(this, &i); 497 unlock( lock ); 498 park( ); 499 on_wakeup(*i.lock, recursion_count); 560 500 } 561 501 … … 645 585 return thrd != 0p; 646 586 } 647
Note:
See TracChangeset
for help on using the changeset viewer.