- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/ready_queue.cfa
rd2fadeb r5f6a172 35 35 static const size_t cache_line_size = 64; 36 36 37 #if !defined(__CFA_NO_STATISTICS__)38 #define __STATS(...) __VA_ARGS__39 #else40 #define __STATS(...)41 #endif42 43 37 // No overriden function, no environment variable, no define 44 38 // fall back to a magic number … … 58 52 #endif 59 53 60 static inline struct $thread * try_pop(struct cluster * cltr, unsigned w __STATS(, __stats_readyQ_pop_t & stats)); 61 static inline struct $thread * try_pop(struct cluster * cltr, unsigned i, unsigned j __STATS(, __stats_readyQ_pop_t & stats)); 54 static inline [unsigned, bool] idx_from_r(unsigned r, unsigned preferred); 55 static inline struct $thread * try_pop(struct cluster * cltr, unsigned w); 56 static inline struct $thread * try_pop(struct cluster * cltr, unsigned i, unsigned j); 62 57 static inline struct $thread * search(struct cluster * cltr); 63 static inline [unsigned, bool] idx_from_r(unsigned r, unsigned preferred);64 58 65 59 … … 275 269 276 270 #if !defined(__CFA_NO_STATISTICS__) 277 if(unlikely(external)) __atomic_fetch_add(&cltr->stats->ready.push.extrn.attempt, 1, __ATOMIC_RELAXED); 278 else if(local) __tls_stats()->ready.push.local.attempt++; 279 else __tls_stats()->ready.push.share.attempt++; 271 if(external) { 272 if(local) __atomic_fetch_add(&cltr->stats->ready.pick.ext.local, 1, __ATOMIC_RELAXED); 273 __atomic_fetch_add(&cltr->stats->ready.pick.ext.attempt, 1, __ATOMIC_RELAXED); 274 } 275 else { 276 if(local) __tls_stats()->ready.pick.push.local++; 277 __tls_stats()->ready.pick.push.attempt++; 278 } 280 279 #endif 281 280 … … 303 302 // Update statistics 304 303 #if !defined(__CFA_NO_STATISTICS__) 305 if(unlikely(external)) __atomic_fetch_add(&cltr->stats->ready.push.extrn.success, 1, __ATOMIC_RELAXED); 306 else if(local) __tls_stats()->ready.push.local.success++; 307 else __tls_stats()->ready.push.share.success++; 304 if(external) { 305 if(local) __atomic_fetch_add(&cltr->stats->ready.pick.ext.lsuccess, 1, __ATOMIC_RELAXED); 306 __atomic_fetch_add(&cltr->stats->ready.pick.ext.success, 1, __ATOMIC_RELAXED); 307 } 308 else { 309 if(local) __tls_stats()->ready.pick.push.lsuccess++; 310 __tls_stats()->ready.pick.push.success++; 311 } 308 312 #endif 309 313 } … … 330 334 [j, localj] = idx_from_r(rj, preferred); 331 335 336 #if !defined(__CFA_NO_STATISTICS__) 337 if(locali && localj) { 338 __tls_stats()->ready.pick.pop.local++; 339 } 340 #endif 341 332 342 i %= count; 333 343 j %= count; 334 344 335 345 // try popping from the 2 picked lists 336 struct $thread * thrd = try_pop(cltr, i, j __STATS(, *(locali || localj ? &__tls_stats()->ready.pop.local : &__tls_stats()->ready.pop.help)));346 struct $thread * thrd = try_pop(cltr, i, j); 337 347 if(thrd) { 348 #if !defined(__CFA_NO_STATISTICS__) 349 if( locali || localj ) __tls_stats()->ready.pick.pop.lsuccess++; 350 #endif 338 351 return thrd; 339 352 } … … 361 374 unsigned i; 362 375 do { 363 #if !defined(__CFA_NO_STATISTICS__)364 if(unlikely(external)) __atomic_fetch_add(&cltr->stats->ready.push.extrn.attempt, 1, __ATOMIC_RELAXED);365 else __tls_stats()->ready.push.local.attempt++;366 #endif367 368 376 if(unlikely(external)) { 369 377 i = __tls_rand() % lanes.count; … … 390 398 // Unlock and return 391 399 __atomic_unlock( &lanes.data[i].lock ); 392 #endif393 394 #if !defined(__CFA_NO_STATISTICS__)395 if(unlikely(external)) __atomic_fetch_add(&cltr->stats->ready.push.extrn.success, 1, __ATOMIC_RELAXED);396 else __tls_stats()->ready.push.local.success++;397 400 #endif 398 401 … … 419 422 } 420 423 else if(lanes.tscs[proc->rdq.target].tv < proc->rdq.cutoff) { 421 $thread * t = try_pop(cltr, proc->rdq.target __STATS(, __tls_stats()->ready.pop.help));424 $thread * t = try_pop(cltr, proc->rdq.target); 422 425 proc->rdq.target = -1u; 423 426 if(t) return t; … … 426 429 for(READYQ_SHARD_FACTOR) { 427 430 unsigned i = proc->rdq.id + (--proc->rdq.itr % READYQ_SHARD_FACTOR); 428 if($thread * t = try_pop(cltr, i __STATS(, __tls_stats()->ready.pop.local))) return t;431 if($thread * t = try_pop(cltr, i)) return t; 429 432 } 430 433 return 0p; … … 434 437 for(25) { 435 438 unsigned i = __tls_rand() % lanes.count; 436 $thread * t = try_pop(cltr, i __STATS(, __tls_stats()->ready.pop.steal));439 $thread * t = try_pop(cltr, i); 437 440 if(t) return t; 438 441 } … … 450 453 //----------------------------------------------------------------------- 451 454 // try to pop from a lane given by index w 452 static inline struct $thread * try_pop(struct cluster * cltr, unsigned w __STATS(, __stats_readyQ_pop_t & stats)) with (cltr->ready_queue) { 453 __STATS( stats.attempt++; ) 454 455 static inline struct $thread * try_pop(struct cluster * cltr, unsigned w) with (cltr->ready_queue) { 455 456 // Get relevant elements locally 456 457 __intrusive_lane_t & lane = lanes.data[w]; 457 458 458 459 // If list looks empty retry 459 if( is_empty(lane) ) { 460 __STATS( stats.espec++; ) 461 return 0p; 462 } 460 if( is_empty(lane) ) return 0p; 463 461 464 462 // If we can't get the lock retry 465 if( !__atomic_try_acquire(&lane.lock) ) { 466 __STATS( stats.elock++; ) 467 return 0p; 468 } 463 if( !__atomic_try_acquire(&lane.lock) ) return 0p; 469 464 470 465 // If list is empty, unlock and retry 471 466 if( is_empty(lane) ) { 472 467 __atomic_unlock(&lane.lock); 473 __STATS( stats.eempty++; )474 468 return 0p; 475 469 } … … 486 480 487 481 // Update statistics 488 __STATS( stats.success++; ) 482 #if !defined(__CFA_NO_STATISTICS__) 483 __tls_stats()->ready.pick.pop.success++; 484 #endif 489 485 490 486 #if defined(USE_WORK_STEALING) … … 505 501 for(i; count) { 506 502 unsigned idx = (offset + i) % count; 507 struct $thread * thrd = try_pop(cltr, idx __STATS(, __tls_stats()->ready.pop.search));503 struct $thread * thrd = try_pop(cltr, idx); 508 504 if(thrd) { 509 505 return thrd; … … 543 539 //----------------------------------------------------------------------- 544 540 // Given 2 indexes, pick the list with the oldest push an try to pop from it 545 static inline struct $thread * try_pop(struct cluster * cltr, unsigned i, unsigned j __STATS(, __stats_readyQ_pop_t & stats)) with (cltr->ready_queue) { 541 static inline struct $thread * try_pop(struct cluster * cltr, unsigned i, unsigned j) with (cltr->ready_queue) { 542 #if !defined(__CFA_NO_STATISTICS__) 543 __tls_stats()->ready.pick.pop.attempt++; 544 #endif 545 546 546 // Pick the bet list 547 547 int w = i; … … 550 550 } 551 551 552 return try_pop(cltr, w __STATS(, stats));552 return try_pop(cltr, w); 553 553 } 554 554
Note:
See TracChangeset
for help on using the changeset viewer.