13#ifndef KMP_WAIT_RELEASE_H
14#define KMP_WAIT_RELEASE_H
20#include "ompt-specific.h"
36struct flag_properties {
37 unsigned int type : 16;
38 unsigned int reserved : 16;
41template <enum flag_type FlagType>
struct flag_traits {};
43template <>
struct flag_traits<flag32> {
44 typedef kmp_uint32 flag_t;
45 static const flag_type t = flag32;
46 static inline flag_t tcr(flag_t f) {
return TCR_4(f); }
47 static inline flag_t test_then_add4(
volatile flag_t *f) {
48 return KMP_TEST_THEN_ADD4_32(RCAST(
volatile kmp_int32 *, f));
50 static inline flag_t test_then_or(
volatile flag_t *f, flag_t v) {
51 return KMP_TEST_THEN_OR32(f, v);
53 static inline flag_t test_then_and(
volatile flag_t *f, flag_t v) {
54 return KMP_TEST_THEN_AND32(f, v);
58template <>
struct flag_traits<atomic_flag64> {
59 typedef kmp_uint64 flag_t;
60 static const flag_type t = atomic_flag64;
61 static inline flag_t tcr(flag_t f) {
return TCR_8(f); }
62 static inline flag_t test_then_add4(
volatile flag_t *f) {
63 return KMP_TEST_THEN_ADD4_64(RCAST(
volatile kmp_int64 *, f));
65 static inline flag_t test_then_or(
volatile flag_t *f, flag_t v) {
66 return KMP_TEST_THEN_OR64(f, v);
68 static inline flag_t test_then_and(
volatile flag_t *f, flag_t v) {
69 return KMP_TEST_THEN_AND64(f, v);
73template <>
struct flag_traits<flag64> {
74 typedef kmp_uint64 flag_t;
75 static const flag_type t = flag64;
76 static inline flag_t tcr(flag_t f) {
return TCR_8(f); }
77 static inline flag_t test_then_add4(
volatile flag_t *f) {
78 return KMP_TEST_THEN_ADD4_64(RCAST(
volatile kmp_int64 *, f));
80 static inline flag_t test_then_or(
volatile flag_t *f, flag_t v) {
81 return KMP_TEST_THEN_OR64(f, v);
83 static inline flag_t test_then_and(
volatile flag_t *f, flag_t v) {
84 return KMP_TEST_THEN_AND64(f, v);
88template <>
struct flag_traits<flag_oncore> {
89 typedef kmp_uint64 flag_t;
90 static const flag_type t = flag_oncore;
91 static inline flag_t tcr(flag_t f) {
return TCR_8(f); }
92 static inline flag_t test_then_add4(
volatile flag_t *f) {
93 return KMP_TEST_THEN_ADD4_64(RCAST(
volatile kmp_int64 *, f));
95 static inline flag_t test_then_or(
volatile flag_t *f, flag_t v) {
96 return KMP_TEST_THEN_OR64(f, v);
98 static inline flag_t test_then_and(
volatile flag_t *f, flag_t v) {
99 return KMP_TEST_THEN_AND64(f, v);
109 std::atomic<bool> *sleepLoc;
112 typedef flag_traits<FlagType> traits_type;
135 enum barrier_type get_bt() {
return bs_last_barrier; }
139template <
typename PtrType, flag_type FlagType,
bool Sleepable>
142 volatile PtrType *loc;
144 typedef flag_traits<FlagType> traits_type;
147 typedef PtrType flag_t;
155 kmp_flag_native(
volatile PtrType *p, PtrType c, std::atomic<bool> *sloc)
158 void *
operator new(
size_t size) {
return __kmp_allocate(size); }
159 void operator delete(
void *p) { __kmp_free(p); }
160 volatile PtrType *get() {
return loc; }
161 void *get_void_p() {
return RCAST(
void *, CCAST(PtrType *, loc)); }
162 void set(
volatile PtrType *new_loc) { loc = new_loc; }
163 PtrType load() {
return *loc; }
164 void store(PtrType val) { *loc = val; }
167 if (Sleepable && !(this->sleepLoc))
168 return (traits_type::tcr(*(this->get())) & ~KMP_BARRIER_SLEEP_STATE) ==
171 return traits_type::tcr(*(this->get())) ==
checker;
182 return traits_type::tcr(*(this->get())) !=
checker;
187 (void)traits_type::test_then_add4((
volatile PtrType *)this->get());
193 if (this->sleepLoc) {
194 this->sleepLoc->store(
true);
195 return *(this->get());
197 return traits_type::test_then_or((
volatile PtrType *)this->get(),
198 KMP_BARRIER_SLEEP_STATE);
204 if (this->sleepLoc) {
205 this->sleepLoc->store(
false);
208 traits_type::test_then_and((
volatile PtrType *)this->get(),
209 ~KMP_BARRIER_SLEEP_STATE);
215 return this->sleepLoc->load();
216 return old_loc & KMP_BARRIER_SLEEP_STATE;
221 return this->sleepLoc->load();
224 bool is_any_sleeping() {
226 return this->sleepLoc->load();
229 kmp_uint8 *get_stolen() {
return NULL; }
233template <
typename PtrType, flag_type FlagType,
bool Sleepable>
236 std::atomic<PtrType> *
loc;
239 typedef flag_traits<FlagType> traits_type;
240 typedef PtrType flag_t;
248 kmp_flag_atomic(std::atomic<PtrType> *p, PtrType c, std::atomic<bool> *sloc)
251 std::atomic<PtrType> *
get() {
return loc; }
255 void set(std::atomic<PtrType> *new_loc) {
loc = new_loc; }
257 PtrType
load() {
return loc->load(std::memory_order_acquire); }
259 void store(PtrType val) {
loc->store(val, std::memory_order_release); }
262 if (Sleepable && !(this->sleepLoc))
263 return (this->
load() & ~KMP_BARRIER_SLEEP_STATE) ==
checker;
283 if (this->sleepLoc) {
284 this->sleepLoc->store(
true);
285 return *(this->
get());
287 return KMP_ATOMIC_OR(this->
get(), KMP_BARRIER_SLEEP_STATE);
293 if (this->sleepLoc) {
294 this->sleepLoc->store(
false);
297 KMP_ATOMIC_AND(this->
get(), ~KMP_BARRIER_SLEEP_STATE);
303 return this->sleepLoc->load();
304 return old_loc & KMP_BARRIER_SLEEP_STATE;
309 return this->sleepLoc->load();
312 bool is_any_sleeping() {
314 return this->sleepLoc->load();
317 kmp_uint8 *get_stolen() {
return NULL; }
322static void __ompt_implicit_task_end(kmp_info_t *this_thr,
323 ompt_state_t ompt_state,
325 int ds_tid = this_thr->th.th_info.ds.ds_tid;
326 if (ompt_state == ompt_state_wait_barrier_implicit) {
327 this_thr->th.ompt_thread_info.state = ompt_state_overhead;
329 void *codeptr = NULL;
330 if (ompt_enabled.ompt_callback_sync_region_wait) {
331 ompt_callbacks.ompt_callback(ompt_callback_sync_region_wait)(
332 ompt_sync_region_barrier_implicit, ompt_scope_end, NULL, tId,
335 if (ompt_enabled.ompt_callback_sync_region) {
336 ompt_callbacks.ompt_callback(ompt_callback_sync_region)(
337 ompt_sync_region_barrier_implicit, ompt_scope_end, NULL, tId,
341 if (!KMP_MASTER_TID(ds_tid)) {
342 if (ompt_enabled.ompt_callback_implicit_task) {
343 int flags = this_thr->th.ompt_thread_info.parallel_flags;
344 flags = (flags & ompt_parallel_league) ? ompt_task_initial
345 : ompt_task_implicit;
346 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
347 ompt_scope_end, NULL, tId, 0, ds_tid, flags);
350 this_thr->th.ompt_thread_info.state = ompt_state_idle;
352 this_thr->th.ompt_thread_info.state = ompt_state_overhead;
363template <
class C,
bool final_spin,
bool Cancellable =
false,
364 bool Sleepable =
true>
366__kmp_wait_template(kmp_info_t *this_thr,
367 C *flag USE_ITT_BUILD_ARG(
void *itt_sync_obj)) {
368#if USE_ITT_BUILD && USE_ITT_NOTIFY
369 volatile void *spin = flag->get();
373 int tasks_completed = FALSE;
375 kmp_uint64 poll_count;
376 kmp_uint64 hibernate_goal;
378 kmp_uint32 hibernate;
382 KMP_FSYNC_SPIN_INIT(spin, NULL);
383 if (flag->done_check()) {
384 KMP_FSYNC_SPIN_ACQUIRED(CCAST(
void *, spin));
387 th_gtid = this_thr->th.th_info.ds.ds_gtid;
389 kmp_team_t *team = this_thr->th.th_team;
390 if (team && team->t.t_cancel_request == cancel_parallel)
395 KMP_ATOMIC_ST_REL(&this_thr->th.th_blocking,
true);
398 (
"__kmp_wait_sleep: T#%d waiting for flag(%p)\n", th_gtid, flag));
454 ompt_state_t ompt_entry_state;
456 if (ompt_enabled.enabled) {
457 ompt_entry_state = this_thr->th.ompt_thread_info.state;
458 if (!final_spin || ompt_entry_state != ompt_state_wait_barrier_implicit ||
459 KMP_MASTER_TID(this_thr->th.th_info.ds.ds_tid)) {
460 ompt_lw_taskteam_t *team = NULL;
461 if (this_thr->th.th_team)
462 team = this_thr->th.th_team->t.ompt_serialized_team_info;
464 tId = &(team->ompt_task_info.task_data);
466 tId = OMPT_CUR_TASK_DATA(this_thr);
469 tId = &(this_thr->th.ompt_thread_info.task_data);
471 if (final_spin && (__kmp_tasking_mode == tskm_immediate_exec ||
472 this_thr->th.th_task_team == NULL)) {
474 __ompt_implicit_task_end(this_thr, ompt_entry_state, tId);
479 KMP_INIT_YIELD(spins);
480 KMP_INIT_BACKOFF(time);
482 if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME ||
483 __kmp_pause_status == kmp_soft_paused) {
487#ifdef KMP_ADJUST_BLOCKTIME
488 if (__kmp_pause_status == kmp_soft_paused ||
489 (__kmp_zero_bt && !this_thr->th.th_team_bt_set))
494 hibernate = this_thr->th.th_team_bt_intervals;
496 hibernate = this_thr->th.th_team_bt_intervals;
507 hibernate += TCR_4(__kmp_global.g.g_time.dt.t_value);
508 KF_TRACE(20, (
"__kmp_wait_sleep: T#%d now=%d, hibernate=%d, intervals=%d\n",
509 th_gtid, __kmp_global.g.g_time.dt.t_value, hibernate,
510 hibernate - __kmp_global.g.g_time.dt.t_value));
512 if (__kmp_pause_status == kmp_soft_paused) {
514 hibernate_goal = KMP_NOW();
516 hibernate_goal = KMP_NOW() + this_thr->th.th_team_bt_intervals;
525 while (flag->notdone_check()) {
526 kmp_task_team_t *task_team = NULL;
527 if (__kmp_tasking_mode != tskm_immediate_exec) {
528 task_team = this_thr->th.th_task_team;