Intel® OpenMP* Runtime Library
kmp_wait_release.h
1 /*
2  * kmp_wait_release.h -- Wait/Release implementation
3  */
4 
5 /* <copyright>
6  Copyright (c) 1997-2015 Intel Corporation. All Rights Reserved.
7 
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions
10  are met:
11 
12  * Redistributions of source code must retain the above copyright
13  notice, this list of conditions and the following disclaimer.
14  * Redistributions in binary form must reproduce the above copyright
15  notice, this list of conditions and the following disclaimer in the
16  documentation and/or other materials provided with the distribution.
17  * Neither the name of Intel Corporation nor the names of its
18  contributors may be used to endorse or promote products derived
19  from this software without specific prior written permission.
20 
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 </copyright> */
34 
35 #ifndef KMP_WAIT_RELEASE_H
36 #define KMP_WAIT_RELEASE_H
37 
38 #include "kmp.h"
39 #include "kmp_itt.h"
40 
57 enum flag_type {
61 };
62 
66 template <typename P>
67 class kmp_flag {
68  volatile P * loc;
70  public:
71  typedef P flag_t;
72  kmp_flag(volatile P *p, flag_type ft) : loc(p), t(ft) {}
76  volatile P * get() { return loc; }
80  void set(volatile P *new_loc) { loc = new_loc; }
84  flag_type get_type() { return t; }
85  // Derived classes must provide the following:
86  /*
87  kmp_info_t * get_waiter(kmp_uint32 i);
88  kmp_uint32 get_num_waiters();
89  bool done_check();
90  bool done_check_val(P old_loc);
91  bool notdone_check();
92  P internal_release();
93  void suspend(int th_gtid);
94  void resume(int th_gtid);
95  P set_sleeping();
96  P unset_sleeping();
97  bool is_sleeping();
98  bool is_any_sleeping();
99  bool is_sleeping_val(P old_loc);
100  int execute_tasks(kmp_info_t *this_thr, kmp_int32 gtid, int final_spin, int *thread_finished
101  USE_ITT_BUILD_ARG(void * itt_sync_obj), kmp_int32 is_constrained);
102  */
103 };
104 
105 /* Spin wait loop that first does pause, then yield, then sleep. A thread that calls __kmp_wait_*
106  must make certain that another thread calls __kmp_release to wake it back up to prevent deadlocks! */
107 template <class C>
108 static inline void __kmp_wait_template(kmp_info_t *this_thr, C *flag, int final_spin
109  USE_ITT_BUILD_ARG(void * itt_sync_obj) )
110 {
111  // NOTE: We may not belong to a team at this point.
112  volatile typename C::flag_t *spin = flag->get();
113  kmp_uint32 spins;
114  kmp_uint32 hibernate;
115  int th_gtid;
116  int tasks_completed = FALSE;
117 
118  KMP_FSYNC_SPIN_INIT(spin, NULL);
119  if (flag->done_check()) {
120  KMP_FSYNC_SPIN_ACQUIRED(spin);
121  return;
122  }
123  th_gtid = this_thr->th.th_info.ds.ds_gtid;
124  KA_TRACE(20, ("__kmp_wait_sleep: T#%d waiting for flag(%p)\n", th_gtid, flag));
125 
126 #if OMPT_SUPPORT && OMPT_BLAME
127  if (ompt_status == ompt_status_track_callback) {
128  if (this_thr->th.ompt_thread_info.state == ompt_state_idle){
129  if (ompt_callbacks.ompt_callback(ompt_event_idle_begin)) {
130  ompt_callbacks.ompt_callback(ompt_event_idle_begin)(th_gtid + 1);
131  }
132  } else if (ompt_callbacks.ompt_callback(ompt_event_wait_barrier_begin)) {
133  KMP_DEBUG_ASSERT(this_thr->th.ompt_thread_info.state == ompt_state_wait_barrier ||
134  this_thr->th.ompt_thread_info.state == ompt_state_wait_barrier_implicit ||
135  this_thr->th.ompt_thread_info.state == ompt_state_wait_barrier_explicit);
136 
137  ompt_lw_taskteam_t* team = this_thr->th.th_team->t.ompt_serialized_team_info;
138  ompt_parallel_id_t pId;
139  ompt_task_id_t tId;
140  if (team){
141  pId = team->ompt_team_info.parallel_id;
142  tId = team->ompt_task_info.task_id;
143  } else {
144  pId = this_thr->th.th_team->t.ompt_team_info.parallel_id;
145  tId = this_thr->th.th_current_task->ompt_task_info.task_id;
146  }
147  ompt_callbacks.ompt_callback(ompt_event_wait_barrier_begin)(pId, tId);
148  }
149  }
150 #endif
151 
152  // Setup for waiting
153  KMP_INIT_YIELD(spins);
154 
155  if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) {
156  // The worker threads cannot rely on the team struct existing at this point.
157  // Use the bt values cached in the thread struct instead.
158 #ifdef KMP_ADJUST_BLOCKTIME
159  if (__kmp_zero_bt && !this_thr->th.th_team_bt_set)
160  // Force immediate suspend if not set by user and more threads than available procs
161  hibernate = 0;
162  else
163  hibernate = this_thr->th.th_team_bt_intervals;
164 #else
165  hibernate = this_thr->th.th_team_bt_intervals;
166 #endif /* KMP_ADJUST_BLOCKTIME */
167 
168  /* If the blocktime is nonzero, we want to make sure that we spin wait for the entirety
169  of the specified #intervals, plus up to one interval more. This increment make
170  certain that this thread doesn't go to sleep too soon. */
171  if (hibernate != 0)
172  hibernate++;
173 
174  // Add in the current time value.
175  hibernate += TCR_4(__kmp_global.g.g_time.dt.t_value);
176  KF_TRACE(20, ("__kmp_wait_sleep: T#%d now=%d, hibernate=%d, intervals=%d\n",
177  th_gtid, __kmp_global.g.g_time.dt.t_value, hibernate,
178  hibernate - __kmp_global.g.g_time.dt.t_value));
179  }
180 
181  KMP_MB();
182 
183  // Main wait spin loop
184 
185  {
186  while (flag->notdone_check()) {
187  int in_pool;
188  /* If the task team is NULL, it means one of things:
189  1) A newly-created thread is first being released by __kmp_fork_barrier(), and
190  its task team has not been set up yet.
191  2) All tasks have been executed to completion, this thread has decremented the task
192  team's ref ct and possibly deallocated it, and should no longer reference it.
193  3) Tasking is off for this region. This could be because we are in a serialized region
194  (perhaps the outer one), or else tasking was manually disabled (KMP_TASKING=0). */
195  kmp_task_team_t * task_team = NULL;
196  if (__kmp_tasking_mode != tskm_immediate_exec) {
197  task_team = this_thr->th.th_task_team;
198  if (task_team != NULL) {
199  if (!TCR_SYNC_4(task_team->tt.tt_active)) {
200  KMP_DEBUG_ASSERT(!KMP_MASTER_TID(this_thr->th.th_info.ds.ds_tid));
201  __kmp_unref_task_team(task_team, this_thr);
202  } else if (KMP_TASKING_ENABLED(task_team)) {
203  flag->execute_tasks(this_thr, th_gtid, final_spin, &tasks_completed
204  USE_ITT_BUILD_ARG(itt_sync_obj), 0);
205  }
206  } // if
207  } // if
208 
209  KMP_FSYNC_SPIN_PREPARE(spin);
210  if (TCR_4(__kmp_global.g.g_done)) {
211  if (__kmp_global.g.g_abort)
212  __kmp_abort_thread();
213  break;
214  }
215 
216  // If we are oversubscribed, or have waited a bit (and KMP_LIBRARY=throughput), then yield
217  KMP_YIELD(TCR_4(__kmp_nth) > __kmp_avail_proc);
218  // TODO: Should it be number of cores instead of thread contexts? Like:
219  // KMP_YIELD(TCR_4(__kmp_nth) > __kmp_ncores);
220  // Need performance improvement data to make the change...
221  KMP_YIELD_SPIN(spins);
222 
223  // Check if this thread was transferred from a team
224  // to the thread pool (or vice-versa) while spinning.
225  in_pool = !!TCR_4(this_thr->th.th_in_pool);
226  if (in_pool != !!this_thr->th.th_active_in_pool) {
227  if (in_pool) { // Recently transferred from team to pool
228  KMP_TEST_THEN_INC32((kmp_int32 *)&__kmp_thread_pool_active_nth);
229  this_thr->th.th_active_in_pool = TRUE;
230  /* Here, we cannot assert that:
231  KMP_DEBUG_ASSERT(TCR_4(__kmp_thread_pool_active_nth) <= __kmp_thread_pool_nth);
232  __kmp_thread_pool_nth is inc/dec'd by the master thread while the fork/join
233  lock is held, whereas __kmp_thread_pool_active_nth is inc/dec'd asynchronously
234  by the workers. The two can get out of sync for brief periods of time. */
235  }
236  else { // Recently transferred from pool to team
237  KMP_TEST_THEN_DEC32((kmp_int32 *) &__kmp_thread_pool_active_nth);
238  KMP_DEBUG_ASSERT(TCR_4(__kmp_thread_pool_active_nth) >= 0);
239  this_thr->th.th_active_in_pool = FALSE;
240  }
241  }
242 
243  // Don't suspend if KMP_BLOCKTIME is set to "infinite"
244  if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME)
245  continue;
246 
247  // Don't suspend if there is a likelihood of new tasks being spawned.
248  if ((task_team != NULL) && TCR_4(task_team->tt.tt_found_tasks))
249  continue;
250 
251  // If we have waited a bit more, fall asleep
252  if (TCR_4(__kmp_global.g.g_time.dt.t_value) < hibernate)
253  continue;
254 
255  KF_TRACE(50, ("__kmp_wait_sleep: T#%d suspend time reached\n", th_gtid));
256  flag->suspend(th_gtid);
257 
258  if (TCR_4(__kmp_global.g.g_done)) {
259  if (__kmp_global.g.g_abort)
260  __kmp_abort_thread();
261  break;
262  }
263  // TODO: If thread is done with work and times out, disband/free
264  }
265  }
266 
267 #if OMPT_SUPPORT && OMPT_BLAME
268  if (ompt_status == ompt_status_track_callback) {
269  if (this_thr->th.ompt_thread_info.state == ompt_state_idle){
270  if (ompt_callbacks.ompt_callback(ompt_event_idle_end)) {
271  ompt_callbacks.ompt_callback(ompt_event_idle_end)(th_gtid + 1);
272  }
273  } else if (ompt_callbacks.ompt_callback(ompt_event_wait_barrier_end)) {
274  KMP_DEBUG_ASSERT(this_thr->th.ompt_thread_info.state == ompt_state_wait_barrier ||
275  this_thr->th.ompt_thread_info.state == ompt_state_wait_barrier_implicit ||
276  this_thr->th.ompt_thread_info.state == ompt_state_wait_barrier_explicit);
277 
278  ompt_lw_taskteam_t* team = this_thr->th.th_team->t.ompt_serialized_team_info;
279  ompt_parallel_id_t pId;
280  ompt_task_id_t tId;
281  if (team){
282  pId = team->ompt_team_info.parallel_id;
283  tId = team->ompt_task_info.task_id;
284  } else {
285  pId = this_thr->th.th_team->t.ompt_team_info.parallel_id;
286  tId = this_thr->th.th_current_task->ompt_task_info.task_id;
287  }
288  ompt_callbacks.ompt_callback(ompt_event_wait_barrier_end)(pId, tId);
289  }
290  }
291 #endif
292 
293  KMP_FSYNC_SPIN_ACQUIRED(spin);
294 }
295 
296 /* Release any threads specified as waiting on the flag by releasing the flag and resume the waiting thread
297  if indicated by the sleep bit(s). A thread that calls __kmp_wait_template must call this function to wake
298  up the potentially sleeping thread and prevent deadlocks! */
299 template <class C>
300 static inline void __kmp_release_template(C *flag)
301 {
302 #ifdef KMP_DEBUG
303  int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
304 #endif
305  KF_TRACE(20, ("__kmp_release: T#%d releasing flag(%x)\n", gtid, flag->get()));
306  KMP_DEBUG_ASSERT(flag->get());
307  KMP_FSYNC_RELEASING(flag->get());
308 
309  flag->internal_release();
310 
311  KF_TRACE(100, ("__kmp_release: T#%d set new spin=%d\n", gtid, flag->get(), *(flag->get())));
312 
313  if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) {
314  // Only need to check sleep stuff if infinite block time not set
315  if (flag->is_any_sleeping()) { // Are *any* of the threads that wait on this flag sleeping?
316  for (unsigned int i=0; i<flag->get_num_waiters(); ++i) {
317  kmp_info_t * waiter = flag->get_waiter(i); // if a sleeping waiter exists at i, sets current_waiter to i inside the flag
318  if (waiter) {
319  int wait_gtid = waiter->th.th_info.ds.ds_gtid;
320  // Wake up thread if needed
321  KF_TRACE(50, ("__kmp_release: T#%d waking up thread T#%d since sleep flag(%p) set\n",
322  gtid, wait_gtid, flag->get()));
323  flag->resume(wait_gtid); // unsets flag's current_waiter when done
324  }
325  }
326  }
327  }
328 }
329 
330 template <typename FlagType>
331 struct flag_traits {};
332 
333 template <>
334 struct flag_traits<kmp_uint32> {
335  typedef kmp_uint32 flag_t;
336  static const flag_type t = flag32;
337  static inline flag_t tcr(flag_t f) { return TCR_4(f); }
338  static inline flag_t test_then_add4(volatile flag_t *f) { return KMP_TEST_THEN_ADD4_32((volatile kmp_int32 *)f); }
339  static inline flag_t test_then_or(volatile flag_t *f, flag_t v) { return KMP_TEST_THEN_OR32((volatile kmp_int32 *)f, v); }
340  static inline flag_t test_then_and(volatile flag_t *f, flag_t v) { return KMP_TEST_THEN_AND32((volatile kmp_int32 *)f, v); }
341 };
342 
343 template <>
344 struct flag_traits<kmp_uint64> {
345  typedef kmp_uint64 flag_t;
346  static const flag_type t = flag64;
347  static inline flag_t tcr(flag_t f) { return TCR_8(f); }
348  static inline flag_t test_then_add4(volatile flag_t *f) { return KMP_TEST_THEN_ADD4_64((volatile kmp_int64 *)f); }
349  static inline flag_t test_then_or(volatile flag_t *f, flag_t v) { return KMP_TEST_THEN_OR64((volatile kmp_int64 *)f, v); }
350  static inline flag_t test_then_and(volatile flag_t *f, flag_t v) { return KMP_TEST_THEN_AND64((volatile kmp_int64 *)f, v); }
351 };
352 
353 template <typename FlagType>
354 class kmp_basic_flag : public kmp_flag<FlagType> {
355  typedef flag_traits<FlagType> traits_type;
356  FlagType checker;
357  kmp_info_t * waiting_threads[1];
358  kmp_uint32 num_waiting_threads;
359  public:
360  kmp_basic_flag(volatile FlagType *p) : kmp_flag<FlagType>(p, traits_type::t), num_waiting_threads(0) {}
361  kmp_basic_flag(volatile FlagType *p, kmp_info_t *thr) : kmp_flag<FlagType>(p, traits_type::t), num_waiting_threads(1) {
362  waiting_threads[0] = thr;
363  }
364  kmp_basic_flag(volatile FlagType *p, FlagType c) : kmp_flag<FlagType>(p, traits_type::t), checker(c), num_waiting_threads(0) {}
369  kmp_info_t * get_waiter(kmp_uint32 i) {
370  KMP_DEBUG_ASSERT(i<num_waiting_threads);
371  return waiting_threads[i];
372  }
376  kmp_uint32 get_num_waiters() { return num_waiting_threads; }
382  void set_waiter(kmp_info_t *thr) {
383  waiting_threads[0] = thr;
384  num_waiting_threads = 1;
385  }
389  bool done_check() { return traits_type::tcr(*(this->get())) == checker; }
394  bool done_check_val(FlagType old_loc) { return old_loc == checker; }
402  bool notdone_check() { return traits_type::tcr(*(this->get())) != checker; }
407  void internal_release() {
408  (void) traits_type::test_then_add4((volatile FlagType *)this->get());
409  }
414  FlagType set_sleeping() {
415  return traits_type::test_then_or((volatile FlagType *)this->get(), KMP_BARRIER_SLEEP_STATE);
416  }
421  FlagType unset_sleeping() {
422  return traits_type::test_then_and((volatile FlagType *)this->get(), ~KMP_BARRIER_SLEEP_STATE);
423  }
428  bool is_sleeping_val(FlagType old_loc) { return old_loc & KMP_BARRIER_SLEEP_STATE; }
432  bool is_sleeping() { return is_sleeping_val(*(this->get())); }
433  bool is_any_sleeping() { return is_sleeping_val(*(this->get())); }
434  kmp_uint8 *get_stolen() { return NULL; }
435  enum barrier_type get_bt() { return bs_last_barrier; }
436 };
437 
438 class kmp_flag_32 : public kmp_basic_flag<kmp_uint32> {
439  public:
440  kmp_flag_32(volatile kmp_uint32 *p) : kmp_basic_flag<kmp_uint32>(p) {}
441  kmp_flag_32(volatile kmp_uint32 *p, kmp_info_t *thr) : kmp_basic_flag<kmp_uint32>(p, thr) {}
442  kmp_flag_32(volatile kmp_uint32 *p, kmp_uint32 c) : kmp_basic_flag<kmp_uint32>(p, c) {}
443  void suspend(int th_gtid) { __kmp_suspend_32(th_gtid, this); }
444  void resume(int th_gtid) { __kmp_resume_32(th_gtid, this); }
445  int execute_tasks(kmp_info_t *this_thr, kmp_int32 gtid, int final_spin, int *thread_finished
446  USE_ITT_BUILD_ARG(void * itt_sync_obj), kmp_int32 is_constrained) {
447  return __kmp_execute_tasks_32(this_thr, gtid, this, final_spin, thread_finished
448  USE_ITT_BUILD_ARG(itt_sync_obj), is_constrained);
449  }
450  void wait(kmp_info_t *this_thr, int final_spin
451  USE_ITT_BUILD_ARG(void * itt_sync_obj)) {
452  __kmp_wait_template(this_thr, this, final_spin
453  USE_ITT_BUILD_ARG(itt_sync_obj));
454  }
455  void release() { __kmp_release_template(this); }
456 };
457 
458 class kmp_flag_64 : public kmp_basic_flag<kmp_uint64> {
459  public:
460  kmp_flag_64(volatile kmp_uint64 *p) : kmp_basic_flag<kmp_uint64>(p) {}
461  kmp_flag_64(volatile kmp_uint64 *p, kmp_info_t *thr) : kmp_basic_flag<kmp_uint64>(p, thr) {}
462  kmp_flag_64(volatile kmp_uint64 *p, kmp_uint64 c) : kmp_basic_flag<kmp_uint64>(p, c) {}
463  void suspend(int th_gtid) { __kmp_suspend_64(th_gtid, this); }
464  void resume(int th_gtid) { __kmp_resume_64(th_gtid, this); }
465  int execute_tasks(kmp_info_t *this_thr, kmp_int32 gtid, int final_spin, int *thread_finished
466  USE_ITT_BUILD_ARG(void * itt_sync_obj), kmp_int32 is_constrained) {
467  return __kmp_execute_tasks_64(this_thr, gtid, this, final_spin, thread_finished
468  USE_ITT_BUILD_ARG(itt_sync_obj), is_constrained);
469  }
470  void wait(kmp_info_t *this_thr, int final_spin
471  USE_ITT_BUILD_ARG(void * itt_sync_obj)) {
472  __kmp_wait_template(this_thr, this, final_spin
473  USE_ITT_BUILD_ARG(itt_sync_obj));
474  }
475  void release() { __kmp_release_template(this); }
476 };
477 
478 // Hierarchical 64-bit on-core barrier instantiation
479 class kmp_flag_oncore : public kmp_flag<kmp_uint64> {
480  kmp_uint64 checker;
481  kmp_info_t * waiting_threads[1];
482  kmp_uint32 num_waiting_threads;
483  kmp_uint32 offset;
484  bool flag_switch;
485  enum barrier_type bt;
486  kmp_info_t * this_thr;
487 #if USE_ITT_BUILD
488  void *itt_sync_obj;
489 #endif
490  unsigned char& byteref(volatile kmp_uint64* loc, size_t offset) { return ((unsigned char *)loc)[offset]; }
491 public:
492  kmp_flag_oncore(volatile kmp_uint64 *p)
493  : kmp_flag<kmp_uint64>(p, flag_oncore), num_waiting_threads(0), flag_switch(false) {}
494  kmp_flag_oncore(volatile kmp_uint64 *p, kmp_uint32 idx)
495  : kmp_flag<kmp_uint64>(p, flag_oncore), num_waiting_threads(0), offset(idx), flag_switch(false) {}
496  kmp_flag_oncore(volatile kmp_uint64 *p, kmp_uint64 c, kmp_uint32 idx, enum barrier_type bar_t,
497  kmp_info_t * thr
498 #if USE_ITT_BUILD
499  , void *itt
500 #endif
501  )
502  : kmp_flag<kmp_uint64>(p, flag_oncore), checker(c), num_waiting_threads(0), offset(idx),
503  flag_switch(false), bt(bar_t), this_thr(thr)
504 #if USE_ITT_BUILD
505  , itt_sync_obj(itt)
506 #endif
507  {}
508  kmp_info_t * get_waiter(kmp_uint32 i) {
509  KMP_DEBUG_ASSERT(i<num_waiting_threads);
510  return waiting_threads[i];
511  }
512  kmp_uint32 get_num_waiters() { return num_waiting_threads; }
513  void set_waiter(kmp_info_t *thr) {
514  waiting_threads[0] = thr;
515  num_waiting_threads = 1;
516  }
517  bool done_check_val(kmp_uint64 old_loc) { return byteref(&old_loc,offset) == checker; }
518  bool done_check() { return done_check_val(*get()); }
519  bool notdone_check() {
520  // Calculate flag_switch
521  if (this_thr->th.th_bar[bt].bb.wait_flag == KMP_BARRIER_SWITCH_TO_OWN_FLAG)
522  flag_switch = true;
523  if (byteref(get(),offset) != 1 && !flag_switch)
524  return true;
525  else if (flag_switch) {
526  this_thr->th.th_bar[bt].bb.wait_flag = KMP_BARRIER_SWITCHING;
527  kmp_flag_64 flag(&this_thr->th.th_bar[bt].bb.b_go, (kmp_uint64)KMP_BARRIER_STATE_BUMP);
528  __kmp_wait_64(this_thr, &flag, TRUE
529 #if USE_ITT_BUILD
530  , itt_sync_obj
531 #endif
532  );
533  }
534  return false;
535  }
536  void internal_release() {
537  if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME) {
538  byteref(get(),offset) = 1;
539  }
540  else {
541  kmp_uint64 mask=0;
542  byteref(&mask,offset) = 1;
543  (void) KMP_TEST_THEN_OR64((volatile kmp_int64 *)get(), mask);
544  }
545  }
546  kmp_uint64 set_sleeping() {
547  return KMP_TEST_THEN_OR64((kmp_int64 volatile *)get(), KMP_BARRIER_SLEEP_STATE);
548  }
549  kmp_uint64 unset_sleeping() {
550  return KMP_TEST_THEN_AND64((kmp_int64 volatile *)get(), ~KMP_BARRIER_SLEEP_STATE);
551  }
552  bool is_sleeping_val(kmp_uint64 old_loc) { return old_loc & KMP_BARRIER_SLEEP_STATE; }
553  bool is_sleeping() { return is_sleeping_val(*get()); }
554  bool is_any_sleeping() { return is_sleeping_val(*get()); }
555  void wait(kmp_info_t *this_thr, int final_spin) {
556  __kmp_wait_template<kmp_flag_oncore>(this_thr, this, final_spin
557  USE_ITT_BUILD_ARG(itt_sync_obj));
558  }
559  void release() { __kmp_release_template(this); }
560  void suspend(int th_gtid) { __kmp_suspend_oncore(th_gtid, this); }
561  void resume(int th_gtid) { __kmp_resume_oncore(th_gtid, this); }
562  int execute_tasks(kmp_info_t *this_thr, kmp_int32 gtid, int final_spin, int *thread_finished
563  USE_ITT_BUILD_ARG(void * itt_sync_obj), kmp_int32 is_constrained) {
564  return __kmp_execute_tasks_oncore(this_thr, gtid, this, final_spin, thread_finished
565  USE_ITT_BUILD_ARG(itt_sync_obj), is_constrained);
566  }
567  kmp_uint8 *get_stolen() { return NULL; }
568  enum barrier_type get_bt() { return bt; }
569 };
570 
571 
576 #endif // KMP_WAIT_RELEASE_H
void set(volatile P *new_loc)
volatile P * loc
flag_type get_type()
flag_type
flag_type t