1 /* 2 * kmp_barrier.cpp 3 */ 4 5 //===----------------------------------------------------------------------===// 6 // 7 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 8 // See https://llvm.org/LICENSE.txt for license information. 9 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "kmp_wait_release.h" 14 #include "kmp_barrier.h" 15 #include "kmp_itt.h" 16 #include "kmp_os.h" 17 #include "kmp_stats.h" 18 #include "ompt-specific.h" 19 // for distributed barrier 20 #include "kmp_affinity.h" 21 22 #if KMP_MIC 23 #include <immintrin.h> 24 #define USE_NGO_STORES 1 25 #endif // KMP_MIC 26 27 #include "tsan_annotations.h" 28 29 #if KMP_MIC && USE_NGO_STORES 30 // ICV copying 31 #define ngo_load(src) __m512d Vt = _mm512_load_pd((void *)(src)) 32 #define ngo_store_icvs(dst, src) _mm512_storenrngo_pd((void *)(dst), Vt) 33 #define ngo_store_go(dst, src) _mm512_storenrngo_pd((void *)(dst), Vt) 34 #define ngo_sync() __asm__ volatile("lock; addl $0,0(%%rsp)" ::: "memory") 35 #else 36 #define ngo_load(src) ((void)0) 37 #define ngo_store_icvs(dst, src) copy_icvs((dst), (src)) 38 #define ngo_store_go(dst, src) KMP_MEMCPY((dst), (src), CACHE_LINE) 39 #define ngo_sync() ((void)0) 40 #endif /* KMP_MIC && USE_NGO_STORES */ 41 42 void __kmp_print_structure(void); // Forward declaration 43 44 // ---------------------------- Barrier Algorithms ---------------------------- 45 // Distributed barrier 46 47 // Compute how many threads to have polling each cache-line. 48 // We want to limit the number of writes to IDEAL_GO_RESOLUTION. 49 void distributedBarrier::computeVarsForN(size_t n) { 50 int nsockets = 1; 51 if (__kmp_topology) { 52 int socket_level = __kmp_topology->get_level(KMP_HW_SOCKET); 53 int core_level = __kmp_topology->get_level(KMP_HW_CORE); 54 int ncores_per_socket = 55 __kmp_topology->calculate_ratio(core_level, socket_level); 56 nsockets = __kmp_topology->get_count(socket_level); 57 58 if (nsockets <= 0) 59 nsockets = 1; 60 if (ncores_per_socket <= 0) 61 ncores_per_socket = 1; 62 63 threads_per_go = ncores_per_socket >> 1; 64 if (!fix_threads_per_go) { 65 // Minimize num_gos 66 if (threads_per_go > 4) { 67 if (KMP_OPTIMIZE_FOR_REDUCTIONS) { 68 threads_per_go = threads_per_go >> 1; 69 } 70 if (threads_per_go > 4 && nsockets == 1) 71 threads_per_go = threads_per_go >> 1; 72 } 73 } 74 if (threads_per_go == 0) 75 threads_per_go = 1; 76 fix_threads_per_go = true; 77 num_gos = n / threads_per_go; 78 if (n % threads_per_go) 79 num_gos++; 80 if (nsockets == 1 || num_gos == 1) 81 num_groups = 1; 82 else { 83 num_groups = num_gos / nsockets; 84 if (num_gos % nsockets) 85 num_groups++; 86 } 87 if (num_groups <= 0) 88 num_groups = 1; 89 gos_per_group = num_gos / num_groups; 90 if (num_gos % num_groups) 91 gos_per_group++; 92 threads_per_group = threads_per_go * gos_per_group; 93 } else { 94 num_gos = n / threads_per_go; 95 if (n % threads_per_go) 96 num_gos++; 97 if (num_gos == 1) 98 num_groups = 1; 99 else { 100 num_groups = num_gos / 2; 101 if (num_gos % 2) 102 num_groups++; 103 } 104 gos_per_group = num_gos / num_groups; 105 if (num_gos % num_groups) 106 gos_per_group++; 107 threads_per_group = threads_per_go * gos_per_group; 108 } 109 } 110 111 void distributedBarrier::computeGo(size_t n) { 112 // Minimize num_gos 113 for (num_gos = 1;; num_gos++) 114 if (IDEAL_CONTENTION * num_gos >= n) 115 break; 116 threads_per_go = n / num_gos; 117 if (n % num_gos) 118 threads_per_go++; 119 while (num_gos > MAX_GOS) { 120 threads_per_go++; 121 num_gos = n / threads_per_go; 122 if (n % threads_per_go) 123 num_gos++; 124 } 125 computeVarsForN(n); 126 } 127 128 // This function is to resize the barrier arrays when the new number of threads 129 // exceeds max_threads, which is the current size of all the arrays 130 void distributedBarrier::resize(size_t nthr) { 131 KMP_DEBUG_ASSERT(nthr > max_threads); 132 133 // expand to requested size * 2 134 max_threads = nthr * 2; 135 136 // allocate arrays to new max threads 137 for (int i = 0; i < MAX_ITERS; ++i) { 138 if (flags[i]) 139 flags[i] = (flags_s *)KMP_INTERNAL_REALLOC(flags[i], 140 max_threads * sizeof(flags_s)); 141 else 142 flags[i] = (flags_s *)KMP_INTERNAL_MALLOC(max_threads * sizeof(flags_s)); 143 } 144 145 if (go) 146 go = (go_s *)KMP_INTERNAL_REALLOC(go, max_threads * sizeof(go_s)); 147 else 148 go = (go_s *)KMP_INTERNAL_MALLOC(max_threads * sizeof(go_s)); 149 150 if (iter) 151 iter = (iter_s *)KMP_INTERNAL_REALLOC(iter, max_threads * sizeof(iter_s)); 152 else 153 iter = (iter_s *)KMP_INTERNAL_MALLOC(max_threads * sizeof(iter_s)); 154 155 if (sleep) 156 sleep = 157 (sleep_s *)KMP_INTERNAL_REALLOC(sleep, max_threads * sizeof(sleep_s)); 158 else 159 sleep = (sleep_s *)KMP_INTERNAL_MALLOC(max_threads * sizeof(sleep_s)); 160 } 161 162 // This function is to set all the go flags that threads might be waiting 163 // on, and when blocktime is not infinite, it should be followed by a wake-up 164 // call to each thread 165 kmp_uint64 distributedBarrier::go_release() { 166 kmp_uint64 next_go = iter[0].iter + distributedBarrier::MAX_ITERS; 167 for (size_t j = 0; j < num_gos; j++) { 168 go[j].go.store(next_go); 169 } 170 return next_go; 171 } 172 173 void distributedBarrier::go_reset() { 174 for (size_t j = 0; j < max_threads; ++j) { 175 for (size_t i = 0; i < distributedBarrier::MAX_ITERS; ++i) { 176 flags[i][j].stillNeed = 1; 177 } 178 go[j].go.store(0); 179 iter[j].iter = 0; 180 } 181 } 182 183 // This function inits/re-inits the distributed barrier for a particular number 184 // of threads. If a resize of arrays is needed, it calls the resize function. 185 void distributedBarrier::init(size_t nthr) { 186 size_t old_max = max_threads; 187 if (nthr > max_threads) { // need more space in arrays 188 resize(nthr); 189 } 190 191 for (size_t i = 0; i < max_threads; i++) { 192 for (size_t j = 0; j < distributedBarrier::MAX_ITERS; j++) { 193 flags[j][i].stillNeed = 1; 194 } 195 go[i].go.store(0); 196 iter[i].iter = 0; 197 if (i >= old_max) 198 sleep[i].sleep = false; 199 } 200 201 // Recalculate num_gos, etc. based on new nthr 202 computeVarsForN(nthr); 203 204 num_threads = nthr; 205 206 if (team_icvs == NULL) 207 team_icvs = __kmp_allocate(sizeof(kmp_internal_control_t)); 208 } 209 210 // This function is used only when KMP_BLOCKTIME is not infinite. 211 // static 212 void __kmp_dist_barrier_wakeup(enum barrier_type bt, kmp_team_t *team, 213 size_t start, size_t stop, size_t inc, 214 size_t tid) { 215 KMP_DEBUG_ASSERT(__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME); 216 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done)) 217 return; 218 219 kmp_info_t **other_threads = team->t.t_threads; 220 for (size_t thr = start; thr < stop; thr += inc) { 221 KMP_DEBUG_ASSERT(other_threads[thr]); 222 int gtid = other_threads[thr]->th.th_info.ds.ds_gtid; 223 // Wake up worker regardless of if it appears to be sleeping or not 224 __kmp_atomic_resume_64(gtid, (kmp_atomic_flag_64<> *)NULL); 225 } 226 } 227 228 static void 229 __kmp_dist_barrier_gather(enum barrier_type bt, kmp_info_t *this_thr, int gtid, 230 int tid, void (*reduce)(void *, void *) 231 USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 232 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_dist_gather); 233 kmp_team_t *team; 234 distributedBarrier *b; 235 kmp_info_t **other_threads; 236 kmp_uint64 my_current_iter, my_next_iter; 237 kmp_uint32 nproc; 238 bool group_leader; 239 240 team = this_thr->th.th_team; 241 nproc = this_thr->th.th_team_nproc; 242 other_threads = team->t.t_threads; 243 b = team->t.b; 244 my_current_iter = b->iter[tid].iter; 245 my_next_iter = (my_current_iter + 1) % distributedBarrier::MAX_ITERS; 246 group_leader = ((tid % b->threads_per_group) == 0); 247 248 KA_TRACE(20, 249 ("__kmp_dist_barrier_gather: T#%d(%d:%d) enter; barrier type %d\n", 250 gtid, team->t.t_id, tid, bt)); 251 252 #if USE_ITT_BUILD && USE_ITT_NOTIFY 253 // Barrier imbalance - save arrive time to the thread 254 if (__kmp_forkjoin_frames_mode == 3 || __kmp_forkjoin_frames_mode == 2) { 255 this_thr->th.th_bar_arrive_time = this_thr->th.th_bar_min_time = 256 __itt_get_timestamp(); 257 } 258 #endif 259 260 if (group_leader) { 261 // Start from the thread after the group leader 262 size_t group_start = tid + 1; 263 size_t group_end = tid + b->threads_per_group; 264 size_t threads_pending = 0; 265 266 if (group_end > nproc) 267 group_end = nproc; 268 do { // wait for threads in my group 269 threads_pending = 0; 270 // Check all the flags every time to avoid branch misspredict 271 for (size_t thr = group_start; thr < group_end; thr++) { 272 // Each thread uses a different cache line 273 threads_pending += b->flags[my_current_iter][thr].stillNeed; 274 } 275 // Execute tasks here 276 if (__kmp_tasking_mode != tskm_immediate_exec) { 277 kmp_task_team_t *task_team = this_thr->th.th_task_team; 278 if (task_team != NULL) { 279 if (TCR_SYNC_4(task_team->tt.tt_active)) { 280 if (KMP_TASKING_ENABLED(task_team)) { 281 int tasks_completed = FALSE; 282 __kmp_atomic_execute_tasks_64( 283 this_thr, gtid, (kmp_atomic_flag_64<> *)NULL, FALSE, 284 &tasks_completed USE_ITT_BUILD_ARG(itt_sync_obj), 0); 285 } else 286 this_thr->th.th_reap_state = KMP_SAFE_TO_REAP; 287 } 288 } else { 289 this_thr->th.th_reap_state = KMP_SAFE_TO_REAP; 290 } // if 291 } 292 if (TCR_4(__kmp_global.g.g_done)) { 293 if (__kmp_global.g.g_abort) 294 __kmp_abort_thread(); 295 break; 296 } else if (__kmp_tasking_mode != tskm_immediate_exec && 297 this_thr->th.th_reap_state == KMP_SAFE_TO_REAP) { 298 this_thr->th.th_reap_state = KMP_NOT_SAFE_TO_REAP; 299 } 300 } while (threads_pending > 0); 301 302 if (reduce) { // Perform reduction if needed 303 OMPT_REDUCTION_DECL(this_thr, gtid); 304 OMPT_REDUCTION_BEGIN; 305 // Group leader reduces all threads in group 306 for (size_t thr = group_start; thr < group_end; thr++) { 307 (*reduce)(this_thr->th.th_local.reduce_data, 308 other_threads[thr]->th.th_local.reduce_data); 309 } 310 OMPT_REDUCTION_END; 311 } 312 313 // Set flag for next iteration 314 b->flags[my_next_iter][tid].stillNeed = 1; 315 // Each thread uses a different cache line; resets stillNeed to 0 to 316 // indicate it has reached the barrier 317 b->flags[my_current_iter][tid].stillNeed = 0; 318 319 do { // wait for all group leaders 320 threads_pending = 0; 321 for (size_t thr = 0; thr < nproc; thr += b->threads_per_group) { 322 threads_pending += b->flags[my_current_iter][thr].stillNeed; 323 } 324 // Execute tasks here 325 if (__kmp_tasking_mode != tskm_immediate_exec) { 326 kmp_task_team_t *task_team = this_thr->th.th_task_team; 327 if (task_team != NULL) { 328 if (TCR_SYNC_4(task_team->tt.tt_active)) { 329 if (KMP_TASKING_ENABLED(task_team)) { 330 int tasks_completed = FALSE; 331 __kmp_atomic_execute_tasks_64( 332 this_thr, gtid, (kmp_atomic_flag_64<> *)NULL, FALSE, 333 &tasks_completed USE_ITT_BUILD_ARG(itt_sync_obj), 0); 334 } else 335 this_thr->th.th_reap_state = KMP_SAFE_TO_REAP; 336 } 337 } else { 338 this_thr->th.th_reap_state = KMP_SAFE_TO_REAP; 339 } // if 340 } 341 if (TCR_4(__kmp_global.g.g_done)) { 342 if (__kmp_global.g.g_abort) 343 __kmp_abort_thread(); 344 break; 345 } else if (__kmp_tasking_mode != tskm_immediate_exec && 346 this_thr->th.th_reap_state == KMP_SAFE_TO_REAP) { 347 this_thr->th.th_reap_state = KMP_NOT_SAFE_TO_REAP; 348 } 349 } while (threads_pending > 0); 350 351 if (reduce) { // Perform reduction if needed 352 if (KMP_MASTER_TID(tid)) { // Master reduces over group leaders 353 OMPT_REDUCTION_DECL(this_thr, gtid); 354 OMPT_REDUCTION_BEGIN; 355 for (size_t thr = b->threads_per_group; thr < nproc; 356 thr += b->threads_per_group) { 357 (*reduce)(this_thr->th.th_local.reduce_data, 358 other_threads[thr]->th.th_local.reduce_data); 359 } 360 OMPT_REDUCTION_END; 361 } 362 } 363 } else { 364 // Set flag for next iteration 365 b->flags[my_next_iter][tid].stillNeed = 1; 366 // Each thread uses a different cache line; resets stillNeed to 0 to 367 // indicate it has reached the barrier 368 b->flags[my_current_iter][tid].stillNeed = 0; 369 } 370 371 KMP_MFENCE(); 372 373 KA_TRACE(20, 374 ("__kmp_dist_barrier_gather: T#%d(%d:%d) exit for barrier type %d\n", 375 gtid, team->t.t_id, tid, bt)); 376 } 377 378 static void __kmp_dist_barrier_release( 379 enum barrier_type bt, kmp_info_t *this_thr, int gtid, int tid, 380 int propagate_icvs USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 381 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_dist_release); 382 kmp_team_t *team; 383 distributedBarrier *b; 384 kmp_bstate_t *thr_bar; 385 kmp_uint64 my_current_iter, next_go; 386 size_t my_go_index; 387 bool group_leader; 388 389 KA_TRACE(20, ("__kmp_dist_barrier_release: T#%d(%d) enter; barrier type %d\n", 390 gtid, tid, bt)); 391 392 thr_bar = &this_thr->th.th_bar[bt].bb; 393 394 if (!KMP_MASTER_TID(tid)) { 395 // workers and non-master group leaders need to check their presence in team 396 do { 397 if (this_thr->th.th_used_in_team.load() != 1 && 398 this_thr->th.th_used_in_team.load() != 3) { 399 // Thread is not in use in a team. Wait on location in tid's thread 400 // struct. The 0 value tells anyone looking that this thread is spinning 401 // or sleeping until this location becomes 3 again; 3 is the transition 402 // state to get to 1 which is waiting on go and being in the team 403 kmp_flag_32<false, false> my_flag(&(this_thr->th.th_used_in_team), 3); 404 if (KMP_COMPARE_AND_STORE_ACQ32(&(this_thr->th.th_used_in_team), 2, 405 0) || 406 this_thr->th.th_used_in_team.load() == 0) { 407 my_flag.wait(this_thr, true, itt_sync_obj); 408 } 409 #if USE_ITT_BUILD && USE_ITT_NOTIFY 410 if ((__itt_sync_create_ptr && itt_sync_obj == NULL) || KMP_ITT_DEBUG) { 411 // In fork barrier where we could not get the object reliably 412 itt_sync_obj = 413 __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier, 0, -1); 414 // Cancel wait on previous parallel region... 415 __kmp_itt_task_starting(itt_sync_obj); 416 417 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done)) 418 return; 419 420 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier); 421 if (itt_sync_obj != NULL) 422 // Call prepare as early as possible for "new" barrier 423 __kmp_itt_task_finished(itt_sync_obj); 424 } else 425 #endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */ 426 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done)) 427 return; 428 } 429 if (this_thr->th.th_used_in_team.load() != 1 && 430 this_thr->th.th_used_in_team.load() != 3) // spurious wake-up? 431 continue; 432 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done)) 433 return; 434 435 // At this point, the thread thinks it is in use in a team, or in 436 // transition to be used in a team, but it might have reached this barrier 437 // before it was marked unused by the team. Unused threads are awoken and 438 // shifted to wait on local thread struct elsewhere. It also might reach 439 // this point by being picked up for use by a different team. Either way, 440 // we need to update the tid. 441 tid = __kmp_tid_from_gtid(gtid); 442 team = this_thr->th.th_team; 443 KMP_DEBUG_ASSERT(tid >= 0); 444 KMP_DEBUG_ASSERT(team); 445 b = team->t.b; 446 my_current_iter = b->iter[tid].iter; 447 next_go = my_current_iter + distributedBarrier::MAX_ITERS; 448 my_go_index = tid / b->threads_per_go; 449 if (this_thr->th.th_used_in_team.load() == 3) { 450 KMP_COMPARE_AND_STORE_ACQ32(&(this_thr->th.th_used_in_team), 3, 1); 451 } 452 // Check if go flag is set 453 if (b->go[my_go_index].go.load() != next_go) { 454 // Wait on go flag on team 455 kmp_atomic_flag_64<false, true> my_flag( 456 &(b->go[my_go_index].go), next_go, &(b->sleep[tid].sleep)); 457 my_flag.wait(this_thr, true, itt_sync_obj); 458 KMP_DEBUG_ASSERT(my_current_iter == b->iter[tid].iter || 459 b->iter[tid].iter == 0); 460 KMP_DEBUG_ASSERT(b->sleep[tid].sleep == false); 461 } 462 463 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done)) 464 return; 465 // At this point, the thread's go location was set. This means the primary 466 // thread is safely in the barrier, and so this thread's data is 467 // up-to-date, but we should check again that this thread is really in 468 // use in the team, as it could have been woken up for the purpose of 469 // changing team size, or reaping threads at shutdown. 470 if (this_thr->th.th_used_in_team.load() == 1) 471 break; 472 } while (1); 473 474 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done)) 475 return; 476 477 group_leader = ((tid % b->threads_per_group) == 0); 478 if (group_leader) { 479 // Tell all the threads in my group they can go! 480 for (size_t go_idx = my_go_index + 1; 481 go_idx < my_go_index + b->gos_per_group; go_idx++) { 482 b->go[go_idx].go.store(next_go); 483 } 484 // Fence added so that workers can see changes to go. sfence inadequate. 485 KMP_MFENCE(); 486 } 487 488 #if KMP_BARRIER_ICV_PUSH 489 if (propagate_icvs) { // copy ICVs to final dest 490 __kmp_init_implicit_task(team->t.t_ident, team->t.t_threads[tid], team, 491 tid, FALSE); 492 copy_icvs(&team->t.t_implicit_task_taskdata[tid].td_icvs, 493 (kmp_internal_control_t *)team->t.b->team_icvs); 494 copy_icvs(&thr_bar->th_fixed_icvs, 495 &team->t.t_implicit_task_taskdata[tid].td_icvs); 496 } 497 #endif 498 if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME && group_leader) { 499 // This thread is now awake and participating in the barrier; 500 // wake up the other threads in the group 501 size_t nproc = this_thr->th.th_team_nproc; 502 size_t group_end = tid + b->threads_per_group; 503 if (nproc < group_end) 504 group_end = nproc; 505 __kmp_dist_barrier_wakeup(bt, team, tid + 1, group_end, 1, tid); 506 } 507 } else { // Primary thread 508 team = this_thr->th.th_team; 509 b = team->t.b; 510 my_current_iter = b->iter[tid].iter; 511 next_go = my_current_iter + distributedBarrier::MAX_ITERS; 512 #if KMP_BARRIER_ICV_PUSH 513 if (propagate_icvs) { 514 // primary thread has ICVs in final destination; copy 515 copy_icvs(&thr_bar->th_fixed_icvs, 516 &team->t.t_implicit_task_taskdata[tid].td_icvs); 517 } 518 #endif 519 // Tell all the group leaders they can go! 520 for (size_t go_idx = 0; go_idx < b->num_gos; go_idx += b->gos_per_group) { 521 b->go[go_idx].go.store(next_go); 522 } 523 524 if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) { 525 // Wake-up the group leaders 526 size_t nproc = this_thr->th.th_team_nproc; 527 __kmp_dist_barrier_wakeup(bt, team, tid + b->threads_per_group, nproc, 528 b->threads_per_group, tid); 529 } 530 531 // Tell all the threads in my group they can go! 532 for (size_t go_idx = 1; go_idx < b->gos_per_group; go_idx++) { 533 b->go[go_idx].go.store(next_go); 534 } 535 536 // Fence added so that workers can see changes to go. sfence inadequate. 537 KMP_MFENCE(); 538 539 if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) { 540 // Wake-up the other threads in my group 541 size_t nproc = this_thr->th.th_team_nproc; 542 size_t group_end = tid + b->threads_per_group; 543 if (nproc < group_end) 544 group_end = nproc; 545 __kmp_dist_barrier_wakeup(bt, team, tid + 1, group_end, 1, tid); 546 } 547 } 548 // Update to next iteration 549 KMP_ASSERT(my_current_iter == b->iter[tid].iter); 550 b->iter[tid].iter = (b->iter[tid].iter + 1) % distributedBarrier::MAX_ITERS; 551 552 KA_TRACE( 553 20, ("__kmp_dist_barrier_release: T#%d(%d:%d) exit for barrier type %d\n", 554 gtid, team->t.t_id, tid, bt)); 555 } 556 557 // Linear Barrier 558 template <bool cancellable = false> 559 static bool __kmp_linear_barrier_gather_template( 560 enum barrier_type bt, kmp_info_t *this_thr, int gtid, int tid, 561 void (*reduce)(void *, void *) USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 562 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_linear_gather); 563 kmp_team_t *team = this_thr->th.th_team; 564 kmp_bstate_t *thr_bar = &this_thr->th.th_bar[bt].bb; 565 kmp_info_t **other_threads = team->t.t_threads; 566 567 KA_TRACE( 568 20, 569 ("__kmp_linear_barrier_gather: T#%d(%d:%d) enter for barrier type %d\n", 570 gtid, team->t.t_id, tid, bt)); 571 KMP_DEBUG_ASSERT(this_thr == other_threads[this_thr->th.th_info.ds.ds_tid]); 572 573 #if USE_ITT_BUILD && USE_ITT_NOTIFY 574 // Barrier imbalance - save arrive time to the thread 575 if (__kmp_forkjoin_frames_mode == 3 || __kmp_forkjoin_frames_mode == 2) { 576 this_thr->th.th_bar_arrive_time = this_thr->th.th_bar_min_time = 577 __itt_get_timestamp(); 578 } 579 #endif 580 // We now perform a linear reduction to signal that all of the threads have 581 // arrived. 582 if (!KMP_MASTER_TID(tid)) { 583 KA_TRACE(20, 584 ("__kmp_linear_barrier_gather: T#%d(%d:%d) releasing T#%d(%d:%d)" 585 "arrived(%p): %llu => %llu\n", 586 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(0, team), 587 team->t.t_id, 0, &thr_bar->b_arrived, thr_bar->b_arrived, 588 thr_bar->b_arrived + KMP_BARRIER_STATE_BUMP)); 589 // Mark arrival to primary thread 590 /* After performing this write, a worker thread may not assume that the team 591 is valid any more - it could be deallocated by the primary thread at any 592 time. */ 593 ANNOTATE_BARRIER_BEGIN(this_thr); 594 kmp_flag_64<> flag(&thr_bar->b_arrived, other_threads[0]); 595 flag.release(); 596 } else { 597 kmp_balign_team_t *team_bar = &team->t.t_bar[bt]; 598 int nproc = this_thr->th.th_team_nproc; 599 int i; 600 // Don't have to worry about sleep bit here or atomic since team setting 601 kmp_uint64 new_state = team_bar->b_arrived + KMP_BARRIER_STATE_BUMP; 602 603 // Collect all the worker team member threads. 604 for (i = 1; i < nproc; ++i) { 605 #if KMP_CACHE_MANAGE 606 // Prefetch next thread's arrived count 607 if (i + 1 < nproc) 608 KMP_CACHE_PREFETCH(&other_threads[i + 1]->th.th_bar[bt].bb.b_arrived); 609 #endif /* KMP_CACHE_MANAGE */ 610 KA_TRACE(20, ("__kmp_linear_barrier_gather: T#%d(%d:%d) wait T#%d(%d:%d) " 611 "arrived(%p) == %llu\n", 612 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(i, team), 613 team->t.t_id, i, 614 &other_threads[i]->th.th_bar[bt].bb.b_arrived, new_state)); 615 616 // Wait for worker thread to arrive 617 if (cancellable) { 618 kmp_flag_64<true, false> flag( 619 &other_threads[i]->th.th_bar[bt].bb.b_arrived, new_state); 620 if (flag.wait(this_thr, FALSE USE_ITT_BUILD_ARG(itt_sync_obj))) 621 return true; 622 } else { 623 kmp_flag_64<> flag(&other_threads[i]->th.th_bar[bt].bb.b_arrived, 624 new_state); 625 flag.wait(this_thr, FALSE USE_ITT_BUILD_ARG(itt_sync_obj)); 626 } 627 ANNOTATE_BARRIER_END(other_threads[i]); 628 #if USE_ITT_BUILD && USE_ITT_NOTIFY 629 // Barrier imbalance - write min of the thread time and the other thread 630 // time to the thread. 631 if (__kmp_forkjoin_frames_mode == 2) { 632 this_thr->th.th_bar_min_time = KMP_MIN( 633 this_thr->th.th_bar_min_time, other_threads[i]->th.th_bar_min_time); 634 } 635 #endif 636 if (reduce) { 637 KA_TRACE(100, 638 ("__kmp_linear_barrier_gather: T#%d(%d:%d) += T#%d(%d:%d)\n", 639 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(i, team), 640 team->t.t_id, i)); 641 ANNOTATE_REDUCE_AFTER(reduce); 642 OMPT_REDUCTION_DECL(this_thr, gtid); 643 OMPT_REDUCTION_BEGIN; 644 (*reduce)(this_thr->th.th_local.reduce_data, 645 other_threads[i]->th.th_local.reduce_data); 646 OMPT_REDUCTION_END; 647 ANNOTATE_REDUCE_BEFORE(reduce); 648 ANNOTATE_REDUCE_BEFORE(&team->t.t_bar); 649 } 650 } 651 // Don't have to worry about sleep bit here or atomic since team setting 652 team_bar->b_arrived = new_state; 653 KA_TRACE(20, ("__kmp_linear_barrier_gather: T#%d(%d:%d) set team %d " 654 "arrived(%p) = %llu\n", 655 gtid, team->t.t_id, tid, team->t.t_id, &team_bar->b_arrived, 656 new_state)); 657 } 658 KA_TRACE( 659 20, 660 ("__kmp_linear_barrier_gather: T#%d(%d:%d) exit for barrier type %d\n", 661 gtid, team->t.t_id, tid, bt)); 662 return false; 663 } 664 665 template <bool cancellable = false> 666 static bool __kmp_linear_barrier_release_template( 667 enum barrier_type bt, kmp_info_t *this_thr, int gtid, int tid, 668 int propagate_icvs USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 669 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_linear_release); 670 kmp_bstate_t *thr_bar = &this_thr->th.th_bar[bt].bb; 671 kmp_team_t *team; 672 673 if (KMP_MASTER_TID(tid)) { 674 unsigned int i; 675 kmp_uint32 nproc = this_thr->th.th_team_nproc; 676 kmp_info_t **other_threads; 677 678 team = __kmp_threads[gtid]->th.th_team; 679 KMP_DEBUG_ASSERT(team != NULL); 680 other_threads = team->t.t_threads; 681 682 KA_TRACE(20, ("__kmp_linear_barrier_release: T#%d(%d:%d) primary enter for " 683 "barrier type %d\n", 684 gtid, team->t.t_id, tid, bt)); 685 686 if (nproc > 1) { 687 #if KMP_BARRIER_ICV_PUSH 688 { 689 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_icv_copy); 690 if (propagate_icvs) { 691 ngo_load(&team->t.t_implicit_task_taskdata[0].td_icvs); 692 for (i = 1; i < nproc; ++i) { 693 __kmp_init_implicit_task(team->t.t_ident, team->t.t_threads[i], 694 team, i, FALSE); 695 ngo_store_icvs(&team->t.t_implicit_task_taskdata[i].td_icvs, 696 &team->t.t_implicit_task_taskdata[0].td_icvs); 697 } 698 ngo_sync(); 699 } 700 } 701 #endif // KMP_BARRIER_ICV_PUSH 702 703 // Now, release all of the worker threads 704 for (i = 1; i < nproc; ++i) { 705 #if KMP_CACHE_MANAGE 706 // Prefetch next thread's go flag 707 if (i + 1 < nproc) 708 KMP_CACHE_PREFETCH(&other_threads[i + 1]->th.th_bar[bt].bb.b_go); 709 #endif /* KMP_CACHE_MANAGE */ 710 KA_TRACE( 711 20, 712 ("__kmp_linear_barrier_release: T#%d(%d:%d) releasing T#%d(%d:%d) " 713 "go(%p): %u => %u\n", 714 gtid, team->t.t_id, tid, other_threads[i]->th.th_info.ds.ds_gtid, 715 team->t.t_id, i, &other_threads[i]->th.th_bar[bt].bb.b_go, 716 other_threads[i]->th.th_bar[bt].bb.b_go, 717 other_threads[i]->th.th_bar[bt].bb.b_go + KMP_BARRIER_STATE_BUMP)); 718 ANNOTATE_BARRIER_BEGIN(other_threads[i]); 719 kmp_flag_64<> flag(&other_threads[i]->th.th_bar[bt].bb.b_go, 720 other_threads[i]); 721 flag.release(); 722 } 723 } 724 } else { // Wait for the PRIMARY thread to release us 725 KA_TRACE(20, ("__kmp_linear_barrier_release: T#%d wait go(%p) == %u\n", 726 gtid, &thr_bar->b_go, KMP_BARRIER_STATE_BUMP)); 727 if (cancellable) { 728 kmp_flag_64<true, false> flag(&thr_bar->b_go, KMP_BARRIER_STATE_BUMP); 729 if (flag.wait(this_thr, TRUE USE_ITT_BUILD_ARG(itt_sync_obj))) 730 return true; 731 } else { 732 kmp_flag_64<> flag(&thr_bar->b_go, KMP_BARRIER_STATE_BUMP); 733 flag.wait(this_thr, TRUE USE_ITT_BUILD_ARG(itt_sync_obj)); 734 } 735 ANNOTATE_BARRIER_END(this_thr); 736 #if USE_ITT_BUILD && USE_ITT_NOTIFY 737 if ((__itt_sync_create_ptr && itt_sync_obj == NULL) || KMP_ITT_DEBUG) { 738 // In a fork barrier; cannot get the object reliably (or ITTNOTIFY is 739 // disabled) 740 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier, 0, -1); 741 // Cancel wait on previous parallel region... 742 __kmp_itt_task_starting(itt_sync_obj); 743 744 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done)) 745 return false; 746 747 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier); 748 if (itt_sync_obj != NULL) 749 // Call prepare as early as possible for "new" barrier 750 __kmp_itt_task_finished(itt_sync_obj); 751 } else 752 #endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */ 753 // Early exit for reaping threads releasing forkjoin barrier 754 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done)) 755 return false; 756 // The worker thread may now assume that the team is valid. 757 #ifdef KMP_DEBUG 758 tid = __kmp_tid_from_gtid(gtid); 759 team = __kmp_threads[gtid]->th.th_team; 760 #endif 761 KMP_DEBUG_ASSERT(team != NULL); 762 TCW_4(thr_bar->b_go, KMP_INIT_BARRIER_STATE); 763 KA_TRACE(20, 764 ("__kmp_linear_barrier_release: T#%d(%d:%d) set go(%p) = %u\n", 765 gtid, team->t.t_id, tid, &thr_bar->b_go, KMP_INIT_BARRIER_STATE)); 766 KMP_MB(); // Flush all pending memory write invalidates. 767 } 768 KA_TRACE( 769 20, 770 ("__kmp_linear_barrier_release: T#%d(%d:%d) exit for barrier type %d\n", 771 gtid, team->t.t_id, tid, bt)); 772 return false; 773 } 774 775 static void __kmp_linear_barrier_gather( 776 enum barrier_type bt, kmp_info_t *this_thr, int gtid, int tid, 777 void (*reduce)(void *, void *) USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 778 __kmp_linear_barrier_gather_template<false>( 779 bt, this_thr, gtid, tid, reduce USE_ITT_BUILD_ARG(itt_sync_obj)); 780 } 781 782 static bool __kmp_linear_barrier_gather_cancellable( 783 enum barrier_type bt, kmp_info_t *this_thr, int gtid, int tid, 784 void (*reduce)(void *, void *) USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 785 return __kmp_linear_barrier_gather_template<true>( 786 bt, this_thr, gtid, tid, reduce USE_ITT_BUILD_ARG(itt_sync_obj)); 787 } 788 789 static void __kmp_linear_barrier_release( 790 enum barrier_type bt, kmp_info_t *this_thr, int gtid, int tid, 791 int propagate_icvs USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 792 __kmp_linear_barrier_release_template<false>( 793 bt, this_thr, gtid, tid, propagate_icvs USE_ITT_BUILD_ARG(itt_sync_obj)); 794 } 795 796 static bool __kmp_linear_barrier_release_cancellable( 797 enum barrier_type bt, kmp_info_t *this_thr, int gtid, int tid, 798 int propagate_icvs USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 799 return __kmp_linear_barrier_release_template<true>( 800 bt, this_thr, gtid, tid, propagate_icvs USE_ITT_BUILD_ARG(itt_sync_obj)); 801 } 802 803 // Tree barrier 804 static void __kmp_tree_barrier_gather( 805 enum barrier_type bt, kmp_info_t *this_thr, int gtid, int tid, 806 void (*reduce)(void *, void *) USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 807 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_tree_gather); 808 kmp_team_t *team = this_thr->th.th_team; 809 kmp_bstate_t *thr_bar = &this_thr->th.th_bar[bt].bb; 810 kmp_info_t **other_threads = team->t.t_threads; 811 kmp_uint32 nproc = this_thr->th.th_team_nproc; 812 kmp_uint32 branch_bits = __kmp_barrier_gather_branch_bits[bt]; 813 kmp_uint32 branch_factor = 1 << branch_bits; 814 kmp_uint32 child; 815 kmp_uint32 child_tid; 816 kmp_uint64 new_state = 0; 817 818 KA_TRACE( 819 20, ("__kmp_tree_barrier_gather: T#%d(%d:%d) enter for barrier type %d\n", 820 gtid, team->t.t_id, tid, bt)); 821 KMP_DEBUG_ASSERT(this_thr == other_threads[this_thr->th.th_info.ds.ds_tid]); 822 823 #if USE_ITT_BUILD && USE_ITT_NOTIFY 824 // Barrier imbalance - save arrive time to the thread 825 if (__kmp_forkjoin_frames_mode == 3 || __kmp_forkjoin_frames_mode == 2) { 826 this_thr->th.th_bar_arrive_time = this_thr->th.th_bar_min_time = 827 __itt_get_timestamp(); 828 } 829 #endif 830 // Perform tree gather to wait until all threads have arrived; reduce any 831 // required data as we go 832 child_tid = (tid << branch_bits) + 1; 833 if (child_tid < nproc) { 834 // Parent threads wait for all their children to arrive 835 new_state = team->t.t_bar[bt].b_arrived + KMP_BARRIER_STATE_BUMP; 836 child = 1; 837 do { 838 kmp_info_t *child_thr = other_threads[child_tid]; 839 kmp_bstate_t *child_bar = &child_thr->th.th_bar[bt].bb; 840 #if KMP_CACHE_MANAGE 841 // Prefetch next thread's arrived count 842 if (child + 1 <= branch_factor && child_tid + 1 < nproc) 843 KMP_CACHE_PREFETCH( 844 &other_threads[child_tid + 1]->th.th_bar[bt].bb.b_arrived); 845 #endif /* KMP_CACHE_MANAGE */ 846 KA_TRACE(20, 847 ("__kmp_tree_barrier_gather: T#%d(%d:%d) wait T#%d(%d:%u) " 848 "arrived(%p) == %llu\n", 849 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(child_tid, team), 850 team->t.t_id, child_tid, &child_bar->b_arrived, new_state)); 851 // Wait for child to arrive 852 kmp_flag_64<> flag(&child_bar->b_arrived, new_state); 853 flag.wait(this_thr, FALSE USE_ITT_BUILD_ARG(itt_sync_obj)); 854 ANNOTATE_BARRIER_END(child_thr); 855 #if USE_ITT_BUILD && USE_ITT_NOTIFY 856 // Barrier imbalance - write min of the thread time and a child time to 857 // the thread. 858 if (__kmp_forkjoin_frames_mode == 2) { 859 this_thr->th.th_bar_min_time = KMP_MIN(this_thr->th.th_bar_min_time, 860 child_thr->th.th_bar_min_time); 861 } 862 #endif 863 if (reduce) { 864 KA_TRACE(100, 865 ("__kmp_tree_barrier_gather: T#%d(%d:%d) += T#%d(%d:%u)\n", 866 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(child_tid, team), 867 team->t.t_id, child_tid)); 868 ANNOTATE_REDUCE_AFTER(reduce); 869 OMPT_REDUCTION_DECL(this_thr, gtid); 870 OMPT_REDUCTION_BEGIN; 871 (*reduce)(this_thr->th.th_local.reduce_data, 872 child_thr->th.th_local.reduce_data); 873 OMPT_REDUCTION_END; 874 ANNOTATE_REDUCE_BEFORE(reduce); 875 ANNOTATE_REDUCE_BEFORE(&team->t.t_bar); 876 } 877 child++; 878 child_tid++; 879 } while (child <= branch_factor && child_tid < nproc); 880 } 881 882 if (!KMP_MASTER_TID(tid)) { // Worker threads 883 kmp_int32 parent_tid = (tid - 1) >> branch_bits; 884 885 KA_TRACE(20, 886 ("__kmp_tree_barrier_gather: T#%d(%d:%d) releasing T#%d(%d:%d) " 887 "arrived(%p): %llu => %llu\n", 888 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(parent_tid, team), 889 team->t.t_id, parent_tid, &thr_bar->b_arrived, thr_bar->b_arrived, 890 thr_bar->b_arrived + KMP_BARRIER_STATE_BUMP)); 891 892 // Mark arrival to parent thread 893 /* After performing this write, a worker thread may not assume that the team 894 is valid any more - it could be deallocated by the primary thread at any 895 time. */ 896 ANNOTATE_BARRIER_BEGIN(this_thr); 897 kmp_flag_64<> flag(&thr_bar->b_arrived, other_threads[parent_tid]); 898 flag.release(); 899 } else { 900 // Need to update the team arrived pointer if we are the primary thread 901 if (nproc > 1) // New value was already computed above 902 team->t.t_bar[bt].b_arrived = new_state; 903 else 904 team->t.t_bar[bt].b_arrived += KMP_BARRIER_STATE_BUMP; 905 KA_TRACE(20, ("__kmp_tree_barrier_gather: T#%d(%d:%d) set team %d " 906 "arrived(%p) = %llu\n", 907 gtid, team->t.t_id, tid, team->t.t_id, 908 &team->t.t_bar[bt].b_arrived, team->t.t_bar[bt].b_arrived)); 909 } 910 KA_TRACE(20, 911 ("__kmp_tree_barrier_gather: T#%d(%d:%d) exit for barrier type %d\n", 912 gtid, team->t.t_id, tid, bt)); 913 } 914 915 static void __kmp_tree_barrier_release( 916 enum barrier_type bt, kmp_info_t *this_thr, int gtid, int tid, 917 int propagate_icvs USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 918 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_tree_release); 919 kmp_team_t *team; 920 kmp_bstate_t *thr_bar = &this_thr->th.th_bar[bt].bb; 921 kmp_uint32 nproc; 922 kmp_uint32 branch_bits = __kmp_barrier_release_branch_bits[bt]; 923 kmp_uint32 branch_factor = 1 << branch_bits; 924 kmp_uint32 child; 925 kmp_uint32 child_tid; 926 927 // Perform a tree release for all of the threads that have been gathered 928 if (!KMP_MASTER_TID( 929 tid)) { // Handle fork barrier workers who aren't part of a team yet 930 KA_TRACE(20, ("__kmp_tree_barrier_release: T#%d wait go(%p) == %u\n", gtid, 931 &thr_bar->b_go, KMP_BARRIER_STATE_BUMP)); 932 // Wait for parent thread to release us 933 kmp_flag_64<> flag(&thr_bar->b_go, KMP_BARRIER_STATE_BUMP); 934 flag.wait(this_thr, TRUE USE_ITT_BUILD_ARG(itt_sync_obj)); 935 ANNOTATE_BARRIER_END(this_thr); 936 #if USE_ITT_BUILD && USE_ITT_NOTIFY 937 if ((__itt_sync_create_ptr && itt_sync_obj == NULL) || KMP_ITT_DEBUG) { 938 // In fork barrier where we could not get the object reliably (or 939 // ITTNOTIFY is disabled) 940 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier, 0, -1); 941 // Cancel wait on previous parallel region... 942 __kmp_itt_task_starting(itt_sync_obj); 943 944 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done)) 945 return; 946 947 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier); 948 if (itt_sync_obj != NULL) 949 // Call prepare as early as possible for "new" barrier 950 __kmp_itt_task_finished(itt_sync_obj); 951 } else 952 #endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */ 953 // Early exit for reaping threads releasing forkjoin barrier 954 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done)) 955 return; 956 957 // The worker thread may now assume that the team is valid. 958 team = __kmp_threads[gtid]->th.th_team; 959 KMP_DEBUG_ASSERT(team != NULL); 960 tid = __kmp_tid_from_gtid(gtid); 961 962 TCW_4(thr_bar->b_go, KMP_INIT_BARRIER_STATE); 963 KA_TRACE(20, 964 ("__kmp_tree_barrier_release: T#%d(%d:%d) set go(%p) = %u\n", gtid, 965 team->t.t_id, tid, &thr_bar->b_go, KMP_INIT_BARRIER_STATE)); 966 KMP_MB(); // Flush all pending memory write invalidates. 967 } else { 968 team = __kmp_threads[gtid]->th.th_team; 969 KMP_DEBUG_ASSERT(team != NULL); 970 KA_TRACE(20, ("__kmp_tree_barrier_release: T#%d(%d:%d) primary enter for " 971 "barrier type %d\n", 972 gtid, team->t.t_id, tid, bt)); 973 } 974 nproc = this_thr->th.th_team_nproc; 975 child_tid = (tid << branch_bits) + 1; 976 977 if (child_tid < nproc) { 978 kmp_info_t **other_threads = team->t.t_threads; 979 child = 1; 980 // Parent threads release all their children 981 do { 982 kmp_info_t *child_thr = other_threads[child_tid]; 983 kmp_bstate_t *child_bar = &child_thr->th.th_bar[bt].bb; 984 #if KMP_CACHE_MANAGE 985 // Prefetch next thread's go count 986 if (child + 1 <= branch_factor && child_tid + 1 < nproc) 987 KMP_CACHE_PREFETCH( 988 &other_threads[child_tid + 1]->th.th_bar[bt].bb.b_go); 989 #endif /* KMP_CACHE_MANAGE */ 990 991 #if KMP_BARRIER_ICV_PUSH 992 { 993 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_icv_copy); 994 if (propagate_icvs) { 995 __kmp_init_implicit_task(team->t.t_ident, 996 team->t.t_threads[child_tid], team, 997 child_tid, FALSE); 998 copy_icvs(&team->t.t_implicit_task_taskdata[child_tid].td_icvs, 999 &team->t.t_implicit_task_taskdata[0].td_icvs); 1000 } 1001 } 1002 #endif // KMP_BARRIER_ICV_PUSH 1003 KA_TRACE(20, 1004 ("__kmp_tree_barrier_release: T#%d(%d:%d) releasing T#%d(%d:%u)" 1005 "go(%p): %u => %u\n", 1006 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(child_tid, team), 1007 team->t.t_id, child_tid, &child_bar->b_go, child_bar->b_go, 1008 child_bar->b_go + KMP_BARRIER_STATE_BUMP)); 1009 // Release child from barrier 1010 ANNOTATE_BARRIER_BEGIN(child_thr); 1011 kmp_flag_64<> flag(&child_bar->b_go, child_thr); 1012 flag.release(); 1013 child++; 1014 child_tid++; 1015 } while (child <= branch_factor && child_tid < nproc); 1016 } 1017 KA_TRACE( 1018 20, ("__kmp_tree_barrier_release: T#%d(%d:%d) exit for barrier type %d\n", 1019 gtid, team->t.t_id, tid, bt)); 1020 } 1021 1022 // Hyper Barrier 1023 static void __kmp_hyper_barrier_gather( 1024 enum barrier_type bt, kmp_info_t *this_thr, int gtid, int tid, 1025 void (*reduce)(void *, void *) USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 1026 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_hyper_gather); 1027 kmp_team_t *team = this_thr->th.th_team; 1028 kmp_bstate_t *thr_bar = &this_thr->th.th_bar[bt].bb; 1029 kmp_info_t **other_threads = team->t.t_threads; 1030 kmp_uint64 new_state = KMP_BARRIER_UNUSED_STATE; 1031 kmp_uint32 num_threads = this_thr->th.th_team_nproc; 1032 kmp_uint32 branch_bits = __kmp_barrier_gather_branch_bits[bt]; 1033 kmp_uint32 branch_factor = 1 << branch_bits; 1034 kmp_uint32 offset; 1035 kmp_uint32 level; 1036 1037 KA_TRACE( 1038 20, 1039 ("__kmp_hyper_barrier_gather: T#%d(%d:%d) enter for barrier type %d\n", 1040 gtid, team->t.t_id, tid, bt)); 1041 KMP_DEBUG_ASSERT(this_thr == other_threads[this_thr->th.th_info.ds.ds_tid]); 1042 1043 #if USE_ITT_BUILD && USE_ITT_NOTIFY 1044 // Barrier imbalance - save arrive time to the thread 1045 if (__kmp_forkjoin_frames_mode == 3 || __kmp_forkjoin_frames_mode == 2) { 1046 this_thr->th.th_bar_arrive_time = this_thr->th.th_bar_min_time = 1047 __itt_get_timestamp(); 1048 } 1049 #endif 1050 /* Perform a hypercube-embedded tree gather to wait until all of the threads 1051 have arrived, and reduce any required data as we go. */ 1052 kmp_flag_64<> p_flag(&thr_bar->b_arrived); 1053 for (level = 0, offset = 1; offset < num_threads; 1054 level += branch_bits, offset <<= branch_bits) { 1055 kmp_uint32 child; 1056 kmp_uint32 child_tid; 1057 1058 if (((tid >> level) & (branch_factor - 1)) != 0) { 1059 kmp_int32 parent_tid = tid & ~((1 << (level + branch_bits)) - 1); 1060 1061 KMP_MB(); // Synchronize parent and child threads. 1062 KA_TRACE(20, 1063 ("__kmp_hyper_barrier_gather: T#%d(%d:%d) releasing T#%d(%d:%d) " 1064 "arrived(%p): %llu => %llu\n", 1065 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(parent_tid, team), 1066 team->t.t_id, parent_tid, &thr_bar->b_arrived, 1067 thr_bar->b_arrived, 1068 thr_bar->b_arrived + KMP_BARRIER_STATE_BUMP)); 1069 // Mark arrival to parent thread 1070 /* After performing this write (in the last iteration of the enclosing for 1071 loop), a worker thread may not assume that the team is valid any more 1072 - it could be deallocated by the primary thread at any time. */ 1073 ANNOTATE_BARRIER_BEGIN(this_thr); 1074 p_flag.set_waiter(other_threads[parent_tid]); 1075 p_flag.release(); 1076 break; 1077 } 1078 1079 // Parent threads wait for children to arrive 1080 if (new_state == KMP_BARRIER_UNUSED_STATE) 1081 new_state = team->t.t_bar[bt].b_arrived + KMP_BARRIER_STATE_BUMP; 1082 for (child = 1, child_tid = tid + (1 << level); 1083 child < branch_factor && child_tid < num_threads; 1084 child++, child_tid += (1 << level)) { 1085 kmp_info_t *child_thr = other_threads[child_tid]; 1086 kmp_bstate_t *child_bar = &child_thr->th.th_bar[bt].bb; 1087 #if KMP_CACHE_MANAGE 1088 kmp_uint32 next_child_tid = child_tid + (1 << level); 1089 // Prefetch next thread's arrived count 1090 if (child + 1 < branch_factor && next_child_tid < num_threads) 1091 KMP_CACHE_PREFETCH( 1092 &other_threads[next_child_tid]->th.th_bar[bt].bb.b_arrived); 1093 #endif /* KMP_CACHE_MANAGE */ 1094 KA_TRACE(20, 1095 ("__kmp_hyper_barrier_gather: T#%d(%d:%d) wait T#%d(%d:%u) " 1096 "arrived(%p) == %llu\n", 1097 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(child_tid, team), 1098 team->t.t_id, child_tid, &child_bar->b_arrived, new_state)); 1099 // Wait for child to arrive 1100 kmp_flag_64<> c_flag(&child_bar->b_arrived, new_state); 1101 c_flag.wait(this_thr, FALSE USE_ITT_BUILD_ARG(itt_sync_obj)); 1102 ANNOTATE_BARRIER_END(child_thr); 1103 KMP_MB(); // Synchronize parent and child threads. 1104 #if USE_ITT_BUILD && USE_ITT_NOTIFY 1105 // Barrier imbalance - write min of the thread time and a child time to 1106 // the thread. 1107 if (__kmp_forkjoin_frames_mode == 2) { 1108 this_thr->th.th_bar_min_time = KMP_MIN(this_thr->th.th_bar_min_time, 1109 child_thr->th.th_bar_min_time); 1110 } 1111 #endif 1112 if (reduce) { 1113 KA_TRACE(100, 1114 ("__kmp_hyper_barrier_gather: T#%d(%d:%d) += T#%d(%d:%u)\n", 1115 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(child_tid, team), 1116 team->t.t_id, child_tid)); 1117 ANNOTATE_REDUCE_AFTER(reduce); 1118 OMPT_REDUCTION_DECL(this_thr, gtid); 1119 OMPT_REDUCTION_BEGIN; 1120 (*reduce)(this_thr->th.th_local.reduce_data, 1121 child_thr->th.th_local.reduce_data); 1122 OMPT_REDUCTION_END; 1123 ANNOTATE_REDUCE_BEFORE(reduce); 1124 ANNOTATE_REDUCE_BEFORE(&team->t.t_bar); 1125 } 1126 } 1127 } 1128 1129 if (KMP_MASTER_TID(tid)) { 1130 // Need to update the team arrived pointer if we are the primary thread 1131 if (new_state == KMP_BARRIER_UNUSED_STATE) 1132 team->t.t_bar[bt].b_arrived += KMP_BARRIER_STATE_BUMP; 1133 else 1134 team->t.t_bar[bt].b_arrived = new_state; 1135 KA_TRACE(20, ("__kmp_hyper_barrier_gather: T#%d(%d:%d) set team %d " 1136 "arrived(%p) = %llu\n", 1137 gtid, team->t.t_id, tid, team->t.t_id, 1138 &team->t.t_bar[bt].b_arrived, team->t.t_bar[bt].b_arrived)); 1139 } 1140 KA_TRACE( 1141 20, ("__kmp_hyper_barrier_gather: T#%d(%d:%d) exit for barrier type %d\n", 1142 gtid, team->t.t_id, tid, bt)); 1143 } 1144 1145 // The reverse versions seem to beat the forward versions overall 1146 #define KMP_REVERSE_HYPER_BAR 1147 static void __kmp_hyper_barrier_release( 1148 enum barrier_type bt, kmp_info_t *this_thr, int gtid, int tid, 1149 int propagate_icvs USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 1150 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_hyper_release); 1151 kmp_team_t *team; 1152 kmp_bstate_t *thr_bar = &this_thr->th.th_bar[bt].bb; 1153 kmp_info_t **other_threads; 1154 kmp_uint32 num_threads; 1155 kmp_uint32 branch_bits = __kmp_barrier_release_branch_bits[bt]; 1156 kmp_uint32 branch_factor = 1 << branch_bits; 1157 kmp_uint32 child; 1158 kmp_uint32 child_tid; 1159 kmp_uint32 offset; 1160 kmp_uint32 level; 1161 1162 /* Perform a hypercube-embedded tree release for all of the threads that have 1163 been gathered. If KMP_REVERSE_HYPER_BAR is defined (default) the threads 1164 are released in the reverse order of the corresponding gather, otherwise 1165 threads are released in the same order. */ 1166 if (KMP_MASTER_TID(tid)) { // primary thread 1167 team = __kmp_threads[gtid]->th.th_team; 1168 KMP_DEBUG_ASSERT(team != NULL); 1169 KA_TRACE(20, ("__kmp_hyper_barrier_release: T#%d(%d:%d) primary enter for " 1170 "barrier type %d\n", 1171 gtid, team->t.t_id, tid, bt)); 1172 #if KMP_BARRIER_ICV_PUSH 1173 if (propagate_icvs) { // primary already has ICVs in final destination; copy 1174 copy_icvs(&thr_bar->th_fixed_icvs, 1175 &team->t.t_implicit_task_taskdata[tid].td_icvs); 1176 } 1177 #endif 1178 } else { // Handle fork barrier workers who aren't part of a team yet 1179 KA_TRACE(20, ("__kmp_hyper_barrier_release: T#%d wait go(%p) == %u\n", gtid, 1180 &thr_bar->b_go, KMP_BARRIER_STATE_BUMP)); 1181 // Wait for parent thread to release us 1182 kmp_flag_64<> flag(&thr_bar->b_go, KMP_BARRIER_STATE_BUMP); 1183 flag.wait(this_thr, TRUE USE_ITT_BUILD_ARG(itt_sync_obj)); 1184 ANNOTATE_BARRIER_END(this_thr); 1185 #if USE_ITT_BUILD && USE_ITT_NOTIFY 1186 if ((__itt_sync_create_ptr && itt_sync_obj == NULL) || KMP_ITT_DEBUG) { 1187 // In fork barrier where we could not get the object reliably 1188 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier, 0, -1); 1189 // Cancel wait on previous parallel region... 1190 __kmp_itt_task_starting(itt_sync_obj); 1191 1192 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done)) 1193 return; 1194 1195 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier); 1196 if (itt_sync_obj != NULL) 1197 // Call prepare as early as possible for "new" barrier 1198 __kmp_itt_task_finished(itt_sync_obj); 1199 } else 1200 #endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */ 1201 // Early exit for reaping threads releasing forkjoin barrier 1202 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done)) 1203 return; 1204 1205 // The worker thread may now assume that the team is valid. 1206 team = __kmp_threads[gtid]->th.th_team; 1207 KMP_DEBUG_ASSERT(team != NULL); 1208 tid = __kmp_tid_from_gtid(gtid); 1209 1210 TCW_4(thr_bar->b_go, KMP_INIT_BARRIER_STATE); 1211 KA_TRACE(20, 1212 ("__kmp_hyper_barrier_release: T#%d(%d:%d) set go(%p) = %u\n", 1213 gtid, team->t.t_id, tid, &thr_bar->b_go, KMP_INIT_BARRIER_STATE)); 1214 KMP_MB(); // Flush all pending memory write invalidates. 1215 } 1216 num_threads = this_thr->th.th_team_nproc; 1217 other_threads = team->t.t_threads; 1218 1219 #ifdef KMP_REVERSE_HYPER_BAR 1220 // Count up to correct level for parent 1221 for (level = 0, offset = 1; 1222 offset < num_threads && (((tid >> level) & (branch_factor - 1)) == 0); 1223 level += branch_bits, offset <<= branch_bits) 1224 ; 1225 1226 // Now go down from there 1227 for (level -= branch_bits, offset >>= branch_bits; offset != 0; 1228 level -= branch_bits, offset >>= branch_bits) 1229 #else 1230 // Go down the tree, level by level 1231 for (level = 0, offset = 1; offset < num_threads; 1232 level += branch_bits, offset <<= branch_bits) 1233 #endif // KMP_REVERSE_HYPER_BAR 1234 { 1235 #ifdef KMP_REVERSE_HYPER_BAR 1236 /* Now go in reverse order through the children, highest to lowest. 1237 Initial setting of child is conservative here. */ 1238 child = num_threads >> ((level == 0) ? level : level - 1); 1239 for (child = (child < branch_factor - 1) ? child : branch_factor - 1, 1240 child_tid = tid + (child << level); 1241 child >= 1; child--, child_tid -= (1 << level)) 1242 #else 1243 if (((tid >> level) & (branch_factor - 1)) != 0) 1244 // No need to go lower than this, since this is the level parent would be 1245 // notified 1246 break; 1247 // Iterate through children on this level of the tree 1248 for (child = 1, child_tid = tid + (1 << level); 1249 child < branch_factor && child_tid < num_threads; 1250 child++, child_tid += (1 << level)) 1251 #endif // KMP_REVERSE_HYPER_BAR 1252 { 1253 if (child_tid >= num_threads) 1254 continue; // Child doesn't exist so keep going 1255 else { 1256 kmp_info_t *child_thr = other_threads[child_tid]; 1257 kmp_bstate_t *child_bar = &child_thr->th.th_bar[bt].bb; 1258 #if KMP_CACHE_MANAGE 1259 kmp_uint32 next_child_tid = child_tid - (1 << level); 1260 // Prefetch next thread's go count 1261 #ifdef KMP_REVERSE_HYPER_BAR 1262 if (child - 1 >= 1 && next_child_tid < num_threads) 1263 #else 1264 if (child + 1 < branch_factor && next_child_tid < num_threads) 1265 #endif // KMP_REVERSE_HYPER_BAR 1266 KMP_CACHE_PREFETCH( 1267 &other_threads[next_child_tid]->th.th_bar[bt].bb.b_go); 1268 #endif /* KMP_CACHE_MANAGE */ 1269 1270 #if KMP_BARRIER_ICV_PUSH 1271 if (propagate_icvs) // push my fixed ICVs to my child 1272 copy_icvs(&child_bar->th_fixed_icvs, &thr_bar->th_fixed_icvs); 1273 #endif // KMP_BARRIER_ICV_PUSH 1274 1275 KA_TRACE( 1276 20, 1277 ("__kmp_hyper_barrier_release: T#%d(%d:%d) releasing T#%d(%d:%u)" 1278 "go(%p): %u => %u\n", 1279 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(child_tid, team), 1280 team->t.t_id, child_tid, &child_bar->b_go, child_bar->b_go, 1281 child_bar->b_go + KMP_BARRIER_STATE_BUMP)); 1282 // Release child from barrier 1283 ANNOTATE_BARRIER_BEGIN(child_thr); 1284 kmp_flag_64<> flag(&child_bar->b_go, child_thr); 1285 flag.release(); 1286 } 1287 } 1288 } 1289 #if KMP_BARRIER_ICV_PUSH 1290 if (propagate_icvs && 1291 !KMP_MASTER_TID(tid)) { // copy ICVs locally to final dest 1292 __kmp_init_implicit_task(team->t.t_ident, team->t.t_threads[tid], team, tid, 1293 FALSE); 1294 copy_icvs(&team->t.t_implicit_task_taskdata[tid].td_icvs, 1295 &thr_bar->th_fixed_icvs); 1296 } 1297 #endif 1298 KA_TRACE( 1299 20, 1300 ("__kmp_hyper_barrier_release: T#%d(%d:%d) exit for barrier type %d\n", 1301 gtid, team->t.t_id, tid, bt)); 1302 } 1303 1304 // Hierarchical Barrier 1305 1306 // Initialize thread barrier data 1307 /* Initializes/re-initializes the hierarchical barrier data stored on a thread. 1308 Performs the minimum amount of initialization required based on how the team 1309 has changed. Returns true if leaf children will require both on-core and 1310 traditional wake-up mechanisms. For example, if the team size increases, 1311 threads already in the team will respond to on-core wakeup on their parent 1312 thread, but threads newly added to the team will only be listening on the 1313 their local b_go. */ 1314 static bool __kmp_init_hierarchical_barrier_thread(enum barrier_type bt, 1315 kmp_bstate_t *thr_bar, 1316 kmp_uint32 nproc, int gtid, 1317 int tid, kmp_team_t *team) { 1318 // Checks to determine if (re-)initialization is needed 1319 bool uninitialized = thr_bar->team == NULL; 1320 bool team_changed = team != thr_bar->team; 1321 bool team_sz_changed = nproc != thr_bar->nproc; 1322 bool tid_changed = tid != thr_bar->old_tid; 1323 bool retval = false; 1324 1325 if (uninitialized || team_sz_changed) { 1326 __kmp_get_hierarchy(nproc, thr_bar); 1327 } 1328 1329 if (uninitialized || team_sz_changed || tid_changed) { 1330 thr_bar->my_level = thr_bar->depth - 1; // default for primary thread 1331 thr_bar->parent_tid = -1; // default for primary thread 1332 if (!KMP_MASTER_TID(tid)) { 1333 // if not primary thread, find parent thread in hierarchy 1334 kmp_uint32 d = 0; 1335 while (d < thr_bar->depth) { // find parent based on level of thread in 1336 // hierarchy, and note level 1337 kmp_uint32 rem; 1338 if (d == thr_bar->depth - 2) { // reached level right below the primary 1339 thr_bar->parent_tid = 0; 1340 thr_bar->my_level = d; 1341 break; 1342 } else if ((rem = tid % thr_bar->skip_per_level[d + 1]) != 0) { 1343 // TODO: can we make the above op faster? 1344 // thread is not a subtree root at next level, so this is max 1345 thr_bar->parent_tid = tid - rem; 1346 thr_bar->my_level = d; 1347 break; 1348 } 1349 ++d; 1350 } 1351 } 1352 __kmp_type_convert(7 - ((tid - thr_bar->parent_tid) / 1353 (thr_bar->skip_per_level[thr_bar->my_level])), 1354 &(thr_bar->offset)); 1355 thr_bar->old_tid = tid; 1356 thr_bar->wait_flag = KMP_BARRIER_NOT_WAITING; 1357 thr_bar->team = team; 1358 thr_bar->parent_bar = 1359 &team->t.t_threads[thr_bar->parent_tid]->th.th_bar[bt].bb; 1360 } 1361 if (uninitialized || team_changed || tid_changed) { 1362 thr_bar->team = team; 1363 thr_bar->parent_bar = 1364 &team->t.t_threads[thr_bar->parent_tid]->th.th_bar[bt].bb; 1365 retval = true; 1366 } 1367 if (uninitialized || team_sz_changed || tid_changed) { 1368 thr_bar->nproc = nproc; 1369 thr_bar->leaf_kids = thr_bar->base_leaf_kids; 1370 if (thr_bar->my_level == 0) 1371 thr_bar->leaf_kids = 0; 1372 if (thr_bar->leaf_kids && (kmp_uint32)tid + thr_bar->leaf_kids + 1 > nproc) 1373 __kmp_type_convert(nproc - tid - 1, &(thr_bar->leaf_kids)); 1374 thr_bar->leaf_state = 0; 1375 for (int i = 0; i < thr_bar->leaf_kids; ++i) 1376 ((char *)&(thr_bar->leaf_state))[7 - i] = 1; 1377 } 1378 return retval; 1379 } 1380 1381 static void __kmp_hierarchical_barrier_gather( 1382 enum barrier_type bt, kmp_info_t *this_thr, int gtid, int tid, 1383 void (*reduce)(void *, void *) USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 1384 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_hier_gather); 1385 kmp_team_t *team = this_thr->th.th_team; 1386 kmp_bstate_t *thr_bar = &this_thr->th.th_bar[bt].bb; 1387 kmp_uint32 nproc = this_thr->th.th_team_nproc; 1388 kmp_info_t **other_threads = team->t.t_threads; 1389 kmp_uint64 new_state = 0; 1390 1391 int level = team->t.t_level; 1392 if (other_threads[0] 1393 ->th.th_teams_microtask) // are we inside the teams construct? 1394 if (this_thr->th.th_teams_size.nteams > 1) 1395 ++level; // level was not increased in teams construct for team_of_masters 1396 if (level == 1) 1397 thr_bar->use_oncore_barrier = 1; 1398 else 1399 thr_bar->use_oncore_barrier = 0; // Do not use oncore barrier when nested 1400 1401 KA_TRACE(20, ("__kmp_hierarchical_barrier_gather: T#%d(%d:%d) enter for " 1402 "barrier type %d\n", 1403 gtid, team->t.t_id, tid, bt)); 1404 KMP_DEBUG_ASSERT(this_thr == other_threads[this_thr->th.th_info.ds.ds_tid]); 1405 1406 #if USE_ITT_BUILD && USE_ITT_NOTIFY 1407 // Barrier imbalance - save arrive time to the thread 1408 if (__kmp_forkjoin_frames_mode == 3 || __kmp_forkjoin_frames_mode == 2) { 1409 this_thr->th.th_bar_arrive_time = __itt_get_timestamp(); 1410 } 1411 #endif 1412 1413 (void)__kmp_init_hierarchical_barrier_thread(bt, thr_bar, nproc, gtid, tid, 1414 team); 1415 1416 if (thr_bar->my_level) { // not a leaf (my_level==0 means leaf) 1417 kmp_int32 child_tid; 1418 new_state = 1419 (kmp_uint64)team->t.t_bar[bt].b_arrived + KMP_BARRIER_STATE_BUMP; 1420 if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME && 1421 thr_bar->use_oncore_barrier) { 1422 if (thr_bar->leaf_kids) { 1423 // First, wait for leaf children to check-in on my b_arrived flag 1424 kmp_uint64 leaf_state = 1425 KMP_MASTER_TID(tid) 1426 ? thr_bar->b_arrived | thr_bar->leaf_state 1427 : team->t.t_bar[bt].b_arrived | thr_bar->leaf_state; 1428 KA_TRACE(20, ("__kmp_hierarchical_barrier_gather: T#%d(%d:%d) waiting " 1429 "for leaf kids\n", 1430 gtid, team->t.t_id, tid)); 1431 kmp_flag_64<> flag(&thr_bar->b_arrived, leaf_state); 1432 flag.wait(this_thr, FALSE USE_ITT_BUILD_ARG(itt_sync_obj)); 1433 if (reduce) { 1434 ANNOTATE_REDUCE_AFTER(reduce); 1435 OMPT_REDUCTION_DECL(this_thr, gtid); 1436 OMPT_REDUCTION_BEGIN; 1437 for (child_tid = tid + 1; child_tid <= tid + thr_bar->leaf_kids; 1438 ++child_tid) { 1439 KA_TRACE(100, ("__kmp_hierarchical_barrier_gather: T#%d(%d:%d) += " 1440 "T#%d(%d:%d)\n", 1441 gtid, team->t.t_id, tid, 1442 __kmp_gtid_from_tid(child_tid, team), team->t.t_id, 1443 child_tid)); 1444 ANNOTATE_BARRIER_END(other_threads[child_tid]); 1445 (*reduce)(this_thr->th.th_local.reduce_data, 1446 other_threads[child_tid]->th.th_local.reduce_data); 1447 } 1448 OMPT_REDUCTION_END; 1449 ANNOTATE_REDUCE_BEFORE(reduce); 1450 ANNOTATE_REDUCE_BEFORE(&team->t.t_bar); 1451 } 1452 // clear leaf_state bits 1453 KMP_TEST_THEN_AND64(&thr_bar->b_arrived, ~(thr_bar->leaf_state)); 1454 } 1455 // Next, wait for higher level children on each child's b_arrived flag 1456 for (kmp_uint32 d = 1; d < thr_bar->my_level; 1457 ++d) { // gather lowest level threads first, but skip 0 1458 kmp_uint32 last = tid + thr_bar->skip_per_level[d + 1], 1459 skip = thr_bar->skip_per_level[d]; 1460 if (last > nproc) 1461 last = nproc; 1462 for (child_tid = tid + skip; child_tid < (int)last; child_tid += skip) { 1463 kmp_info_t *child_thr = other_threads[child_tid]; 1464 kmp_bstate_t *child_bar = &child_thr->th.th_bar[bt].bb; 1465 KA_TRACE(20, ("__kmp_hierarchical_barrier_gather: T#%d(%d:%d) wait " 1466 "T#%d(%d:%d) " 1467 "arrived(%p) == %llu\n", 1468 gtid, team->t.t_id, tid, 1469 __kmp_gtid_from_tid(child_tid, team), team->t.t_id, 1470 child_tid, &child_bar->b_arrived, new_state)); 1471 kmp_flag_64<> flag(&child_bar->b_arrived, new_state); 1472 flag.wait(this_thr, FALSE USE_ITT_BUILD_ARG(itt_sync_obj)); 1473 ANNOTATE_BARRIER_END(child_thr); 1474 if (reduce) { 1475 KA_TRACE(100, ("__kmp_hierarchical_barrier_gather: T#%d(%d:%d) += " 1476 "T#%d(%d:%d)\n", 1477 gtid, team->t.t_id, tid, 1478 __kmp_gtid_from_tid(child_tid, team), team->t.t_id, 1479 child_tid)); 1480 ANNOTATE_REDUCE_AFTER(reduce); 1481 (*reduce)(this_thr->th.th_local.reduce_data, 1482 child_thr->th.th_local.reduce_data); 1483 ANNOTATE_REDUCE_BEFORE(reduce); 1484 ANNOTATE_REDUCE_BEFORE(&team->t.t_bar); 1485 } 1486 } 1487 } 1488 } else { // Blocktime is not infinite 1489 for (kmp_uint32 d = 0; d < thr_bar->my_level; 1490 ++d) { // Gather lowest level threads first 1491 kmp_uint32 last = tid + thr_bar->skip_per_level[d + 1], 1492 skip = thr_bar->skip_per_level[d]; 1493 if (last > nproc) 1494 last = nproc; 1495 for (child_tid = tid + skip; child_tid < (int)last; child_tid += skip) { 1496 kmp_info_t *child_thr = other_threads[child_tid]; 1497 kmp_bstate_t *child_bar = &child_thr->th.th_bar[bt].bb; 1498 KA_TRACE(20, ("__kmp_hierarchical_barrier_gather: T#%d(%d:%d) wait " 1499 "T#%d(%d:%d) " 1500 "arrived(%p) == %llu\n", 1501 gtid, team->t.t_id, tid, 1502 __kmp_gtid_from_tid(child_tid, team), team->t.t_id, 1503 child_tid, &child_bar->b_arrived, new_state)); 1504 kmp_flag_64<> flag(&child_bar->b_arrived, new_state); 1505 flag.wait(this_thr, FALSE USE_ITT_BUILD_ARG(itt_sync_obj)); 1506 ANNOTATE_BARRIER_END(child_thr); 1507 if (reduce) { 1508 KA_TRACE(100, ("__kmp_hierarchical_barrier_gather: T#%d(%d:%d) += " 1509 "T#%d(%d:%d)\n", 1510 gtid, team->t.t_id, tid, 1511 __kmp_gtid_from_tid(child_tid, team), team->t.t_id, 1512 child_tid)); 1513 ANNOTATE_REDUCE_AFTER(reduce); 1514 (*reduce)(this_thr->th.th_local.reduce_data, 1515 child_thr->th.th_local.reduce_data); 1516 ANNOTATE_REDUCE_BEFORE(reduce); 1517 ANNOTATE_REDUCE_BEFORE(&team->t.t_bar); 1518 } 1519 } 1520 } 1521 } 1522 } 1523 // All subordinates are gathered; now release parent if not primary thread 1524 1525 if (!KMP_MASTER_TID(tid)) { // worker threads release parent in hierarchy 1526 KA_TRACE(20, ("__kmp_hierarchical_barrier_gather: T#%d(%d:%d) releasing" 1527 " T#%d(%d:%d) arrived(%p): %llu => %llu\n", 1528 gtid, team->t.t_id, tid, 1529 __kmp_gtid_from_tid(thr_bar->parent_tid, team), team->t.t_id, 1530 thr_bar->parent_tid, &thr_bar->b_arrived, thr_bar->b_arrived, 1531 thr_bar->b_arrived + KMP_BARRIER_STATE_BUMP)); 1532 /* Mark arrival to parent: After performing this write, a worker thread may 1533 not assume that the team is valid any more - it could be deallocated by 1534 the primary thread at any time. */ 1535 if (thr_bar->my_level || __kmp_dflt_blocktime != KMP_MAX_BLOCKTIME || 1536 !thr_bar->use_oncore_barrier) { // Parent is waiting on my b_arrived 1537 // flag; release it 1538 ANNOTATE_BARRIER_BEGIN(this_thr); 1539 kmp_flag_64<> flag(&thr_bar->b_arrived, 1540 other_threads[thr_bar->parent_tid]); 1541 flag.release(); 1542 } else { 1543 // Leaf does special release on "offset" bits of parent's b_arrived flag 1544 thr_bar->b_arrived = team->t.t_bar[bt].b_arrived + KMP_BARRIER_STATE_BUMP; 1545 kmp_flag_oncore flag(&thr_bar->parent_bar->b_arrived, 1546 thr_bar->offset + 1); 1547 flag.set_waiter(other_threads[thr_bar->parent_tid]); 1548 flag.release(); 1549 } 1550 } else { // Primary thread needs to update the team's b_arrived value 1551 team->t.t_bar[bt].b_arrived = new_state; 1552 KA_TRACE(20, ("__kmp_hierarchical_barrier_gather: T#%d(%d:%d) set team %d " 1553 "arrived(%p) = %llu\n", 1554 gtid, team->t.t_id, tid, team->t.t_id, 1555 &team->t.t_bar[bt].b_arrived, team->t.t_bar[bt].b_arrived)); 1556 } 1557 // Is the team access below unsafe or just technically invalid? 1558 KA_TRACE(20, ("__kmp_hierarchical_barrier_gather: T#%d(%d:%d) exit for " 1559 "barrier type %d\n", 1560 gtid, team->t.t_id, tid, bt)); 1561 } 1562 1563 static void __kmp_hierarchical_barrier_release( 1564 enum barrier_type bt, kmp_info_t *this_thr, int gtid, int tid, 1565 int propagate_icvs USE_ITT_BUILD_ARG(void *itt_sync_obj)) { 1566 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_hier_release); 1567 kmp_team_t *team; 1568 kmp_bstate_t *thr_bar = &this_thr->th.th_bar[bt].bb; 1569 kmp_uint32 nproc; 1570 bool team_change = false; // indicates on-core barrier shouldn't be used 1571 1572 if (KMP_MASTER_TID(tid)) { 1573 team = __kmp_threads[gtid]->th.th_team; 1574 KMP_DEBUG_ASSERT(team != NULL); 1575 KA_TRACE(20, ("__kmp_hierarchical_barrier_release: T#%d(%d:%d) primary " 1576 "entered barrier type %d\n", 1577 gtid, team->t.t_id, tid, bt)); 1578 } else { // Worker threads 1579 // Wait for parent thread to release me 1580 if (!thr_bar->use_oncore_barrier || 1581 __kmp_dflt_blocktime != KMP_MAX_BLOCKTIME || thr_bar->my_level != 0 || 1582 thr_bar->team == NULL) { 1583 // Use traditional method of waiting on my own b_go flag 1584 thr_bar->wait_flag = KMP_BARRIER_OWN_FLAG; 1585 kmp_flag_64<> flag(&thr_bar->b_go, KMP_BARRIER_STATE_BUMP); 1586 flag.wait(this_thr, TRUE USE_ITT_BUILD_ARG(itt_sync_obj)); 1587 ANNOTATE_BARRIER_END(this_thr); 1588 TCW_8(thr_bar->b_go, 1589 KMP_INIT_BARRIER_STATE); // Reset my b_go flag for next time 1590 } else { // Thread barrier data is initialized, this is a leaf, blocktime is 1591 // infinite, not nested 1592 // Wait on my "offset" bits on parent's b_go flag 1593 thr_bar->wait_flag = KMP_BARRIER_PARENT_FLAG; 1594 kmp_flag_oncore flag(&thr_bar->parent_bar->b_go, KMP_BARRIER_STATE_BUMP, 1595 thr_bar->offset + 1, bt, 1596 this_thr USE_ITT_BUILD_ARG(itt_sync_obj)); 1597 flag.wait(this_thr, TRUE); 1598 if (thr_bar->wait_flag == 1599 KMP_BARRIER_SWITCHING) { // Thread was switched to own b_go 1600 TCW_8(thr_bar->b_go, 1601 KMP_INIT_BARRIER_STATE); // Reset my b_go flag for next time 1602 } else { // Reset my bits on parent's b_go flag 1603 (RCAST(volatile char *, 1604 &(thr_bar->parent_bar->b_go)))[thr_bar->offset + 1] = 0; 1605 } 1606 } 1607 thr_bar->wait_flag = KMP_BARRIER_NOT_WAITING; 1608 // Early exit for reaping threads releasing forkjoin barrier 1609 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done)) 1610 return; 1611 // The worker thread may now assume that the team is valid. 1612 team = __kmp_threads[gtid]->th.th_team; 1613 KMP_DEBUG_ASSERT(team != NULL); 1614 tid = __kmp_tid_from_gtid(gtid); 1615 1616 KA_TRACE( 1617 20, 1618 ("__kmp_hierarchical_barrier_release: T#%d(%d:%d) set go(%p) = %u\n", 1619 gtid, team->t.t_id, tid, &thr_bar->b_go, KMP_INIT_BARRIER_STATE)); 1620 KMP_MB(); // Flush all pending memory write invalidates. 1621 } 1622 1623 nproc = this_thr->th.th_team_nproc; 1624 int level = team->t.t_level; 1625 if (team->t.t_threads[0] 1626 ->th.th_teams_microtask) { // are we inside the teams construct? 1627 if (team->t.t_pkfn != (microtask_t)__kmp_teams_master && 1628 this_thr->th.th_teams_level == level) 1629 ++level; // level was not increased in teams construct for team_of_workers 1630 if (this_thr->th.th_teams_size.nteams > 1) 1631 ++level; // level was not increased in teams construct for team_of_masters 1632 } 1633 if (level == 1) 1634 thr_bar->use_oncore_barrier = 1; 1635 else 1636 thr_bar->use_oncore_barrier = 0; // Do not use oncore barrier when nested 1637 1638 // If the team size has increased, we still communicate with old leaves via 1639 // oncore barrier. 1640 unsigned short int old_leaf_kids = thr_bar->leaf_kids; 1641 kmp_uint64 old_leaf_state = thr_bar->leaf_state; 1642 team_change = __kmp_init_hierarchical_barrier_thread(bt, thr_bar, nproc, gtid, 1643 tid, team); 1644 // But if the entire team changes, we won't use oncore barrier at all 1645 if (team_change) 1646 old_leaf_kids = 0; 1647 1648 #if KMP_BARRIER_ICV_PUSH 1649 if (propagate_icvs) { 1650 __kmp_init_implicit_task(team->t.t_ident, team->t.t_threads[tid], team, tid, 1651 FALSE); 1652 if (KMP_MASTER_TID( 1653 tid)) { // primary already has copy in final destination; copy 1654 copy_icvs(&thr_bar->th_fixed_icvs, 1655 &team->t.t_implicit_task_taskdata[tid].td_icvs); 1656 } else if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME && 1657 thr_bar->use_oncore_barrier) { // optimization for inf blocktime 1658 if (!thr_bar->my_level) // I'm a leaf in the hierarchy (my_level==0) 1659 // leaves (on-core children) pull parent's fixed ICVs directly to local 1660 // ICV store 1661 copy_icvs(&team->t.t_implicit_task_taskdata[tid].td_icvs, 1662 &thr_bar->parent_bar->th_fixed_icvs); 1663 // non-leaves will get ICVs piggybacked with b_go via NGO store 1664 } else { // blocktime is not infinite; pull ICVs from parent's fixed ICVs 1665 if (thr_bar->my_level) // not a leaf; copy ICVs to my fixed ICVs child can 1666 // access 1667 copy_icvs(&thr_bar->th_fixed_icvs, &thr_bar->parent_bar->th_fixed_icvs); 1668 else // leaves copy parent's fixed ICVs directly to local ICV store 1669 copy_icvs(&team->t.t_implicit_task_taskdata[tid].td_icvs, 1670 &thr_bar->parent_bar->th_fixed_icvs); 1671 } 1672 } 1673 #endif // KMP_BARRIER_ICV_PUSH 1674 1675 // Now, release my children 1676 if (thr_bar->my_level) { // not a leaf 1677 kmp_int32 child_tid; 1678 kmp_uint32 last; 1679 if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME && 1680 thr_bar->use_oncore_barrier) { 1681 if (KMP_MASTER_TID(tid)) { // do a flat release 1682 // Set local b_go to bump children via NGO store of the cache line 1683 // containing IVCs and b_go. 1684 thr_bar->b_go = KMP_BARRIER_STATE_BUMP; 1685 // Use ngo stores if available; b_go piggybacks in the last 8 bytes of 1686 // the cache line 1687 ngo_load(&thr_bar->th_fixed_icvs); 1688 // This loops over all the threads skipping only the leaf nodes in the 1689 // hierarchy 1690 for (child_tid = thr_bar->skip_per_level[1]; child_tid < (int)nproc; 1691 child_tid += thr_bar->skip_per_level[1]) { 1692 kmp_bstate_t *child_bar = 1693 &team->t.t_threads[child_tid]->th.th_bar[bt].bb; 1694 KA_TRACE(20, ("__kmp_hierarchical_barrier_release: T#%d(%d:%d) " 1695 "releasing T#%d(%d:%d)" 1696 " go(%p): %u => %u\n", 1697 gtid, team->t.t_id, tid, 1698 __kmp_gtid_from_tid(child_tid, team), team->t.t_id, 1699 child_tid, &child_bar->b_go, child_bar->b_go, 1700 child_bar->b_go + KMP_BARRIER_STATE_BUMP)); 1701 // Use ngo store (if available) to both store ICVs and release child 1702 // via child's b_go 1703 ngo_store_go(&child_bar->th_fixed_icvs, &thr_bar->th_fixed_icvs); 1704 } 1705 ngo_sync(); 1706 } 1707 TCW_8(thr_bar->b_go, 1708 KMP_INIT_BARRIER_STATE); // Reset my b_go flag for next time 1709 // Now, release leaf children 1710 if (thr_bar->leaf_kids) { // if there are any 1711 // We test team_change on the off-chance that the level 1 team changed. 1712 if (team_change || 1713 old_leaf_kids < thr_bar->leaf_kids) { // some old, some new 1714 if (old_leaf_kids) { // release old leaf kids 1715 thr_bar->b_go |= old_leaf_state; 1716 } 1717 // Release new leaf kids 1718 last = tid + thr_bar->skip_per_level[1]; 1719 if (last > nproc) 1720 last = nproc; 1721 for (child_tid = tid + 1 + old_leaf_kids; child_tid < (int)last; 1722 ++child_tid) { // skip_per_level[0]=1 1723 kmp_info_t *child_thr = team->t.t_threads[child_tid]; 1724 kmp_bstate_t *child_bar = &child_thr->th.th_bar[bt].bb; 1725 KA_TRACE( 1726 20, 1727 ("__kmp_hierarchical_barrier_release: T#%d(%d:%d) releasing" 1728 " T#%d(%d:%d) go(%p): %u => %u\n", 1729 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(child_tid, team), 1730 team->t.t_id, child_tid, &child_bar->b_go, child_bar->b_go, 1731 child_bar->b_go + KMP_BARRIER_STATE_BUMP)); 1732 // Release child using child's b_go flag 1733 ANNOTATE_BARRIER_BEGIN(child_thr); 1734 kmp_flag_64<> flag(&child_bar->b_go, child_thr); 1735 flag.release(); 1736 } 1737 } else { // Release all children at once with leaf_state bits on my own 1738 // b_go flag 1739 thr_bar->b_go |= thr_bar->leaf_state; 1740 } 1741 } 1742 } else { // Blocktime is not infinite; do a simple hierarchical release 1743 for (int d = thr_bar->my_level - 1; d >= 0; 1744 --d) { // Release highest level threads first 1745 last = tid + thr_bar->skip_per_level[d + 1]; 1746 kmp_uint32 skip = thr_bar->skip_per_level[d]; 1747 if (last > nproc) 1748 last = nproc; 1749 for (child_tid = tid + skip; child_tid < (int)last; child_tid += skip) { 1750 kmp_info_t *child_thr = team->t.t_threads[child_tid]; 1751 kmp_bstate_t *child_bar = &child_thr->th.th_bar[bt].bb; 1752 KA_TRACE(20, ("__kmp_hierarchical_barrier_release: T#%d(%d:%d) " 1753 "releasing T#%d(%d:%d) go(%p): %u => %u\n", 1754 gtid, team->t.t_id, tid, 1755 __kmp_gtid_from_tid(child_tid, team), team->t.t_id, 1756 child_tid, &child_bar->b_go, child_bar->b_go, 1757 child_bar->b_go + KMP_BARRIER_STATE_BUMP)); 1758 // Release child using child's b_go flag 1759 ANNOTATE_BARRIER_BEGIN(child_thr); 1760 kmp_flag_64<> flag(&child_bar->b_go, child_thr); 1761 flag.release(); 1762 } 1763 } 1764 } 1765 #if KMP_BARRIER_ICV_PUSH 1766 if (propagate_icvs && !KMP_MASTER_TID(tid)) 1767 // non-leaves copy ICVs from fixed ICVs to local dest 1768 copy_icvs(&team->t.t_implicit_task_taskdata[tid].td_icvs, 1769 &thr_bar->th_fixed_icvs); 1770 #endif // KMP_BARRIER_ICV_PUSH 1771 } 1772 KA_TRACE(20, ("__kmp_hierarchical_barrier_release: T#%d(%d:%d) exit for " 1773 "barrier type %d\n", 1774 gtid, team->t.t_id, tid, bt)); 1775 } 1776 1777 // End of Barrier Algorithms 1778 1779 // type traits for cancellable value 1780 // if cancellable is true, then is_cancellable is a normal boolean variable 1781 // if cancellable is false, then is_cancellable is a compile time constant 1782 template <bool cancellable> struct is_cancellable {}; 1783 template <> struct is_cancellable<true> { 1784 bool value; 1785 is_cancellable() : value(false) {} 1786 is_cancellable(bool b) : value(b) {} 1787 is_cancellable &operator=(bool b) { 1788 value = b; 1789 return *this; 1790 } 1791 operator bool() const { return value; } 1792 }; 1793 template <> struct is_cancellable<false> { 1794 is_cancellable &operator=(bool b) { return *this; } 1795 constexpr operator bool() const { return false; } 1796 }; 1797 1798 // Internal function to do a barrier. 1799 /* If is_split is true, do a split barrier, otherwise, do a plain barrier 1800 If reduce is non-NULL, do a split reduction barrier, otherwise, do a split 1801 barrier 1802 When cancellable = false, 1803 Returns 0 if primary thread, 1 if worker thread. 1804 When cancellable = true 1805 Returns 0 if not cancelled, 1 if cancelled. */ 1806 template <bool cancellable = false> 1807 static int __kmp_barrier_template(enum barrier_type bt, int gtid, int is_split, 1808 size_t reduce_size, void *reduce_data, 1809 void (*reduce)(void *, void *)) { 1810 KMP_TIME_PARTITIONED_BLOCK(OMP_plain_barrier); 1811 KMP_SET_THREAD_STATE_BLOCK(PLAIN_BARRIER); 1812 int tid = __kmp_tid_from_gtid(gtid); 1813 kmp_info_t *this_thr = __kmp_threads[gtid]; 1814 kmp_team_t *team = this_thr->th.th_team; 1815 int status = 0; 1816 is_cancellable<cancellable> cancelled; 1817 #if OMPT_SUPPORT && OMPT_OPTIONAL 1818 ompt_data_t *my_task_data; 1819 ompt_data_t *my_parallel_data; 1820 void *return_address; 1821 ompt_sync_region_t barrier_kind; 1822 #endif 1823 1824 KA_TRACE(15, ("__kmp_barrier: T#%d(%d:%d) has arrived\n", gtid, 1825 __kmp_team_from_gtid(gtid)->t.t_id, __kmp_tid_from_gtid(gtid))); 1826 1827 ANNOTATE_BARRIER_BEGIN(&team->t.t_bar); 1828 #if OMPT_SUPPORT 1829 if (ompt_enabled.enabled) { 1830 #if OMPT_OPTIONAL 1831 my_task_data = OMPT_CUR_TASK_DATA(this_thr); 1832 my_parallel_data = OMPT_CUR_TEAM_DATA(this_thr); 1833 return_address = OMPT_LOAD_RETURN_ADDRESS(gtid); 1834 barrier_kind = __ompt_get_barrier_kind(bt, this_thr); 1835 if (ompt_enabled.ompt_callback_sync_region) { 1836 ompt_callbacks.ompt_callback(ompt_callback_sync_region)( 1837 barrier_kind, ompt_scope_begin, my_parallel_data, my_task_data, 1838 return_address); 1839 } 1840 if (ompt_enabled.ompt_callback_sync_region_wait) { 1841 ompt_callbacks.ompt_callback(ompt_callback_sync_region_wait)( 1842 barrier_kind, ompt_scope_begin, my_parallel_data, my_task_data, 1843 return_address); 1844 } 1845 #endif 1846 // It is OK to report the barrier state after the barrier begin callback. 1847 // According to the OMPT specification, a compliant implementation may 1848 // even delay reporting this state until the barrier begins to wait. 1849 this_thr->th.ompt_thread_info.state = ompt_state_wait_barrier; 1850 } 1851 #endif 1852 1853 if (!team->t.t_serialized) { 1854 #if USE_ITT_BUILD 1855 // This value will be used in itt notify events below. 1856 void *itt_sync_obj = NULL; 1857 #if USE_ITT_NOTIFY 1858 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) 1859 itt_sync_obj = __kmp_itt_barrier_object(gtid, bt, 1); 1860 #endif 1861 #endif /* USE_ITT_BUILD */ 1862 if (__kmp_tasking_mode == tskm_extra_barrier) { 1863 __kmp_tasking_barrier(team, this_thr, gtid); 1864 KA_TRACE(15, 1865 ("__kmp_barrier: T#%d(%d:%d) past tasking barrier\n", gtid, 1866 __kmp_team_from_gtid(gtid)->t.t_id, __kmp_tid_from_gtid(gtid))); 1867 } 1868 1869 /* Copy the blocktime info to the thread, where __kmp_wait_template() can 1870 access it when the team struct is not guaranteed to exist. */ 1871 // See note about the corresponding code in __kmp_join_barrier() being 1872 // performance-critical. 1873 if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) { 1874 #if KMP_USE_MONITOR 1875 this_thr->th.th_team_bt_intervals = 1876 team->t.t_implicit_task_taskdata[tid].td_icvs.bt_intervals; 1877 this_thr->th.th_team_bt_set = 1878 team->t.t_implicit_task_taskdata[tid].td_icvs.bt_set; 1879 #else 1880 this_thr->th.th_team_bt_intervals = KMP_BLOCKTIME_INTERVAL(team, tid); 1881 #endif 1882 } 1883 1884 #if USE_ITT_BUILD 1885 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) 1886 __kmp_itt_barrier_starting(gtid, itt_sync_obj); 1887 #endif /* USE_ITT_BUILD */ 1888 #if USE_DEBUGGER 1889 // Let the debugger know: the thread arrived to the barrier and waiting. 1890 if (KMP_MASTER_TID(tid)) { // Primary thread counter stored in team struct 1891 team->t.t_bar[bt].b_master_arrived += 1; 1892 } else { 1893 this_thr->th.th_bar[bt].bb.b_worker_arrived += 1; 1894 } // if 1895 #endif /* USE_DEBUGGER */ 1896 if (reduce != NULL) { 1897 // KMP_DEBUG_ASSERT( is_split == TRUE ); // #C69956 1898 this_thr->th.th_local.reduce_data = reduce_data; 1899 } 1900 1901 if (KMP_MASTER_TID(tid) && __kmp_tasking_mode != tskm_immediate_exec) 1902 // use 0 to only setup the current team if nthreads > 1 1903 __kmp_task_team_setup(this_thr, team, 0); 1904 1905 if (cancellable) { 1906 cancelled = __kmp_linear_barrier_gather_cancellable( 1907 bt, this_thr, gtid, tid, reduce USE_ITT_BUILD_ARG(itt_sync_obj)); 1908 } else { 1909 switch (__kmp_barrier_gather_pattern[bt]) { 1910 case bp_dist_bar: { 1911 __kmp_dist_barrier_gather(bt, this_thr, gtid, tid, 1912 reduce USE_ITT_BUILD_ARG(itt_sync_obj)); 1913 break; 1914 } 1915 case bp_hyper_bar: { 1916 // don't set branch bits to 0; use linear 1917 KMP_ASSERT(__kmp_barrier_gather_branch_bits[bt]); 1918 __kmp_hyper_barrier_gather(bt, this_thr, gtid, tid, 1919 reduce USE_ITT_BUILD_ARG(itt_sync_obj)); 1920 break; 1921 } 1922 case bp_hierarchical_bar: { 1923 __kmp_hierarchical_barrier_gather( 1924 bt, this_thr, gtid, tid, reduce USE_ITT_BUILD_ARG(itt_sync_obj)); 1925 break; 1926 } 1927 case bp_tree_bar: { 1928 // don't set branch bits to 0; use linear 1929 KMP_ASSERT(__kmp_barrier_gather_branch_bits[bt]); 1930 __kmp_tree_barrier_gather(bt, this_thr, gtid, tid, 1931 reduce USE_ITT_BUILD_ARG(itt_sync_obj)); 1932 break; 1933 } 1934 default: { 1935 __kmp_linear_barrier_gather(bt, this_thr, gtid, tid, 1936 reduce USE_ITT_BUILD_ARG(itt_sync_obj)); 1937 } 1938 } 1939 } 1940 1941 KMP_MB(); 1942 1943 if (KMP_MASTER_TID(tid)) { 1944 status = 0; 1945 if (__kmp_tasking_mode != tskm_immediate_exec && !cancelled) { 1946 __kmp_task_team_wait(this_thr, team USE_ITT_BUILD_ARG(itt_sync_obj)); 1947 } 1948 #if USE_DEBUGGER 1949 // Let the debugger know: All threads are arrived and starting leaving the 1950 // barrier. 1951 team->t.t_bar[bt].b_team_arrived += 1; 1952 #endif 1953 1954 if (__kmp_omp_cancellation) { 1955 kmp_int32 cancel_request = KMP_ATOMIC_LD_RLX(&team->t.t_cancel_request); 1956 // Reset cancellation flag for worksharing constructs 1957 if (cancel_request == cancel_loop || 1958 cancel_request == cancel_sections) { 1959 KMP_ATOMIC_ST_RLX(&team->t.t_cancel_request, cancel_noreq); 1960 } 1961 } 1962 #if USE_ITT_BUILD 1963 /* TODO: In case of split reduction barrier, primary thread may send 1964 acquired event early, before the final summation into the shared 1965 variable is done (final summation can be a long operation for array 1966 reductions). */ 1967 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) 1968 __kmp_itt_barrier_middle(gtid, itt_sync_obj); 1969 #endif /* USE_ITT_BUILD */ 1970 #if USE_ITT_BUILD && USE_ITT_NOTIFY 1971 // Barrier - report frame end (only if active_level == 1) 1972 if ((__itt_frame_submit_v3_ptr || KMP_ITT_DEBUG) && 1973 __kmp_forkjoin_frames_mode && 1974 (this_thr->th.th_teams_microtask == NULL || // either not in teams 1975 this_thr->th.th_teams_size.nteams == 1) && // or inside single team 1976 team->t.t_active_level == 1) { 1977 ident_t *loc = __kmp_threads[gtid]->th.th_ident; 1978 kmp_uint64 cur_time = __itt_get_timestamp(); 1979 kmp_info_t **other_threads = team->t.t_threads; 1980 int nproc = this_thr->th.th_team_nproc; 1981 int i; 1982 switch (__kmp_forkjoin_frames_mode) { 1983 case 1: 1984 __kmp_itt_frame_submit(gtid, this_thr->th.th_frame_time, cur_time, 0, 1985 loc, nproc); 1986 this_thr->th.th_frame_time = cur_time; 1987 break; 1988 case 2: // AC 2015-01-19: currently does not work for hierarchical (to 1989 // be fixed) 1990 __kmp_itt_frame_submit(gtid, this_thr->th.th_bar_min_time, cur_time, 1991 1, loc, nproc); 1992 break; 1993 case 3: 1994 if (__itt_metadata_add_ptr) { 1995 // Initialize with primary thread's wait time 1996 kmp_uint64 delta = cur_time - this_thr->th.th_bar_arrive_time; 1997 // Set arrive time to zero to be able to check it in 1998 // __kmp_invoke_task(); the same is done inside the loop below 1999 this_thr->th.th_bar_arrive_time = 0; 2000 for (i = 1; i < nproc; ++i) { 2001 delta += (cur_time - other_threads[i]->th.th_bar_arrive_time); 2002 other_threads[i]->th.th_bar_arrive_time = 0; 2003 } 2004 __kmp_itt_metadata_imbalance(gtid, this_thr->th.th_frame_time, 2005 cur_time, delta, 2006 (kmp_uint64)(reduce != NULL)); 2007 } 2008 __kmp_itt_frame_submit(gtid, this_thr->th.th_frame_time, cur_time, 0, 2009 loc, nproc); 2010 this_thr->th.th_frame_time = cur_time; 2011 break; 2012 } 2013 } 2014 #endif /* USE_ITT_BUILD */ 2015 } else { 2016 status = 1; 2017 #if USE_ITT_BUILD 2018 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) 2019 __kmp_itt_barrier_middle(gtid, itt_sync_obj); 2020 #endif /* USE_ITT_BUILD */ 2021 } 2022 if ((status == 1 || !is_split) && !cancelled) { 2023 if (cancellable) { 2024 cancelled = __kmp_linear_barrier_release_cancellable( 2025 bt, this_thr, gtid, tid, FALSE USE_ITT_BUILD_ARG(itt_sync_obj)); 2026 } else { 2027 switch (__kmp_barrier_release_pattern[bt]) { 2028 case bp_dist_bar: { 2029 KMP_ASSERT(__kmp_barrier_release_branch_bits[bt]); 2030 __kmp_dist_barrier_release(bt, this_thr, gtid, tid, 2031 FALSE USE_ITT_BUILD_ARG(itt_sync_obj)); 2032 break; 2033 } 2034 case bp_hyper_bar: { 2035 KMP_ASSERT(__kmp_barrier_release_branch_bits[bt]); 2036 __kmp_hyper_barrier_release(bt, this_thr, gtid, tid, 2037 FALSE USE_ITT_BUILD_ARG(itt_sync_obj)); 2038 break; 2039 } 2040 case bp_hierarchical_bar: { 2041 __kmp_hierarchical_barrier_release( 2042 bt, this_thr, gtid, tid, FALSE USE_ITT_BUILD_ARG(itt_sync_obj)); 2043 break; 2044 } 2045 case bp_tree_bar: { 2046 KMP_ASSERT(__kmp_barrier_release_branch_bits[bt]); 2047 __kmp_tree_barrier_release(bt, this_thr, gtid, tid, 2048 FALSE USE_ITT_BUILD_ARG(itt_sync_obj)); 2049 break; 2050 } 2051 default: { 2052 __kmp_linear_barrier_release(bt, this_thr, gtid, tid, 2053 FALSE USE_ITT_BUILD_ARG(itt_sync_obj)); 2054 } 2055 } 2056 } 2057 if (__kmp_tasking_mode != tskm_immediate_exec && !cancelled) { 2058 __kmp_task_team_sync(this_thr, team); 2059 } 2060 } 2061 2062 #if USE_ITT_BUILD 2063 /* GEH: TODO: Move this under if-condition above and also include in 2064 __kmp_end_split_barrier(). This will more accurately represent the actual 2065 release time of the threads for split barriers. */ 2066 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) 2067 __kmp_itt_barrier_finished(gtid, itt_sync_obj); 2068 #endif /* USE_ITT_BUILD */ 2069 } else { // Team is serialized. 2070 status = 0; 2071 if (__kmp_tasking_mode != tskm_immediate_exec) { 2072 if (this_thr->th.th_task_team != NULL) { 2073 #if USE_ITT_NOTIFY 2074 void *itt_sync_obj = NULL; 2075 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) { 2076 itt_sync_obj = __kmp_itt_barrier_object(gtid, bt, 1); 2077 __kmp_itt_barrier_starting(gtid, itt_sync_obj); 2078 } 2079 #endif 2080 2081 KMP_DEBUG_ASSERT(this_thr->th.th_task_team->tt.tt_found_proxy_tasks == 2082 TRUE); 2083 __kmp_task_team_wait(this_thr, team USE_ITT_BUILD_ARG(itt_sync_obj)); 2084 __kmp_task_team_setup(this_thr, team, 0); 2085 2086 #if USE_ITT_BUILD 2087 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) 2088 __kmp_itt_barrier_finished(gtid, itt_sync_obj); 2089 #endif /* USE_ITT_BUILD */ 2090 } 2091 } 2092 } 2093 KA_TRACE(15, ("__kmp_barrier: T#%d(%d:%d) is leaving with return value %d\n", 2094 gtid, __kmp_team_from_gtid(gtid)->t.t_id, 2095 __kmp_tid_from_gtid(gtid), status)); 2096 2097 #if OMPT_SUPPORT 2098 if (ompt_enabled.enabled) { 2099 #if OMPT_OPTIONAL 2100 if (ompt_enabled.ompt_callback_sync_region_wait) { 2101 ompt_callbacks.ompt_callback(ompt_callback_sync_region_wait)( 2102 barrier_kind, ompt_scope_end, my_parallel_data, my_task_data, 2103 return_address); 2104 } 2105 if (ompt_enabled.ompt_callback_sync_region) { 2106 ompt_callbacks.ompt_callback(ompt_callback_sync_region)( 2107 barrier_kind, ompt_scope_end, my_parallel_data, my_task_data, 2108 return_address); 2109 } 2110 #endif 2111 this_thr->th.ompt_thread_info.state = ompt_state_work_parallel; 2112 } 2113 #endif 2114 ANNOTATE_BARRIER_END(&team->t.t_bar); 2115 2116 if (cancellable) 2117 return (int)cancelled; 2118 return status; 2119 } 2120 2121 // Returns 0 if primary thread, 1 if worker thread. 2122 int __kmp_barrier(enum barrier_type bt, int gtid, int is_split, 2123 size_t reduce_size, void *reduce_data, 2124 void (*reduce)(void *, void *)) { 2125 return __kmp_barrier_template<>(bt, gtid, is_split, reduce_size, reduce_data, 2126 reduce); 2127 } 2128 2129 #if defined(KMP_GOMP_COMPAT) 2130 // Returns 1 if cancelled, 0 otherwise 2131 int __kmp_barrier_gomp_cancel(int gtid) { 2132 if (__kmp_omp_cancellation) { 2133 int cancelled = __kmp_barrier_template<true>(bs_plain_barrier, gtid, FALSE, 2134 0, NULL, NULL); 2135 if (cancelled) { 2136 int tid = __kmp_tid_from_gtid(gtid); 2137 kmp_info_t *this_thr = __kmp_threads[gtid]; 2138 if (KMP_MASTER_TID(tid)) { 2139 // Primary thread does not need to revert anything 2140 } else { 2141 // Workers need to revert their private b_arrived flag 2142 this_thr->th.th_bar[bs_plain_barrier].bb.b_arrived -= 2143 KMP_BARRIER_STATE_BUMP; 2144 } 2145 } 2146 return cancelled; 2147 } 2148 __kmp_barrier(bs_plain_barrier, gtid, FALSE, 0, NULL, NULL); 2149 return FALSE; 2150 } 2151 #endif 2152 2153 void __kmp_end_split_barrier(enum barrier_type bt, int gtid) { 2154 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_end_split_barrier); 2155 KMP_SET_THREAD_STATE_BLOCK(PLAIN_BARRIER); 2156 KMP_DEBUG_ASSERT(bt < bs_last_barrier); 2157 int tid = __kmp_tid_from_gtid(gtid); 2158 kmp_info_t *this_thr = __kmp_threads[gtid]; 2159 kmp_team_t *team = this_thr->th.th_team; 2160 2161 ANNOTATE_BARRIER_BEGIN(&team->t.t_bar); 2162 if (!team->t.t_serialized) { 2163 if (KMP_MASTER_GTID(gtid)) { 2164 switch (__kmp_barrier_release_pattern[bt]) { 2165 case bp_dist_bar: { 2166 __kmp_dist_barrier_release(bt, this_thr, gtid, tid, 2167 FALSE USE_ITT_BUILD_ARG(NULL)); 2168 break; 2169 } 2170 case bp_hyper_bar: { 2171 KMP_ASSERT(__kmp_barrier_release_branch_bits[bt]); 2172 __kmp_hyper_barrier_release(bt, this_thr, gtid, tid, 2173 FALSE USE_ITT_BUILD_ARG(NULL)); 2174 break; 2175 } 2176 case bp_hierarchical_bar: { 2177 __kmp_hierarchical_barrier_release(bt, this_thr, gtid, tid, 2178 FALSE USE_ITT_BUILD_ARG(NULL)); 2179 break; 2180 } 2181 case bp_tree_bar: { 2182 KMP_ASSERT(__kmp_barrier_release_branch_bits[bt]); 2183 __kmp_tree_barrier_release(bt, this_thr, gtid, tid, 2184 FALSE USE_ITT_BUILD_ARG(NULL)); 2185 break; 2186 } 2187 default: { 2188 __kmp_linear_barrier_release(bt, this_thr, gtid, tid, 2189 FALSE USE_ITT_BUILD_ARG(NULL)); 2190 } 2191 } 2192 if (__kmp_tasking_mode != tskm_immediate_exec) { 2193 __kmp_task_team_sync(this_thr, team); 2194 } // if 2195 } 2196 } 2197 ANNOTATE_BARRIER_END(&team->t.t_bar); 2198 } 2199 2200 void __kmp_join_barrier(int gtid) { 2201 KMP_TIME_PARTITIONED_BLOCK(OMP_join_barrier); 2202 KMP_SET_THREAD_STATE_BLOCK(FORK_JOIN_BARRIER); 2203 2204 KMP_DEBUG_ASSERT(__kmp_threads && __kmp_threads[gtid]); 2205 2206 kmp_info_t *this_thr = __kmp_threads[gtid]; 2207 kmp_team_t *team; 2208 kmp_uint nproc; 2209 kmp_info_t *master_thread; 2210 int tid; 2211 #ifdef KMP_DEBUG 2212 int team_id; 2213 #endif /* KMP_DEBUG */ 2214 #if USE_ITT_BUILD 2215 void *itt_sync_obj = NULL; 2216 #if USE_ITT_NOTIFY 2217 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) // Don't call routine without need 2218 // Get object created at fork_barrier 2219 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier); 2220 #endif 2221 #endif /* USE_ITT_BUILD */ 2222 KMP_MB(); 2223 2224 // Get current info 2225 team = this_thr->th.th_team; 2226 nproc = this_thr->th.th_team_nproc; 2227 KMP_DEBUG_ASSERT((int)nproc == team->t.t_nproc); 2228 tid = __kmp_tid_from_gtid(gtid); 2229 #ifdef KMP_DEBUG 2230 team_id = team->t.t_id; 2231 #endif /* KMP_DEBUG */ 2232 master_thread = this_thr->th.th_team_master; 2233 #ifdef KMP_DEBUG 2234 if (master_thread != team->t.t_threads[0]) { 2235 __kmp_print_structure(); 2236 } 2237 #endif /* KMP_DEBUG */ 2238 KMP_DEBUG_ASSERT(master_thread == team->t.t_threads[0]); 2239 KMP_MB(); 2240 2241 // Verify state 2242 KMP_DEBUG_ASSERT(TCR_PTR(this_thr->th.th_team)); 2243 KMP_DEBUG_ASSERT(TCR_PTR(this_thr->th.th_root)); 2244 KMP_DEBUG_ASSERT(this_thr == team->t.t_threads[tid]); 2245 KA_TRACE(10, ("__kmp_join_barrier: T#%d(%d:%d) arrived at join barrier\n", 2246 gtid, team_id, tid)); 2247 2248 ANNOTATE_BARRIER_BEGIN(&team->t.t_bar); 2249 #if OMPT_SUPPORT 2250 if (ompt_enabled.enabled) { 2251 #if OMPT_OPTIONAL 2252 ompt_data_t *my_task_data; 2253 ompt_data_t *my_parallel_data; 2254 void *codeptr = NULL; 2255 int ds_tid = this_thr->th.th_info.ds.ds_tid; 2256 if (KMP_MASTER_TID(ds_tid) && 2257 (ompt_callbacks.ompt_callback(ompt_callback_sync_region_wait) || 2258 ompt_callbacks.ompt_callback(ompt_callback_sync_region))) 2259 codeptr = team->t.ompt_team_info.master_return_address; 2260 my_task_data = OMPT_CUR_TASK_DATA(this_thr); 2261 my_parallel_data = OMPT_CUR_TEAM_DATA(this_thr); 2262 if (ompt_enabled.ompt_callback_sync_region) { 2263 ompt_callbacks.ompt_callback(ompt_callback_sync_region)( 2264 ompt_sync_region_barrier_implicit, ompt_scope_begin, my_parallel_data, 2265 my_task_data, codeptr); 2266 } 2267 if (ompt_enabled.ompt_callback_sync_region_wait) { 2268 ompt_callbacks.ompt_callback(ompt_callback_sync_region_wait)( 2269 ompt_sync_region_barrier_implicit, ompt_scope_begin, my_parallel_data, 2270 my_task_data, codeptr); 2271 } 2272 if (!KMP_MASTER_TID(ds_tid)) 2273 this_thr->th.ompt_thread_info.task_data = *OMPT_CUR_TASK_DATA(this_thr); 2274 #endif 2275 this_thr->th.ompt_thread_info.state = ompt_state_wait_barrier_implicit; 2276 } 2277 #endif 2278 2279 if (__kmp_tasking_mode == tskm_extra_barrier) { 2280 __kmp_tasking_barrier(team, this_thr, gtid); 2281 KA_TRACE(10, ("__kmp_join_barrier: T#%d(%d:%d) past tasking barrier\n", 2282 gtid, team_id, tid)); 2283 } 2284 #ifdef KMP_DEBUG 2285 if (__kmp_tasking_mode != tskm_immediate_exec) { 2286 KA_TRACE(20, ("__kmp_join_barrier: T#%d, old team = %d, old task_team = " 2287 "%p, th_task_team = %p\n", 2288 __kmp_gtid_from_thread(this_thr), team_id, 2289 team->t.t_task_team[this_thr->th.th_task_state], 2290 this_thr->th.th_task_team)); 2291 if (this_thr->th.th_task_team) 2292 KMP_DEBUG_ASSERT(this_thr->th.th_task_team == 2293 team->t.t_task_team[this_thr->th.th_task_state]); 2294 } 2295 #endif /* KMP_DEBUG */ 2296 2297 /* Copy the blocktime info to the thread, where __kmp_wait_template() can 2298 access it when the team struct is not guaranteed to exist. Doing these 2299 loads causes a cache miss slows down EPCC parallel by 2x. As a workaround, 2300 we do not perform the copy if blocktime=infinite, since the values are not 2301 used by __kmp_wait_template() in that case. */ 2302 if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) { 2303 #if KMP_USE_MONITOR 2304 this_thr->th.th_team_bt_intervals = 2305 team->t.t_implicit_task_taskdata[tid].td_icvs.bt_intervals; 2306 this_thr->th.th_team_bt_set = 2307 team->t.t_implicit_task_taskdata[tid].td_icvs.bt_set; 2308 #else 2309 this_thr->th.th_team_bt_intervals = KMP_BLOCKTIME_INTERVAL(team, tid); 2310 #endif 2311 } 2312 2313 #if USE_ITT_BUILD 2314 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) 2315 __kmp_itt_barrier_starting(gtid, itt_sync_obj); 2316 #endif /* USE_ITT_BUILD */ 2317 2318 switch (__kmp_barrier_gather_pattern[bs_forkjoin_barrier]) { 2319 case bp_dist_bar: { 2320 __kmp_dist_barrier_gather(bs_forkjoin_barrier, this_thr, gtid, tid, 2321 NULL USE_ITT_BUILD_ARG(itt_sync_obj)); 2322 break; 2323 } 2324 case bp_hyper_bar: { 2325 KMP_ASSERT(__kmp_barrier_gather_branch_bits[bs_forkjoin_barrier]); 2326 __kmp_hyper_barrier_gather(bs_forkjoin_barrier, this_thr, gtid, tid, 2327 NULL USE_ITT_BUILD_ARG(itt_sync_obj)); 2328 break; 2329 } 2330 case bp_hierarchical_bar: { 2331 __kmp_hierarchical_barrier_gather(bs_forkjoin_barrier, this_thr, gtid, tid, 2332 NULL USE_ITT_BUILD_ARG(itt_sync_obj)); 2333 break; 2334 } 2335 case bp_tree_bar: { 2336 KMP_ASSERT(__kmp_barrier_gather_branch_bits[bs_forkjoin_barrier]); 2337 __kmp_tree_barrier_gather(bs_forkjoin_barrier, this_thr, gtid, tid, 2338 NULL USE_ITT_BUILD_ARG(itt_sync_obj)); 2339 break; 2340 } 2341 default: { 2342 __kmp_linear_barrier_gather(bs_forkjoin_barrier, this_thr, gtid, tid, 2343 NULL USE_ITT_BUILD_ARG(itt_sync_obj)); 2344 } 2345 } 2346 2347 /* From this point on, the team data structure may be deallocated at any time 2348 by the primary thread - it is unsafe to reference it in any of the worker 2349 threads. Any per-team data items that need to be referenced before the 2350 end of the barrier should be moved to the kmp_task_team_t structs. */ 2351 if (KMP_MASTER_TID(tid)) { 2352 if (__kmp_tasking_mode != tskm_immediate_exec) { 2353 __kmp_task_team_wait(this_thr, team USE_ITT_BUILD_ARG(itt_sync_obj)); 2354 } 2355 if (__kmp_display_affinity) { 2356 KMP_CHECK_UPDATE(team->t.t_display_affinity, 0); 2357 } 2358 #if KMP_STATS_ENABLED 2359 // Have primary thread flag the workers to indicate they are now waiting for 2360 // next parallel region, Also wake them up so they switch their timers to 2361 // idle. 2362 for (int i = 0; i < team->t.t_nproc; ++i) { 2363 kmp_info_t *team_thread = team->t.t_threads[i]; 2364 if (team_thread == this_thr) 2365 continue; 2366 team_thread->th.th_stats->setIdleFlag(); 2367 if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME && 2368 team_thread->th.th_sleep_loc != NULL) 2369 __kmp_null_resume_wrapper(team_thread); 2370 } 2371 #endif 2372 #if USE_ITT_BUILD 2373 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) 2374 __kmp_itt_barrier_middle(gtid, itt_sync_obj); 2375 #endif /* USE_ITT_BUILD */ 2376 2377 #if USE_ITT_BUILD && USE_ITT_NOTIFY 2378 // Join barrier - report frame end 2379 if ((__itt_frame_submit_v3_ptr || KMP_ITT_DEBUG) && 2380 __kmp_forkjoin_frames_mode && 2381 (this_thr->th.th_teams_microtask == NULL || // either not in teams 2382 this_thr->th.th_teams_size.nteams == 1) && // or inside single team 2383 team->t.t_active_level == 1) { 2384 kmp_uint64 cur_time = __itt_get_timestamp(); 2385 ident_t *loc = team->t.t_ident; 2386 kmp_info_t **other_threads = team->t.t_threads; 2387 int nproc = this_thr->th.th_team_nproc; 2388 int i; 2389 switch (__kmp_forkjoin_frames_mode) { 2390 case 1: 2391 __kmp_itt_frame_submit(gtid, this_thr->th.th_frame_time, cur_time, 0, 2392 loc, nproc); 2393 break; 2394 case 2: 2395 __kmp_itt_frame_submit(gtid, this_thr->th.th_bar_min_time, cur_time, 1, 2396 loc, nproc); 2397 break; 2398 case 3: 2399 if (__itt_metadata_add_ptr) { 2400 // Initialize with primary thread's wait time 2401 kmp_uint64 delta = cur_time - this_thr->th.th_bar_arrive_time; 2402 // Set arrive time to zero to be able to check it in 2403 // __kmp_invoke_task(); the same is done inside the loop below 2404 this_thr->th.th_bar_arrive_time = 0; 2405 for (i = 1; i < nproc; ++i) { 2406 delta += (cur_time - other_threads[i]->th.th_bar_arrive_time); 2407 other_threads[i]->th.th_bar_arrive_time = 0; 2408 } 2409 __kmp_itt_metadata_imbalance(gtid, this_thr->th.th_frame_time, 2410 cur_time, delta, 0); 2411 } 2412 __kmp_itt_frame_submit(gtid, this_thr->th.th_frame_time, cur_time, 0, 2413 loc, nproc); 2414 this_thr->th.th_frame_time = cur_time; 2415 break; 2416 } 2417 } 2418 #endif /* USE_ITT_BUILD */ 2419 } 2420 #if USE_ITT_BUILD 2421 else { 2422 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) 2423 __kmp_itt_barrier_middle(gtid, itt_sync_obj); 2424 } 2425 #endif /* USE_ITT_BUILD */ 2426 2427 #if KMP_DEBUG 2428 if (KMP_MASTER_TID(tid)) { 2429 KA_TRACE( 2430 15, 2431 ("__kmp_join_barrier: T#%d(%d:%d) says all %d team threads arrived\n", 2432 gtid, team_id, tid, nproc)); 2433 } 2434 #endif /* KMP_DEBUG */ 2435 2436 // TODO now, mark worker threads as done so they may be disbanded 2437 KMP_MB(); // Flush all pending memory write invalidates. 2438 KA_TRACE(10, 2439 ("__kmp_join_barrier: T#%d(%d:%d) leaving\n", gtid, team_id, tid)); 2440 2441 ANNOTATE_BARRIER_END(&team->t.t_bar); 2442 } 2443 2444 // TODO release worker threads' fork barriers as we are ready instead of all at 2445 // once 2446 void __kmp_fork_barrier(int gtid, int tid) { 2447 KMP_TIME_PARTITIONED_BLOCK(OMP_fork_barrier); 2448 KMP_SET_THREAD_STATE_BLOCK(FORK_JOIN_BARRIER); 2449 kmp_info_t *this_thr = __kmp_threads[gtid]; 2450 kmp_team_t *team = (tid == 0) ? this_thr->th.th_team : NULL; 2451 #if USE_ITT_BUILD 2452 void *itt_sync_obj = NULL; 2453 #endif /* USE_ITT_BUILD */ 2454 if (team) 2455 ANNOTATE_BARRIER_END(&team->t.t_bar); 2456 2457 KA_TRACE(10, ("__kmp_fork_barrier: T#%d(%d:%d) has arrived\n", gtid, 2458 (team != NULL) ? team->t.t_id : -1, tid)); 2459 2460 // th_team pointer only valid for primary thread here 2461 if (KMP_MASTER_TID(tid)) { 2462 #if USE_ITT_BUILD && USE_ITT_NOTIFY 2463 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) { 2464 // Create itt barrier object 2465 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier, 1); 2466 __kmp_itt_barrier_middle(gtid, itt_sync_obj); // Call acquired/releasing 2467 } 2468 #endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */ 2469 2470 #ifdef KMP_DEBUG 2471 KMP_DEBUG_ASSERT(team); 2472 kmp_info_t **other_threads = team->t.t_threads; 2473 int i; 2474 2475 // Verify state 2476 KMP_MB(); 2477 2478 for (i = 1; i < team->t.t_nproc; ++i) { 2479 KA_TRACE(500, 2480 ("__kmp_fork_barrier: T#%d(%d:0) checking T#%d(%d:%d) fork go " 2481 "== %u.\n", 2482 gtid, team->t.t_id, other_threads[i]->th.th_info.ds.ds_gtid, 2483 team->t.t_id, other_threads[i]->th.th_info.ds.ds_tid, 2484 other_threads[i]->th.th_bar[bs_forkjoin_barrier].bb.b_go)); 2485 KMP_DEBUG_ASSERT( 2486 (TCR_4(other_threads[i]->th.th_bar[bs_forkjoin_barrier].bb.b_go) & 2487 ~(KMP_BARRIER_SLEEP_STATE)) == KMP_INIT_BARRIER_STATE); 2488 KMP_DEBUG_ASSERT(other_threads[i]->th.th_team == team); 2489 } 2490 #endif 2491 2492 if (__kmp_tasking_mode != tskm_immediate_exec) { 2493 // 0 indicates setup current task team if nthreads > 1 2494 __kmp_task_team_setup(this_thr, team, 0); 2495 } 2496 2497 /* The primary thread may have changed its blocktime between join barrier 2498 and fork barrier. Copy the blocktime info to the thread, where 2499 __kmp_wait_template() can access it when the team struct is not 2500 guaranteed to exist. */ 2501 // See note about the corresponding code in __kmp_join_barrier() being 2502 // performance-critical 2503 if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) { 2504 #if KMP_USE_MONITOR 2505 this_thr->th.th_team_bt_intervals = 2506 team->t.t_implicit_task_taskdata[tid].td_icvs.bt_intervals; 2507 this_thr->th.th_team_bt_set = 2508 team->t.t_implicit_task_taskdata[tid].td_icvs.bt_set; 2509 #else 2510 this_thr->th.th_team_bt_intervals = KMP_BLOCKTIME_INTERVAL(team, tid); 2511 #endif 2512 } 2513 } // primary thread 2514 2515 switch (__kmp_barrier_release_pattern[bs_forkjoin_barrier]) { 2516 case bp_dist_bar: { 2517 __kmp_dist_barrier_release(bs_forkjoin_barrier, this_thr, gtid, tid, 2518 TRUE USE_ITT_BUILD_ARG(NULL)); 2519 break; 2520 } 2521 case bp_hyper_bar: { 2522 KMP_ASSERT(__kmp_barrier_release_branch_bits[bs_forkjoin_barrier]); 2523 __kmp_hyper_barrier_release(bs_forkjoin_barrier, this_thr, gtid, tid, 2524 TRUE USE_ITT_BUILD_ARG(itt_sync_obj)); 2525 break; 2526 } 2527 case bp_hierarchical_bar: { 2528 __kmp_hierarchical_barrier_release(bs_forkjoin_barrier, this_thr, gtid, tid, 2529 TRUE USE_ITT_BUILD_ARG(itt_sync_obj)); 2530 break; 2531 } 2532 case bp_tree_bar: { 2533 KMP_ASSERT(__kmp_barrier_release_branch_bits[bs_forkjoin_barrier]); 2534 __kmp_tree_barrier_release(bs_forkjoin_barrier, this_thr, gtid, tid, 2535 TRUE USE_ITT_BUILD_ARG(itt_sync_obj)); 2536 break; 2537 } 2538 default: { 2539 __kmp_linear_barrier_release(bs_forkjoin_barrier, this_thr, gtid, tid, 2540 TRUE USE_ITT_BUILD_ARG(itt_sync_obj)); 2541 } 2542 } 2543 2544 #if OMPT_SUPPORT 2545 if (ompt_enabled.enabled && 2546 this_thr->th.ompt_thread_info.state == ompt_state_wait_barrier_implicit) { 2547 int ds_tid = this_thr->th.th_info.ds.ds_tid; 2548 ompt_data_t *task_data = (team) 2549 ? OMPT_CUR_TASK_DATA(this_thr) 2550 : &(this_thr->th.ompt_thread_info.task_data); 2551 this_thr->th.ompt_thread_info.state = ompt_state_overhead; 2552 #if OMPT_OPTIONAL 2553 void *codeptr = NULL; 2554 if (KMP_MASTER_TID(ds_tid) && 2555 (ompt_callbacks.ompt_callback(ompt_callback_sync_region_wait) || 2556 ompt_callbacks.ompt_callback(ompt_callback_sync_region))) 2557 codeptr = team ? team->t.ompt_team_info.master_return_address : NULL; 2558 if (ompt_enabled.ompt_callback_sync_region_wait) { 2559 ompt_callbacks.ompt_callback(ompt_callback_sync_region_wait)( 2560 ompt_sync_region_barrier_implicit, ompt_scope_end, NULL, task_data, 2561 codeptr); 2562 } 2563 if (ompt_enabled.ompt_callback_sync_region) { 2564 ompt_callbacks.ompt_callback(ompt_callback_sync_region)( 2565 ompt_sync_region_barrier_implicit, ompt_scope_end, NULL, task_data, 2566 codeptr); 2567 } 2568 #endif 2569 if (!KMP_MASTER_TID(ds_tid) && ompt_enabled.ompt_callback_implicit_task) { 2570 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)( 2571 ompt_scope_end, NULL, task_data, 0, ds_tid, 2572 ompt_task_implicit); // TODO: Can this be ompt_task_initial? 2573 } 2574 } 2575 #endif 2576 2577 // Early exit for reaping threads releasing forkjoin barrier 2578 if (TCR_4(__kmp_global.g.g_done)) { 2579 this_thr->th.th_task_team = NULL; 2580 2581 #if USE_ITT_BUILD && USE_ITT_NOTIFY 2582 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) { 2583 if (!KMP_MASTER_TID(tid)) { 2584 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier); 2585 if (itt_sync_obj) 2586 __kmp_itt_barrier_finished(gtid, itt_sync_obj); 2587 } 2588 } 2589 #endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */ 2590 KA_TRACE(10, ("__kmp_fork_barrier: T#%d is leaving early\n", gtid)); 2591 return; 2592 } 2593 2594 /* We can now assume that a valid team structure has been allocated by the 2595 primary thread and propagated to all worker threads. The current thread, 2596 however, may not be part of the team, so we can't blindly assume that the 2597 team pointer is non-null. */ 2598 team = (kmp_team_t *)TCR_PTR(this_thr->th.th_team); 2599 KMP_DEBUG_ASSERT(team != NULL); 2600 tid = __kmp_tid_from_gtid(gtid); 2601 2602 #if KMP_BARRIER_ICV_PULL 2603 /* Primary thread's copy of the ICVs was set up on the implicit taskdata in 2604 __kmp_reinitialize_team. __kmp_fork_call() assumes the primary thread's 2605 implicit task has this data before this function is called. We cannot 2606 modify __kmp_fork_call() to look at the fixed ICVs in the primary thread's 2607 thread struct, because it is not always the case that the threads arrays 2608 have been allocated when __kmp_fork_call() is executed. */ 2609 { 2610 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_icv_copy); 2611 if (!KMP_MASTER_TID(tid)) { // primary thread already has ICVs 2612 // Copy the initial ICVs from the primary thread's thread struct to the 2613 // implicit task for this tid. 2614 KA_TRACE(10, 2615 ("__kmp_fork_barrier: T#%d(%d) is PULLing ICVs\n", gtid, tid)); 2616 __kmp_init_implicit_task(team->t.t_ident, team->t.t_threads[tid], team, 2617 tid, FALSE); 2618 copy_icvs(&team->t.t_implicit_task_taskdata[tid].td_icvs, 2619 &team->t.t_threads[0] 2620 ->th.th_bar[bs_forkjoin_barrier] 2621 .bb.th_fixed_icvs); 2622 } 2623 } 2624 #endif // KMP_BARRIER_ICV_PULL 2625 2626 if (__kmp_tasking_mode != tskm_immediate_exec) { 2627 __kmp_task_team_sync(this_thr, team); 2628 } 2629 2630 #if KMP_AFFINITY_SUPPORTED 2631 kmp_proc_bind_t proc_bind = team->t.t_proc_bind; 2632 if (proc_bind == proc_bind_intel) { 2633 // Call dynamic affinity settings 2634 if (__kmp_affinity_type == affinity_balanced && team->t.t_size_changed) { 2635 __kmp_balanced_affinity(this_thr, team->t.t_nproc); 2636 } 2637 } else if (proc_bind != proc_bind_false) { 2638 if (this_thr->th.th_new_place == this_thr->th.th_current_place) { 2639 KA_TRACE(100, ("__kmp_fork_barrier: T#%d already in correct place %d\n", 2640 __kmp_gtid_from_thread(this_thr), 2641 this_thr->th.th_current_place)); 2642 } else { 2643 __kmp_affinity_set_place(gtid); 2644 } 2645 } 2646 #endif // KMP_AFFINITY_SUPPORTED 2647 // Perform the display affinity functionality 2648 if (__kmp_display_affinity) { 2649 if (team->t.t_display_affinity 2650 #if KMP_AFFINITY_SUPPORTED 2651 || (__kmp_affinity_type == affinity_balanced && team->t.t_size_changed) 2652 #endif 2653 ) { 2654 // NULL means use the affinity-format-var ICV 2655 __kmp_aux_display_affinity(gtid, NULL); 2656 this_thr->th.th_prev_num_threads = team->t.t_nproc; 2657 this_thr->th.th_prev_level = team->t.t_level; 2658 } 2659 } 2660 if (!KMP_MASTER_TID(tid)) 2661 KMP_CHECK_UPDATE(this_thr->th.th_def_allocator, team->t.t_def_allocator); 2662 2663 #if USE_ITT_BUILD && USE_ITT_NOTIFY 2664 if (__itt_sync_create_ptr || KMP_ITT_DEBUG) { 2665 if (!KMP_MASTER_TID(tid)) { 2666 // Get correct barrier object 2667 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier); 2668 __kmp_itt_barrier_finished(gtid, itt_sync_obj); // Workers call acquired 2669 } // (prepare called inside barrier_release) 2670 } 2671 #endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */ 2672 ANNOTATE_BARRIER_END(&team->t.t_bar); 2673 KA_TRACE(10, ("__kmp_fork_barrier: T#%d(%d:%d) is leaving\n", gtid, 2674 team->t.t_id, tid)); 2675 } 2676 2677 void __kmp_setup_icv_copy(kmp_team_t *team, int new_nproc, 2678 kmp_internal_control_t *new_icvs, ident_t *loc) { 2679 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_setup_icv_copy); 2680 2681 KMP_DEBUG_ASSERT(team && new_nproc && new_icvs); 2682 KMP_DEBUG_ASSERT((!TCR_4(__kmp_init_parallel)) || new_icvs->nproc); 2683 2684 /* Primary thread's copy of the ICVs was set up on the implicit taskdata in 2685 __kmp_reinitialize_team. __kmp_fork_call() assumes the primary thread's 2686 implicit task has this data before this function is called. */ 2687 #if KMP_BARRIER_ICV_PULL 2688 /* Copy ICVs to primary thread's thread structure into th_fixed_icvs (which 2689 remains untouched), where all of the worker threads can access them and 2690 make their own copies after the barrier. */ 2691 KMP_DEBUG_ASSERT(team->t.t_threads[0]); // The threads arrays should be 2692 // allocated at this point 2693 copy_icvs( 2694 &team->t.t_threads[0]->th.th_bar[bs_forkjoin_barrier].bb.th_fixed_icvs, 2695 new_icvs); 2696 KF_TRACE(10, ("__kmp_setup_icv_copy: PULL: T#%d this_thread=%p team=%p\n", 0, 2697 team->t.t_threads[0], team)); 2698 #elif KMP_BARRIER_ICV_PUSH 2699 // The ICVs will be propagated in the fork barrier, so nothing needs to be 2700 // done here. 2701 KF_TRACE(10, ("__kmp_setup_icv_copy: PUSH: T#%d this_thread=%p team=%p\n", 0, 2702 team->t.t_threads[0], team)); 2703 #else 2704 // Copy the ICVs to each of the non-primary threads. This takes O(nthreads) 2705 // time. 2706 ngo_load(new_icvs); 2707 KMP_DEBUG_ASSERT(team->t.t_threads[0]); // The threads arrays should be 2708 // allocated at this point 2709 for (int f = 1; f < new_nproc; ++f) { // Skip the primary thread 2710 // TODO: GEH - pass in better source location info since usually NULL here 2711 KF_TRACE(10, ("__kmp_setup_icv_copy: LINEAR: T#%d this_thread=%p team=%p\n", 2712 f, team->t.t_threads[f], team)); 2713 __kmp_init_implicit_task(loc, team->t.t_threads[f], team, f, FALSE); 2714 ngo_store_icvs(&team->t.t_implicit_task_taskdata[f].td_icvs, new_icvs); 2715 KF_TRACE(10, ("__kmp_setup_icv_copy: LINEAR: T#%d this_thread=%p team=%p\n", 2716 f, team->t.t_threads[f], team)); 2717 } 2718 ngo_sync(); 2719 #endif // KMP_BARRIER_ICV_PULL 2720 } 2721