14 #include "kmp_wait_release.h"
17 #include "kmp_stats.h"
18 #include "ompt-specific.h"
21 #include <immintrin.h>
22 #define USE_NGO_STORES 1
25 #if KMP_MIC && USE_NGO_STORES
27 #define ngo_load(src) __m512d Vt = _mm512_load_pd((void *)(src))
28 #define ngo_store_icvs(dst, src) _mm512_storenrngo_pd((void *)(dst), Vt)
29 #define ngo_store_go(dst, src) _mm512_storenrngo_pd((void *)(dst), Vt)
30 #define ngo_sync() __asm__ volatile("lock; addl $0,0(%%rsp)" ::: "memory")
32 #define ngo_load(src) ((void)0)
33 #define ngo_store_icvs(dst, src) copy_icvs((dst), (src))
34 #define ngo_store_go(dst, src) KMP_MEMCPY((dst), (src), CACHE_LINE)
35 #define ngo_sync() ((void)0)
38 void __kmp_print_structure(
void);
43 template <
bool cancellable = false>
44 static bool __kmp_linear_barrier_gather_template(
45 enum barrier_type bt, kmp_info_t *this_thr,
int gtid,
int tid,
46 void (*reduce)(
void *,
void *) USE_ITT_BUILD_ARG(
void *itt_sync_obj)) {
47 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_linear_gather);
48 kmp_team_t *team = this_thr->th.th_team;
49 kmp_bstate_t *thr_bar = &this_thr->th.th_bar[bt].bb;
50 kmp_info_t **other_threads = team->t.t_threads;
54 (
"__kmp_linear_barrier_gather: T#%d(%d:%d) enter for barrier type %d\n",
55 gtid, team->t.t_id, tid, bt));
56 KMP_DEBUG_ASSERT(this_thr == other_threads[this_thr->th.th_info.ds.ds_tid]);
58 #if USE_ITT_BUILD && USE_ITT_NOTIFY
60 if (__kmp_forkjoin_frames_mode == 3 || __kmp_forkjoin_frames_mode == 2) {
61 this_thr->th.th_bar_arrive_time = this_thr->th.th_bar_min_time =
62 __itt_get_timestamp();
67 if (!KMP_MASTER_TID(tid)) {
69 (
"__kmp_linear_barrier_gather: T#%d(%d:%d) releasing T#%d(%d:%d)"
70 "arrived(%p): %llu => %llu\n",
71 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(0, team),
72 team->t.t_id, 0, &thr_bar->b_arrived, thr_bar->b_arrived,
73 thr_bar->b_arrived + KMP_BARRIER_STATE_BUMP));
78 kmp_flag_64<> flag(&thr_bar->b_arrived, other_threads[0]);
81 kmp_balign_team_t *team_bar = &team->t.t_bar[bt];
82 int nproc = this_thr->th.th_team_nproc;
85 kmp_uint64 new_state = team_bar->b_arrived + KMP_BARRIER_STATE_BUMP;
88 for (i = 1; i < nproc; ++i) {
92 KMP_CACHE_PREFETCH(&other_threads[i + 1]->th.th_bar[bt].bb.b_arrived);
94 KA_TRACE(20, (
"__kmp_linear_barrier_gather: T#%d(%d:%d) wait T#%d(%d:%d) "
95 "arrived(%p) == %llu\n",
96 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(i, team),
98 &other_threads[i]->th.th_bar[bt].bb.b_arrived, new_state));
102 kmp_flag_64<true, false> flag(
103 &other_threads[i]->th.th_bar[bt].bb.b_arrived, new_state);
104 if (flag.wait(this_thr, FALSE USE_ITT_BUILD_ARG(itt_sync_obj)))
107 kmp_flag_64<> flag(&other_threads[i]->th.th_bar[bt].bb.b_arrived,
109 flag.wait(this_thr, FALSE USE_ITT_BUILD_ARG(itt_sync_obj));
111 #if USE_ITT_BUILD && USE_ITT_NOTIFY
114 if (__kmp_forkjoin_frames_mode == 2) {
115 this_thr->th.th_bar_min_time = KMP_MIN(
116 this_thr->th.th_bar_min_time, other_threads[i]->th.th_bar_min_time);
121 (
"__kmp_linear_barrier_gather: T#%d(%d:%d) += T#%d(%d:%d)\n",
122 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(i, team),
124 OMPT_REDUCTION_DECL(this_thr, gtid);
125 OMPT_REDUCTION_BEGIN;
126 (*reduce)(this_thr->th.th_local.reduce_data,
127 other_threads[i]->th.th_local.reduce_data);
132 team_bar->b_arrived = new_state;
133 KA_TRACE(20, (
"__kmp_linear_barrier_gather: T#%d(%d:%d) set team %d "
134 "arrived(%p) = %llu\n",
135 gtid, team->t.t_id, tid, team->t.t_id, &team_bar->b_arrived,
140 (
"__kmp_linear_barrier_gather: T#%d(%d:%d) exit for barrier type %d\n",
141 gtid, team->t.t_id, tid, bt));
145 template <
bool cancellable = false>
146 static bool __kmp_linear_barrier_release_template(
147 enum barrier_type bt, kmp_info_t *this_thr,
int gtid,
int tid,
148 int propagate_icvs USE_ITT_BUILD_ARG(
void *itt_sync_obj)) {
149 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_linear_release);
150 kmp_bstate_t *thr_bar = &this_thr->th.th_bar[bt].bb;
153 if (KMP_MASTER_TID(tid)) {
155 kmp_uint32 nproc = this_thr->th.th_team_nproc;
156 kmp_info_t **other_threads;
158 team = __kmp_threads[gtid]->th.th_team;
159 KMP_DEBUG_ASSERT(team != NULL);
160 other_threads = team->t.t_threads;
162 KA_TRACE(20, (
"__kmp_linear_barrier_release: T#%d(%d:%d) primary enter for "
164 gtid, team->t.t_id, tid, bt));
167 #if KMP_BARRIER_ICV_PUSH
169 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_icv_copy);
170 if (propagate_icvs) {
171 ngo_load(&team->t.t_implicit_task_taskdata[0].td_icvs);
172 for (i = 1; i < nproc; ++i) {
173 __kmp_init_implicit_task(team->t.t_ident, team->t.t_threads[i],
175 ngo_store_icvs(&team->t.t_implicit_task_taskdata[i].td_icvs,
176 &team->t.t_implicit_task_taskdata[0].td_icvs);
184 for (i = 1; i < nproc; ++i) {
188 KMP_CACHE_PREFETCH(&other_threads[i + 1]->th.th_bar[bt].bb.b_go);
192 (
"__kmp_linear_barrier_release: T#%d(%d:%d) releasing T#%d(%d:%d) "
193 "go(%p): %u => %u\n",
194 gtid, team->t.t_id, tid, other_threads[i]->th.th_info.ds.ds_gtid,
195 team->t.t_id, i, &other_threads[i]->th.th_bar[bt].bb.b_go,
196 other_threads[i]->th.th_bar[bt].bb.b_go,
197 other_threads[i]->th.th_bar[bt].bb.b_go + KMP_BARRIER_STATE_BUMP));
198 kmp_flag_64<> flag(&other_threads[i]->th.th_bar[bt].bb.b_go,
204 KA_TRACE(20, (
"__kmp_linear_barrier_release: T#%d wait go(%p) == %u\n",
205 gtid, &thr_bar->b_go, KMP_BARRIER_STATE_BUMP));
207 kmp_flag_64<true, false> flag(&thr_bar->b_go, KMP_BARRIER_STATE_BUMP);
208 if (flag.wait(this_thr, TRUE USE_ITT_BUILD_ARG(itt_sync_obj)))
211 kmp_flag_64<> flag(&thr_bar->b_go, KMP_BARRIER_STATE_BUMP);
212 flag.wait(this_thr, TRUE USE_ITT_BUILD_ARG(itt_sync_obj));
214 #if USE_ITT_BUILD && USE_ITT_NOTIFY
215 if ((__itt_sync_create_ptr && itt_sync_obj == NULL) || KMP_ITT_DEBUG) {
218 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier, 0, -1);
220 __kmp_itt_task_starting(itt_sync_obj);
222 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done))
225 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier);
226 if (itt_sync_obj != NULL)
228 __kmp_itt_task_finished(itt_sync_obj);
232 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done))
236 tid = __kmp_tid_from_gtid(gtid);
237 team = __kmp_threads[gtid]->th.th_team;
239 KMP_DEBUG_ASSERT(team != NULL);
240 TCW_4(thr_bar->b_go, KMP_INIT_BARRIER_STATE);
242 (
"__kmp_linear_barrier_release: T#%d(%d:%d) set go(%p) = %u\n",
243 gtid, team->t.t_id, tid, &thr_bar->b_go, KMP_INIT_BARRIER_STATE));
248 (
"__kmp_linear_barrier_release: T#%d(%d:%d) exit for barrier type %d\n",
249 gtid, team->t.t_id, tid, bt));
253 static void __kmp_linear_barrier_gather(
254 enum barrier_type bt, kmp_info_t *this_thr,
int gtid,
int tid,
255 void (*reduce)(
void *,
void *) USE_ITT_BUILD_ARG(
void *itt_sync_obj)) {
256 __kmp_linear_barrier_gather_template<false>(
257 bt, this_thr, gtid, tid, reduce USE_ITT_BUILD_ARG(itt_sync_obj));
260 static bool __kmp_linear_barrier_gather_cancellable(
261 enum barrier_type bt, kmp_info_t *this_thr,
int gtid,
int tid,
262 void (*reduce)(
void *,
void *) USE_ITT_BUILD_ARG(
void *itt_sync_obj)) {
263 return __kmp_linear_barrier_gather_template<true>(
264 bt, this_thr, gtid, tid, reduce USE_ITT_BUILD_ARG(itt_sync_obj));
267 static void __kmp_linear_barrier_release(
268 enum barrier_type bt, kmp_info_t *this_thr,
int gtid,
int tid,
269 int propagate_icvs USE_ITT_BUILD_ARG(
void *itt_sync_obj)) {
270 __kmp_linear_barrier_release_template<false>(
271 bt, this_thr, gtid, tid, propagate_icvs USE_ITT_BUILD_ARG(itt_sync_obj));
274 static bool __kmp_linear_barrier_release_cancellable(
275 enum barrier_type bt, kmp_info_t *this_thr,
int gtid,
int tid,
276 int propagate_icvs USE_ITT_BUILD_ARG(
void *itt_sync_obj)) {
277 return __kmp_linear_barrier_release_template<true>(
278 bt, this_thr, gtid, tid, propagate_icvs USE_ITT_BUILD_ARG(itt_sync_obj));
282 static void __kmp_tree_barrier_gather(
283 enum barrier_type bt, kmp_info_t *this_thr,
int gtid,
int tid,
284 void (*reduce)(
void *,
void *) USE_ITT_BUILD_ARG(
void *itt_sync_obj)) {
285 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_tree_gather);
286 kmp_team_t *team = this_thr->th.th_team;
287 kmp_bstate_t *thr_bar = &this_thr->th.th_bar[bt].bb;
288 kmp_info_t **other_threads = team->t.t_threads;
289 kmp_uint32 nproc = this_thr->th.th_team_nproc;
290 kmp_uint32 branch_bits = __kmp_barrier_gather_branch_bits[bt];
291 kmp_uint32 branch_factor = 1 << branch_bits;
293 kmp_uint32 child_tid;
294 kmp_uint64 new_state = 0;
297 20, (
"__kmp_tree_barrier_gather: T#%d(%d:%d) enter for barrier type %d\n",
298 gtid, team->t.t_id, tid, bt));
299 KMP_DEBUG_ASSERT(this_thr == other_threads[this_thr->th.th_info.ds.ds_tid]);
301 #if USE_ITT_BUILD && USE_ITT_NOTIFY
303 if (__kmp_forkjoin_frames_mode == 3 || __kmp_forkjoin_frames_mode == 2) {
304 this_thr->th.th_bar_arrive_time = this_thr->th.th_bar_min_time =
305 __itt_get_timestamp();
310 child_tid = (tid << branch_bits) + 1;
311 if (child_tid < nproc) {
313 new_state = team->t.t_bar[bt].b_arrived + KMP_BARRIER_STATE_BUMP;
316 kmp_info_t *child_thr = other_threads[child_tid];
317 kmp_bstate_t *child_bar = &child_thr->th.th_bar[bt].bb;
320 if (child + 1 <= branch_factor && child_tid + 1 < nproc)
322 &other_threads[child_tid + 1]->th.th_bar[bt].bb.b_arrived);
325 (
"__kmp_tree_barrier_gather: T#%d(%d:%d) wait T#%d(%d:%u) "
326 "arrived(%p) == %llu\n",
327 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(child_tid, team),
328 team->t.t_id, child_tid, &child_bar->b_arrived, new_state));
330 kmp_flag_64<> flag(&child_bar->b_arrived, new_state);
331 flag.wait(this_thr, FALSE USE_ITT_BUILD_ARG(itt_sync_obj));
332 #if USE_ITT_BUILD && USE_ITT_NOTIFY
335 if (__kmp_forkjoin_frames_mode == 2) {
336 this_thr->th.th_bar_min_time = KMP_MIN(this_thr->th.th_bar_min_time,
337 child_thr->th.th_bar_min_time);
342 (
"__kmp_tree_barrier_gather: T#%d(%d:%d) += T#%d(%d:%u)\n",
343 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(child_tid, team),
344 team->t.t_id, child_tid));
345 OMPT_REDUCTION_DECL(this_thr, gtid);
346 OMPT_REDUCTION_BEGIN;
347 (*reduce)(this_thr->th.th_local.reduce_data,
348 child_thr->th.th_local.reduce_data);
353 }
while (child <= branch_factor && child_tid < nproc);
356 if (!KMP_MASTER_TID(tid)) {
357 kmp_int32 parent_tid = (tid - 1) >> branch_bits;
360 (
"__kmp_tree_barrier_gather: T#%d(%d:%d) releasing T#%d(%d:%d) "
361 "arrived(%p): %llu => %llu\n",
362 gtid, team->t.t_id, tid, __kmp_gtid_from_tid(parent_tid, team),
363 team->t.t_id, parent_tid, &thr_bar->b_arrived, thr_bar->b_arrived,
364 thr_bar->b_arrived + KMP_BARRIER_STATE_BUMP));
370 kmp_flag_64<> flag(&thr_bar->b_arrived, other_threads[parent_tid]);
375 team->t.t_bar[bt].b_arrived = new_state;
377 team->t.t_bar[bt].b_arrived += KMP_BARRIER_STATE_BUMP;
378 KA_TRACE(20, (
"__kmp_tree_barrier_gather: T#%d(%d:%d) set team %d "
379 "arrived(%p) = %llu\n",
380 gtid, team->t.t_id, tid, team->t.t_id,
381 &team->t.t_bar[bt].b_arrived, team->t.t_bar[bt].b_arrived));
384 (
"__kmp_tree_barrier_gather: T#%d(%d:%d) exit for barrier type %d\n",
385 gtid, team->t.t_id, tid, bt));
388 static void __kmp_tree_barrier_release(
389 enum barrier_type bt, kmp_info_t *this_thr,
int gtid,
int tid,
390 int propagate_icvs USE_ITT_BUILD_ARG(
void *itt_sync_obj)) {
391 KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_tree_release);
393 kmp_bstate_t *thr_bar = &this_thr->th.th_bar[bt].bb;
395 kmp_uint32 branch_bits = __kmp_barrier_release_branch_bits[bt];
396 kmp_uint32 branch_factor = 1 << branch_bits;
398 kmp_uint32 child_tid;
403 KA_TRACE(20, (
"__kmp_tree_barrier_release: T#%d wait go(%p) == %u\n", gtid,
404 &thr_bar->b_go, KMP_BARRIER_STATE_BUMP));
406 kmp_flag_64<> flag(&thr_bar->b_go, KMP_BARRIER_STATE_BUMP);
407 flag.wait(this_thr, TRUE USE_ITT_BUILD_ARG(itt_sync_obj));
408 #if USE_ITT_BUILD && USE_ITT_NOTIFY
409 if ((__itt_sync_create_ptr && itt_sync_obj == NULL) || KMP_ITT_DEBUG) {
412 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier, 0, -1);
414 __kmp_itt_task_starting(itt_sync_obj);
416 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done))
419 itt_sync_obj = __kmp_itt_barrier_object(gtid, bs_forkjoin_barrier);
420 if (itt_sync_obj != NULL)
422 __kmp_itt_task_finished(itt_sync_obj);
426 if (bt == bs_forkjoin_barrier && TCR_4(__kmp_global.g.g_done))