17cc577a4SJonathan Peyton /*
2de4749b7SJonathan Peyton  * kmp_csupport.cpp -- kfront linkage support for OpenMP.
37cc577a4SJonathan Peyton  */
47cc577a4SJonathan Peyton 
57cc577a4SJonathan Peyton //===----------------------------------------------------------------------===//
67cc577a4SJonathan Peyton //
757b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
857b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
957b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
107cc577a4SJonathan Peyton //
117cc577a4SJonathan Peyton //===----------------------------------------------------------------------===//
127cc577a4SJonathan Peyton 
1392ca6188SJonathan Peyton #define __KMP_IMP
147cc577a4SJonathan Peyton #include "omp.h" /* extern "C" declarations of user-visible routines */
157cc577a4SJonathan Peyton #include "kmp.h"
163041982dSJonathan Peyton #include "kmp_error.h"
177cc577a4SJonathan Peyton #include "kmp_i18n.h"
187cc577a4SJonathan Peyton #include "kmp_itt.h"
197cc577a4SJonathan Peyton #include "kmp_lock.h"
207cc577a4SJonathan Peyton #include "kmp_stats.h"
217cc577a4SJonathan Peyton #include "ompt-specific.h"
227cc577a4SJonathan Peyton 
237cc577a4SJonathan Peyton #define MAX_MESSAGE 512
247cc577a4SJonathan Peyton 
253041982dSJonathan Peyton // flags will be used in future, e.g. to implement openmp_strict library
263041982dSJonathan Peyton // restrictions
277cc577a4SJonathan Peyton 
287cc577a4SJonathan Peyton /*!
297cc577a4SJonathan Peyton  * @ingroup STARTUP_SHUTDOWN
307cc577a4SJonathan Peyton  * @param loc   in   source location information
317cc577a4SJonathan Peyton  * @param flags in   for future use (currently ignored)
327cc577a4SJonathan Peyton  *
337cc577a4SJonathan Peyton  * Initialize the runtime library. This call is optional; if it is not made then
347cc577a4SJonathan Peyton  * it will be implicitly called by attempts to use other library functions.
357cc577a4SJonathan Peyton  */
__kmpc_begin(ident_t * loc,kmp_int32 flags)363041982dSJonathan Peyton void __kmpc_begin(ident_t *loc, kmp_int32 flags) {
37ad3f6398SAndrey Churbanov   // By default __kmpc_begin() is no-op.
38ad3f6398SAndrey Churbanov   char *env;
39ad3f6398SAndrey Churbanov   if ((env = getenv("KMP_INITIAL_THREAD_BIND")) != NULL &&
40ad3f6398SAndrey Churbanov       __kmp_str_match_true(env)) {
41ad3f6398SAndrey Churbanov     __kmp_middle_initialize();
420ddde4d8SPeyton, Jonathan L     __kmp_assign_root_init_mask();
43ad3f6398SAndrey Churbanov     KC_TRACE(10, ("__kmpc_begin: middle initialization called\n"));
44ad3f6398SAndrey Churbanov   } else if (__kmp_ignore_mppbeg() == FALSE) {
457cc577a4SJonathan Peyton     // By default __kmp_ignore_mppbeg() returns TRUE.
467cc577a4SJonathan Peyton     __kmp_internal_begin();
477cc577a4SJonathan Peyton     KC_TRACE(10, ("__kmpc_begin: called\n"));
487cc577a4SJonathan Peyton   }
497cc577a4SJonathan Peyton }
507cc577a4SJonathan Peyton 
517cc577a4SJonathan Peyton /*!
527cc577a4SJonathan Peyton  * @ingroup STARTUP_SHUTDOWN
537cc577a4SJonathan Peyton  * @param loc source location information
547cc577a4SJonathan Peyton  *
553041982dSJonathan Peyton  * Shutdown the runtime library. This is also optional, and even if called will
563041982dSJonathan Peyton  * not do anything unless the `KMP_IGNORE_MPPEND` environment variable is set to
573041982dSJonathan Peyton  * zero.
587cc577a4SJonathan Peyton  */
__kmpc_end(ident_t * loc)593041982dSJonathan Peyton void __kmpc_end(ident_t *loc) {
603041982dSJonathan Peyton   // By default, __kmp_ignore_mppend() returns TRUE which makes __kmpc_end()
613041982dSJonathan Peyton   // call no-op. However, this can be overridden with KMP_IGNORE_MPPEND
623041982dSJonathan Peyton   // environment variable. If KMP_IGNORE_MPPEND is 0, __kmp_ignore_mppend()
633041982dSJonathan Peyton   // returns FALSE and __kmpc_end() will unregister this root (it can cause
643041982dSJonathan Peyton   // library shut down).
657cc577a4SJonathan Peyton   if (__kmp_ignore_mppend() == FALSE) {
667cc577a4SJonathan Peyton     KC_TRACE(10, ("__kmpc_end: called\n"));
677cc577a4SJonathan Peyton     KA_TRACE(30, ("__kmpc_end\n"));
687cc577a4SJonathan Peyton 
697cc577a4SJonathan Peyton     __kmp_internal_end_thread(-1);
707cc577a4SJonathan Peyton   }
718bb8a92dSJonathan Peyton #if KMP_OS_WINDOWS && OMPT_SUPPORT
728bb8a92dSJonathan Peyton   // Normal exit process on Windows does not allow worker threads of the final
738bb8a92dSJonathan Peyton   // parallel region to finish reporting their events, so shutting down the
748bb8a92dSJonathan Peyton   // library here fixes the issue at least for the cases where __kmpc_end() is
758bb8a92dSJonathan Peyton   // placed properly.
768bb8a92dSJonathan Peyton   if (ompt_enabled.enabled)
778bb8a92dSJonathan Peyton     __kmp_internal_end_library(__kmp_gtid_get_specific());
788bb8a92dSJonathan Peyton #endif
797cc577a4SJonathan Peyton }
807cc577a4SJonathan Peyton 
817cc577a4SJonathan Peyton /*!
827cc577a4SJonathan Peyton @ingroup THREAD_STATES
837cc577a4SJonathan Peyton @param loc Source location information.
847cc577a4SJonathan Peyton @return The global thread index of the active thread.
857cc577a4SJonathan Peyton 
867cc577a4SJonathan Peyton This function can be called in any context.
877cc577a4SJonathan Peyton 
887cc577a4SJonathan Peyton If the runtime has ony been entered at the outermost level from a
893041982dSJonathan Peyton single (necessarily non-OpenMP<sup>*</sup>) thread, then the thread number is
903041982dSJonathan Peyton that which would be returned by omp_get_thread_num() in the outermost
917cc577a4SJonathan Peyton active parallel construct. (Or zero if there is no active parallel
9297d000cfStlwilmar construct, since the primary thread is necessarily thread zero).
937cc577a4SJonathan Peyton 
947cc577a4SJonathan Peyton If multiple non-OpenMP threads all enter an OpenMP construct then this
957cc577a4SJonathan Peyton will be a unique thread identifier among all the threads created by
9642016791SKazuaki Ishizaki the OpenMP runtime (but the value cannot be defined in terms of
977cc577a4SJonathan Peyton OpenMP thread ids returned by omp_get_thread_num()).
987cc577a4SJonathan Peyton */
__kmpc_global_thread_num(ident_t * loc)993041982dSJonathan Peyton kmp_int32 __kmpc_global_thread_num(ident_t *loc) {
1007cc577a4SJonathan Peyton   kmp_int32 gtid = __kmp_entry_gtid();
1017cc577a4SJonathan Peyton 
1027cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_global_thread_num: T#%d\n", gtid));
1037cc577a4SJonathan Peyton 
1047cc577a4SJonathan Peyton   return gtid;
1057cc577a4SJonathan Peyton }
1067cc577a4SJonathan Peyton 
1077cc577a4SJonathan Peyton /*!
1087cc577a4SJonathan Peyton @ingroup THREAD_STATES
1097cc577a4SJonathan Peyton @param loc Source location information.
1107cc577a4SJonathan Peyton @return The number of threads under control of the OpenMP<sup>*</sup> runtime
1117cc577a4SJonathan Peyton 
1127cc577a4SJonathan Peyton This function can be called in any context.
1133041982dSJonathan Peyton It returns the total number of threads under the control of the OpenMP runtime.
1143041982dSJonathan Peyton That is not a number that can be determined by any OpenMP standard calls, since
1153041982dSJonathan Peyton the library may be called from more than one non-OpenMP thread, and this
1163041982dSJonathan Peyton reflects the total over all such calls. Similarly the runtime maintains
1173041982dSJonathan Peyton underlying threads even when they are not active (since the cost of creating
1183041982dSJonathan Peyton and destroying OS threads is high), this call counts all such threads even if
1193041982dSJonathan Peyton they are not waiting for work.
1207cc577a4SJonathan Peyton */
__kmpc_global_num_threads(ident_t * loc)1213041982dSJonathan Peyton kmp_int32 __kmpc_global_num_threads(ident_t *loc) {
1223041982dSJonathan Peyton   KC_TRACE(10,
1233041982dSJonathan Peyton            ("__kmpc_global_num_threads: num_threads = %d\n", __kmp_all_nth));
1247cc577a4SJonathan Peyton 
12576d42854SAndrey Churbanov   return TCR_4(__kmp_all_nth);
1267cc577a4SJonathan Peyton }
1277cc577a4SJonathan Peyton 
1287cc577a4SJonathan Peyton /*!
1297cc577a4SJonathan Peyton @ingroup THREAD_STATES
1307cc577a4SJonathan Peyton @param loc Source location information.
1313041982dSJonathan Peyton @return The thread number of the calling thread in the innermost active parallel
1323041982dSJonathan Peyton construct.
1337cc577a4SJonathan Peyton */
__kmpc_bound_thread_num(ident_t * loc)1343041982dSJonathan Peyton kmp_int32 __kmpc_bound_thread_num(ident_t *loc) {
1357cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_bound_thread_num: called\n"));
1367cc577a4SJonathan Peyton   return __kmp_tid_from_gtid(__kmp_entry_gtid());
1377cc577a4SJonathan Peyton }
1387cc577a4SJonathan Peyton 
1397cc577a4SJonathan Peyton /*!
1407cc577a4SJonathan Peyton @ingroup THREAD_STATES
1417cc577a4SJonathan Peyton @param loc Source location information.
1427cc577a4SJonathan Peyton @return The number of threads in the innermost active parallel construct.
1437cc577a4SJonathan Peyton */
__kmpc_bound_num_threads(ident_t * loc)1443041982dSJonathan Peyton kmp_int32 __kmpc_bound_num_threads(ident_t *loc) {
1457cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_bound_num_threads: called\n"));
1467cc577a4SJonathan Peyton 
1477cc577a4SJonathan Peyton   return __kmp_entry_thread()->th.th_team->t.t_nproc;
1487cc577a4SJonathan Peyton }
1497cc577a4SJonathan Peyton 
1507cc577a4SJonathan Peyton /*!
1517cc577a4SJonathan Peyton  * @ingroup DEPRECATED
1527cc577a4SJonathan Peyton  * @param loc location description
1537cc577a4SJonathan Peyton  *
1547cc577a4SJonathan Peyton  * This function need not be called. It always returns TRUE.
1557cc577a4SJonathan Peyton  */
__kmpc_ok_to_fork(ident_t * loc)1563041982dSJonathan Peyton kmp_int32 __kmpc_ok_to_fork(ident_t *loc) {
1577cc577a4SJonathan Peyton #ifndef KMP_DEBUG
1587cc577a4SJonathan Peyton 
1597cc577a4SJonathan Peyton   return TRUE;
1607cc577a4SJonathan Peyton 
1617cc577a4SJonathan Peyton #else
1627cc577a4SJonathan Peyton 
1637cc577a4SJonathan Peyton   const char *semi2;
1647cc577a4SJonathan Peyton   const char *semi3;
1657cc577a4SJonathan Peyton   int line_no;
1667cc577a4SJonathan Peyton 
1677cc577a4SJonathan Peyton   if (__kmp_par_range == 0) {
1687cc577a4SJonathan Peyton     return TRUE;
1697cc577a4SJonathan Peyton   }
1707cc577a4SJonathan Peyton   semi2 = loc->psource;
1717cc577a4SJonathan Peyton   if (semi2 == NULL) {
1727cc577a4SJonathan Peyton     return TRUE;
1737cc577a4SJonathan Peyton   }
1747cc577a4SJonathan Peyton   semi2 = strchr(semi2, ';');
1757cc577a4SJonathan Peyton   if (semi2 == NULL) {
1767cc577a4SJonathan Peyton     return TRUE;
1777cc577a4SJonathan Peyton   }
1787cc577a4SJonathan Peyton   semi2 = strchr(semi2 + 1, ';');
1797cc577a4SJonathan Peyton   if (semi2 == NULL) {
1807cc577a4SJonathan Peyton     return TRUE;
1817cc577a4SJonathan Peyton   }
1827cc577a4SJonathan Peyton   if (__kmp_par_range_filename[0]) {
1837cc577a4SJonathan Peyton     const char *name = semi2 - 1;
1847cc577a4SJonathan Peyton     while ((name > loc->psource) && (*name != '/') && (*name != ';')) {
1857cc577a4SJonathan Peyton       name--;
1867cc577a4SJonathan Peyton     }
1877cc577a4SJonathan Peyton     if ((*name == '/') || (*name == ';')) {
1887cc577a4SJonathan Peyton       name++;
1897cc577a4SJonathan Peyton     }
1907cc577a4SJonathan Peyton     if (strncmp(__kmp_par_range_filename, name, semi2 - name)) {
1917cc577a4SJonathan Peyton       return __kmp_par_range < 0;
1927cc577a4SJonathan Peyton     }
1937cc577a4SJonathan Peyton   }
1947cc577a4SJonathan Peyton   semi3 = strchr(semi2 + 1, ';');
1957cc577a4SJonathan Peyton   if (__kmp_par_range_routine[0]) {
1963041982dSJonathan Peyton     if ((semi3 != NULL) && (semi3 > semi2) &&
1973041982dSJonathan Peyton         (strncmp(__kmp_par_range_routine, semi2 + 1, semi3 - semi2 - 1))) {
1987cc577a4SJonathan Peyton       return __kmp_par_range < 0;
1997cc577a4SJonathan Peyton     }
2007cc577a4SJonathan Peyton   }
2017cc577a4SJonathan Peyton   if (KMP_SSCANF(semi3 + 1, "%d", &line_no) == 1) {
2027cc577a4SJonathan Peyton     if ((line_no >= __kmp_par_range_lb) && (line_no <= __kmp_par_range_ub)) {
2037cc577a4SJonathan Peyton       return __kmp_par_range > 0;
2047cc577a4SJonathan Peyton     }
2057cc577a4SJonathan Peyton     return __kmp_par_range < 0;
2067cc577a4SJonathan Peyton   }
2077cc577a4SJonathan Peyton   return TRUE;
2087cc577a4SJonathan Peyton 
2097cc577a4SJonathan Peyton #endif /* KMP_DEBUG */
2107cc577a4SJonathan Peyton }
2117cc577a4SJonathan Peyton 
2127cc577a4SJonathan Peyton /*!
2137cc577a4SJonathan Peyton @ingroup THREAD_STATES
2147cc577a4SJonathan Peyton @param loc Source location information.
2153041982dSJonathan Peyton @return 1 if this thread is executing inside an active parallel region, zero if
2163041982dSJonathan Peyton not.
2177cc577a4SJonathan Peyton */
__kmpc_in_parallel(ident_t * loc)2183041982dSJonathan Peyton kmp_int32 __kmpc_in_parallel(ident_t *loc) {
2197cc577a4SJonathan Peyton   return __kmp_entry_thread()->th.th_root->r.r_active;
2207cc577a4SJonathan Peyton }
2217cc577a4SJonathan Peyton 
2227cc577a4SJonathan Peyton /*!
2237cc577a4SJonathan Peyton @ingroup PARALLEL
2247cc577a4SJonathan Peyton @param loc source location information
2257cc577a4SJonathan Peyton @param global_tid global thread number
2267cc577a4SJonathan Peyton @param num_threads number of threads requested for this parallel construct
2277cc577a4SJonathan Peyton 
2287cc577a4SJonathan Peyton Set the number of threads to be used by the next fork spawned by this thread.
2297cc577a4SJonathan Peyton This call is only required if the parallel construct has a `num_threads` clause.
2307cc577a4SJonathan Peyton */
__kmpc_push_num_threads(ident_t * loc,kmp_int32 global_tid,kmp_int32 num_threads)2313041982dSJonathan Peyton void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
2323041982dSJonathan Peyton                              kmp_int32 num_threads) {
2337cc577a4SJonathan Peyton   KA_TRACE(20, ("__kmpc_push_num_threads: enter T#%d num_threads=%d\n",
2347cc577a4SJonathan Peyton                 global_tid, num_threads));
235787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
2367cc577a4SJonathan Peyton   __kmp_push_num_threads(loc, global_tid, num_threads);
2377cc577a4SJonathan Peyton }
2387cc577a4SJonathan Peyton 
__kmpc_pop_num_threads(ident_t * loc,kmp_int32 global_tid)2393041982dSJonathan Peyton void __kmpc_pop_num_threads(ident_t *loc, kmp_int32 global_tid) {
2407cc577a4SJonathan Peyton   KA_TRACE(20, ("__kmpc_pop_num_threads: enter\n"));
2417cc577a4SJonathan Peyton   /* the num_threads are automatically popped */
2427cc577a4SJonathan Peyton }
2437cc577a4SJonathan Peyton 
__kmpc_push_proc_bind(ident_t * loc,kmp_int32 global_tid,kmp_int32 proc_bind)2443041982dSJonathan Peyton void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
2453041982dSJonathan Peyton                            kmp_int32 proc_bind) {
2463041982dSJonathan Peyton   KA_TRACE(20, ("__kmpc_push_proc_bind: enter T#%d proc_bind=%d\n", global_tid,
2473041982dSJonathan Peyton                 proc_bind));
248787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
2497cc577a4SJonathan Peyton   __kmp_push_proc_bind(loc, global_tid, (kmp_proc_bind_t)proc_bind);
2507cc577a4SJonathan Peyton }
2517cc577a4SJonathan Peyton 
2527cc577a4SJonathan Peyton /*!
2537cc577a4SJonathan Peyton @ingroup PARALLEL
2547cc577a4SJonathan Peyton @param loc  source location information
2557cc577a4SJonathan Peyton @param argc  total number of arguments in the ellipsis
2563041982dSJonathan Peyton @param microtask  pointer to callback routine consisting of outlined parallel
2573041982dSJonathan Peyton construct
2587cc577a4SJonathan Peyton @param ...  pointers to shared variables that aren't global
2597cc577a4SJonathan Peyton 
2607cc577a4SJonathan Peyton Do the actual fork and call the microtask in the relevant number of threads.
2617cc577a4SJonathan Peyton */
__kmpc_fork_call(ident_t * loc,kmp_int32 argc,kmpc_micro microtask,...)2623041982dSJonathan Peyton void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro microtask, ...) {
2637cc577a4SJonathan Peyton   int gtid = __kmp_entry_gtid();
2647cc577a4SJonathan Peyton 
2657cc577a4SJonathan Peyton #if (KMP_STATS_ENABLED)
266f0682ac4SJonathan Peyton   // If we were in a serial region, then stop the serial timer, record
267f0682ac4SJonathan Peyton   // the event, and start parallel region timer
268f0682ac4SJonathan Peyton   stats_state_e previous_state = KMP_GET_THREAD_STATE();
269f0682ac4SJonathan Peyton   if (previous_state == stats_state_e::SERIAL_REGION) {
270f0682ac4SJonathan Peyton     KMP_EXCHANGE_PARTITIONED_TIMER(OMP_parallel_overhead);
271f0682ac4SJonathan Peyton   } else {
272f0682ac4SJonathan Peyton     KMP_PUSH_PARTITIONED_TIMER(OMP_parallel_overhead);
273f0682ac4SJonathan Peyton   }
2747cc577a4SJonathan Peyton   int inParallel = __kmpc_in_parallel(loc);
2753041982dSJonathan Peyton   if (inParallel) {
2767cc577a4SJonathan Peyton     KMP_COUNT_BLOCK(OMP_NESTED_PARALLEL);
2773041982dSJonathan Peyton   } else {
2787cc577a4SJonathan Peyton     KMP_COUNT_BLOCK(OMP_PARALLEL);
2797cc577a4SJonathan Peyton   }
2807cc577a4SJonathan Peyton #endif
2817cc577a4SJonathan Peyton 
2827cc577a4SJonathan Peyton   // maybe to save thr_state is enough here
2837cc577a4SJonathan Peyton   {
2847cc577a4SJonathan Peyton     va_list ap;
2857cc577a4SJonathan Peyton     va_start(ap, microtask);
2867cc577a4SJonathan Peyton 
2877cc577a4SJonathan Peyton #if OMPT_SUPPORT
2880e0d6cddSJoachim Protze     ompt_frame_t *ompt_frame;
28982e94a59SJoachim Protze     if (ompt_enabled.enabled) {
2907cc577a4SJonathan Peyton       kmp_info_t *master_th = __kmp_threads[gtid];
291f2410bfbSVladimir Inđić       ompt_frame = &master_th->th.th_current_task->ompt_task_info.frame;
2920e0d6cddSJoachim Protze       ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
2937cc577a4SJonathan Peyton     }
2946d3b8166SJoachim Protze     OMPT_STORE_RETURN_ADDRESS(gtid);
2957cc577a4SJonathan Peyton #endif
2967cc577a4SJonathan Peyton 
2977cc577a4SJonathan Peyton #if INCLUDE_SSC_MARKS
2987cc577a4SJonathan Peyton     SSC_MARK_FORKING();
2997cc577a4SJonathan Peyton #endif
3003041982dSJonathan Peyton     __kmp_fork_call(loc, gtid, fork_context_intel, argc,
3017cc577a4SJonathan Peyton                     VOLATILE_CAST(microtask_t) microtask, // "wrapped" task
3027cc577a4SJonathan Peyton                     VOLATILE_CAST(launch_t) __kmp_invoke_task_func,
303cde8f4c1SDimitry Andric                     kmp_va_addr_of(ap));
3047cc577a4SJonathan Peyton #if INCLUDE_SSC_MARKS
3057cc577a4SJonathan Peyton     SSC_MARK_JOINING();
3067cc577a4SJonathan Peyton #endif
3077cc577a4SJonathan Peyton     __kmp_join_call(loc, gtid
3087cc577a4SJonathan Peyton #if OMPT_SUPPORT
3093041982dSJonathan Peyton                     ,
3103041982dSJonathan Peyton                     fork_context_intel
3117cc577a4SJonathan Peyton #endif
3127cc577a4SJonathan Peyton     );
3137cc577a4SJonathan Peyton 
3147cc577a4SJonathan Peyton     va_end(ap);
315f2410bfbSVladimir Inđić 
316f2410bfbSVladimir Inđić #if OMPT_SUPPORT
317f2410bfbSVladimir Inđić     if (ompt_enabled.enabled) {
318f2410bfbSVladimir Inđić       ompt_frame->enter_frame = ompt_data_none;
319f2410bfbSVladimir Inđić     }
320f2410bfbSVladimir Inđić #endif
3217cc577a4SJonathan Peyton   }
322f0682ac4SJonathan Peyton 
323f0682ac4SJonathan Peyton #if KMP_STATS_ENABLED
324f0682ac4SJonathan Peyton   if (previous_state == stats_state_e::SERIAL_REGION) {
325f0682ac4SJonathan Peyton     KMP_EXCHANGE_PARTITIONED_TIMER(OMP_serial);
3260454154eSPeyton, Jonathan L     KMP_SET_THREAD_STATE(previous_state);
327f0682ac4SJonathan Peyton   } else {
328f0682ac4SJonathan Peyton     KMP_POP_PARTITIONED_TIMER();
329f0682ac4SJonathan Peyton   }
330f0682ac4SJonathan Peyton #endif // KMP_STATS_ENABLED
3317cc577a4SJonathan Peyton }
3327cc577a4SJonathan Peyton 
3337cc577a4SJonathan Peyton /*!
3347cc577a4SJonathan Peyton @ingroup PARALLEL
3357cc577a4SJonathan Peyton @param loc source location information
3367cc577a4SJonathan Peyton @param global_tid global thread number
3377cc577a4SJonathan Peyton @param num_teams number of teams requested for the teams construct
3387cc577a4SJonathan Peyton @param num_threads number of threads per team requested for the teams construct
3397cc577a4SJonathan Peyton 
3407cc577a4SJonathan Peyton Set the number of teams to be used by the teams construct.
3417cc577a4SJonathan Peyton This call is only required if the teams construct has a `num_teams` clause
3427cc577a4SJonathan Peyton or a `thread_limit` clause (or both).
3437cc577a4SJonathan Peyton */
__kmpc_push_num_teams(ident_t * loc,kmp_int32 global_tid,kmp_int32 num_teams,kmp_int32 num_threads)3443041982dSJonathan Peyton void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
3453041982dSJonathan Peyton                            kmp_int32 num_teams, kmp_int32 num_threads) {
3463041982dSJonathan Peyton   KA_TRACE(20,
3473041982dSJonathan Peyton            ("__kmpc_push_num_teams: enter T#%d num_teams=%d num_threads=%d\n",
3487cc577a4SJonathan Peyton             global_tid, num_teams, num_threads));
349787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
3507cc577a4SJonathan Peyton   __kmp_push_num_teams(loc, global_tid, num_teams, num_threads);
3517cc577a4SJonathan Peyton }
3527cc577a4SJonathan Peyton 
3537cc577a4SJonathan Peyton /*!
3547cc577a4SJonathan Peyton @ingroup PARALLEL
3557cc577a4SJonathan Peyton @param loc source location information
3564692bb4aSNawrin Sultana @param global_tid global thread number
357747a4906SJonathan Peyton @param num_teams_lb lower bound on number of teams requested for the teams
3584692bb4aSNawrin Sultana construct
359747a4906SJonathan Peyton @param num_teams_ub upper bound on number of teams requested for the teams
3604692bb4aSNawrin Sultana construct
3614692bb4aSNawrin Sultana @param num_threads number of threads per team requested for the teams construct
3624692bb4aSNawrin Sultana 
3634692bb4aSNawrin Sultana Set the number of teams to be used by the teams construct. The number of initial
3644692bb4aSNawrin Sultana teams cretaed will be greater than or equal to the lower bound and less than or
3654692bb4aSNawrin Sultana equal to the upper bound.
3664692bb4aSNawrin Sultana This call is only required if the teams construct has a `num_teams` clause
3674692bb4aSNawrin Sultana or a `thread_limit` clause (or both).
3684692bb4aSNawrin Sultana */
__kmpc_push_num_teams_51(ident_t * loc,kmp_int32 global_tid,kmp_int32 num_teams_lb,kmp_int32 num_teams_ub,kmp_int32 num_threads)3694692bb4aSNawrin Sultana void __kmpc_push_num_teams_51(ident_t *loc, kmp_int32 global_tid,
3704692bb4aSNawrin Sultana                               kmp_int32 num_teams_lb, kmp_int32 num_teams_ub,
3714692bb4aSNawrin Sultana                               kmp_int32 num_threads) {
3724692bb4aSNawrin Sultana   KA_TRACE(20, ("__kmpc_push_num_teams_51: enter T#%d num_teams_lb=%d"
3734692bb4aSNawrin Sultana                 " num_teams_ub=%d num_threads=%d\n",
3744692bb4aSNawrin Sultana                 global_tid, num_teams_lb, num_teams_ub, num_threads));
3754692bb4aSNawrin Sultana   __kmp_assert_valid_gtid(global_tid);
3764692bb4aSNawrin Sultana   __kmp_push_num_teams_51(loc, global_tid, num_teams_lb, num_teams_ub,
3774692bb4aSNawrin Sultana                           num_threads);
3784692bb4aSNawrin Sultana }
3794692bb4aSNawrin Sultana 
3804692bb4aSNawrin Sultana /*!
3814692bb4aSNawrin Sultana @ingroup PARALLEL
3824692bb4aSNawrin Sultana @param loc  source location information
3837cc577a4SJonathan Peyton @param argc  total number of arguments in the ellipsis
3843041982dSJonathan Peyton @param microtask  pointer to callback routine consisting of outlined teams
3853041982dSJonathan Peyton construct
3867cc577a4SJonathan Peyton @param ...  pointers to shared variables that aren't global
3877cc577a4SJonathan Peyton 
3887cc577a4SJonathan Peyton Do the actual fork and call the microtask in the relevant number of threads.
3897cc577a4SJonathan Peyton */
__kmpc_fork_teams(ident_t * loc,kmp_int32 argc,kmpc_micro microtask,...)3903041982dSJonathan Peyton void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro microtask,
3913041982dSJonathan Peyton                        ...) {
3927cc577a4SJonathan Peyton   int gtid = __kmp_entry_gtid();
3937cc577a4SJonathan Peyton   kmp_info_t *this_thr = __kmp_threads[gtid];
3947cc577a4SJonathan Peyton   va_list ap;
3957cc577a4SJonathan Peyton   va_start(ap, microtask);
3967cc577a4SJonathan Peyton 
397d2b53cadSJonathan Peyton #if KMP_STATS_ENABLED
3987cc577a4SJonathan Peyton   KMP_COUNT_BLOCK(OMP_TEAMS);
399d2b53cadSJonathan Peyton   stats_state_e previous_state = KMP_GET_THREAD_STATE();
400d2b53cadSJonathan Peyton   if (previous_state == stats_state_e::SERIAL_REGION) {
401d2b53cadSJonathan Peyton     KMP_EXCHANGE_PARTITIONED_TIMER(OMP_teams_overhead);
402d2b53cadSJonathan Peyton   } else {
403d2b53cadSJonathan Peyton     KMP_PUSH_PARTITIONED_TIMER(OMP_teams_overhead);
404d2b53cadSJonathan Peyton   }
405d2b53cadSJonathan Peyton #endif
4067cc577a4SJonathan Peyton 
4077cc577a4SJonathan Peyton   // remember teams entry point and nesting level
4087cc577a4SJonathan Peyton   this_thr->th.th_teams_microtask = microtask;
4093041982dSJonathan Peyton   this_thr->th.th_teams_level =
4103041982dSJonathan Peyton       this_thr->th.th_team->t.t_level; // AC: can be >0 on host
4117cc577a4SJonathan Peyton 
4127cc577a4SJonathan Peyton #if OMPT_SUPPORT
4137cc577a4SJonathan Peyton   kmp_team_t *parent_team = this_thr->th.th_team;
4147cc577a4SJonathan Peyton   int tid = __kmp_tid_from_gtid(gtid);
41582e94a59SJoachim Protze   if (ompt_enabled.enabled) {
4163041982dSJonathan Peyton     parent_team->t.t_implicit_task_taskdata[tid]
4170e0d6cddSJoachim Protze         .ompt_task_info.frame.enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
4187cc577a4SJonathan Peyton   }
41982e94a59SJoachim Protze   OMPT_STORE_RETURN_ADDRESS(gtid);
4207cc577a4SJonathan Peyton #endif
4217cc577a4SJonathan Peyton 
4223041982dSJonathan Peyton   // check if __kmpc_push_num_teams called, set default number of teams
4233041982dSJonathan Peyton   // otherwise
4247cc577a4SJonathan Peyton   if (this_thr->th.th_teams_size.nteams == 0) {
4257cc577a4SJonathan Peyton     __kmp_push_num_teams(loc, gtid, 0, 0);
4267cc577a4SJonathan Peyton   }
4277cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(this_thr->th.th_set_nproc >= 1);
4287cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(this_thr->th.th_teams_size.nteams >= 1);
4297cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(this_thr->th.th_teams_size.nth >= 1);
4307cc577a4SJonathan Peyton 
431cde8f4c1SDimitry Andric   __kmp_fork_call(
432cde8f4c1SDimitry Andric       loc, gtid, fork_context_intel, argc,
433cde8f4c1SDimitry Andric       VOLATILE_CAST(microtask_t) __kmp_teams_master, // "wrapped" task
434cde8f4c1SDimitry Andric       VOLATILE_CAST(launch_t) __kmp_invoke_teams_master, kmp_va_addr_of(ap));
4357cc577a4SJonathan Peyton   __kmp_join_call(loc, gtid
4367cc577a4SJonathan Peyton #if OMPT_SUPPORT
4373041982dSJonathan Peyton                   ,
4383041982dSJonathan Peyton                   fork_context_intel
4397cc577a4SJonathan Peyton #endif
4407cc577a4SJonathan Peyton   );
4417cc577a4SJonathan Peyton 
44265ebfeecSJonathan Peyton   // Pop current CG root off list
44365ebfeecSJonathan Peyton   KMP_DEBUG_ASSERT(this_thr->th.th_cg_roots);
44465ebfeecSJonathan Peyton   kmp_cg_root_t *tmp = this_thr->th.th_cg_roots;
44565ebfeecSJonathan Peyton   this_thr->th.th_cg_roots = tmp->up;
44665ebfeecSJonathan Peyton   KA_TRACE(100, ("__kmpc_fork_teams: Thread %p popping node %p and moving up"
44765ebfeecSJonathan Peyton                  " to node %p. cg_nthreads was %d\n",
44865ebfeecSJonathan Peyton                  this_thr, tmp, this_thr->th.th_cg_roots, tmp->cg_nthreads));
449b7e6c37eSAndrey Churbanov   KMP_DEBUG_ASSERT(tmp->cg_nthreads);
450b7e6c37eSAndrey Churbanov   int i = tmp->cg_nthreads--;
451b7e6c37eSAndrey Churbanov   if (i == 1) { // check is we are the last thread in CG (not always the case)
45265ebfeecSJonathan Peyton     __kmp_free(tmp);
453b7e6c37eSAndrey Churbanov   }
45465ebfeecSJonathan Peyton   // Restore current task's thread_limit from CG root
45565ebfeecSJonathan Peyton   KMP_DEBUG_ASSERT(this_thr->th.th_cg_roots);
45665ebfeecSJonathan Peyton   this_thr->th.th_current_task->td_icvs.thread_limit =
45765ebfeecSJonathan Peyton       this_thr->th.th_cg_roots->cg_thread_limit;
45865ebfeecSJonathan Peyton 
4597cc577a4SJonathan Peyton   this_thr->th.th_teams_microtask = NULL;
4607cc577a4SJonathan Peyton   this_thr->th.th_teams_level = 0;
4617cc577a4SJonathan Peyton   *(kmp_int64 *)(&this_thr->th.th_teams_size) = 0L;
4627cc577a4SJonathan Peyton   va_end(ap);
463d2b53cadSJonathan Peyton #if KMP_STATS_ENABLED
464d2b53cadSJonathan Peyton   if (previous_state == stats_state_e::SERIAL_REGION) {
465d2b53cadSJonathan Peyton     KMP_EXCHANGE_PARTITIONED_TIMER(OMP_serial);
4660454154eSPeyton, Jonathan L     KMP_SET_THREAD_STATE(previous_state);
467d2b53cadSJonathan Peyton   } else {
468d2b53cadSJonathan Peyton     KMP_POP_PARTITIONED_TIMER();
469d2b53cadSJonathan Peyton   }
470d2b53cadSJonathan Peyton #endif // KMP_STATS_ENABLED
4717cc577a4SJonathan Peyton }
4727cc577a4SJonathan Peyton 
4737cc577a4SJonathan Peyton // I don't think this function should ever have been exported.
4747cc577a4SJonathan Peyton // The __kmpc_ prefix was misapplied.  I'm fairly certain that no generated
4757cc577a4SJonathan Peyton // openmp code ever called it, but it's been exported from the RTL for so
4767cc577a4SJonathan Peyton // long that I'm afraid to remove the definition.
__kmpc_invoke_task_func(int gtid)4773041982dSJonathan Peyton int __kmpc_invoke_task_func(int gtid) { return __kmp_invoke_task_func(gtid); }
4787cc577a4SJonathan Peyton 
4797cc577a4SJonathan Peyton /*!
4807cc577a4SJonathan Peyton @ingroup PARALLEL
4817cc577a4SJonathan Peyton @param loc  source location information
4827cc577a4SJonathan Peyton @param global_tid  global thread number
4837cc577a4SJonathan Peyton 
4847cc577a4SJonathan Peyton Enter a serialized parallel construct. This interface is used to handle a
4857cc577a4SJonathan Peyton conditional parallel region, like this,
4867cc577a4SJonathan Peyton @code
4877cc577a4SJonathan Peyton #pragma omp parallel if (condition)
4887cc577a4SJonathan Peyton @endcode
4897cc577a4SJonathan Peyton when the condition is false.
4907cc577a4SJonathan Peyton */
__kmpc_serialized_parallel(ident_t * loc,kmp_int32 global_tid)4913041982dSJonathan Peyton void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 global_tid) {
492de4749b7SJonathan Peyton   // The implementation is now in kmp_runtime.cpp so that it can share static
493de4749b7SJonathan Peyton   // functions with kmp_fork_call since the tasks to be done are similar in
494de4749b7SJonathan Peyton   // each case.
495787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
49682e94a59SJoachim Protze #if OMPT_SUPPORT
49782e94a59SJoachim Protze   OMPT_STORE_RETURN_ADDRESS(global_tid);
49882e94a59SJoachim Protze #endif
499de4749b7SJonathan Peyton   __kmp_serialized_parallel(loc, global_tid);
5007cc577a4SJonathan Peyton }
5017cc577a4SJonathan Peyton 
5027cc577a4SJonathan Peyton /*!
5037cc577a4SJonathan Peyton @ingroup PARALLEL
5047cc577a4SJonathan Peyton @param loc  source location information
5057cc577a4SJonathan Peyton @param global_tid  global thread number
5067cc577a4SJonathan Peyton 
5077cc577a4SJonathan Peyton Leave a serialized parallel construct.
5087cc577a4SJonathan Peyton */
__kmpc_end_serialized_parallel(ident_t * loc,kmp_int32 global_tid)5093041982dSJonathan Peyton void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 global_tid) {
5107cc577a4SJonathan Peyton   kmp_internal_control_t *top;
5117cc577a4SJonathan Peyton   kmp_info_t *this_thr;
5127cc577a4SJonathan Peyton   kmp_team_t *serial_team;
5137cc577a4SJonathan Peyton 
5143041982dSJonathan Peyton   KC_TRACE(10,
5153041982dSJonathan Peyton            ("__kmpc_end_serialized_parallel: called by T#%d\n", global_tid));
5167cc577a4SJonathan Peyton 
5177cc577a4SJonathan Peyton   /* skip all this code for autopar serialized loops since it results in
5187cc577a4SJonathan Peyton      unacceptable overhead */
5197cc577a4SJonathan Peyton   if (loc != NULL && (loc->flags & KMP_IDENT_AUTOPAR))
5207cc577a4SJonathan Peyton     return;
5217cc577a4SJonathan Peyton 
5227cc577a4SJonathan Peyton   // Not autopar code
523787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
5247cc577a4SJonathan Peyton   if (!TCR_4(__kmp_init_parallel))
5257cc577a4SJonathan Peyton     __kmp_parallel_initialize();
5267cc577a4SJonathan Peyton 
5279b8bb323SJonathan Peyton   __kmp_resume_if_soft_paused();
5289b8bb323SJonathan Peyton 
5297cc577a4SJonathan Peyton   this_thr = __kmp_threads[global_tid];
5307cc577a4SJonathan Peyton   serial_team = this_thr->th.th_serial_team;
5317cc577a4SJonathan Peyton 
5327cc577a4SJonathan Peyton   kmp_task_team_t *task_team = this_thr->th.th_task_team;
5337cc577a4SJonathan Peyton   // we need to wait for the proxy tasks before finishing the thread
534458db51cSShilei Tian   if (task_team != NULL && (task_team->tt.tt_found_proxy_tasks ||
535458db51cSShilei Tian                             task_team->tt.tt_hidden_helper_task_encountered))
5363041982dSJonathan Peyton     __kmp_task_team_wait(this_thr, serial_team USE_ITT_BUILD_ARG(NULL));
5377cc577a4SJonathan Peyton 
5387cc577a4SJonathan Peyton   KMP_MB();
5397cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(serial_team);
5407cc577a4SJonathan Peyton   KMP_ASSERT(serial_team->t.t_serialized);
5417cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(this_thr->th.th_team == serial_team);
5427cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(serial_team != this_thr->th.th_root->r.r_root_team);
5437cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(serial_team->t.t_threads);
5447cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(serial_team->t.t_threads[0] == this_thr);
5457cc577a4SJonathan Peyton 
54682e94a59SJoachim Protze #if OMPT_SUPPORT
54782e94a59SJoachim Protze   if (ompt_enabled.enabled &&
5480e0d6cddSJoachim Protze       this_thr->th.ompt_thread_info.state != ompt_state_overhead) {
5490e0d6cddSJoachim Protze     OMPT_CUR_TASK_INFO(this_thr)->frame.exit_frame = ompt_data_none;
55082e94a59SJoachim Protze     if (ompt_enabled.ompt_callback_implicit_task) {
55182e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
55282e94a59SJoachim Protze           ompt_scope_end, NULL, OMPT_CUR_TASK_DATA(this_thr), 1,
5532b46d30fSJoachim Protze           OMPT_CUR_TASK_INFO(this_thr)->thread_num, ompt_task_implicit);
55482e94a59SJoachim Protze     }
55582e94a59SJoachim Protze 
55682e94a59SJoachim Protze     // reset clear the task id only after unlinking the task
55782e94a59SJoachim Protze     ompt_data_t *parent_task_data;
55882e94a59SJoachim Protze     __ompt_get_task_info_internal(1, NULL, &parent_task_data, NULL, NULL, NULL);
55982e94a59SJoachim Protze 
56082e94a59SJoachim Protze     if (ompt_enabled.ompt_callback_parallel_end) {
56182e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_parallel_end)(
56282e94a59SJoachim Protze           &(serial_team->t.ompt_team_info.parallel_data), parent_task_data,
56367e93a1aSHansang Bae           ompt_parallel_invoker_program | ompt_parallel_team,
56467e93a1aSHansang Bae           OMPT_LOAD_RETURN_ADDRESS(global_tid));
56582e94a59SJoachim Protze     }
56682e94a59SJoachim Protze     __ompt_lw_taskteam_unlink(this_thr);
5670e0d6cddSJoachim Protze     this_thr->th.ompt_thread_info.state = ompt_state_overhead;
56882e94a59SJoachim Protze   }
56982e94a59SJoachim Protze #endif
57082e94a59SJoachim Protze 
5713041982dSJonathan Peyton   /* If necessary, pop the internal control stack values and replace the team
5723041982dSJonathan Peyton    * values */
5737cc577a4SJonathan Peyton   top = serial_team->t.t_control_stack_top;
5747cc577a4SJonathan Peyton   if (top && top->serial_nesting_level == serial_team->t.t_serialized) {
5757cc577a4SJonathan Peyton     copy_icvs(&serial_team->t.t_threads[0]->th.th_current_task->td_icvs, top);
5767cc577a4SJonathan Peyton     serial_team->t.t_control_stack_top = top->next;
5777cc577a4SJonathan Peyton     __kmp_free(top);
5787cc577a4SJonathan Peyton   }
5797cc577a4SJonathan Peyton 
5807cc577a4SJonathan Peyton   /* pop dispatch buffers stack */
5817cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(serial_team->t.t_dispatch->th_disp_buffer);
5827cc577a4SJonathan Peyton   {
5833041982dSJonathan Peyton     dispatch_private_info_t *disp_buffer =
5843041982dSJonathan Peyton         serial_team->t.t_dispatch->th_disp_buffer;
5857cc577a4SJonathan Peyton     serial_team->t.t_dispatch->th_disp_buffer =
5867cc577a4SJonathan Peyton         serial_team->t.t_dispatch->th_disp_buffer->next;
5877cc577a4SJonathan Peyton     __kmp_free(disp_buffer);
5887cc577a4SJonathan Peyton   }
58992ca6188SJonathan Peyton   this_thr->th.th_def_allocator = serial_team->t.t_def_allocator; // restore
5907cc577a4SJonathan Peyton 
5917cc577a4SJonathan Peyton   --serial_team->t.t_serialized;
5927cc577a4SJonathan Peyton   if (serial_team->t.t_serialized == 0) {
5937cc577a4SJonathan Peyton 
5947cc577a4SJonathan Peyton     /* return to the parallel section */
5957cc577a4SJonathan Peyton 
5967cc577a4SJonathan Peyton #if KMP_ARCH_X86 || KMP_ARCH_X86_64
5977cc577a4SJonathan Peyton     if (__kmp_inherit_fp_control && serial_team->t.t_fp_control_saved) {
5987cc577a4SJonathan Peyton       __kmp_clear_x87_fpu_status_word();
5997cc577a4SJonathan Peyton       __kmp_load_x87_fpu_control_word(&serial_team->t.t_x87_fpu_control_word);
6007cc577a4SJonathan Peyton       __kmp_load_mxcsr(&serial_team->t.t_mxcsr);
6017cc577a4SJonathan Peyton     }
6027cc577a4SJonathan Peyton #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
6037cc577a4SJonathan Peyton 
604589519b9SVignesh Balasubramanian     __kmp_pop_current_task_from_thread(this_thr);
605f61602b0SVignesh Balasubramanian #if OMPD_SUPPORT
606f61602b0SVignesh Balasubramanian     if (ompd_state & OMPD_ENABLE_BP)
607f61602b0SVignesh Balasubramanian       ompd_bp_parallel_end();
608f61602b0SVignesh Balasubramanian #endif
609f61602b0SVignesh Balasubramanian 
6107cc577a4SJonathan Peyton     this_thr->th.th_team = serial_team->t.t_parent;
6117cc577a4SJonathan Peyton     this_thr->th.th_info.ds.ds_tid = serial_team->t.t_master_tid;
6127cc577a4SJonathan Peyton 
6137cc577a4SJonathan Peyton     /* restore values cached in the thread */
6147cc577a4SJonathan Peyton     this_thr->th.th_team_nproc = serial_team->t.t_parent->t.t_nproc; /*  JPH */
6153041982dSJonathan Peyton     this_thr->th.th_team_master =
6163041982dSJonathan Peyton         serial_team->t.t_parent->t.t_threads[0]; /* JPH */
6177cc577a4SJonathan Peyton     this_thr->th.th_team_serialized = this_thr->th.th_team->t.t_serialized;
6187cc577a4SJonathan Peyton 
6197cc577a4SJonathan Peyton     /* TODO the below shouldn't need to be adjusted for serialized teams */
6203041982dSJonathan Peyton     this_thr->th.th_dispatch =
6213041982dSJonathan Peyton         &this_thr->th.th_team->t.t_dispatch[serial_team->t.t_master_tid];
6227cc577a4SJonathan Peyton 
6237cc577a4SJonathan Peyton     KMP_ASSERT(this_thr->th.th_current_task->td_flags.executing == 0);
6247cc577a4SJonathan Peyton     this_thr->th.th_current_task->td_flags.executing = 1;
6257cc577a4SJonathan Peyton 
6267cc577a4SJonathan Peyton     if (__kmp_tasking_mode != tskm_immediate_exec) {
6277cc577a4SJonathan Peyton       // Copy the task team from the new child / old parent team to the thread.
6283041982dSJonathan Peyton       this_thr->th.th_task_team =
6293041982dSJonathan Peyton           this_thr->th.th_team->t.t_task_team[this_thr->th.th_task_state];
6303041982dSJonathan Peyton       KA_TRACE(20,
6313041982dSJonathan Peyton                ("__kmpc_end_serialized_parallel: T#%d restoring task_team %p / "
6323041982dSJonathan Peyton                 "team %p\n",
6337cc577a4SJonathan Peyton                 global_tid, this_thr->th.th_task_team, this_thr->th.th_team));
6347cc577a4SJonathan Peyton     }
635*17dcde5fSAndreyChurbanov #if KMP_AFFINITY_SUPPORTED
636*17dcde5fSAndreyChurbanov     if (this_thr->th.th_team->t.t_level == 0 && __kmp_affin_reset) {
637*17dcde5fSAndreyChurbanov       __kmp_reset_root_init_mask(global_tid);
638*17dcde5fSAndreyChurbanov     }
639*17dcde5fSAndreyChurbanov #endif
6407cc577a4SJonathan Peyton   } else {
6417cc577a4SJonathan Peyton     if (__kmp_tasking_mode != tskm_immediate_exec) {
6423041982dSJonathan Peyton       KA_TRACE(20, ("__kmpc_end_serialized_parallel: T#%d decreasing nesting "
6433041982dSJonathan Peyton                     "depth of serial team %p to %d\n",
6447cc577a4SJonathan Peyton                     global_tid, serial_team, serial_team->t.t_serialized));
6457cc577a4SJonathan Peyton     }
6467cc577a4SJonathan Peyton   }
6477cc577a4SJonathan Peyton 
648589519b9SVignesh Balasubramanian   serial_team->t.t_level--;
6497cc577a4SJonathan Peyton   if (__kmp_env_consistency_check)
6507cc577a4SJonathan Peyton     __kmp_pop_parallel(global_tid, NULL);
65182e94a59SJoachim Protze #if OMPT_SUPPORT
65282e94a59SJoachim Protze   if (ompt_enabled.enabled)
65382e94a59SJoachim Protze     this_thr->th.ompt_thread_info.state =
6540e0d6cddSJoachim Protze         ((this_thr->th.th_team_serialized) ? ompt_state_work_serial
6550e0d6cddSJoachim Protze                                            : ompt_state_work_parallel);
65682e94a59SJoachim Protze #endif
6577cc577a4SJonathan Peyton }
6587cc577a4SJonathan Peyton 
6597cc577a4SJonathan Peyton /*!
6607cc577a4SJonathan Peyton @ingroup SYNCHRONIZATION
6617cc577a4SJonathan Peyton @param loc  source location information.
6627cc577a4SJonathan Peyton 
6637cc577a4SJonathan Peyton Execute <tt>flush</tt>. This is implemented as a full memory fence. (Though
6647cc577a4SJonathan Peyton depending on the memory ordering convention obeyed by the compiler
6657cc577a4SJonathan Peyton even that may not be necessary).
6667cc577a4SJonathan Peyton */
__kmpc_flush(ident_t * loc)6673041982dSJonathan Peyton void __kmpc_flush(ident_t *loc) {
6687cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_flush: called\n"));
6697cc577a4SJonathan Peyton 
6707cc577a4SJonathan Peyton   /* need explicit __mf() here since use volatile instead in library */
6717cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
6727cc577a4SJonathan Peyton 
6737cc577a4SJonathan Peyton #if (KMP_ARCH_X86 || KMP_ARCH_X86_64)
6747cc577a4SJonathan Peyton #if KMP_MIC
6757cc577a4SJonathan Peyton // fence-style instructions do not exist, but lock; xaddl $0,(%rsp) can be used.
6767cc577a4SJonathan Peyton // We shouldn't need it, though, since the ABI rules require that
6777cc577a4SJonathan Peyton // * If the compiler generates NGO stores it also generates the fence
6787cc577a4SJonathan Peyton // * If users hand-code NGO stores they should insert the fence
6797cc577a4SJonathan Peyton // therefore no incomplete unordered stores should be visible.
6807cc577a4SJonathan Peyton #else
6817cc577a4SJonathan Peyton   // C74404
6827cc577a4SJonathan Peyton   // This is to address non-temporal store instructions (sfence needed).
6837cc577a4SJonathan Peyton   // The clflush instruction is addressed either (mfence needed).
6843041982dSJonathan Peyton   // Probably the non-temporal load monvtdqa instruction should also be
6853041982dSJonathan Peyton   // addressed.
6867cc577a4SJonathan Peyton   // mfence is a SSE2 instruction. Do not execute it if CPU is not SSE2.
6877cc577a4SJonathan Peyton   if (!__kmp_cpuinfo.initialized) {
6887cc577a4SJonathan Peyton     __kmp_query_cpuid(&__kmp_cpuinfo);
689bd3a7633SJonathan Peyton   }
690343b9e85SPeyton, Jonathan L   if (!__kmp_cpuinfo.flags.sse2) {
6917cc577a4SJonathan Peyton     // CPU cannot execute SSE2 instructions.
6927cc577a4SJonathan Peyton   } else {
6931234011bSJonathan Peyton #if KMP_COMPILER_ICC || KMP_COMPILER_ICX
6947cc577a4SJonathan Peyton     _mm_mfence();
6957cc577a4SJonathan Peyton #elif KMP_COMPILER_MSVC
6967cc577a4SJonathan Peyton     MemoryBarrier();
6977cc577a4SJonathan Peyton #else
6987cc577a4SJonathan Peyton     __sync_synchronize();
6991234011bSJonathan Peyton #endif // KMP_COMPILER_ICC || KMP_COMPILER_ICX
700bd3a7633SJonathan Peyton   }
7017cc577a4SJonathan Peyton #endif // KMP_MIC
7022488ae9dSJonas Hahnfeld #elif (KMP_ARCH_ARM || KMP_ARCH_AARCH64 || KMP_ARCH_MIPS || KMP_ARCH_MIPS64 || \
7032488ae9dSJonas Hahnfeld        KMP_ARCH_RISCV64)
7047cc577a4SJonathan Peyton // Nothing to see here move along
7057cc577a4SJonathan Peyton #elif KMP_ARCH_PPC64
7067cc577a4SJonathan Peyton // Nothing needed here (we have a real MB above).
7077cc577a4SJonathan Peyton #else
7087cc577a4SJonathan Peyton #error Unknown or unsupported architecture
7097cc577a4SJonathan Peyton #endif
71082e94a59SJoachim Protze 
71182e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
71282e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_flush) {
71382e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_flush)(
71482e94a59SJoachim Protze         __ompt_get_thread_data_internal(), OMPT_GET_RETURN_ADDRESS(0));
71582e94a59SJoachim Protze   }
71682e94a59SJoachim Protze #endif
7177cc577a4SJonathan Peyton }
7187cc577a4SJonathan Peyton 
7197cc577a4SJonathan Peyton /* -------------------------------------------------------------------------- */
7207cc577a4SJonathan Peyton /*!
7217cc577a4SJonathan Peyton @ingroup SYNCHRONIZATION
7227cc577a4SJonathan Peyton @param loc source location information
7237cc577a4SJonathan Peyton @param global_tid thread id.
7247cc577a4SJonathan Peyton 
7257cc577a4SJonathan Peyton Execute a barrier.
7267cc577a4SJonathan Peyton */
__kmpc_barrier(ident_t * loc,kmp_int32 global_tid)7273041982dSJonathan Peyton void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid) {
7287cc577a4SJonathan Peyton   KMP_COUNT_BLOCK(OMP_BARRIER);
7297cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_barrier: called T#%d\n", global_tid));
730787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
7317cc577a4SJonathan Peyton 
7327cc577a4SJonathan Peyton   if (!TCR_4(__kmp_init_parallel))
7337cc577a4SJonathan Peyton     __kmp_parallel_initialize();
7347cc577a4SJonathan Peyton 
7359b8bb323SJonathan Peyton   __kmp_resume_if_soft_paused();
7369b8bb323SJonathan Peyton 
7377cc577a4SJonathan Peyton   if (__kmp_env_consistency_check) {
7387cc577a4SJonathan Peyton     if (loc == 0) {
7397cc577a4SJonathan Peyton       KMP_WARNING(ConstructIdentInvalid); // ??? What does it mean for the user?
740bd3a7633SJonathan Peyton     }
7417cc577a4SJonathan Peyton     __kmp_check_barrier(global_tid, ct_barrier, loc);
7427cc577a4SJonathan Peyton   }
7437cc577a4SJonathan Peyton 
74482e94a59SJoachim Protze #if OMPT_SUPPORT
7450e0d6cddSJoachim Protze   ompt_frame_t *ompt_frame;
74682e94a59SJoachim Protze   if (ompt_enabled.enabled) {
74782e94a59SJoachim Protze     __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL);
7480e0d6cddSJoachim Protze     if (ompt_frame->enter_frame.ptr == NULL)
7490e0d6cddSJoachim Protze       ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
7507cc577a4SJonathan Peyton   }
7516d3b8166SJoachim Protze   OMPT_STORE_RETURN_ADDRESS(global_tid);
7527cc577a4SJonathan Peyton #endif
7537cc577a4SJonathan Peyton   __kmp_threads[global_tid]->th.th_ident = loc;
7547cc577a4SJonathan Peyton   // TODO: explicit barrier_wait_id:
7557cc577a4SJonathan Peyton   //   this function is called when 'barrier' directive is present or
7567cc577a4SJonathan Peyton   //   implicit barrier at the end of a worksharing construct.
7577cc577a4SJonathan Peyton   // 1) better to add a per-thread barrier counter to a thread data structure
7587cc577a4SJonathan Peyton   // 2) set to 0 when a new team is created
7597cc577a4SJonathan Peyton   // 4) no sync is required
7607cc577a4SJonathan Peyton 
7617cc577a4SJonathan Peyton   __kmp_barrier(bs_plain_barrier, global_tid, FALSE, 0, NULL, NULL);
76282e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
76382e94a59SJoachim Protze   if (ompt_enabled.enabled) {
7640e0d6cddSJoachim Protze     ompt_frame->enter_frame = ompt_data_none;
7657cc577a4SJonathan Peyton   }
7667cc577a4SJonathan Peyton #endif
7677cc577a4SJonathan Peyton }
7687cc577a4SJonathan Peyton 
7697cc577a4SJonathan Peyton /* The BARRIER for a MASTER section is always explicit   */
7707cc577a4SJonathan Peyton /*!
7717cc577a4SJonathan Peyton @ingroup WORK_SHARING
7727cc577a4SJonathan Peyton @param loc  source location information.
7737cc577a4SJonathan Peyton @param global_tid  global thread number .
7747cc577a4SJonathan Peyton @return 1 if this thread should execute the <tt>master</tt> block, 0 otherwise.
7757cc577a4SJonathan Peyton */
__kmpc_master(ident_t * loc,kmp_int32 global_tid)7763041982dSJonathan Peyton kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid) {
7777cc577a4SJonathan Peyton   int status = 0;
7787cc577a4SJonathan Peyton 
7797cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_master: called T#%d\n", global_tid));
780787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
7817cc577a4SJonathan Peyton 
7827cc577a4SJonathan Peyton   if (!TCR_4(__kmp_init_parallel))
7837cc577a4SJonathan Peyton     __kmp_parallel_initialize();
7847cc577a4SJonathan Peyton 
7859b8bb323SJonathan Peyton   __kmp_resume_if_soft_paused();
7869b8bb323SJonathan Peyton 
7877cc577a4SJonathan Peyton   if (KMP_MASTER_GTID(global_tid)) {
7887cc577a4SJonathan Peyton     KMP_COUNT_BLOCK(OMP_MASTER);
7897cc577a4SJonathan Peyton     KMP_PUSH_PARTITIONED_TIMER(OMP_master);
7907cc577a4SJonathan Peyton     status = 1;
7917cc577a4SJonathan Peyton   }
7927cc577a4SJonathan Peyton 
79382e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
7947cc577a4SJonathan Peyton   if (status) {
7956213ed06SJoachim Protze     if (ompt_enabled.ompt_callback_masked) {
7967cc577a4SJonathan Peyton       kmp_info_t *this_thr = __kmp_threads[global_tid];
7977cc577a4SJonathan Peyton       kmp_team_t *team = this_thr->th.th_team;
7987cc577a4SJonathan Peyton 
7997cc577a4SJonathan Peyton       int tid = __kmp_tid_from_gtid(global_tid);
8006213ed06SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_masked)(
80182e94a59SJoachim Protze           ompt_scope_begin, &(team->t.ompt_team_info.parallel_data),
80282e94a59SJoachim Protze           &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data),
80382e94a59SJoachim Protze           OMPT_GET_RETURN_ADDRESS(0));
8047cc577a4SJonathan Peyton     }
8057cc577a4SJonathan Peyton   }
8067cc577a4SJonathan Peyton #endif
8077cc577a4SJonathan Peyton 
8087cc577a4SJonathan Peyton   if (__kmp_env_consistency_check) {
8097cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
8107cc577a4SJonathan Peyton     if (status)
8117cc577a4SJonathan Peyton       __kmp_push_sync(global_tid, ct_master, loc, NULL, 0);
8127cc577a4SJonathan Peyton     else
8137cc577a4SJonathan Peyton       __kmp_check_sync(global_tid, ct_master, loc, NULL, 0);
8147cc577a4SJonathan Peyton #else
8157cc577a4SJonathan Peyton     if (status)
8167cc577a4SJonathan Peyton       __kmp_push_sync(global_tid, ct_master, loc, NULL);
8177cc577a4SJonathan Peyton     else
8187cc577a4SJonathan Peyton       __kmp_check_sync(global_tid, ct_master, loc, NULL);
8197cc577a4SJonathan Peyton #endif
8207cc577a4SJonathan Peyton   }
8217cc577a4SJonathan Peyton 
8227cc577a4SJonathan Peyton   return status;
8237cc577a4SJonathan Peyton }
8247cc577a4SJonathan Peyton 
8257cc577a4SJonathan Peyton /*!
8267cc577a4SJonathan Peyton @ingroup WORK_SHARING
8277cc577a4SJonathan Peyton @param loc  source location information.
8287cc577a4SJonathan Peyton @param global_tid  global thread number .
8297cc577a4SJonathan Peyton 
8303041982dSJonathan Peyton Mark the end of a <tt>master</tt> region. This should only be called by the
8313041982dSJonathan Peyton thread that executes the <tt>master</tt> region.
8327cc577a4SJonathan Peyton */
__kmpc_end_master(ident_t * loc,kmp_int32 global_tid)8333041982dSJonathan Peyton void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid) {
8347cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_end_master: called T#%d\n", global_tid));
835787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
8367cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(KMP_MASTER_GTID(global_tid));
8377cc577a4SJonathan Peyton   KMP_POP_PARTITIONED_TIMER();
8387cc577a4SJonathan Peyton 
83982e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
8407cc577a4SJonathan Peyton   kmp_info_t *this_thr = __kmp_threads[global_tid];
8417cc577a4SJonathan Peyton   kmp_team_t *team = this_thr->th.th_team;
8426213ed06SJoachim Protze   if (ompt_enabled.ompt_callback_masked) {
8437cc577a4SJonathan Peyton     int tid = __kmp_tid_from_gtid(global_tid);
8446213ed06SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_masked)(
84582e94a59SJoachim Protze         ompt_scope_end, &(team->t.ompt_team_info.parallel_data),
84682e94a59SJoachim Protze         &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data),
84782e94a59SJoachim Protze         OMPT_GET_RETURN_ADDRESS(0));
8487cc577a4SJonathan Peyton   }
8497cc577a4SJonathan Peyton #endif
8507cc577a4SJonathan Peyton 
8517cc577a4SJonathan Peyton   if (__kmp_env_consistency_check) {
8527cc577a4SJonathan Peyton     if (KMP_MASTER_GTID(global_tid))
8537cc577a4SJonathan Peyton       __kmp_pop_sync(global_tid, ct_master, loc);
8547cc577a4SJonathan Peyton   }
8557cc577a4SJonathan Peyton }
8567cc577a4SJonathan Peyton 
8577cc577a4SJonathan Peyton /*!
8587cc577a4SJonathan Peyton @ingroup WORK_SHARING
8597cc577a4SJonathan Peyton @param loc  source location information.
86097d000cfStlwilmar @param global_tid  global thread number.
86197d000cfStlwilmar @param filter result of evaluating filter clause on thread global_tid, or zero
86297d000cfStlwilmar if no filter clause present
86397d000cfStlwilmar @return 1 if this thread should execute the <tt>masked</tt> block, 0 otherwise.
86497d000cfStlwilmar */
__kmpc_masked(ident_t * loc,kmp_int32 global_tid,kmp_int32 filter)86597d000cfStlwilmar kmp_int32 __kmpc_masked(ident_t *loc, kmp_int32 global_tid, kmp_int32 filter) {
86697d000cfStlwilmar   int status = 0;
86797d000cfStlwilmar   int tid;
86897d000cfStlwilmar   KC_TRACE(10, ("__kmpc_masked: called T#%d\n", global_tid));
86997d000cfStlwilmar   __kmp_assert_valid_gtid(global_tid);
87097d000cfStlwilmar 
87197d000cfStlwilmar   if (!TCR_4(__kmp_init_parallel))
87297d000cfStlwilmar     __kmp_parallel_initialize();
87397d000cfStlwilmar 
87497d000cfStlwilmar   __kmp_resume_if_soft_paused();
87597d000cfStlwilmar 
87697d000cfStlwilmar   tid = __kmp_tid_from_gtid(global_tid);
87797d000cfStlwilmar   if (tid == filter) {
87897d000cfStlwilmar     KMP_COUNT_BLOCK(OMP_MASKED);
87997d000cfStlwilmar     KMP_PUSH_PARTITIONED_TIMER(OMP_masked);
88097d000cfStlwilmar     status = 1;
88197d000cfStlwilmar   }
88297d000cfStlwilmar 
88397d000cfStlwilmar #if OMPT_SUPPORT && OMPT_OPTIONAL
88497d000cfStlwilmar   if (status) {
88597d000cfStlwilmar     if (ompt_enabled.ompt_callback_masked) {
88697d000cfStlwilmar       kmp_info_t *this_thr = __kmp_threads[global_tid];
88797d000cfStlwilmar       kmp_team_t *team = this_thr->th.th_team;
88897d000cfStlwilmar       ompt_callbacks.ompt_callback(ompt_callback_masked)(
88997d000cfStlwilmar           ompt_scope_begin, &(team->t.ompt_team_info.parallel_data),
89097d000cfStlwilmar           &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data),
89197d000cfStlwilmar           OMPT_GET_RETURN_ADDRESS(0));
89297d000cfStlwilmar     }
89397d000cfStlwilmar   }
89497d000cfStlwilmar #endif
89597d000cfStlwilmar 
89697d000cfStlwilmar   if (__kmp_env_consistency_check) {
89797d000cfStlwilmar #if KMP_USE_DYNAMIC_LOCK
89897d000cfStlwilmar     if (status)
89997d000cfStlwilmar       __kmp_push_sync(global_tid, ct_masked, loc, NULL, 0);
90097d000cfStlwilmar     else
90197d000cfStlwilmar       __kmp_check_sync(global_tid, ct_masked, loc, NULL, 0);
90297d000cfStlwilmar #else
90397d000cfStlwilmar     if (status)
90497d000cfStlwilmar       __kmp_push_sync(global_tid, ct_masked, loc, NULL);
90597d000cfStlwilmar     else
90697d000cfStlwilmar       __kmp_check_sync(global_tid, ct_masked, loc, NULL);
90797d000cfStlwilmar #endif
90897d000cfStlwilmar   }
90997d000cfStlwilmar 
91097d000cfStlwilmar   return status;
91197d000cfStlwilmar }
91297d000cfStlwilmar 
91397d000cfStlwilmar /*!
91497d000cfStlwilmar @ingroup WORK_SHARING
91597d000cfStlwilmar @param loc  source location information.
91697d000cfStlwilmar @param global_tid  global thread number .
91797d000cfStlwilmar 
91897d000cfStlwilmar Mark the end of a <tt>masked</tt> region. This should only be called by the
91997d000cfStlwilmar thread that executes the <tt>masked</tt> region.
92097d000cfStlwilmar */
__kmpc_end_masked(ident_t * loc,kmp_int32 global_tid)92197d000cfStlwilmar void __kmpc_end_masked(ident_t *loc, kmp_int32 global_tid) {
92297d000cfStlwilmar   KC_TRACE(10, ("__kmpc_end_masked: called T#%d\n", global_tid));
92397d000cfStlwilmar   __kmp_assert_valid_gtid(global_tid);
92497d000cfStlwilmar   KMP_POP_PARTITIONED_TIMER();
92597d000cfStlwilmar 
92697d000cfStlwilmar #if OMPT_SUPPORT && OMPT_OPTIONAL
92797d000cfStlwilmar   kmp_info_t *this_thr = __kmp_threads[global_tid];
92897d000cfStlwilmar   kmp_team_t *team = this_thr->th.th_team;
92997d000cfStlwilmar   if (ompt_enabled.ompt_callback_masked) {
93097d000cfStlwilmar     int tid = __kmp_tid_from_gtid(global_tid);
93197d000cfStlwilmar     ompt_callbacks.ompt_callback(ompt_callback_masked)(
93297d000cfStlwilmar         ompt_scope_end, &(team->t.ompt_team_info.parallel_data),
93397d000cfStlwilmar         &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data),
93497d000cfStlwilmar         OMPT_GET_RETURN_ADDRESS(0));
93597d000cfStlwilmar   }
93697d000cfStlwilmar #endif
93797d000cfStlwilmar 
93897d000cfStlwilmar   if (__kmp_env_consistency_check) {
93997d000cfStlwilmar     __kmp_pop_sync(global_tid, ct_masked, loc);
94097d000cfStlwilmar   }
94197d000cfStlwilmar }
94297d000cfStlwilmar 
94397d000cfStlwilmar /*!
94497d000cfStlwilmar @ingroup WORK_SHARING
94597d000cfStlwilmar @param loc  source location information.
9467cc577a4SJonathan Peyton @param gtid  global thread number.
9477cc577a4SJonathan Peyton 
9487cc577a4SJonathan Peyton Start execution of an <tt>ordered</tt> construct.
9497cc577a4SJonathan Peyton */
__kmpc_ordered(ident_t * loc,kmp_int32 gtid)9503041982dSJonathan Peyton void __kmpc_ordered(ident_t *loc, kmp_int32 gtid) {
9517cc577a4SJonathan Peyton   int cid = 0;
9527cc577a4SJonathan Peyton   kmp_info_t *th;
9537cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(__kmp_init_serial);
9547cc577a4SJonathan Peyton 
9557cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_ordered: called T#%d\n", gtid));
956787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(gtid);
9577cc577a4SJonathan Peyton 
9587cc577a4SJonathan Peyton   if (!TCR_4(__kmp_init_parallel))
9597cc577a4SJonathan Peyton     __kmp_parallel_initialize();
9607cc577a4SJonathan Peyton 
9619b8bb323SJonathan Peyton   __kmp_resume_if_soft_paused();
9629b8bb323SJonathan Peyton 
9637cc577a4SJonathan Peyton #if USE_ITT_BUILD
9647cc577a4SJonathan Peyton   __kmp_itt_ordered_prep(gtid);
9657cc577a4SJonathan Peyton // TODO: ordered_wait_id
9667cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
9677cc577a4SJonathan Peyton 
9687cc577a4SJonathan Peyton   th = __kmp_threads[gtid];
9697cc577a4SJonathan Peyton 
97082e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
97182e94a59SJoachim Protze   kmp_team_t *team;
9720e0d6cddSJoachim Protze   ompt_wait_id_t lck;
97382e94a59SJoachim Protze   void *codeptr_ra;
97482e94a59SJoachim Protze   OMPT_STORE_RETURN_ADDRESS(gtid);
9756d3b8166SJoachim Protze   if (ompt_enabled.enabled) {
97682e94a59SJoachim Protze     team = __kmp_team_from_gtid(gtid);
9774109d560SJoachim Protze     lck = (ompt_wait_id_t)(uintptr_t)&team->t.t_ordered.dt.t_value;
9787cc577a4SJonathan Peyton     /* OMPT state update */
97982e94a59SJoachim Protze     th->th.ompt_thread_info.wait_id = lck;
9800e0d6cddSJoachim Protze     th->th.ompt_thread_info.state = ompt_state_wait_ordered;
9817cc577a4SJonathan Peyton 
9827cc577a4SJonathan Peyton     /* OMPT event callback */
98382e94a59SJoachim Protze     codeptr_ra = OMPT_LOAD_RETURN_ADDRESS(gtid);
98482e94a59SJoachim Protze     if (ompt_enabled.ompt_callback_mutex_acquire) {
98582e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)(
9864109d560SJoachim Protze           ompt_mutex_ordered, omp_lock_hint_none, kmp_mutex_impl_spin, lck,
9874109d560SJoachim Protze           codeptr_ra);
9887cc577a4SJonathan Peyton     }
9897cc577a4SJonathan Peyton   }
9907cc577a4SJonathan Peyton #endif
9917cc577a4SJonathan Peyton 
9927cc577a4SJonathan Peyton   if (th->th.th_dispatch->th_deo_fcn != 0)
9937cc577a4SJonathan Peyton     (*th->th.th_dispatch->th_deo_fcn)(&gtid, &cid, loc);
9947cc577a4SJonathan Peyton   else
9957cc577a4SJonathan Peyton     __kmp_parallel_deo(&gtid, &cid, loc);
9967cc577a4SJonathan Peyton 
99782e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
99882e94a59SJoachim Protze   if (ompt_enabled.enabled) {
9997cc577a4SJonathan Peyton     /* OMPT state update */
10000e0d6cddSJoachim Protze     th->th.ompt_thread_info.state = ompt_state_work_parallel;
10017cc577a4SJonathan Peyton     th->th.ompt_thread_info.wait_id = 0;
10027cc577a4SJonathan Peyton 
10037cc577a4SJonathan Peyton     /* OMPT event callback */
100482e94a59SJoachim Protze     if (ompt_enabled.ompt_callback_mutex_acquired) {
100582e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)(
10064109d560SJoachim Protze           ompt_mutex_ordered, (ompt_wait_id_t)(uintptr_t)lck, codeptr_ra);
10077cc577a4SJonathan Peyton     }
10087cc577a4SJonathan Peyton   }
10097cc577a4SJonathan Peyton #endif
10107cc577a4SJonathan Peyton 
10117cc577a4SJonathan Peyton #if USE_ITT_BUILD
10127cc577a4SJonathan Peyton   __kmp_itt_ordered_start(gtid);
10137cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
10147cc577a4SJonathan Peyton }
10157cc577a4SJonathan Peyton 
10167cc577a4SJonathan Peyton /*!
10177cc577a4SJonathan Peyton @ingroup WORK_SHARING
10187cc577a4SJonathan Peyton @param loc  source location information.
10197cc577a4SJonathan Peyton @param gtid  global thread number.
10207cc577a4SJonathan Peyton 
10217cc577a4SJonathan Peyton End execution of an <tt>ordered</tt> construct.
10227cc577a4SJonathan Peyton */
__kmpc_end_ordered(ident_t * loc,kmp_int32 gtid)10233041982dSJonathan Peyton void __kmpc_end_ordered(ident_t *loc, kmp_int32 gtid) {
10247cc577a4SJonathan Peyton   int cid = 0;
10257cc577a4SJonathan Peyton   kmp_info_t *th;
10267cc577a4SJonathan Peyton 
10277cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_end_ordered: called T#%d\n", gtid));
1028787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(gtid);
10297cc577a4SJonathan Peyton 
10307cc577a4SJonathan Peyton #if USE_ITT_BUILD
10317cc577a4SJonathan Peyton   __kmp_itt_ordered_end(gtid);
10327cc577a4SJonathan Peyton // TODO: ordered_wait_id
10337cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
10347cc577a4SJonathan Peyton 
10357cc577a4SJonathan Peyton   th = __kmp_threads[gtid];
10367cc577a4SJonathan Peyton 
10377cc577a4SJonathan Peyton   if (th->th.th_dispatch->th_dxo_fcn != 0)
10387cc577a4SJonathan Peyton     (*th->th.th_dispatch->th_dxo_fcn)(&gtid, &cid, loc);
10397cc577a4SJonathan Peyton   else
10407cc577a4SJonathan Peyton     __kmp_parallel_dxo(&gtid, &cid, loc);
10417cc577a4SJonathan Peyton 
104282e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
104382e94a59SJoachim Protze   OMPT_STORE_RETURN_ADDRESS(gtid);
104482e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_mutex_released) {
104582e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_mutex_released)(
104682e94a59SJoachim Protze         ompt_mutex_ordered,
10474109d560SJoachim Protze         (ompt_wait_id_t)(uintptr_t)&__kmp_team_from_gtid(gtid)
10484109d560SJoachim Protze             ->t.t_ordered.dt.t_value,
104982e94a59SJoachim Protze         OMPT_LOAD_RETURN_ADDRESS(gtid));
10507cc577a4SJonathan Peyton   }
10517cc577a4SJonathan Peyton #endif
10527cc577a4SJonathan Peyton }
10537cc577a4SJonathan Peyton 
10547cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
10557cc577a4SJonathan Peyton 
10567cc577a4SJonathan Peyton static __forceinline void
__kmp_init_indirect_csptr(kmp_critical_name * crit,ident_t const * loc,kmp_int32 gtid,kmp_indirect_locktag_t tag)10573041982dSJonathan Peyton __kmp_init_indirect_csptr(kmp_critical_name *crit, ident_t const *loc,
10583041982dSJonathan Peyton                           kmp_int32 gtid, kmp_indirect_locktag_t tag) {
10593041982dSJonathan Peyton   // Pointer to the allocated indirect lock is written to crit, while indexing
10603041982dSJonathan Peyton   // is ignored.
10617cc577a4SJonathan Peyton   void *idx;
10627cc577a4SJonathan Peyton   kmp_indirect_lock_t **lck;
10637cc577a4SJonathan Peyton   lck = (kmp_indirect_lock_t **)crit;
10647cc577a4SJonathan Peyton   kmp_indirect_lock_t *ilk = __kmp_allocate_indirect_lock(&idx, gtid, tag);
10657cc577a4SJonathan Peyton   KMP_I_LOCK_FUNC(ilk, init)(ilk->lock);
10667cc577a4SJonathan Peyton   KMP_SET_I_LOCK_LOCATION(ilk, loc);
10677cc577a4SJonathan Peyton   KMP_SET_I_LOCK_FLAGS(ilk, kmp_lf_critical_section);
10683041982dSJonathan Peyton   KA_TRACE(20,
10693041982dSJonathan Peyton            ("__kmp_init_indirect_csptr: initialized indirect lock #%d\n", tag));
10707cc577a4SJonathan Peyton #if USE_ITT_BUILD
10717cc577a4SJonathan Peyton   __kmp_itt_critical_creating(ilk->lock, loc);
10727cc577a4SJonathan Peyton #endif
10735ba90c79SAndrey Churbanov   int status = KMP_COMPARE_AND_STORE_PTR(lck, nullptr, ilk);
10747cc577a4SJonathan Peyton   if (status == 0) {
10757cc577a4SJonathan Peyton #if USE_ITT_BUILD
10767cc577a4SJonathan Peyton     __kmp_itt_critical_destroyed(ilk->lock);
10777cc577a4SJonathan Peyton #endif
10783041982dSJonathan Peyton     // We don't really need to destroy the unclaimed lock here since it will be
10793041982dSJonathan Peyton     // cleaned up at program exit.
10807cc577a4SJonathan Peyton     // KMP_D_LOCK_FUNC(&idx, destroy)((kmp_dyna_lock_t *)&idx);
10817cc577a4SJonathan Peyton   }
10827cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(*lck != NULL);
10837cc577a4SJonathan Peyton }
10847cc577a4SJonathan Peyton 
10857cc577a4SJonathan Peyton // Fast-path acquire tas lock
10863041982dSJonathan Peyton #define KMP_ACQUIRE_TAS_LOCK(lock, gtid)                                       \
10873041982dSJonathan Peyton   {                                                                            \
10887cc577a4SJonathan Peyton     kmp_tas_lock_t *l = (kmp_tas_lock_t *)lock;                                \
108937e2ef54SJonathan Peyton     kmp_int32 tas_free = KMP_LOCK_FREE(tas);                                   \
109037e2ef54SJonathan Peyton     kmp_int32 tas_busy = KMP_LOCK_BUSY(gtid + 1, tas);                         \
109137e2ef54SJonathan Peyton     if (KMP_ATOMIC_LD_RLX(&l->lk.poll) != tas_free ||                          \
109237e2ef54SJonathan Peyton         !__kmp_atomic_compare_store_acq(&l->lk.poll, tas_free, tas_busy)) {    \
10937cc577a4SJonathan Peyton       kmp_uint32 spins;                                                        \
10947cc577a4SJonathan Peyton       KMP_FSYNC_PREPARE(l);                                                    \
10957cc577a4SJonathan Peyton       KMP_INIT_YIELD(spins);                                                   \
10967cc577a4SJonathan Peyton       kmp_backoff_t backoff = __kmp_spin_backoff_params;                       \
1097e47d32f1SJonathan Peyton       do {                                                                     \
10983041982dSJonathan Peyton         if (TCR_4(__kmp_nth) >                                                 \
10993041982dSJonathan Peyton             (__kmp_avail_proc ? __kmp_avail_proc : __kmp_xproc)) {             \
11007cc577a4SJonathan Peyton           KMP_YIELD(TRUE);                                                     \
11017cc577a4SJonathan Peyton         } else {                                                               \
11027cc577a4SJonathan Peyton           KMP_YIELD_SPIN(spins);                                               \
11037cc577a4SJonathan Peyton         }                                                                      \
1104e47d32f1SJonathan Peyton         __kmp_spin_backoff(&backoff);                                          \
1105e47d32f1SJonathan Peyton       } while (                                                                \
1106e47d32f1SJonathan Peyton           KMP_ATOMIC_LD_RLX(&l->lk.poll) != tas_free ||                        \
1107e47d32f1SJonathan Peyton           !__kmp_atomic_compare_store_acq(&l->lk.poll, tas_free, tas_busy));   \
11087cc577a4SJonathan Peyton     }                                                                          \
11097cc577a4SJonathan Peyton     KMP_FSYNC_ACQUIRED(l);                                                     \
11107cc577a4SJonathan Peyton   }
11117cc577a4SJonathan Peyton 
11127cc577a4SJonathan Peyton // Fast-path test tas lock
11133041982dSJonathan Peyton #define KMP_TEST_TAS_LOCK(lock, gtid, rc)                                      \
11143041982dSJonathan Peyton   {                                                                            \
11157cc577a4SJonathan Peyton     kmp_tas_lock_t *l = (kmp_tas_lock_t *)lock;                                \
111637e2ef54SJonathan Peyton     kmp_int32 tas_free = KMP_LOCK_FREE(tas);                                   \
111737e2ef54SJonathan Peyton     kmp_int32 tas_busy = KMP_LOCK_BUSY(gtid + 1, tas);                         \
111837e2ef54SJonathan Peyton     rc = KMP_ATOMIC_LD_RLX(&l->lk.poll) == tas_free &&                         \
111937e2ef54SJonathan Peyton          __kmp_atomic_compare_store_acq(&l->lk.poll, tas_free, tas_busy);      \
11207cc577a4SJonathan Peyton   }
11217cc577a4SJonathan Peyton 
11227cc577a4SJonathan Peyton // Fast-path release tas lock
11233041982dSJonathan Peyton #define KMP_RELEASE_TAS_LOCK(lock, gtid)                                       \
112437e2ef54SJonathan Peyton   { KMP_ATOMIC_ST_REL(&((kmp_tas_lock_t *)lock)->lk.poll, KMP_LOCK_FREE(tas)); }
11257cc577a4SJonathan Peyton 
11267cc577a4SJonathan Peyton #if KMP_USE_FUTEX
11277cc577a4SJonathan Peyton 
11287cc577a4SJonathan Peyton #include <sys/syscall.h>
11293041982dSJonathan Peyton #include <unistd.h>
11307cc577a4SJonathan Peyton #ifndef FUTEX_WAIT
11317cc577a4SJonathan Peyton #define FUTEX_WAIT 0
11327cc577a4SJonathan Peyton #endif
11337cc577a4SJonathan Peyton #ifndef FUTEX_WAKE
11347cc577a4SJonathan Peyton #define FUTEX_WAKE 1
11357cc577a4SJonathan Peyton #endif
11367cc577a4SJonathan Peyton 
11377cc577a4SJonathan Peyton // Fast-path acquire futex lock
11383041982dSJonathan Peyton #define KMP_ACQUIRE_FUTEX_LOCK(lock, gtid)                                     \
11393041982dSJonathan Peyton   {                                                                            \
11407cc577a4SJonathan Peyton     kmp_futex_lock_t *ftx = (kmp_futex_lock_t *)lock;                          \
11417cc577a4SJonathan Peyton     kmp_int32 gtid_code = (gtid + 1) << 1;                                     \
11427cc577a4SJonathan Peyton     KMP_MB();                                                                  \
11437cc577a4SJonathan Peyton     KMP_FSYNC_PREPARE(ftx);                                                    \
11447cc577a4SJonathan Peyton     kmp_int32 poll_val;                                                        \
11453041982dSJonathan Peyton     while ((poll_val = KMP_COMPARE_AND_STORE_RET32(                            \
11463041982dSJonathan Peyton                 &(ftx->lk.poll), KMP_LOCK_FREE(futex),                         \
11477cc577a4SJonathan Peyton                 KMP_LOCK_BUSY(gtid_code, futex))) != KMP_LOCK_FREE(futex)) {   \
11487cc577a4SJonathan Peyton       kmp_int32 cond = KMP_LOCK_STRIP(poll_val) & 1;                           \
11497cc577a4SJonathan Peyton       if (!cond) {                                                             \
11503041982dSJonathan Peyton         if (!KMP_COMPARE_AND_STORE_RET32(&(ftx->lk.poll), poll_val,            \
11513041982dSJonathan Peyton                                          poll_val |                            \
11523041982dSJonathan Peyton                                              KMP_LOCK_BUSY(1, futex))) {       \
11537cc577a4SJonathan Peyton           continue;                                                            \
11547cc577a4SJonathan Peyton         }                                                                      \
11557cc577a4SJonathan Peyton         poll_val |= KMP_LOCK_BUSY(1, futex);                                   \
11567cc577a4SJonathan Peyton       }                                                                        \
11577cc577a4SJonathan Peyton       kmp_int32 rc;                                                            \
11583041982dSJonathan Peyton       if ((rc = syscall(__NR_futex, &(ftx->lk.poll), FUTEX_WAIT, poll_val,     \
11593041982dSJonathan Peyton                         NULL, NULL, 0)) != 0) {                                \
11607cc577a4SJonathan Peyton         continue;                                                              \
11617cc577a4SJonathan Peyton       }                                                                        \
11627cc577a4SJonathan Peyton       gtid_code |= 1;                                                          \
11637cc577a4SJonathan Peyton     }                                                                          \
11647cc577a4SJonathan Peyton     KMP_FSYNC_ACQUIRED(ftx);                                                   \
11657cc577a4SJonathan Peyton   }
11667cc577a4SJonathan Peyton 
11677cc577a4SJonathan Peyton // Fast-path test futex lock
11683041982dSJonathan Peyton #define KMP_TEST_FUTEX_LOCK(lock, gtid, rc)                                    \
11693041982dSJonathan Peyton   {                                                                            \
11707cc577a4SJonathan Peyton     kmp_futex_lock_t *ftx = (kmp_futex_lock_t *)lock;                          \
11713041982dSJonathan Peyton     if (KMP_COMPARE_AND_STORE_ACQ32(&(ftx->lk.poll), KMP_LOCK_FREE(futex),     \
11723041982dSJonathan Peyton                                     KMP_LOCK_BUSY(gtid + 1 << 1, futex))) {    \
11737cc577a4SJonathan Peyton       KMP_FSYNC_ACQUIRED(ftx);                                                 \
11747cc577a4SJonathan Peyton       rc = TRUE;                                                               \
11757cc577a4SJonathan Peyton     } else {                                                                   \
11767cc577a4SJonathan Peyton       rc = FALSE;                                                              \
11777cc577a4SJonathan Peyton     }                                                                          \
11787cc577a4SJonathan Peyton   }
11797cc577a4SJonathan Peyton 
11807cc577a4SJonathan Peyton // Fast-path release futex lock
11813041982dSJonathan Peyton #define KMP_RELEASE_FUTEX_LOCK(lock, gtid)                                     \
11823041982dSJonathan Peyton   {                                                                            \
11837cc577a4SJonathan Peyton     kmp_futex_lock_t *ftx = (kmp_futex_lock_t *)lock;                          \
11847cc577a4SJonathan Peyton     KMP_MB();                                                                  \
11857cc577a4SJonathan Peyton     KMP_FSYNC_RELEASING(ftx);                                                  \
11863041982dSJonathan Peyton     kmp_int32 poll_val =                                                       \
11873041982dSJonathan Peyton         KMP_XCHG_FIXED32(&(ftx->lk.poll), KMP_LOCK_FREE(futex));               \
11887cc577a4SJonathan Peyton     if (KMP_LOCK_STRIP(poll_val) & 1) {                                        \
11893041982dSJonathan Peyton       syscall(__NR_futex, &(ftx->lk.poll), FUTEX_WAKE,                         \
11903041982dSJonathan Peyton               KMP_LOCK_BUSY(1, futex), NULL, NULL, 0);                         \
11917cc577a4SJonathan Peyton     }                                                                          \
11927cc577a4SJonathan Peyton     KMP_MB();                                                                  \
1193e47d32f1SJonathan Peyton     KMP_YIELD_OVERSUB();                                                       \
11947cc577a4SJonathan Peyton   }
11957cc577a4SJonathan Peyton 
11967cc577a4SJonathan Peyton #endif // KMP_USE_FUTEX
11977cc577a4SJonathan Peyton 
11987cc577a4SJonathan Peyton #else // KMP_USE_DYNAMIC_LOCK
11997cc577a4SJonathan Peyton 
__kmp_get_critical_section_ptr(kmp_critical_name * crit,ident_t const * loc,kmp_int32 gtid)12003041982dSJonathan Peyton static kmp_user_lock_p __kmp_get_critical_section_ptr(kmp_critical_name *crit,
12013041982dSJonathan Peyton                                                       ident_t const *loc,
12023041982dSJonathan Peyton                                                       kmp_int32 gtid) {
12037cc577a4SJonathan Peyton   kmp_user_lock_p *lck_pp = (kmp_user_lock_p *)crit;
12047cc577a4SJonathan Peyton 
12053041982dSJonathan Peyton   // Because of the double-check, the following load doesn't need to be volatile
12067cc577a4SJonathan Peyton   kmp_user_lock_p lck = (kmp_user_lock_p)TCR_PTR(*lck_pp);
12077cc577a4SJonathan Peyton 
12087cc577a4SJonathan Peyton   if (lck == NULL) {
12097cc577a4SJonathan Peyton     void *idx;
12107cc577a4SJonathan Peyton 
12117cc577a4SJonathan Peyton     // Allocate & initialize the lock.
12123041982dSJonathan Peyton     // Remember alloc'ed locks in table in order to free them in __kmp_cleanup()
12137cc577a4SJonathan Peyton     lck = __kmp_user_lock_allocate(&idx, gtid, kmp_lf_critical_section);
12147cc577a4SJonathan Peyton     __kmp_init_user_lock_with_checks(lck);
12157cc577a4SJonathan Peyton     __kmp_set_user_lock_location(lck, loc);
12167cc577a4SJonathan Peyton #if USE_ITT_BUILD
12177cc577a4SJonathan Peyton     __kmp_itt_critical_creating(lck);
12183041982dSJonathan Peyton // __kmp_itt_critical_creating() should be called *before* the first usage
12193041982dSJonathan Peyton // of underlying lock. It is the only place where we can guarantee it. There
12203041982dSJonathan Peyton // are chances the lock will destroyed with no usage, but it is not a
12213041982dSJonathan Peyton // problem, because this is not real event seen by user but rather setting
12223041982dSJonathan Peyton // name for object (lock). See more details in kmp_itt.h.
12237cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
12247cc577a4SJonathan Peyton 
12253041982dSJonathan Peyton     // Use a cmpxchg instruction to slam the start of the critical section with
12263041982dSJonathan Peyton     // the lock pointer.  If another thread beat us to it, deallocate the lock,
12273041982dSJonathan Peyton     // and use the lock that the other thread allocated.
12287cc577a4SJonathan Peyton     int status = KMP_COMPARE_AND_STORE_PTR(lck_pp, 0, lck);
12297cc577a4SJonathan Peyton 
12307cc577a4SJonathan Peyton     if (status == 0) {
12317cc577a4SJonathan Peyton // Deallocate the lock and reload the value.
12327cc577a4SJonathan Peyton #if USE_ITT_BUILD
12337cc577a4SJonathan Peyton       __kmp_itt_critical_destroyed(lck);
12343041982dSJonathan Peyton // Let ITT know the lock is destroyed and the same memory location may be reused
12353041982dSJonathan Peyton // for another purpose.
12367cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
12377cc577a4SJonathan Peyton       __kmp_destroy_user_lock_with_checks(lck);
12387cc577a4SJonathan Peyton       __kmp_user_lock_free(&idx, gtid, lck);
12397cc577a4SJonathan Peyton       lck = (kmp_user_lock_p)TCR_PTR(*lck_pp);
12407cc577a4SJonathan Peyton       KMP_DEBUG_ASSERT(lck != NULL);
12417cc577a4SJonathan Peyton     }
12427cc577a4SJonathan Peyton   }
12437cc577a4SJonathan Peyton   return lck;
12447cc577a4SJonathan Peyton }
12457cc577a4SJonathan Peyton 
12467cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
12477cc577a4SJonathan Peyton 
12487cc577a4SJonathan Peyton /*!
12497cc577a4SJonathan Peyton @ingroup WORK_SHARING
12507cc577a4SJonathan Peyton @param loc  source location information.
12517cc577a4SJonathan Peyton @param global_tid  global thread number.
12523041982dSJonathan Peyton @param crit identity of the critical section. This could be a pointer to a lock
12533041982dSJonathan Peyton associated with the critical section, or some other suitably unique value.
12547cc577a4SJonathan Peyton 
12557cc577a4SJonathan Peyton Enter code protected by a `critical` construct.
12567cc577a4SJonathan Peyton This function blocks until the executing thread can enter the critical section.
12577cc577a4SJonathan Peyton */
__kmpc_critical(ident_t * loc,kmp_int32 global_tid,kmp_critical_name * crit)12583041982dSJonathan Peyton void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
12593041982dSJonathan Peyton                      kmp_critical_name *crit) {
12607cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
126182e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
126282e94a59SJoachim Protze   OMPT_STORE_RETURN_ADDRESS(global_tid);
126382e94a59SJoachim Protze #endif // OMPT_SUPPORT
12647cc577a4SJonathan Peyton   __kmpc_critical_with_hint(loc, global_tid, crit, omp_lock_hint_none);
12657cc577a4SJonathan Peyton #else
12667cc577a4SJonathan Peyton   KMP_COUNT_BLOCK(OMP_CRITICAL);
126782e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
12680e0d6cddSJoachim Protze   ompt_state_t prev_state = ompt_state_undefined;
126982e94a59SJoachim Protze   ompt_thread_info_t ti;
127082e94a59SJoachim Protze #endif
12717cc577a4SJonathan Peyton   kmp_user_lock_p lck;
12727cc577a4SJonathan Peyton 
12737cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_critical: called T#%d\n", global_tid));
1274787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
12757cc577a4SJonathan Peyton 
12767cc577a4SJonathan Peyton   // TODO: add THR_OVHD_STATE
12777cc577a4SJonathan Peyton 
1278f0682ac4SJonathan Peyton   KMP_PUSH_PARTITIONED_TIMER(OMP_critical_wait);
12797cc577a4SJonathan Peyton   KMP_CHECK_USER_LOCK_INIT();
12807cc577a4SJonathan Peyton 
12813041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
12823041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) <= OMP_CRITICAL_SIZE)) {
12837cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)crit;
12847cc577a4SJonathan Peyton   }
12857cc577a4SJonathan Peyton #if KMP_USE_FUTEX
12863041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
12873041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) <= OMP_CRITICAL_SIZE)) {
12887cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)crit;
12897cc577a4SJonathan Peyton   }
12907cc577a4SJonathan Peyton #endif
12917cc577a4SJonathan Peyton   else { // ticket, queuing or drdpa
12927cc577a4SJonathan Peyton     lck = __kmp_get_critical_section_ptr(crit, loc, global_tid);
12937cc577a4SJonathan Peyton   }
12947cc577a4SJonathan Peyton 
12957cc577a4SJonathan Peyton   if (__kmp_env_consistency_check)
12967cc577a4SJonathan Peyton     __kmp_push_sync(global_tid, ct_critical, loc, lck);
12977cc577a4SJonathan Peyton 
12983041982dSJonathan Peyton     // since the critical directive binds to all threads, not just the current
12993041982dSJonathan Peyton     // team we have to check this even if we are in a serialized team.
13003041982dSJonathan Peyton     // also, even if we are the uber thread, we still have to conduct the lock,
13013041982dSJonathan Peyton     // as we have to contend with sibling threads.
13027cc577a4SJonathan Peyton 
13037cc577a4SJonathan Peyton #if USE_ITT_BUILD
13047cc577a4SJonathan Peyton   __kmp_itt_critical_acquiring(lck);
13057cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
130682e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
130782e94a59SJoachim Protze   OMPT_STORE_RETURN_ADDRESS(gtid);
130882e94a59SJoachim Protze   void *codeptr_ra = NULL;
130982e94a59SJoachim Protze   if (ompt_enabled.enabled) {
131082e94a59SJoachim Protze     ti = __kmp_threads[global_tid]->th.ompt_thread_info;
131182e94a59SJoachim Protze     /* OMPT state update */
131282e94a59SJoachim Protze     prev_state = ti.state;
13134109d560SJoachim Protze     ti.wait_id = (ompt_wait_id_t)(uintptr_t)lck;
13140e0d6cddSJoachim Protze     ti.state = ompt_state_wait_critical;
131582e94a59SJoachim Protze 
131682e94a59SJoachim Protze     /* OMPT event callback */
131782e94a59SJoachim Protze     codeptr_ra = OMPT_LOAD_RETURN_ADDRESS(gtid);
131882e94a59SJoachim Protze     if (ompt_enabled.ompt_callback_mutex_acquire) {
131982e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)(
132082e94a59SJoachim Protze           ompt_mutex_critical, omp_lock_hint_none, __ompt_get_mutex_impl_type(),
13214109d560SJoachim Protze           (ompt_wait_id_t)(uintptr_t)lck, codeptr_ra);
132282e94a59SJoachim Protze     }
132382e94a59SJoachim Protze   }
132482e94a59SJoachim Protze #endif
13253041982dSJonathan Peyton   // Value of 'crit' should be good for using as a critical_id of the critical
13263041982dSJonathan Peyton   // section directive.
13277cc577a4SJonathan Peyton   __kmp_acquire_user_lock_with_checks(lck, global_tid);
13287cc577a4SJonathan Peyton 
13297cc577a4SJonathan Peyton #if USE_ITT_BUILD
13307cc577a4SJonathan Peyton   __kmp_itt_critical_acquired(lck);
13317cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
133282e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
133382e94a59SJoachim Protze   if (ompt_enabled.enabled) {
133482e94a59SJoachim Protze     /* OMPT state update */
133582e94a59SJoachim Protze     ti.state = prev_state;
133682e94a59SJoachim Protze     ti.wait_id = 0;
133782e94a59SJoachim Protze 
133882e94a59SJoachim Protze     /* OMPT event callback */
133982e94a59SJoachim Protze     if (ompt_enabled.ompt_callback_mutex_acquired) {
134082e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)(
13414109d560SJoachim Protze           ompt_mutex_critical, (ompt_wait_id_t)(uintptr_t)lck, codeptr_ra);
134282e94a59SJoachim Protze     }
134382e94a59SJoachim Protze   }
134482e94a59SJoachim Protze #endif
1345f0682ac4SJonathan Peyton   KMP_POP_PARTITIONED_TIMER();
13467cc577a4SJonathan Peyton 
1347f0682ac4SJonathan Peyton   KMP_PUSH_PARTITIONED_TIMER(OMP_critical);
13487cc577a4SJonathan Peyton   KA_TRACE(15, ("__kmpc_critical: done T#%d\n", global_tid));
13497cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
13507cc577a4SJonathan Peyton }
13517cc577a4SJonathan Peyton 
13527cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
13537cc577a4SJonathan Peyton 
13547cc577a4SJonathan Peyton // Converts the given hint to an internal lock implementation
__kmp_map_hint_to_lock(uintptr_t hint)13553041982dSJonathan Peyton static __forceinline kmp_dyna_lockseq_t __kmp_map_hint_to_lock(uintptr_t hint) {
13567cc577a4SJonathan Peyton #if KMP_USE_TSX
13577cc577a4SJonathan Peyton #define KMP_TSX_LOCK(seq) lockseq_##seq
13587cc577a4SJonathan Peyton #else
13597cc577a4SJonathan Peyton #define KMP_TSX_LOCK(seq) __kmp_user_lock_seq
13607cc577a4SJonathan Peyton #endif
13617cc577a4SJonathan Peyton 
13627cc577a4SJonathan Peyton #if KMP_ARCH_X86 || KMP_ARCH_X86_64
1363343b9e85SPeyton, Jonathan L #define KMP_CPUINFO_RTM (__kmp_cpuinfo.flags.rtm)
13647cc577a4SJonathan Peyton #else
13657cc577a4SJonathan Peyton #define KMP_CPUINFO_RTM 0
13667cc577a4SJonathan Peyton #endif
13677cc577a4SJonathan Peyton 
13687cc577a4SJonathan Peyton   // Hints that do not require further logic
13697cc577a4SJonathan Peyton   if (hint & kmp_lock_hint_hle)
13707cc577a4SJonathan Peyton     return KMP_TSX_LOCK(hle);
13717cc577a4SJonathan Peyton   if (hint & kmp_lock_hint_rtm)
1372c3b5009aSHansang Bae     return KMP_CPUINFO_RTM ? KMP_TSX_LOCK(rtm_queuing) : __kmp_user_lock_seq;
13737cc577a4SJonathan Peyton   if (hint & kmp_lock_hint_adaptive)
13747cc577a4SJonathan Peyton     return KMP_CPUINFO_RTM ? KMP_TSX_LOCK(adaptive) : __kmp_user_lock_seq;
13757cc577a4SJonathan Peyton 
13767cc577a4SJonathan Peyton   // Rule out conflicting hints first by returning the default lock
13777cc577a4SJonathan Peyton   if ((hint & omp_lock_hint_contended) && (hint & omp_lock_hint_uncontended))
13787cc577a4SJonathan Peyton     return __kmp_user_lock_seq;
13793041982dSJonathan Peyton   if ((hint & omp_lock_hint_speculative) &&
13803041982dSJonathan Peyton       (hint & omp_lock_hint_nonspeculative))
13817cc577a4SJonathan Peyton     return __kmp_user_lock_seq;
13827cc577a4SJonathan Peyton 
13837cc577a4SJonathan Peyton   // Do not even consider speculation when it appears to be contended
13847cc577a4SJonathan Peyton   if (hint & omp_lock_hint_contended)
13857cc577a4SJonathan Peyton     return lockseq_queuing;
13867cc577a4SJonathan Peyton 
13877cc577a4SJonathan Peyton   // Uncontended lock without speculation
13887cc577a4SJonathan Peyton   if ((hint & omp_lock_hint_uncontended) && !(hint & omp_lock_hint_speculative))
13897cc577a4SJonathan Peyton     return lockseq_tas;
13907cc577a4SJonathan Peyton 
1391c3b5009aSHansang Bae   // Use RTM lock for speculation
13927cc577a4SJonathan Peyton   if (hint & omp_lock_hint_speculative)
1393c3b5009aSHansang Bae     return KMP_CPUINFO_RTM ? KMP_TSX_LOCK(rtm_spin) : __kmp_user_lock_seq;
13947cc577a4SJonathan Peyton 
13957cc577a4SJonathan Peyton   return __kmp_user_lock_seq;
13967cc577a4SJonathan Peyton }
13977cc577a4SJonathan Peyton 
139882e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
1399baad3f60SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
14001b2bd268SJoachim Protze static kmp_mutex_impl_t
__ompt_get_mutex_impl_type(void * user_lock,kmp_indirect_lock_t * ilock=0)140182e94a59SJoachim Protze __ompt_get_mutex_impl_type(void *user_lock, kmp_indirect_lock_t *ilock = 0) {
140282e94a59SJoachim Protze   if (user_lock) {
140382e94a59SJoachim Protze     switch (KMP_EXTRACT_D_TAG(user_lock)) {
140482e94a59SJoachim Protze     case 0:
140582e94a59SJoachim Protze       break;
140682e94a59SJoachim Protze #if KMP_USE_FUTEX
140782e94a59SJoachim Protze     case locktag_futex:
14081b2bd268SJoachim Protze       return kmp_mutex_impl_queuing;
140982e94a59SJoachim Protze #endif
141082e94a59SJoachim Protze     case locktag_tas:
14111b2bd268SJoachim Protze       return kmp_mutex_impl_spin;
141282e94a59SJoachim Protze #if KMP_USE_TSX
141382e94a59SJoachim Protze     case locktag_hle:
1414c3b5009aSHansang Bae     case locktag_rtm_spin:
14151b2bd268SJoachim Protze       return kmp_mutex_impl_speculative;
141682e94a59SJoachim Protze #endif
141782e94a59SJoachim Protze     default:
14182b46d30fSJoachim Protze       return kmp_mutex_impl_none;
141982e94a59SJoachim Protze     }
142082e94a59SJoachim Protze     ilock = KMP_LOOKUP_I_LOCK(user_lock);
142182e94a59SJoachim Protze   }
142282e94a59SJoachim Protze   KMP_ASSERT(ilock);
142382e94a59SJoachim Protze   switch (ilock->type) {
142482e94a59SJoachim Protze #if KMP_USE_TSX
142582e94a59SJoachim Protze   case locktag_adaptive:
1426c3b5009aSHansang Bae   case locktag_rtm_queuing:
14271b2bd268SJoachim Protze     return kmp_mutex_impl_speculative;
142882e94a59SJoachim Protze #endif
142982e94a59SJoachim Protze   case locktag_nested_tas:
14301b2bd268SJoachim Protze     return kmp_mutex_impl_spin;
143182e94a59SJoachim Protze #if KMP_USE_FUTEX
143282e94a59SJoachim Protze   case locktag_nested_futex:
143382e94a59SJoachim Protze #endif
143482e94a59SJoachim Protze   case locktag_ticket:
143582e94a59SJoachim Protze   case locktag_queuing:
143682e94a59SJoachim Protze   case locktag_drdpa:
143782e94a59SJoachim Protze   case locktag_nested_ticket:
143882e94a59SJoachim Protze   case locktag_nested_queuing:
143982e94a59SJoachim Protze   case locktag_nested_drdpa:
14401b2bd268SJoachim Protze     return kmp_mutex_impl_queuing;
144182e94a59SJoachim Protze   default:
14422b46d30fSJoachim Protze     return kmp_mutex_impl_none;
144382e94a59SJoachim Protze   }
144482e94a59SJoachim Protze }
1445baad3f60SJonathan Peyton #else
144682e94a59SJoachim Protze // For locks without dynamic binding
__ompt_get_mutex_impl_type()14471b2bd268SJoachim Protze static kmp_mutex_impl_t __ompt_get_mutex_impl_type() {
144882e94a59SJoachim Protze   switch (__kmp_user_lock_kind) {
144982e94a59SJoachim Protze   case lk_tas:
14501b2bd268SJoachim Protze     return kmp_mutex_impl_spin;
145182e94a59SJoachim Protze #if KMP_USE_FUTEX
145282e94a59SJoachim Protze   case lk_futex:
145382e94a59SJoachim Protze #endif
145482e94a59SJoachim Protze   case lk_ticket:
145582e94a59SJoachim Protze   case lk_queuing:
145682e94a59SJoachim Protze   case lk_drdpa:
14571b2bd268SJoachim Protze     return kmp_mutex_impl_queuing;
145882e94a59SJoachim Protze #if KMP_USE_TSX
145982e94a59SJoachim Protze   case lk_hle:
1460c3b5009aSHansang Bae   case lk_rtm_queuing:
1461c3b5009aSHansang Bae   case lk_rtm_spin:
146282e94a59SJoachim Protze   case lk_adaptive:
14631b2bd268SJoachim Protze     return kmp_mutex_impl_speculative;
146482e94a59SJoachim Protze #endif
146582e94a59SJoachim Protze   default:
14662b46d30fSJoachim Protze     return kmp_mutex_impl_none;
146782e94a59SJoachim Protze   }
146882e94a59SJoachim Protze }
1469baad3f60SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
1470baad3f60SJonathan Peyton #endif // OMPT_SUPPORT && OMPT_OPTIONAL
147182e94a59SJoachim Protze 
14727cc577a4SJonathan Peyton /*!
14737cc577a4SJonathan Peyton @ingroup WORK_SHARING
14747cc577a4SJonathan Peyton @param loc  source location information.
14757cc577a4SJonathan Peyton @param global_tid  global thread number.
14763041982dSJonathan Peyton @param crit identity of the critical section. This could be a pointer to a lock
14773041982dSJonathan Peyton associated with the critical section, or some other suitably unique value.
14787cc577a4SJonathan Peyton @param hint the lock hint.
14797cc577a4SJonathan Peyton 
14803041982dSJonathan Peyton Enter code protected by a `critical` construct with a hint. The hint value is
14813041982dSJonathan Peyton used to suggest a lock implementation. This function blocks until the executing
14823041982dSJonathan Peyton thread can enter the critical section unless the hint suggests use of
14837cc577a4SJonathan Peyton speculative execution and the hardware supports it.
14847cc577a4SJonathan Peyton */
__kmpc_critical_with_hint(ident_t * loc,kmp_int32 global_tid,kmp_critical_name * crit,uint32_t hint)14853041982dSJonathan Peyton void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1486a2f6eff4SJonathan Peyton                                kmp_critical_name *crit, uint32_t hint) {
14877cc577a4SJonathan Peyton   KMP_COUNT_BLOCK(OMP_CRITICAL);
14887cc577a4SJonathan Peyton   kmp_user_lock_p lck;
148982e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
14900e0d6cddSJoachim Protze   ompt_state_t prev_state = ompt_state_undefined;
149182e94a59SJoachim Protze   ompt_thread_info_t ti;
149282e94a59SJoachim Protze   // This is the case, if called from __kmpc_critical:
149382e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(global_tid);
149482e94a59SJoachim Protze   if (!codeptr)
149582e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
149682e94a59SJoachim Protze #endif
14977cc577a4SJonathan Peyton 
14987cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_critical: called T#%d\n", global_tid));
1499787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
15007cc577a4SJonathan Peyton 
15017cc577a4SJonathan Peyton   kmp_dyna_lock_t *lk = (kmp_dyna_lock_t *)crit;
15027cc577a4SJonathan Peyton   // Check if it is initialized.
1503f0682ac4SJonathan Peyton   KMP_PUSH_PARTITIONED_TIMER(OMP_critical_wait);
150495cefacfSHansang Bae   kmp_dyna_lockseq_t lockseq = __kmp_map_hint_to_lock(hint);
15057cc577a4SJonathan Peyton   if (*lk == 0) {
150695cefacfSHansang Bae     if (KMP_IS_D_LOCK(lockseq)) {
15073041982dSJonathan Peyton       KMP_COMPARE_AND_STORE_ACQ32((volatile kmp_int32 *)crit, 0,
150895cefacfSHansang Bae                                   KMP_GET_D_TAG(lockseq));
15097cc577a4SJonathan Peyton     } else {
151095cefacfSHansang Bae       __kmp_init_indirect_csptr(crit, loc, global_tid, KMP_GET_I_TAG(lockseq));
15117cc577a4SJonathan Peyton     }
15127cc577a4SJonathan Peyton   }
15133041982dSJonathan Peyton   // Branch for accessing the actual lock object and set operation. This
15143041982dSJonathan Peyton   // branching is inevitable since this lock initialization does not follow the
15153041982dSJonathan Peyton   // normal dispatch path (lock table is not used).
15167cc577a4SJonathan Peyton   if (KMP_EXTRACT_D_TAG(lk) != 0) {
15177cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)lk;
15187cc577a4SJonathan Peyton     if (__kmp_env_consistency_check) {
15193041982dSJonathan Peyton       __kmp_push_sync(global_tid, ct_critical, loc, lck,
15203041982dSJonathan Peyton                       __kmp_map_hint_to_lock(hint));
15217cc577a4SJonathan Peyton     }
15227cc577a4SJonathan Peyton #if USE_ITT_BUILD
15237cc577a4SJonathan Peyton     __kmp_itt_critical_acquiring(lck);
15247cc577a4SJonathan Peyton #endif
152582e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
152682e94a59SJoachim Protze     if (ompt_enabled.enabled) {
152782e94a59SJoachim Protze       ti = __kmp_threads[global_tid]->th.ompt_thread_info;
152882e94a59SJoachim Protze       /* OMPT state update */
152982e94a59SJoachim Protze       prev_state = ti.state;
15304109d560SJoachim Protze       ti.wait_id = (ompt_wait_id_t)(uintptr_t)lck;
15310e0d6cddSJoachim Protze       ti.state = ompt_state_wait_critical;
153282e94a59SJoachim Protze 
153382e94a59SJoachim Protze       /* OMPT event callback */
153482e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_mutex_acquire) {
153582e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)(
153682e94a59SJoachim Protze             ompt_mutex_critical, (unsigned int)hint,
15374109d560SJoachim Protze             __ompt_get_mutex_impl_type(crit), (ompt_wait_id_t)(uintptr_t)lck,
15384109d560SJoachim Protze             codeptr);
153982e94a59SJoachim Protze       }
154082e94a59SJoachim Protze     }
154182e94a59SJoachim Protze #endif
15427cc577a4SJonathan Peyton #if KMP_USE_INLINED_TAS
154395cefacfSHansang Bae     if (lockseq == lockseq_tas && !__kmp_env_consistency_check) {
15447cc577a4SJonathan Peyton       KMP_ACQUIRE_TAS_LOCK(lck, global_tid);
15457cc577a4SJonathan Peyton     } else
15467cc577a4SJonathan Peyton #elif KMP_USE_INLINED_FUTEX
154795cefacfSHansang Bae     if (lockseq == lockseq_futex && !__kmp_env_consistency_check) {
15487cc577a4SJonathan Peyton       KMP_ACQUIRE_FUTEX_LOCK(lck, global_tid);
15497cc577a4SJonathan Peyton     } else
15507cc577a4SJonathan Peyton #endif
15517cc577a4SJonathan Peyton     {
15527cc577a4SJonathan Peyton       KMP_D_LOCK_FUNC(lk, set)(lk, global_tid);
15537cc577a4SJonathan Peyton     }
15547cc577a4SJonathan Peyton   } else {
15557cc577a4SJonathan Peyton     kmp_indirect_lock_t *ilk = *((kmp_indirect_lock_t **)lk);
15567cc577a4SJonathan Peyton     lck = ilk->lock;
15577cc577a4SJonathan Peyton     if (__kmp_env_consistency_check) {
15583041982dSJonathan Peyton       __kmp_push_sync(global_tid, ct_critical, loc, lck,
15593041982dSJonathan Peyton                       __kmp_map_hint_to_lock(hint));
15607cc577a4SJonathan Peyton     }
15617cc577a4SJonathan Peyton #if USE_ITT_BUILD
15627cc577a4SJonathan Peyton     __kmp_itt_critical_acquiring(lck);
15637cc577a4SJonathan Peyton #endif
156482e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
156582e94a59SJoachim Protze     if (ompt_enabled.enabled) {
156682e94a59SJoachim Protze       ti = __kmp_threads[global_tid]->th.ompt_thread_info;
156782e94a59SJoachim Protze       /* OMPT state update */
156882e94a59SJoachim Protze       prev_state = ti.state;
15694109d560SJoachim Protze       ti.wait_id = (ompt_wait_id_t)(uintptr_t)lck;
15700e0d6cddSJoachim Protze       ti.state = ompt_state_wait_critical;
157182e94a59SJoachim Protze 
157282e94a59SJoachim Protze       /* OMPT event callback */
157382e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_mutex_acquire) {
157482e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)(
157582e94a59SJoachim Protze             ompt_mutex_critical, (unsigned int)hint,
15764109d560SJoachim Protze             __ompt_get_mutex_impl_type(0, ilk), (ompt_wait_id_t)(uintptr_t)lck,
15774109d560SJoachim Protze             codeptr);
157882e94a59SJoachim Protze       }
157982e94a59SJoachim Protze     }
158082e94a59SJoachim Protze #endif
15817cc577a4SJonathan Peyton     KMP_I_LOCK_FUNC(ilk, set)(lck, global_tid);
15827cc577a4SJonathan Peyton   }
1583f0682ac4SJonathan Peyton   KMP_POP_PARTITIONED_TIMER();
15847cc577a4SJonathan Peyton 
15857cc577a4SJonathan Peyton #if USE_ITT_BUILD
15867cc577a4SJonathan Peyton   __kmp_itt_critical_acquired(lck);
15877cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
158882e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
158982e94a59SJoachim Protze   if (ompt_enabled.enabled) {
159082e94a59SJoachim Protze     /* OMPT state update */
159182e94a59SJoachim Protze     ti.state = prev_state;
159282e94a59SJoachim Protze     ti.wait_id = 0;
159382e94a59SJoachim Protze 
159482e94a59SJoachim Protze     /* OMPT event callback */
159582e94a59SJoachim Protze     if (ompt_enabled.ompt_callback_mutex_acquired) {
159682e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)(
15974109d560SJoachim Protze           ompt_mutex_critical, (ompt_wait_id_t)(uintptr_t)lck, codeptr);
159882e94a59SJoachim Protze     }
159982e94a59SJoachim Protze   }
160082e94a59SJoachim Protze #endif
16017cc577a4SJonathan Peyton 
16027cc577a4SJonathan Peyton   KMP_PUSH_PARTITIONED_TIMER(OMP_critical);
16037cc577a4SJonathan Peyton   KA_TRACE(15, ("__kmpc_critical: done T#%d\n", global_tid));
16047cc577a4SJonathan Peyton } // __kmpc_critical_with_hint
16057cc577a4SJonathan Peyton 
16067cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
16077cc577a4SJonathan Peyton 
16087cc577a4SJonathan Peyton /*!
16097cc577a4SJonathan Peyton @ingroup WORK_SHARING
16107cc577a4SJonathan Peyton @param loc  source location information.
16117cc577a4SJonathan Peyton @param global_tid  global thread number .
16123041982dSJonathan Peyton @param crit identity of the critical section. This could be a pointer to a lock
16133041982dSJonathan Peyton associated with the critical section, or some other suitably unique value.
16147cc577a4SJonathan Peyton 
16157cc577a4SJonathan Peyton Leave a critical section, releasing any lock that was held during its execution.
16167cc577a4SJonathan Peyton */
__kmpc_end_critical(ident_t * loc,kmp_int32 global_tid,kmp_critical_name * crit)16173041982dSJonathan Peyton void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
16183041982dSJonathan Peyton                          kmp_critical_name *crit) {
16197cc577a4SJonathan Peyton   kmp_user_lock_p lck;
16207cc577a4SJonathan Peyton 
16217cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_end_critical: called T#%d\n", global_tid));
16227cc577a4SJonathan Peyton 
16237cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
162495cefacfSHansang Bae   int locktag = KMP_EXTRACT_D_TAG(crit);
162595cefacfSHansang Bae   if (locktag) {
16267cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)crit;
16277cc577a4SJonathan Peyton     KMP_ASSERT(lck != NULL);
16287cc577a4SJonathan Peyton     if (__kmp_env_consistency_check) {
16297cc577a4SJonathan Peyton       __kmp_pop_sync(global_tid, ct_critical, loc);
16307cc577a4SJonathan Peyton     }
16317cc577a4SJonathan Peyton #if USE_ITT_BUILD
16327cc577a4SJonathan Peyton     __kmp_itt_critical_releasing(lck);
16337cc577a4SJonathan Peyton #endif
16347cc577a4SJonathan Peyton #if KMP_USE_INLINED_TAS
163595cefacfSHansang Bae     if (locktag == locktag_tas && !__kmp_env_consistency_check) {
16367cc577a4SJonathan Peyton       KMP_RELEASE_TAS_LOCK(lck, global_tid);
16377cc577a4SJonathan Peyton     } else
16387cc577a4SJonathan Peyton #elif KMP_USE_INLINED_FUTEX
163995cefacfSHansang Bae     if (locktag == locktag_futex && !__kmp_env_consistency_check) {
16407cc577a4SJonathan Peyton       KMP_RELEASE_FUTEX_LOCK(lck, global_tid);
16417cc577a4SJonathan Peyton     } else
16427cc577a4SJonathan Peyton #endif
16437cc577a4SJonathan Peyton     {
16447cc577a4SJonathan Peyton       KMP_D_LOCK_FUNC(lck, unset)((kmp_dyna_lock_t *)lck, global_tid);
16457cc577a4SJonathan Peyton     }
16467cc577a4SJonathan Peyton   } else {
16473041982dSJonathan Peyton     kmp_indirect_lock_t *ilk =
16483041982dSJonathan Peyton         (kmp_indirect_lock_t *)TCR_PTR(*((kmp_indirect_lock_t **)crit));
16497cc577a4SJonathan Peyton     KMP_ASSERT(ilk != NULL);
16507cc577a4SJonathan Peyton     lck = ilk->lock;
16517cc577a4SJonathan Peyton     if (__kmp_env_consistency_check) {
16527cc577a4SJonathan Peyton       __kmp_pop_sync(global_tid, ct_critical, loc);
16537cc577a4SJonathan Peyton     }
16547cc577a4SJonathan Peyton #if USE_ITT_BUILD
16557cc577a4SJonathan Peyton     __kmp_itt_critical_releasing(lck);
16567cc577a4SJonathan Peyton #endif
16577cc577a4SJonathan Peyton     KMP_I_LOCK_FUNC(ilk, unset)(lck, global_tid);
16587cc577a4SJonathan Peyton   }
16597cc577a4SJonathan Peyton 
16607cc577a4SJonathan Peyton #else // KMP_USE_DYNAMIC_LOCK
16617cc577a4SJonathan Peyton 
16623041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
16633041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) <= OMP_CRITICAL_SIZE)) {
16647cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)crit;
16657cc577a4SJonathan Peyton   }
16667cc577a4SJonathan Peyton #if KMP_USE_FUTEX
16673041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
16683041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) <= OMP_CRITICAL_SIZE)) {
16697cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)crit;
16707cc577a4SJonathan Peyton   }
16717cc577a4SJonathan Peyton #endif
16727cc577a4SJonathan Peyton   else { // ticket, queuing or drdpa
16737cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)TCR_PTR(*((kmp_user_lock_p *)crit));
16747cc577a4SJonathan Peyton   }
16757cc577a4SJonathan Peyton 
16767cc577a4SJonathan Peyton   KMP_ASSERT(lck != NULL);
16777cc577a4SJonathan Peyton 
16787cc577a4SJonathan Peyton   if (__kmp_env_consistency_check)
16797cc577a4SJonathan Peyton     __kmp_pop_sync(global_tid, ct_critical, loc);
16807cc577a4SJonathan Peyton 
16817cc577a4SJonathan Peyton #if USE_ITT_BUILD
16827cc577a4SJonathan Peyton   __kmp_itt_critical_releasing(lck);
16837cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
16843041982dSJonathan Peyton   // Value of 'crit' should be good for using as a critical_id of the critical
16853041982dSJonathan Peyton   // section directive.
16867cc577a4SJonathan Peyton   __kmp_release_user_lock_with_checks(lck, global_tid);
16877cc577a4SJonathan Peyton 
168882e94a59SJoachim Protze #endif // KMP_USE_DYNAMIC_LOCK
168982e94a59SJoachim Protze 
169082e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
169182e94a59SJoachim Protze   /* OMPT release event triggers after lock is released; place here to trigger
169282e94a59SJoachim Protze    * for all #if branches */
169382e94a59SJoachim Protze   OMPT_STORE_RETURN_ADDRESS(global_tid);
169482e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_mutex_released) {
169582e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_mutex_released)(
16964109d560SJoachim Protze         ompt_mutex_critical, (ompt_wait_id_t)(uintptr_t)lck,
16974109d560SJoachim Protze         OMPT_LOAD_RETURN_ADDRESS(0));
16987cc577a4SJonathan Peyton   }
16997cc577a4SJonathan Peyton #endif
17007cc577a4SJonathan Peyton 
17017cc577a4SJonathan Peyton   KMP_POP_PARTITIONED_TIMER();
17027cc577a4SJonathan Peyton   KA_TRACE(15, ("__kmpc_end_critical: done T#%d\n", global_tid));
17037cc577a4SJonathan Peyton }
17047cc577a4SJonathan Peyton 
17057cc577a4SJonathan Peyton /*!
17067cc577a4SJonathan Peyton @ingroup SYNCHRONIZATION
17077cc577a4SJonathan Peyton @param loc source location information
17087cc577a4SJonathan Peyton @param global_tid thread id.
17097cc577a4SJonathan Peyton @return one if the thread should execute the master block, zero otherwise
17107cc577a4SJonathan Peyton 
17113041982dSJonathan Peyton Start execution of a combined barrier and master. The barrier is executed inside
17123041982dSJonathan Peyton this function.
17137cc577a4SJonathan Peyton */
__kmpc_barrier_master(ident_t * loc,kmp_int32 global_tid)17143041982dSJonathan Peyton kmp_int32 __kmpc_barrier_master(ident_t *loc, kmp_int32 global_tid) {
17157cc577a4SJonathan Peyton   int status;
17167cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_barrier_master: called T#%d\n", global_tid));
1717787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
17187cc577a4SJonathan Peyton 
17197cc577a4SJonathan Peyton   if (!TCR_4(__kmp_init_parallel))
17207cc577a4SJonathan Peyton     __kmp_parallel_initialize();
17217cc577a4SJonathan Peyton 
17229b8bb323SJonathan Peyton   __kmp_resume_if_soft_paused();
17239b8bb323SJonathan Peyton 
17247cc577a4SJonathan Peyton   if (__kmp_env_consistency_check)
17257cc577a4SJonathan Peyton     __kmp_check_barrier(global_tid, ct_barrier, loc);
17267cc577a4SJonathan Peyton 
172782e94a59SJoachim Protze #if OMPT_SUPPORT
17280e0d6cddSJoachim Protze   ompt_frame_t *ompt_frame;
172982e94a59SJoachim Protze   if (ompt_enabled.enabled) {
173082e94a59SJoachim Protze     __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL);
17310e0d6cddSJoachim Protze     if (ompt_frame->enter_frame.ptr == NULL)
17320e0d6cddSJoachim Protze       ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
173382e94a59SJoachim Protze   }
17346d3b8166SJoachim Protze   OMPT_STORE_RETURN_ADDRESS(global_tid);
173582e94a59SJoachim Protze #endif
17367cc577a4SJonathan Peyton #if USE_ITT_NOTIFY
17377cc577a4SJonathan Peyton   __kmp_threads[global_tid]->th.th_ident = loc;
17387cc577a4SJonathan Peyton #endif
17397cc577a4SJonathan Peyton   status = __kmp_barrier(bs_plain_barrier, global_tid, TRUE, 0, NULL, NULL);
174082e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
174182e94a59SJoachim Protze   if (ompt_enabled.enabled) {
17420e0d6cddSJoachim Protze     ompt_frame->enter_frame = ompt_data_none;
174382e94a59SJoachim Protze   }
174482e94a59SJoachim Protze #endif
17457cc577a4SJonathan Peyton 
17467cc577a4SJonathan Peyton   return (status != 0) ? 0 : 1;
17477cc577a4SJonathan Peyton }
17487cc577a4SJonathan Peyton 
17497cc577a4SJonathan Peyton /*!
17507cc577a4SJonathan Peyton @ingroup SYNCHRONIZATION
17517cc577a4SJonathan Peyton @param loc source location information
17527cc577a4SJonathan Peyton @param global_tid thread id.
17537cc577a4SJonathan Peyton 
17547cc577a4SJonathan Peyton Complete the execution of a combined barrier and master. This function should
17557cc577a4SJonathan Peyton only be called at the completion of the <tt>master</tt> code. Other threads will
17567cc577a4SJonathan Peyton still be waiting at the barrier and this call releases them.
17577cc577a4SJonathan Peyton */
__kmpc_end_barrier_master(ident_t * loc,kmp_int32 global_tid)17583041982dSJonathan Peyton void __kmpc_end_barrier_master(ident_t *loc, kmp_int32 global_tid) {
17597cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_end_barrier_master: called T#%d\n", global_tid));
1760787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
17617cc577a4SJonathan Peyton   __kmp_end_split_barrier(bs_plain_barrier, global_tid);
17627cc577a4SJonathan Peyton }
17637cc577a4SJonathan Peyton 
17647cc577a4SJonathan Peyton /*!
17657cc577a4SJonathan Peyton @ingroup SYNCHRONIZATION
17667cc577a4SJonathan Peyton @param loc source location information
17677cc577a4SJonathan Peyton @param global_tid thread id.
17687cc577a4SJonathan Peyton @return one if the thread should execute the master block, zero otherwise
17697cc577a4SJonathan Peyton 
17707cc577a4SJonathan Peyton Start execution of a combined barrier and master(nowait) construct.
17717cc577a4SJonathan Peyton The barrier is executed inside this function.
17727cc577a4SJonathan Peyton There is no equivalent "end" function, since the
17737cc577a4SJonathan Peyton */
__kmpc_barrier_master_nowait(ident_t * loc,kmp_int32 global_tid)17743041982dSJonathan Peyton kmp_int32 __kmpc_barrier_master_nowait(ident_t *loc, kmp_int32 global_tid) {
17757cc577a4SJonathan Peyton   kmp_int32 ret;
17767cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_barrier_master_nowait: called T#%d\n", global_tid));
1777787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
17787cc577a4SJonathan Peyton 
17797cc577a4SJonathan Peyton   if (!TCR_4(__kmp_init_parallel))
17807cc577a4SJonathan Peyton     __kmp_parallel_initialize();
17817cc577a4SJonathan Peyton 
17829b8bb323SJonathan Peyton   __kmp_resume_if_soft_paused();
17839b8bb323SJonathan Peyton 
17847cc577a4SJonathan Peyton   if (__kmp_env_consistency_check) {
17857cc577a4SJonathan Peyton     if (loc == 0) {
17867cc577a4SJonathan Peyton       KMP_WARNING(ConstructIdentInvalid); // ??? What does it mean for the user?
17877cc577a4SJonathan Peyton     }
17887cc577a4SJonathan Peyton     __kmp_check_barrier(global_tid, ct_barrier, loc);
17897cc577a4SJonathan Peyton   }
17907cc577a4SJonathan Peyton 
179182e94a59SJoachim Protze #if OMPT_SUPPORT
17920e0d6cddSJoachim Protze   ompt_frame_t *ompt_frame;
179382e94a59SJoachim Protze   if (ompt_enabled.enabled) {
179482e94a59SJoachim Protze     __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL);
17950e0d6cddSJoachim Protze     if (ompt_frame->enter_frame.ptr == NULL)
17960e0d6cddSJoachim Protze       ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
179782e94a59SJoachim Protze   }
17986d3b8166SJoachim Protze   OMPT_STORE_RETURN_ADDRESS(global_tid);
179982e94a59SJoachim Protze #endif
18007cc577a4SJonathan Peyton #if USE_ITT_NOTIFY
18017cc577a4SJonathan Peyton   __kmp_threads[global_tid]->th.th_ident = loc;
18027cc577a4SJonathan Peyton #endif
18037cc577a4SJonathan Peyton   __kmp_barrier(bs_plain_barrier, global_tid, FALSE, 0, NULL, NULL);
180482e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
180582e94a59SJoachim Protze   if (ompt_enabled.enabled) {
18060e0d6cddSJoachim Protze     ompt_frame->enter_frame = ompt_data_none;
180782e94a59SJoachim Protze   }
180882e94a59SJoachim Protze #endif
18097cc577a4SJonathan Peyton 
18107cc577a4SJonathan Peyton   ret = __kmpc_master(loc, global_tid);
18117cc577a4SJonathan Peyton 
18127cc577a4SJonathan Peyton   if (__kmp_env_consistency_check) {
18137cc577a4SJonathan Peyton     /*  there's no __kmpc_end_master called; so the (stats) */
18147cc577a4SJonathan Peyton     /*  actions of __kmpc_end_master are done here          */
18157cc577a4SJonathan Peyton     if (ret) {
18167cc577a4SJonathan Peyton       /* only one thread should do the pop since only */
18177cc577a4SJonathan Peyton       /* one did the push (see __kmpc_master())       */
18187cc577a4SJonathan Peyton       __kmp_pop_sync(global_tid, ct_master, loc);
18197cc577a4SJonathan Peyton     }
18207cc577a4SJonathan Peyton   }
18217cc577a4SJonathan Peyton 
18227cc577a4SJonathan Peyton   return (ret);
18237cc577a4SJonathan Peyton }
18247cc577a4SJonathan Peyton 
18257cc577a4SJonathan Peyton /* The BARRIER for a SINGLE process section is always explicit   */
18267cc577a4SJonathan Peyton /*!
18277cc577a4SJonathan Peyton @ingroup WORK_SHARING
18287cc577a4SJonathan Peyton @param loc  source location information
18297cc577a4SJonathan Peyton @param global_tid  global thread number
18307cc577a4SJonathan Peyton @return One if this thread should execute the single construct, zero otherwise.
18317cc577a4SJonathan Peyton 
18327cc577a4SJonathan Peyton Test whether to execute a <tt>single</tt> construct.
18333041982dSJonathan Peyton There are no implicit barriers in the two "single" calls, rather the compiler
18343041982dSJonathan Peyton should introduce an explicit barrier if it is required.
18357cc577a4SJonathan Peyton */
18367cc577a4SJonathan Peyton 
__kmpc_single(ident_t * loc,kmp_int32 global_tid)18373041982dSJonathan Peyton kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid) {
1838787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
18397cc577a4SJonathan Peyton   kmp_int32 rc = __kmp_enter_single(global_tid, loc, TRUE);
18407cc577a4SJonathan Peyton 
18417cc577a4SJonathan Peyton   if (rc) {
18427cc577a4SJonathan Peyton     // We are going to execute the single statement, so we should count it.
18437cc577a4SJonathan Peyton     KMP_COUNT_BLOCK(OMP_SINGLE);
18447cc577a4SJonathan Peyton     KMP_PUSH_PARTITIONED_TIMER(OMP_single);
18457cc577a4SJonathan Peyton   }
18467cc577a4SJonathan Peyton 
184782e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
18487cc577a4SJonathan Peyton   kmp_info_t *this_thr = __kmp_threads[global_tid];
18497cc577a4SJonathan Peyton   kmp_team_t *team = this_thr->th.th_team;
18507cc577a4SJonathan Peyton   int tid = __kmp_tid_from_gtid(global_tid);
18517cc577a4SJonathan Peyton 
185282e94a59SJoachim Protze   if (ompt_enabled.enabled) {
18537cc577a4SJonathan Peyton     if (rc) {
185482e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_work) {
185582e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_work)(
185682e94a59SJoachim Protze             ompt_work_single_executor, ompt_scope_begin,
185782e94a59SJoachim Protze             &(team->t.ompt_team_info.parallel_data),
185882e94a59SJoachim Protze             &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data),
185982e94a59SJoachim Protze             1, OMPT_GET_RETURN_ADDRESS(0));
18607cc577a4SJonathan Peyton       }
18617cc577a4SJonathan Peyton     } else {
186282e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_work) {
186382e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_work)(
186482e94a59SJoachim Protze             ompt_work_single_other, ompt_scope_begin,
186582e94a59SJoachim Protze             &(team->t.ompt_team_info.parallel_data),
186682e94a59SJoachim Protze             &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data),
186782e94a59SJoachim Protze             1, OMPT_GET_RETURN_ADDRESS(0));
186882e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_work)(
186982e94a59SJoachim Protze             ompt_work_single_other, ompt_scope_end,
187082e94a59SJoachim Protze             &(team->t.ompt_team_info.parallel_data),
187182e94a59SJoachim Protze             &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data),
187282e94a59SJoachim Protze             1, OMPT_GET_RETURN_ADDRESS(0));
18737cc577a4SJonathan Peyton       }
18747cc577a4SJonathan Peyton     }
18757cc577a4SJonathan Peyton   }
18767cc577a4SJonathan Peyton #endif
18777cc577a4SJonathan Peyton 
18787cc577a4SJonathan Peyton   return rc;
18797cc577a4SJonathan Peyton }
18807cc577a4SJonathan Peyton 
18817cc577a4SJonathan Peyton /*!
18827cc577a4SJonathan Peyton @ingroup WORK_SHARING
18837cc577a4SJonathan Peyton @param loc  source location information
18847cc577a4SJonathan Peyton @param global_tid  global thread number
18857cc577a4SJonathan Peyton 
18867cc577a4SJonathan Peyton Mark the end of a <tt>single</tt> construct.  This function should
18877cc577a4SJonathan Peyton only be called by the thread that executed the block of code protected
18887cc577a4SJonathan Peyton by the `single` construct.
18897cc577a4SJonathan Peyton */
__kmpc_end_single(ident_t * loc,kmp_int32 global_tid)18903041982dSJonathan Peyton void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid) {
1891787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
18927cc577a4SJonathan Peyton   __kmp_exit_single(global_tid);
18937cc577a4SJonathan Peyton   KMP_POP_PARTITIONED_TIMER();
18947cc577a4SJonathan Peyton 
189582e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
18967cc577a4SJonathan Peyton   kmp_info_t *this_thr = __kmp_threads[global_tid];
18977cc577a4SJonathan Peyton   kmp_team_t *team = this_thr->th.th_team;
18987cc577a4SJonathan Peyton   int tid = __kmp_tid_from_gtid(global_tid);
18997cc577a4SJonathan Peyton 
190082e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_work) {
190182e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_work)(
190282e94a59SJoachim Protze         ompt_work_single_executor, ompt_scope_end,
190382e94a59SJoachim Protze         &(team->t.ompt_team_info.parallel_data),
190482e94a59SJoachim Protze         &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data), 1,
190582e94a59SJoachim Protze         OMPT_GET_RETURN_ADDRESS(0));
19067cc577a4SJonathan Peyton   }
19077cc577a4SJonathan Peyton #endif
19087cc577a4SJonathan Peyton }
19097cc577a4SJonathan Peyton 
19107cc577a4SJonathan Peyton /*!
19117cc577a4SJonathan Peyton @ingroup WORK_SHARING
19127cc577a4SJonathan Peyton @param loc Source location
19137cc577a4SJonathan Peyton @param global_tid Global thread id
19147cc577a4SJonathan Peyton 
19157cc577a4SJonathan Peyton Mark the end of a statically scheduled loop.
19167cc577a4SJonathan Peyton */
__kmpc_for_static_fini(ident_t * loc,kmp_int32 global_tid)19173041982dSJonathan Peyton void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid) {
1918f0682ac4SJonathan Peyton   KMP_POP_PARTITIONED_TIMER();
19197cc577a4SJonathan Peyton   KE_TRACE(10, ("__kmpc_for_static_fini called T#%d\n", global_tid));
19207cc577a4SJonathan Peyton 
192182e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
192282e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_work) {
1923489cdb78SJoachim Protze     ompt_work_t ompt_work_type = ompt_work_loop;
19247cc577a4SJonathan Peyton     ompt_team_info_t *team_info = __ompt_get_teaminfo(0, NULL);
192582e94a59SJoachim Protze     ompt_task_info_t *task_info = __ompt_get_task_info_object(0);
192682e94a59SJoachim Protze     // Determine workshare type
192782e94a59SJoachim Protze     if (loc != NULL) {
192882e94a59SJoachim Protze       if ((loc->flags & KMP_IDENT_WORK_LOOP) != 0) {
192982e94a59SJoachim Protze         ompt_work_type = ompt_work_loop;
193082e94a59SJoachim Protze       } else if ((loc->flags & KMP_IDENT_WORK_SECTIONS) != 0) {
193182e94a59SJoachim Protze         ompt_work_type = ompt_work_sections;
193282e94a59SJoachim Protze       } else if ((loc->flags & KMP_IDENT_WORK_DISTRIBUTE) != 0) {
193382e94a59SJoachim Protze         ompt_work_type = ompt_work_distribute;
193482e94a59SJoachim Protze       } else {
193591732475SJoachim Protze         // use default set above.
193691732475SJoachim Protze         // a warning about this case is provided in __kmpc_for_static_init
193782e94a59SJoachim Protze       }
193882e94a59SJoachim Protze       KMP_DEBUG_ASSERT(ompt_work_type);
193982e94a59SJoachim Protze     }
194082e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_work)(
194182e94a59SJoachim Protze         ompt_work_type, ompt_scope_end, &(team_info->parallel_data),
194282e94a59SJoachim Protze         &(task_info->task_data), 0, OMPT_GET_RETURN_ADDRESS(0));
19437cc577a4SJonathan Peyton   }
19447cc577a4SJonathan Peyton #endif
19457cc577a4SJonathan Peyton   if (__kmp_env_consistency_check)
19467cc577a4SJonathan Peyton     __kmp_pop_workshare(global_tid, ct_pdo, loc);
19477cc577a4SJonathan Peyton }
19487cc577a4SJonathan Peyton 
19493041982dSJonathan Peyton // User routines which take C-style arguments (call by value)
19503041982dSJonathan Peyton // different from the Fortran equivalent routines
19517cc577a4SJonathan Peyton 
ompc_set_num_threads(int arg)19523041982dSJonathan Peyton void ompc_set_num_threads(int arg) {
19537cc577a4SJonathan Peyton   // !!!!! TODO: check the per-task binding
19547cc577a4SJonathan Peyton   __kmp_set_num_threads(arg, __kmp_entry_gtid());
19557cc577a4SJonathan Peyton }
19567cc577a4SJonathan Peyton 
ompc_set_dynamic(int flag)19573041982dSJonathan Peyton void ompc_set_dynamic(int flag) {
19587cc577a4SJonathan Peyton   kmp_info_t *thread;
19597cc577a4SJonathan Peyton 
19607cc577a4SJonathan Peyton   /* For the thread-private implementation of the internal controls */
19617cc577a4SJonathan Peyton   thread = __kmp_entry_thread();
19627cc577a4SJonathan Peyton 
19637cc577a4SJonathan Peyton   __kmp_save_internal_controls(thread);
19647cc577a4SJonathan Peyton 
19656b316febSTerry Wilmarth   set__dynamic(thread, flag ? true : false);
19667cc577a4SJonathan Peyton }
19677cc577a4SJonathan Peyton 
ompc_set_nested(int flag)19683041982dSJonathan Peyton void ompc_set_nested(int flag) {
19697cc577a4SJonathan Peyton   kmp_info_t *thread;
19707cc577a4SJonathan Peyton 
19717cc577a4SJonathan Peyton   /* For the thread-private internal controls implementation */
19727cc577a4SJonathan Peyton   thread = __kmp_entry_thread();
19737cc577a4SJonathan Peyton 
19747cc577a4SJonathan Peyton   __kmp_save_internal_controls(thread);
19757cc577a4SJonathan Peyton 
197676b45e87SJonathan Peyton   set__max_active_levels(thread, flag ? __kmp_dflt_max_active_levels : 1);
19777cc577a4SJonathan Peyton }
19787cc577a4SJonathan Peyton 
ompc_set_max_active_levels(int max_active_levels)19793041982dSJonathan Peyton void ompc_set_max_active_levels(int max_active_levels) {
19807cc577a4SJonathan Peyton   /* TO DO */
19817cc577a4SJonathan Peyton   /* we want per-task implementation of this internal control */
19827cc577a4SJonathan Peyton 
19837cc577a4SJonathan Peyton   /* For the per-thread internal controls implementation */
19847cc577a4SJonathan Peyton   __kmp_set_max_active_levels(__kmp_entry_gtid(), max_active_levels);
19857cc577a4SJonathan Peyton }
19867cc577a4SJonathan Peyton 
ompc_set_schedule(omp_sched_t kind,int modifier)19873041982dSJonathan Peyton void ompc_set_schedule(omp_sched_t kind, int modifier) {
19887cc577a4SJonathan Peyton   // !!!!! TODO: check the per-task binding
19897cc577a4SJonathan Peyton   __kmp_set_schedule(__kmp_entry_gtid(), (kmp_sched_t)kind, modifier);
19907cc577a4SJonathan Peyton }
19917cc577a4SJonathan Peyton 
ompc_get_ancestor_thread_num(int level)19923041982dSJonathan Peyton int ompc_get_ancestor_thread_num(int level) {
19937cc577a4SJonathan Peyton   return __kmp_get_ancestor_thread_num(__kmp_entry_gtid(), level);
19947cc577a4SJonathan Peyton }
19957cc577a4SJonathan Peyton 
ompc_get_team_size(int level)19963041982dSJonathan Peyton int ompc_get_team_size(int level) {
19977cc577a4SJonathan Peyton   return __kmp_get_team_size(__kmp_entry_gtid(), level);
19987cc577a4SJonathan Peyton }
19997cc577a4SJonathan Peyton 
20006d88e049SJonathan Peyton /* OpenMP 5.0 Affinity Format API */
KMP_EXPAND_NAME(ompc_set_affinity_format)200156da2824SPeyton, Jonathan L void KMP_EXPAND_NAME(ompc_set_affinity_format)(char const *format) {
20026d88e049SJonathan Peyton   if (!__kmp_init_serial) {
20036d88e049SJonathan Peyton     __kmp_serial_initialize();
20046d88e049SJonathan Peyton   }
20056d88e049SJonathan Peyton   __kmp_strncpy_truncate(__kmp_affinity_format, KMP_AFFINITY_FORMAT_SIZE,
20066d88e049SJonathan Peyton                          format, KMP_STRLEN(format) + 1);
20076d88e049SJonathan Peyton }
20086d88e049SJonathan Peyton 
KMP_EXPAND_NAME(ompc_get_affinity_format)200956da2824SPeyton, Jonathan L size_t KMP_EXPAND_NAME(ompc_get_affinity_format)(char *buffer, size_t size) {
20106d88e049SJonathan Peyton   size_t format_size;
20116d88e049SJonathan Peyton   if (!__kmp_init_serial) {
20126d88e049SJonathan Peyton     __kmp_serial_initialize();
20136d88e049SJonathan Peyton   }
20146d88e049SJonathan Peyton   format_size = KMP_STRLEN(__kmp_affinity_format);
20156d88e049SJonathan Peyton   if (buffer && size) {
20166d88e049SJonathan Peyton     __kmp_strncpy_truncate(buffer, size, __kmp_affinity_format,
20176d88e049SJonathan Peyton                            format_size + 1);
20186d88e049SJonathan Peyton   }
20196d88e049SJonathan Peyton   return format_size;
20206d88e049SJonathan Peyton }
20216d88e049SJonathan Peyton 
KMP_EXPAND_NAME(ompc_display_affinity)202256da2824SPeyton, Jonathan L void KMP_EXPAND_NAME(ompc_display_affinity)(char const *format) {
20236d88e049SJonathan Peyton   int gtid;
20246d88e049SJonathan Peyton   if (!TCR_4(__kmp_init_middle)) {
20256d88e049SJonathan Peyton     __kmp_middle_initialize();
20266d88e049SJonathan Peyton   }
20270ddde4d8SPeyton, Jonathan L   __kmp_assign_root_init_mask();
20286d88e049SJonathan Peyton   gtid = __kmp_get_gtid();
2029*17dcde5fSAndreyChurbanov #if KMP_AFFINITY_SUPPORTED
2030*17dcde5fSAndreyChurbanov   if (__kmp_threads[gtid]->th.th_team->t.t_level == 0 && __kmp_affin_reset) {
2031*17dcde5fSAndreyChurbanov     __kmp_reset_root_init_mask(gtid);
2032*17dcde5fSAndreyChurbanov   }
2033*17dcde5fSAndreyChurbanov #endif
20346d88e049SJonathan Peyton   __kmp_aux_display_affinity(gtid, format);
20356d88e049SJonathan Peyton }
20366d88e049SJonathan Peyton 
KMP_EXPAND_NAME(ompc_capture_affinity)203756da2824SPeyton, Jonathan L size_t KMP_EXPAND_NAME(ompc_capture_affinity)(char *buffer, size_t buf_size,
20386d88e049SJonathan Peyton                                               char const *format) {
20396d88e049SJonathan Peyton   int gtid;
20406d88e049SJonathan Peyton   size_t num_required;
20416d88e049SJonathan Peyton   kmp_str_buf_t capture_buf;
20426d88e049SJonathan Peyton   if (!TCR_4(__kmp_init_middle)) {
20436d88e049SJonathan Peyton     __kmp_middle_initialize();
20446d88e049SJonathan Peyton   }
20450ddde4d8SPeyton, Jonathan L   __kmp_assign_root_init_mask();
20466d88e049SJonathan Peyton   gtid = __kmp_get_gtid();
2047*17dcde5fSAndreyChurbanov #if KMP_AFFINITY_SUPPORTED
2048*17dcde5fSAndreyChurbanov   if (__kmp_threads[gtid]->th.th_team->t.t_level == 0 && __kmp_affin_reset) {
2049*17dcde5fSAndreyChurbanov     __kmp_reset_root_init_mask(gtid);
2050*17dcde5fSAndreyChurbanov   }
2051*17dcde5fSAndreyChurbanov #endif
20526d88e049SJonathan Peyton   __kmp_str_buf_init(&capture_buf);
20536d88e049SJonathan Peyton   num_required = __kmp_aux_capture_affinity(gtid, format, &capture_buf);
20546d88e049SJonathan Peyton   if (buffer && buf_size) {
20556d88e049SJonathan Peyton     __kmp_strncpy_truncate(buffer, buf_size, capture_buf.str,
20566d88e049SJonathan Peyton                            capture_buf.used + 1);
20576d88e049SJonathan Peyton   }
20586d88e049SJonathan Peyton   __kmp_str_buf_free(&capture_buf);
20596d88e049SJonathan Peyton   return num_required;
20606d88e049SJonathan Peyton }
20616d88e049SJonathan Peyton 
kmpc_set_stacksize(int arg)20623041982dSJonathan Peyton void kmpc_set_stacksize(int arg) {
20637cc577a4SJonathan Peyton   // __kmp_aux_set_stacksize initializes the library if needed
20647cc577a4SJonathan Peyton   __kmp_aux_set_stacksize(arg);
20657cc577a4SJonathan Peyton }
20667cc577a4SJonathan Peyton 
kmpc_set_stacksize_s(size_t arg)20673041982dSJonathan Peyton void kmpc_set_stacksize_s(size_t arg) {
20687cc577a4SJonathan Peyton   // __kmp_aux_set_stacksize initializes the library if needed
20697cc577a4SJonathan Peyton   __kmp_aux_set_stacksize(arg);
20707cc577a4SJonathan Peyton }
20717cc577a4SJonathan Peyton 
kmpc_set_blocktime(int arg)20723041982dSJonathan Peyton void kmpc_set_blocktime(int arg) {
20737cc577a4SJonathan Peyton   int gtid, tid;
20747cc577a4SJonathan Peyton   kmp_info_t *thread;
20757cc577a4SJonathan Peyton 
20767cc577a4SJonathan Peyton   gtid = __kmp_entry_gtid();
20777cc577a4SJonathan Peyton   tid = __kmp_tid_from_gtid(gtid);
20787cc577a4SJonathan Peyton   thread = __kmp_thread_from_gtid(gtid);
20797cc577a4SJonathan Peyton 
20807cc577a4SJonathan Peyton   __kmp_aux_set_blocktime(arg, thread, tid);
20817cc577a4SJonathan Peyton }
20827cc577a4SJonathan Peyton 
kmpc_set_library(int arg)20833041982dSJonathan Peyton void kmpc_set_library(int arg) {
20847cc577a4SJonathan Peyton   // __kmp_user_set_library initializes the library if needed
20857cc577a4SJonathan Peyton   __kmp_user_set_library((enum library_type)arg);
20867cc577a4SJonathan Peyton }
20877cc577a4SJonathan Peyton 
kmpc_set_defaults(char const * str)20883041982dSJonathan Peyton void kmpc_set_defaults(char const *str) {
20897cc577a4SJonathan Peyton   // __kmp_aux_set_defaults initializes the library if needed
20907cc577a4SJonathan Peyton   __kmp_aux_set_defaults(str, KMP_STRLEN(str));
20917cc577a4SJonathan Peyton }
20927cc577a4SJonathan Peyton 
kmpc_set_disp_num_buffers(int arg)20933041982dSJonathan Peyton void kmpc_set_disp_num_buffers(int arg) {
20947cc577a4SJonathan Peyton   // ignore after initialization because some teams have already
20957cc577a4SJonathan Peyton   // allocated dispatch buffers
20968c73be9dSPeyton, Jonathan L   if (__kmp_init_serial == FALSE && arg >= KMP_MIN_DISP_NUM_BUFF &&
20978c73be9dSPeyton, Jonathan L       arg <= KMP_MAX_DISP_NUM_BUFF) {
20987cc577a4SJonathan Peyton     __kmp_dispatch_num_buffers = arg;
20997cc577a4SJonathan Peyton   }
21008c73be9dSPeyton, Jonathan L }
21017cc577a4SJonathan Peyton 
kmpc_set_affinity_mask_proc(int proc,void ** mask)21023041982dSJonathan Peyton int kmpc_set_affinity_mask_proc(int proc, void **mask) {
21037cc577a4SJonathan Peyton #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
21047cc577a4SJonathan Peyton   return -1;
21057cc577a4SJonathan Peyton #else
21067cc577a4SJonathan Peyton   if (!TCR_4(__kmp_init_middle)) {
21077cc577a4SJonathan Peyton     __kmp_middle_initialize();
21087cc577a4SJonathan Peyton   }
21090ddde4d8SPeyton, Jonathan L   __kmp_assign_root_init_mask();
21107cc577a4SJonathan Peyton   return __kmp_aux_set_affinity_mask_proc(proc, mask);
21117cc577a4SJonathan Peyton #endif
21127cc577a4SJonathan Peyton }
21137cc577a4SJonathan Peyton 
kmpc_unset_affinity_mask_proc(int proc,void ** mask)21143041982dSJonathan Peyton int kmpc_unset_affinity_mask_proc(int proc, void **mask) {
21157cc577a4SJonathan Peyton #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
21167cc577a4SJonathan Peyton   return -1;
21177cc577a4SJonathan Peyton #else
21187cc577a4SJonathan Peyton   if (!TCR_4(__kmp_init_middle)) {
21197cc577a4SJonathan Peyton     __kmp_middle_initialize();
21207cc577a4SJonathan Peyton   }
21210ddde4d8SPeyton, Jonathan L   __kmp_assign_root_init_mask();
21227cc577a4SJonathan Peyton   return __kmp_aux_unset_affinity_mask_proc(proc, mask);
21237cc577a4SJonathan Peyton #endif
21247cc577a4SJonathan Peyton }
21257cc577a4SJonathan Peyton 
kmpc_get_affinity_mask_proc(int proc,void ** mask)21263041982dSJonathan Peyton int kmpc_get_affinity_mask_proc(int proc, void **mask) {
21277cc577a4SJonathan Peyton #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED
21287cc577a4SJonathan Peyton   return -1;
21297cc577a4SJonathan Peyton #else
21307cc577a4SJonathan Peyton   if (!TCR_4(__kmp_init_middle)) {
21317cc577a4SJonathan Peyton     __kmp_middle_initialize();
21327cc577a4SJonathan Peyton   }
21330ddde4d8SPeyton, Jonathan L   __kmp_assign_root_init_mask();
21347cc577a4SJonathan Peyton   return __kmp_aux_get_affinity_mask_proc(proc, mask);
21357cc577a4SJonathan Peyton #endif
21367cc577a4SJonathan Peyton }
21377cc577a4SJonathan Peyton 
21387cc577a4SJonathan Peyton /* -------------------------------------------------------------------------- */
21397cc577a4SJonathan Peyton /*!
21407cc577a4SJonathan Peyton @ingroup THREADPRIVATE
21417cc577a4SJonathan Peyton @param loc       source location information
21427cc577a4SJonathan Peyton @param gtid      global thread number
21437cc577a4SJonathan Peyton @param cpy_size  size of the cpy_data buffer
21447cc577a4SJonathan Peyton @param cpy_data  pointer to data to be copied
21457cc577a4SJonathan Peyton @param cpy_func  helper function to call for copying data
21467cc577a4SJonathan Peyton @param didit     flag variable: 1=single thread; 0=not single thread
21477cc577a4SJonathan Peyton 
21483041982dSJonathan Peyton __kmpc_copyprivate implements the interface for the private data broadcast
21493041982dSJonathan Peyton needed for the copyprivate clause associated with a single region in an
21503041982dSJonathan Peyton OpenMP<sup>*</sup> program (both C and Fortran).
21517cc577a4SJonathan Peyton All threads participating in the parallel region call this routine.
21523041982dSJonathan Peyton One of the threads (called the single thread) should have the <tt>didit</tt>
21533041982dSJonathan Peyton variable set to 1 and all other threads should have that variable set to 0.
21547cc577a4SJonathan Peyton All threads pass a pointer to a data buffer (cpy_data) that they have built.
21557cc577a4SJonathan Peyton 
21563041982dSJonathan Peyton The OpenMP specification forbids the use of nowait on the single region when a
21573041982dSJonathan Peyton copyprivate clause is present. However, @ref __kmpc_copyprivate implements a
21583041982dSJonathan Peyton barrier internally to avoid race conditions, so the code generation for the
21593041982dSJonathan Peyton single region should avoid generating a barrier after the call to @ref
21603041982dSJonathan Peyton __kmpc_copyprivate.
21617cc577a4SJonathan Peyton 
21627cc577a4SJonathan Peyton The <tt>gtid</tt> parameter is the global thread id for the current thread.
21637cc577a4SJonathan Peyton The <tt>loc</tt> parameter is a pointer to source location information.
21647cc577a4SJonathan Peyton 
21653041982dSJonathan Peyton Internal implementation: The single thread will first copy its descriptor
21663041982dSJonathan Peyton address (cpy_data) to a team-private location, then the other threads will each
21673041982dSJonathan Peyton call the function pointed to by the parameter cpy_func, which carries out the
21683041982dSJonathan Peyton copy by copying the data using the cpy_data buffer.
21697cc577a4SJonathan Peyton 
21703041982dSJonathan Peyton The cpy_func routine used for the copy and the contents of the data area defined
21713041982dSJonathan Peyton by cpy_data and cpy_size may be built in any fashion that will allow the copy
21723041982dSJonathan Peyton to be done. For instance, the cpy_data buffer can hold the actual data to be
21733041982dSJonathan Peyton copied or it may hold a list of pointers to the data. The cpy_func routine must
21743041982dSJonathan Peyton interpret the cpy_data buffer appropriately.
21757cc577a4SJonathan Peyton 
21767cc577a4SJonathan Peyton The interface to cpy_func is as follows:
21777cc577a4SJonathan Peyton @code
21787cc577a4SJonathan Peyton void cpy_func( void *destination, void *source )
21797cc577a4SJonathan Peyton @endcode
21807cc577a4SJonathan Peyton where void *destination is the cpy_data pointer for the thread being copied to
21817cc577a4SJonathan Peyton and void *source is the cpy_data pointer for the thread being copied from.
21827cc577a4SJonathan Peyton */
__kmpc_copyprivate(ident_t * loc,kmp_int32 gtid,size_t cpy_size,void * cpy_data,void (* cpy_func)(void *,void *),kmp_int32 didit)21833041982dSJonathan Peyton void __kmpc_copyprivate(ident_t *loc, kmp_int32 gtid, size_t cpy_size,
21843041982dSJonathan Peyton                         void *cpy_data, void (*cpy_func)(void *, void *),
21853041982dSJonathan Peyton                         kmp_int32 didit) {
21867cc577a4SJonathan Peyton   void **data_ptr;
21877cc577a4SJonathan Peyton   KC_TRACE(10, ("__kmpc_copyprivate: called T#%d\n", gtid));
2188787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(gtid);
21897cc577a4SJonathan Peyton 
21907cc577a4SJonathan Peyton   KMP_MB();
21917cc577a4SJonathan Peyton 
21927cc577a4SJonathan Peyton   data_ptr = &__kmp_team_from_gtid(gtid)->t.t_copypriv_data;
21937cc577a4SJonathan Peyton 
21947cc577a4SJonathan Peyton   if (__kmp_env_consistency_check) {
21957cc577a4SJonathan Peyton     if (loc == 0) {
21967cc577a4SJonathan Peyton       KMP_WARNING(ConstructIdentInvalid);
21977cc577a4SJonathan Peyton     }
21987cc577a4SJonathan Peyton   }
21997cc577a4SJonathan Peyton 
22003041982dSJonathan Peyton   // ToDo: Optimize the following two barriers into some kind of split barrier
22017cc577a4SJonathan Peyton 
22023041982dSJonathan Peyton   if (didit)
22033041982dSJonathan Peyton     *data_ptr = cpy_data;
22047cc577a4SJonathan Peyton 
220582e94a59SJoachim Protze #if OMPT_SUPPORT
22060e0d6cddSJoachim Protze   ompt_frame_t *ompt_frame;
220782e94a59SJoachim Protze   if (ompt_enabled.enabled) {
220882e94a59SJoachim Protze     __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL);
22090e0d6cddSJoachim Protze     if (ompt_frame->enter_frame.ptr == NULL)
22100e0d6cddSJoachim Protze       ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
221182e94a59SJoachim Protze   }
22126d3b8166SJoachim Protze   OMPT_STORE_RETURN_ADDRESS(gtid);
221382e94a59SJoachim Protze #endif
22147cc577a4SJonathan Peyton /* This barrier is not a barrier region boundary */
22157cc577a4SJonathan Peyton #if USE_ITT_NOTIFY
22167cc577a4SJonathan Peyton   __kmp_threads[gtid]->th.th_ident = loc;
22177cc577a4SJonathan Peyton #endif
22187cc577a4SJonathan Peyton   __kmp_barrier(bs_plain_barrier, gtid, FALSE, 0, NULL, NULL);
22197cc577a4SJonathan Peyton 
22203041982dSJonathan Peyton   if (!didit)
22213041982dSJonathan Peyton     (*cpy_func)(cpy_data, *data_ptr);
22227cc577a4SJonathan Peyton 
22233041982dSJonathan Peyton   // Consider next barrier a user-visible barrier for barrier region boundaries
22243041982dSJonathan Peyton   // Nesting checks are already handled by the single construct checks
22256d3b8166SJoachim Protze   {
222682e94a59SJoachim Protze #if OMPT_SUPPORT
222782e94a59SJoachim Protze     OMPT_STORE_RETURN_ADDRESS(gtid);
222882e94a59SJoachim Protze #endif
22297cc577a4SJonathan Peyton #if USE_ITT_NOTIFY
22303041982dSJonathan Peyton     __kmp_threads[gtid]->th.th_ident = loc; // TODO: check if it is needed (e.g.
22313041982dSJonathan Peyton // tasks can overwrite the location)
22327cc577a4SJonathan Peyton #endif
22337cc577a4SJonathan Peyton     __kmp_barrier(bs_plain_barrier, gtid, FALSE, 0, NULL, NULL);
223482e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
223582e94a59SJoachim Protze     if (ompt_enabled.enabled) {
22360e0d6cddSJoachim Protze       ompt_frame->enter_frame = ompt_data_none;
223782e94a59SJoachim Protze     }
223882e94a59SJoachim Protze #endif
22397cc577a4SJonathan Peyton   }
22406d3b8166SJoachim Protze }
22417cc577a4SJonathan Peyton 
22427cc577a4SJonathan Peyton /* --------------------------------------------------------------------------*/
224343d5c4d5SVadim Paretsky /*!
224443d5c4d5SVadim Paretsky @ingroup THREADPRIVATE
224543d5c4d5SVadim Paretsky @param loc       source location information
224643d5c4d5SVadim Paretsky @param gtid      global thread number
224743d5c4d5SVadim Paretsky @param cpy_data  pointer to the data to be saved/copied or 0
224843d5c4d5SVadim Paretsky @return          the saved pointer to the data
224943d5c4d5SVadim Paretsky 
225043d5c4d5SVadim Paretsky __kmpc_copyprivate_light is a lighter version of __kmpc_copyprivate:
225143d5c4d5SVadim Paretsky __kmpc_copyprivate_light only saves the pointer it's given (if it's not 0, so
225243d5c4d5SVadim Paretsky coming from single), and returns that pointer in all calls (for single thread
225343d5c4d5SVadim Paretsky it's not needed). This version doesn't do any actual data copying. Data copying
225443d5c4d5SVadim Paretsky has to be done somewhere else, e.g. inline in the generated code. Due to this,
225543d5c4d5SVadim Paretsky this function doesn't have any barrier at the end of the function, like
225643d5c4d5SVadim Paretsky __kmpc_copyprivate does, so generated code needs barrier after copying of all
225743d5c4d5SVadim Paretsky data was done.
225843d5c4d5SVadim Paretsky */
__kmpc_copyprivate_light(ident_t * loc,kmp_int32 gtid,void * cpy_data)225943d5c4d5SVadim Paretsky void *__kmpc_copyprivate_light(ident_t *loc, kmp_int32 gtid, void *cpy_data) {
226043d5c4d5SVadim Paretsky   void **data_ptr;
226143d5c4d5SVadim Paretsky 
226243d5c4d5SVadim Paretsky   KC_TRACE(10, ("__kmpc_copyprivate_light: called T#%d\n", gtid));
226343d5c4d5SVadim Paretsky 
226443d5c4d5SVadim Paretsky   KMP_MB();
226543d5c4d5SVadim Paretsky 
226643d5c4d5SVadim Paretsky   data_ptr = &__kmp_team_from_gtid(gtid)->t.t_copypriv_data;
226743d5c4d5SVadim Paretsky 
226843d5c4d5SVadim Paretsky   if (__kmp_env_consistency_check) {
226943d5c4d5SVadim Paretsky     if (loc == 0) {
227043d5c4d5SVadim Paretsky       KMP_WARNING(ConstructIdentInvalid);
227143d5c4d5SVadim Paretsky     }
227243d5c4d5SVadim Paretsky   }
227343d5c4d5SVadim Paretsky 
227443d5c4d5SVadim Paretsky   // ToDo: Optimize the following barrier
227543d5c4d5SVadim Paretsky 
227643d5c4d5SVadim Paretsky   if (cpy_data)
227743d5c4d5SVadim Paretsky     *data_ptr = cpy_data;
227843d5c4d5SVadim Paretsky 
227943d5c4d5SVadim Paretsky #if OMPT_SUPPORT
228043d5c4d5SVadim Paretsky   ompt_frame_t *ompt_frame;
228143d5c4d5SVadim Paretsky   if (ompt_enabled.enabled) {
228243d5c4d5SVadim Paretsky     __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL);
228343d5c4d5SVadim Paretsky     if (ompt_frame->enter_frame.ptr == NULL)
228443d5c4d5SVadim Paretsky       ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
228543d5c4d5SVadim Paretsky     OMPT_STORE_RETURN_ADDRESS(gtid);
228643d5c4d5SVadim Paretsky   }
228743d5c4d5SVadim Paretsky #endif
228843d5c4d5SVadim Paretsky /* This barrier is not a barrier region boundary */
228943d5c4d5SVadim Paretsky #if USE_ITT_NOTIFY
229043d5c4d5SVadim Paretsky   __kmp_threads[gtid]->th.th_ident = loc;
229143d5c4d5SVadim Paretsky #endif
229243d5c4d5SVadim Paretsky   __kmp_barrier(bs_plain_barrier, gtid, FALSE, 0, NULL, NULL);
229343d5c4d5SVadim Paretsky 
229443d5c4d5SVadim Paretsky   return *data_ptr;
229543d5c4d5SVadim Paretsky }
229643d5c4d5SVadim Paretsky 
229743d5c4d5SVadim Paretsky /* -------------------------------------------------------------------------- */
22987cc577a4SJonathan Peyton 
22997cc577a4SJonathan Peyton #define INIT_LOCK __kmp_init_user_lock_with_checks
23007cc577a4SJonathan Peyton #define INIT_NESTED_LOCK __kmp_init_nested_user_lock_with_checks
23017cc577a4SJonathan Peyton #define ACQUIRE_LOCK __kmp_acquire_user_lock_with_checks
23027cc577a4SJonathan Peyton #define ACQUIRE_LOCK_TIMED __kmp_acquire_user_lock_with_checks_timed
23037cc577a4SJonathan Peyton #define ACQUIRE_NESTED_LOCK __kmp_acquire_nested_user_lock_with_checks
23043041982dSJonathan Peyton #define ACQUIRE_NESTED_LOCK_TIMED                                              \
23053041982dSJonathan Peyton   __kmp_acquire_nested_user_lock_with_checks_timed
23067cc577a4SJonathan Peyton #define RELEASE_LOCK __kmp_release_user_lock_with_checks
23077cc577a4SJonathan Peyton #define RELEASE_NESTED_LOCK __kmp_release_nested_user_lock_with_checks
23087cc577a4SJonathan Peyton #define TEST_LOCK __kmp_test_user_lock_with_checks
23097cc577a4SJonathan Peyton #define TEST_NESTED_LOCK __kmp_test_nested_user_lock_with_checks
23107cc577a4SJonathan Peyton #define DESTROY_LOCK __kmp_destroy_user_lock_with_checks
23117cc577a4SJonathan Peyton #define DESTROY_NESTED_LOCK __kmp_destroy_nested_user_lock_with_checks
23127cc577a4SJonathan Peyton 
23133041982dSJonathan Peyton // TODO: Make check abort messages use location info & pass it into
23143041982dSJonathan Peyton // with_checks routines
23157cc577a4SJonathan Peyton 
23167cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
23177cc577a4SJonathan Peyton 
23187cc577a4SJonathan Peyton // internal lock initializer
__kmp_init_lock_with_hint(ident_t * loc,void ** lock,kmp_dyna_lockseq_t seq)23193041982dSJonathan Peyton static __forceinline void __kmp_init_lock_with_hint(ident_t *loc, void **lock,
23203041982dSJonathan Peyton                                                     kmp_dyna_lockseq_t seq) {
23217cc577a4SJonathan Peyton   if (KMP_IS_D_LOCK(seq)) {
23227cc577a4SJonathan Peyton     KMP_INIT_D_LOCK(lock, seq);
23237cc577a4SJonathan Peyton #if USE_ITT_BUILD
23247cc577a4SJonathan Peyton     __kmp_itt_lock_creating((kmp_user_lock_p)lock, NULL);
23257cc577a4SJonathan Peyton #endif
23267cc577a4SJonathan Peyton   } else {
23277cc577a4SJonathan Peyton     KMP_INIT_I_LOCK(lock, seq);
23287cc577a4SJonathan Peyton #if USE_ITT_BUILD
23297cc577a4SJonathan Peyton     kmp_indirect_lock_t *ilk = KMP_LOOKUP_I_LOCK(lock);
23307cc577a4SJonathan Peyton     __kmp_itt_lock_creating(ilk->lock, loc);
23317cc577a4SJonathan Peyton #endif
23327cc577a4SJonathan Peyton   }
23337cc577a4SJonathan Peyton }
23347cc577a4SJonathan Peyton 
23357cc577a4SJonathan Peyton // internal nest lock initializer
23367cc577a4SJonathan Peyton static __forceinline void
__kmp_init_nest_lock_with_hint(ident_t * loc,void ** lock,kmp_dyna_lockseq_t seq)23373041982dSJonathan Peyton __kmp_init_nest_lock_with_hint(ident_t *loc, void **lock,
23383041982dSJonathan Peyton                                kmp_dyna_lockseq_t seq) {
23397cc577a4SJonathan Peyton #if KMP_USE_TSX
23407cc577a4SJonathan Peyton   // Don't have nested lock implementation for speculative locks
2341c3b5009aSHansang Bae   if (seq == lockseq_hle || seq == lockseq_rtm_queuing ||
2342c3b5009aSHansang Bae       seq == lockseq_rtm_spin || seq == lockseq_adaptive)
23437cc577a4SJonathan Peyton     seq = __kmp_user_lock_seq;
23447cc577a4SJonathan Peyton #endif
23457cc577a4SJonathan Peyton   switch (seq) {
23467cc577a4SJonathan Peyton   case lockseq_tas:
23477cc577a4SJonathan Peyton     seq = lockseq_nested_tas;
23487cc577a4SJonathan Peyton     break;
23497cc577a4SJonathan Peyton #if KMP_USE_FUTEX
23507cc577a4SJonathan Peyton   case lockseq_futex:
23517cc577a4SJonathan Peyton     seq = lockseq_nested_futex;
23527cc577a4SJonathan Peyton     break;
23537cc577a4SJonathan Peyton #endif
23547cc577a4SJonathan Peyton   case lockseq_ticket:
23557cc577a4SJonathan Peyton     seq = lockseq_nested_ticket;
23567cc577a4SJonathan Peyton     break;
23577cc577a4SJonathan Peyton   case lockseq_queuing:
23587cc577a4SJonathan Peyton     seq = lockseq_nested_queuing;
23597cc577a4SJonathan Peyton     break;
23607cc577a4SJonathan Peyton   case lockseq_drdpa:
23617cc577a4SJonathan Peyton     seq = lockseq_nested_drdpa;
23627cc577a4SJonathan Peyton     break;
23637cc577a4SJonathan Peyton   default:
23647cc577a4SJonathan Peyton     seq = lockseq_nested_queuing;
23657cc577a4SJonathan Peyton   }
23667cc577a4SJonathan Peyton   KMP_INIT_I_LOCK(lock, seq);
23677cc577a4SJonathan Peyton #if USE_ITT_BUILD
23687cc577a4SJonathan Peyton   kmp_indirect_lock_t *ilk = KMP_LOOKUP_I_LOCK(lock);
23697cc577a4SJonathan Peyton   __kmp_itt_lock_creating(ilk->lock, loc);
23707cc577a4SJonathan Peyton #endif
23717cc577a4SJonathan Peyton }
23727cc577a4SJonathan Peyton 
23737cc577a4SJonathan Peyton /* initialize the lock with a hint */
__kmpc_init_lock_with_hint(ident_t * loc,kmp_int32 gtid,void ** user_lock,uintptr_t hint)23743041982dSJonathan Peyton void __kmpc_init_lock_with_hint(ident_t *loc, kmp_int32 gtid, void **user_lock,
23753041982dSJonathan Peyton                                 uintptr_t hint) {
23767cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(__kmp_init_serial);
23777cc577a4SJonathan Peyton   if (__kmp_env_consistency_check && user_lock == NULL) {
23787cc577a4SJonathan Peyton     KMP_FATAL(LockIsUninitialized, "omp_init_lock_with_hint");
23797cc577a4SJonathan Peyton   }
23807cc577a4SJonathan Peyton 
23817cc577a4SJonathan Peyton   __kmp_init_lock_with_hint(loc, user_lock, __kmp_map_hint_to_lock(hint));
238282e94a59SJoachim Protze 
238382e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
238482e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
238582e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
238682e94a59SJoachim Protze   if (!codeptr)
238782e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
238882e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_lock_init) {
238982e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_lock_init)(
239082e94a59SJoachim Protze         ompt_mutex_lock, (omp_lock_hint_t)hint,
23914109d560SJoachim Protze         __ompt_get_mutex_impl_type(user_lock),
23924109d560SJoachim Protze         (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
239382e94a59SJoachim Protze   }
239482e94a59SJoachim Protze #endif
23957cc577a4SJonathan Peyton }
23967cc577a4SJonathan Peyton 
23977cc577a4SJonathan Peyton /* initialize the lock with a hint */
__kmpc_init_nest_lock_with_hint(ident_t * loc,kmp_int32 gtid,void ** user_lock,uintptr_t hint)23983041982dSJonathan Peyton void __kmpc_init_nest_lock_with_hint(ident_t *loc, kmp_int32 gtid,
23993041982dSJonathan Peyton                                      void **user_lock, uintptr_t hint) {
24007cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(__kmp_init_serial);
24017cc577a4SJonathan Peyton   if (__kmp_env_consistency_check && user_lock == NULL) {
24027cc577a4SJonathan Peyton     KMP_FATAL(LockIsUninitialized, "omp_init_nest_lock_with_hint");
24037cc577a4SJonathan Peyton   }
24047cc577a4SJonathan Peyton 
24057cc577a4SJonathan Peyton   __kmp_init_nest_lock_with_hint(loc, user_lock, __kmp_map_hint_to_lock(hint));
240682e94a59SJoachim Protze 
240782e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
240882e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
240982e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
241082e94a59SJoachim Protze   if (!codeptr)
241182e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
241282e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_lock_init) {
241382e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_lock_init)(
241482e94a59SJoachim Protze         ompt_mutex_nest_lock, (omp_lock_hint_t)hint,
24154109d560SJoachim Protze         __ompt_get_mutex_impl_type(user_lock),
24164109d560SJoachim Protze         (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
241782e94a59SJoachim Protze   }
241882e94a59SJoachim Protze #endif
24197cc577a4SJonathan Peyton }
24207cc577a4SJonathan Peyton 
24217cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
24227cc577a4SJonathan Peyton 
24237cc577a4SJonathan Peyton /* initialize the lock */
__kmpc_init_lock(ident_t * loc,kmp_int32 gtid,void ** user_lock)24243041982dSJonathan Peyton void __kmpc_init_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) {
24257cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
24263041982dSJonathan Peyton 
24277cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(__kmp_init_serial);
24287cc577a4SJonathan Peyton   if (__kmp_env_consistency_check && user_lock == NULL) {
24297cc577a4SJonathan Peyton     KMP_FATAL(LockIsUninitialized, "omp_init_lock");
24307cc577a4SJonathan Peyton   }
24317cc577a4SJonathan Peyton   __kmp_init_lock_with_hint(loc, user_lock, __kmp_user_lock_seq);
24327cc577a4SJonathan Peyton 
243382e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
243482e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
243582e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
243682e94a59SJoachim Protze   if (!codeptr)
243782e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
243882e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_lock_init) {
243982e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_lock_init)(
244082e94a59SJoachim Protze         ompt_mutex_lock, omp_lock_hint_none,
24414109d560SJoachim Protze         __ompt_get_mutex_impl_type(user_lock),
24424109d560SJoachim Protze         (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
244382e94a59SJoachim Protze   }
244482e94a59SJoachim Protze #endif
244582e94a59SJoachim Protze 
24467cc577a4SJonathan Peyton #else // KMP_USE_DYNAMIC_LOCK
24477cc577a4SJonathan Peyton 
24487cc577a4SJonathan Peyton   static char const *const func = "omp_init_lock";
24497cc577a4SJonathan Peyton   kmp_user_lock_p lck;
24507cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(__kmp_init_serial);
24517cc577a4SJonathan Peyton 
24527cc577a4SJonathan Peyton   if (__kmp_env_consistency_check) {
24537cc577a4SJonathan Peyton     if (user_lock == NULL) {
24547cc577a4SJonathan Peyton       KMP_FATAL(LockIsUninitialized, func);
24557cc577a4SJonathan Peyton     }
24567cc577a4SJonathan Peyton   }
24577cc577a4SJonathan Peyton 
24587cc577a4SJonathan Peyton   KMP_CHECK_USER_LOCK_INIT();
24597cc577a4SJonathan Peyton 
24603041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
24613041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) <= OMP_LOCK_T_SIZE)) {
24627cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
24637cc577a4SJonathan Peyton   }
24647cc577a4SJonathan Peyton #if KMP_USE_FUTEX
24653041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
24663041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) <= OMP_LOCK_T_SIZE)) {
24677cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
24687cc577a4SJonathan Peyton   }
24697cc577a4SJonathan Peyton #endif
24707cc577a4SJonathan Peyton   else {
24717cc577a4SJonathan Peyton     lck = __kmp_user_lock_allocate(user_lock, gtid, 0);
24727cc577a4SJonathan Peyton   }
24737cc577a4SJonathan Peyton   INIT_LOCK(lck);
24747cc577a4SJonathan Peyton   __kmp_set_user_lock_location(lck, loc);
24757cc577a4SJonathan Peyton 
247682e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
247782e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
247882e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
247982e94a59SJoachim Protze   if (!codeptr)
248082e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
248182e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_lock_init) {
248282e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_lock_init)(
248382e94a59SJoachim Protze         ompt_mutex_lock, omp_lock_hint_none, __ompt_get_mutex_impl_type(),
24844109d560SJoachim Protze         (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
24857cc577a4SJonathan Peyton   }
24867cc577a4SJonathan Peyton #endif
24877cc577a4SJonathan Peyton 
24887cc577a4SJonathan Peyton #if USE_ITT_BUILD
24897cc577a4SJonathan Peyton   __kmp_itt_lock_creating(lck);
24907cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
24917cc577a4SJonathan Peyton 
24927cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
24937cc577a4SJonathan Peyton } // __kmpc_init_lock
24947cc577a4SJonathan Peyton 
24957cc577a4SJonathan Peyton /* initialize the lock */
__kmpc_init_nest_lock(ident_t * loc,kmp_int32 gtid,void ** user_lock)24963041982dSJonathan Peyton void __kmpc_init_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) {
24977cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
24987cc577a4SJonathan Peyton 
24997cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(__kmp_init_serial);
25007cc577a4SJonathan Peyton   if (__kmp_env_consistency_check && user_lock == NULL) {
25017cc577a4SJonathan Peyton     KMP_FATAL(LockIsUninitialized, "omp_init_nest_lock");
25027cc577a4SJonathan Peyton   }
25037cc577a4SJonathan Peyton   __kmp_init_nest_lock_with_hint(loc, user_lock, __kmp_user_lock_seq);
25047cc577a4SJonathan Peyton 
250582e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
250682e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
250782e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
250882e94a59SJoachim Protze   if (!codeptr)
250982e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
251082e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_lock_init) {
251182e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_lock_init)(
251282e94a59SJoachim Protze         ompt_mutex_nest_lock, omp_lock_hint_none,
25134109d560SJoachim Protze         __ompt_get_mutex_impl_type(user_lock),
25144109d560SJoachim Protze         (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
251582e94a59SJoachim Protze   }
251682e94a59SJoachim Protze #endif
251782e94a59SJoachim Protze 
25187cc577a4SJonathan Peyton #else // KMP_USE_DYNAMIC_LOCK
25197cc577a4SJonathan Peyton 
25207cc577a4SJonathan Peyton   static char const *const func = "omp_init_nest_lock";
25217cc577a4SJonathan Peyton   kmp_user_lock_p lck;
25227cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(__kmp_init_serial);
25237cc577a4SJonathan Peyton 
25247cc577a4SJonathan Peyton   if (__kmp_env_consistency_check) {
25257cc577a4SJonathan Peyton     if (user_lock == NULL) {
25267cc577a4SJonathan Peyton       KMP_FATAL(LockIsUninitialized, func);
25277cc577a4SJonathan Peyton     }
25287cc577a4SJonathan Peyton   }
25297cc577a4SJonathan Peyton 
25307cc577a4SJonathan Peyton   KMP_CHECK_USER_LOCK_INIT();
25317cc577a4SJonathan Peyton 
25323041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
25333041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) + sizeof(lck->tas.lk.depth_locked) <=
25343041982dSJonathan Peyton        OMP_NEST_LOCK_T_SIZE)) {
25357cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
25367cc577a4SJonathan Peyton   }
25377cc577a4SJonathan Peyton #if KMP_USE_FUTEX
25383041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
25393041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) + sizeof(lck->futex.lk.depth_locked) <=
25403041982dSJonathan Peyton             OMP_NEST_LOCK_T_SIZE)) {
25417cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
25427cc577a4SJonathan Peyton   }
25437cc577a4SJonathan Peyton #endif
25447cc577a4SJonathan Peyton   else {
25457cc577a4SJonathan Peyton     lck = __kmp_user_lock_allocate(user_lock, gtid, 0);
25467cc577a4SJonathan Peyton   }
25477cc577a4SJonathan Peyton 
25487cc577a4SJonathan Peyton   INIT_NESTED_LOCK(lck);
25497cc577a4SJonathan Peyton   __kmp_set_user_lock_location(lck, loc);
25507cc577a4SJonathan Peyton 
255182e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
255282e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
255382e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
255482e94a59SJoachim Protze   if (!codeptr)
255582e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
255682e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_lock_init) {
255782e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_lock_init)(
255882e94a59SJoachim Protze         ompt_mutex_nest_lock, omp_lock_hint_none, __ompt_get_mutex_impl_type(),
25594109d560SJoachim Protze         (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
25607cc577a4SJonathan Peyton   }
25617cc577a4SJonathan Peyton #endif
25627cc577a4SJonathan Peyton 
25637cc577a4SJonathan Peyton #if USE_ITT_BUILD
25647cc577a4SJonathan Peyton   __kmp_itt_lock_creating(lck);
25657cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
25667cc577a4SJonathan Peyton 
25677cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
25687cc577a4SJonathan Peyton } // __kmpc_init_nest_lock
25697cc577a4SJonathan Peyton 
__kmpc_destroy_lock(ident_t * loc,kmp_int32 gtid,void ** user_lock)25703041982dSJonathan Peyton void __kmpc_destroy_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) {
25717cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
25727cc577a4SJonathan Peyton 
25737cc577a4SJonathan Peyton #if USE_ITT_BUILD
25747cc577a4SJonathan Peyton   kmp_user_lock_p lck;
25757cc577a4SJonathan Peyton   if (KMP_EXTRACT_D_TAG(user_lock) == 0) {
25767cc577a4SJonathan Peyton     lck = ((kmp_indirect_lock_t *)KMP_LOOKUP_I_LOCK(user_lock))->lock;
25777cc577a4SJonathan Peyton   } else {
25787cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
25797cc577a4SJonathan Peyton   }
25807cc577a4SJonathan Peyton   __kmp_itt_lock_destroyed(lck);
25817cc577a4SJonathan Peyton #endif
258282e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
258382e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
258482e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
258582e94a59SJoachim Protze   if (!codeptr)
258682e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
258782e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_lock_destroy) {
258882e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_lock_destroy)(
25894109d560SJoachim Protze         ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
259082e94a59SJoachim Protze   }
259182e94a59SJoachim Protze #endif
25927cc577a4SJonathan Peyton   KMP_D_LOCK_FUNC(user_lock, destroy)((kmp_dyna_lock_t *)user_lock);
25937cc577a4SJonathan Peyton #else
25947cc577a4SJonathan Peyton   kmp_user_lock_p lck;
25957cc577a4SJonathan Peyton 
25963041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
25973041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) <= OMP_LOCK_T_SIZE)) {
25987cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
25997cc577a4SJonathan Peyton   }
26007cc577a4SJonathan Peyton #if KMP_USE_FUTEX
26013041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
26023041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) <= OMP_LOCK_T_SIZE)) {
26037cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
26047cc577a4SJonathan Peyton   }
26057cc577a4SJonathan Peyton #endif
26067cc577a4SJonathan Peyton   else {
26077cc577a4SJonathan Peyton     lck = __kmp_lookup_user_lock(user_lock, "omp_destroy_lock");
26087cc577a4SJonathan Peyton   }
26097cc577a4SJonathan Peyton 
261082e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
261182e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
261282e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
261382e94a59SJoachim Protze   if (!codeptr)
261482e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
261582e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_lock_destroy) {
261682e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_lock_destroy)(
26174109d560SJoachim Protze         ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
26187cc577a4SJonathan Peyton   }
26197cc577a4SJonathan Peyton #endif
26207cc577a4SJonathan Peyton 
26217cc577a4SJonathan Peyton #if USE_ITT_BUILD
26227cc577a4SJonathan Peyton   __kmp_itt_lock_destroyed(lck);
26237cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
26247cc577a4SJonathan Peyton   DESTROY_LOCK(lck);
26257cc577a4SJonathan Peyton 
26263041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
26273041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) <= OMP_LOCK_T_SIZE)) {
26287cc577a4SJonathan Peyton     ;
26297cc577a4SJonathan Peyton   }
26307cc577a4SJonathan Peyton #if KMP_USE_FUTEX
26313041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
26323041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) <= OMP_LOCK_T_SIZE)) {
26337cc577a4SJonathan Peyton     ;
26347cc577a4SJonathan Peyton   }
26357cc577a4SJonathan Peyton #endif
26367cc577a4SJonathan Peyton   else {
26377cc577a4SJonathan Peyton     __kmp_user_lock_free(user_lock, gtid, lck);
26387cc577a4SJonathan Peyton   }
26397cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
26407cc577a4SJonathan Peyton } // __kmpc_destroy_lock
26417cc577a4SJonathan Peyton 
26427cc577a4SJonathan Peyton /* destroy the lock */
__kmpc_destroy_nest_lock(ident_t * loc,kmp_int32 gtid,void ** user_lock)26433041982dSJonathan Peyton void __kmpc_destroy_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) {
26447cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
26457cc577a4SJonathan Peyton 
26467cc577a4SJonathan Peyton #if USE_ITT_BUILD
26477cc577a4SJonathan Peyton   kmp_indirect_lock_t *ilk = KMP_LOOKUP_I_LOCK(user_lock);
26487cc577a4SJonathan Peyton   __kmp_itt_lock_destroyed(ilk->lock);
26497cc577a4SJonathan Peyton #endif
265082e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
265182e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
265282e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
265382e94a59SJoachim Protze   if (!codeptr)
265482e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
265582e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_lock_destroy) {
265682e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_lock_destroy)(
26574109d560SJoachim Protze         ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
265882e94a59SJoachim Protze   }
265982e94a59SJoachim Protze #endif
26607cc577a4SJonathan Peyton   KMP_D_LOCK_FUNC(user_lock, destroy)((kmp_dyna_lock_t *)user_lock);
26617cc577a4SJonathan Peyton 
26627cc577a4SJonathan Peyton #else // KMP_USE_DYNAMIC_LOCK
26637cc577a4SJonathan Peyton 
26647cc577a4SJonathan Peyton   kmp_user_lock_p lck;
26657cc577a4SJonathan Peyton 
26663041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
26673041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) + sizeof(lck->tas.lk.depth_locked) <=
26683041982dSJonathan Peyton        OMP_NEST_LOCK_T_SIZE)) {
26697cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
26707cc577a4SJonathan Peyton   }
26717cc577a4SJonathan Peyton #if KMP_USE_FUTEX
26723041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
26733041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) + sizeof(lck->futex.lk.depth_locked) <=
26743041982dSJonathan Peyton             OMP_NEST_LOCK_T_SIZE)) {
26757cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
26767cc577a4SJonathan Peyton   }
26777cc577a4SJonathan Peyton #endif
26787cc577a4SJonathan Peyton   else {
26797cc577a4SJonathan Peyton     lck = __kmp_lookup_user_lock(user_lock, "omp_destroy_nest_lock");
26807cc577a4SJonathan Peyton   }
26817cc577a4SJonathan Peyton 
268282e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
268382e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
268482e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
268582e94a59SJoachim Protze   if (!codeptr)
268682e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
268782e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_lock_destroy) {
268882e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_lock_destroy)(
26894109d560SJoachim Protze         ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
26907cc577a4SJonathan Peyton   }
26917cc577a4SJonathan Peyton #endif
26927cc577a4SJonathan Peyton 
26937cc577a4SJonathan Peyton #if USE_ITT_BUILD
26947cc577a4SJonathan Peyton   __kmp_itt_lock_destroyed(lck);
26957cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
26967cc577a4SJonathan Peyton 
26977cc577a4SJonathan Peyton   DESTROY_NESTED_LOCK(lck);
26987cc577a4SJonathan Peyton 
26993041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
27003041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) + sizeof(lck->tas.lk.depth_locked) <=
27013041982dSJonathan Peyton        OMP_NEST_LOCK_T_SIZE)) {
27027cc577a4SJonathan Peyton     ;
27037cc577a4SJonathan Peyton   }
27047cc577a4SJonathan Peyton #if KMP_USE_FUTEX
27053041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
27063041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) + sizeof(lck->futex.lk.depth_locked) <=
27073041982dSJonathan Peyton             OMP_NEST_LOCK_T_SIZE)) {
27087cc577a4SJonathan Peyton     ;
27097cc577a4SJonathan Peyton   }
27107cc577a4SJonathan Peyton #endif
27117cc577a4SJonathan Peyton   else {
27127cc577a4SJonathan Peyton     __kmp_user_lock_free(user_lock, gtid, lck);
27137cc577a4SJonathan Peyton   }
27147cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
27157cc577a4SJonathan Peyton } // __kmpc_destroy_nest_lock
27167cc577a4SJonathan Peyton 
__kmpc_set_lock(ident_t * loc,kmp_int32 gtid,void ** user_lock)27173041982dSJonathan Peyton void __kmpc_set_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) {
27187cc577a4SJonathan Peyton   KMP_COUNT_BLOCK(OMP_set_lock);
27197cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
27207cc577a4SJonathan Peyton   int tag = KMP_EXTRACT_D_TAG(user_lock);
27217cc577a4SJonathan Peyton #if USE_ITT_BUILD
27223041982dSJonathan Peyton   __kmp_itt_lock_acquiring(
27233041982dSJonathan Peyton       (kmp_user_lock_p)
27243041982dSJonathan Peyton           user_lock); // itt function will get to the right lock object.
27257cc577a4SJonathan Peyton #endif
272682e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
272782e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
272882e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
272982e94a59SJoachim Protze   if (!codeptr)
273082e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
273182e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_mutex_acquire) {
273282e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)(
273382e94a59SJoachim Protze         ompt_mutex_lock, omp_lock_hint_none,
27344109d560SJoachim Protze         __ompt_get_mutex_impl_type(user_lock),
27354109d560SJoachim Protze         (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
273682e94a59SJoachim Protze   }
273782e94a59SJoachim Protze #endif
27387cc577a4SJonathan Peyton #if KMP_USE_INLINED_TAS
27397cc577a4SJonathan Peyton   if (tag == locktag_tas && !__kmp_env_consistency_check) {
27407cc577a4SJonathan Peyton     KMP_ACQUIRE_TAS_LOCK(user_lock, gtid);
27417cc577a4SJonathan Peyton   } else
27427cc577a4SJonathan Peyton #elif KMP_USE_INLINED_FUTEX
27437cc577a4SJonathan Peyton   if (tag == locktag_futex && !__kmp_env_consistency_check) {
27447cc577a4SJonathan Peyton     KMP_ACQUIRE_FUTEX_LOCK(user_lock, gtid);
27457cc577a4SJonathan Peyton   } else
27467cc577a4SJonathan Peyton #endif
27477cc577a4SJonathan Peyton   {
27487cc577a4SJonathan Peyton     __kmp_direct_set[tag]((kmp_dyna_lock_t *)user_lock, gtid);
27497cc577a4SJonathan Peyton   }
27507cc577a4SJonathan Peyton #if USE_ITT_BUILD
27517cc577a4SJonathan Peyton   __kmp_itt_lock_acquired((kmp_user_lock_p)user_lock);
27527cc577a4SJonathan Peyton #endif
275382e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
275482e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_mutex_acquired) {
275582e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)(
27564109d560SJoachim Protze         ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
275782e94a59SJoachim Protze   }
275882e94a59SJoachim Protze #endif
27597cc577a4SJonathan Peyton 
27607cc577a4SJonathan Peyton #else // KMP_USE_DYNAMIC_LOCK
27617cc577a4SJonathan Peyton 
27627cc577a4SJonathan Peyton   kmp_user_lock_p lck;
27637cc577a4SJonathan Peyton 
27643041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
27653041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) <= OMP_LOCK_T_SIZE)) {
27667cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
27677cc577a4SJonathan Peyton   }
27687cc577a4SJonathan Peyton #if KMP_USE_FUTEX
27693041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
27703041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) <= OMP_LOCK_T_SIZE)) {
27717cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
27727cc577a4SJonathan Peyton   }
27737cc577a4SJonathan Peyton #endif
27747cc577a4SJonathan Peyton   else {
27757cc577a4SJonathan Peyton     lck = __kmp_lookup_user_lock(user_lock, "omp_set_lock");
27767cc577a4SJonathan Peyton   }
27777cc577a4SJonathan Peyton 
27787cc577a4SJonathan Peyton #if USE_ITT_BUILD
27797cc577a4SJonathan Peyton   __kmp_itt_lock_acquiring(lck);
27807cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
278182e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
278282e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
278382e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
278482e94a59SJoachim Protze   if (!codeptr)
278582e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
278682e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_mutex_acquire) {
278782e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)(
278882e94a59SJoachim Protze         ompt_mutex_lock, omp_lock_hint_none, __ompt_get_mutex_impl_type(),
27894109d560SJoachim Protze         (ompt_wait_id_t)(uintptr_t)lck, codeptr);
279082e94a59SJoachim Protze   }
279182e94a59SJoachim Protze #endif
27927cc577a4SJonathan Peyton 
27937cc577a4SJonathan Peyton   ACQUIRE_LOCK(lck, gtid);
27947cc577a4SJonathan Peyton 
27957cc577a4SJonathan Peyton #if USE_ITT_BUILD
27967cc577a4SJonathan Peyton   __kmp_itt_lock_acquired(lck);
27977cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
27987cc577a4SJonathan Peyton 
279982e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
280082e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_mutex_acquired) {
280182e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)(
28024109d560SJoachim Protze         ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr);
28037cc577a4SJonathan Peyton   }
28047cc577a4SJonathan Peyton #endif
28057cc577a4SJonathan Peyton 
28067cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
28077cc577a4SJonathan Peyton }
28087cc577a4SJonathan Peyton 
__kmpc_set_nest_lock(ident_t * loc,kmp_int32 gtid,void ** user_lock)28093041982dSJonathan Peyton void __kmpc_set_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) {
28107cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
28117cc577a4SJonathan Peyton 
28127cc577a4SJonathan Peyton #if USE_ITT_BUILD
28137cc577a4SJonathan Peyton   __kmp_itt_lock_acquiring((kmp_user_lock_p)user_lock);
28147cc577a4SJonathan Peyton #endif
281582e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
281682e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
281782e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
281882e94a59SJoachim Protze   if (!codeptr)
281982e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
282082e94a59SJoachim Protze   if (ompt_enabled.enabled) {
282182e94a59SJoachim Protze     if (ompt_enabled.ompt_callback_mutex_acquire) {
282282e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)(
282382e94a59SJoachim Protze           ompt_mutex_nest_lock, omp_lock_hint_none,
28244109d560SJoachim Protze           __ompt_get_mutex_impl_type(user_lock),
28254109d560SJoachim Protze           (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
282682e94a59SJoachim Protze     }
282782e94a59SJoachim Protze   }
282882e94a59SJoachim Protze #endif
282982e94a59SJoachim Protze   int acquire_status =
28307cc577a4SJonathan Peyton       KMP_D_LOCK_FUNC(user_lock, set)((kmp_dyna_lock_t *)user_lock, gtid);
283115f5407dSGheorghe-Teodor Bercea   (void)acquire_status;
28327cc577a4SJonathan Peyton #if USE_ITT_BUILD
28337cc577a4SJonathan Peyton   __kmp_itt_lock_acquired((kmp_user_lock_p)user_lock);
28347cc577a4SJonathan Peyton #endif
28357cc577a4SJonathan Peyton 
283682e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
283782e94a59SJoachim Protze   if (ompt_enabled.enabled) {
283882e94a59SJoachim Protze     if (acquire_status == KMP_LOCK_ACQUIRED_FIRST) {
283982e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_mutex_acquired) {
284082e94a59SJoachim Protze         // lock_first
284182e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)(
28424109d560SJoachim Protze             ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock,
28434109d560SJoachim Protze             codeptr);
284482e94a59SJoachim Protze       }
284582e94a59SJoachim Protze     } else {
284682e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_nest_lock) {
284782e94a59SJoachim Protze         // lock_next
284882e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_nest_lock)(
28494109d560SJoachim Protze             ompt_scope_begin, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
285082e94a59SJoachim Protze       }
285182e94a59SJoachim Protze     }
28527cc577a4SJonathan Peyton   }
28537cc577a4SJonathan Peyton #endif
28547cc577a4SJonathan Peyton 
28557cc577a4SJonathan Peyton #else // KMP_USE_DYNAMIC_LOCK
28567cc577a4SJonathan Peyton   int acquire_status;
28577cc577a4SJonathan Peyton   kmp_user_lock_p lck;
28587cc577a4SJonathan Peyton 
28593041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
28603041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) + sizeof(lck->tas.lk.depth_locked) <=
28613041982dSJonathan Peyton        OMP_NEST_LOCK_T_SIZE)) {
28627cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
28637cc577a4SJonathan Peyton   }
28647cc577a4SJonathan Peyton #if KMP_USE_FUTEX
28653041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
28663041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) + sizeof(lck->futex.lk.depth_locked) <=
28673041982dSJonathan Peyton             OMP_NEST_LOCK_T_SIZE)) {
28687cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
28697cc577a4SJonathan Peyton   }
28707cc577a4SJonathan Peyton #endif
28717cc577a4SJonathan Peyton   else {
28727cc577a4SJonathan Peyton     lck = __kmp_lookup_user_lock(user_lock, "omp_set_nest_lock");
28737cc577a4SJonathan Peyton   }
28747cc577a4SJonathan Peyton 
28757cc577a4SJonathan Peyton #if USE_ITT_BUILD
28767cc577a4SJonathan Peyton   __kmp_itt_lock_acquiring(lck);
28777cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
287882e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
287982e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
288082e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
288182e94a59SJoachim Protze   if (!codeptr)
288282e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
288382e94a59SJoachim Protze   if (ompt_enabled.enabled) {
288482e94a59SJoachim Protze     if (ompt_enabled.ompt_callback_mutex_acquire) {
288582e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)(
288682e94a59SJoachim Protze           ompt_mutex_nest_lock, omp_lock_hint_none,
28874109d560SJoachim Protze           __ompt_get_mutex_impl_type(), (ompt_wait_id_t)(uintptr_t)lck,
28884109d560SJoachim Protze           codeptr);
288982e94a59SJoachim Protze     }
289082e94a59SJoachim Protze   }
289182e94a59SJoachim Protze #endif
28927cc577a4SJonathan Peyton 
28937cc577a4SJonathan Peyton   ACQUIRE_NESTED_LOCK(lck, gtid, &acquire_status);
28947cc577a4SJonathan Peyton 
28957cc577a4SJonathan Peyton #if USE_ITT_BUILD
28967cc577a4SJonathan Peyton   __kmp_itt_lock_acquired(lck);
28977cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
28987cc577a4SJonathan Peyton 
289982e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
290082e94a59SJoachim Protze   if (ompt_enabled.enabled) {
29017cc577a4SJonathan Peyton     if (acquire_status == KMP_LOCK_ACQUIRED_FIRST) {
290282e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_mutex_acquired) {
290382e94a59SJoachim Protze         // lock_first
290482e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)(
29054109d560SJoachim Protze             ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr);
290682e94a59SJoachim Protze       }
29077cc577a4SJonathan Peyton     } else {
290882e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_nest_lock) {
290982e94a59SJoachim Protze         // lock_next
291082e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_nest_lock)(
29114109d560SJoachim Protze             ompt_scope_begin, (ompt_wait_id_t)(uintptr_t)lck, codeptr);
291282e94a59SJoachim Protze       }
29137cc577a4SJonathan Peyton     }
29147cc577a4SJonathan Peyton   }
29157cc577a4SJonathan Peyton #endif
29167cc577a4SJonathan Peyton 
29177cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
29187cc577a4SJonathan Peyton }
29197cc577a4SJonathan Peyton 
__kmpc_unset_lock(ident_t * loc,kmp_int32 gtid,void ** user_lock)29203041982dSJonathan Peyton void __kmpc_unset_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) {
29217cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
29227cc577a4SJonathan Peyton 
29237cc577a4SJonathan Peyton   int tag = KMP_EXTRACT_D_TAG(user_lock);
29247cc577a4SJonathan Peyton #if USE_ITT_BUILD
29257cc577a4SJonathan Peyton   __kmp_itt_lock_releasing((kmp_user_lock_p)user_lock);
29267cc577a4SJonathan Peyton #endif
29277cc577a4SJonathan Peyton #if KMP_USE_INLINED_TAS
29287cc577a4SJonathan Peyton   if (tag == locktag_tas && !__kmp_env_consistency_check) {
29297cc577a4SJonathan Peyton     KMP_RELEASE_TAS_LOCK(user_lock, gtid);
29307cc577a4SJonathan Peyton   } else
29317cc577a4SJonathan Peyton #elif KMP_USE_INLINED_FUTEX
29327cc577a4SJonathan Peyton   if (tag == locktag_futex && !__kmp_env_consistency_check) {
29337cc577a4SJonathan Peyton     KMP_RELEASE_FUTEX_LOCK(user_lock, gtid);
29347cc577a4SJonathan Peyton   } else
29357cc577a4SJonathan Peyton #endif
29367cc577a4SJonathan Peyton   {
29377cc577a4SJonathan Peyton     __kmp_direct_unset[tag]((kmp_dyna_lock_t *)user_lock, gtid);
29387cc577a4SJonathan Peyton   }
29397cc577a4SJonathan Peyton 
294082e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
294182e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
294282e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
294382e94a59SJoachim Protze   if (!codeptr)
294482e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
294582e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_mutex_released) {
294682e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_mutex_released)(
29474109d560SJoachim Protze         ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
294882e94a59SJoachim Protze   }
294982e94a59SJoachim Protze #endif
295082e94a59SJoachim Protze 
29517cc577a4SJonathan Peyton #else // KMP_USE_DYNAMIC_LOCK
29527cc577a4SJonathan Peyton 
29537cc577a4SJonathan Peyton   kmp_user_lock_p lck;
29547cc577a4SJonathan Peyton 
29557cc577a4SJonathan Peyton   /* Can't use serial interval since not block structured */
29567cc577a4SJonathan Peyton   /* release the lock */
29577cc577a4SJonathan Peyton 
29583041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
29593041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) <= OMP_LOCK_T_SIZE)) {
29603041982dSJonathan Peyton #if KMP_OS_LINUX &&                                                            \
29613041982dSJonathan Peyton     (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_ARM || KMP_ARCH_AARCH64)
29627cc577a4SJonathan Peyton // "fast" path implemented to fix customer performance issue
29637cc577a4SJonathan Peyton #if USE_ITT_BUILD
29647cc577a4SJonathan Peyton     __kmp_itt_lock_releasing((kmp_user_lock_p)user_lock);
29657cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
29667cc577a4SJonathan Peyton     TCW_4(((kmp_user_lock_p)user_lock)->tas.lk.poll, 0);
29677cc577a4SJonathan Peyton     KMP_MB();
296882e94a59SJoachim Protze 
296982e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
297082e94a59SJoachim Protze     // This is the case, if called from omp_init_lock_with_hint:
297182e94a59SJoachim Protze     void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
297282e94a59SJoachim Protze     if (!codeptr)
297382e94a59SJoachim Protze       codeptr = OMPT_GET_RETURN_ADDRESS(0);
297482e94a59SJoachim Protze     if (ompt_enabled.ompt_callback_mutex_released) {
297582e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_mutex_released)(
29764109d560SJoachim Protze           ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr);
297782e94a59SJoachim Protze     }
297882e94a59SJoachim Protze #endif
297982e94a59SJoachim Protze 
29807cc577a4SJonathan Peyton     return;
29817cc577a4SJonathan Peyton #else
29827cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
29837cc577a4SJonathan Peyton #endif
29847cc577a4SJonathan Peyton   }
29857cc577a4SJonathan Peyton #if KMP_USE_FUTEX
29863041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
29873041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) <= OMP_LOCK_T_SIZE)) {
29887cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
29897cc577a4SJonathan Peyton   }
29907cc577a4SJonathan Peyton #endif
29917cc577a4SJonathan Peyton   else {
29927cc577a4SJonathan Peyton     lck = __kmp_lookup_user_lock(user_lock, "omp_unset_lock");
29937cc577a4SJonathan Peyton   }
29947cc577a4SJonathan Peyton 
29957cc577a4SJonathan Peyton #if USE_ITT_BUILD
29967cc577a4SJonathan Peyton   __kmp_itt_lock_releasing(lck);
29977cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
29987cc577a4SJonathan Peyton 
29997cc577a4SJonathan Peyton   RELEASE_LOCK(lck, gtid);
30007cc577a4SJonathan Peyton 
300182e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
300282e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
300382e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
300482e94a59SJoachim Protze   if (!codeptr)
300582e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
300682e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_mutex_released) {
300782e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_mutex_released)(
30084109d560SJoachim Protze         ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr);
30097cc577a4SJonathan Peyton   }
30107cc577a4SJonathan Peyton #endif
30117cc577a4SJonathan Peyton 
30127cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
30137cc577a4SJonathan Peyton }
30147cc577a4SJonathan Peyton 
30157cc577a4SJonathan Peyton /* release the lock */
__kmpc_unset_nest_lock(ident_t * loc,kmp_int32 gtid,void ** user_lock)30163041982dSJonathan Peyton void __kmpc_unset_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) {
30177cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
30187cc577a4SJonathan Peyton 
30197cc577a4SJonathan Peyton #if USE_ITT_BUILD
30207cc577a4SJonathan Peyton   __kmp_itt_lock_releasing((kmp_user_lock_p)user_lock);
30217cc577a4SJonathan Peyton #endif
302282e94a59SJoachim Protze   int release_status =
30237cc577a4SJonathan Peyton       KMP_D_LOCK_FUNC(user_lock, unset)((kmp_dyna_lock_t *)user_lock, gtid);
302415f5407dSGheorghe-Teodor Bercea   (void)release_status;
30257cc577a4SJonathan Peyton 
302682e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
302782e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
302882e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
302982e94a59SJoachim Protze   if (!codeptr)
303082e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
303182e94a59SJoachim Protze   if (ompt_enabled.enabled) {
303282e94a59SJoachim Protze     if (release_status == KMP_LOCK_RELEASED) {
303382e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_mutex_released) {
303482e94a59SJoachim Protze         // release_lock_last
303582e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_mutex_released)(
30364109d560SJoachim Protze             ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock,
30374109d560SJoachim Protze             codeptr);
303882e94a59SJoachim Protze       }
303982e94a59SJoachim Protze     } else if (ompt_enabled.ompt_callback_nest_lock) {
304082e94a59SJoachim Protze       // release_lock_prev
304182e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_nest_lock)(
30424109d560SJoachim Protze           ompt_scope_end, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
304382e94a59SJoachim Protze     }
304482e94a59SJoachim Protze   }
304582e94a59SJoachim Protze #endif
304682e94a59SJoachim Protze 
30477cc577a4SJonathan Peyton #else // KMP_USE_DYNAMIC_LOCK
30487cc577a4SJonathan Peyton 
30497cc577a4SJonathan Peyton   kmp_user_lock_p lck;
30507cc577a4SJonathan Peyton 
30517cc577a4SJonathan Peyton   /* Can't use serial interval since not block structured */
30527cc577a4SJonathan Peyton 
30533041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
30543041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) + sizeof(lck->tas.lk.depth_locked) <=
30553041982dSJonathan Peyton        OMP_NEST_LOCK_T_SIZE)) {
30563041982dSJonathan Peyton #if KMP_OS_LINUX &&                                                            \
30573041982dSJonathan Peyton     (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_ARM || KMP_ARCH_AARCH64)
30587cc577a4SJonathan Peyton     // "fast" path implemented to fix customer performance issue
30597cc577a4SJonathan Peyton     kmp_tas_lock_t *tl = (kmp_tas_lock_t *)user_lock;
30607cc577a4SJonathan Peyton #if USE_ITT_BUILD
30617cc577a4SJonathan Peyton     __kmp_itt_lock_releasing((kmp_user_lock_p)user_lock);
30627cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
306382e94a59SJoachim Protze 
306482e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
306582e94a59SJoachim Protze     int release_status = KMP_LOCK_STILL_HELD;
306682e94a59SJoachim Protze #endif
306782e94a59SJoachim Protze 
30687cc577a4SJonathan Peyton     if (--(tl->lk.depth_locked) == 0) {
30697cc577a4SJonathan Peyton       TCW_4(tl->lk.poll, 0);
307082e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
307182e94a59SJoachim Protze       release_status = KMP_LOCK_RELEASED;
307282e94a59SJoachim Protze #endif
30737cc577a4SJonathan Peyton     }
30747cc577a4SJonathan Peyton     KMP_MB();
307582e94a59SJoachim Protze 
307682e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
307782e94a59SJoachim Protze     // This is the case, if called from omp_init_lock_with_hint:
307882e94a59SJoachim Protze     void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
307982e94a59SJoachim Protze     if (!codeptr)
308082e94a59SJoachim Protze       codeptr = OMPT_GET_RETURN_ADDRESS(0);
308182e94a59SJoachim Protze     if (ompt_enabled.enabled) {
308282e94a59SJoachim Protze       if (release_status == KMP_LOCK_RELEASED) {
308382e94a59SJoachim Protze         if (ompt_enabled.ompt_callback_mutex_released) {
308482e94a59SJoachim Protze           // release_lock_last
308582e94a59SJoachim Protze           ompt_callbacks.ompt_callback(ompt_callback_mutex_released)(
30864109d560SJoachim Protze               ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr);
308782e94a59SJoachim Protze         }
308882e94a59SJoachim Protze       } else if (ompt_enabled.ompt_callback_nest_lock) {
308982e94a59SJoachim Protze         // release_lock_previous
309082e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_nest_lock)(
30914109d560SJoachim Protze             ompt_mutex_scope_end, (ompt_wait_id_t)(uintptr_t)lck, codeptr);
309282e94a59SJoachim Protze       }
309382e94a59SJoachim Protze     }
309482e94a59SJoachim Protze #endif
309582e94a59SJoachim Protze 
30967cc577a4SJonathan Peyton     return;
30977cc577a4SJonathan Peyton #else
30987cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
30997cc577a4SJonathan Peyton #endif
31007cc577a4SJonathan Peyton   }
31017cc577a4SJonathan Peyton #if KMP_USE_FUTEX
31023041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
31033041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) + sizeof(lck->futex.lk.depth_locked) <=
31043041982dSJonathan Peyton             OMP_NEST_LOCK_T_SIZE)) {
31057cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
31067cc577a4SJonathan Peyton   }
31077cc577a4SJonathan Peyton #endif
31087cc577a4SJonathan Peyton   else {
31097cc577a4SJonathan Peyton     lck = __kmp_lookup_user_lock(user_lock, "omp_unset_nest_lock");
31107cc577a4SJonathan Peyton   }
31117cc577a4SJonathan Peyton 
31127cc577a4SJonathan Peyton #if USE_ITT_BUILD
31137cc577a4SJonathan Peyton   __kmp_itt_lock_releasing(lck);
31147cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
31157cc577a4SJonathan Peyton 
31167cc577a4SJonathan Peyton   int release_status;
31177cc577a4SJonathan Peyton   release_status = RELEASE_NESTED_LOCK(lck, gtid);
311882e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
311982e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
312082e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
312182e94a59SJoachim Protze   if (!codeptr)
312282e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
312382e94a59SJoachim Protze   if (ompt_enabled.enabled) {
31247cc577a4SJonathan Peyton     if (release_status == KMP_LOCK_RELEASED) {
312582e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_mutex_released) {
312682e94a59SJoachim Protze         // release_lock_last
312782e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_mutex_released)(
31284109d560SJoachim Protze             ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr);
31297cc577a4SJonathan Peyton       }
313082e94a59SJoachim Protze     } else if (ompt_enabled.ompt_callback_nest_lock) {
313182e94a59SJoachim Protze       // release_lock_previous
313282e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_nest_lock)(
31334109d560SJoachim Protze           ompt_mutex_scope_end, (ompt_wait_id_t)(uintptr_t)lck, codeptr);
31347cc577a4SJonathan Peyton     }
31357cc577a4SJonathan Peyton   }
31367cc577a4SJonathan Peyton #endif
31377cc577a4SJonathan Peyton 
31387cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
31397cc577a4SJonathan Peyton }
31407cc577a4SJonathan Peyton 
31417cc577a4SJonathan Peyton /* try to acquire the lock */
__kmpc_test_lock(ident_t * loc,kmp_int32 gtid,void ** user_lock)31423041982dSJonathan Peyton int __kmpc_test_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) {
31437cc577a4SJonathan Peyton   KMP_COUNT_BLOCK(OMP_test_lock);
31447cc577a4SJonathan Peyton 
31457cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
31467cc577a4SJonathan Peyton   int rc;
31477cc577a4SJonathan Peyton   int tag = KMP_EXTRACT_D_TAG(user_lock);
31487cc577a4SJonathan Peyton #if USE_ITT_BUILD
31497cc577a4SJonathan Peyton   __kmp_itt_lock_acquiring((kmp_user_lock_p)user_lock);
31507cc577a4SJonathan Peyton #endif
315182e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
315282e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
315382e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
315482e94a59SJoachim Protze   if (!codeptr)
315582e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
315682e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_mutex_acquire) {
315782e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)(
315882e94a59SJoachim Protze         ompt_mutex_lock, omp_lock_hint_none,
31594109d560SJoachim Protze         __ompt_get_mutex_impl_type(user_lock),
31604109d560SJoachim Protze         (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
316182e94a59SJoachim Protze   }
316282e94a59SJoachim Protze #endif
31637cc577a4SJonathan Peyton #if KMP_USE_INLINED_TAS
31647cc577a4SJonathan Peyton   if (tag == locktag_tas && !__kmp_env_consistency_check) {
31657cc577a4SJonathan Peyton     KMP_TEST_TAS_LOCK(user_lock, gtid, rc);
31667cc577a4SJonathan Peyton   } else
31677cc577a4SJonathan Peyton #elif KMP_USE_INLINED_FUTEX
31687cc577a4SJonathan Peyton   if (tag == locktag_futex && !__kmp_env_consistency_check) {
31697cc577a4SJonathan Peyton     KMP_TEST_FUTEX_LOCK(user_lock, gtid, rc);
31707cc577a4SJonathan Peyton   } else
31717cc577a4SJonathan Peyton #endif
31727cc577a4SJonathan Peyton   {
31737cc577a4SJonathan Peyton     rc = __kmp_direct_test[tag]((kmp_dyna_lock_t *)user_lock, gtid);
31747cc577a4SJonathan Peyton   }
31757cc577a4SJonathan Peyton   if (rc) {
31767cc577a4SJonathan Peyton #if USE_ITT_BUILD
31777cc577a4SJonathan Peyton     __kmp_itt_lock_acquired((kmp_user_lock_p)user_lock);
31787cc577a4SJonathan Peyton #endif
317982e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
318082e94a59SJoachim Protze     if (ompt_enabled.ompt_callback_mutex_acquired) {
318182e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)(
31824109d560SJoachim Protze           ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
318382e94a59SJoachim Protze     }
318482e94a59SJoachim Protze #endif
31857cc577a4SJonathan Peyton     return FTN_TRUE;
31867cc577a4SJonathan Peyton   } else {
31877cc577a4SJonathan Peyton #if USE_ITT_BUILD
31887cc577a4SJonathan Peyton     __kmp_itt_lock_cancelled((kmp_user_lock_p)user_lock);
31897cc577a4SJonathan Peyton #endif
31907cc577a4SJonathan Peyton     return FTN_FALSE;
31917cc577a4SJonathan Peyton   }
31927cc577a4SJonathan Peyton 
31937cc577a4SJonathan Peyton #else // KMP_USE_DYNAMIC_LOCK
31947cc577a4SJonathan Peyton 
31957cc577a4SJonathan Peyton   kmp_user_lock_p lck;
31967cc577a4SJonathan Peyton   int rc;
31977cc577a4SJonathan Peyton 
31983041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
31993041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) <= OMP_LOCK_T_SIZE)) {
32007cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
32017cc577a4SJonathan Peyton   }
32027cc577a4SJonathan Peyton #if KMP_USE_FUTEX
32033041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
32043041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) <= OMP_LOCK_T_SIZE)) {
32057cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
32067cc577a4SJonathan Peyton   }
32077cc577a4SJonathan Peyton #endif
32087cc577a4SJonathan Peyton   else {
32097cc577a4SJonathan Peyton     lck = __kmp_lookup_user_lock(user_lock, "omp_test_lock");
32107cc577a4SJonathan Peyton   }
32117cc577a4SJonathan Peyton 
32127cc577a4SJonathan Peyton #if USE_ITT_BUILD
32137cc577a4SJonathan Peyton   __kmp_itt_lock_acquiring(lck);
32147cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
321582e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
321682e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
321782e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
321882e94a59SJoachim Protze   if (!codeptr)
321982e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
322082e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_mutex_acquire) {
322182e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)(
322282e94a59SJoachim Protze         ompt_mutex_lock, omp_lock_hint_none, __ompt_get_mutex_impl_type(),
32234109d560SJoachim Protze         (ompt_wait_id_t)(uintptr_t)lck, codeptr);
322482e94a59SJoachim Protze   }
322582e94a59SJoachim Protze #endif
32267cc577a4SJonathan Peyton 
32277cc577a4SJonathan Peyton   rc = TEST_LOCK(lck, gtid);
32287cc577a4SJonathan Peyton #if USE_ITT_BUILD
32297cc577a4SJonathan Peyton   if (rc) {
32307cc577a4SJonathan Peyton     __kmp_itt_lock_acquired(lck);
32317cc577a4SJonathan Peyton   } else {
32327cc577a4SJonathan Peyton     __kmp_itt_lock_cancelled(lck);
32337cc577a4SJonathan Peyton   }
32347cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
323582e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
323682e94a59SJoachim Protze   if (rc && ompt_enabled.ompt_callback_mutex_acquired) {
323782e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)(
32384109d560SJoachim Protze         ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr);
323982e94a59SJoachim Protze   }
324082e94a59SJoachim Protze #endif
324182e94a59SJoachim Protze 
32427cc577a4SJonathan Peyton   return (rc ? FTN_TRUE : FTN_FALSE);
32437cc577a4SJonathan Peyton 
32447cc577a4SJonathan Peyton   /* Can't use serial interval since not block structured */
32457cc577a4SJonathan Peyton 
32467cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
32477cc577a4SJonathan Peyton }
32487cc577a4SJonathan Peyton 
32497cc577a4SJonathan Peyton /* try to acquire the lock */
__kmpc_test_nest_lock(ident_t * loc,kmp_int32 gtid,void ** user_lock)32503041982dSJonathan Peyton int __kmpc_test_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) {
32517cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
32527cc577a4SJonathan Peyton   int rc;
32537cc577a4SJonathan Peyton #if USE_ITT_BUILD
32547cc577a4SJonathan Peyton   __kmp_itt_lock_acquiring((kmp_user_lock_p)user_lock);
32557cc577a4SJonathan Peyton #endif
325682e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
325782e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
325882e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
325982e94a59SJoachim Protze   if (!codeptr)
326082e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
326182e94a59SJoachim Protze   if (ompt_enabled.ompt_callback_mutex_acquire) {
326282e94a59SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)(
326382e94a59SJoachim Protze         ompt_mutex_nest_lock, omp_lock_hint_none,
32644109d560SJoachim Protze         __ompt_get_mutex_impl_type(user_lock),
32654109d560SJoachim Protze         (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
326682e94a59SJoachim Protze   }
326782e94a59SJoachim Protze #endif
32687cc577a4SJonathan Peyton   rc = KMP_D_LOCK_FUNC(user_lock, test)((kmp_dyna_lock_t *)user_lock, gtid);
32697cc577a4SJonathan Peyton #if USE_ITT_BUILD
32707cc577a4SJonathan Peyton   if (rc) {
32717cc577a4SJonathan Peyton     __kmp_itt_lock_acquired((kmp_user_lock_p)user_lock);
32727cc577a4SJonathan Peyton   } else {
32737cc577a4SJonathan Peyton     __kmp_itt_lock_cancelled((kmp_user_lock_p)user_lock);
32747cc577a4SJonathan Peyton   }
32757cc577a4SJonathan Peyton #endif
327682e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
327782e94a59SJoachim Protze   if (ompt_enabled.enabled && rc) {
327882e94a59SJoachim Protze     if (rc == 1) {
327982e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_mutex_acquired) {
328082e94a59SJoachim Protze         // lock_first
328182e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)(
32824109d560SJoachim Protze             ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock,
32834109d560SJoachim Protze             codeptr);
328482e94a59SJoachim Protze       }
328582e94a59SJoachim Protze     } else {
328682e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_nest_lock) {
328782e94a59SJoachim Protze         // lock_next
328882e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_nest_lock)(
32894109d560SJoachim Protze             ompt_scope_begin, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr);
329082e94a59SJoachim Protze       }
329182e94a59SJoachim Protze     }
329282e94a59SJoachim Protze   }
329382e94a59SJoachim Protze #endif
32947cc577a4SJonathan Peyton   return rc;
32957cc577a4SJonathan Peyton 
32967cc577a4SJonathan Peyton #else // KMP_USE_DYNAMIC_LOCK
32977cc577a4SJonathan Peyton 
32987cc577a4SJonathan Peyton   kmp_user_lock_p lck;
32997cc577a4SJonathan Peyton   int rc;
33007cc577a4SJonathan Peyton 
33013041982dSJonathan Peyton   if ((__kmp_user_lock_kind == lk_tas) &&
33023041982dSJonathan Peyton       (sizeof(lck->tas.lk.poll) + sizeof(lck->tas.lk.depth_locked) <=
33033041982dSJonathan Peyton        OMP_NEST_LOCK_T_SIZE)) {
33047cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
33057cc577a4SJonathan Peyton   }
33067cc577a4SJonathan Peyton #if KMP_USE_FUTEX
33073041982dSJonathan Peyton   else if ((__kmp_user_lock_kind == lk_futex) &&
33083041982dSJonathan Peyton            (sizeof(lck->futex.lk.poll) + sizeof(lck->futex.lk.depth_locked) <=
33093041982dSJonathan Peyton             OMP_NEST_LOCK_T_SIZE)) {
33107cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)user_lock;
33117cc577a4SJonathan Peyton   }
33127cc577a4SJonathan Peyton #endif
33137cc577a4SJonathan Peyton   else {
33147cc577a4SJonathan Peyton     lck = __kmp_lookup_user_lock(user_lock, "omp_test_nest_lock");
33157cc577a4SJonathan Peyton   }
33167cc577a4SJonathan Peyton 
33177cc577a4SJonathan Peyton #if USE_ITT_BUILD
33187cc577a4SJonathan Peyton   __kmp_itt_lock_acquiring(lck);
33197cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
33207cc577a4SJonathan Peyton 
332182e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
332282e94a59SJoachim Protze   // This is the case, if called from omp_init_lock_with_hint:
332382e94a59SJoachim Protze   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid);
332482e94a59SJoachim Protze   if (!codeptr)
332582e94a59SJoachim Protze     codeptr = OMPT_GET_RETURN_ADDRESS(0);
332682e94a59SJoachim Protze   if (ompt_enabled.enabled) &&
332782e94a59SJoachim Protze         ompt_enabled.ompt_callback_mutex_acquire) {
332882e94a59SJoachim Protze       ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)(
332982e94a59SJoachim Protze           ompt_mutex_nest_lock, omp_lock_hint_none,
33304109d560SJoachim Protze           __ompt_get_mutex_impl_type(), (ompt_wait_id_t)(uintptr_t)lck,
33314109d560SJoachim Protze           codeptr);
333282e94a59SJoachim Protze     }
333382e94a59SJoachim Protze #endif
333482e94a59SJoachim Protze 
33357cc577a4SJonathan Peyton   rc = TEST_NESTED_LOCK(lck, gtid);
33367cc577a4SJonathan Peyton #if USE_ITT_BUILD
33377cc577a4SJonathan Peyton   if (rc) {
33387cc577a4SJonathan Peyton     __kmp_itt_lock_acquired(lck);
33397cc577a4SJonathan Peyton   } else {
33407cc577a4SJonathan Peyton     __kmp_itt_lock_cancelled(lck);
33417cc577a4SJonathan Peyton   }
33427cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
334382e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
334482e94a59SJoachim Protze   if (ompt_enabled.enabled && rc) {
334582e94a59SJoachim Protze     if (rc == 1) {
334682e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_mutex_acquired) {
334782e94a59SJoachim Protze         // lock_first
334882e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)(
33494109d560SJoachim Protze             ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr);
335082e94a59SJoachim Protze       }
335182e94a59SJoachim Protze     } else {
335282e94a59SJoachim Protze       if (ompt_enabled.ompt_callback_nest_lock) {
335382e94a59SJoachim Protze         // lock_next
335482e94a59SJoachim Protze         ompt_callbacks.ompt_callback(ompt_callback_nest_lock)(
33554109d560SJoachim Protze             ompt_mutex_scope_begin, (ompt_wait_id_t)(uintptr_t)lck, codeptr);
335682e94a59SJoachim Protze       }
335782e94a59SJoachim Protze     }
335882e94a59SJoachim Protze   }
335982e94a59SJoachim Protze #endif
33607cc577a4SJonathan Peyton   return rc;
33617cc577a4SJonathan Peyton 
33627cc577a4SJonathan Peyton   /* Can't use serial interval since not block structured */
33637cc577a4SJonathan Peyton 
33647cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
33657cc577a4SJonathan Peyton }
33667cc577a4SJonathan Peyton 
33673041982dSJonathan Peyton // Interface to fast scalable reduce methods routines
33687cc577a4SJonathan Peyton 
33693041982dSJonathan Peyton // keep the selected method in a thread local structure for cross-function
33703041982dSJonathan Peyton // usage: will be used in __kmpc_end_reduce* functions;
33713041982dSJonathan Peyton // another solution: to re-determine the method one more time in
33723041982dSJonathan Peyton // __kmpc_end_reduce* functions (new prototype required then)
33737cc577a4SJonathan Peyton // AT: which solution is better?
33747cc577a4SJonathan Peyton #define __KMP_SET_REDUCTION_METHOD(gtid, rmethod)                              \
33757cc577a4SJonathan Peyton   ((__kmp_threads[(gtid)]->th.th_local.packed_reduction_method) = (rmethod))
33767cc577a4SJonathan Peyton 
33777cc577a4SJonathan Peyton #define __KMP_GET_REDUCTION_METHOD(gtid)                                       \
33787cc577a4SJonathan Peyton   (__kmp_threads[(gtid)]->th.th_local.packed_reduction_method)
33797cc577a4SJonathan Peyton 
33803041982dSJonathan Peyton // description of the packed_reduction_method variable: look at the macros in
33813041982dSJonathan Peyton // kmp.h
33827cc577a4SJonathan Peyton 
33837cc577a4SJonathan Peyton // used in a critical section reduce block
33847cc577a4SJonathan Peyton static __forceinline void
__kmp_enter_critical_section_reduce_block(ident_t * loc,kmp_int32 global_tid,kmp_critical_name * crit)33853041982dSJonathan Peyton __kmp_enter_critical_section_reduce_block(ident_t *loc, kmp_int32 global_tid,
33863041982dSJonathan Peyton                                           kmp_critical_name *crit) {
33877cc577a4SJonathan Peyton 
33883041982dSJonathan Peyton   // this lock was visible to a customer and to the threading profile tool as a
33893041982dSJonathan Peyton   // serial overhead span (although it's used for an internal purpose only)
33907cc577a4SJonathan Peyton   //            why was it visible in previous implementation?
33917cc577a4SJonathan Peyton   //            should we keep it visible in new reduce block?
33927cc577a4SJonathan Peyton   kmp_user_lock_p lck;
33937cc577a4SJonathan Peyton 
33947cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
33957cc577a4SJonathan Peyton 
33967cc577a4SJonathan Peyton   kmp_dyna_lock_t *lk = (kmp_dyna_lock_t *)crit;
33977cc577a4SJonathan Peyton   // Check if it is initialized.
33987cc577a4SJonathan Peyton   if (*lk == 0) {
33997cc577a4SJonathan Peyton     if (KMP_IS_D_LOCK(__kmp_user_lock_seq)) {
34003041982dSJonathan Peyton       KMP_COMPARE_AND_STORE_ACQ32((volatile kmp_int32 *)crit, 0,
34013041982dSJonathan Peyton                                   KMP_GET_D_TAG(__kmp_user_lock_seq));
34027cc577a4SJonathan Peyton     } else {
34033041982dSJonathan Peyton       __kmp_init_indirect_csptr(crit, loc, global_tid,
34043041982dSJonathan Peyton                                 KMP_GET_I_TAG(__kmp_user_lock_seq));
34057cc577a4SJonathan Peyton     }
34067cc577a4SJonathan Peyton   }
34073041982dSJonathan Peyton   // Branch for accessing the actual lock object and set operation. This
34083041982dSJonathan Peyton   // branching is inevitable since this lock initialization does not follow the
34093041982dSJonathan Peyton   // normal dispatch path (lock table is not used).
34107cc577a4SJonathan Peyton   if (KMP_EXTRACT_D_TAG(lk) != 0) {
34117cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)lk;
34127cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT(lck != NULL);
34137cc577a4SJonathan Peyton     if (__kmp_env_consistency_check) {
34147cc577a4SJonathan Peyton       __kmp_push_sync(global_tid, ct_critical, loc, lck, __kmp_user_lock_seq);
34157cc577a4SJonathan Peyton     }
34167cc577a4SJonathan Peyton     KMP_D_LOCK_FUNC(lk, set)(lk, global_tid);
34177cc577a4SJonathan Peyton   } else {
34187cc577a4SJonathan Peyton     kmp_indirect_lock_t *ilk = *((kmp_indirect_lock_t **)lk);
34197cc577a4SJonathan Peyton     lck = ilk->lock;
34207cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT(lck != NULL);
34217cc577a4SJonathan Peyton     if (__kmp_env_consistency_check) {
34227cc577a4SJonathan Peyton       __kmp_push_sync(global_tid, ct_critical, loc, lck, __kmp_user_lock_seq);
34237cc577a4SJonathan Peyton     }
34247cc577a4SJonathan Peyton     KMP_I_LOCK_FUNC(ilk, set)(lck, global_tid);
34257cc577a4SJonathan Peyton   }
34267cc577a4SJonathan Peyton 
34277cc577a4SJonathan Peyton #else // KMP_USE_DYNAMIC_LOCK
34287cc577a4SJonathan Peyton 
34297cc577a4SJonathan Peyton   // We know that the fast reduction code is only emitted by Intel compilers
34307cc577a4SJonathan Peyton   // with 32 byte critical sections. If there isn't enough space, then we
34317cc577a4SJonathan Peyton   // have to use a pointer.
34327cc577a4SJonathan Peyton   if (__kmp_base_user_lock_size <= INTEL_CRITICAL_SIZE) {
34337cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)crit;
34343041982dSJonathan Peyton   } else {
34357cc577a4SJonathan Peyton     lck = __kmp_get_critical_section_ptr(crit, loc, global_tid);
34367cc577a4SJonathan Peyton   }
34377cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(lck != NULL);
34387cc577a4SJonathan Peyton 
34397cc577a4SJonathan Peyton   if (__kmp_env_consistency_check)
34407cc577a4SJonathan Peyton     __kmp_push_sync(global_tid, ct_critical, loc, lck);
34417cc577a4SJonathan Peyton 
34427cc577a4SJonathan Peyton   __kmp_acquire_user_lock_with_checks(lck, global_tid);
34437cc577a4SJonathan Peyton 
34447cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
34457cc577a4SJonathan Peyton }
34467cc577a4SJonathan Peyton 
34477cc577a4SJonathan Peyton // used in a critical section reduce block
34487cc577a4SJonathan Peyton static __forceinline void
__kmp_end_critical_section_reduce_block(ident_t * loc,kmp_int32 global_tid,kmp_critical_name * crit)34493041982dSJonathan Peyton __kmp_end_critical_section_reduce_block(ident_t *loc, kmp_int32 global_tid,
34503041982dSJonathan Peyton                                         kmp_critical_name *crit) {
34517cc577a4SJonathan Peyton 
34527cc577a4SJonathan Peyton   kmp_user_lock_p lck;
34537cc577a4SJonathan Peyton 
34547cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
34557cc577a4SJonathan Peyton 
34567cc577a4SJonathan Peyton   if (KMP_IS_D_LOCK(__kmp_user_lock_seq)) {
34577cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)crit;
34587cc577a4SJonathan Peyton     if (__kmp_env_consistency_check)
34597cc577a4SJonathan Peyton       __kmp_pop_sync(global_tid, ct_critical, loc);
34607cc577a4SJonathan Peyton     KMP_D_LOCK_FUNC(lck, unset)((kmp_dyna_lock_t *)lck, global_tid);
34617cc577a4SJonathan Peyton   } else {
34623041982dSJonathan Peyton     kmp_indirect_lock_t *ilk =
34633041982dSJonathan Peyton         (kmp_indirect_lock_t *)TCR_PTR(*((kmp_indirect_lock_t **)crit));
34647cc577a4SJonathan Peyton     if (__kmp_env_consistency_check)
34657cc577a4SJonathan Peyton       __kmp_pop_sync(global_tid, ct_critical, loc);
34667cc577a4SJonathan Peyton     KMP_I_LOCK_FUNC(ilk, unset)(ilk->lock, global_tid);
34677cc577a4SJonathan Peyton   }
34687cc577a4SJonathan Peyton 
34697cc577a4SJonathan Peyton #else // KMP_USE_DYNAMIC_LOCK
34707cc577a4SJonathan Peyton 
34713041982dSJonathan Peyton   // We know that the fast reduction code is only emitted by Intel compilers
34723041982dSJonathan Peyton   // with 32 byte critical sections. If there isn't enough space, then we have
34733041982dSJonathan Peyton   // to use a pointer.
34747cc577a4SJonathan Peyton   if (__kmp_base_user_lock_size > 32) {
34757cc577a4SJonathan Peyton     lck = *((kmp_user_lock_p *)crit);
34767cc577a4SJonathan Peyton     KMP_ASSERT(lck != NULL);
34777cc577a4SJonathan Peyton   } else {
34787cc577a4SJonathan Peyton     lck = (kmp_user_lock_p)crit;
34797cc577a4SJonathan Peyton   }
34807cc577a4SJonathan Peyton 
34817cc577a4SJonathan Peyton   if (__kmp_env_consistency_check)
34827cc577a4SJonathan Peyton     __kmp_pop_sync(global_tid, ct_critical, loc);
34837cc577a4SJonathan Peyton 
34847cc577a4SJonathan Peyton   __kmp_release_user_lock_with_checks(lck, global_tid);
34857cc577a4SJonathan Peyton 
34867cc577a4SJonathan Peyton #endif // KMP_USE_DYNAMIC_LOCK
34877cc577a4SJonathan Peyton } // __kmp_end_critical_section_reduce_block
34887cc577a4SJonathan Peyton 
3489a4ca525cSJonas Hahnfeld static __forceinline int
__kmp_swap_teams_for_teams_reduction(kmp_info_t * th,kmp_team_t ** team_p,int * task_state)3490a4ca525cSJonas Hahnfeld __kmp_swap_teams_for_teams_reduction(kmp_info_t *th, kmp_team_t **team_p,
3491a4ca525cSJonas Hahnfeld                                      int *task_state) {
3492a4ca525cSJonas Hahnfeld   kmp_team_t *team;
3493a4ca525cSJonas Hahnfeld 
3494a4ca525cSJonas Hahnfeld   // Check if we are inside the teams construct?
3495a4ca525cSJonas Hahnfeld   if (th->th.th_teams_microtask) {
3496a4ca525cSJonas Hahnfeld     *team_p = team = th->th.th_team;
3497a4ca525cSJonas Hahnfeld     if (team->t.t_level == th->th.th_teams_level) {
3498a4ca525cSJonas Hahnfeld       // This is reduction at teams construct.
3499a4ca525cSJonas Hahnfeld       KMP_DEBUG_ASSERT(!th->th.th_info.ds.ds_tid); // AC: check that tid == 0
3500a4ca525cSJonas Hahnfeld       // Let's swap teams temporarily for the reduction.
3501a4ca525cSJonas Hahnfeld       th->th.th_info.ds.ds_tid = team->t.t_master_tid;
3502a4ca525cSJonas Hahnfeld       th->th.th_team = team->t.t_parent;
3503a4ca525cSJonas Hahnfeld       th->th.th_team_nproc = th->th.th_team->t.t_nproc;
3504a4ca525cSJonas Hahnfeld       th->th.th_task_team = th->th.th_team->t.t_task_team[0];
3505a4ca525cSJonas Hahnfeld       *task_state = th->th.th_task_state;
3506a4ca525cSJonas Hahnfeld       th->th.th_task_state = 0;
3507a4ca525cSJonas Hahnfeld 
3508a4ca525cSJonas Hahnfeld       return 1;
3509a4ca525cSJonas Hahnfeld     }
3510a4ca525cSJonas Hahnfeld   }
3511a4ca525cSJonas Hahnfeld   return 0;
3512a4ca525cSJonas Hahnfeld }
3513a4ca525cSJonas Hahnfeld 
3514a4ca525cSJonas Hahnfeld static __forceinline void
__kmp_restore_swapped_teams(kmp_info_t * th,kmp_team_t * team,int task_state)3515a4ca525cSJonas Hahnfeld __kmp_restore_swapped_teams(kmp_info_t *th, kmp_team_t *team, int task_state) {
3516a4ca525cSJonas Hahnfeld   // Restore thread structure swapped in __kmp_swap_teams_for_teams_reduction.
3517a4ca525cSJonas Hahnfeld   th->th.th_info.ds.ds_tid = 0;
3518a4ca525cSJonas Hahnfeld   th->th.th_team = team;
3519a4ca525cSJonas Hahnfeld   th->th.th_team_nproc = team->t.t_nproc;
3520a4ca525cSJonas Hahnfeld   th->th.th_task_team = team->t.t_task_team[task_state];
35216b316febSTerry Wilmarth   __kmp_type_convert(task_state, &(th->th.th_task_state));
3522a4ca525cSJonas Hahnfeld }
3523a4ca525cSJonas Hahnfeld 
35247cc577a4SJonathan Peyton /* 2.a.i. Reduce Block without a terminating barrier */
35257cc577a4SJonathan Peyton /*!
35267cc577a4SJonathan Peyton @ingroup SYNCHRONIZATION
35277cc577a4SJonathan Peyton @param loc source location information
35287cc577a4SJonathan Peyton @param global_tid global thread number
35297cc577a4SJonathan Peyton @param num_vars number of items (variables) to be reduced
35307cc577a4SJonathan Peyton @param reduce_size size of data in bytes to be reduced
35317cc577a4SJonathan Peyton @param reduce_data pointer to data to be reduced
35323041982dSJonathan Peyton @param reduce_func callback function providing reduction operation on two
35333041982dSJonathan Peyton operands and returning result of reduction in lhs_data
35347cc577a4SJonathan Peyton @param lck pointer to the unique lock data structure
353597d000cfStlwilmar @result 1 for the primary thread, 0 for all other team threads, 2 for all team
35363041982dSJonathan Peyton threads if atomic reduction needed
35377cc577a4SJonathan Peyton 
35387cc577a4SJonathan Peyton The nowait version is used for a reduce clause with the nowait argument.
35397cc577a4SJonathan Peyton */
35407cc577a4SJonathan Peyton kmp_int32
__kmpc_reduce_nowait(ident_t * loc,kmp_int32 global_tid,kmp_int32 num_vars,size_t reduce_size,void * reduce_data,void (* reduce_func)(void * lhs_data,void * rhs_data),kmp_critical_name * lck)35413041982dSJonathan Peyton __kmpc_reduce_nowait(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars,
35423041982dSJonathan Peyton                      size_t reduce_size, void *reduce_data,
35433041982dSJonathan Peyton                      void (*reduce_func)(void *lhs_data, void *rhs_data),
35447cc577a4SJonathan Peyton                      kmp_critical_name *lck) {
35457cc577a4SJonathan Peyton 
35467cc577a4SJonathan Peyton   KMP_COUNT_BLOCK(REDUCE_nowait);
35477cc577a4SJonathan Peyton   int retval = 0;
35487cc577a4SJonathan Peyton   PACKED_REDUCTION_METHOD_T packed_reduction_method;
35497cc577a4SJonathan Peyton   kmp_info_t *th;
3550a4ca525cSJonas Hahnfeld   kmp_team_t *team;
35517cc577a4SJonathan Peyton   int teams_swapped = 0, task_state;
35527cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmpc_reduce_nowait() enter: called T#%d\n", global_tid));
3553787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
35547cc577a4SJonathan Peyton 
35557cc577a4SJonathan Peyton   // why do we need this initialization here at all?
35567cc577a4SJonathan Peyton   // Reduction clause can not be used as a stand-alone directive.
35577cc577a4SJonathan Peyton 
35583041982dSJonathan Peyton   // do not call __kmp_serial_initialize(), it will be called by
35593041982dSJonathan Peyton   // __kmp_parallel_initialize() if needed
35607cc577a4SJonathan Peyton   // possible detection of false-positive race by the threadchecker ???
35617cc577a4SJonathan Peyton   if (!TCR_4(__kmp_init_parallel))
35627cc577a4SJonathan Peyton     __kmp_parallel_initialize();
35637cc577a4SJonathan Peyton 
35649b8bb323SJonathan Peyton   __kmp_resume_if_soft_paused();
35659b8bb323SJonathan Peyton 
35667cc577a4SJonathan Peyton // check correctness of reduce block nesting
35677cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
35687cc577a4SJonathan Peyton   if (__kmp_env_consistency_check)
35697cc577a4SJonathan Peyton     __kmp_push_sync(global_tid, ct_reduce, loc, NULL, 0);
35707cc577a4SJonathan Peyton #else
35717cc577a4SJonathan Peyton   if (__kmp_env_consistency_check)
35727cc577a4SJonathan Peyton     __kmp_push_sync(global_tid, ct_reduce, loc, NULL);
35737cc577a4SJonathan Peyton #endif
35747cc577a4SJonathan Peyton 
35757cc577a4SJonathan Peyton   th = __kmp_thread_from_gtid(global_tid);
3576a4ca525cSJonas Hahnfeld   teams_swapped = __kmp_swap_teams_for_teams_reduction(th, &team, &task_state);
35777cc577a4SJonathan Peyton 
35783041982dSJonathan Peyton   // packed_reduction_method value will be reused by __kmp_end_reduce* function,
35793041982dSJonathan Peyton   // the value should be kept in a variable
35803041982dSJonathan Peyton   // the variable should be either a construct-specific or thread-specific
35813041982dSJonathan Peyton   // property, not a team specific property
35823041982dSJonathan Peyton   //     (a thread can reach the next reduce block on the next construct, reduce
35833041982dSJonathan Peyton   //     method may differ on the next construct)
35843041982dSJonathan Peyton   // an ident_t "loc" parameter could be used as a construct-specific property
35853041982dSJonathan Peyton   // (what if loc == 0?)
35863041982dSJonathan Peyton   //     (if both construct-specific and team-specific variables were shared,
35873041982dSJonathan Peyton   //     then unness extra syncs should be needed)
35883041982dSJonathan Peyton   // a thread-specific variable is better regarding two issues above (next
35893041982dSJonathan Peyton   // construct and extra syncs)
35907cc577a4SJonathan Peyton   // a thread-specific "th_local.reduction_method" variable is used currently
35913041982dSJonathan Peyton   // each thread executes 'determine' and 'set' lines (no need to execute by one
35923041982dSJonathan Peyton   // thread, to avoid unness extra syncs)
35937cc577a4SJonathan Peyton 
35943041982dSJonathan Peyton   packed_reduction_method = __kmp_determine_reduction_method(
35953041982dSJonathan Peyton       loc, global_tid, num_vars, reduce_size, reduce_data, reduce_func, lck);
35967cc577a4SJonathan Peyton   __KMP_SET_REDUCTION_METHOD(global_tid, packed_reduction_method);
35977cc577a4SJonathan Peyton 
35983356e268S[email protected]   OMPT_REDUCTION_DECL(th, global_tid);
35997cc577a4SJonathan Peyton   if (packed_reduction_method == critical_reduce_block) {
36007cc577a4SJonathan Peyton 
36013356e268S[email protected]     OMPT_REDUCTION_BEGIN;
36023356e268S[email protected] 
36037cc577a4SJonathan Peyton     __kmp_enter_critical_section_reduce_block(loc, global_tid, lck);
36047cc577a4SJonathan Peyton     retval = 1;
36057cc577a4SJonathan Peyton 
36067cc577a4SJonathan Peyton   } else if (packed_reduction_method == empty_reduce_block) {
36077cc577a4SJonathan Peyton 
36083356e268S[email protected]     OMPT_REDUCTION_BEGIN;
36093356e268S[email protected] 
36103041982dSJonathan Peyton     // usage: if team size == 1, no synchronization is required ( Intel
36113041982dSJonathan Peyton     // platforms only )
36127cc577a4SJonathan Peyton     retval = 1;
36137cc577a4SJonathan Peyton 
36147cc577a4SJonathan Peyton   } else if (packed_reduction_method == atomic_reduce_block) {
36157cc577a4SJonathan Peyton 
36167cc577a4SJonathan Peyton     retval = 2;
36177cc577a4SJonathan Peyton 
36183041982dSJonathan Peyton     // all threads should do this pop here (because __kmpc_end_reduce_nowait()
36193041982dSJonathan Peyton     // won't be called by the code gen)
36203041982dSJonathan Peyton     //     (it's not quite good, because the checking block has been closed by
36213041982dSJonathan Peyton     //     this 'pop',
36223041982dSJonathan Peyton     //      but atomic operation has not been executed yet, will be executed
36233041982dSJonathan Peyton     //      slightly later, literally on next instruction)
36247cc577a4SJonathan Peyton     if (__kmp_env_consistency_check)
36257cc577a4SJonathan Peyton       __kmp_pop_sync(global_tid, ct_reduce, loc);
36267cc577a4SJonathan Peyton 
36273041982dSJonathan Peyton   } else if (TEST_REDUCTION_METHOD(packed_reduction_method,
36283041982dSJonathan Peyton                                    tree_reduce_block)) {
36297cc577a4SJonathan Peyton 
36307cc577a4SJonathan Peyton // AT: performance issue: a real barrier here
363197d000cfStlwilmar // AT: (if primary thread is slow, other threads are blocked here waiting for
363297d000cfStlwilmar //      the primary thread to come and release them)
36337cc577a4SJonathan Peyton // AT: (it's not what a customer might expect specifying NOWAIT clause)
36343041982dSJonathan Peyton // AT: (specifying NOWAIT won't result in improvement of performance, it'll
36353041982dSJonathan Peyton //      be confusing to a customer)
36363041982dSJonathan Peyton // AT: another implementation of *barrier_gather*nowait() (or some other design)
36373041982dSJonathan Peyton // might go faster and be more in line with sense of NOWAIT
36387cc577a4SJonathan Peyton // AT: TO DO: do epcc test and compare times
36397cc577a4SJonathan Peyton 
36403041982dSJonathan Peyton // this barrier should be invisible to a customer and to the threading profile
36413041982dSJonathan Peyton // tool (it's neither a terminating barrier nor customer's code, it's
36423041982dSJonathan Peyton // used for an internal purpose)
364382e94a59SJoachim Protze #if OMPT_SUPPORT
364482e94a59SJoachim Protze     // JP: can this barrier potentially leed to task scheduling?
364582e94a59SJoachim Protze     // JP: as long as there is a barrier in the implementation, OMPT should and
364682e94a59SJoachim Protze     // will provide the barrier events
364782e94a59SJoachim Protze     //         so we set-up the necessary frame/return addresses.
36480e0d6cddSJoachim Protze     ompt_frame_t *ompt_frame;
364982e94a59SJoachim Protze     if (ompt_enabled.enabled) {
365082e94a59SJoachim Protze       __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL);
36510e0d6cddSJoachim Protze       if (ompt_frame->enter_frame.ptr == NULL)
36520e0d6cddSJoachim Protze         ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
365382e94a59SJoachim Protze     }
36546d3b8166SJoachim Protze     OMPT_STORE_RETURN_ADDRESS(global_tid);
365582e94a59SJoachim Protze #endif
36567cc577a4SJonathan Peyton #if USE_ITT_NOTIFY
36577cc577a4SJonathan Peyton     __kmp_threads[global_tid]->th.th_ident = loc;
36587cc577a4SJonathan Peyton #endif
36593041982dSJonathan Peyton     retval =
36603041982dSJonathan Peyton         __kmp_barrier(UNPACK_REDUCTION_BARRIER(packed_reduction_method),
36613041982dSJonathan Peyton                       global_tid, FALSE, reduce_size, reduce_data, reduce_func);
36627cc577a4SJonathan Peyton     retval = (retval != 0) ? (0) : (1);
366382e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
366482e94a59SJoachim Protze     if (ompt_enabled.enabled) {
36650e0d6cddSJoachim Protze       ompt_frame->enter_frame = ompt_data_none;
366682e94a59SJoachim Protze     }
366782e94a59SJoachim Protze #endif
36687cc577a4SJonathan Peyton 
366997d000cfStlwilmar     // all other workers except primary thread should do this pop here
36707cc577a4SJonathan Peyton     //     ( none of other workers will get to __kmpc_end_reduce_nowait() )
36717cc577a4SJonathan Peyton     if (__kmp_env_consistency_check) {
36727cc577a4SJonathan Peyton       if (retval == 0) {
36737cc577a4SJonathan Peyton         __kmp_pop_sync(global_tid, ct_reduce, loc);
36747cc577a4SJonathan Peyton       }
36757cc577a4SJonathan Peyton     }
36767cc577a4SJonathan Peyton 
36777cc577a4SJonathan Peyton   } else {
36787cc577a4SJonathan Peyton 
36797cc577a4SJonathan Peyton     // should never reach this block
36807cc577a4SJonathan Peyton     KMP_ASSERT(0); // "unexpected method"
36817cc577a4SJonathan Peyton   }
36827cc577a4SJonathan Peyton   if (teams_swapped) {
3683a4ca525cSJonas Hahnfeld     __kmp_restore_swapped_teams(th, team, task_state);
36847cc577a4SJonathan Peyton   }
36853041982dSJonathan Peyton   KA_TRACE(
36863041982dSJonathan Peyton       10,
36873041982dSJonathan Peyton       ("__kmpc_reduce_nowait() exit: called T#%d: method %08x, returns %08x\n",
36883041982dSJonathan Peyton        global_tid, packed_reduction_method, retval));
36897cc577a4SJonathan Peyton 
36907cc577a4SJonathan Peyton   return retval;
36917cc577a4SJonathan Peyton }
36927cc577a4SJonathan Peyton 
36937cc577a4SJonathan Peyton /*!
36947cc577a4SJonathan Peyton @ingroup SYNCHRONIZATION
36957cc577a4SJonathan Peyton @param loc source location information
36967cc577a4SJonathan Peyton @param global_tid global thread id.
36977cc577a4SJonathan Peyton @param lck pointer to the unique lock data structure
36987cc577a4SJonathan Peyton 
36997cc577a4SJonathan Peyton Finish the execution of a reduce nowait.
37007cc577a4SJonathan Peyton */
__kmpc_end_reduce_nowait(ident_t * loc,kmp_int32 global_tid,kmp_critical_name * lck)37013041982dSJonathan Peyton void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
37023041982dSJonathan Peyton                               kmp_critical_name *lck) {
37037cc577a4SJonathan Peyton 
37047cc577a4SJonathan Peyton   PACKED_REDUCTION_METHOD_T packed_reduction_method;
37057cc577a4SJonathan Peyton 
37067cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmpc_end_reduce_nowait() enter: called T#%d\n", global_tid));
3707787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
37087cc577a4SJonathan Peyton 
37097cc577a4SJonathan Peyton   packed_reduction_method = __KMP_GET_REDUCTION_METHOD(global_tid);
37107cc577a4SJonathan Peyton 
37113356e268S[email protected]   OMPT_REDUCTION_DECL(__kmp_thread_from_gtid(global_tid), global_tid);
37123356e268S[email protected] 
37137cc577a4SJonathan Peyton   if (packed_reduction_method == critical_reduce_block) {
37147cc577a4SJonathan Peyton 
37157cc577a4SJonathan Peyton     __kmp_end_critical_section_reduce_block(loc, global_tid, lck);
37163356e268S[email protected]     OMPT_REDUCTION_END;
37177cc577a4SJonathan Peyton 
37187cc577a4SJonathan Peyton   } else if (packed_reduction_method == empty_reduce_block) {
37197cc577a4SJonathan Peyton 
37203041982dSJonathan Peyton     // usage: if team size == 1, no synchronization is required ( on Intel
37213041982dSJonathan Peyton     // platforms only )
37227cc577a4SJonathan Peyton 
37233356e268S[email protected]     OMPT_REDUCTION_END;
37243356e268S[email protected] 
37257cc577a4SJonathan Peyton   } else if (packed_reduction_method == atomic_reduce_block) {
37267cc577a4SJonathan Peyton 
372797d000cfStlwilmar     // neither primary thread nor other workers should get here
37287cc577a4SJonathan Peyton     //     (code gen does not generate this call in case 2: atomic reduce block)
37297cc577a4SJonathan Peyton     // actually it's better to remove this elseif at all;
37307cc577a4SJonathan Peyton     // after removal this value will checked by the 'else' and will assert
37317cc577a4SJonathan Peyton 
37323041982dSJonathan Peyton   } else if (TEST_REDUCTION_METHOD(packed_reduction_method,
37333041982dSJonathan Peyton                                    tree_reduce_block)) {
37347cc577a4SJonathan Peyton 
373597d000cfStlwilmar     // only primary thread gets here
37363356e268S[email protected]     // OMPT: tree reduction is annotated in the barrier code
37377cc577a4SJonathan Peyton 
37387cc577a4SJonathan Peyton   } else {
37397cc577a4SJonathan Peyton 
37407cc577a4SJonathan Peyton     // should never reach this block
37417cc577a4SJonathan Peyton     KMP_ASSERT(0); // "unexpected method"
37427cc577a4SJonathan Peyton   }
37437cc577a4SJonathan Peyton 
37447cc577a4SJonathan Peyton   if (__kmp_env_consistency_check)
37457cc577a4SJonathan Peyton     __kmp_pop_sync(global_tid, ct_reduce, loc);
37467cc577a4SJonathan Peyton 
37473041982dSJonathan Peyton   KA_TRACE(10, ("__kmpc_end_reduce_nowait() exit: called T#%d: method %08x\n",
37483041982dSJonathan Peyton                 global_tid, packed_reduction_method));
37497cc577a4SJonathan Peyton 
37507cc577a4SJonathan Peyton   return;
37517cc577a4SJonathan Peyton }
37527cc577a4SJonathan Peyton 
37537cc577a4SJonathan Peyton /* 2.a.ii. Reduce Block with a terminating barrier */
37547cc577a4SJonathan Peyton 
37557cc577a4SJonathan Peyton /*!
37567cc577a4SJonathan Peyton @ingroup SYNCHRONIZATION
37577cc577a4SJonathan Peyton @param loc source location information
37587cc577a4SJonathan Peyton @param global_tid global thread number
37597cc577a4SJonathan Peyton @param num_vars number of items (variables) to be reduced
37607cc577a4SJonathan Peyton @param reduce_size size of data in bytes to be reduced
37617cc577a4SJonathan Peyton @param reduce_data pointer to data to be reduced
37623041982dSJonathan Peyton @param reduce_func callback function providing reduction operation on two
37633041982dSJonathan Peyton operands and returning result of reduction in lhs_data
37647cc577a4SJonathan Peyton @param lck pointer to the unique lock data structure
376597d000cfStlwilmar @result 1 for the primary thread, 0 for all other team threads, 2 for all team
37663041982dSJonathan Peyton threads if atomic reduction needed
37677cc577a4SJonathan Peyton 
37687cc577a4SJonathan Peyton A blocking reduce that includes an implicit barrier.
37697cc577a4SJonathan Peyton */
__kmpc_reduce(ident_t * loc,kmp_int32 global_tid,kmp_int32 num_vars,size_t reduce_size,void * reduce_data,void (* reduce_func)(void * lhs_data,void * rhs_data),kmp_critical_name * lck)37703041982dSJonathan Peyton kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars,
37713041982dSJonathan Peyton                         size_t reduce_size, void *reduce_data,
37727cc577a4SJonathan Peyton                         void (*reduce_func)(void *lhs_data, void *rhs_data),
37733041982dSJonathan Peyton                         kmp_critical_name *lck) {
37747cc577a4SJonathan Peyton   KMP_COUNT_BLOCK(REDUCE_wait);
37757cc577a4SJonathan Peyton   int retval = 0;
37767cc577a4SJonathan Peyton   PACKED_REDUCTION_METHOD_T packed_reduction_method;
3777a4ca525cSJonas Hahnfeld   kmp_info_t *th;
3778a4ca525cSJonas Hahnfeld   kmp_team_t *team;
3779a4ca525cSJonas Hahnfeld   int teams_swapped = 0, task_state;
37807cc577a4SJonathan Peyton 
37817cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmpc_reduce() enter: called T#%d\n", global_tid));
3782787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
37837cc577a4SJonathan Peyton 
37847cc577a4SJonathan Peyton   // why do we need this initialization here at all?
37857cc577a4SJonathan Peyton   // Reduction clause can not be a stand-alone directive.
37867cc577a4SJonathan Peyton 
37873041982dSJonathan Peyton   // do not call __kmp_serial_initialize(), it will be called by
37883041982dSJonathan Peyton   // __kmp_parallel_initialize() if needed
37897cc577a4SJonathan Peyton   // possible detection of false-positive race by the threadchecker ???
37907cc577a4SJonathan Peyton   if (!TCR_4(__kmp_init_parallel))
37917cc577a4SJonathan Peyton     __kmp_parallel_initialize();
37927cc577a4SJonathan Peyton 
37939b8bb323SJonathan Peyton   __kmp_resume_if_soft_paused();
37949b8bb323SJonathan Peyton 
37957cc577a4SJonathan Peyton // check correctness of reduce block nesting
37967cc577a4SJonathan Peyton #if KMP_USE_DYNAMIC_LOCK
37977cc577a4SJonathan Peyton   if (__kmp_env_consistency_check)
37987cc577a4SJonathan Peyton     __kmp_push_sync(global_tid, ct_reduce, loc, NULL, 0);
37997cc577a4SJonathan Peyton #else
38007cc577a4SJonathan Peyton   if (__kmp_env_consistency_check)
38017cc577a4SJonathan Peyton     __kmp_push_sync(global_tid, ct_reduce, loc, NULL);
38027cc577a4SJonathan Peyton #endif
38037cc577a4SJonathan Peyton 
3804a4ca525cSJonas Hahnfeld   th = __kmp_thread_from_gtid(global_tid);
3805a4ca525cSJonas Hahnfeld   teams_swapped = __kmp_swap_teams_for_teams_reduction(th, &team, &task_state);
3806a4ca525cSJonas Hahnfeld 
38073041982dSJonathan Peyton   packed_reduction_method = __kmp_determine_reduction_method(
38083041982dSJonathan Peyton       loc, global_tid, num_vars, reduce_size, reduce_data, reduce_func, lck);
38097cc577a4SJonathan Peyton   __KMP_SET_REDUCTION_METHOD(global_tid, packed_reduction_method);
38107cc577a4SJonathan Peyton 
38113356e268S[email protected]   OMPT_REDUCTION_DECL(th, global_tid);
38123356e268S[email protected] 
38137cc577a4SJonathan Peyton   if (packed_reduction_method == critical_reduce_block) {
38147cc577a4SJonathan Peyton 
38153356e268S[email protected]     OMPT_REDUCTION_BEGIN;
38167cc577a4SJonathan Peyton     __kmp_enter_critical_section_reduce_block(loc, global_tid, lck);
38177cc577a4SJonathan Peyton     retval = 1;
38187cc577a4SJonathan Peyton 
38197cc577a4SJonathan Peyton   } else if (packed_reduction_method == empty_reduce_block) {
38207cc577a4SJonathan Peyton 
38213356e268S[email protected]     OMPT_REDUCTION_BEGIN;
38223041982dSJonathan Peyton     // usage: if team size == 1, no synchronization is required ( Intel
38233041982dSJonathan Peyton     // platforms only )
38247cc577a4SJonathan Peyton     retval = 1;
38257cc577a4SJonathan Peyton 
38267cc577a4SJonathan Peyton   } else if (packed_reduction_method == atomic_reduce_block) {
38277cc577a4SJonathan Peyton 
38287cc577a4SJonathan Peyton     retval = 2;
38297cc577a4SJonathan Peyton 
38303041982dSJonathan Peyton   } else if (TEST_REDUCTION_METHOD(packed_reduction_method,
38313041982dSJonathan Peyton                                    tree_reduce_block)) {
38327cc577a4SJonathan Peyton 
38337cc577a4SJonathan Peyton // case tree_reduce_block:
38343041982dSJonathan Peyton // this barrier should be visible to a customer and to the threading profile
38353041982dSJonathan Peyton // tool (it's a terminating barrier on constructs if NOWAIT not specified)
383682e94a59SJoachim Protze #if OMPT_SUPPORT
38370e0d6cddSJoachim Protze     ompt_frame_t *ompt_frame;
383882e94a59SJoachim Protze     if (ompt_enabled.enabled) {
383982e94a59SJoachim Protze       __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL);
38400e0d6cddSJoachim Protze       if (ompt_frame->enter_frame.ptr == NULL)
38410e0d6cddSJoachim Protze         ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
384282e94a59SJoachim Protze     }
38436d3b8166SJoachim Protze     OMPT_STORE_RETURN_ADDRESS(global_tid);
384482e94a59SJoachim Protze #endif
38457cc577a4SJonathan Peyton #if USE_ITT_NOTIFY
38463041982dSJonathan Peyton     __kmp_threads[global_tid]->th.th_ident =
38473041982dSJonathan Peyton         loc; // needed for correct notification of frames
38487cc577a4SJonathan Peyton #endif
38493041982dSJonathan Peyton     retval =
38503041982dSJonathan Peyton         __kmp_barrier(UNPACK_REDUCTION_BARRIER(packed_reduction_method),
38513041982dSJonathan Peyton                       global_tid, TRUE, reduce_size, reduce_data, reduce_func);
38527cc577a4SJonathan Peyton     retval = (retval != 0) ? (0) : (1);
385382e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
385482e94a59SJoachim Protze     if (ompt_enabled.enabled) {
38550e0d6cddSJoachim Protze       ompt_frame->enter_frame = ompt_data_none;
385682e94a59SJoachim Protze     }
385782e94a59SJoachim Protze #endif
38587cc577a4SJonathan Peyton 
385997d000cfStlwilmar     // all other workers except primary thread should do this pop here
386097d000cfStlwilmar     // (none of other workers except primary will enter __kmpc_end_reduce())
38617cc577a4SJonathan Peyton     if (__kmp_env_consistency_check) {
386297d000cfStlwilmar       if (retval == 0) { // 0: all other workers; 1: primary thread
38637cc577a4SJonathan Peyton         __kmp_pop_sync(global_tid, ct_reduce, loc);
38647cc577a4SJonathan Peyton       }
38657cc577a4SJonathan Peyton     }
38667cc577a4SJonathan Peyton 
38677cc577a4SJonathan Peyton   } else {
38687cc577a4SJonathan Peyton 
38697cc577a4SJonathan Peyton     // should never reach this block
38707cc577a4SJonathan Peyton     KMP_ASSERT(0); // "unexpected method"
38717cc577a4SJonathan Peyton   }
3872a4ca525cSJonas Hahnfeld   if (teams_swapped) {
3873a4ca525cSJonas Hahnfeld     __kmp_restore_swapped_teams(th, team, task_state);
3874a4ca525cSJonas Hahnfeld   }
38757cc577a4SJonathan Peyton 
38763041982dSJonathan Peyton   KA_TRACE(10,
38773041982dSJonathan Peyton            ("__kmpc_reduce() exit: called T#%d: method %08x, returns %08x\n",
38783041982dSJonathan Peyton             global_tid, packed_reduction_method, retval));
38797cc577a4SJonathan Peyton   return retval;
38807cc577a4SJonathan Peyton }
38817cc577a4SJonathan Peyton 
38827cc577a4SJonathan Peyton /*!
38837cc577a4SJonathan Peyton @ingroup SYNCHRONIZATION
38847cc577a4SJonathan Peyton @param loc source location information
38857cc577a4SJonathan Peyton @param global_tid global thread id.
38867cc577a4SJonathan Peyton @param lck pointer to the unique lock data structure
38877cc577a4SJonathan Peyton 
38887cc577a4SJonathan Peyton Finish the execution of a blocking reduce.
38893041982dSJonathan Peyton The <tt>lck</tt> pointer must be the same as that used in the corresponding
38903041982dSJonathan Peyton start function.
38917cc577a4SJonathan Peyton */
__kmpc_end_reduce(ident_t * loc,kmp_int32 global_tid,kmp_critical_name * lck)38923041982dSJonathan Peyton void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
38933041982dSJonathan Peyton                        kmp_critical_name *lck) {
38947cc577a4SJonathan Peyton 
38957cc577a4SJonathan Peyton   PACKED_REDUCTION_METHOD_T packed_reduction_method;
3896a4ca525cSJonas Hahnfeld   kmp_info_t *th;
3897a4ca525cSJonas Hahnfeld   kmp_team_t *team;
3898a4ca525cSJonas Hahnfeld   int teams_swapped = 0, task_state;
38997cc577a4SJonathan Peyton 
39007cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmpc_end_reduce() enter: called T#%d\n", global_tid));
3901787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(global_tid);
39027cc577a4SJonathan Peyton 
3903a4ca525cSJonas Hahnfeld   th = __kmp_thread_from_gtid(global_tid);
3904a4ca525cSJonas Hahnfeld   teams_swapped = __kmp_swap_teams_for_teams_reduction(th, &team, &task_state);
3905a4ca525cSJonas Hahnfeld 
39067cc577a4SJonathan Peyton   packed_reduction_method = __KMP_GET_REDUCTION_METHOD(global_tid);
39077cc577a4SJonathan Peyton 
39083041982dSJonathan Peyton   // this barrier should be visible to a customer and to the threading profile
39093041982dSJonathan Peyton   // tool (it's a terminating barrier on constructs if NOWAIT not specified)
39103356e268S[email protected]   OMPT_REDUCTION_DECL(th, global_tid);
39117cc577a4SJonathan Peyton 
39127cc577a4SJonathan Peyton   if (packed_reduction_method == critical_reduce_block) {
39137cc577a4SJonathan Peyton     __kmp_end_critical_section_reduce_block(loc, global_tid, lck);
39147cc577a4SJonathan Peyton 
39153356e268S[email protected]     OMPT_REDUCTION_END;
39163356e268S[email protected] 
39177cc577a4SJonathan Peyton // TODO: implicit barrier: should be exposed
391882e94a59SJoachim Protze #if OMPT_SUPPORT
39190e0d6cddSJoachim Protze     ompt_frame_t *ompt_frame;
392082e94a59SJoachim Protze     if (ompt_enabled.enabled) {
392182e94a59SJoachim Protze       __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL);
39220e0d6cddSJoachim Protze       if (ompt_frame->enter_frame.ptr == NULL)
39230e0d6cddSJoachim Protze         ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
392482e94a59SJoachim Protze     }
39256d3b8166SJoachim Protze     OMPT_STORE_RETURN_ADDRESS(global_tid);
392682e94a59SJoachim Protze #endif
39277cc577a4SJonathan Peyton #if USE_ITT_NOTIFY
39287cc577a4SJonathan Peyton     __kmp_threads[global_tid]->th.th_ident = loc;
39297cc577a4SJonathan Peyton #endif
39307cc577a4SJonathan Peyton     __kmp_barrier(bs_plain_barrier, global_tid, FALSE, 0, NULL, NULL);
393182e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
393282e94a59SJoachim Protze     if (ompt_enabled.enabled) {
39330e0d6cddSJoachim Protze       ompt_frame->enter_frame = ompt_data_none;
393482e94a59SJoachim Protze     }
393582e94a59SJoachim Protze #endif
39367cc577a4SJonathan Peyton 
39377cc577a4SJonathan Peyton   } else if (packed_reduction_method == empty_reduce_block) {
39387cc577a4SJonathan Peyton 
39393356e268S[email protected]     OMPT_REDUCTION_END;
39403356e268S[email protected] 
39417cc577a4SJonathan Peyton // usage: if team size==1, no synchronization is required (Intel platforms only)
39427cc577a4SJonathan Peyton 
39437cc577a4SJonathan Peyton // TODO: implicit barrier: should be exposed
394482e94a59SJoachim Protze #if OMPT_SUPPORT
39450e0d6cddSJoachim Protze     ompt_frame_t *ompt_frame;
394682e94a59SJoachim Protze     if (ompt_enabled.enabled) {
394782e94a59SJoachim Protze       __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL);
39480e0d6cddSJoachim Protze       if (ompt_frame->enter_frame.ptr == NULL)
39490e0d6cddSJoachim Protze         ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
395082e94a59SJoachim Protze     }
39516d3b8166SJoachim Protze     OMPT_STORE_RETURN_ADDRESS(global_tid);
395282e94a59SJoachim Protze #endif
39537cc577a4SJonathan Peyton #if USE_ITT_NOTIFY
39547cc577a4SJonathan Peyton     __kmp_threads[global_tid]->th.th_ident = loc;
39557cc577a4SJonathan Peyton #endif
39567cc577a4SJonathan Peyton     __kmp_barrier(bs_plain_barrier, global_tid, FALSE, 0, NULL, NULL);
395782e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
395882e94a59SJoachim Protze     if (ompt_enabled.enabled) {
39590e0d6cddSJoachim Protze       ompt_frame->enter_frame = ompt_data_none;
396082e94a59SJoachim Protze     }
396182e94a59SJoachim Protze #endif
39627cc577a4SJonathan Peyton 
39637cc577a4SJonathan Peyton   } else if (packed_reduction_method == atomic_reduce_block) {
39647cc577a4SJonathan Peyton 
396582e94a59SJoachim Protze #if OMPT_SUPPORT
39660e0d6cddSJoachim Protze     ompt_frame_t *ompt_frame;
396782e94a59SJoachim Protze     if (ompt_enabled.enabled) {
396882e94a59SJoachim Protze       __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL);
39690e0d6cddSJoachim Protze       if (ompt_frame->enter_frame.ptr == NULL)
39700e0d6cddSJoachim Protze         ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
397182e94a59SJoachim Protze     }
39726d3b8166SJoachim Protze     OMPT_STORE_RETURN_ADDRESS(global_tid);
397382e94a59SJoachim Protze #endif
39747cc577a4SJonathan Peyton // TODO: implicit barrier: should be exposed
39757cc577a4SJonathan Peyton #if USE_ITT_NOTIFY
39767cc577a4SJonathan Peyton     __kmp_threads[global_tid]->th.th_ident = loc;
39777cc577a4SJonathan Peyton #endif
39787cc577a4SJonathan Peyton     __kmp_barrier(bs_plain_barrier, global_tid, FALSE, 0, NULL, NULL);
397982e94a59SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
398082e94a59SJoachim Protze     if (ompt_enabled.enabled) {
39810e0d6cddSJoachim Protze       ompt_frame->enter_frame = ompt_data_none;
398282e94a59SJoachim Protze     }
398382e94a59SJoachim Protze #endif
39847cc577a4SJonathan Peyton 
39853041982dSJonathan Peyton   } else if (TEST_REDUCTION_METHOD(packed_reduction_method,
39863041982dSJonathan Peyton                                    tree_reduce_block)) {
39877cc577a4SJonathan Peyton 
398897d000cfStlwilmar     // only primary thread executes here (primary releases all other workers)
39893041982dSJonathan Peyton     __kmp_end_split_barrier(UNPACK_REDUCTION_BARRIER(packed_reduction_method),
39903041982dSJonathan Peyton                             global_tid);
39917cc577a4SJonathan Peyton 
39927cc577a4SJonathan Peyton   } else {
39937cc577a4SJonathan Peyton 
39947cc577a4SJonathan Peyton     // should never reach this block
39957cc577a4SJonathan Peyton     KMP_ASSERT(0); // "unexpected method"
39967cc577a4SJonathan Peyton   }
3997a4ca525cSJonas Hahnfeld   if (teams_swapped) {
3998a4ca525cSJonas Hahnfeld     __kmp_restore_swapped_teams(th, team, task_state);
3999a4ca525cSJonas Hahnfeld   }
40007cc577a4SJonathan Peyton 
40017cc577a4SJonathan Peyton   if (__kmp_env_consistency_check)
40027cc577a4SJonathan Peyton     __kmp_pop_sync(global_tid, ct_reduce, loc);
40037cc577a4SJonathan Peyton 
40043041982dSJonathan Peyton   KA_TRACE(10, ("__kmpc_end_reduce() exit: called T#%d: method %08x\n",
40053041982dSJonathan Peyton                 global_tid, packed_reduction_method));
40067cc577a4SJonathan Peyton 
40077cc577a4SJonathan Peyton   return;
40087cc577a4SJonathan Peyton }
40097cc577a4SJonathan Peyton 
40107cc577a4SJonathan Peyton #undef __KMP_GET_REDUCTION_METHOD
40117cc577a4SJonathan Peyton #undef __KMP_SET_REDUCTION_METHOD
40127cc577a4SJonathan Peyton 
40133041982dSJonathan Peyton /* end of interface to fast scalable reduce routines */
40147cc577a4SJonathan Peyton 
__kmpc_get_taskid()40153041982dSJonathan Peyton kmp_uint64 __kmpc_get_taskid() {
40167cc577a4SJonathan Peyton 
40177cc577a4SJonathan Peyton   kmp_int32 gtid;
40187cc577a4SJonathan Peyton   kmp_info_t *thread;
40197cc577a4SJonathan Peyton 
40207cc577a4SJonathan Peyton   gtid = __kmp_get_gtid();
40217cc577a4SJonathan Peyton   if (gtid < 0) {
40227cc577a4SJonathan Peyton     return 0;
4023bd3a7633SJonathan Peyton   }
40247cc577a4SJonathan Peyton   thread = __kmp_thread_from_gtid(gtid);
40257cc577a4SJonathan Peyton   return thread->th.th_current_task->td_task_id;
40267cc577a4SJonathan Peyton 
40277cc577a4SJonathan Peyton } // __kmpc_get_taskid
40287cc577a4SJonathan Peyton 
__kmpc_get_parent_taskid()40293041982dSJonathan Peyton kmp_uint64 __kmpc_get_parent_taskid() {
40307cc577a4SJonathan Peyton 
40317cc577a4SJonathan Peyton   kmp_int32 gtid;
40327cc577a4SJonathan Peyton   kmp_info_t *thread;
40337cc577a4SJonathan Peyton   kmp_taskdata_t *parent_task;
40347cc577a4SJonathan Peyton 
40357cc577a4SJonathan Peyton   gtid = __kmp_get_gtid();
40367cc577a4SJonathan Peyton   if (gtid < 0) {
40377cc577a4SJonathan Peyton     return 0;
4038bd3a7633SJonathan Peyton   }
40397cc577a4SJonathan Peyton   thread = __kmp_thread_from_gtid(gtid);
40407cc577a4SJonathan Peyton   parent_task = thread->th.th_current_task->td_parent;
40417cc577a4SJonathan Peyton   return (parent_task == NULL ? 0 : parent_task->td_task_id);
40427cc577a4SJonathan Peyton 
40437cc577a4SJonathan Peyton } // __kmpc_get_parent_taskid
40447cc577a4SJonathan Peyton 
40457cc577a4SJonathan Peyton /*!
40467cc577a4SJonathan Peyton @ingroup WORK_SHARING
40477cc577a4SJonathan Peyton @param loc  source location information.
40487cc577a4SJonathan Peyton @param gtid  global thread number.
40497cc577a4SJonathan Peyton @param num_dims  number of associated doacross loops.
40507cc577a4SJonathan Peyton @param dims  info on loops bounds.
40517cc577a4SJonathan Peyton 
40527cc577a4SJonathan Peyton Initialize doacross loop information.
40537cc577a4SJonathan Peyton Expect compiler send us inclusive bounds,
40547cc577a4SJonathan Peyton e.g. for(i=2;i<9;i+=2) lo=2, up=8, st=2.
40557cc577a4SJonathan Peyton */
__kmpc_doacross_init(ident_t * loc,int gtid,int num_dims,const struct kmp_dim * dims)40563041982dSJonathan Peyton void __kmpc_doacross_init(ident_t *loc, int gtid, int num_dims,
4057369d72dbSJonathan Peyton                           const struct kmp_dim *dims) {
4058787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(gtid);
40597cc577a4SJonathan Peyton   int j, idx;
40607cc577a4SJonathan Peyton   kmp_int64 last, trace_count;
40617cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[gtid];
40627cc577a4SJonathan Peyton   kmp_team_t *team = th->th.th_team;
40637cc577a4SJonathan Peyton   kmp_uint32 *flags;
40647cc577a4SJonathan Peyton   kmp_disp_t *pr_buf = th->th.th_dispatch;
40657cc577a4SJonathan Peyton   dispatch_shared_info_t *sh_buf;
40667cc577a4SJonathan Peyton 
40673041982dSJonathan Peyton   KA_TRACE(
40683041982dSJonathan Peyton       20,
40693041982dSJonathan Peyton       ("__kmpc_doacross_init() enter: called T#%d, num dims %d, active %d\n",
40707cc577a4SJonathan Peyton        gtid, num_dims, !team->t.t_serialized));
40717cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(dims != NULL);
40727cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(num_dims > 0);
40737cc577a4SJonathan Peyton 
40747cc577a4SJonathan Peyton   if (team->t.t_serialized) {
40757cc577a4SJonathan Peyton     KA_TRACE(20, ("__kmpc_doacross_init() exit: serialized team\n"));
40767cc577a4SJonathan Peyton     return; // no dependencies if team is serialized
40777cc577a4SJonathan Peyton   }
40787cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(team->t.t_nproc > 1);
40793041982dSJonathan Peyton   idx = pr_buf->th_doacross_buf_idx++; // Increment index of shared buffer for
40803041982dSJonathan Peyton   // the next loop
40817cc577a4SJonathan Peyton   sh_buf = &team->t.t_disp_buffer[idx % __kmp_dispatch_num_buffers];
40827cc577a4SJonathan Peyton 
40837cc577a4SJonathan Peyton   // Save bounds info into allocated private buffer
40847cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(pr_buf->th_doacross_info == NULL);
40853041982dSJonathan Peyton   pr_buf->th_doacross_info = (kmp_int64 *)__kmp_thread_malloc(
40863041982dSJonathan Peyton       th, sizeof(kmp_int64) * (4 * num_dims + 1));
40877cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(pr_buf->th_doacross_info != NULL);
40883041982dSJonathan Peyton   pr_buf->th_doacross_info[0] =
40893041982dSJonathan Peyton       (kmp_int64)num_dims; // first element is number of dimensions
40903041982dSJonathan Peyton   // Save also address of num_done in order to access it later without knowing
40913041982dSJonathan Peyton   // the buffer index
40927cc577a4SJonathan Peyton   pr_buf->th_doacross_info[1] = (kmp_int64)&sh_buf->doacross_num_done;
40937cc577a4SJonathan Peyton   pr_buf->th_doacross_info[2] = dims[0].lo;
40947cc577a4SJonathan Peyton   pr_buf->th_doacross_info[3] = dims[0].up;
40957cc577a4SJonathan Peyton   pr_buf->th_doacross_info[4] = dims[0].st;
40967cc577a4SJonathan Peyton   last = 5;
40977cc577a4SJonathan Peyton   for (j = 1; j < num_dims; ++j) {
40983041982dSJonathan Peyton     kmp_int64
40993041982dSJonathan Peyton         range_length; // To keep ranges of all dimensions but the first dims[0]
41007cc577a4SJonathan Peyton     if (dims[j].st == 1) { // most common case
41017cc577a4SJonathan Peyton       // AC: should we care of ranges bigger than LLONG_MAX? (not for now)
41027cc577a4SJonathan Peyton       range_length = dims[j].up - dims[j].lo + 1;
41037cc577a4SJonathan Peyton     } else {
41047cc577a4SJonathan Peyton       if (dims[j].st > 0) {
41057cc577a4SJonathan Peyton         KMP_DEBUG_ASSERT(dims[j].up > dims[j].lo);
41067cc577a4SJonathan Peyton         range_length = (kmp_uint64)(dims[j].up - dims[j].lo) / dims[j].st + 1;
41077cc577a4SJonathan Peyton       } else { // negative increment
41087cc577a4SJonathan Peyton         KMP_DEBUG_ASSERT(dims[j].lo > dims[j].up);
41093041982dSJonathan Peyton         range_length =
41103041982dSJonathan Peyton             (kmp_uint64)(dims[j].lo - dims[j].up) / (-dims[j].st) + 1;
41117cc577a4SJonathan Peyton       }
41127cc577a4SJonathan Peyton     }
41137cc577a4SJonathan Peyton     pr_buf->th_doacross_info[last++] = range_length;
41147cc577a4SJonathan Peyton     pr_buf->th_doacross_info[last++] = dims[j].lo;
41157cc577a4SJonathan Peyton     pr_buf->th_doacross_info[last++] = dims[j].up;
41167cc577a4SJonathan Peyton     pr_buf->th_doacross_info[last++] = dims[j].st;
41177cc577a4SJonathan Peyton   }
41187cc577a4SJonathan Peyton 
41197cc577a4SJonathan Peyton   // Compute total trip count.
41207cc577a4SJonathan Peyton   // Start with range of dims[0] which we don't need to keep in the buffer.
41217cc577a4SJonathan Peyton   if (dims[0].st == 1) { // most common case
41227cc577a4SJonathan Peyton     trace_count = dims[0].up - dims[0].lo + 1;
41237cc577a4SJonathan Peyton   } else if (dims[0].st > 0) {
41247cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT(dims[0].up > dims[0].lo);
41257cc577a4SJonathan Peyton     trace_count = (kmp_uint64)(dims[0].up - dims[0].lo) / dims[0].st + 1;
41267cc577a4SJonathan Peyton   } else { // negative increment
41277cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT(dims[0].lo > dims[0].up);
41287cc577a4SJonathan Peyton     trace_count = (kmp_uint64)(dims[0].lo - dims[0].up) / (-dims[0].st) + 1;
41297cc577a4SJonathan Peyton   }
41307cc577a4SJonathan Peyton   for (j = 1; j < num_dims; ++j) {
41317cc577a4SJonathan Peyton     trace_count *= pr_buf->th_doacross_info[4 * j + 1]; // use kept ranges
41327cc577a4SJonathan Peyton   }
41337cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(trace_count > 0);
41347cc577a4SJonathan Peyton 
41353041982dSJonathan Peyton   // Check if shared buffer is not occupied by other loop (idx -
41363041982dSJonathan Peyton   // __kmp_dispatch_num_buffers)
41377cc577a4SJonathan Peyton   if (idx != sh_buf->doacross_buf_idx) {
41387cc577a4SJonathan Peyton     // Shared buffer is occupied, wait for it to be free
4139e47d32f1SJonathan Peyton     __kmp_wait_4((volatile kmp_uint32 *)&sh_buf->doacross_buf_idx, idx,
4140c47afcd9SAndrey Churbanov                  __kmp_eq_4, NULL);
41417cc577a4SJonathan Peyton   }
414258acafc4SAndrey Churbanov #if KMP_32_BIT_ARCH
41437cc577a4SJonathan Peyton   // Check if we are the first thread. After the CAS the first thread gets 0,
41447cc577a4SJonathan Peyton   // others get 1 if initialization is in progress, allocated pointer otherwise.
414558acafc4SAndrey Churbanov   // Treat pointer as volatile integer (value 0 or 1) until memory is allocated.
414658acafc4SAndrey Churbanov   flags = (kmp_uint32 *)KMP_COMPARE_AND_STORE_RET32(
414758acafc4SAndrey Churbanov       (volatile kmp_int32 *)&sh_buf->doacross_flags, NULL, 1);
414858acafc4SAndrey Churbanov #else
41497cc577a4SJonathan Peyton   flags = (kmp_uint32 *)KMP_COMPARE_AND_STORE_RET64(
415058acafc4SAndrey Churbanov       (volatile kmp_int64 *)&sh_buf->doacross_flags, NULL, 1LL);
415158acafc4SAndrey Churbanov #endif
41527cc577a4SJonathan Peyton   if (flags == NULL) {
41537cc577a4SJonathan Peyton     // we are the first thread, allocate the array of flags
41546b316febSTerry Wilmarth     size_t size =
41556b316febSTerry Wilmarth         (size_t)trace_count / 8 + 8; // in bytes, use single bit per iteration
4156221e7bb1SJonas Hahnfeld     flags = (kmp_uint32 *)__kmp_thread_calloc(th, size, 1);
4157221e7bb1SJonas Hahnfeld     KMP_MB();
4158221e7bb1SJonas Hahnfeld     sh_buf->doacross_flags = flags;
415958acafc4SAndrey Churbanov   } else if (flags == (kmp_uint32 *)1) {
416058acafc4SAndrey Churbanov #if KMP_32_BIT_ARCH
41617cc577a4SJonathan Peyton     // initialization is still in progress, need to wait
416258acafc4SAndrey Churbanov     while (*(volatile kmp_int32 *)&sh_buf->doacross_flags == 1)
416358acafc4SAndrey Churbanov #else
416458acafc4SAndrey Churbanov     while (*(volatile kmp_int64 *)&sh_buf->doacross_flags == 1LL)
416558acafc4SAndrey Churbanov #endif
41667cc577a4SJonathan Peyton       KMP_YIELD(TRUE);
4167221e7bb1SJonas Hahnfeld     KMP_MB();
4168221e7bb1SJonas Hahnfeld   } else {
4169221e7bb1SJonas Hahnfeld     KMP_MB();
41707cc577a4SJonathan Peyton   }
417158acafc4SAndrey Churbanov   KMP_DEBUG_ASSERT(sh_buf->doacross_flags > (kmp_uint32 *)1); // check ptr value
41723041982dSJonathan Peyton   pr_buf->th_doacross_flags =
41733041982dSJonathan Peyton       sh_buf->doacross_flags; // save private copy in order to not
41747cc577a4SJonathan Peyton   // touch shared buffer on each iteration
41757cc577a4SJonathan Peyton   KA_TRACE(20, ("__kmpc_doacross_init() exit: T#%d\n", gtid));
41767cc577a4SJonathan Peyton }
41777cc577a4SJonathan Peyton 
__kmpc_doacross_wait(ident_t * loc,int gtid,const kmp_int64 * vec)4178369d72dbSJonathan Peyton void __kmpc_doacross_wait(ident_t *loc, int gtid, const kmp_int64 *vec) {
4179787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(gtid);
41806b316febSTerry Wilmarth   kmp_int64 shft;
41816b316febSTerry Wilmarth   size_t num_dims, i;
41827cc577a4SJonathan Peyton   kmp_uint32 flag;
41837cc577a4SJonathan Peyton   kmp_int64 iter_number; // iteration number of "collapsed" loop nest
41847cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[gtid];
41857cc577a4SJonathan Peyton   kmp_team_t *team = th->th.th_team;
41867cc577a4SJonathan Peyton   kmp_disp_t *pr_buf;
41877cc577a4SJonathan Peyton   kmp_int64 lo, up, st;
41887cc577a4SJonathan Peyton 
41897cc577a4SJonathan Peyton   KA_TRACE(20, ("__kmpc_doacross_wait() enter: called T#%d\n", gtid));
41907cc577a4SJonathan Peyton   if (team->t.t_serialized) {
41917cc577a4SJonathan Peyton     KA_TRACE(20, ("__kmpc_doacross_wait() exit: serialized team\n"));
41927cc577a4SJonathan Peyton     return; // no dependencies if team is serialized
41937cc577a4SJonathan Peyton   }
41947cc577a4SJonathan Peyton 
41957cc577a4SJonathan Peyton   // calculate sequential iteration number and check out-of-bounds condition
41967cc577a4SJonathan Peyton   pr_buf = th->th.th_dispatch;
41977cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(pr_buf->th_doacross_info != NULL);
41986b316febSTerry Wilmarth   num_dims = (size_t)pr_buf->th_doacross_info[0];
41997cc577a4SJonathan Peyton   lo = pr_buf->th_doacross_info[2];
42007cc577a4SJonathan Peyton   up = pr_buf->th_doacross_info[3];
42017cc577a4SJonathan Peyton   st = pr_buf->th_doacross_info[4];
4202cbea3690SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
4203cbea3690SJoachim Protze   ompt_dependence_t deps[num_dims];
4204cbea3690SJoachim Protze #endif
42057cc577a4SJonathan Peyton   if (st == 1) { // most common case
42067cc577a4SJonathan Peyton     if (vec[0] < lo || vec[0] > up) {
42073041982dSJonathan Peyton       KA_TRACE(20, ("__kmpc_doacross_wait() exit: T#%d iter %lld is out of "
42083041982dSJonathan Peyton                     "bounds [%lld,%lld]\n",
42097cc577a4SJonathan Peyton                     gtid, vec[0], lo, up));
42107cc577a4SJonathan Peyton       return;
42117cc577a4SJonathan Peyton     }
42127cc577a4SJonathan Peyton     iter_number = vec[0] - lo;
42137cc577a4SJonathan Peyton   } else if (st > 0) {
42147cc577a4SJonathan Peyton     if (vec[0] < lo || vec[0] > up) {
42153041982dSJonathan Peyton       KA_TRACE(20, ("__kmpc_doacross_wait() exit: T#%d iter %lld is out of "
42163041982dSJonathan Peyton                     "bounds [%lld,%lld]\n",
42177cc577a4SJonathan Peyton                     gtid, vec[0], lo, up));
42187cc577a4SJonathan Peyton       return;
42197cc577a4SJonathan Peyton     }
42207cc577a4SJonathan Peyton     iter_number = (kmp_uint64)(vec[0] - lo) / st;
42217cc577a4SJonathan Peyton   } else { // negative increment
42227cc577a4SJonathan Peyton     if (vec[0] > lo || vec[0] < up) {
42233041982dSJonathan Peyton       KA_TRACE(20, ("__kmpc_doacross_wait() exit: T#%d iter %lld is out of "
42243041982dSJonathan Peyton                     "bounds [%lld,%lld]\n",
42257cc577a4SJonathan Peyton                     gtid, vec[0], lo, up));
42267cc577a4SJonathan Peyton       return;
42277cc577a4SJonathan Peyton     }
42287cc577a4SJonathan Peyton     iter_number = (kmp_uint64)(lo - vec[0]) / (-st);
42297cc577a4SJonathan Peyton   }
4230cbea3690SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
4231cbea3690SJoachim Protze   deps[0].variable.value = iter_number;
4232cbea3690SJoachim Protze   deps[0].dependence_type = ompt_dependence_type_sink;
4233cbea3690SJoachim Protze #endif
42347cc577a4SJonathan Peyton   for (i = 1; i < num_dims; ++i) {
42357cc577a4SJonathan Peyton     kmp_int64 iter, ln;
42366b316febSTerry Wilmarth     size_t j = i * 4;
42377cc577a4SJonathan Peyton     ln = pr_buf->th_doacross_info[j + 1];
42387cc577a4SJonathan Peyton     lo = pr_buf->th_doacross_info[j + 2];
42397cc577a4SJonathan Peyton     up = pr_buf->th_doacross_info[j + 3];
42407cc577a4SJonathan Peyton     st = pr_buf->th_doacross_info[j + 4];
42417cc577a4SJonathan Peyton     if (st == 1) {
42427cc577a4SJonathan Peyton       if (vec[i] < lo || vec[i] > up) {
42433041982dSJonathan Peyton         KA_TRACE(20, ("__kmpc_doacross_wait() exit: T#%d iter %lld is out of "
42443041982dSJonathan Peyton                       "bounds [%lld,%lld]\n",
42457cc577a4SJonathan Peyton                       gtid, vec[i], lo, up));
42467cc577a4SJonathan Peyton         return;
42477cc577a4SJonathan Peyton       }
42487cc577a4SJonathan Peyton       iter = vec[i] - lo;
42497cc577a4SJonathan Peyton     } else if (st > 0) {
42507cc577a4SJonathan Peyton       if (vec[i] < lo || vec[i] > up) {
42513041982dSJonathan Peyton         KA_TRACE(20, ("__kmpc_doacross_wait() exit: T#%d iter %lld is out of "
42523041982dSJonathan Peyton                       "bounds [%lld,%lld]\n",
42537cc577a4SJonathan Peyton                       gtid, vec[i], lo, up));
42547cc577a4SJonathan Peyton         return;
42557cc577a4SJonathan Peyton       }
42567cc577a4SJonathan Peyton       iter = (kmp_uint64)(vec[i] - lo) / st;
42577cc577a4SJonathan Peyton     } else { // st < 0
42587cc577a4SJonathan Peyton       if (vec[i] > lo || vec[i] < up) {
42593041982dSJonathan Peyton         KA_TRACE(20, ("__kmpc_doacross_wait() exit: T#%d iter %lld is out of "
42603041982dSJonathan Peyton                       "bounds [%lld,%lld]\n",
42617cc577a4SJonathan Peyton                       gtid, vec[i], lo, up));
42627cc577a4SJonathan Peyton         return;
42637cc577a4SJonathan Peyton       }
42647cc577a4SJonathan Peyton       iter = (kmp_uint64)(lo - vec[i]) / (-st);
42657cc577a4SJonathan Peyton     }
42667cc577a4SJonathan Peyton     iter_number = iter + ln * iter_number;
4267cbea3690SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
4268cbea3690SJoachim Protze     deps[i].variable.value = iter;
4269cbea3690SJoachim Protze     deps[i].dependence_type = ompt_dependence_type_sink;
4270cbea3690SJoachim Protze #endif
42717cc577a4SJonathan Peyton   }
42727cc577a4SJonathan Peyton   shft = iter_number % 32; // use 32-bit granularity
42737cc577a4SJonathan Peyton   iter_number >>= 5; // divided by 32
42747cc577a4SJonathan Peyton   flag = 1 << shft;
42757cc577a4SJonathan Peyton   while ((flag & pr_buf->th_doacross_flags[iter_number]) == 0) {
42767cc577a4SJonathan Peyton     KMP_YIELD(TRUE);
42777cc577a4SJonathan Peyton   }
4278221e7bb1SJonas Hahnfeld   KMP_MB();
4279cbea3690SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
4280cbea3690SJoachim Protze   if (ompt_enabled.ompt_callback_dependences) {
4281cbea3690SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_dependences)(
42826b316febSTerry Wilmarth         &(OMPT_CUR_TASK_INFO(th)->task_data), deps, (kmp_uint32)num_dims);
4283cbea3690SJoachim Protze   }
4284cbea3690SJoachim Protze #endif
42853041982dSJonathan Peyton   KA_TRACE(20,
42863041982dSJonathan Peyton            ("__kmpc_doacross_wait() exit: T#%d wait for iter %lld completed\n",
42877cc577a4SJonathan Peyton             gtid, (iter_number << 5) + shft));
42887cc577a4SJonathan Peyton }
42897cc577a4SJonathan Peyton 
__kmpc_doacross_post(ident_t * loc,int gtid,const kmp_int64 * vec)4290369d72dbSJonathan Peyton void __kmpc_doacross_post(ident_t *loc, int gtid, const kmp_int64 *vec) {
4291787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(gtid);
42926b316febSTerry Wilmarth   kmp_int64 shft;
42936b316febSTerry Wilmarth   size_t num_dims, i;
42947cc577a4SJonathan Peyton   kmp_uint32 flag;
42957cc577a4SJonathan Peyton   kmp_int64 iter_number; // iteration number of "collapsed" loop nest
42967cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[gtid];
42977cc577a4SJonathan Peyton   kmp_team_t *team = th->th.th_team;
42987cc577a4SJonathan Peyton   kmp_disp_t *pr_buf;
42997cc577a4SJonathan Peyton   kmp_int64 lo, st;
43007cc577a4SJonathan Peyton 
43017cc577a4SJonathan Peyton   KA_TRACE(20, ("__kmpc_doacross_post() enter: called T#%d\n", gtid));
43027cc577a4SJonathan Peyton   if (team->t.t_serialized) {
43037cc577a4SJonathan Peyton     KA_TRACE(20, ("__kmpc_doacross_post() exit: serialized team\n"));
43047cc577a4SJonathan Peyton     return; // no dependencies if team is serialized
43057cc577a4SJonathan Peyton   }
43067cc577a4SJonathan Peyton 
43073041982dSJonathan Peyton   // calculate sequential iteration number (same as in "wait" but no
43083041982dSJonathan Peyton   // out-of-bounds checks)
43097cc577a4SJonathan Peyton   pr_buf = th->th.th_dispatch;
43107cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(pr_buf->th_doacross_info != NULL);
43116b316febSTerry Wilmarth   num_dims = (size_t)pr_buf->th_doacross_info[0];
43127cc577a4SJonathan Peyton   lo = pr_buf->th_doacross_info[2];
43137cc577a4SJonathan Peyton   st = pr_buf->th_doacross_info[4];
4314cbea3690SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
4315cbea3690SJoachim Protze   ompt_dependence_t deps[num_dims];
4316cbea3690SJoachim Protze #endif
43177cc577a4SJonathan Peyton   if (st == 1) { // most common case
43187cc577a4SJonathan Peyton     iter_number = vec[0] - lo;
43197cc577a4SJonathan Peyton   } else if (st > 0) {
43207cc577a4SJonathan Peyton     iter_number = (kmp_uint64)(vec[0] - lo) / st;
43217cc577a4SJonathan Peyton   } else { // negative increment
43227cc577a4SJonathan Peyton     iter_number = (kmp_uint64)(lo - vec[0]) / (-st);
43237cc577a4SJonathan Peyton   }
4324cbea3690SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
4325cbea3690SJoachim Protze   deps[0].variable.value = iter_number;
4326cbea3690SJoachim Protze   deps[0].dependence_type = ompt_dependence_type_source;
4327cbea3690SJoachim Protze #endif
43287cc577a4SJonathan Peyton   for (i = 1; i < num_dims; ++i) {
43297cc577a4SJonathan Peyton     kmp_int64 iter, ln;
43306b316febSTerry Wilmarth     size_t j = i * 4;
43317cc577a4SJonathan Peyton     ln = pr_buf->th_doacross_info[j + 1];
43327cc577a4SJonathan Peyton     lo = pr_buf->th_doacross_info[j + 2];
43337cc577a4SJonathan Peyton     st = pr_buf->th_doacross_info[j + 4];
43347cc577a4SJonathan Peyton     if (st == 1) {
43357cc577a4SJonathan Peyton       iter = vec[i] - lo;
43367cc577a4SJonathan Peyton     } else if (st > 0) {
43377cc577a4SJonathan Peyton       iter = (kmp_uint64)(vec[i] - lo) / st;
43387cc577a4SJonathan Peyton     } else { // st < 0
43397cc577a4SJonathan Peyton       iter = (kmp_uint64)(lo - vec[i]) / (-st);
43407cc577a4SJonathan Peyton     }
43417cc577a4SJonathan Peyton     iter_number = iter + ln * iter_number;
4342cbea3690SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
4343cbea3690SJoachim Protze     deps[i].variable.value = iter;
4344cbea3690SJoachim Protze     deps[i].dependence_type = ompt_dependence_type_source;
4345cbea3690SJoachim Protze #endif
43467cc577a4SJonathan Peyton   }
4347cbea3690SJoachim Protze #if OMPT_SUPPORT && OMPT_OPTIONAL
4348cbea3690SJoachim Protze   if (ompt_enabled.ompt_callback_dependences) {
4349cbea3690SJoachim Protze     ompt_callbacks.ompt_callback(ompt_callback_dependences)(
43506b316febSTerry Wilmarth         &(OMPT_CUR_TASK_INFO(th)->task_data), deps, (kmp_uint32)num_dims);
4351cbea3690SJoachim Protze   }
4352cbea3690SJoachim Protze #endif
43537cc577a4SJonathan Peyton   shft = iter_number % 32; // use 32-bit granularity
43547cc577a4SJonathan Peyton   iter_number >>= 5; // divided by 32
43557cc577a4SJonathan Peyton   flag = 1 << shft;
4356221e7bb1SJonas Hahnfeld   KMP_MB();
43577cc577a4SJonathan Peyton   if ((flag & pr_buf->th_doacross_flags[iter_number]) == 0)
43585ba90c79SAndrey Churbanov     KMP_TEST_THEN_OR32(&pr_buf->th_doacross_flags[iter_number], flag);
43593041982dSJonathan Peyton   KA_TRACE(20, ("__kmpc_doacross_post() exit: T#%d iter %lld posted\n", gtid,
43603041982dSJonathan Peyton                 (iter_number << 5) + shft));
43617cc577a4SJonathan Peyton }
43627cc577a4SJonathan Peyton 
__kmpc_doacross_fini(ident_t * loc,int gtid)43633041982dSJonathan Peyton void __kmpc_doacross_fini(ident_t *loc, int gtid) {
4364787eb0c6SAndreyChurbanov   __kmp_assert_valid_gtid(gtid);
43653ffca790SJonas Hahnfeld   kmp_int32 num_done;
43667cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[gtid];
43677cc577a4SJonathan Peyton   kmp_team_t *team = th->th.th_team;
43687cc577a4SJonathan Peyton   kmp_disp_t *pr_buf = th->th.th_dispatch;
43697cc577a4SJonathan Peyton 
43707cc577a4SJonathan Peyton   KA_TRACE(20, ("__kmpc_doacross_fini() enter: called T#%d\n", gtid));
43717cc577a4SJonathan Peyton   if (team->t.t_serialized) {
43727cc577a4SJonathan Peyton     KA_TRACE(20, ("__kmpc_doacross_fini() exit: serialized team %p\n", team));
43737cc577a4SJonathan Peyton     return; // nothing to do
43747cc577a4SJonathan Peyton   }
43756b316febSTerry Wilmarth   num_done =
43766b316febSTerry Wilmarth       KMP_TEST_THEN_INC32((kmp_uintptr_t)(pr_buf->th_doacross_info[1])) + 1;
43777cc577a4SJonathan Peyton   if (num_done == th->th.th_team_nproc) {
43787cc577a4SJonathan Peyton     // we are the last thread, need to free shared resources
43797cc577a4SJonathan Peyton     int idx = pr_buf->th_doacross_buf_idx - 1;
43803041982dSJonathan Peyton     dispatch_shared_info_t *sh_buf =
43813041982dSJonathan Peyton         &team->t.t_disp_buffer[idx % __kmp_dispatch_num_buffers];
43823041982dSJonathan Peyton     KMP_DEBUG_ASSERT(pr_buf->th_doacross_info[1] ==
43833041982dSJonathan Peyton                      (kmp_int64)&sh_buf->doacross_num_done);
43843ffca790SJonas Hahnfeld     KMP_DEBUG_ASSERT(num_done == sh_buf->doacross_num_done);
43857cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT(idx == sh_buf->doacross_buf_idx);
4386c47afcd9SAndrey Churbanov     __kmp_thread_free(th, CCAST(kmp_uint32 *, sh_buf->doacross_flags));
43877cc577a4SJonathan Peyton     sh_buf->doacross_flags = NULL;
43887cc577a4SJonathan Peyton     sh_buf->doacross_num_done = 0;
43893041982dSJonathan Peyton     sh_buf->doacross_buf_idx +=
43903041982dSJonathan Peyton         __kmp_dispatch_num_buffers; // free buffer for future re-use
43917cc577a4SJonathan Peyton   }
43927cc577a4SJonathan Peyton   // free private resources (need to keep buffer index forever)
4393369d72dbSJonathan Peyton   pr_buf->th_doacross_flags = NULL;
43947cc577a4SJonathan Peyton   __kmp_thread_free(th, (void *)pr_buf->th_doacross_info);
43957cc577a4SJonathan Peyton   pr_buf->th_doacross_info = NULL;
43967cc577a4SJonathan Peyton   KA_TRACE(20, ("__kmpc_doacross_fini() exit: T#%d\n", gtid));
43977cc577a4SJonathan Peyton }
43987cc577a4SJonathan Peyton 
4399f5c0c917SAndreyChurbanov /* OpenMP 5.1 Memory Management routines */
omp_alloc(size_t size,omp_allocator_handle_t allocator)4400ebf1830bSJonathan Peyton void *omp_alloc(size_t size, omp_allocator_handle_t allocator) {
4401f5c0c917SAndreyChurbanov   return __kmp_alloc(__kmp_entry_gtid(), 0, size, allocator);
4402f5c0c917SAndreyChurbanov }
4403f5c0c917SAndreyChurbanov 
omp_aligned_alloc(size_t align,size_t size,omp_allocator_handle_t allocator)4404f5c0c917SAndreyChurbanov void *omp_aligned_alloc(size_t align, size_t size,
4405f5c0c917SAndreyChurbanov                         omp_allocator_handle_t allocator) {
4406f5c0c917SAndreyChurbanov   return __kmp_alloc(__kmp_entry_gtid(), align, size, allocator);
4407ebf1830bSJonathan Peyton }
4408ebf1830bSJonathan Peyton 
omp_calloc(size_t nmemb,size_t size,omp_allocator_handle_t allocator)4409938f1b85SNawrin Sultana void *omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t allocator) {
4410f5c0c917SAndreyChurbanov   return __kmp_calloc(__kmp_entry_gtid(), 0, nmemb, size, allocator);
4411f5c0c917SAndreyChurbanov }
4412f5c0c917SAndreyChurbanov 
omp_aligned_calloc(size_t align,size_t nmemb,size_t size,omp_allocator_handle_t allocator)4413f5c0c917SAndreyChurbanov void *omp_aligned_calloc(size_t align, size_t nmemb, size_t size,
4414f5c0c917SAndreyChurbanov                          omp_allocator_handle_t allocator) {
4415f5c0c917SAndreyChurbanov   return __kmp_calloc(__kmp_entry_gtid(), align, nmemb, size, allocator);
4416938f1b85SNawrin Sultana }
4417938f1b85SNawrin Sultana 
omp_realloc(void * ptr,size_t size,omp_allocator_handle_t allocator,omp_allocator_handle_t free_allocator)44185439db05SNawrin Sultana void *omp_realloc(void *ptr, size_t size, omp_allocator_handle_t allocator,
44195439db05SNawrin Sultana                   omp_allocator_handle_t free_allocator) {
4420f5c0c917SAndreyChurbanov   return __kmp_realloc(__kmp_entry_gtid(), ptr, size, allocator,
44215439db05SNawrin Sultana                        free_allocator);
44225439db05SNawrin Sultana }
44235439db05SNawrin Sultana 
omp_free(void * ptr,omp_allocator_handle_t allocator)4424ebf1830bSJonathan Peyton void omp_free(void *ptr, omp_allocator_handle_t allocator) {
4425f5c0c917SAndreyChurbanov   ___kmpc_free(__kmp_entry_gtid(), ptr, allocator);
4426ebf1830bSJonathan Peyton }
4427f5c0c917SAndreyChurbanov /* end of OpenMP 5.1 Memory Management routines */
4428ebf1830bSJonathan Peyton 
__kmpc_get_target_offload(void)44292d91a8a3SAndrey Churbanov int __kmpc_get_target_offload(void) {
44302d91a8a3SAndrey Churbanov   if (!__kmp_init_serial) {
44312d91a8a3SAndrey Churbanov     __kmp_serial_initialize();
44322d91a8a3SAndrey Churbanov   }
44332d91a8a3SAndrey Churbanov   return __kmp_target_offload;
44342d91a8a3SAndrey Churbanov }
44359b8bb323SJonathan Peyton 
__kmpc_pause_resource(kmp_pause_status_t level)44369b8bb323SJonathan Peyton int __kmpc_pause_resource(kmp_pause_status_t level) {
44379b8bb323SJonathan Peyton   if (!__kmp_init_serial) {
44389b8bb323SJonathan Peyton     return 1; // Can't pause if runtime is not initialized
44399b8bb323SJonathan Peyton   }
44409b8bb323SJonathan Peyton   return __kmp_pause_resource(level);
44419b8bb323SJonathan Peyton }
4442a6f9cb6aSHansang Bae 
__kmpc_error(ident_t * loc,int severity,const char * message)4443a6f9cb6aSHansang Bae void __kmpc_error(ident_t *loc, int severity, const char *message) {
4444a6f9cb6aSHansang Bae   if (!__kmp_init_serial)
4445a6f9cb6aSHansang Bae     __kmp_serial_initialize();
4446a6f9cb6aSHansang Bae 
4447a6f9cb6aSHansang Bae   KMP_ASSERT(severity == severity_warning || severity == severity_fatal);
4448a6f9cb6aSHansang Bae 
4449a6f9cb6aSHansang Bae #if OMPT_SUPPORT
4450a6f9cb6aSHansang Bae   if (ompt_enabled.enabled && ompt_enabled.ompt_callback_error) {
4451a6f9cb6aSHansang Bae     ompt_callbacks.ompt_callback(ompt_callback_error)(
4452a6f9cb6aSHansang Bae         (ompt_severity_t)severity, message, KMP_STRLEN(message),
4453a6f9cb6aSHansang Bae         OMPT_GET_RETURN_ADDRESS(0));
4454a6f9cb6aSHansang Bae   }
4455a6f9cb6aSHansang Bae #endif // OMPT_SUPPORT
4456a6f9cb6aSHansang Bae 
4457a6f9cb6aSHansang Bae   char *src_loc;
4458a6f9cb6aSHansang Bae   if (loc && loc->psource) {
4459a6f9cb6aSHansang Bae     kmp_str_loc_t str_loc = __kmp_str_loc_init(loc->psource, false);
4460a6f9cb6aSHansang Bae     src_loc =
4461a6f9cb6aSHansang Bae         __kmp_str_format("%s:%s:%s", str_loc.file, str_loc.line, str_loc.col);
4462a6f9cb6aSHansang Bae     __kmp_str_loc_free(&str_loc);
4463a6f9cb6aSHansang Bae   } else {
4464a6f9cb6aSHansang Bae     src_loc = __kmp_str_format("unknown");
4465a6f9cb6aSHansang Bae   }
4466a6f9cb6aSHansang Bae 
4467a6f9cb6aSHansang Bae   if (severity == severity_warning)
4468a6f9cb6aSHansang Bae     KMP_WARNING(UserDirectedWarning, src_loc, message);
4469a6f9cb6aSHansang Bae   else
4470a6f9cb6aSHansang Bae     KMP_FATAL(UserDirectedError, src_loc, message);
4471a6f9cb6aSHansang Bae 
4472a6f9cb6aSHansang Bae   __kmp_str_free(&src_loc);
4473a6f9cb6aSHansang Bae }
447456da2824SPeyton, Jonathan L 
4475224f51d8SHansang Bae // Mark begin of scope directive.
__kmpc_scope(ident_t * loc,kmp_int32 gtid,void * reserved)4476224f51d8SHansang Bae void __kmpc_scope(ident_t *loc, kmp_int32 gtid, void *reserved) {
4477224f51d8SHansang Bae // reserved is for extension of scope directive and not used.
4478224f51d8SHansang Bae #if OMPT_SUPPORT && OMPT_OPTIONAL
4479224f51d8SHansang Bae   if (ompt_enabled.enabled && ompt_enabled.ompt_callback_work) {
4480224f51d8SHansang Bae     kmp_team_t *team = __kmp_threads[gtid]->th.th_team;
4481224f51d8SHansang Bae     int tid = __kmp_tid_from_gtid(gtid);
4482224f51d8SHansang Bae     ompt_callbacks.ompt_callback(ompt_callback_work)(
4483224f51d8SHansang Bae         ompt_work_scope, ompt_scope_begin,
4484224f51d8SHansang Bae         &(team->t.ompt_team_info.parallel_data),
4485224f51d8SHansang Bae         &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data), 1,
4486224f51d8SHansang Bae         OMPT_GET_RETURN_ADDRESS(0));
4487224f51d8SHansang Bae   }
4488224f51d8SHansang Bae #endif // OMPT_SUPPORT && OMPT_OPTIONAL
4489224f51d8SHansang Bae }
4490224f51d8SHansang Bae 
4491224f51d8SHansang Bae // Mark end of scope directive
__kmpc_end_scope(ident_t * loc,kmp_int32 gtid,void * reserved)4492224f51d8SHansang Bae void __kmpc_end_scope(ident_t *loc, kmp_int32 gtid, void *reserved) {
4493224f51d8SHansang Bae // reserved is for extension of scope directive and not used.
4494224f51d8SHansang Bae #if OMPT_SUPPORT && OMPT_OPTIONAL
4495224f51d8SHansang Bae   if (ompt_enabled.enabled && ompt_enabled.ompt_callback_work) {
4496224f51d8SHansang Bae     kmp_team_t *team = __kmp_threads[gtid]->th.th_team;
4497224f51d8SHansang Bae     int tid = __kmp_tid_from_gtid(gtid);
4498224f51d8SHansang Bae     ompt_callbacks.ompt_callback(ompt_callback_work)(
4499224f51d8SHansang Bae         ompt_work_scope, ompt_scope_end,
4500224f51d8SHansang Bae         &(team->t.ompt_team_info.parallel_data),
4501224f51d8SHansang Bae         &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data), 1,
4502224f51d8SHansang Bae         OMPT_GET_RETURN_ADDRESS(0));
4503224f51d8SHansang Bae   }
4504224f51d8SHansang Bae #endif // OMPT_SUPPORT && OMPT_OPTIONAL
4505224f51d8SHansang Bae }
4506224f51d8SHansang Bae 
450756da2824SPeyton, Jonathan L #ifdef KMP_USE_VERSION_SYMBOLS
450856da2824SPeyton, Jonathan L // For GOMP compatibility there are two versions of each omp_* API.
450956da2824SPeyton, Jonathan L // One is the plain C symbol and one is the Fortran symbol with an appended
451056da2824SPeyton, Jonathan L // underscore. When we implement a specific ompc_* version of an omp_*
451156da2824SPeyton, Jonathan L // function, we want the plain GOMP versioned symbol to alias the ompc_* version
451256da2824SPeyton, Jonathan L // instead of the Fortran versions in kmp_ftn_entry.h
451356da2824SPeyton, Jonathan L extern "C" {
451456da2824SPeyton, Jonathan L // Have to undef these from omp.h so they aren't translated into
451556da2824SPeyton, Jonathan L // their ompc counterparts in the KMP_VERSION_OMPC_SYMBOL macros below
451656da2824SPeyton, Jonathan L #ifdef omp_set_affinity_format
451756da2824SPeyton, Jonathan L #undef omp_set_affinity_format
451856da2824SPeyton, Jonathan L #endif
451956da2824SPeyton, Jonathan L #ifdef omp_get_affinity_format
452056da2824SPeyton, Jonathan L #undef omp_get_affinity_format
452156da2824SPeyton, Jonathan L #endif
452256da2824SPeyton, Jonathan L #ifdef omp_display_affinity
452356da2824SPeyton, Jonathan L #undef omp_display_affinity
452456da2824SPeyton, Jonathan L #endif
452556da2824SPeyton, Jonathan L #ifdef omp_capture_affinity
452656da2824SPeyton, Jonathan L #undef omp_capture_affinity
452756da2824SPeyton, Jonathan L #endif
452856da2824SPeyton, Jonathan L KMP_VERSION_OMPC_SYMBOL(ompc_set_affinity_format, omp_set_affinity_format, 50,
452956da2824SPeyton, Jonathan L                         "OMP_5.0");
453056da2824SPeyton, Jonathan L KMP_VERSION_OMPC_SYMBOL(ompc_get_affinity_format, omp_get_affinity_format, 50,
453156da2824SPeyton, Jonathan L                         "OMP_5.0");
453256da2824SPeyton, Jonathan L KMP_VERSION_OMPC_SYMBOL(ompc_display_affinity, omp_display_affinity, 50,
453356da2824SPeyton, Jonathan L                         "OMP_5.0");
453456da2824SPeyton, Jonathan L KMP_VERSION_OMPC_SYMBOL(ompc_capture_affinity, omp_capture_affinity, 50,
453556da2824SPeyton, Jonathan L                         "OMP_5.0");
453656da2824SPeyton, Jonathan L } // extern "C"
453756da2824SPeyton, Jonathan L #endif
4538