Changeset 6f774be for libcfa/src/concurrency
- Timestamp:
- Jun 1, 2023, 11:58:50 AM (19 months ago)
- Branches:
- ast-experimental, master
- Children:
- 8421d3f
- Parents:
- 8913de4
- Location:
- libcfa/src/concurrency
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/channel.hfa
r8913de4 r6f774be 341 341 } 342 342 343 // special case of __handle_waituntil_OR, that does some work to avoid starvation/deadlock case 344 static inline bool __handle_pending( dlist( select_node ) & queue, select_node & mine ) { 345 while ( !queue`isEmpty ) { 346 // if node not a special OR case or if we win the special OR case race break 347 if ( !queue`first.clause_status || queue`first.park_counter || __pending_set_other( queue`first, mine, ((unsigned long int)(&(queue`first))) ) ) 348 return true; 349 350 // our node lost the race when toggling in __pending_set_other 351 if ( *mine.clause_status != __SELECT_PENDING ) 352 return false; 353 354 // otherwise we lost the special OR race so discard node 355 try_pop_front( queue ); 356 } 357 return false; 358 } 359 343 360 // type used by select statement to capture a chan read as the selected operation 344 361 struct chan_read { … … 374 391 return false; 375 392 } 376 377 if ( __handle_ waituntil_OR( prods) ) {393 394 if ( __handle_pending( prods, node ) ) { 378 395 __prods_handoff( chan, ret ); 379 396 __make_select_node_sat( node ); // need to to mark SAT now that we know operation is done or else threads could get stuck in __mark_select_node … … 381 398 return true; 382 399 } 383 __make_select_node_unsat( node ); 400 if ( *node.clause_status == __SELECT_PENDING ) 401 __make_select_node_unsat( node ); 384 402 } 385 403 // check if we can complete operation. If so race to establish winner in special OR case … … 464 482 return false; 465 483 } 466 467 if ( __handle_ waituntil_OR( cons) ) {484 485 if ( __handle_pending( cons, node ) ) { 468 486 __cons_handoff( chan, elem ); 469 487 __make_select_node_sat( node ); // need to to mark SAT now that we know operation is done or else threads could get stuck in __mark_select_node … … 471 489 return true; 472 490 } 473 __make_select_node_unsat( node ); 491 if ( *node.clause_status == __SELECT_PENDING ) 492 __make_select_node_unsat( node ); 474 493 } 475 494 // check if we can complete operation. If so race to establish winner in special OR case -
libcfa/src/concurrency/select.hfa
r8913de4 r6f774be 103 103 //============================================================================================= 104 104 105 static inline void __make_select_node_unsat( select_node & this ) with( this ) { 106 __atomic_store_n( clause_status, __SELECT_UNSAT, __ATOMIC_SEQ_CST ); 107 } 108 static inline void __make_select_node_sat( select_node & this ) with( this ) { 109 __atomic_store_n( clause_status, __SELECT_SAT, __ATOMIC_SEQ_CST ); 110 } 111 105 112 // used for the 2-stage avail needed by the special OR case 106 113 static inline bool __mark_select_node( select_node & this, unsigned long int val ) with( this ) { … … 116 123 } 117 124 118 static inline void __make_select_node_unsat( select_node & this ) with( this ) { 119 __atomic_store_n( clause_status, __SELECT_UNSAT, __ATOMIC_SEQ_CST ); 120 } 121 static inline void __make_select_node_sat( select_node & this ) with( this ) { 122 __atomic_store_n( clause_status, __SELECT_SAT, __ATOMIC_SEQ_CST ); 125 // used for the 2-stage avail by the thread who owns a pending node 126 static inline bool __pending_set_other( select_node & other, select_node & mine, unsigned long int val ) with( other ) { 127 /* paranoid */ verify( park_counter == 0p ); 128 /* paranoid */ verify( clause_status != 0p ); 129 130 unsigned long int cmp_status = __SELECT_UNSAT; 131 while( !__atomic_compare_exchange_n( clause_status, &cmp_status, val, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) { 132 if ( cmp_status != __SELECT_PENDING ) 133 return false; 134 135 // toggle current status flag to avoid starvation/deadlock 136 __make_select_node_unsat( mine ); 137 cmp_status = __SELECT_UNSAT; 138 if ( !__atomic_compare_exchange_n( mine.clause_status, &cmp_status, __SELECT_PENDING, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) 139 return false; 140 cmp_status = __SELECT_UNSAT; 141 } 142 return true; 123 143 } 124 144
Note: See TracChangeset
for help on using the changeset viewer.