- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/locks.cfa
r5a05946 rf5f2768 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 // … … 79 79 // lock is held by some other thread 80 80 if ( owner != 0p && owner != thrd ) { 81 select_node node; 82 insert_last( blocked_threads, node ); 81 insert_last( blocked_threads, *thrd ); 83 82 wait_count++; 84 83 unlock( lock ); 85 84 park( ); 86 return; 87 } else if ( owner == thrd && multi_acquisition ) { // multi acquisition lock is held by current thread 85 } 86 // multi acquisition lock is held by current thread 87 else if ( owner == thrd && multi_acquisition ) { 88 88 recursion_count++; 89 } else { // lock isn't held 89 unlock( lock ); 90 } 91 // lock isn't held 92 else { 90 93 owner = thrd; 91 94 recursion_count = 1; 92 }93 unlock( lock ); 95 unlock( lock ); 96 } 94 97 } 95 98 … … 114 117 } 115 118 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 } 119 static void pop_and_set_new_owner( blocking_lock & this ) with( this ) { 120 thread$ * t = &try_pop_front( blocked_threads ); 121 owner = t; 122 recursion_count = ( t ? 1 : 0 ); 123 if ( t ) wait_count--; 124 unpark( t ); 129 125 } 130 126 … … 138 134 recursion_count--; 139 135 if ( recursion_count == 0 ) { 140 pop_ node( this );136 pop_and_set_new_owner( this ); 141 137 } 142 138 unlock( lock ); … … 151 147 // lock held 152 148 if ( owner != 0p ) { 153 insert_last( blocked_threads, * (select_node *)t->link_node);149 insert_last( blocked_threads, *t ); 154 150 wait_count++; 151 unlock( lock ); 155 152 } 156 153 // lock not held … … 159 156 recursion_count = 1; 160 157 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 ) {158 unlock( lock ); 159 } 160 } 161 162 size_t on_wait( blocking_lock & this ) with( this ) { 166 163 lock( lock __cfaabi_dbg_ctx2 ); 167 164 /* paranoid */ verifyf( owner != 0p, "Attempt to release lock %p that isn't held", &this ); … … 170 167 size_t ret = recursion_count; 171 168 172 pop_node( this ); 173 174 select_node node; 175 active_thread()->link_node = (void *)&node; 169 pop_and_set_new_owner( this ); 176 170 unlock( lock ); 177 178 pre_park_then_park( pp_fn, pp_datum );179 180 171 return ret; 181 172 } … … 184 175 recursion_count = recursion; 185 176 } 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 bool on_selected( blocking_lock & this, select_node & node ) { return true; }242 177 243 178 //----------------------------------------------------------------------------- … … 376 311 int counter( condition_variable(L) & this ) with(this) { return count; } 377 312 378 static void enqueue_thread( condition_variable(L) & this, info_thread(L) * i ) with(this) {313 static size_t queue_and_get_recursion( condition_variable(L) & this, info_thread(L) * i ) with(this) { 379 314 // add info_thread to waiting queue 380 315 insert_last( blocked_threads, *i ); 381 316 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 ); } 317 size_t recursion_count = 0; 318 if (i->lock) { 319 // if lock was passed get recursion count to reset to after waking thread 320 recursion_count = on_wait( *i->lock ); 321 } 322 return recursion_count; 323 } 393 324 394 325 // helper for wait()'s' with no timeout 395 326 static void queue_info_thread( condition_variable(L) & this, info_thread(L) & i ) with(this) { 396 327 lock( lock __cfaabi_dbg_ctx2 ); 397 enqueue_thread( this, &i);328 size_t recursion_count = queue_and_get_recursion(this, &i); 398 329 unlock( lock ); 399 330 400 331 // blocks here 401 size_t recursion_count = block_and_get_recursion( i);332 park( ); 402 333 403 334 // resets recursion count here after waking 404 if ( i.lock ) on_wakeup( *i.lock, recursion_count);335 if (i.lock) on_wakeup(*i.lock, recursion_count); 405 336 } 406 337 … … 409 340 queue_info_thread( this, i ); 410 341 411 static void cond_alarm_register( void * node_ptr ) { register_self( (alarm_node_t *)node_ptr ); }412 413 342 // helper for wait()'s' with a timeout 414 343 static void queue_info_thread_timeout( condition_variable(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) { 415 344 lock( lock __cfaabi_dbg_ctx2 ); 416 enqueue_thread( this, &info);345 size_t recursion_count = queue_and_get_recursion(this, &info); 417 346 alarm_node_wrap(L) node_wrap = { t, 0`s, callback, &this, &info }; 418 347 unlock( lock ); 419 348 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(); 349 // registers alarm outside cond lock to avoid deadlock 350 register_self( &node_wrap.alarm_node ); 351 352 // blocks here 353 park(); 423 354 424 355 // unregisters alarm so it doesn't go off if this happens first … … 426 357 427 358 // resets recursion count here after waking 428 if ( info.lock ) on_wakeup( *info.lock, recursion_count);359 if (info.lock) on_wakeup(*info.lock, recursion_count); 429 360 } 430 361 … … 486 417 info_thread( L ) i = { active_thread(), info, &l }; 487 418 insert_last( blocked_threads, i ); 488 size_t recursion_count = on_wait( *i.lock , pre_park_noop, 0p ); // blocks here489 //park( );419 size_t recursion_count = on_wait( *i.lock ); 420 park( ); 490 421 on_wakeup(*i.lock, recursion_count); 491 422 } … … 528 459 bool empty ( pthread_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty; } 529 460 461 static size_t queue_and_get_recursion( pthread_cond_var(L) & this, info_thread(L) * i ) with(this) { 462 // add info_thread to waiting queue 463 insert_last( blocked_threads, *i ); 464 size_t recursion_count = 0; 465 recursion_count = on_wait( *i->lock ); 466 return recursion_count; 467 } 468 530 469 static void queue_info_thread_timeout( pthread_cond_var(L) & this, info_thread(L) & info, Duration t, Alarm_Callback callback ) with(this) { 531 470 lock( lock __cfaabi_dbg_ctx2 ); 532 insert_last( blocked_threads, info);471 size_t recursion_count = queue_and_get_recursion(this, &info); 533 472 pthread_alarm_node_wrap(L) node_wrap = { t, 0`s, callback, &this, &info }; 534 473 unlock( lock ); 535 474 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 475 // registers alarm outside cond lock to avoid deadlock 476 register_self( &node_wrap.alarm_node ); 477 478 // blocks here 479 park(); 480 481 // unregisters alarm so it doesn't go off if this happens first 540 482 unregister_self( &node_wrap.alarm_node ); 541 483 542 484 // resets recursion count here after waking 543 if ( info.lock ) on_wakeup( *info.lock, recursion_count);485 if (info.lock) on_wakeup(*info.lock, recursion_count); 544 486 } 545 487 … … 551 493 lock( lock __cfaabi_dbg_ctx2 ); 552 494 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 ); 495 size_t recursion_count = queue_and_get_recursion(this, &i); 496 unlock( lock ); 497 park( ); 498 on_wakeup(*i.lock, recursion_count); 560 499 } 561 500 … … 645 584 return thrd != 0p; 646 585 } 647
Note:
See TracChangeset
for help on using the changeset viewer.