10b57cec5SDimitry Andric /* 20b57cec5SDimitry Andric * kmp_csupport.cpp -- kfront linkage support for OpenMP. 30b57cec5SDimitry Andric */ 40b57cec5SDimitry Andric 50b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 80b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 90b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #define __KMP_IMP 140b57cec5SDimitry Andric #include "omp.h" /* extern "C" declarations of user-visible routines */ 150b57cec5SDimitry Andric #include "kmp.h" 160b57cec5SDimitry Andric #include "kmp_error.h" 170b57cec5SDimitry Andric #include "kmp_i18n.h" 180b57cec5SDimitry Andric #include "kmp_itt.h" 190b57cec5SDimitry Andric #include "kmp_lock.h" 200b57cec5SDimitry Andric #include "kmp_stats.h" 21*0fca6ea1SDimitry Andric #include "kmp_utils.h" 220b57cec5SDimitry Andric #include "ompt-specific.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #define MAX_MESSAGE 512 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric // flags will be used in future, e.g. to implement openmp_strict library 270b57cec5SDimitry Andric // restrictions 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric /*! 300b57cec5SDimitry Andric * @ingroup STARTUP_SHUTDOWN 310b57cec5SDimitry Andric * @param loc in source location information 320b57cec5SDimitry Andric * @param flags in for future use (currently ignored) 330b57cec5SDimitry Andric * 340b57cec5SDimitry Andric * Initialize the runtime library. This call is optional; if it is not made then 350b57cec5SDimitry Andric * it will be implicitly called by attempts to use other library functions. 360b57cec5SDimitry Andric */ 370b57cec5SDimitry Andric void __kmpc_begin(ident_t *loc, kmp_int32 flags) { 380b57cec5SDimitry Andric // By default __kmpc_begin() is no-op. 390b57cec5SDimitry Andric char *env; 400b57cec5SDimitry Andric if ((env = getenv("KMP_INITIAL_THREAD_BIND")) != NULL && 410b57cec5SDimitry Andric __kmp_str_match_true(env)) { 420b57cec5SDimitry Andric __kmp_middle_initialize(); 43fe6060f1SDimitry Andric __kmp_assign_root_init_mask(); 440b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_begin: middle initialization called\n")); 450b57cec5SDimitry Andric } else if (__kmp_ignore_mppbeg() == FALSE) { 460b57cec5SDimitry Andric // By default __kmp_ignore_mppbeg() returns TRUE. 470b57cec5SDimitry Andric __kmp_internal_begin(); 480b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_begin: called\n")); 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric /*! 530b57cec5SDimitry Andric * @ingroup STARTUP_SHUTDOWN 540b57cec5SDimitry Andric * @param loc source location information 550b57cec5SDimitry Andric * 560b57cec5SDimitry Andric * Shutdown the runtime library. This is also optional, and even if called will 570b57cec5SDimitry Andric * not do anything unless the `KMP_IGNORE_MPPEND` environment variable is set to 580b57cec5SDimitry Andric * zero. 590b57cec5SDimitry Andric */ 600b57cec5SDimitry Andric void __kmpc_end(ident_t *loc) { 610b57cec5SDimitry Andric // By default, __kmp_ignore_mppend() returns TRUE which makes __kmpc_end() 620b57cec5SDimitry Andric // call no-op. However, this can be overridden with KMP_IGNORE_MPPEND 630b57cec5SDimitry Andric // environment variable. If KMP_IGNORE_MPPEND is 0, __kmp_ignore_mppend() 640b57cec5SDimitry Andric // returns FALSE and __kmpc_end() will unregister this root (it can cause 650b57cec5SDimitry Andric // library shut down). 660b57cec5SDimitry Andric if (__kmp_ignore_mppend() == FALSE) { 670b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_end: called\n")); 680b57cec5SDimitry Andric KA_TRACE(30, ("__kmpc_end\n")); 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric __kmp_internal_end_thread(-1); 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric #if KMP_OS_WINDOWS && OMPT_SUPPORT 730b57cec5SDimitry Andric // Normal exit process on Windows does not allow worker threads of the final 740b57cec5SDimitry Andric // parallel region to finish reporting their events, so shutting down the 750b57cec5SDimitry Andric // library here fixes the issue at least for the cases where __kmpc_end() is 760b57cec5SDimitry Andric // placed properly. 770b57cec5SDimitry Andric if (ompt_enabled.enabled) 780b57cec5SDimitry Andric __kmp_internal_end_library(__kmp_gtid_get_specific()); 790b57cec5SDimitry Andric #endif 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric /*! 830b57cec5SDimitry Andric @ingroup THREAD_STATES 840b57cec5SDimitry Andric @param loc Source location information. 850b57cec5SDimitry Andric @return The global thread index of the active thread. 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric This function can be called in any context. 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric If the runtime has ony been entered at the outermost level from a 900b57cec5SDimitry Andric single (necessarily non-OpenMP<sup>*</sup>) thread, then the thread number is 910b57cec5SDimitry Andric that which would be returned by omp_get_thread_num() in the outermost 920b57cec5SDimitry Andric active parallel construct. (Or zero if there is no active parallel 93fe6060f1SDimitry Andric construct, since the primary thread is necessarily thread zero). 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric If multiple non-OpenMP threads all enter an OpenMP construct then this 960b57cec5SDimitry Andric will be a unique thread identifier among all the threads created by 975ffd83dbSDimitry Andric the OpenMP runtime (but the value cannot be defined in terms of 980b57cec5SDimitry Andric OpenMP thread ids returned by omp_get_thread_num()). 990b57cec5SDimitry Andric */ 1000b57cec5SDimitry Andric kmp_int32 __kmpc_global_thread_num(ident_t *loc) { 1010b57cec5SDimitry Andric kmp_int32 gtid = __kmp_entry_gtid(); 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_global_thread_num: T#%d\n", gtid)); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric return gtid; 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric /*! 1090b57cec5SDimitry Andric @ingroup THREAD_STATES 1100b57cec5SDimitry Andric @param loc Source location information. 1110b57cec5SDimitry Andric @return The number of threads under control of the OpenMP<sup>*</sup> runtime 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric This function can be called in any context. 1140b57cec5SDimitry Andric It returns the total number of threads under the control of the OpenMP runtime. 1150b57cec5SDimitry Andric That is not a number that can be determined by any OpenMP standard calls, since 1160b57cec5SDimitry Andric the library may be called from more than one non-OpenMP thread, and this 1170b57cec5SDimitry Andric reflects the total over all such calls. Similarly the runtime maintains 1180b57cec5SDimitry Andric underlying threads even when they are not active (since the cost of creating 1190b57cec5SDimitry Andric and destroying OS threads is high), this call counts all such threads even if 1200b57cec5SDimitry Andric they are not waiting for work. 1210b57cec5SDimitry Andric */ 1220b57cec5SDimitry Andric kmp_int32 __kmpc_global_num_threads(ident_t *loc) { 1230b57cec5SDimitry Andric KC_TRACE(10, 1240b57cec5SDimitry Andric ("__kmpc_global_num_threads: num_threads = %d\n", __kmp_all_nth)); 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric return TCR_4(__kmp_all_nth); 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric /*! 1300b57cec5SDimitry Andric @ingroup THREAD_STATES 1310b57cec5SDimitry Andric @param loc Source location information. 1320b57cec5SDimitry Andric @return The thread number of the calling thread in the innermost active parallel 1330b57cec5SDimitry Andric construct. 1340b57cec5SDimitry Andric */ 1350b57cec5SDimitry Andric kmp_int32 __kmpc_bound_thread_num(ident_t *loc) { 1360b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_bound_thread_num: called\n")); 1370b57cec5SDimitry Andric return __kmp_tid_from_gtid(__kmp_entry_gtid()); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric /*! 1410b57cec5SDimitry Andric @ingroup THREAD_STATES 1420b57cec5SDimitry Andric @param loc Source location information. 1430b57cec5SDimitry Andric @return The number of threads in the innermost active parallel construct. 1440b57cec5SDimitry Andric */ 1450b57cec5SDimitry Andric kmp_int32 __kmpc_bound_num_threads(ident_t *loc) { 1460b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_bound_num_threads: called\n")); 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric return __kmp_entry_thread()->th.th_team->t.t_nproc; 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric /*! 1520b57cec5SDimitry Andric * @ingroup DEPRECATED 1530b57cec5SDimitry Andric * @param loc location description 1540b57cec5SDimitry Andric * 1550b57cec5SDimitry Andric * This function need not be called. It always returns TRUE. 1560b57cec5SDimitry Andric */ 1570b57cec5SDimitry Andric kmp_int32 __kmpc_ok_to_fork(ident_t *loc) { 1580b57cec5SDimitry Andric #ifndef KMP_DEBUG 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric return TRUE; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric #else 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric const char *semi2; 1650b57cec5SDimitry Andric const char *semi3; 1660b57cec5SDimitry Andric int line_no; 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric if (__kmp_par_range == 0) { 1690b57cec5SDimitry Andric return TRUE; 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric semi2 = loc->psource; 1720b57cec5SDimitry Andric if (semi2 == NULL) { 1730b57cec5SDimitry Andric return TRUE; 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric semi2 = strchr(semi2, ';'); 1760b57cec5SDimitry Andric if (semi2 == NULL) { 1770b57cec5SDimitry Andric return TRUE; 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric semi2 = strchr(semi2 + 1, ';'); 1800b57cec5SDimitry Andric if (semi2 == NULL) { 1810b57cec5SDimitry Andric return TRUE; 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric if (__kmp_par_range_filename[0]) { 1840b57cec5SDimitry Andric const char *name = semi2 - 1; 1850b57cec5SDimitry Andric while ((name > loc->psource) && (*name != '/') && (*name != ';')) { 1860b57cec5SDimitry Andric name--; 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric if ((*name == '/') || (*name == ';')) { 1890b57cec5SDimitry Andric name++; 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric if (strncmp(__kmp_par_range_filename, name, semi2 - name)) { 1920b57cec5SDimitry Andric return __kmp_par_range < 0; 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric semi3 = strchr(semi2 + 1, ';'); 1960b57cec5SDimitry Andric if (__kmp_par_range_routine[0]) { 1970b57cec5SDimitry Andric if ((semi3 != NULL) && (semi3 > semi2) && 1980b57cec5SDimitry Andric (strncmp(__kmp_par_range_routine, semi2 + 1, semi3 - semi2 - 1))) { 1990b57cec5SDimitry Andric return __kmp_par_range < 0; 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric if (KMP_SSCANF(semi3 + 1, "%d", &line_no) == 1) { 2030b57cec5SDimitry Andric if ((line_no >= __kmp_par_range_lb) && (line_no <= __kmp_par_range_ub)) { 2040b57cec5SDimitry Andric return __kmp_par_range > 0; 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric return __kmp_par_range < 0; 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric return TRUE; 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric #endif /* KMP_DEBUG */ 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric /*! 2140b57cec5SDimitry Andric @ingroup THREAD_STATES 2150b57cec5SDimitry Andric @param loc Source location information. 2160b57cec5SDimitry Andric @return 1 if this thread is executing inside an active parallel region, zero if 2170b57cec5SDimitry Andric not. 2180b57cec5SDimitry Andric */ 2190b57cec5SDimitry Andric kmp_int32 __kmpc_in_parallel(ident_t *loc) { 2200b57cec5SDimitry Andric return __kmp_entry_thread()->th.th_root->r.r_active; 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric /*! 2240b57cec5SDimitry Andric @ingroup PARALLEL 2250b57cec5SDimitry Andric @param loc source location information 2260b57cec5SDimitry Andric @param global_tid global thread number 2270b57cec5SDimitry Andric @param num_threads number of threads requested for this parallel construct 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric Set the number of threads to be used by the next fork spawned by this thread. 2300b57cec5SDimitry Andric This call is only required if the parallel construct has a `num_threads` clause. 2310b57cec5SDimitry Andric */ 2320b57cec5SDimitry Andric void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 2330b57cec5SDimitry Andric kmp_int32 num_threads) { 2340b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_push_num_threads: enter T#%d num_threads=%d\n", 2350b57cec5SDimitry Andric global_tid, num_threads)); 236e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 2370b57cec5SDimitry Andric __kmp_push_num_threads(loc, global_tid, num_threads); 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric 240*0fca6ea1SDimitry Andric void __kmpc_push_num_threads_strict(ident_t *loc, kmp_int32 global_tid, 241*0fca6ea1SDimitry Andric kmp_int32 num_threads, int severity, 242*0fca6ea1SDimitry Andric const char *message) { 243*0fca6ea1SDimitry Andric __kmp_push_num_threads(loc, global_tid, num_threads); 244*0fca6ea1SDimitry Andric __kmp_set_strict_num_threads(loc, global_tid, severity, message); 245*0fca6ea1SDimitry Andric } 246*0fca6ea1SDimitry Andric 247*0fca6ea1SDimitry Andric /*! 248*0fca6ea1SDimitry Andric @ingroup PARALLEL 249*0fca6ea1SDimitry Andric @param loc source location information 250*0fca6ea1SDimitry Andric @param global_tid global thread number 251*0fca6ea1SDimitry Andric @param list_length number of entries in the num_threads_list array 252*0fca6ea1SDimitry Andric @param num_threads_list array of numbers of threads requested for this parallel 253*0fca6ea1SDimitry Andric construct and subsequent nested parallel constructs 254*0fca6ea1SDimitry Andric 255*0fca6ea1SDimitry Andric Set the number of threads to be used by the next fork spawned by this thread, 256*0fca6ea1SDimitry Andric and some nested forks as well. 257*0fca6ea1SDimitry Andric This call is only required if the parallel construct has a `num_threads` clause 258*0fca6ea1SDimitry Andric that has a list of integers as the argument. 259*0fca6ea1SDimitry Andric */ 260*0fca6ea1SDimitry Andric void __kmpc_push_num_threads_list(ident_t *loc, kmp_int32 global_tid, 261*0fca6ea1SDimitry Andric kmp_uint32 list_length, 262*0fca6ea1SDimitry Andric kmp_int32 *num_threads_list) { 263*0fca6ea1SDimitry Andric KA_TRACE(20, ("__kmpc_push_num_threads_list: enter T#%d num_threads_list=", 264*0fca6ea1SDimitry Andric global_tid)); 265*0fca6ea1SDimitry Andric KA_TRACE(20, ("%d", num_threads_list[0])); 266*0fca6ea1SDimitry Andric #ifdef KMP_DEBUG 267*0fca6ea1SDimitry Andric for (kmp_uint32 i = 1; i < list_length; ++i) 268*0fca6ea1SDimitry Andric KA_TRACE(20, (", %d", num_threads_list[i])); 269*0fca6ea1SDimitry Andric #endif 270*0fca6ea1SDimitry Andric KA_TRACE(20, ("/n")); 271*0fca6ea1SDimitry Andric 272*0fca6ea1SDimitry Andric __kmp_assert_valid_gtid(global_tid); 273*0fca6ea1SDimitry Andric __kmp_push_num_threads_list(loc, global_tid, list_length, num_threads_list); 274*0fca6ea1SDimitry Andric } 275*0fca6ea1SDimitry Andric 276*0fca6ea1SDimitry Andric void __kmpc_push_num_threads_list_strict(ident_t *loc, kmp_int32 global_tid, 277*0fca6ea1SDimitry Andric kmp_uint32 list_length, 278*0fca6ea1SDimitry Andric kmp_int32 *num_threads_list, 279*0fca6ea1SDimitry Andric int severity, const char *message) { 280*0fca6ea1SDimitry Andric __kmp_push_num_threads_list(loc, global_tid, list_length, num_threads_list); 281*0fca6ea1SDimitry Andric __kmp_set_strict_num_threads(loc, global_tid, severity, message); 282*0fca6ea1SDimitry Andric } 283*0fca6ea1SDimitry Andric 2840b57cec5SDimitry Andric void __kmpc_pop_num_threads(ident_t *loc, kmp_int32 global_tid) { 2850b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_pop_num_threads: enter\n")); 2860b57cec5SDimitry Andric /* the num_threads are automatically popped */ 2870b57cec5SDimitry Andric } 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2900b57cec5SDimitry Andric kmp_int32 proc_bind) { 2910b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_push_proc_bind: enter T#%d proc_bind=%d\n", global_tid, 2920b57cec5SDimitry Andric proc_bind)); 293e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 2940b57cec5SDimitry Andric __kmp_push_proc_bind(loc, global_tid, (kmp_proc_bind_t)proc_bind); 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric /*! 2980b57cec5SDimitry Andric @ingroup PARALLEL 2990b57cec5SDimitry Andric @param loc source location information 3000b57cec5SDimitry Andric @param argc total number of arguments in the ellipsis 3010b57cec5SDimitry Andric @param microtask pointer to callback routine consisting of outlined parallel 3020b57cec5SDimitry Andric construct 3030b57cec5SDimitry Andric @param ... pointers to shared variables that aren't global 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric Do the actual fork and call the microtask in the relevant number of threads. 3060b57cec5SDimitry Andric */ 3070b57cec5SDimitry Andric void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro microtask, ...) { 3080b57cec5SDimitry Andric int gtid = __kmp_entry_gtid(); 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric #if (KMP_STATS_ENABLED) 3110b57cec5SDimitry Andric // If we were in a serial region, then stop the serial timer, record 3120b57cec5SDimitry Andric // the event, and start parallel region timer 3130b57cec5SDimitry Andric stats_state_e previous_state = KMP_GET_THREAD_STATE(); 3140b57cec5SDimitry Andric if (previous_state == stats_state_e::SERIAL_REGION) { 3150b57cec5SDimitry Andric KMP_EXCHANGE_PARTITIONED_TIMER(OMP_parallel_overhead); 3160b57cec5SDimitry Andric } else { 3170b57cec5SDimitry Andric KMP_PUSH_PARTITIONED_TIMER(OMP_parallel_overhead); 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric int inParallel = __kmpc_in_parallel(loc); 3200b57cec5SDimitry Andric if (inParallel) { 3210b57cec5SDimitry Andric KMP_COUNT_BLOCK(OMP_NESTED_PARALLEL); 3220b57cec5SDimitry Andric } else { 3230b57cec5SDimitry Andric KMP_COUNT_BLOCK(OMP_PARALLEL); 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric #endif 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric // maybe to save thr_state is enough here 3280b57cec5SDimitry Andric { 3290b57cec5SDimitry Andric va_list ap; 3300b57cec5SDimitry Andric va_start(ap, microtask); 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric #if OMPT_SUPPORT 3330b57cec5SDimitry Andric ompt_frame_t *ompt_frame; 3340b57cec5SDimitry Andric if (ompt_enabled.enabled) { 3350b57cec5SDimitry Andric kmp_info_t *master_th = __kmp_threads[gtid]; 336349cc55cSDimitry Andric ompt_frame = &master_th->th.th_current_task->ompt_task_info.frame; 3370b57cec5SDimitry Andric ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0); 3380b57cec5SDimitry Andric } 339e8d8bef9SDimitry Andric OMPT_STORE_RETURN_ADDRESS(gtid); 3400b57cec5SDimitry Andric #endif 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric #if INCLUDE_SSC_MARKS 3430b57cec5SDimitry Andric SSC_MARK_FORKING(); 3440b57cec5SDimitry Andric #endif 3450b57cec5SDimitry Andric __kmp_fork_call(loc, gtid, fork_context_intel, argc, 3460b57cec5SDimitry Andric VOLATILE_CAST(microtask_t) microtask, // "wrapped" task 3470b57cec5SDimitry Andric VOLATILE_CAST(launch_t) __kmp_invoke_task_func, 34816794618SDimitry Andric kmp_va_addr_of(ap)); 3490b57cec5SDimitry Andric #if INCLUDE_SSC_MARKS 3500b57cec5SDimitry Andric SSC_MARK_JOINING(); 3510b57cec5SDimitry Andric #endif 3520b57cec5SDimitry Andric __kmp_join_call(loc, gtid 3530b57cec5SDimitry Andric #if OMPT_SUPPORT 3540b57cec5SDimitry Andric , 3550b57cec5SDimitry Andric fork_context_intel 3560b57cec5SDimitry Andric #endif 3570b57cec5SDimitry Andric ); 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric va_end(ap); 360349cc55cSDimitry Andric 361349cc55cSDimitry Andric #if OMPT_SUPPORT 362349cc55cSDimitry Andric if (ompt_enabled.enabled) { 363349cc55cSDimitry Andric ompt_frame->enter_frame = ompt_data_none; 364349cc55cSDimitry Andric } 365349cc55cSDimitry Andric #endif 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric #if KMP_STATS_ENABLED 3690b57cec5SDimitry Andric if (previous_state == stats_state_e::SERIAL_REGION) { 3700b57cec5SDimitry Andric KMP_EXCHANGE_PARTITIONED_TIMER(OMP_serial); 371e8d8bef9SDimitry Andric KMP_SET_THREAD_STATE(previous_state); 3720b57cec5SDimitry Andric } else { 3730b57cec5SDimitry Andric KMP_POP_PARTITIONED_TIMER(); 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric #endif // KMP_STATS_ENABLED 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric /*! 3790b57cec5SDimitry Andric @ingroup PARALLEL 3800b57cec5SDimitry Andric @param loc source location information 381bdd1243dSDimitry Andric @param microtask pointer to callback routine consisting of outlined parallel 382bdd1243dSDimitry Andric construct 383bdd1243dSDimitry Andric @param cond condition for running in parallel 384bdd1243dSDimitry Andric @param args struct of pointers to shared variables that aren't global 385bdd1243dSDimitry Andric 386bdd1243dSDimitry Andric Perform a fork only if the condition is true. 387bdd1243dSDimitry Andric */ 388bdd1243dSDimitry Andric void __kmpc_fork_call_if(ident_t *loc, kmp_int32 argc, kmpc_micro microtask, 389bdd1243dSDimitry Andric kmp_int32 cond, void *args) { 390bdd1243dSDimitry Andric int gtid = __kmp_entry_gtid(); 391bdd1243dSDimitry Andric if (cond) { 392bdd1243dSDimitry Andric if (args) 393bdd1243dSDimitry Andric __kmpc_fork_call(loc, argc, microtask, args); 394bdd1243dSDimitry Andric else 395bdd1243dSDimitry Andric __kmpc_fork_call(loc, argc, microtask); 396bdd1243dSDimitry Andric } else { 397bdd1243dSDimitry Andric __kmpc_serialized_parallel(loc, gtid); 398bdd1243dSDimitry Andric 3995f757f3fSDimitry Andric #if OMPT_SUPPORT 4005f757f3fSDimitry Andric void *exit_frame_ptr; 4015f757f3fSDimitry Andric #endif 4025f757f3fSDimitry Andric 403bdd1243dSDimitry Andric if (args) 4045f757f3fSDimitry Andric __kmp_invoke_microtask(VOLATILE_CAST(microtask_t) microtask, gtid, 4055f757f3fSDimitry Andric /*npr=*/0, 4065f757f3fSDimitry Andric /*argc=*/1, &args 4075f757f3fSDimitry Andric #if OMPT_SUPPORT 4085f757f3fSDimitry Andric , 4095f757f3fSDimitry Andric &exit_frame_ptr 4105f757f3fSDimitry Andric #endif 4115f757f3fSDimitry Andric ); 412bdd1243dSDimitry Andric else 4135f757f3fSDimitry Andric __kmp_invoke_microtask(VOLATILE_CAST(microtask_t) microtask, gtid, 4145f757f3fSDimitry Andric /*npr=*/0, 4155f757f3fSDimitry Andric /*argc=*/0, 4165f757f3fSDimitry Andric /*args=*/nullptr 4175f757f3fSDimitry Andric #if OMPT_SUPPORT 4185f757f3fSDimitry Andric , 4195f757f3fSDimitry Andric &exit_frame_ptr 4205f757f3fSDimitry Andric #endif 4215f757f3fSDimitry Andric ); 422bdd1243dSDimitry Andric 423bdd1243dSDimitry Andric __kmpc_end_serialized_parallel(loc, gtid); 424bdd1243dSDimitry Andric } 425bdd1243dSDimitry Andric } 426bdd1243dSDimitry Andric 427bdd1243dSDimitry Andric /*! 428bdd1243dSDimitry Andric @ingroup PARALLEL 429bdd1243dSDimitry Andric @param loc source location information 4300b57cec5SDimitry Andric @param global_tid global thread number 4310b57cec5SDimitry Andric @param num_teams number of teams requested for the teams construct 4320b57cec5SDimitry Andric @param num_threads number of threads per team requested for the teams construct 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric Set the number of teams to be used by the teams construct. 4350b57cec5SDimitry Andric This call is only required if the teams construct has a `num_teams` clause 4360b57cec5SDimitry Andric or a `thread_limit` clause (or both). 4370b57cec5SDimitry Andric */ 4380b57cec5SDimitry Andric void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 4390b57cec5SDimitry Andric kmp_int32 num_teams, kmp_int32 num_threads) { 4400b57cec5SDimitry Andric KA_TRACE(20, 4410b57cec5SDimitry Andric ("__kmpc_push_num_teams: enter T#%d num_teams=%d num_threads=%d\n", 4420b57cec5SDimitry Andric global_tid, num_teams, num_threads)); 443e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 4440b57cec5SDimitry Andric __kmp_push_num_teams(loc, global_tid, num_teams, num_threads); 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric /*! 4480b57cec5SDimitry Andric @ingroup PARALLEL 4490b57cec5SDimitry Andric @param loc source location information 450fe6060f1SDimitry Andric @param global_tid global thread number 4515f757f3fSDimitry Andric @param thread_limit limit on number of threads which can be created within the 4525f757f3fSDimitry Andric current task 4535f757f3fSDimitry Andric 4545f757f3fSDimitry Andric Set the thread_limit for the current task 4555f757f3fSDimitry Andric This call is there to support `thread_limit` clause on the `target` construct 4565f757f3fSDimitry Andric */ 4575f757f3fSDimitry Andric void __kmpc_set_thread_limit(ident_t *loc, kmp_int32 global_tid, 4585f757f3fSDimitry Andric kmp_int32 thread_limit) { 4595f757f3fSDimitry Andric __kmp_assert_valid_gtid(global_tid); 4605f757f3fSDimitry Andric kmp_info_t *thread = __kmp_threads[global_tid]; 4615f757f3fSDimitry Andric if (thread_limit > 0) 4625f757f3fSDimitry Andric thread->th.th_current_task->td_icvs.task_thread_limit = thread_limit; 4635f757f3fSDimitry Andric } 4645f757f3fSDimitry Andric 4655f757f3fSDimitry Andric /*! 4665f757f3fSDimitry Andric @ingroup PARALLEL 4675f757f3fSDimitry Andric @param loc source location information 4685f757f3fSDimitry Andric @param global_tid global thread number 46981ad6265SDimitry Andric @param num_teams_lb lower bound on number of teams requested for the teams 470fe6060f1SDimitry Andric construct 47181ad6265SDimitry Andric @param num_teams_ub upper bound on number of teams requested for the teams 472fe6060f1SDimitry Andric construct 473fe6060f1SDimitry Andric @param num_threads number of threads per team requested for the teams construct 474fe6060f1SDimitry Andric 475fe6060f1SDimitry Andric Set the number of teams to be used by the teams construct. The number of initial 476fe6060f1SDimitry Andric teams cretaed will be greater than or equal to the lower bound and less than or 477fe6060f1SDimitry Andric equal to the upper bound. 478fe6060f1SDimitry Andric This call is only required if the teams construct has a `num_teams` clause 479fe6060f1SDimitry Andric or a `thread_limit` clause (or both). 480fe6060f1SDimitry Andric */ 481fe6060f1SDimitry Andric void __kmpc_push_num_teams_51(ident_t *loc, kmp_int32 global_tid, 482fe6060f1SDimitry Andric kmp_int32 num_teams_lb, kmp_int32 num_teams_ub, 483fe6060f1SDimitry Andric kmp_int32 num_threads) { 484fe6060f1SDimitry Andric KA_TRACE(20, ("__kmpc_push_num_teams_51: enter T#%d num_teams_lb=%d" 485fe6060f1SDimitry Andric " num_teams_ub=%d num_threads=%d\n", 486fe6060f1SDimitry Andric global_tid, num_teams_lb, num_teams_ub, num_threads)); 487fe6060f1SDimitry Andric __kmp_assert_valid_gtid(global_tid); 488fe6060f1SDimitry Andric __kmp_push_num_teams_51(loc, global_tid, num_teams_lb, num_teams_ub, 489fe6060f1SDimitry Andric num_threads); 490fe6060f1SDimitry Andric } 491fe6060f1SDimitry Andric 492fe6060f1SDimitry Andric /*! 493fe6060f1SDimitry Andric @ingroup PARALLEL 494fe6060f1SDimitry Andric @param loc source location information 4950b57cec5SDimitry Andric @param argc total number of arguments in the ellipsis 4960b57cec5SDimitry Andric @param microtask pointer to callback routine consisting of outlined teams 4970b57cec5SDimitry Andric construct 4980b57cec5SDimitry Andric @param ... pointers to shared variables that aren't global 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric Do the actual fork and call the microtask in the relevant number of threads. 5010b57cec5SDimitry Andric */ 5020b57cec5SDimitry Andric void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro microtask, 5030b57cec5SDimitry Andric ...) { 5040b57cec5SDimitry Andric int gtid = __kmp_entry_gtid(); 5050b57cec5SDimitry Andric kmp_info_t *this_thr = __kmp_threads[gtid]; 5060b57cec5SDimitry Andric va_list ap; 5070b57cec5SDimitry Andric va_start(ap, microtask); 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric #if KMP_STATS_ENABLED 5100b57cec5SDimitry Andric KMP_COUNT_BLOCK(OMP_TEAMS); 5110b57cec5SDimitry Andric stats_state_e previous_state = KMP_GET_THREAD_STATE(); 5120b57cec5SDimitry Andric if (previous_state == stats_state_e::SERIAL_REGION) { 5130b57cec5SDimitry Andric KMP_EXCHANGE_PARTITIONED_TIMER(OMP_teams_overhead); 5140b57cec5SDimitry Andric } else { 5150b57cec5SDimitry Andric KMP_PUSH_PARTITIONED_TIMER(OMP_teams_overhead); 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric #endif 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric // remember teams entry point and nesting level 5200b57cec5SDimitry Andric this_thr->th.th_teams_microtask = microtask; 5210b57cec5SDimitry Andric this_thr->th.th_teams_level = 5220b57cec5SDimitry Andric this_thr->th.th_team->t.t_level; // AC: can be >0 on host 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric #if OMPT_SUPPORT 5250b57cec5SDimitry Andric kmp_team_t *parent_team = this_thr->th.th_team; 5260b57cec5SDimitry Andric int tid = __kmp_tid_from_gtid(gtid); 5270b57cec5SDimitry Andric if (ompt_enabled.enabled) { 5280b57cec5SDimitry Andric parent_team->t.t_implicit_task_taskdata[tid] 5290b57cec5SDimitry Andric .ompt_task_info.frame.enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0); 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric OMPT_STORE_RETURN_ADDRESS(gtid); 5320b57cec5SDimitry Andric #endif 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric // check if __kmpc_push_num_teams called, set default number of teams 5350b57cec5SDimitry Andric // otherwise 5360b57cec5SDimitry Andric if (this_thr->th.th_teams_size.nteams == 0) { 5370b57cec5SDimitry Andric __kmp_push_num_teams(loc, gtid, 0, 0); 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric KMP_DEBUG_ASSERT(this_thr->th.th_set_nproc >= 1); 5400b57cec5SDimitry Andric KMP_DEBUG_ASSERT(this_thr->th.th_teams_size.nteams >= 1); 5410b57cec5SDimitry Andric KMP_DEBUG_ASSERT(this_thr->th.th_teams_size.nth >= 1); 5420b57cec5SDimitry Andric 54316794618SDimitry Andric __kmp_fork_call( 54416794618SDimitry Andric loc, gtid, fork_context_intel, argc, 54516794618SDimitry Andric VOLATILE_CAST(microtask_t) __kmp_teams_master, // "wrapped" task 54616794618SDimitry Andric VOLATILE_CAST(launch_t) __kmp_invoke_teams_master, kmp_va_addr_of(ap)); 5470b57cec5SDimitry Andric __kmp_join_call(loc, gtid 5480b57cec5SDimitry Andric #if OMPT_SUPPORT 5490b57cec5SDimitry Andric , 5500b57cec5SDimitry Andric fork_context_intel 5510b57cec5SDimitry Andric #endif 5520b57cec5SDimitry Andric ); 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric // Pop current CG root off list 5550b57cec5SDimitry Andric KMP_DEBUG_ASSERT(this_thr->th.th_cg_roots); 5560b57cec5SDimitry Andric kmp_cg_root_t *tmp = this_thr->th.th_cg_roots; 5570b57cec5SDimitry Andric this_thr->th.th_cg_roots = tmp->up; 5580b57cec5SDimitry Andric KA_TRACE(100, ("__kmpc_fork_teams: Thread %p popping node %p and moving up" 5590b57cec5SDimitry Andric " to node %p. cg_nthreads was %d\n", 5600b57cec5SDimitry Andric this_thr, tmp, this_thr->th.th_cg_roots, tmp->cg_nthreads)); 5610b57cec5SDimitry Andric KMP_DEBUG_ASSERT(tmp->cg_nthreads); 5620b57cec5SDimitry Andric int i = tmp->cg_nthreads--; 5630b57cec5SDimitry Andric if (i == 1) { // check is we are the last thread in CG (not always the case) 5640b57cec5SDimitry Andric __kmp_free(tmp); 5650b57cec5SDimitry Andric } 5660b57cec5SDimitry Andric // Restore current task's thread_limit from CG root 5670b57cec5SDimitry Andric KMP_DEBUG_ASSERT(this_thr->th.th_cg_roots); 5680b57cec5SDimitry Andric this_thr->th.th_current_task->td_icvs.thread_limit = 5690b57cec5SDimitry Andric this_thr->th.th_cg_roots->cg_thread_limit; 5700b57cec5SDimitry Andric 5710b57cec5SDimitry Andric this_thr->th.th_teams_microtask = NULL; 5720b57cec5SDimitry Andric this_thr->th.th_teams_level = 0; 5730b57cec5SDimitry Andric *(kmp_int64 *)(&this_thr->th.th_teams_size) = 0L; 5740b57cec5SDimitry Andric va_end(ap); 5750b57cec5SDimitry Andric #if KMP_STATS_ENABLED 5760b57cec5SDimitry Andric if (previous_state == stats_state_e::SERIAL_REGION) { 5770b57cec5SDimitry Andric KMP_EXCHANGE_PARTITIONED_TIMER(OMP_serial); 578e8d8bef9SDimitry Andric KMP_SET_THREAD_STATE(previous_state); 5790b57cec5SDimitry Andric } else { 5800b57cec5SDimitry Andric KMP_POP_PARTITIONED_TIMER(); 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric #endif // KMP_STATS_ENABLED 5830b57cec5SDimitry Andric } 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric // I don't think this function should ever have been exported. 5860b57cec5SDimitry Andric // The __kmpc_ prefix was misapplied. I'm fairly certain that no generated 5870b57cec5SDimitry Andric // openmp code ever called it, but it's been exported from the RTL for so 5880b57cec5SDimitry Andric // long that I'm afraid to remove the definition. 5890b57cec5SDimitry Andric int __kmpc_invoke_task_func(int gtid) { return __kmp_invoke_task_func(gtid); } 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric /*! 5920b57cec5SDimitry Andric @ingroup PARALLEL 5930b57cec5SDimitry Andric @param loc source location information 5940b57cec5SDimitry Andric @param global_tid global thread number 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric Enter a serialized parallel construct. This interface is used to handle a 5970b57cec5SDimitry Andric conditional parallel region, like this, 5980b57cec5SDimitry Andric @code 5990b57cec5SDimitry Andric #pragma omp parallel if (condition) 6000b57cec5SDimitry Andric @endcode 6010b57cec5SDimitry Andric when the condition is false. 6020b57cec5SDimitry Andric */ 6030b57cec5SDimitry Andric void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 global_tid) { 6040b57cec5SDimitry Andric // The implementation is now in kmp_runtime.cpp so that it can share static 6050b57cec5SDimitry Andric // functions with kmp_fork_call since the tasks to be done are similar in 6060b57cec5SDimitry Andric // each case. 607e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 6080b57cec5SDimitry Andric #if OMPT_SUPPORT 6090b57cec5SDimitry Andric OMPT_STORE_RETURN_ADDRESS(global_tid); 6100b57cec5SDimitry Andric #endif 6110b57cec5SDimitry Andric __kmp_serialized_parallel(loc, global_tid); 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric /*! 6150b57cec5SDimitry Andric @ingroup PARALLEL 6160b57cec5SDimitry Andric @param loc source location information 6170b57cec5SDimitry Andric @param global_tid global thread number 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andric Leave a serialized parallel construct. 6200b57cec5SDimitry Andric */ 6210b57cec5SDimitry Andric void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 global_tid) { 6220b57cec5SDimitry Andric kmp_internal_control_t *top; 6230b57cec5SDimitry Andric kmp_info_t *this_thr; 6240b57cec5SDimitry Andric kmp_team_t *serial_team; 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric KC_TRACE(10, 6270b57cec5SDimitry Andric ("__kmpc_end_serialized_parallel: called by T#%d\n", global_tid)); 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric /* skip all this code for autopar serialized loops since it results in 6300b57cec5SDimitry Andric unacceptable overhead */ 6310b57cec5SDimitry Andric if (loc != NULL && (loc->flags & KMP_IDENT_AUTOPAR)) 6320b57cec5SDimitry Andric return; 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric // Not autopar code 635e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 6360b57cec5SDimitry Andric if (!TCR_4(__kmp_init_parallel)) 6370b57cec5SDimitry Andric __kmp_parallel_initialize(); 6380b57cec5SDimitry Andric 6390b57cec5SDimitry Andric __kmp_resume_if_soft_paused(); 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric this_thr = __kmp_threads[global_tid]; 6420b57cec5SDimitry Andric serial_team = this_thr->th.th_serial_team; 6430b57cec5SDimitry Andric 6440b57cec5SDimitry Andric kmp_task_team_t *task_team = this_thr->th.th_task_team; 6450b57cec5SDimitry Andric // we need to wait for the proxy tasks before finishing the thread 64604eeddc0SDimitry Andric if (task_team != NULL && (task_team->tt.tt_found_proxy_tasks || 64704eeddc0SDimitry Andric task_team->tt.tt_hidden_helper_task_encountered)) 6480b57cec5SDimitry Andric __kmp_task_team_wait(this_thr, serial_team USE_ITT_BUILD_ARG(NULL)); 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric KMP_MB(); 6510b57cec5SDimitry Andric KMP_DEBUG_ASSERT(serial_team); 6520b57cec5SDimitry Andric KMP_ASSERT(serial_team->t.t_serialized); 6530b57cec5SDimitry Andric KMP_DEBUG_ASSERT(this_thr->th.th_team == serial_team); 6540b57cec5SDimitry Andric KMP_DEBUG_ASSERT(serial_team != this_thr->th.th_root->r.r_root_team); 6550b57cec5SDimitry Andric KMP_DEBUG_ASSERT(serial_team->t.t_threads); 6560b57cec5SDimitry Andric KMP_DEBUG_ASSERT(serial_team->t.t_threads[0] == this_thr); 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric #if OMPT_SUPPORT 6590b57cec5SDimitry Andric if (ompt_enabled.enabled && 6600b57cec5SDimitry Andric this_thr->th.ompt_thread_info.state != ompt_state_overhead) { 6610b57cec5SDimitry Andric OMPT_CUR_TASK_INFO(this_thr)->frame.exit_frame = ompt_data_none; 6620b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_implicit_task) { 6630b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_implicit_task)( 6640b57cec5SDimitry Andric ompt_scope_end, NULL, OMPT_CUR_TASK_DATA(this_thr), 1, 6650b57cec5SDimitry Andric OMPT_CUR_TASK_INFO(this_thr)->thread_num, ompt_task_implicit); 6660b57cec5SDimitry Andric } 6670b57cec5SDimitry Andric 6680b57cec5SDimitry Andric // reset clear the task id only after unlinking the task 6690b57cec5SDimitry Andric ompt_data_t *parent_task_data; 6700b57cec5SDimitry Andric __ompt_get_task_info_internal(1, NULL, &parent_task_data, NULL, NULL, NULL); 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_parallel_end) { 6730b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_parallel_end)( 6740b57cec5SDimitry Andric &(serial_team->t.ompt_team_info.parallel_data), parent_task_data, 675489b1cf2SDimitry Andric ompt_parallel_invoker_program | ompt_parallel_team, 676489b1cf2SDimitry Andric OMPT_LOAD_RETURN_ADDRESS(global_tid)); 6770b57cec5SDimitry Andric } 6780b57cec5SDimitry Andric __ompt_lw_taskteam_unlink(this_thr); 6790b57cec5SDimitry Andric this_thr->th.ompt_thread_info.state = ompt_state_overhead; 6800b57cec5SDimitry Andric } 6810b57cec5SDimitry Andric #endif 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric /* If necessary, pop the internal control stack values and replace the team 6840b57cec5SDimitry Andric * values */ 6850b57cec5SDimitry Andric top = serial_team->t.t_control_stack_top; 6860b57cec5SDimitry Andric if (top && top->serial_nesting_level == serial_team->t.t_serialized) { 6870b57cec5SDimitry Andric copy_icvs(&serial_team->t.t_threads[0]->th.th_current_task->td_icvs, top); 6880b57cec5SDimitry Andric serial_team->t.t_control_stack_top = top->next; 6890b57cec5SDimitry Andric __kmp_free(top); 6900b57cec5SDimitry Andric } 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric /* pop dispatch buffers stack */ 6930b57cec5SDimitry Andric KMP_DEBUG_ASSERT(serial_team->t.t_dispatch->th_disp_buffer); 6940b57cec5SDimitry Andric { 6950b57cec5SDimitry Andric dispatch_private_info_t *disp_buffer = 6960b57cec5SDimitry Andric serial_team->t.t_dispatch->th_disp_buffer; 6970b57cec5SDimitry Andric serial_team->t.t_dispatch->th_disp_buffer = 6980b57cec5SDimitry Andric serial_team->t.t_dispatch->th_disp_buffer->next; 6990b57cec5SDimitry Andric __kmp_free(disp_buffer); 7000b57cec5SDimitry Andric } 701*0fca6ea1SDimitry Andric 702*0fca6ea1SDimitry Andric /* pop the task team stack */ 703*0fca6ea1SDimitry Andric if (serial_team->t.t_serialized > 1) { 704*0fca6ea1SDimitry Andric __kmp_pop_task_team_node(this_thr, serial_team); 705*0fca6ea1SDimitry Andric } 706*0fca6ea1SDimitry Andric 7070b57cec5SDimitry Andric this_thr->th.th_def_allocator = serial_team->t.t_def_allocator; // restore 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric --serial_team->t.t_serialized; 7100b57cec5SDimitry Andric if (serial_team->t.t_serialized == 0) { 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric /* return to the parallel section */ 7130b57cec5SDimitry Andric 7140b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 7150b57cec5SDimitry Andric if (__kmp_inherit_fp_control && serial_team->t.t_fp_control_saved) { 7160b57cec5SDimitry Andric __kmp_clear_x87_fpu_status_word(); 7170b57cec5SDimitry Andric __kmp_load_x87_fpu_control_word(&serial_team->t.t_x87_fpu_control_word); 7180b57cec5SDimitry Andric __kmp_load_mxcsr(&serial_team->t.t_mxcsr); 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ 7210b57cec5SDimitry Andric 722349cc55cSDimitry Andric __kmp_pop_current_task_from_thread(this_thr); 723fe6060f1SDimitry Andric #if OMPD_SUPPORT 724fe6060f1SDimitry Andric if (ompd_state & OMPD_ENABLE_BP) 725fe6060f1SDimitry Andric ompd_bp_parallel_end(); 726fe6060f1SDimitry Andric #endif 727fe6060f1SDimitry Andric 7280b57cec5SDimitry Andric this_thr->th.th_team = serial_team->t.t_parent; 7290b57cec5SDimitry Andric this_thr->th.th_info.ds.ds_tid = serial_team->t.t_master_tid; 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric /* restore values cached in the thread */ 7320b57cec5SDimitry Andric this_thr->th.th_team_nproc = serial_team->t.t_parent->t.t_nproc; /* JPH */ 7330b57cec5SDimitry Andric this_thr->th.th_team_master = 7340b57cec5SDimitry Andric serial_team->t.t_parent->t.t_threads[0]; /* JPH */ 7350b57cec5SDimitry Andric this_thr->th.th_team_serialized = this_thr->th.th_team->t.t_serialized; 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric /* TODO the below shouldn't need to be adjusted for serialized teams */ 7380b57cec5SDimitry Andric this_thr->th.th_dispatch = 7390b57cec5SDimitry Andric &this_thr->th.th_team->t.t_dispatch[serial_team->t.t_master_tid]; 7400b57cec5SDimitry Andric 7410b57cec5SDimitry Andric KMP_ASSERT(this_thr->th.th_current_task->td_flags.executing == 0); 7420b57cec5SDimitry Andric this_thr->th.th_current_task->td_flags.executing = 1; 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric if (__kmp_tasking_mode != tskm_immediate_exec) { 745*0fca6ea1SDimitry Andric // Restore task state from serial team structure 746*0fca6ea1SDimitry Andric KMP_DEBUG_ASSERT(serial_team->t.t_primary_task_state == 0 || 747*0fca6ea1SDimitry Andric serial_team->t.t_primary_task_state == 1); 748*0fca6ea1SDimitry Andric this_thr->th.th_task_state = 749*0fca6ea1SDimitry Andric (kmp_uint8)serial_team->t.t_primary_task_state; 7500b57cec5SDimitry Andric // Copy the task team from the new child / old parent team to the thread. 7510b57cec5SDimitry Andric this_thr->th.th_task_team = 7520b57cec5SDimitry Andric this_thr->th.th_team->t.t_task_team[this_thr->th.th_task_state]; 7530b57cec5SDimitry Andric KA_TRACE(20, 7540b57cec5SDimitry Andric ("__kmpc_end_serialized_parallel: T#%d restoring task_team %p / " 7550b57cec5SDimitry Andric "team %p\n", 7560b57cec5SDimitry Andric global_tid, this_thr->th.th_task_team, this_thr->th.th_team)); 7570b57cec5SDimitry Andric } 758fcaf7f86SDimitry Andric #if KMP_AFFINITY_SUPPORTED 759bdd1243dSDimitry Andric if (this_thr->th.th_team->t.t_level == 0 && __kmp_affinity.flags.reset) { 760fcaf7f86SDimitry Andric __kmp_reset_root_init_mask(global_tid); 761fcaf7f86SDimitry Andric } 762fcaf7f86SDimitry Andric #endif 7630b57cec5SDimitry Andric } else { 7640b57cec5SDimitry Andric if (__kmp_tasking_mode != tskm_immediate_exec) { 7650b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_end_serialized_parallel: T#%d decreasing nesting " 7660b57cec5SDimitry Andric "depth of serial team %p to %d\n", 7670b57cec5SDimitry Andric global_tid, serial_team, serial_team->t.t_serialized)); 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric } 7700b57cec5SDimitry Andric 771349cc55cSDimitry Andric serial_team->t.t_level--; 7720b57cec5SDimitry Andric if (__kmp_env_consistency_check) 7730b57cec5SDimitry Andric __kmp_pop_parallel(global_tid, NULL); 7740b57cec5SDimitry Andric #if OMPT_SUPPORT 7750b57cec5SDimitry Andric if (ompt_enabled.enabled) 7760b57cec5SDimitry Andric this_thr->th.ompt_thread_info.state = 7770b57cec5SDimitry Andric ((this_thr->th.th_team_serialized) ? ompt_state_work_serial 7780b57cec5SDimitry Andric : ompt_state_work_parallel); 7790b57cec5SDimitry Andric #endif 7800b57cec5SDimitry Andric } 7810b57cec5SDimitry Andric 7820b57cec5SDimitry Andric /*! 7830b57cec5SDimitry Andric @ingroup SYNCHRONIZATION 7840b57cec5SDimitry Andric @param loc source location information. 7850b57cec5SDimitry Andric 7860b57cec5SDimitry Andric Execute <tt>flush</tt>. This is implemented as a full memory fence. (Though 7870b57cec5SDimitry Andric depending on the memory ordering convention obeyed by the compiler 7880b57cec5SDimitry Andric even that may not be necessary). 7890b57cec5SDimitry Andric */ 7900b57cec5SDimitry Andric void __kmpc_flush(ident_t *loc) { 7910b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_flush: called\n")); 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric /* need explicit __mf() here since use volatile instead in library */ 794bdd1243dSDimitry Andric KMP_MFENCE(); /* Flush all pending memory write invalidates. */ 7950b57cec5SDimitry Andric 7960b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 7970b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_flush) { 7980b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_flush)( 7990b57cec5SDimitry Andric __ompt_get_thread_data_internal(), OMPT_GET_RETURN_ADDRESS(0)); 8000b57cec5SDimitry Andric } 8010b57cec5SDimitry Andric #endif 8020b57cec5SDimitry Andric } 8030b57cec5SDimitry Andric 8040b57cec5SDimitry Andric /* -------------------------------------------------------------------------- */ 8050b57cec5SDimitry Andric /*! 8060b57cec5SDimitry Andric @ingroup SYNCHRONIZATION 8070b57cec5SDimitry Andric @param loc source location information 8080b57cec5SDimitry Andric @param global_tid thread id. 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric Execute a barrier. 8110b57cec5SDimitry Andric */ 8120b57cec5SDimitry Andric void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid) { 8130b57cec5SDimitry Andric KMP_COUNT_BLOCK(OMP_BARRIER); 8140b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_barrier: called T#%d\n", global_tid)); 815e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric if (!TCR_4(__kmp_init_parallel)) 8180b57cec5SDimitry Andric __kmp_parallel_initialize(); 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric __kmp_resume_if_soft_paused(); 8210b57cec5SDimitry Andric 8220b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 8230b57cec5SDimitry Andric if (loc == 0) { 8240b57cec5SDimitry Andric KMP_WARNING(ConstructIdentInvalid); // ??? What does it mean for the user? 8250b57cec5SDimitry Andric } 8260b57cec5SDimitry Andric __kmp_check_barrier(global_tid, ct_barrier, loc); 8270b57cec5SDimitry Andric } 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric #if OMPT_SUPPORT 8300b57cec5SDimitry Andric ompt_frame_t *ompt_frame; 8310b57cec5SDimitry Andric if (ompt_enabled.enabled) { 8320b57cec5SDimitry Andric __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL); 8330b57cec5SDimitry Andric if (ompt_frame->enter_frame.ptr == NULL) 8340b57cec5SDimitry Andric ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0); 8350b57cec5SDimitry Andric } 836e8d8bef9SDimitry Andric OMPT_STORE_RETURN_ADDRESS(global_tid); 8370b57cec5SDimitry Andric #endif 8380b57cec5SDimitry Andric __kmp_threads[global_tid]->th.th_ident = loc; 8390b57cec5SDimitry Andric // TODO: explicit barrier_wait_id: 8400b57cec5SDimitry Andric // this function is called when 'barrier' directive is present or 8410b57cec5SDimitry Andric // implicit barrier at the end of a worksharing construct. 8420b57cec5SDimitry Andric // 1) better to add a per-thread barrier counter to a thread data structure 8430b57cec5SDimitry Andric // 2) set to 0 when a new team is created 8440b57cec5SDimitry Andric // 4) no sync is required 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric __kmp_barrier(bs_plain_barrier, global_tid, FALSE, 0, NULL, NULL); 8470b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 8480b57cec5SDimitry Andric if (ompt_enabled.enabled) { 8490b57cec5SDimitry Andric ompt_frame->enter_frame = ompt_data_none; 8500b57cec5SDimitry Andric } 8510b57cec5SDimitry Andric #endif 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric 8540b57cec5SDimitry Andric /* The BARRIER for a MASTER section is always explicit */ 8550b57cec5SDimitry Andric /*! 8560b57cec5SDimitry Andric @ingroup WORK_SHARING 8570b57cec5SDimitry Andric @param loc source location information. 8580b57cec5SDimitry Andric @param global_tid global thread number . 8590b57cec5SDimitry Andric @return 1 if this thread should execute the <tt>master</tt> block, 0 otherwise. 8600b57cec5SDimitry Andric */ 8610b57cec5SDimitry Andric kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid) { 8620b57cec5SDimitry Andric int status = 0; 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_master: called T#%d\n", global_tid)); 865e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 8660b57cec5SDimitry Andric 8670b57cec5SDimitry Andric if (!TCR_4(__kmp_init_parallel)) 8680b57cec5SDimitry Andric __kmp_parallel_initialize(); 8690b57cec5SDimitry Andric 8700b57cec5SDimitry Andric __kmp_resume_if_soft_paused(); 8710b57cec5SDimitry Andric 8720b57cec5SDimitry Andric if (KMP_MASTER_GTID(global_tid)) { 8730b57cec5SDimitry Andric KMP_COUNT_BLOCK(OMP_MASTER); 8740b57cec5SDimitry Andric KMP_PUSH_PARTITIONED_TIMER(OMP_master); 8750b57cec5SDimitry Andric status = 1; 8760b57cec5SDimitry Andric } 8770b57cec5SDimitry Andric 8780b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 8790b57cec5SDimitry Andric if (status) { 880e8d8bef9SDimitry Andric if (ompt_enabled.ompt_callback_masked) { 8810b57cec5SDimitry Andric kmp_info_t *this_thr = __kmp_threads[global_tid]; 8820b57cec5SDimitry Andric kmp_team_t *team = this_thr->th.th_team; 8830b57cec5SDimitry Andric 8840b57cec5SDimitry Andric int tid = __kmp_tid_from_gtid(global_tid); 885e8d8bef9SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_masked)( 8860b57cec5SDimitry Andric ompt_scope_begin, &(team->t.ompt_team_info.parallel_data), 8870b57cec5SDimitry Andric &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data), 8880b57cec5SDimitry Andric OMPT_GET_RETURN_ADDRESS(0)); 8890b57cec5SDimitry Andric } 8900b57cec5SDimitry Andric } 8910b57cec5SDimitry Andric #endif 8920b57cec5SDimitry Andric 8930b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 8940b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 8950b57cec5SDimitry Andric if (status) 8960b57cec5SDimitry Andric __kmp_push_sync(global_tid, ct_master, loc, NULL, 0); 8970b57cec5SDimitry Andric else 8980b57cec5SDimitry Andric __kmp_check_sync(global_tid, ct_master, loc, NULL, 0); 8990b57cec5SDimitry Andric #else 9000b57cec5SDimitry Andric if (status) 9010b57cec5SDimitry Andric __kmp_push_sync(global_tid, ct_master, loc, NULL); 9020b57cec5SDimitry Andric else 9030b57cec5SDimitry Andric __kmp_check_sync(global_tid, ct_master, loc, NULL); 9040b57cec5SDimitry Andric #endif 9050b57cec5SDimitry Andric } 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric return status; 9080b57cec5SDimitry Andric } 9090b57cec5SDimitry Andric 9100b57cec5SDimitry Andric /*! 9110b57cec5SDimitry Andric @ingroup WORK_SHARING 9120b57cec5SDimitry Andric @param loc source location information. 9130b57cec5SDimitry Andric @param global_tid global thread number . 9140b57cec5SDimitry Andric 9150b57cec5SDimitry Andric Mark the end of a <tt>master</tt> region. This should only be called by the 9160b57cec5SDimitry Andric thread that executes the <tt>master</tt> region. 9170b57cec5SDimitry Andric */ 9180b57cec5SDimitry Andric void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid) { 9190b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_end_master: called T#%d\n", global_tid)); 920e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 9210b57cec5SDimitry Andric KMP_DEBUG_ASSERT(KMP_MASTER_GTID(global_tid)); 9220b57cec5SDimitry Andric KMP_POP_PARTITIONED_TIMER(); 9230b57cec5SDimitry Andric 9240b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 9250b57cec5SDimitry Andric kmp_info_t *this_thr = __kmp_threads[global_tid]; 9260b57cec5SDimitry Andric kmp_team_t *team = this_thr->th.th_team; 927e8d8bef9SDimitry Andric if (ompt_enabled.ompt_callback_masked) { 9280b57cec5SDimitry Andric int tid = __kmp_tid_from_gtid(global_tid); 929e8d8bef9SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_masked)( 9300b57cec5SDimitry Andric ompt_scope_end, &(team->t.ompt_team_info.parallel_data), 9310b57cec5SDimitry Andric &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data), 9320b57cec5SDimitry Andric OMPT_GET_RETURN_ADDRESS(0)); 9330b57cec5SDimitry Andric } 9340b57cec5SDimitry Andric #endif 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 9370b57cec5SDimitry Andric if (KMP_MASTER_GTID(global_tid)) 9380b57cec5SDimitry Andric __kmp_pop_sync(global_tid, ct_master, loc); 9390b57cec5SDimitry Andric } 9400b57cec5SDimitry Andric } 9410b57cec5SDimitry Andric 9420b57cec5SDimitry Andric /*! 9430b57cec5SDimitry Andric @ingroup WORK_SHARING 9440b57cec5SDimitry Andric @param loc source location information. 945fe6060f1SDimitry Andric @param global_tid global thread number. 946fe6060f1SDimitry Andric @param filter result of evaluating filter clause on thread global_tid, or zero 947fe6060f1SDimitry Andric if no filter clause present 948fe6060f1SDimitry Andric @return 1 if this thread should execute the <tt>masked</tt> block, 0 otherwise. 949fe6060f1SDimitry Andric */ 950fe6060f1SDimitry Andric kmp_int32 __kmpc_masked(ident_t *loc, kmp_int32 global_tid, kmp_int32 filter) { 951fe6060f1SDimitry Andric int status = 0; 952fe6060f1SDimitry Andric int tid; 953fe6060f1SDimitry Andric KC_TRACE(10, ("__kmpc_masked: called T#%d\n", global_tid)); 954fe6060f1SDimitry Andric __kmp_assert_valid_gtid(global_tid); 955fe6060f1SDimitry Andric 956fe6060f1SDimitry Andric if (!TCR_4(__kmp_init_parallel)) 957fe6060f1SDimitry Andric __kmp_parallel_initialize(); 958fe6060f1SDimitry Andric 959fe6060f1SDimitry Andric __kmp_resume_if_soft_paused(); 960fe6060f1SDimitry Andric 961fe6060f1SDimitry Andric tid = __kmp_tid_from_gtid(global_tid); 962fe6060f1SDimitry Andric if (tid == filter) { 963fe6060f1SDimitry Andric KMP_COUNT_BLOCK(OMP_MASKED); 964fe6060f1SDimitry Andric KMP_PUSH_PARTITIONED_TIMER(OMP_masked); 965fe6060f1SDimitry Andric status = 1; 966fe6060f1SDimitry Andric } 967fe6060f1SDimitry Andric 968fe6060f1SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 969fe6060f1SDimitry Andric if (status) { 970fe6060f1SDimitry Andric if (ompt_enabled.ompt_callback_masked) { 971fe6060f1SDimitry Andric kmp_info_t *this_thr = __kmp_threads[global_tid]; 972fe6060f1SDimitry Andric kmp_team_t *team = this_thr->th.th_team; 973fe6060f1SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_masked)( 974fe6060f1SDimitry Andric ompt_scope_begin, &(team->t.ompt_team_info.parallel_data), 975fe6060f1SDimitry Andric &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data), 976fe6060f1SDimitry Andric OMPT_GET_RETURN_ADDRESS(0)); 977fe6060f1SDimitry Andric } 978fe6060f1SDimitry Andric } 979fe6060f1SDimitry Andric #endif 980fe6060f1SDimitry Andric 981fe6060f1SDimitry Andric if (__kmp_env_consistency_check) { 982fe6060f1SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 983fe6060f1SDimitry Andric if (status) 984fe6060f1SDimitry Andric __kmp_push_sync(global_tid, ct_masked, loc, NULL, 0); 985fe6060f1SDimitry Andric else 986fe6060f1SDimitry Andric __kmp_check_sync(global_tid, ct_masked, loc, NULL, 0); 987fe6060f1SDimitry Andric #else 988fe6060f1SDimitry Andric if (status) 989fe6060f1SDimitry Andric __kmp_push_sync(global_tid, ct_masked, loc, NULL); 990fe6060f1SDimitry Andric else 991fe6060f1SDimitry Andric __kmp_check_sync(global_tid, ct_masked, loc, NULL); 992fe6060f1SDimitry Andric #endif 993fe6060f1SDimitry Andric } 994fe6060f1SDimitry Andric 995fe6060f1SDimitry Andric return status; 996fe6060f1SDimitry Andric } 997fe6060f1SDimitry Andric 998fe6060f1SDimitry Andric /*! 999fe6060f1SDimitry Andric @ingroup WORK_SHARING 1000fe6060f1SDimitry Andric @param loc source location information. 1001fe6060f1SDimitry Andric @param global_tid global thread number . 1002fe6060f1SDimitry Andric 1003fe6060f1SDimitry Andric Mark the end of a <tt>masked</tt> region. This should only be called by the 1004fe6060f1SDimitry Andric thread that executes the <tt>masked</tt> region. 1005fe6060f1SDimitry Andric */ 1006fe6060f1SDimitry Andric void __kmpc_end_masked(ident_t *loc, kmp_int32 global_tid) { 1007fe6060f1SDimitry Andric KC_TRACE(10, ("__kmpc_end_masked: called T#%d\n", global_tid)); 1008fe6060f1SDimitry Andric __kmp_assert_valid_gtid(global_tid); 1009fe6060f1SDimitry Andric KMP_POP_PARTITIONED_TIMER(); 1010fe6060f1SDimitry Andric 1011fe6060f1SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 1012fe6060f1SDimitry Andric kmp_info_t *this_thr = __kmp_threads[global_tid]; 1013fe6060f1SDimitry Andric kmp_team_t *team = this_thr->th.th_team; 1014fe6060f1SDimitry Andric if (ompt_enabled.ompt_callback_masked) { 1015fe6060f1SDimitry Andric int tid = __kmp_tid_from_gtid(global_tid); 1016fe6060f1SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_masked)( 1017fe6060f1SDimitry Andric ompt_scope_end, &(team->t.ompt_team_info.parallel_data), 1018fe6060f1SDimitry Andric &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data), 1019fe6060f1SDimitry Andric OMPT_GET_RETURN_ADDRESS(0)); 1020fe6060f1SDimitry Andric } 1021fe6060f1SDimitry Andric #endif 1022fe6060f1SDimitry Andric 1023fe6060f1SDimitry Andric if (__kmp_env_consistency_check) { 1024fe6060f1SDimitry Andric __kmp_pop_sync(global_tid, ct_masked, loc); 1025fe6060f1SDimitry Andric } 1026fe6060f1SDimitry Andric } 1027fe6060f1SDimitry Andric 1028fe6060f1SDimitry Andric /*! 1029fe6060f1SDimitry Andric @ingroup WORK_SHARING 1030fe6060f1SDimitry Andric @param loc source location information. 10310b57cec5SDimitry Andric @param gtid global thread number. 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric Start execution of an <tt>ordered</tt> construct. 10340b57cec5SDimitry Andric */ 10350b57cec5SDimitry Andric void __kmpc_ordered(ident_t *loc, kmp_int32 gtid) { 10360b57cec5SDimitry Andric int cid = 0; 10370b57cec5SDimitry Andric kmp_info_t *th; 10380b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); 10390b57cec5SDimitry Andric 10400b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_ordered: called T#%d\n", gtid)); 1041e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(gtid); 10420b57cec5SDimitry Andric 10430b57cec5SDimitry Andric if (!TCR_4(__kmp_init_parallel)) 10440b57cec5SDimitry Andric __kmp_parallel_initialize(); 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric __kmp_resume_if_soft_paused(); 10470b57cec5SDimitry Andric 10480b57cec5SDimitry Andric #if USE_ITT_BUILD 10490b57cec5SDimitry Andric __kmp_itt_ordered_prep(gtid); 10500b57cec5SDimitry Andric // TODO: ordered_wait_id 10510b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric th = __kmp_threads[gtid]; 10540b57cec5SDimitry Andric 10550b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 10560b57cec5SDimitry Andric kmp_team_t *team; 10570b57cec5SDimitry Andric ompt_wait_id_t lck; 10580b57cec5SDimitry Andric void *codeptr_ra; 10590b57cec5SDimitry Andric OMPT_STORE_RETURN_ADDRESS(gtid); 1060e8d8bef9SDimitry Andric if (ompt_enabled.enabled) { 10610b57cec5SDimitry Andric team = __kmp_team_from_gtid(gtid); 10620b57cec5SDimitry Andric lck = (ompt_wait_id_t)(uintptr_t)&team->t.t_ordered.dt.t_value; 10630b57cec5SDimitry Andric /* OMPT state update */ 10640b57cec5SDimitry Andric th->th.ompt_thread_info.wait_id = lck; 10650b57cec5SDimitry Andric th->th.ompt_thread_info.state = ompt_state_wait_ordered; 10660b57cec5SDimitry Andric 10670b57cec5SDimitry Andric /* OMPT event callback */ 10680b57cec5SDimitry Andric codeptr_ra = OMPT_LOAD_RETURN_ADDRESS(gtid); 10690b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquire) { 10700b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( 10710b57cec5SDimitry Andric ompt_mutex_ordered, omp_lock_hint_none, kmp_mutex_impl_spin, lck, 10720b57cec5SDimitry Andric codeptr_ra); 10730b57cec5SDimitry Andric } 10740b57cec5SDimitry Andric } 10750b57cec5SDimitry Andric #endif 10760b57cec5SDimitry Andric 10770b57cec5SDimitry Andric if (th->th.th_dispatch->th_deo_fcn != 0) 10780b57cec5SDimitry Andric (*th->th.th_dispatch->th_deo_fcn)(>id, &cid, loc); 10790b57cec5SDimitry Andric else 10800b57cec5SDimitry Andric __kmp_parallel_deo(>id, &cid, loc); 10810b57cec5SDimitry Andric 10820b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 10830b57cec5SDimitry Andric if (ompt_enabled.enabled) { 10840b57cec5SDimitry Andric /* OMPT state update */ 10850b57cec5SDimitry Andric th->th.ompt_thread_info.state = ompt_state_work_parallel; 10860b57cec5SDimitry Andric th->th.ompt_thread_info.wait_id = 0; 10870b57cec5SDimitry Andric 10880b57cec5SDimitry Andric /* OMPT event callback */ 10890b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquired) { 10900b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( 10910b57cec5SDimitry Andric ompt_mutex_ordered, (ompt_wait_id_t)(uintptr_t)lck, codeptr_ra); 10920b57cec5SDimitry Andric } 10930b57cec5SDimitry Andric } 10940b57cec5SDimitry Andric #endif 10950b57cec5SDimitry Andric 10960b57cec5SDimitry Andric #if USE_ITT_BUILD 10970b57cec5SDimitry Andric __kmp_itt_ordered_start(gtid); 10980b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 10990b57cec5SDimitry Andric } 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andric /*! 11020b57cec5SDimitry Andric @ingroup WORK_SHARING 11030b57cec5SDimitry Andric @param loc source location information. 11040b57cec5SDimitry Andric @param gtid global thread number. 11050b57cec5SDimitry Andric 11060b57cec5SDimitry Andric End execution of an <tt>ordered</tt> construct. 11070b57cec5SDimitry Andric */ 11080b57cec5SDimitry Andric void __kmpc_end_ordered(ident_t *loc, kmp_int32 gtid) { 11090b57cec5SDimitry Andric int cid = 0; 11100b57cec5SDimitry Andric kmp_info_t *th; 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_end_ordered: called T#%d\n", gtid)); 1113e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(gtid); 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric #if USE_ITT_BUILD 11160b57cec5SDimitry Andric __kmp_itt_ordered_end(gtid); 11170b57cec5SDimitry Andric // TODO: ordered_wait_id 11180b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 11190b57cec5SDimitry Andric 11200b57cec5SDimitry Andric th = __kmp_threads[gtid]; 11210b57cec5SDimitry Andric 11220b57cec5SDimitry Andric if (th->th.th_dispatch->th_dxo_fcn != 0) 11230b57cec5SDimitry Andric (*th->th.th_dispatch->th_dxo_fcn)(>id, &cid, loc); 11240b57cec5SDimitry Andric else 11250b57cec5SDimitry Andric __kmp_parallel_dxo(>id, &cid, loc); 11260b57cec5SDimitry Andric 11270b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 11280b57cec5SDimitry Andric OMPT_STORE_RETURN_ADDRESS(gtid); 11290b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_released) { 11300b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( 11310b57cec5SDimitry Andric ompt_mutex_ordered, 11320b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)&__kmp_team_from_gtid(gtid) 11330b57cec5SDimitry Andric ->t.t_ordered.dt.t_value, 11340b57cec5SDimitry Andric OMPT_LOAD_RETURN_ADDRESS(gtid)); 11350b57cec5SDimitry Andric } 11360b57cec5SDimitry Andric #endif 11370b57cec5SDimitry Andric } 11380b57cec5SDimitry Andric 11390b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 11400b57cec5SDimitry Andric 11410b57cec5SDimitry Andric static __forceinline void 11420b57cec5SDimitry Andric __kmp_init_indirect_csptr(kmp_critical_name *crit, ident_t const *loc, 11430b57cec5SDimitry Andric kmp_int32 gtid, kmp_indirect_locktag_t tag) { 11440b57cec5SDimitry Andric // Pointer to the allocated indirect lock is written to crit, while indexing 11450b57cec5SDimitry Andric // is ignored. 11460b57cec5SDimitry Andric void *idx; 11470b57cec5SDimitry Andric kmp_indirect_lock_t **lck; 11480b57cec5SDimitry Andric lck = (kmp_indirect_lock_t **)crit; 11490b57cec5SDimitry Andric kmp_indirect_lock_t *ilk = __kmp_allocate_indirect_lock(&idx, gtid, tag); 11500b57cec5SDimitry Andric KMP_I_LOCK_FUNC(ilk, init)(ilk->lock); 11510b57cec5SDimitry Andric KMP_SET_I_LOCK_LOCATION(ilk, loc); 11520b57cec5SDimitry Andric KMP_SET_I_LOCK_FLAGS(ilk, kmp_lf_critical_section); 11530b57cec5SDimitry Andric KA_TRACE(20, 11540b57cec5SDimitry Andric ("__kmp_init_indirect_csptr: initialized indirect lock #%d\n", tag)); 11550b57cec5SDimitry Andric #if USE_ITT_BUILD 11560b57cec5SDimitry Andric __kmp_itt_critical_creating(ilk->lock, loc); 11570b57cec5SDimitry Andric #endif 11580b57cec5SDimitry Andric int status = KMP_COMPARE_AND_STORE_PTR(lck, nullptr, ilk); 11590b57cec5SDimitry Andric if (status == 0) { 11600b57cec5SDimitry Andric #if USE_ITT_BUILD 11610b57cec5SDimitry Andric __kmp_itt_critical_destroyed(ilk->lock); 11620b57cec5SDimitry Andric #endif 11630b57cec5SDimitry Andric // We don't really need to destroy the unclaimed lock here since it will be 11640b57cec5SDimitry Andric // cleaned up at program exit. 11650b57cec5SDimitry Andric // KMP_D_LOCK_FUNC(&idx, destroy)((kmp_dyna_lock_t *)&idx); 11660b57cec5SDimitry Andric } 11670b57cec5SDimitry Andric KMP_DEBUG_ASSERT(*lck != NULL); 11680b57cec5SDimitry Andric } 11690b57cec5SDimitry Andric 11700b57cec5SDimitry Andric // Fast-path acquire tas lock 11710b57cec5SDimitry Andric #define KMP_ACQUIRE_TAS_LOCK(lock, gtid) \ 11720b57cec5SDimitry Andric { \ 11730b57cec5SDimitry Andric kmp_tas_lock_t *l = (kmp_tas_lock_t *)lock; \ 11740b57cec5SDimitry Andric kmp_int32 tas_free = KMP_LOCK_FREE(tas); \ 11750b57cec5SDimitry Andric kmp_int32 tas_busy = KMP_LOCK_BUSY(gtid + 1, tas); \ 11760b57cec5SDimitry Andric if (KMP_ATOMIC_LD_RLX(&l->lk.poll) != tas_free || \ 11770b57cec5SDimitry Andric !__kmp_atomic_compare_store_acq(&l->lk.poll, tas_free, tas_busy)) { \ 11780b57cec5SDimitry Andric kmp_uint32 spins; \ 11790b57cec5SDimitry Andric KMP_FSYNC_PREPARE(l); \ 11800b57cec5SDimitry Andric KMP_INIT_YIELD(spins); \ 11810b57cec5SDimitry Andric kmp_backoff_t backoff = __kmp_spin_backoff_params; \ 11820b57cec5SDimitry Andric do { \ 11830b57cec5SDimitry Andric if (TCR_4(__kmp_nth) > \ 11840b57cec5SDimitry Andric (__kmp_avail_proc ? __kmp_avail_proc : __kmp_xproc)) { \ 11850b57cec5SDimitry Andric KMP_YIELD(TRUE); \ 11860b57cec5SDimitry Andric } else { \ 11870b57cec5SDimitry Andric KMP_YIELD_SPIN(spins); \ 11880b57cec5SDimitry Andric } \ 11890b57cec5SDimitry Andric __kmp_spin_backoff(&backoff); \ 11900b57cec5SDimitry Andric } while ( \ 11910b57cec5SDimitry Andric KMP_ATOMIC_LD_RLX(&l->lk.poll) != tas_free || \ 11920b57cec5SDimitry Andric !__kmp_atomic_compare_store_acq(&l->lk.poll, tas_free, tas_busy)); \ 11930b57cec5SDimitry Andric } \ 11940b57cec5SDimitry Andric KMP_FSYNC_ACQUIRED(l); \ 11950b57cec5SDimitry Andric } 11960b57cec5SDimitry Andric 11970b57cec5SDimitry Andric // Fast-path test tas lock 11980b57cec5SDimitry Andric #define KMP_TEST_TAS_LOCK(lock, gtid, rc) \ 11990b57cec5SDimitry Andric { \ 12000b57cec5SDimitry Andric kmp_tas_lock_t *l = (kmp_tas_lock_t *)lock; \ 12010b57cec5SDimitry Andric kmp_int32 tas_free = KMP_LOCK_FREE(tas); \ 12020b57cec5SDimitry Andric kmp_int32 tas_busy = KMP_LOCK_BUSY(gtid + 1, tas); \ 12030b57cec5SDimitry Andric rc = KMP_ATOMIC_LD_RLX(&l->lk.poll) == tas_free && \ 12040b57cec5SDimitry Andric __kmp_atomic_compare_store_acq(&l->lk.poll, tas_free, tas_busy); \ 12050b57cec5SDimitry Andric } 12060b57cec5SDimitry Andric 12070b57cec5SDimitry Andric // Fast-path release tas lock 12080b57cec5SDimitry Andric #define KMP_RELEASE_TAS_LOCK(lock, gtid) \ 12090b57cec5SDimitry Andric { KMP_ATOMIC_ST_REL(&((kmp_tas_lock_t *)lock)->lk.poll, KMP_LOCK_FREE(tas)); } 12100b57cec5SDimitry Andric 12110b57cec5SDimitry Andric #if KMP_USE_FUTEX 12120b57cec5SDimitry Andric 12130b57cec5SDimitry Andric #include <sys/syscall.h> 12140b57cec5SDimitry Andric #include <unistd.h> 12150b57cec5SDimitry Andric #ifndef FUTEX_WAIT 12160b57cec5SDimitry Andric #define FUTEX_WAIT 0 12170b57cec5SDimitry Andric #endif 12180b57cec5SDimitry Andric #ifndef FUTEX_WAKE 12190b57cec5SDimitry Andric #define FUTEX_WAKE 1 12200b57cec5SDimitry Andric #endif 12210b57cec5SDimitry Andric 12220b57cec5SDimitry Andric // Fast-path acquire futex lock 12230b57cec5SDimitry Andric #define KMP_ACQUIRE_FUTEX_LOCK(lock, gtid) \ 12240b57cec5SDimitry Andric { \ 12250b57cec5SDimitry Andric kmp_futex_lock_t *ftx = (kmp_futex_lock_t *)lock; \ 12260b57cec5SDimitry Andric kmp_int32 gtid_code = (gtid + 1) << 1; \ 12270b57cec5SDimitry Andric KMP_MB(); \ 12280b57cec5SDimitry Andric KMP_FSYNC_PREPARE(ftx); \ 12290b57cec5SDimitry Andric kmp_int32 poll_val; \ 12300b57cec5SDimitry Andric while ((poll_val = KMP_COMPARE_AND_STORE_RET32( \ 12310b57cec5SDimitry Andric &(ftx->lk.poll), KMP_LOCK_FREE(futex), \ 12320b57cec5SDimitry Andric KMP_LOCK_BUSY(gtid_code, futex))) != KMP_LOCK_FREE(futex)) { \ 12330b57cec5SDimitry Andric kmp_int32 cond = KMP_LOCK_STRIP(poll_val) & 1; \ 12340b57cec5SDimitry Andric if (!cond) { \ 12350b57cec5SDimitry Andric if (!KMP_COMPARE_AND_STORE_RET32(&(ftx->lk.poll), poll_val, \ 12360b57cec5SDimitry Andric poll_val | \ 12370b57cec5SDimitry Andric KMP_LOCK_BUSY(1, futex))) { \ 12380b57cec5SDimitry Andric continue; \ 12390b57cec5SDimitry Andric } \ 12400b57cec5SDimitry Andric poll_val |= KMP_LOCK_BUSY(1, futex); \ 12410b57cec5SDimitry Andric } \ 12420b57cec5SDimitry Andric kmp_int32 rc; \ 12430b57cec5SDimitry Andric if ((rc = syscall(__NR_futex, &(ftx->lk.poll), FUTEX_WAIT, poll_val, \ 12440b57cec5SDimitry Andric NULL, NULL, 0)) != 0) { \ 12450b57cec5SDimitry Andric continue; \ 12460b57cec5SDimitry Andric } \ 12470b57cec5SDimitry Andric gtid_code |= 1; \ 12480b57cec5SDimitry Andric } \ 12490b57cec5SDimitry Andric KMP_FSYNC_ACQUIRED(ftx); \ 12500b57cec5SDimitry Andric } 12510b57cec5SDimitry Andric 12520b57cec5SDimitry Andric // Fast-path test futex lock 12530b57cec5SDimitry Andric #define KMP_TEST_FUTEX_LOCK(lock, gtid, rc) \ 12540b57cec5SDimitry Andric { \ 12550b57cec5SDimitry Andric kmp_futex_lock_t *ftx = (kmp_futex_lock_t *)lock; \ 12560b57cec5SDimitry Andric if (KMP_COMPARE_AND_STORE_ACQ32(&(ftx->lk.poll), KMP_LOCK_FREE(futex), \ 12570b57cec5SDimitry Andric KMP_LOCK_BUSY(gtid + 1 << 1, futex))) { \ 12580b57cec5SDimitry Andric KMP_FSYNC_ACQUIRED(ftx); \ 12590b57cec5SDimitry Andric rc = TRUE; \ 12600b57cec5SDimitry Andric } else { \ 12610b57cec5SDimitry Andric rc = FALSE; \ 12620b57cec5SDimitry Andric } \ 12630b57cec5SDimitry Andric } 12640b57cec5SDimitry Andric 12650b57cec5SDimitry Andric // Fast-path release futex lock 12660b57cec5SDimitry Andric #define KMP_RELEASE_FUTEX_LOCK(lock, gtid) \ 12670b57cec5SDimitry Andric { \ 12680b57cec5SDimitry Andric kmp_futex_lock_t *ftx = (kmp_futex_lock_t *)lock; \ 12690b57cec5SDimitry Andric KMP_MB(); \ 12700b57cec5SDimitry Andric KMP_FSYNC_RELEASING(ftx); \ 12710b57cec5SDimitry Andric kmp_int32 poll_val = \ 12720b57cec5SDimitry Andric KMP_XCHG_FIXED32(&(ftx->lk.poll), KMP_LOCK_FREE(futex)); \ 12730b57cec5SDimitry Andric if (KMP_LOCK_STRIP(poll_val) & 1) { \ 12740b57cec5SDimitry Andric syscall(__NR_futex, &(ftx->lk.poll), FUTEX_WAKE, \ 12750b57cec5SDimitry Andric KMP_LOCK_BUSY(1, futex), NULL, NULL, 0); \ 12760b57cec5SDimitry Andric } \ 12770b57cec5SDimitry Andric KMP_MB(); \ 12780b57cec5SDimitry Andric KMP_YIELD_OVERSUB(); \ 12790b57cec5SDimitry Andric } 12800b57cec5SDimitry Andric 12810b57cec5SDimitry Andric #endif // KMP_USE_FUTEX 12820b57cec5SDimitry Andric 12830b57cec5SDimitry Andric #else // KMP_USE_DYNAMIC_LOCK 12840b57cec5SDimitry Andric 12850b57cec5SDimitry Andric static kmp_user_lock_p __kmp_get_critical_section_ptr(kmp_critical_name *crit, 12860b57cec5SDimitry Andric ident_t const *loc, 12870b57cec5SDimitry Andric kmp_int32 gtid) { 12880b57cec5SDimitry Andric kmp_user_lock_p *lck_pp = (kmp_user_lock_p *)crit; 12890b57cec5SDimitry Andric 12900b57cec5SDimitry Andric // Because of the double-check, the following load doesn't need to be volatile 12910b57cec5SDimitry Andric kmp_user_lock_p lck = (kmp_user_lock_p)TCR_PTR(*lck_pp); 12920b57cec5SDimitry Andric 12930b57cec5SDimitry Andric if (lck == NULL) { 12940b57cec5SDimitry Andric void *idx; 12950b57cec5SDimitry Andric 12960b57cec5SDimitry Andric // Allocate & initialize the lock. 12970b57cec5SDimitry Andric // Remember alloc'ed locks in table in order to free them in __kmp_cleanup() 12980b57cec5SDimitry Andric lck = __kmp_user_lock_allocate(&idx, gtid, kmp_lf_critical_section); 12990b57cec5SDimitry Andric __kmp_init_user_lock_with_checks(lck); 13000b57cec5SDimitry Andric __kmp_set_user_lock_location(lck, loc); 13010b57cec5SDimitry Andric #if USE_ITT_BUILD 13020b57cec5SDimitry Andric __kmp_itt_critical_creating(lck); 13030b57cec5SDimitry Andric // __kmp_itt_critical_creating() should be called *before* the first usage 13040b57cec5SDimitry Andric // of underlying lock. It is the only place where we can guarantee it. There 13050b57cec5SDimitry Andric // are chances the lock will destroyed with no usage, but it is not a 13060b57cec5SDimitry Andric // problem, because this is not real event seen by user but rather setting 13070b57cec5SDimitry Andric // name for object (lock). See more details in kmp_itt.h. 13080b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 13090b57cec5SDimitry Andric 13100b57cec5SDimitry Andric // Use a cmpxchg instruction to slam the start of the critical section with 13110b57cec5SDimitry Andric // the lock pointer. If another thread beat us to it, deallocate the lock, 13120b57cec5SDimitry Andric // and use the lock that the other thread allocated. 13130b57cec5SDimitry Andric int status = KMP_COMPARE_AND_STORE_PTR(lck_pp, 0, lck); 13140b57cec5SDimitry Andric 13150b57cec5SDimitry Andric if (status == 0) { 13160b57cec5SDimitry Andric // Deallocate the lock and reload the value. 13170b57cec5SDimitry Andric #if USE_ITT_BUILD 13180b57cec5SDimitry Andric __kmp_itt_critical_destroyed(lck); 13190b57cec5SDimitry Andric // Let ITT know the lock is destroyed and the same memory location may be reused 13200b57cec5SDimitry Andric // for another purpose. 13210b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 13220b57cec5SDimitry Andric __kmp_destroy_user_lock_with_checks(lck); 13230b57cec5SDimitry Andric __kmp_user_lock_free(&idx, gtid, lck); 13240b57cec5SDimitry Andric lck = (kmp_user_lock_p)TCR_PTR(*lck_pp); 13250b57cec5SDimitry Andric KMP_DEBUG_ASSERT(lck != NULL); 13260b57cec5SDimitry Andric } 13270b57cec5SDimitry Andric } 13280b57cec5SDimitry Andric return lck; 13290b57cec5SDimitry Andric } 13300b57cec5SDimitry Andric 13310b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 13320b57cec5SDimitry Andric 13330b57cec5SDimitry Andric /*! 13340b57cec5SDimitry Andric @ingroup WORK_SHARING 13350b57cec5SDimitry Andric @param loc source location information. 13360b57cec5SDimitry Andric @param global_tid global thread number. 13370b57cec5SDimitry Andric @param crit identity of the critical section. This could be a pointer to a lock 13380b57cec5SDimitry Andric associated with the critical section, or some other suitably unique value. 13390b57cec5SDimitry Andric 13400b57cec5SDimitry Andric Enter code protected by a `critical` construct. 13410b57cec5SDimitry Andric This function blocks until the executing thread can enter the critical section. 13420b57cec5SDimitry Andric */ 13430b57cec5SDimitry Andric void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 13440b57cec5SDimitry Andric kmp_critical_name *crit) { 13450b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 13460b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 13470b57cec5SDimitry Andric OMPT_STORE_RETURN_ADDRESS(global_tid); 13480b57cec5SDimitry Andric #endif // OMPT_SUPPORT 13490b57cec5SDimitry Andric __kmpc_critical_with_hint(loc, global_tid, crit, omp_lock_hint_none); 13500b57cec5SDimitry Andric #else 13510b57cec5SDimitry Andric KMP_COUNT_BLOCK(OMP_CRITICAL); 13520b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 13530b57cec5SDimitry Andric ompt_state_t prev_state = ompt_state_undefined; 13540b57cec5SDimitry Andric ompt_thread_info_t ti; 13550b57cec5SDimitry Andric #endif 13560b57cec5SDimitry Andric kmp_user_lock_p lck; 13570b57cec5SDimitry Andric 13580b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_critical: called T#%d\n", global_tid)); 1359e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 13600b57cec5SDimitry Andric 13610b57cec5SDimitry Andric // TODO: add THR_OVHD_STATE 13620b57cec5SDimitry Andric 13630b57cec5SDimitry Andric KMP_PUSH_PARTITIONED_TIMER(OMP_critical_wait); 13640b57cec5SDimitry Andric KMP_CHECK_USER_LOCK_INIT(); 13650b57cec5SDimitry Andric 13660b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 13670b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) <= OMP_CRITICAL_SIZE)) { 13680b57cec5SDimitry Andric lck = (kmp_user_lock_p)crit; 13690b57cec5SDimitry Andric } 13700b57cec5SDimitry Andric #if KMP_USE_FUTEX 13710b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 13720b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) <= OMP_CRITICAL_SIZE)) { 13730b57cec5SDimitry Andric lck = (kmp_user_lock_p)crit; 13740b57cec5SDimitry Andric } 13750b57cec5SDimitry Andric #endif 13760b57cec5SDimitry Andric else { // ticket, queuing or drdpa 13770b57cec5SDimitry Andric lck = __kmp_get_critical_section_ptr(crit, loc, global_tid); 13780b57cec5SDimitry Andric } 13790b57cec5SDimitry Andric 13800b57cec5SDimitry Andric if (__kmp_env_consistency_check) 13810b57cec5SDimitry Andric __kmp_push_sync(global_tid, ct_critical, loc, lck); 13820b57cec5SDimitry Andric 13830b57cec5SDimitry Andric // since the critical directive binds to all threads, not just the current 13840b57cec5SDimitry Andric // team we have to check this even if we are in a serialized team. 13850b57cec5SDimitry Andric // also, even if we are the uber thread, we still have to conduct the lock, 13860b57cec5SDimitry Andric // as we have to contend with sibling threads. 13870b57cec5SDimitry Andric 13880b57cec5SDimitry Andric #if USE_ITT_BUILD 13890b57cec5SDimitry Andric __kmp_itt_critical_acquiring(lck); 13900b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 13910b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 13920b57cec5SDimitry Andric OMPT_STORE_RETURN_ADDRESS(gtid); 13930b57cec5SDimitry Andric void *codeptr_ra = NULL; 13940b57cec5SDimitry Andric if (ompt_enabled.enabled) { 13950b57cec5SDimitry Andric ti = __kmp_threads[global_tid]->th.ompt_thread_info; 13960b57cec5SDimitry Andric /* OMPT state update */ 13970b57cec5SDimitry Andric prev_state = ti.state; 13980b57cec5SDimitry Andric ti.wait_id = (ompt_wait_id_t)(uintptr_t)lck; 13990b57cec5SDimitry Andric ti.state = ompt_state_wait_critical; 14000b57cec5SDimitry Andric 14010b57cec5SDimitry Andric /* OMPT event callback */ 14020b57cec5SDimitry Andric codeptr_ra = OMPT_LOAD_RETURN_ADDRESS(gtid); 14030b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquire) { 14040b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( 14050b57cec5SDimitry Andric ompt_mutex_critical, omp_lock_hint_none, __ompt_get_mutex_impl_type(), 14060b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)lck, codeptr_ra); 14070b57cec5SDimitry Andric } 14080b57cec5SDimitry Andric } 14090b57cec5SDimitry Andric #endif 14100b57cec5SDimitry Andric // Value of 'crit' should be good for using as a critical_id of the critical 14110b57cec5SDimitry Andric // section directive. 14120b57cec5SDimitry Andric __kmp_acquire_user_lock_with_checks(lck, global_tid); 14130b57cec5SDimitry Andric 14140b57cec5SDimitry Andric #if USE_ITT_BUILD 14150b57cec5SDimitry Andric __kmp_itt_critical_acquired(lck); 14160b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 14170b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 14180b57cec5SDimitry Andric if (ompt_enabled.enabled) { 14190b57cec5SDimitry Andric /* OMPT state update */ 14200b57cec5SDimitry Andric ti.state = prev_state; 14210b57cec5SDimitry Andric ti.wait_id = 0; 14220b57cec5SDimitry Andric 14230b57cec5SDimitry Andric /* OMPT event callback */ 14240b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquired) { 14250b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( 14260b57cec5SDimitry Andric ompt_mutex_critical, (ompt_wait_id_t)(uintptr_t)lck, codeptr_ra); 14270b57cec5SDimitry Andric } 14280b57cec5SDimitry Andric } 14290b57cec5SDimitry Andric #endif 14300b57cec5SDimitry Andric KMP_POP_PARTITIONED_TIMER(); 14310b57cec5SDimitry Andric 14320b57cec5SDimitry Andric KMP_PUSH_PARTITIONED_TIMER(OMP_critical); 14330b57cec5SDimitry Andric KA_TRACE(15, ("__kmpc_critical: done T#%d\n", global_tid)); 14340b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 14350b57cec5SDimitry Andric } 14360b57cec5SDimitry Andric 14370b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 14380b57cec5SDimitry Andric 14390b57cec5SDimitry Andric // Converts the given hint to an internal lock implementation 14400b57cec5SDimitry Andric static __forceinline kmp_dyna_lockseq_t __kmp_map_hint_to_lock(uintptr_t hint) { 14410b57cec5SDimitry Andric #if KMP_USE_TSX 14420b57cec5SDimitry Andric #define KMP_TSX_LOCK(seq) lockseq_##seq 14430b57cec5SDimitry Andric #else 14440b57cec5SDimitry Andric #define KMP_TSX_LOCK(seq) __kmp_user_lock_seq 14450b57cec5SDimitry Andric #endif 14460b57cec5SDimitry Andric 14470b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64 1448349cc55cSDimitry Andric #define KMP_CPUINFO_RTM (__kmp_cpuinfo.flags.rtm) 14490b57cec5SDimitry Andric #else 14500b57cec5SDimitry Andric #define KMP_CPUINFO_RTM 0 14510b57cec5SDimitry Andric #endif 14520b57cec5SDimitry Andric 14530b57cec5SDimitry Andric // Hints that do not require further logic 14540b57cec5SDimitry Andric if (hint & kmp_lock_hint_hle) 14550b57cec5SDimitry Andric return KMP_TSX_LOCK(hle); 14560b57cec5SDimitry Andric if (hint & kmp_lock_hint_rtm) 1457e8d8bef9SDimitry Andric return KMP_CPUINFO_RTM ? KMP_TSX_LOCK(rtm_queuing) : __kmp_user_lock_seq; 14580b57cec5SDimitry Andric if (hint & kmp_lock_hint_adaptive) 14590b57cec5SDimitry Andric return KMP_CPUINFO_RTM ? KMP_TSX_LOCK(adaptive) : __kmp_user_lock_seq; 14600b57cec5SDimitry Andric 14610b57cec5SDimitry Andric // Rule out conflicting hints first by returning the default lock 14620b57cec5SDimitry Andric if ((hint & omp_lock_hint_contended) && (hint & omp_lock_hint_uncontended)) 14630b57cec5SDimitry Andric return __kmp_user_lock_seq; 14640b57cec5SDimitry Andric if ((hint & omp_lock_hint_speculative) && 14650b57cec5SDimitry Andric (hint & omp_lock_hint_nonspeculative)) 14660b57cec5SDimitry Andric return __kmp_user_lock_seq; 14670b57cec5SDimitry Andric 14680b57cec5SDimitry Andric // Do not even consider speculation when it appears to be contended 14690b57cec5SDimitry Andric if (hint & omp_lock_hint_contended) 14700b57cec5SDimitry Andric return lockseq_queuing; 14710b57cec5SDimitry Andric 14720b57cec5SDimitry Andric // Uncontended lock without speculation 14730b57cec5SDimitry Andric if ((hint & omp_lock_hint_uncontended) && !(hint & omp_lock_hint_speculative)) 14740b57cec5SDimitry Andric return lockseq_tas; 14750b57cec5SDimitry Andric 1476e8d8bef9SDimitry Andric // Use RTM lock for speculation 14770b57cec5SDimitry Andric if (hint & omp_lock_hint_speculative) 1478e8d8bef9SDimitry Andric return KMP_CPUINFO_RTM ? KMP_TSX_LOCK(rtm_spin) : __kmp_user_lock_seq; 14790b57cec5SDimitry Andric 14800b57cec5SDimitry Andric return __kmp_user_lock_seq; 14810b57cec5SDimitry Andric } 14820b57cec5SDimitry Andric 14830b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 14840b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 14850b57cec5SDimitry Andric static kmp_mutex_impl_t 14860b57cec5SDimitry Andric __ompt_get_mutex_impl_type(void *user_lock, kmp_indirect_lock_t *ilock = 0) { 14870b57cec5SDimitry Andric if (user_lock) { 14880b57cec5SDimitry Andric switch (KMP_EXTRACT_D_TAG(user_lock)) { 14890b57cec5SDimitry Andric case 0: 14900b57cec5SDimitry Andric break; 14910b57cec5SDimitry Andric #if KMP_USE_FUTEX 14920b57cec5SDimitry Andric case locktag_futex: 14930b57cec5SDimitry Andric return kmp_mutex_impl_queuing; 14940b57cec5SDimitry Andric #endif 14950b57cec5SDimitry Andric case locktag_tas: 14960b57cec5SDimitry Andric return kmp_mutex_impl_spin; 14970b57cec5SDimitry Andric #if KMP_USE_TSX 14980b57cec5SDimitry Andric case locktag_hle: 1499e8d8bef9SDimitry Andric case locktag_rtm_spin: 15000b57cec5SDimitry Andric return kmp_mutex_impl_speculative; 15010b57cec5SDimitry Andric #endif 15020b57cec5SDimitry Andric default: 15030b57cec5SDimitry Andric return kmp_mutex_impl_none; 15040b57cec5SDimitry Andric } 15050b57cec5SDimitry Andric ilock = KMP_LOOKUP_I_LOCK(user_lock); 15060b57cec5SDimitry Andric } 15070b57cec5SDimitry Andric KMP_ASSERT(ilock); 15080b57cec5SDimitry Andric switch (ilock->type) { 15090b57cec5SDimitry Andric #if KMP_USE_TSX 15100b57cec5SDimitry Andric case locktag_adaptive: 1511e8d8bef9SDimitry Andric case locktag_rtm_queuing: 15120b57cec5SDimitry Andric return kmp_mutex_impl_speculative; 15130b57cec5SDimitry Andric #endif 15140b57cec5SDimitry Andric case locktag_nested_tas: 15150b57cec5SDimitry Andric return kmp_mutex_impl_spin; 15160b57cec5SDimitry Andric #if KMP_USE_FUTEX 15170b57cec5SDimitry Andric case locktag_nested_futex: 15180b57cec5SDimitry Andric #endif 15190b57cec5SDimitry Andric case locktag_ticket: 15200b57cec5SDimitry Andric case locktag_queuing: 15210b57cec5SDimitry Andric case locktag_drdpa: 15220b57cec5SDimitry Andric case locktag_nested_ticket: 15230b57cec5SDimitry Andric case locktag_nested_queuing: 15240b57cec5SDimitry Andric case locktag_nested_drdpa: 15250b57cec5SDimitry Andric return kmp_mutex_impl_queuing; 15260b57cec5SDimitry Andric default: 15270b57cec5SDimitry Andric return kmp_mutex_impl_none; 15280b57cec5SDimitry Andric } 15290b57cec5SDimitry Andric } 15300b57cec5SDimitry Andric #else 15310b57cec5SDimitry Andric // For locks without dynamic binding 15320b57cec5SDimitry Andric static kmp_mutex_impl_t __ompt_get_mutex_impl_type() { 15330b57cec5SDimitry Andric switch (__kmp_user_lock_kind) { 15340b57cec5SDimitry Andric case lk_tas: 15350b57cec5SDimitry Andric return kmp_mutex_impl_spin; 15360b57cec5SDimitry Andric #if KMP_USE_FUTEX 15370b57cec5SDimitry Andric case lk_futex: 15380b57cec5SDimitry Andric #endif 15390b57cec5SDimitry Andric case lk_ticket: 15400b57cec5SDimitry Andric case lk_queuing: 15410b57cec5SDimitry Andric case lk_drdpa: 15420b57cec5SDimitry Andric return kmp_mutex_impl_queuing; 15430b57cec5SDimitry Andric #if KMP_USE_TSX 15440b57cec5SDimitry Andric case lk_hle: 1545e8d8bef9SDimitry Andric case lk_rtm_queuing: 1546e8d8bef9SDimitry Andric case lk_rtm_spin: 15470b57cec5SDimitry Andric case lk_adaptive: 15480b57cec5SDimitry Andric return kmp_mutex_impl_speculative; 15490b57cec5SDimitry Andric #endif 15500b57cec5SDimitry Andric default: 15510b57cec5SDimitry Andric return kmp_mutex_impl_none; 15520b57cec5SDimitry Andric } 15530b57cec5SDimitry Andric } 15540b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 15550b57cec5SDimitry Andric #endif // OMPT_SUPPORT && OMPT_OPTIONAL 15560b57cec5SDimitry Andric 15570b57cec5SDimitry Andric /*! 15580b57cec5SDimitry Andric @ingroup WORK_SHARING 15590b57cec5SDimitry Andric @param loc source location information. 15600b57cec5SDimitry Andric @param global_tid global thread number. 15610b57cec5SDimitry Andric @param crit identity of the critical section. This could be a pointer to a lock 15620b57cec5SDimitry Andric associated with the critical section, or some other suitably unique value. 15630b57cec5SDimitry Andric @param hint the lock hint. 15640b57cec5SDimitry Andric 15650b57cec5SDimitry Andric Enter code protected by a `critical` construct with a hint. The hint value is 15660b57cec5SDimitry Andric used to suggest a lock implementation. This function blocks until the executing 15670b57cec5SDimitry Andric thread can enter the critical section unless the hint suggests use of 15680b57cec5SDimitry Andric speculative execution and the hardware supports it. 15690b57cec5SDimitry Andric */ 15700b57cec5SDimitry Andric void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 15710b57cec5SDimitry Andric kmp_critical_name *crit, uint32_t hint) { 15720b57cec5SDimitry Andric KMP_COUNT_BLOCK(OMP_CRITICAL); 15730b57cec5SDimitry Andric kmp_user_lock_p lck; 15740b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 15750b57cec5SDimitry Andric ompt_state_t prev_state = ompt_state_undefined; 15760b57cec5SDimitry Andric ompt_thread_info_t ti; 15770b57cec5SDimitry Andric // This is the case, if called from __kmpc_critical: 15780b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(global_tid); 15790b57cec5SDimitry Andric if (!codeptr) 15800b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 15810b57cec5SDimitry Andric #endif 15820b57cec5SDimitry Andric 15830b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_critical: called T#%d\n", global_tid)); 1584e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 15850b57cec5SDimitry Andric 15860b57cec5SDimitry Andric kmp_dyna_lock_t *lk = (kmp_dyna_lock_t *)crit; 15870b57cec5SDimitry Andric // Check if it is initialized. 15880b57cec5SDimitry Andric KMP_PUSH_PARTITIONED_TIMER(OMP_critical_wait); 1589fe6060f1SDimitry Andric kmp_dyna_lockseq_t lockseq = __kmp_map_hint_to_lock(hint); 15900b57cec5SDimitry Andric if (*lk == 0) { 1591fe6060f1SDimitry Andric if (KMP_IS_D_LOCK(lockseq)) { 159274626c16SDimitry Andric KMP_COMPARE_AND_STORE_ACQ32( 159374626c16SDimitry Andric (volatile kmp_int32 *)&((kmp_base_tas_lock_t *)crit)->poll, 0, 1594fe6060f1SDimitry Andric KMP_GET_D_TAG(lockseq)); 15950b57cec5SDimitry Andric } else { 1596fe6060f1SDimitry Andric __kmp_init_indirect_csptr(crit, loc, global_tid, KMP_GET_I_TAG(lockseq)); 15970b57cec5SDimitry Andric } 15980b57cec5SDimitry Andric } 15990b57cec5SDimitry Andric // Branch for accessing the actual lock object and set operation. This 16000b57cec5SDimitry Andric // branching is inevitable since this lock initialization does not follow the 16010b57cec5SDimitry Andric // normal dispatch path (lock table is not used). 16020b57cec5SDimitry Andric if (KMP_EXTRACT_D_TAG(lk) != 0) { 16030b57cec5SDimitry Andric lck = (kmp_user_lock_p)lk; 16040b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 16050b57cec5SDimitry Andric __kmp_push_sync(global_tid, ct_critical, loc, lck, 16060b57cec5SDimitry Andric __kmp_map_hint_to_lock(hint)); 16070b57cec5SDimitry Andric } 16080b57cec5SDimitry Andric #if USE_ITT_BUILD 16090b57cec5SDimitry Andric __kmp_itt_critical_acquiring(lck); 16100b57cec5SDimitry Andric #endif 16110b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 16120b57cec5SDimitry Andric if (ompt_enabled.enabled) { 16130b57cec5SDimitry Andric ti = __kmp_threads[global_tid]->th.ompt_thread_info; 16140b57cec5SDimitry Andric /* OMPT state update */ 16150b57cec5SDimitry Andric prev_state = ti.state; 16160b57cec5SDimitry Andric ti.wait_id = (ompt_wait_id_t)(uintptr_t)lck; 16170b57cec5SDimitry Andric ti.state = ompt_state_wait_critical; 16180b57cec5SDimitry Andric 16190b57cec5SDimitry Andric /* OMPT event callback */ 16200b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquire) { 16210b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( 16220b57cec5SDimitry Andric ompt_mutex_critical, (unsigned int)hint, 16230b57cec5SDimitry Andric __ompt_get_mutex_impl_type(crit), (ompt_wait_id_t)(uintptr_t)lck, 16240b57cec5SDimitry Andric codeptr); 16250b57cec5SDimitry Andric } 16260b57cec5SDimitry Andric } 16270b57cec5SDimitry Andric #endif 16280b57cec5SDimitry Andric #if KMP_USE_INLINED_TAS 1629fe6060f1SDimitry Andric if (lockseq == lockseq_tas && !__kmp_env_consistency_check) { 16300b57cec5SDimitry Andric KMP_ACQUIRE_TAS_LOCK(lck, global_tid); 16310b57cec5SDimitry Andric } else 16320b57cec5SDimitry Andric #elif KMP_USE_INLINED_FUTEX 1633fe6060f1SDimitry Andric if (lockseq == lockseq_futex && !__kmp_env_consistency_check) { 16340b57cec5SDimitry Andric KMP_ACQUIRE_FUTEX_LOCK(lck, global_tid); 16350b57cec5SDimitry Andric } else 16360b57cec5SDimitry Andric #endif 16370b57cec5SDimitry Andric { 16380b57cec5SDimitry Andric KMP_D_LOCK_FUNC(lk, set)(lk, global_tid); 16390b57cec5SDimitry Andric } 16400b57cec5SDimitry Andric } else { 16410b57cec5SDimitry Andric kmp_indirect_lock_t *ilk = *((kmp_indirect_lock_t **)lk); 16420b57cec5SDimitry Andric lck = ilk->lock; 16430b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 16440b57cec5SDimitry Andric __kmp_push_sync(global_tid, ct_critical, loc, lck, 16450b57cec5SDimitry Andric __kmp_map_hint_to_lock(hint)); 16460b57cec5SDimitry Andric } 16470b57cec5SDimitry Andric #if USE_ITT_BUILD 16480b57cec5SDimitry Andric __kmp_itt_critical_acquiring(lck); 16490b57cec5SDimitry Andric #endif 16500b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 16510b57cec5SDimitry Andric if (ompt_enabled.enabled) { 16520b57cec5SDimitry Andric ti = __kmp_threads[global_tid]->th.ompt_thread_info; 16530b57cec5SDimitry Andric /* OMPT state update */ 16540b57cec5SDimitry Andric prev_state = ti.state; 16550b57cec5SDimitry Andric ti.wait_id = (ompt_wait_id_t)(uintptr_t)lck; 16560b57cec5SDimitry Andric ti.state = ompt_state_wait_critical; 16570b57cec5SDimitry Andric 16580b57cec5SDimitry Andric /* OMPT event callback */ 16590b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquire) { 16600b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( 16610b57cec5SDimitry Andric ompt_mutex_critical, (unsigned int)hint, 16620b57cec5SDimitry Andric __ompt_get_mutex_impl_type(0, ilk), (ompt_wait_id_t)(uintptr_t)lck, 16630b57cec5SDimitry Andric codeptr); 16640b57cec5SDimitry Andric } 16650b57cec5SDimitry Andric } 16660b57cec5SDimitry Andric #endif 16670b57cec5SDimitry Andric KMP_I_LOCK_FUNC(ilk, set)(lck, global_tid); 16680b57cec5SDimitry Andric } 16690b57cec5SDimitry Andric KMP_POP_PARTITIONED_TIMER(); 16700b57cec5SDimitry Andric 16710b57cec5SDimitry Andric #if USE_ITT_BUILD 16720b57cec5SDimitry Andric __kmp_itt_critical_acquired(lck); 16730b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 16740b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 16750b57cec5SDimitry Andric if (ompt_enabled.enabled) { 16760b57cec5SDimitry Andric /* OMPT state update */ 16770b57cec5SDimitry Andric ti.state = prev_state; 16780b57cec5SDimitry Andric ti.wait_id = 0; 16790b57cec5SDimitry Andric 16800b57cec5SDimitry Andric /* OMPT event callback */ 16810b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquired) { 16820b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( 16830b57cec5SDimitry Andric ompt_mutex_critical, (ompt_wait_id_t)(uintptr_t)lck, codeptr); 16840b57cec5SDimitry Andric } 16850b57cec5SDimitry Andric } 16860b57cec5SDimitry Andric #endif 16870b57cec5SDimitry Andric 16880b57cec5SDimitry Andric KMP_PUSH_PARTITIONED_TIMER(OMP_critical); 16890b57cec5SDimitry Andric KA_TRACE(15, ("__kmpc_critical: done T#%d\n", global_tid)); 16900b57cec5SDimitry Andric } // __kmpc_critical_with_hint 16910b57cec5SDimitry Andric 16920b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 16930b57cec5SDimitry Andric 16940b57cec5SDimitry Andric /*! 16950b57cec5SDimitry Andric @ingroup WORK_SHARING 16960b57cec5SDimitry Andric @param loc source location information. 16970b57cec5SDimitry Andric @param global_tid global thread number . 16980b57cec5SDimitry Andric @param crit identity of the critical section. This could be a pointer to a lock 16990b57cec5SDimitry Andric associated with the critical section, or some other suitably unique value. 17000b57cec5SDimitry Andric 17010b57cec5SDimitry Andric Leave a critical section, releasing any lock that was held during its execution. 17020b57cec5SDimitry Andric */ 17030b57cec5SDimitry Andric void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 17040b57cec5SDimitry Andric kmp_critical_name *crit) { 17050b57cec5SDimitry Andric kmp_user_lock_p lck; 17060b57cec5SDimitry Andric 17070b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_end_critical: called T#%d\n", global_tid)); 17080b57cec5SDimitry Andric 17090b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 1710fe6060f1SDimitry Andric int locktag = KMP_EXTRACT_D_TAG(crit); 1711fe6060f1SDimitry Andric if (locktag) { 17120b57cec5SDimitry Andric lck = (kmp_user_lock_p)crit; 17130b57cec5SDimitry Andric KMP_ASSERT(lck != NULL); 17140b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 17150b57cec5SDimitry Andric __kmp_pop_sync(global_tid, ct_critical, loc); 17160b57cec5SDimitry Andric } 17170b57cec5SDimitry Andric #if USE_ITT_BUILD 17180b57cec5SDimitry Andric __kmp_itt_critical_releasing(lck); 17190b57cec5SDimitry Andric #endif 17200b57cec5SDimitry Andric #if KMP_USE_INLINED_TAS 1721fe6060f1SDimitry Andric if (locktag == locktag_tas && !__kmp_env_consistency_check) { 17220b57cec5SDimitry Andric KMP_RELEASE_TAS_LOCK(lck, global_tid); 17230b57cec5SDimitry Andric } else 17240b57cec5SDimitry Andric #elif KMP_USE_INLINED_FUTEX 1725fe6060f1SDimitry Andric if (locktag == locktag_futex && !__kmp_env_consistency_check) { 17260b57cec5SDimitry Andric KMP_RELEASE_FUTEX_LOCK(lck, global_tid); 17270b57cec5SDimitry Andric } else 17280b57cec5SDimitry Andric #endif 17290b57cec5SDimitry Andric { 17300b57cec5SDimitry Andric KMP_D_LOCK_FUNC(lck, unset)((kmp_dyna_lock_t *)lck, global_tid); 17310b57cec5SDimitry Andric } 17320b57cec5SDimitry Andric } else { 17330b57cec5SDimitry Andric kmp_indirect_lock_t *ilk = 17340b57cec5SDimitry Andric (kmp_indirect_lock_t *)TCR_PTR(*((kmp_indirect_lock_t **)crit)); 17350b57cec5SDimitry Andric KMP_ASSERT(ilk != NULL); 17360b57cec5SDimitry Andric lck = ilk->lock; 17370b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 17380b57cec5SDimitry Andric __kmp_pop_sync(global_tid, ct_critical, loc); 17390b57cec5SDimitry Andric } 17400b57cec5SDimitry Andric #if USE_ITT_BUILD 17410b57cec5SDimitry Andric __kmp_itt_critical_releasing(lck); 17420b57cec5SDimitry Andric #endif 17430b57cec5SDimitry Andric KMP_I_LOCK_FUNC(ilk, unset)(lck, global_tid); 17440b57cec5SDimitry Andric } 17450b57cec5SDimitry Andric 17460b57cec5SDimitry Andric #else // KMP_USE_DYNAMIC_LOCK 17470b57cec5SDimitry Andric 17480b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 17490b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) <= OMP_CRITICAL_SIZE)) { 17500b57cec5SDimitry Andric lck = (kmp_user_lock_p)crit; 17510b57cec5SDimitry Andric } 17520b57cec5SDimitry Andric #if KMP_USE_FUTEX 17530b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 17540b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) <= OMP_CRITICAL_SIZE)) { 17550b57cec5SDimitry Andric lck = (kmp_user_lock_p)crit; 17560b57cec5SDimitry Andric } 17570b57cec5SDimitry Andric #endif 17580b57cec5SDimitry Andric else { // ticket, queuing or drdpa 17590b57cec5SDimitry Andric lck = (kmp_user_lock_p)TCR_PTR(*((kmp_user_lock_p *)crit)); 17600b57cec5SDimitry Andric } 17610b57cec5SDimitry Andric 17620b57cec5SDimitry Andric KMP_ASSERT(lck != NULL); 17630b57cec5SDimitry Andric 17640b57cec5SDimitry Andric if (__kmp_env_consistency_check) 17650b57cec5SDimitry Andric __kmp_pop_sync(global_tid, ct_critical, loc); 17660b57cec5SDimitry Andric 17670b57cec5SDimitry Andric #if USE_ITT_BUILD 17680b57cec5SDimitry Andric __kmp_itt_critical_releasing(lck); 17690b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 17700b57cec5SDimitry Andric // Value of 'crit' should be good for using as a critical_id of the critical 17710b57cec5SDimitry Andric // section directive. 17720b57cec5SDimitry Andric __kmp_release_user_lock_with_checks(lck, global_tid); 17730b57cec5SDimitry Andric 17740b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 17750b57cec5SDimitry Andric 17760b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 17770b57cec5SDimitry Andric /* OMPT release event triggers after lock is released; place here to trigger 17780b57cec5SDimitry Andric * for all #if branches */ 17790b57cec5SDimitry Andric OMPT_STORE_RETURN_ADDRESS(global_tid); 17800b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_released) { 17810b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( 17820b57cec5SDimitry Andric ompt_mutex_critical, (ompt_wait_id_t)(uintptr_t)lck, 17830b57cec5SDimitry Andric OMPT_LOAD_RETURN_ADDRESS(0)); 17840b57cec5SDimitry Andric } 17850b57cec5SDimitry Andric #endif 17860b57cec5SDimitry Andric 17870b57cec5SDimitry Andric KMP_POP_PARTITIONED_TIMER(); 17880b57cec5SDimitry Andric KA_TRACE(15, ("__kmpc_end_critical: done T#%d\n", global_tid)); 17890b57cec5SDimitry Andric } 17900b57cec5SDimitry Andric 17910b57cec5SDimitry Andric /*! 17920b57cec5SDimitry Andric @ingroup SYNCHRONIZATION 17930b57cec5SDimitry Andric @param loc source location information 17940b57cec5SDimitry Andric @param global_tid thread id. 17950b57cec5SDimitry Andric @return one if the thread should execute the master block, zero otherwise 17960b57cec5SDimitry Andric 17970b57cec5SDimitry Andric Start execution of a combined barrier and master. The barrier is executed inside 17980b57cec5SDimitry Andric this function. 17990b57cec5SDimitry Andric */ 18000b57cec5SDimitry Andric kmp_int32 __kmpc_barrier_master(ident_t *loc, kmp_int32 global_tid) { 18010b57cec5SDimitry Andric int status; 18020b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_barrier_master: called T#%d\n", global_tid)); 1803e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 18040b57cec5SDimitry Andric 18050b57cec5SDimitry Andric if (!TCR_4(__kmp_init_parallel)) 18060b57cec5SDimitry Andric __kmp_parallel_initialize(); 18070b57cec5SDimitry Andric 18080b57cec5SDimitry Andric __kmp_resume_if_soft_paused(); 18090b57cec5SDimitry Andric 18100b57cec5SDimitry Andric if (__kmp_env_consistency_check) 18110b57cec5SDimitry Andric __kmp_check_barrier(global_tid, ct_barrier, loc); 18120b57cec5SDimitry Andric 18130b57cec5SDimitry Andric #if OMPT_SUPPORT 18140b57cec5SDimitry Andric ompt_frame_t *ompt_frame; 18150b57cec5SDimitry Andric if (ompt_enabled.enabled) { 18160b57cec5SDimitry Andric __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL); 18170b57cec5SDimitry Andric if (ompt_frame->enter_frame.ptr == NULL) 18180b57cec5SDimitry Andric ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0); 18190b57cec5SDimitry Andric } 1820e8d8bef9SDimitry Andric OMPT_STORE_RETURN_ADDRESS(global_tid); 18210b57cec5SDimitry Andric #endif 18220b57cec5SDimitry Andric #if USE_ITT_NOTIFY 18230b57cec5SDimitry Andric __kmp_threads[global_tid]->th.th_ident = loc; 18240b57cec5SDimitry Andric #endif 18250b57cec5SDimitry Andric status = __kmp_barrier(bs_plain_barrier, global_tid, TRUE, 0, NULL, NULL); 18260b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 18270b57cec5SDimitry Andric if (ompt_enabled.enabled) { 18280b57cec5SDimitry Andric ompt_frame->enter_frame = ompt_data_none; 18290b57cec5SDimitry Andric } 18300b57cec5SDimitry Andric #endif 18310b57cec5SDimitry Andric 18320b57cec5SDimitry Andric return (status != 0) ? 0 : 1; 18330b57cec5SDimitry Andric } 18340b57cec5SDimitry Andric 18350b57cec5SDimitry Andric /*! 18360b57cec5SDimitry Andric @ingroup SYNCHRONIZATION 18370b57cec5SDimitry Andric @param loc source location information 18380b57cec5SDimitry Andric @param global_tid thread id. 18390b57cec5SDimitry Andric 18400b57cec5SDimitry Andric Complete the execution of a combined barrier and master. This function should 18410b57cec5SDimitry Andric only be called at the completion of the <tt>master</tt> code. Other threads will 18420b57cec5SDimitry Andric still be waiting at the barrier and this call releases them. 18430b57cec5SDimitry Andric */ 18440b57cec5SDimitry Andric void __kmpc_end_barrier_master(ident_t *loc, kmp_int32 global_tid) { 18450b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_end_barrier_master: called T#%d\n", global_tid)); 1846e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 18470b57cec5SDimitry Andric __kmp_end_split_barrier(bs_plain_barrier, global_tid); 18480b57cec5SDimitry Andric } 18490b57cec5SDimitry Andric 18500b57cec5SDimitry Andric /*! 18510b57cec5SDimitry Andric @ingroup SYNCHRONIZATION 18520b57cec5SDimitry Andric @param loc source location information 18530b57cec5SDimitry Andric @param global_tid thread id. 18540b57cec5SDimitry Andric @return one if the thread should execute the master block, zero otherwise 18550b57cec5SDimitry Andric 18560b57cec5SDimitry Andric Start execution of a combined barrier and master(nowait) construct. 18570b57cec5SDimitry Andric The barrier is executed inside this function. 18580b57cec5SDimitry Andric There is no equivalent "end" function, since the 18590b57cec5SDimitry Andric */ 18600b57cec5SDimitry Andric kmp_int32 __kmpc_barrier_master_nowait(ident_t *loc, kmp_int32 global_tid) { 18610b57cec5SDimitry Andric kmp_int32 ret; 18620b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_barrier_master_nowait: called T#%d\n", global_tid)); 1863e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 18640b57cec5SDimitry Andric 18650b57cec5SDimitry Andric if (!TCR_4(__kmp_init_parallel)) 18660b57cec5SDimitry Andric __kmp_parallel_initialize(); 18670b57cec5SDimitry Andric 18680b57cec5SDimitry Andric __kmp_resume_if_soft_paused(); 18690b57cec5SDimitry Andric 18700b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 18710b57cec5SDimitry Andric if (loc == 0) { 18720b57cec5SDimitry Andric KMP_WARNING(ConstructIdentInvalid); // ??? What does it mean for the user? 18730b57cec5SDimitry Andric } 18740b57cec5SDimitry Andric __kmp_check_barrier(global_tid, ct_barrier, loc); 18750b57cec5SDimitry Andric } 18760b57cec5SDimitry Andric 18770b57cec5SDimitry Andric #if OMPT_SUPPORT 18780b57cec5SDimitry Andric ompt_frame_t *ompt_frame; 18790b57cec5SDimitry Andric if (ompt_enabled.enabled) { 18800b57cec5SDimitry Andric __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL); 18810b57cec5SDimitry Andric if (ompt_frame->enter_frame.ptr == NULL) 18820b57cec5SDimitry Andric ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0); 18830b57cec5SDimitry Andric } 1884e8d8bef9SDimitry Andric OMPT_STORE_RETURN_ADDRESS(global_tid); 18850b57cec5SDimitry Andric #endif 18860b57cec5SDimitry Andric #if USE_ITT_NOTIFY 18870b57cec5SDimitry Andric __kmp_threads[global_tid]->th.th_ident = loc; 18880b57cec5SDimitry Andric #endif 18890b57cec5SDimitry Andric __kmp_barrier(bs_plain_barrier, global_tid, FALSE, 0, NULL, NULL); 18900b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 18910b57cec5SDimitry Andric if (ompt_enabled.enabled) { 18920b57cec5SDimitry Andric ompt_frame->enter_frame = ompt_data_none; 18930b57cec5SDimitry Andric } 18940b57cec5SDimitry Andric #endif 18950b57cec5SDimitry Andric 18960b57cec5SDimitry Andric ret = __kmpc_master(loc, global_tid); 18970b57cec5SDimitry Andric 18980b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 18990b57cec5SDimitry Andric /* there's no __kmpc_end_master called; so the (stats) */ 19000b57cec5SDimitry Andric /* actions of __kmpc_end_master are done here */ 19010b57cec5SDimitry Andric if (ret) { 19020b57cec5SDimitry Andric /* only one thread should do the pop since only */ 19030b57cec5SDimitry Andric /* one did the push (see __kmpc_master()) */ 19040b57cec5SDimitry Andric __kmp_pop_sync(global_tid, ct_master, loc); 19050b57cec5SDimitry Andric } 19060b57cec5SDimitry Andric } 19070b57cec5SDimitry Andric 19080b57cec5SDimitry Andric return (ret); 19090b57cec5SDimitry Andric } 19100b57cec5SDimitry Andric 19110b57cec5SDimitry Andric /* The BARRIER for a SINGLE process section is always explicit */ 19120b57cec5SDimitry Andric /*! 19130b57cec5SDimitry Andric @ingroup WORK_SHARING 19140b57cec5SDimitry Andric @param loc source location information 19150b57cec5SDimitry Andric @param global_tid global thread number 19160b57cec5SDimitry Andric @return One if this thread should execute the single construct, zero otherwise. 19170b57cec5SDimitry Andric 19180b57cec5SDimitry Andric Test whether to execute a <tt>single</tt> construct. 19190b57cec5SDimitry Andric There are no implicit barriers in the two "single" calls, rather the compiler 19200b57cec5SDimitry Andric should introduce an explicit barrier if it is required. 19210b57cec5SDimitry Andric */ 19220b57cec5SDimitry Andric 19230b57cec5SDimitry Andric kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid) { 1924e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 19250b57cec5SDimitry Andric kmp_int32 rc = __kmp_enter_single(global_tid, loc, TRUE); 19260b57cec5SDimitry Andric 19270b57cec5SDimitry Andric if (rc) { 19280b57cec5SDimitry Andric // We are going to execute the single statement, so we should count it. 19290b57cec5SDimitry Andric KMP_COUNT_BLOCK(OMP_SINGLE); 19300b57cec5SDimitry Andric KMP_PUSH_PARTITIONED_TIMER(OMP_single); 19310b57cec5SDimitry Andric } 19320b57cec5SDimitry Andric 19330b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 19340b57cec5SDimitry Andric kmp_info_t *this_thr = __kmp_threads[global_tid]; 19350b57cec5SDimitry Andric kmp_team_t *team = this_thr->th.th_team; 19360b57cec5SDimitry Andric int tid = __kmp_tid_from_gtid(global_tid); 19370b57cec5SDimitry Andric 19380b57cec5SDimitry Andric if (ompt_enabled.enabled) { 19390b57cec5SDimitry Andric if (rc) { 19400b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_work) { 19410b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_work)( 19420b57cec5SDimitry Andric ompt_work_single_executor, ompt_scope_begin, 19430b57cec5SDimitry Andric &(team->t.ompt_team_info.parallel_data), 19440b57cec5SDimitry Andric &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data), 19450b57cec5SDimitry Andric 1, OMPT_GET_RETURN_ADDRESS(0)); 19460b57cec5SDimitry Andric } 19470b57cec5SDimitry Andric } else { 19480b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_work) { 19490b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_work)( 19500b57cec5SDimitry Andric ompt_work_single_other, ompt_scope_begin, 19510b57cec5SDimitry Andric &(team->t.ompt_team_info.parallel_data), 19520b57cec5SDimitry Andric &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data), 19530b57cec5SDimitry Andric 1, OMPT_GET_RETURN_ADDRESS(0)); 19540b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_work)( 19550b57cec5SDimitry Andric ompt_work_single_other, ompt_scope_end, 19560b57cec5SDimitry Andric &(team->t.ompt_team_info.parallel_data), 19570b57cec5SDimitry Andric &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data), 19580b57cec5SDimitry Andric 1, OMPT_GET_RETURN_ADDRESS(0)); 19590b57cec5SDimitry Andric } 19600b57cec5SDimitry Andric } 19610b57cec5SDimitry Andric } 19620b57cec5SDimitry Andric #endif 19630b57cec5SDimitry Andric 19640b57cec5SDimitry Andric return rc; 19650b57cec5SDimitry Andric } 19660b57cec5SDimitry Andric 19670b57cec5SDimitry Andric /*! 19680b57cec5SDimitry Andric @ingroup WORK_SHARING 19690b57cec5SDimitry Andric @param loc source location information 19700b57cec5SDimitry Andric @param global_tid global thread number 19710b57cec5SDimitry Andric 19720b57cec5SDimitry Andric Mark the end of a <tt>single</tt> construct. This function should 19730b57cec5SDimitry Andric only be called by the thread that executed the block of code protected 19740b57cec5SDimitry Andric by the `single` construct. 19750b57cec5SDimitry Andric */ 19760b57cec5SDimitry Andric void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid) { 1977e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 19780b57cec5SDimitry Andric __kmp_exit_single(global_tid); 19790b57cec5SDimitry Andric KMP_POP_PARTITIONED_TIMER(); 19800b57cec5SDimitry Andric 19810b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 19820b57cec5SDimitry Andric kmp_info_t *this_thr = __kmp_threads[global_tid]; 19830b57cec5SDimitry Andric kmp_team_t *team = this_thr->th.th_team; 19840b57cec5SDimitry Andric int tid = __kmp_tid_from_gtid(global_tid); 19850b57cec5SDimitry Andric 19860b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_work) { 19870b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_work)( 19880b57cec5SDimitry Andric ompt_work_single_executor, ompt_scope_end, 19890b57cec5SDimitry Andric &(team->t.ompt_team_info.parallel_data), 19900b57cec5SDimitry Andric &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data), 1, 19910b57cec5SDimitry Andric OMPT_GET_RETURN_ADDRESS(0)); 19920b57cec5SDimitry Andric } 19930b57cec5SDimitry Andric #endif 19940b57cec5SDimitry Andric } 19950b57cec5SDimitry Andric 19960b57cec5SDimitry Andric /*! 19970b57cec5SDimitry Andric @ingroup WORK_SHARING 19980b57cec5SDimitry Andric @param loc Source location 19990b57cec5SDimitry Andric @param global_tid Global thread id 20000b57cec5SDimitry Andric 20010b57cec5SDimitry Andric Mark the end of a statically scheduled loop. 20020b57cec5SDimitry Andric */ 20030b57cec5SDimitry Andric void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid) { 20040b57cec5SDimitry Andric KMP_POP_PARTITIONED_TIMER(); 20050b57cec5SDimitry Andric KE_TRACE(10, ("__kmpc_for_static_fini called T#%d\n", global_tid)); 20060b57cec5SDimitry Andric 20070b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 20080b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_work) { 2009*0fca6ea1SDimitry Andric ompt_work_t ompt_work_type = ompt_work_loop_static; 20100b57cec5SDimitry Andric ompt_team_info_t *team_info = __ompt_get_teaminfo(0, NULL); 20110b57cec5SDimitry Andric ompt_task_info_t *task_info = __ompt_get_task_info_object(0); 20120b57cec5SDimitry Andric // Determine workshare type 20130b57cec5SDimitry Andric if (loc != NULL) { 20140b57cec5SDimitry Andric if ((loc->flags & KMP_IDENT_WORK_LOOP) != 0) { 2015*0fca6ea1SDimitry Andric ompt_work_type = ompt_work_loop_static; 20160b57cec5SDimitry Andric } else if ((loc->flags & KMP_IDENT_WORK_SECTIONS) != 0) { 20170b57cec5SDimitry Andric ompt_work_type = ompt_work_sections; 20180b57cec5SDimitry Andric } else if ((loc->flags & KMP_IDENT_WORK_DISTRIBUTE) != 0) { 20190b57cec5SDimitry Andric ompt_work_type = ompt_work_distribute; 20200b57cec5SDimitry Andric } else { 20210b57cec5SDimitry Andric // use default set above. 20220b57cec5SDimitry Andric // a warning about this case is provided in __kmpc_for_static_init 20230b57cec5SDimitry Andric } 20240b57cec5SDimitry Andric KMP_DEBUG_ASSERT(ompt_work_type); 20250b57cec5SDimitry Andric } 20260b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_work)( 20270b57cec5SDimitry Andric ompt_work_type, ompt_scope_end, &(team_info->parallel_data), 20280b57cec5SDimitry Andric &(task_info->task_data), 0, OMPT_GET_RETURN_ADDRESS(0)); 20290b57cec5SDimitry Andric } 20300b57cec5SDimitry Andric #endif 20310b57cec5SDimitry Andric if (__kmp_env_consistency_check) 20320b57cec5SDimitry Andric __kmp_pop_workshare(global_tid, ct_pdo, loc); 20330b57cec5SDimitry Andric } 20340b57cec5SDimitry Andric 20350b57cec5SDimitry Andric // User routines which take C-style arguments (call by value) 20360b57cec5SDimitry Andric // different from the Fortran equivalent routines 20370b57cec5SDimitry Andric 20380b57cec5SDimitry Andric void ompc_set_num_threads(int arg) { 20390b57cec5SDimitry Andric // !!!!! TODO: check the per-task binding 20400b57cec5SDimitry Andric __kmp_set_num_threads(arg, __kmp_entry_gtid()); 20410b57cec5SDimitry Andric } 20420b57cec5SDimitry Andric 20430b57cec5SDimitry Andric void ompc_set_dynamic(int flag) { 20440b57cec5SDimitry Andric kmp_info_t *thread; 20450b57cec5SDimitry Andric 20460b57cec5SDimitry Andric /* For the thread-private implementation of the internal controls */ 20470b57cec5SDimitry Andric thread = __kmp_entry_thread(); 20480b57cec5SDimitry Andric 20490b57cec5SDimitry Andric __kmp_save_internal_controls(thread); 20500b57cec5SDimitry Andric 2051e8d8bef9SDimitry Andric set__dynamic(thread, flag ? true : false); 20520b57cec5SDimitry Andric } 20530b57cec5SDimitry Andric 20540b57cec5SDimitry Andric void ompc_set_nested(int flag) { 20550b57cec5SDimitry Andric kmp_info_t *thread; 20560b57cec5SDimitry Andric 20570b57cec5SDimitry Andric /* For the thread-private internal controls implementation */ 20580b57cec5SDimitry Andric thread = __kmp_entry_thread(); 20590b57cec5SDimitry Andric 20600b57cec5SDimitry Andric __kmp_save_internal_controls(thread); 20610b57cec5SDimitry Andric 20620b57cec5SDimitry Andric set__max_active_levels(thread, flag ? __kmp_dflt_max_active_levels : 1); 20630b57cec5SDimitry Andric } 20640b57cec5SDimitry Andric 20650b57cec5SDimitry Andric void ompc_set_max_active_levels(int max_active_levels) { 20660b57cec5SDimitry Andric /* TO DO */ 20670b57cec5SDimitry Andric /* we want per-task implementation of this internal control */ 20680b57cec5SDimitry Andric 20690b57cec5SDimitry Andric /* For the per-thread internal controls implementation */ 20700b57cec5SDimitry Andric __kmp_set_max_active_levels(__kmp_entry_gtid(), max_active_levels); 20710b57cec5SDimitry Andric } 20720b57cec5SDimitry Andric 20730b57cec5SDimitry Andric void ompc_set_schedule(omp_sched_t kind, int modifier) { 20740b57cec5SDimitry Andric // !!!!! TODO: check the per-task binding 20750b57cec5SDimitry Andric __kmp_set_schedule(__kmp_entry_gtid(), (kmp_sched_t)kind, modifier); 20760b57cec5SDimitry Andric } 20770b57cec5SDimitry Andric 20780b57cec5SDimitry Andric int ompc_get_ancestor_thread_num(int level) { 20790b57cec5SDimitry Andric return __kmp_get_ancestor_thread_num(__kmp_entry_gtid(), level); 20800b57cec5SDimitry Andric } 20810b57cec5SDimitry Andric 20820b57cec5SDimitry Andric int ompc_get_team_size(int level) { 20830b57cec5SDimitry Andric return __kmp_get_team_size(__kmp_entry_gtid(), level); 20840b57cec5SDimitry Andric } 20850b57cec5SDimitry Andric 20860b57cec5SDimitry Andric /* OpenMP 5.0 Affinity Format API */ 2087fe6060f1SDimitry Andric void KMP_EXPAND_NAME(ompc_set_affinity_format)(char const *format) { 20880b57cec5SDimitry Andric if (!__kmp_init_serial) { 20890b57cec5SDimitry Andric __kmp_serial_initialize(); 20900b57cec5SDimitry Andric } 20910b57cec5SDimitry Andric __kmp_strncpy_truncate(__kmp_affinity_format, KMP_AFFINITY_FORMAT_SIZE, 20920b57cec5SDimitry Andric format, KMP_STRLEN(format) + 1); 20930b57cec5SDimitry Andric } 20940b57cec5SDimitry Andric 2095fe6060f1SDimitry Andric size_t KMP_EXPAND_NAME(ompc_get_affinity_format)(char *buffer, size_t size) { 20960b57cec5SDimitry Andric size_t format_size; 20970b57cec5SDimitry Andric if (!__kmp_init_serial) { 20980b57cec5SDimitry Andric __kmp_serial_initialize(); 20990b57cec5SDimitry Andric } 21000b57cec5SDimitry Andric format_size = KMP_STRLEN(__kmp_affinity_format); 21010b57cec5SDimitry Andric if (buffer && size) { 21020b57cec5SDimitry Andric __kmp_strncpy_truncate(buffer, size, __kmp_affinity_format, 21030b57cec5SDimitry Andric format_size + 1); 21040b57cec5SDimitry Andric } 21050b57cec5SDimitry Andric return format_size; 21060b57cec5SDimitry Andric } 21070b57cec5SDimitry Andric 2108fe6060f1SDimitry Andric void KMP_EXPAND_NAME(ompc_display_affinity)(char const *format) { 21090b57cec5SDimitry Andric int gtid; 21100b57cec5SDimitry Andric if (!TCR_4(__kmp_init_middle)) { 21110b57cec5SDimitry Andric __kmp_middle_initialize(); 21120b57cec5SDimitry Andric } 2113fe6060f1SDimitry Andric __kmp_assign_root_init_mask(); 21140b57cec5SDimitry Andric gtid = __kmp_get_gtid(); 2115fcaf7f86SDimitry Andric #if KMP_AFFINITY_SUPPORTED 2116bdd1243dSDimitry Andric if (__kmp_threads[gtid]->th.th_team->t.t_level == 0 && 2117bdd1243dSDimitry Andric __kmp_affinity.flags.reset) { 2118fcaf7f86SDimitry Andric __kmp_reset_root_init_mask(gtid); 2119fcaf7f86SDimitry Andric } 2120fcaf7f86SDimitry Andric #endif 21210b57cec5SDimitry Andric __kmp_aux_display_affinity(gtid, format); 21220b57cec5SDimitry Andric } 21230b57cec5SDimitry Andric 2124fe6060f1SDimitry Andric size_t KMP_EXPAND_NAME(ompc_capture_affinity)(char *buffer, size_t buf_size, 21250b57cec5SDimitry Andric char const *format) { 21260b57cec5SDimitry Andric int gtid; 21270b57cec5SDimitry Andric size_t num_required; 21280b57cec5SDimitry Andric kmp_str_buf_t capture_buf; 21290b57cec5SDimitry Andric if (!TCR_4(__kmp_init_middle)) { 21300b57cec5SDimitry Andric __kmp_middle_initialize(); 21310b57cec5SDimitry Andric } 2132fe6060f1SDimitry Andric __kmp_assign_root_init_mask(); 21330b57cec5SDimitry Andric gtid = __kmp_get_gtid(); 2134fcaf7f86SDimitry Andric #if KMP_AFFINITY_SUPPORTED 2135bdd1243dSDimitry Andric if (__kmp_threads[gtid]->th.th_team->t.t_level == 0 && 2136bdd1243dSDimitry Andric __kmp_affinity.flags.reset) { 2137fcaf7f86SDimitry Andric __kmp_reset_root_init_mask(gtid); 2138fcaf7f86SDimitry Andric } 2139fcaf7f86SDimitry Andric #endif 21400b57cec5SDimitry Andric __kmp_str_buf_init(&capture_buf); 21410b57cec5SDimitry Andric num_required = __kmp_aux_capture_affinity(gtid, format, &capture_buf); 21420b57cec5SDimitry Andric if (buffer && buf_size) { 21430b57cec5SDimitry Andric __kmp_strncpy_truncate(buffer, buf_size, capture_buf.str, 21440b57cec5SDimitry Andric capture_buf.used + 1); 21450b57cec5SDimitry Andric } 21460b57cec5SDimitry Andric __kmp_str_buf_free(&capture_buf); 21470b57cec5SDimitry Andric return num_required; 21480b57cec5SDimitry Andric } 21490b57cec5SDimitry Andric 21500b57cec5SDimitry Andric void kmpc_set_stacksize(int arg) { 21510b57cec5SDimitry Andric // __kmp_aux_set_stacksize initializes the library if needed 21520b57cec5SDimitry Andric __kmp_aux_set_stacksize(arg); 21530b57cec5SDimitry Andric } 21540b57cec5SDimitry Andric 21550b57cec5SDimitry Andric void kmpc_set_stacksize_s(size_t arg) { 21560b57cec5SDimitry Andric // __kmp_aux_set_stacksize initializes the library if needed 21570b57cec5SDimitry Andric __kmp_aux_set_stacksize(arg); 21580b57cec5SDimitry Andric } 21590b57cec5SDimitry Andric 21600b57cec5SDimitry Andric void kmpc_set_blocktime(int arg) { 21615f757f3fSDimitry Andric int gtid, tid, bt = arg; 21620b57cec5SDimitry Andric kmp_info_t *thread; 21630b57cec5SDimitry Andric 21640b57cec5SDimitry Andric gtid = __kmp_entry_gtid(); 21650b57cec5SDimitry Andric tid = __kmp_tid_from_gtid(gtid); 21660b57cec5SDimitry Andric thread = __kmp_thread_from_gtid(gtid); 21670b57cec5SDimitry Andric 21685f757f3fSDimitry Andric __kmp_aux_convert_blocktime(&bt); 21695f757f3fSDimitry Andric __kmp_aux_set_blocktime(bt, thread, tid); 21700b57cec5SDimitry Andric } 21710b57cec5SDimitry Andric 21720b57cec5SDimitry Andric void kmpc_set_library(int arg) { 21730b57cec5SDimitry Andric // __kmp_user_set_library initializes the library if needed 21740b57cec5SDimitry Andric __kmp_user_set_library((enum library_type)arg); 21750b57cec5SDimitry Andric } 21760b57cec5SDimitry Andric 21770b57cec5SDimitry Andric void kmpc_set_defaults(char const *str) { 21780b57cec5SDimitry Andric // __kmp_aux_set_defaults initializes the library if needed 21790b57cec5SDimitry Andric __kmp_aux_set_defaults(str, KMP_STRLEN(str)); 21800b57cec5SDimitry Andric } 21810b57cec5SDimitry Andric 21820b57cec5SDimitry Andric void kmpc_set_disp_num_buffers(int arg) { 21830b57cec5SDimitry Andric // ignore after initialization because some teams have already 21840b57cec5SDimitry Andric // allocated dispatch buffers 2185fe6060f1SDimitry Andric if (__kmp_init_serial == FALSE && arg >= KMP_MIN_DISP_NUM_BUFF && 2186fe6060f1SDimitry Andric arg <= KMP_MAX_DISP_NUM_BUFF) { 21870b57cec5SDimitry Andric __kmp_dispatch_num_buffers = arg; 21880b57cec5SDimitry Andric } 2189fe6060f1SDimitry Andric } 21900b57cec5SDimitry Andric 21910b57cec5SDimitry Andric int kmpc_set_affinity_mask_proc(int proc, void **mask) { 21920b57cec5SDimitry Andric #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED 21930b57cec5SDimitry Andric return -1; 21940b57cec5SDimitry Andric #else 21950b57cec5SDimitry Andric if (!TCR_4(__kmp_init_middle)) { 21960b57cec5SDimitry Andric __kmp_middle_initialize(); 21970b57cec5SDimitry Andric } 2198fe6060f1SDimitry Andric __kmp_assign_root_init_mask(); 21990b57cec5SDimitry Andric return __kmp_aux_set_affinity_mask_proc(proc, mask); 22000b57cec5SDimitry Andric #endif 22010b57cec5SDimitry Andric } 22020b57cec5SDimitry Andric 22030b57cec5SDimitry Andric int kmpc_unset_affinity_mask_proc(int proc, void **mask) { 22040b57cec5SDimitry Andric #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED 22050b57cec5SDimitry Andric return -1; 22060b57cec5SDimitry Andric #else 22070b57cec5SDimitry Andric if (!TCR_4(__kmp_init_middle)) { 22080b57cec5SDimitry Andric __kmp_middle_initialize(); 22090b57cec5SDimitry Andric } 2210fe6060f1SDimitry Andric __kmp_assign_root_init_mask(); 22110b57cec5SDimitry Andric return __kmp_aux_unset_affinity_mask_proc(proc, mask); 22120b57cec5SDimitry Andric #endif 22130b57cec5SDimitry Andric } 22140b57cec5SDimitry Andric 22150b57cec5SDimitry Andric int kmpc_get_affinity_mask_proc(int proc, void **mask) { 22160b57cec5SDimitry Andric #if defined(KMP_STUB) || !KMP_AFFINITY_SUPPORTED 22170b57cec5SDimitry Andric return -1; 22180b57cec5SDimitry Andric #else 22190b57cec5SDimitry Andric if (!TCR_4(__kmp_init_middle)) { 22200b57cec5SDimitry Andric __kmp_middle_initialize(); 22210b57cec5SDimitry Andric } 2222fe6060f1SDimitry Andric __kmp_assign_root_init_mask(); 22230b57cec5SDimitry Andric return __kmp_aux_get_affinity_mask_proc(proc, mask); 22240b57cec5SDimitry Andric #endif 22250b57cec5SDimitry Andric } 22260b57cec5SDimitry Andric 22270b57cec5SDimitry Andric /* -------------------------------------------------------------------------- */ 22280b57cec5SDimitry Andric /*! 22290b57cec5SDimitry Andric @ingroup THREADPRIVATE 22300b57cec5SDimitry Andric @param loc source location information 22310b57cec5SDimitry Andric @param gtid global thread number 22320b57cec5SDimitry Andric @param cpy_size size of the cpy_data buffer 22330b57cec5SDimitry Andric @param cpy_data pointer to data to be copied 22340b57cec5SDimitry Andric @param cpy_func helper function to call for copying data 22350b57cec5SDimitry Andric @param didit flag variable: 1=single thread; 0=not single thread 22360b57cec5SDimitry Andric 22370b57cec5SDimitry Andric __kmpc_copyprivate implements the interface for the private data broadcast 22380b57cec5SDimitry Andric needed for the copyprivate clause associated with a single region in an 22390b57cec5SDimitry Andric OpenMP<sup>*</sup> program (both C and Fortran). 22400b57cec5SDimitry Andric All threads participating in the parallel region call this routine. 22410b57cec5SDimitry Andric One of the threads (called the single thread) should have the <tt>didit</tt> 22420b57cec5SDimitry Andric variable set to 1 and all other threads should have that variable set to 0. 22430b57cec5SDimitry Andric All threads pass a pointer to a data buffer (cpy_data) that they have built. 22440b57cec5SDimitry Andric 22450b57cec5SDimitry Andric The OpenMP specification forbids the use of nowait on the single region when a 22460b57cec5SDimitry Andric copyprivate clause is present. However, @ref __kmpc_copyprivate implements a 22470b57cec5SDimitry Andric barrier internally to avoid race conditions, so the code generation for the 22480b57cec5SDimitry Andric single region should avoid generating a barrier after the call to @ref 22490b57cec5SDimitry Andric __kmpc_copyprivate. 22500b57cec5SDimitry Andric 22510b57cec5SDimitry Andric The <tt>gtid</tt> parameter is the global thread id for the current thread. 22520b57cec5SDimitry Andric The <tt>loc</tt> parameter is a pointer to source location information. 22530b57cec5SDimitry Andric 22540b57cec5SDimitry Andric Internal implementation: The single thread will first copy its descriptor 22550b57cec5SDimitry Andric address (cpy_data) to a team-private location, then the other threads will each 22560b57cec5SDimitry Andric call the function pointed to by the parameter cpy_func, which carries out the 22570b57cec5SDimitry Andric copy by copying the data using the cpy_data buffer. 22580b57cec5SDimitry Andric 22590b57cec5SDimitry Andric The cpy_func routine used for the copy and the contents of the data area defined 22600b57cec5SDimitry Andric by cpy_data and cpy_size may be built in any fashion that will allow the copy 22610b57cec5SDimitry Andric to be done. For instance, the cpy_data buffer can hold the actual data to be 22620b57cec5SDimitry Andric copied or it may hold a list of pointers to the data. The cpy_func routine must 22630b57cec5SDimitry Andric interpret the cpy_data buffer appropriately. 22640b57cec5SDimitry Andric 22650b57cec5SDimitry Andric The interface to cpy_func is as follows: 22660b57cec5SDimitry Andric @code 22670b57cec5SDimitry Andric void cpy_func( void *destination, void *source ) 22680b57cec5SDimitry Andric @endcode 22690b57cec5SDimitry Andric where void *destination is the cpy_data pointer for the thread being copied to 22700b57cec5SDimitry Andric and void *source is the cpy_data pointer for the thread being copied from. 22710b57cec5SDimitry Andric */ 22720b57cec5SDimitry Andric void __kmpc_copyprivate(ident_t *loc, kmp_int32 gtid, size_t cpy_size, 22730b57cec5SDimitry Andric void *cpy_data, void (*cpy_func)(void *, void *), 22740b57cec5SDimitry Andric kmp_int32 didit) { 22750b57cec5SDimitry Andric void **data_ptr; 22760b57cec5SDimitry Andric KC_TRACE(10, ("__kmpc_copyprivate: called T#%d\n", gtid)); 2277e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(gtid); 22780b57cec5SDimitry Andric 22790b57cec5SDimitry Andric KMP_MB(); 22800b57cec5SDimitry Andric 22810b57cec5SDimitry Andric data_ptr = &__kmp_team_from_gtid(gtid)->t.t_copypriv_data; 22820b57cec5SDimitry Andric 22830b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 22840b57cec5SDimitry Andric if (loc == 0) { 22850b57cec5SDimitry Andric KMP_WARNING(ConstructIdentInvalid); 22860b57cec5SDimitry Andric } 22870b57cec5SDimitry Andric } 22880b57cec5SDimitry Andric 22890b57cec5SDimitry Andric // ToDo: Optimize the following two barriers into some kind of split barrier 22900b57cec5SDimitry Andric 22910b57cec5SDimitry Andric if (didit) 22920b57cec5SDimitry Andric *data_ptr = cpy_data; 22930b57cec5SDimitry Andric 22940b57cec5SDimitry Andric #if OMPT_SUPPORT 22950b57cec5SDimitry Andric ompt_frame_t *ompt_frame; 22960b57cec5SDimitry Andric if (ompt_enabled.enabled) { 22970b57cec5SDimitry Andric __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL); 22980b57cec5SDimitry Andric if (ompt_frame->enter_frame.ptr == NULL) 22990b57cec5SDimitry Andric ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0); 23000b57cec5SDimitry Andric } 2301e8d8bef9SDimitry Andric OMPT_STORE_RETURN_ADDRESS(gtid); 23020b57cec5SDimitry Andric #endif 23030b57cec5SDimitry Andric /* This barrier is not a barrier region boundary */ 23040b57cec5SDimitry Andric #if USE_ITT_NOTIFY 23050b57cec5SDimitry Andric __kmp_threads[gtid]->th.th_ident = loc; 23060b57cec5SDimitry Andric #endif 23070b57cec5SDimitry Andric __kmp_barrier(bs_plain_barrier, gtid, FALSE, 0, NULL, NULL); 23080b57cec5SDimitry Andric 23090b57cec5SDimitry Andric if (!didit) 23100b57cec5SDimitry Andric (*cpy_func)(cpy_data, *data_ptr); 23110b57cec5SDimitry Andric 23120b57cec5SDimitry Andric // Consider next barrier a user-visible barrier for barrier region boundaries 23130b57cec5SDimitry Andric // Nesting checks are already handled by the single construct checks 2314e8d8bef9SDimitry Andric { 23150b57cec5SDimitry Andric #if OMPT_SUPPORT 23160b57cec5SDimitry Andric OMPT_STORE_RETURN_ADDRESS(gtid); 23170b57cec5SDimitry Andric #endif 23180b57cec5SDimitry Andric #if USE_ITT_NOTIFY 23190b57cec5SDimitry Andric __kmp_threads[gtid]->th.th_ident = loc; // TODO: check if it is needed (e.g. 23200b57cec5SDimitry Andric // tasks can overwrite the location) 23210b57cec5SDimitry Andric #endif 23220b57cec5SDimitry Andric __kmp_barrier(bs_plain_barrier, gtid, FALSE, 0, NULL, NULL); 23230b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 23240b57cec5SDimitry Andric if (ompt_enabled.enabled) { 23250b57cec5SDimitry Andric ompt_frame->enter_frame = ompt_data_none; 23260b57cec5SDimitry Andric } 23270b57cec5SDimitry Andric #endif 23280b57cec5SDimitry Andric } 2329e8d8bef9SDimitry Andric } 23300b57cec5SDimitry Andric 23310b57cec5SDimitry Andric /* --------------------------------------------------------------------------*/ 2332753f127fSDimitry Andric /*! 2333753f127fSDimitry Andric @ingroup THREADPRIVATE 2334753f127fSDimitry Andric @param loc source location information 2335753f127fSDimitry Andric @param gtid global thread number 2336753f127fSDimitry Andric @param cpy_data pointer to the data to be saved/copied or 0 2337753f127fSDimitry Andric @return the saved pointer to the data 2338753f127fSDimitry Andric 2339753f127fSDimitry Andric __kmpc_copyprivate_light is a lighter version of __kmpc_copyprivate: 2340753f127fSDimitry Andric __kmpc_copyprivate_light only saves the pointer it's given (if it's not 0, so 2341753f127fSDimitry Andric coming from single), and returns that pointer in all calls (for single thread 2342753f127fSDimitry Andric it's not needed). This version doesn't do any actual data copying. Data copying 2343753f127fSDimitry Andric has to be done somewhere else, e.g. inline in the generated code. Due to this, 2344753f127fSDimitry Andric this function doesn't have any barrier at the end of the function, like 2345753f127fSDimitry Andric __kmpc_copyprivate does, so generated code needs barrier after copying of all 2346753f127fSDimitry Andric data was done. 2347753f127fSDimitry Andric */ 2348753f127fSDimitry Andric void *__kmpc_copyprivate_light(ident_t *loc, kmp_int32 gtid, void *cpy_data) { 2349753f127fSDimitry Andric void **data_ptr; 2350753f127fSDimitry Andric 2351753f127fSDimitry Andric KC_TRACE(10, ("__kmpc_copyprivate_light: called T#%d\n", gtid)); 2352753f127fSDimitry Andric 2353753f127fSDimitry Andric KMP_MB(); 2354753f127fSDimitry Andric 2355753f127fSDimitry Andric data_ptr = &__kmp_team_from_gtid(gtid)->t.t_copypriv_data; 2356753f127fSDimitry Andric 2357753f127fSDimitry Andric if (__kmp_env_consistency_check) { 2358753f127fSDimitry Andric if (loc == 0) { 2359753f127fSDimitry Andric KMP_WARNING(ConstructIdentInvalid); 2360753f127fSDimitry Andric } 2361753f127fSDimitry Andric } 2362753f127fSDimitry Andric 2363753f127fSDimitry Andric // ToDo: Optimize the following barrier 2364753f127fSDimitry Andric 2365753f127fSDimitry Andric if (cpy_data) 2366753f127fSDimitry Andric *data_ptr = cpy_data; 2367753f127fSDimitry Andric 2368753f127fSDimitry Andric #if OMPT_SUPPORT 2369753f127fSDimitry Andric ompt_frame_t *ompt_frame; 2370753f127fSDimitry Andric if (ompt_enabled.enabled) { 2371753f127fSDimitry Andric __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL); 2372753f127fSDimitry Andric if (ompt_frame->enter_frame.ptr == NULL) 2373753f127fSDimitry Andric ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0); 2374753f127fSDimitry Andric OMPT_STORE_RETURN_ADDRESS(gtid); 2375753f127fSDimitry Andric } 2376753f127fSDimitry Andric #endif 2377753f127fSDimitry Andric /* This barrier is not a barrier region boundary */ 2378753f127fSDimitry Andric #if USE_ITT_NOTIFY 2379753f127fSDimitry Andric __kmp_threads[gtid]->th.th_ident = loc; 2380753f127fSDimitry Andric #endif 2381753f127fSDimitry Andric __kmp_barrier(bs_plain_barrier, gtid, FALSE, 0, NULL, NULL); 2382753f127fSDimitry Andric 2383753f127fSDimitry Andric return *data_ptr; 2384753f127fSDimitry Andric } 2385753f127fSDimitry Andric 2386753f127fSDimitry Andric /* -------------------------------------------------------------------------- */ 23870b57cec5SDimitry Andric 23880b57cec5SDimitry Andric #define INIT_LOCK __kmp_init_user_lock_with_checks 23890b57cec5SDimitry Andric #define INIT_NESTED_LOCK __kmp_init_nested_user_lock_with_checks 23900b57cec5SDimitry Andric #define ACQUIRE_LOCK __kmp_acquire_user_lock_with_checks 23910b57cec5SDimitry Andric #define ACQUIRE_LOCK_TIMED __kmp_acquire_user_lock_with_checks_timed 23920b57cec5SDimitry Andric #define ACQUIRE_NESTED_LOCK __kmp_acquire_nested_user_lock_with_checks 23930b57cec5SDimitry Andric #define ACQUIRE_NESTED_LOCK_TIMED \ 23940b57cec5SDimitry Andric __kmp_acquire_nested_user_lock_with_checks_timed 23950b57cec5SDimitry Andric #define RELEASE_LOCK __kmp_release_user_lock_with_checks 23960b57cec5SDimitry Andric #define RELEASE_NESTED_LOCK __kmp_release_nested_user_lock_with_checks 23970b57cec5SDimitry Andric #define TEST_LOCK __kmp_test_user_lock_with_checks 23980b57cec5SDimitry Andric #define TEST_NESTED_LOCK __kmp_test_nested_user_lock_with_checks 23990b57cec5SDimitry Andric #define DESTROY_LOCK __kmp_destroy_user_lock_with_checks 24000b57cec5SDimitry Andric #define DESTROY_NESTED_LOCK __kmp_destroy_nested_user_lock_with_checks 24010b57cec5SDimitry Andric 24020b57cec5SDimitry Andric // TODO: Make check abort messages use location info & pass it into 24030b57cec5SDimitry Andric // with_checks routines 24040b57cec5SDimitry Andric 24050b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 24060b57cec5SDimitry Andric 24070b57cec5SDimitry Andric // internal lock initializer 24080b57cec5SDimitry Andric static __forceinline void __kmp_init_lock_with_hint(ident_t *loc, void **lock, 24090b57cec5SDimitry Andric kmp_dyna_lockseq_t seq) { 24100b57cec5SDimitry Andric if (KMP_IS_D_LOCK(seq)) { 24110b57cec5SDimitry Andric KMP_INIT_D_LOCK(lock, seq); 24120b57cec5SDimitry Andric #if USE_ITT_BUILD 24130b57cec5SDimitry Andric __kmp_itt_lock_creating((kmp_user_lock_p)lock, NULL); 24140b57cec5SDimitry Andric #endif 24150b57cec5SDimitry Andric } else { 24160b57cec5SDimitry Andric KMP_INIT_I_LOCK(lock, seq); 24170b57cec5SDimitry Andric #if USE_ITT_BUILD 24180b57cec5SDimitry Andric kmp_indirect_lock_t *ilk = KMP_LOOKUP_I_LOCK(lock); 24190b57cec5SDimitry Andric __kmp_itt_lock_creating(ilk->lock, loc); 24200b57cec5SDimitry Andric #endif 24210b57cec5SDimitry Andric } 24220b57cec5SDimitry Andric } 24230b57cec5SDimitry Andric 24240b57cec5SDimitry Andric // internal nest lock initializer 24250b57cec5SDimitry Andric static __forceinline void 24260b57cec5SDimitry Andric __kmp_init_nest_lock_with_hint(ident_t *loc, void **lock, 24270b57cec5SDimitry Andric kmp_dyna_lockseq_t seq) { 24280b57cec5SDimitry Andric #if KMP_USE_TSX 24290b57cec5SDimitry Andric // Don't have nested lock implementation for speculative locks 2430e8d8bef9SDimitry Andric if (seq == lockseq_hle || seq == lockseq_rtm_queuing || 2431e8d8bef9SDimitry Andric seq == lockseq_rtm_spin || seq == lockseq_adaptive) 24320b57cec5SDimitry Andric seq = __kmp_user_lock_seq; 24330b57cec5SDimitry Andric #endif 24340b57cec5SDimitry Andric switch (seq) { 24350b57cec5SDimitry Andric case lockseq_tas: 24360b57cec5SDimitry Andric seq = lockseq_nested_tas; 24370b57cec5SDimitry Andric break; 24380b57cec5SDimitry Andric #if KMP_USE_FUTEX 24390b57cec5SDimitry Andric case lockseq_futex: 24400b57cec5SDimitry Andric seq = lockseq_nested_futex; 24410b57cec5SDimitry Andric break; 24420b57cec5SDimitry Andric #endif 24430b57cec5SDimitry Andric case lockseq_ticket: 24440b57cec5SDimitry Andric seq = lockseq_nested_ticket; 24450b57cec5SDimitry Andric break; 24460b57cec5SDimitry Andric case lockseq_queuing: 24470b57cec5SDimitry Andric seq = lockseq_nested_queuing; 24480b57cec5SDimitry Andric break; 24490b57cec5SDimitry Andric case lockseq_drdpa: 24500b57cec5SDimitry Andric seq = lockseq_nested_drdpa; 24510b57cec5SDimitry Andric break; 24520b57cec5SDimitry Andric default: 24530b57cec5SDimitry Andric seq = lockseq_nested_queuing; 24540b57cec5SDimitry Andric } 24550b57cec5SDimitry Andric KMP_INIT_I_LOCK(lock, seq); 24560b57cec5SDimitry Andric #if USE_ITT_BUILD 24570b57cec5SDimitry Andric kmp_indirect_lock_t *ilk = KMP_LOOKUP_I_LOCK(lock); 24580b57cec5SDimitry Andric __kmp_itt_lock_creating(ilk->lock, loc); 24590b57cec5SDimitry Andric #endif 24600b57cec5SDimitry Andric } 24610b57cec5SDimitry Andric 24620b57cec5SDimitry Andric /* initialize the lock with a hint */ 24630b57cec5SDimitry Andric void __kmpc_init_lock_with_hint(ident_t *loc, kmp_int32 gtid, void **user_lock, 24640b57cec5SDimitry Andric uintptr_t hint) { 24650b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); 24660b57cec5SDimitry Andric if (__kmp_env_consistency_check && user_lock == NULL) { 24670b57cec5SDimitry Andric KMP_FATAL(LockIsUninitialized, "omp_init_lock_with_hint"); 24680b57cec5SDimitry Andric } 24690b57cec5SDimitry Andric 24700b57cec5SDimitry Andric __kmp_init_lock_with_hint(loc, user_lock, __kmp_map_hint_to_lock(hint)); 24710b57cec5SDimitry Andric 24720b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 24730b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 24740b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 24750b57cec5SDimitry Andric if (!codeptr) 24760b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 24770b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_lock_init) { 24780b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_lock_init)( 24790b57cec5SDimitry Andric ompt_mutex_lock, (omp_lock_hint_t)hint, 24800b57cec5SDimitry Andric __ompt_get_mutex_impl_type(user_lock), 24810b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 24820b57cec5SDimitry Andric } 24830b57cec5SDimitry Andric #endif 24840b57cec5SDimitry Andric } 24850b57cec5SDimitry Andric 24860b57cec5SDimitry Andric /* initialize the lock with a hint */ 24870b57cec5SDimitry Andric void __kmpc_init_nest_lock_with_hint(ident_t *loc, kmp_int32 gtid, 24880b57cec5SDimitry Andric void **user_lock, uintptr_t hint) { 24890b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); 24900b57cec5SDimitry Andric if (__kmp_env_consistency_check && user_lock == NULL) { 24910b57cec5SDimitry Andric KMP_FATAL(LockIsUninitialized, "omp_init_nest_lock_with_hint"); 24920b57cec5SDimitry Andric } 24930b57cec5SDimitry Andric 24940b57cec5SDimitry Andric __kmp_init_nest_lock_with_hint(loc, user_lock, __kmp_map_hint_to_lock(hint)); 24950b57cec5SDimitry Andric 24960b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 24970b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 24980b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 24990b57cec5SDimitry Andric if (!codeptr) 25000b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 25010b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_lock_init) { 25020b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_lock_init)( 25030b57cec5SDimitry Andric ompt_mutex_nest_lock, (omp_lock_hint_t)hint, 25040b57cec5SDimitry Andric __ompt_get_mutex_impl_type(user_lock), 25050b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 25060b57cec5SDimitry Andric } 25070b57cec5SDimitry Andric #endif 25080b57cec5SDimitry Andric } 25090b57cec5SDimitry Andric 25100b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 25110b57cec5SDimitry Andric 25120b57cec5SDimitry Andric /* initialize the lock */ 25130b57cec5SDimitry Andric void __kmpc_init_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { 25140b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 25150b57cec5SDimitry Andric 25160b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); 25170b57cec5SDimitry Andric if (__kmp_env_consistency_check && user_lock == NULL) { 25180b57cec5SDimitry Andric KMP_FATAL(LockIsUninitialized, "omp_init_lock"); 25190b57cec5SDimitry Andric } 25200b57cec5SDimitry Andric __kmp_init_lock_with_hint(loc, user_lock, __kmp_user_lock_seq); 25210b57cec5SDimitry Andric 25220b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 25230b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 25240b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 25250b57cec5SDimitry Andric if (!codeptr) 25260b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 25270b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_lock_init) { 25280b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_lock_init)( 25290b57cec5SDimitry Andric ompt_mutex_lock, omp_lock_hint_none, 25300b57cec5SDimitry Andric __ompt_get_mutex_impl_type(user_lock), 25310b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 25320b57cec5SDimitry Andric } 25330b57cec5SDimitry Andric #endif 25340b57cec5SDimitry Andric 25350b57cec5SDimitry Andric #else // KMP_USE_DYNAMIC_LOCK 25360b57cec5SDimitry Andric 25370b57cec5SDimitry Andric static char const *const func = "omp_init_lock"; 25380b57cec5SDimitry Andric kmp_user_lock_p lck; 25390b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); 25400b57cec5SDimitry Andric 25410b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 25420b57cec5SDimitry Andric if (user_lock == NULL) { 25430b57cec5SDimitry Andric KMP_FATAL(LockIsUninitialized, func); 25440b57cec5SDimitry Andric } 25450b57cec5SDimitry Andric } 25460b57cec5SDimitry Andric 25470b57cec5SDimitry Andric KMP_CHECK_USER_LOCK_INIT(); 25480b57cec5SDimitry Andric 25490b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 25500b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) <= OMP_LOCK_T_SIZE)) { 25510b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 25520b57cec5SDimitry Andric } 25530b57cec5SDimitry Andric #if KMP_USE_FUTEX 25540b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 25550b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) <= OMP_LOCK_T_SIZE)) { 25560b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 25570b57cec5SDimitry Andric } 25580b57cec5SDimitry Andric #endif 25590b57cec5SDimitry Andric else { 25600b57cec5SDimitry Andric lck = __kmp_user_lock_allocate(user_lock, gtid, 0); 25610b57cec5SDimitry Andric } 25620b57cec5SDimitry Andric INIT_LOCK(lck); 25630b57cec5SDimitry Andric __kmp_set_user_lock_location(lck, loc); 25640b57cec5SDimitry Andric 25650b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 25660b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 25670b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 25680b57cec5SDimitry Andric if (!codeptr) 25690b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 25700b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_lock_init) { 25710b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_lock_init)( 25720b57cec5SDimitry Andric ompt_mutex_lock, omp_lock_hint_none, __ompt_get_mutex_impl_type(), 25730b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 25740b57cec5SDimitry Andric } 25750b57cec5SDimitry Andric #endif 25760b57cec5SDimitry Andric 25770b57cec5SDimitry Andric #if USE_ITT_BUILD 25780b57cec5SDimitry Andric __kmp_itt_lock_creating(lck); 25790b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 25800b57cec5SDimitry Andric 25810b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 25820b57cec5SDimitry Andric } // __kmpc_init_lock 25830b57cec5SDimitry Andric 25840b57cec5SDimitry Andric /* initialize the lock */ 25850b57cec5SDimitry Andric void __kmpc_init_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { 25860b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 25870b57cec5SDimitry Andric 25880b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); 25890b57cec5SDimitry Andric if (__kmp_env_consistency_check && user_lock == NULL) { 25900b57cec5SDimitry Andric KMP_FATAL(LockIsUninitialized, "omp_init_nest_lock"); 25910b57cec5SDimitry Andric } 25920b57cec5SDimitry Andric __kmp_init_nest_lock_with_hint(loc, user_lock, __kmp_user_lock_seq); 25930b57cec5SDimitry Andric 25940b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 25950b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 25960b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 25970b57cec5SDimitry Andric if (!codeptr) 25980b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 25990b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_lock_init) { 26000b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_lock_init)( 26010b57cec5SDimitry Andric ompt_mutex_nest_lock, omp_lock_hint_none, 26020b57cec5SDimitry Andric __ompt_get_mutex_impl_type(user_lock), 26030b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 26040b57cec5SDimitry Andric } 26050b57cec5SDimitry Andric #endif 26060b57cec5SDimitry Andric 26070b57cec5SDimitry Andric #else // KMP_USE_DYNAMIC_LOCK 26080b57cec5SDimitry Andric 26090b57cec5SDimitry Andric static char const *const func = "omp_init_nest_lock"; 26100b57cec5SDimitry Andric kmp_user_lock_p lck; 26110b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); 26120b57cec5SDimitry Andric 26130b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 26140b57cec5SDimitry Andric if (user_lock == NULL) { 26150b57cec5SDimitry Andric KMP_FATAL(LockIsUninitialized, func); 26160b57cec5SDimitry Andric } 26170b57cec5SDimitry Andric } 26180b57cec5SDimitry Andric 26190b57cec5SDimitry Andric KMP_CHECK_USER_LOCK_INIT(); 26200b57cec5SDimitry Andric 26210b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 26220b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) + sizeof(lck->tas.lk.depth_locked) <= 26230b57cec5SDimitry Andric OMP_NEST_LOCK_T_SIZE)) { 26240b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 26250b57cec5SDimitry Andric } 26260b57cec5SDimitry Andric #if KMP_USE_FUTEX 26270b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 26280b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) + sizeof(lck->futex.lk.depth_locked) <= 26290b57cec5SDimitry Andric OMP_NEST_LOCK_T_SIZE)) { 26300b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 26310b57cec5SDimitry Andric } 26320b57cec5SDimitry Andric #endif 26330b57cec5SDimitry Andric else { 26340b57cec5SDimitry Andric lck = __kmp_user_lock_allocate(user_lock, gtid, 0); 26350b57cec5SDimitry Andric } 26360b57cec5SDimitry Andric 26370b57cec5SDimitry Andric INIT_NESTED_LOCK(lck); 26380b57cec5SDimitry Andric __kmp_set_user_lock_location(lck, loc); 26390b57cec5SDimitry Andric 26400b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 26410b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 26420b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 26430b57cec5SDimitry Andric if (!codeptr) 26440b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 26450b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_lock_init) { 26460b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_lock_init)( 26470b57cec5SDimitry Andric ompt_mutex_nest_lock, omp_lock_hint_none, __ompt_get_mutex_impl_type(), 26480b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 26490b57cec5SDimitry Andric } 26500b57cec5SDimitry Andric #endif 26510b57cec5SDimitry Andric 26520b57cec5SDimitry Andric #if USE_ITT_BUILD 26530b57cec5SDimitry Andric __kmp_itt_lock_creating(lck); 26540b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 26550b57cec5SDimitry Andric 26560b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 26570b57cec5SDimitry Andric } // __kmpc_init_nest_lock 26580b57cec5SDimitry Andric 26590b57cec5SDimitry Andric void __kmpc_destroy_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { 26600b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 26610b57cec5SDimitry Andric 26620b57cec5SDimitry Andric #if USE_ITT_BUILD 26630b57cec5SDimitry Andric kmp_user_lock_p lck; 26640b57cec5SDimitry Andric if (KMP_EXTRACT_D_TAG(user_lock) == 0) { 26650b57cec5SDimitry Andric lck = ((kmp_indirect_lock_t *)KMP_LOOKUP_I_LOCK(user_lock))->lock; 26660b57cec5SDimitry Andric } else { 26670b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 26680b57cec5SDimitry Andric } 26690b57cec5SDimitry Andric __kmp_itt_lock_destroyed(lck); 26700b57cec5SDimitry Andric #endif 26710b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 26720b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 26730b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 26740b57cec5SDimitry Andric if (!codeptr) 26750b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 26760b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_lock_destroy) { 26770b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_lock_destroy)( 26780b57cec5SDimitry Andric ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 26790b57cec5SDimitry Andric } 26800b57cec5SDimitry Andric #endif 26810b57cec5SDimitry Andric KMP_D_LOCK_FUNC(user_lock, destroy)((kmp_dyna_lock_t *)user_lock); 26820b57cec5SDimitry Andric #else 26830b57cec5SDimitry Andric kmp_user_lock_p lck; 26840b57cec5SDimitry Andric 26850b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 26860b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) <= OMP_LOCK_T_SIZE)) { 26870b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 26880b57cec5SDimitry Andric } 26890b57cec5SDimitry Andric #if KMP_USE_FUTEX 26900b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 26910b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) <= OMP_LOCK_T_SIZE)) { 26920b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 26930b57cec5SDimitry Andric } 26940b57cec5SDimitry Andric #endif 26950b57cec5SDimitry Andric else { 26960b57cec5SDimitry Andric lck = __kmp_lookup_user_lock(user_lock, "omp_destroy_lock"); 26970b57cec5SDimitry Andric } 26980b57cec5SDimitry Andric 26990b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 27000b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 27010b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 27020b57cec5SDimitry Andric if (!codeptr) 27030b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 27040b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_lock_destroy) { 27050b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_lock_destroy)( 27060b57cec5SDimitry Andric ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 27070b57cec5SDimitry Andric } 27080b57cec5SDimitry Andric #endif 27090b57cec5SDimitry Andric 27100b57cec5SDimitry Andric #if USE_ITT_BUILD 27110b57cec5SDimitry Andric __kmp_itt_lock_destroyed(lck); 27120b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 27130b57cec5SDimitry Andric DESTROY_LOCK(lck); 27140b57cec5SDimitry Andric 27150b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 27160b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) <= OMP_LOCK_T_SIZE)) { 27170b57cec5SDimitry Andric ; 27180b57cec5SDimitry Andric } 27190b57cec5SDimitry Andric #if KMP_USE_FUTEX 27200b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 27210b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) <= OMP_LOCK_T_SIZE)) { 27220b57cec5SDimitry Andric ; 27230b57cec5SDimitry Andric } 27240b57cec5SDimitry Andric #endif 27250b57cec5SDimitry Andric else { 27260b57cec5SDimitry Andric __kmp_user_lock_free(user_lock, gtid, lck); 27270b57cec5SDimitry Andric } 27280b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 27290b57cec5SDimitry Andric } // __kmpc_destroy_lock 27300b57cec5SDimitry Andric 27310b57cec5SDimitry Andric /* destroy the lock */ 27320b57cec5SDimitry Andric void __kmpc_destroy_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { 27330b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 27340b57cec5SDimitry Andric 27350b57cec5SDimitry Andric #if USE_ITT_BUILD 27360b57cec5SDimitry Andric kmp_indirect_lock_t *ilk = KMP_LOOKUP_I_LOCK(user_lock); 27370b57cec5SDimitry Andric __kmp_itt_lock_destroyed(ilk->lock); 27380b57cec5SDimitry Andric #endif 27390b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 27400b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 27410b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 27420b57cec5SDimitry Andric if (!codeptr) 27430b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 27440b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_lock_destroy) { 27450b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_lock_destroy)( 27460b57cec5SDimitry Andric ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 27470b57cec5SDimitry Andric } 27480b57cec5SDimitry Andric #endif 27490b57cec5SDimitry Andric KMP_D_LOCK_FUNC(user_lock, destroy)((kmp_dyna_lock_t *)user_lock); 27500b57cec5SDimitry Andric 27510b57cec5SDimitry Andric #else // KMP_USE_DYNAMIC_LOCK 27520b57cec5SDimitry Andric 27530b57cec5SDimitry Andric kmp_user_lock_p lck; 27540b57cec5SDimitry Andric 27550b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 27560b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) + sizeof(lck->tas.lk.depth_locked) <= 27570b57cec5SDimitry Andric OMP_NEST_LOCK_T_SIZE)) { 27580b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 27590b57cec5SDimitry Andric } 27600b57cec5SDimitry Andric #if KMP_USE_FUTEX 27610b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 27620b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) + sizeof(lck->futex.lk.depth_locked) <= 27630b57cec5SDimitry Andric OMP_NEST_LOCK_T_SIZE)) { 27640b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 27650b57cec5SDimitry Andric } 27660b57cec5SDimitry Andric #endif 27670b57cec5SDimitry Andric else { 27680b57cec5SDimitry Andric lck = __kmp_lookup_user_lock(user_lock, "omp_destroy_nest_lock"); 27690b57cec5SDimitry Andric } 27700b57cec5SDimitry Andric 27710b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 27720b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 27730b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 27740b57cec5SDimitry Andric if (!codeptr) 27750b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 27760b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_lock_destroy) { 27770b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_lock_destroy)( 27780b57cec5SDimitry Andric ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 27790b57cec5SDimitry Andric } 27800b57cec5SDimitry Andric #endif 27810b57cec5SDimitry Andric 27820b57cec5SDimitry Andric #if USE_ITT_BUILD 27830b57cec5SDimitry Andric __kmp_itt_lock_destroyed(lck); 27840b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 27850b57cec5SDimitry Andric 27860b57cec5SDimitry Andric DESTROY_NESTED_LOCK(lck); 27870b57cec5SDimitry Andric 27880b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 27890b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) + sizeof(lck->tas.lk.depth_locked) <= 27900b57cec5SDimitry Andric OMP_NEST_LOCK_T_SIZE)) { 27910b57cec5SDimitry Andric ; 27920b57cec5SDimitry Andric } 27930b57cec5SDimitry Andric #if KMP_USE_FUTEX 27940b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 27950b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) + sizeof(lck->futex.lk.depth_locked) <= 27960b57cec5SDimitry Andric OMP_NEST_LOCK_T_SIZE)) { 27970b57cec5SDimitry Andric ; 27980b57cec5SDimitry Andric } 27990b57cec5SDimitry Andric #endif 28000b57cec5SDimitry Andric else { 28010b57cec5SDimitry Andric __kmp_user_lock_free(user_lock, gtid, lck); 28020b57cec5SDimitry Andric } 28030b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 28040b57cec5SDimitry Andric } // __kmpc_destroy_nest_lock 28050b57cec5SDimitry Andric 28060b57cec5SDimitry Andric void __kmpc_set_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { 28070b57cec5SDimitry Andric KMP_COUNT_BLOCK(OMP_set_lock); 28080b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 28090b57cec5SDimitry Andric int tag = KMP_EXTRACT_D_TAG(user_lock); 28100b57cec5SDimitry Andric #if USE_ITT_BUILD 28110b57cec5SDimitry Andric __kmp_itt_lock_acquiring( 28120b57cec5SDimitry Andric (kmp_user_lock_p) 28130b57cec5SDimitry Andric user_lock); // itt function will get to the right lock object. 28140b57cec5SDimitry Andric #endif 28150b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 28160b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 28170b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 28180b57cec5SDimitry Andric if (!codeptr) 28190b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 28200b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquire) { 28210b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( 28220b57cec5SDimitry Andric ompt_mutex_lock, omp_lock_hint_none, 28230b57cec5SDimitry Andric __ompt_get_mutex_impl_type(user_lock), 28240b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 28250b57cec5SDimitry Andric } 28260b57cec5SDimitry Andric #endif 28270b57cec5SDimitry Andric #if KMP_USE_INLINED_TAS 28280b57cec5SDimitry Andric if (tag == locktag_tas && !__kmp_env_consistency_check) { 28290b57cec5SDimitry Andric KMP_ACQUIRE_TAS_LOCK(user_lock, gtid); 28300b57cec5SDimitry Andric } else 28310b57cec5SDimitry Andric #elif KMP_USE_INLINED_FUTEX 28320b57cec5SDimitry Andric if (tag == locktag_futex && !__kmp_env_consistency_check) { 28330b57cec5SDimitry Andric KMP_ACQUIRE_FUTEX_LOCK(user_lock, gtid); 28340b57cec5SDimitry Andric } else 28350b57cec5SDimitry Andric #endif 28360b57cec5SDimitry Andric { 28370b57cec5SDimitry Andric __kmp_direct_set[tag]((kmp_dyna_lock_t *)user_lock, gtid); 28380b57cec5SDimitry Andric } 28390b57cec5SDimitry Andric #if USE_ITT_BUILD 28400b57cec5SDimitry Andric __kmp_itt_lock_acquired((kmp_user_lock_p)user_lock); 28410b57cec5SDimitry Andric #endif 28420b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 28430b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquired) { 28440b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( 28450b57cec5SDimitry Andric ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 28460b57cec5SDimitry Andric } 28470b57cec5SDimitry Andric #endif 28480b57cec5SDimitry Andric 28490b57cec5SDimitry Andric #else // KMP_USE_DYNAMIC_LOCK 28500b57cec5SDimitry Andric 28510b57cec5SDimitry Andric kmp_user_lock_p lck; 28520b57cec5SDimitry Andric 28530b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 28540b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) <= OMP_LOCK_T_SIZE)) { 28550b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 28560b57cec5SDimitry Andric } 28570b57cec5SDimitry Andric #if KMP_USE_FUTEX 28580b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 28590b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) <= OMP_LOCK_T_SIZE)) { 28600b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 28610b57cec5SDimitry Andric } 28620b57cec5SDimitry Andric #endif 28630b57cec5SDimitry Andric else { 28640b57cec5SDimitry Andric lck = __kmp_lookup_user_lock(user_lock, "omp_set_lock"); 28650b57cec5SDimitry Andric } 28660b57cec5SDimitry Andric 28670b57cec5SDimitry Andric #if USE_ITT_BUILD 28680b57cec5SDimitry Andric __kmp_itt_lock_acquiring(lck); 28690b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 28700b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 28710b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 28720b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 28730b57cec5SDimitry Andric if (!codeptr) 28740b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 28750b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquire) { 28760b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( 28770b57cec5SDimitry Andric ompt_mutex_lock, omp_lock_hint_none, __ompt_get_mutex_impl_type(), 28780b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)lck, codeptr); 28790b57cec5SDimitry Andric } 28800b57cec5SDimitry Andric #endif 28810b57cec5SDimitry Andric 28820b57cec5SDimitry Andric ACQUIRE_LOCK(lck, gtid); 28830b57cec5SDimitry Andric 28840b57cec5SDimitry Andric #if USE_ITT_BUILD 28850b57cec5SDimitry Andric __kmp_itt_lock_acquired(lck); 28860b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 28870b57cec5SDimitry Andric 28880b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 28890b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquired) { 28900b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( 28910b57cec5SDimitry Andric ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); 28920b57cec5SDimitry Andric } 28930b57cec5SDimitry Andric #endif 28940b57cec5SDimitry Andric 28950b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 28960b57cec5SDimitry Andric } 28970b57cec5SDimitry Andric 28980b57cec5SDimitry Andric void __kmpc_set_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { 28990b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 29000b57cec5SDimitry Andric 29010b57cec5SDimitry Andric #if USE_ITT_BUILD 29020b57cec5SDimitry Andric __kmp_itt_lock_acquiring((kmp_user_lock_p)user_lock); 29030b57cec5SDimitry Andric #endif 29040b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 29050b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 29060b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 29070b57cec5SDimitry Andric if (!codeptr) 29080b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 29090b57cec5SDimitry Andric if (ompt_enabled.enabled) { 29100b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquire) { 29110b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( 29120b57cec5SDimitry Andric ompt_mutex_nest_lock, omp_lock_hint_none, 29130b57cec5SDimitry Andric __ompt_get_mutex_impl_type(user_lock), 29140b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 29150b57cec5SDimitry Andric } 29160b57cec5SDimitry Andric } 29170b57cec5SDimitry Andric #endif 29180b57cec5SDimitry Andric int acquire_status = 29190b57cec5SDimitry Andric KMP_D_LOCK_FUNC(user_lock, set)((kmp_dyna_lock_t *)user_lock, gtid); 29200b57cec5SDimitry Andric (void)acquire_status; 29210b57cec5SDimitry Andric #if USE_ITT_BUILD 29220b57cec5SDimitry Andric __kmp_itt_lock_acquired((kmp_user_lock_p)user_lock); 29230b57cec5SDimitry Andric #endif 29240b57cec5SDimitry Andric 29250b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 29260b57cec5SDimitry Andric if (ompt_enabled.enabled) { 29270b57cec5SDimitry Andric if (acquire_status == KMP_LOCK_ACQUIRED_FIRST) { 29280b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquired) { 29290b57cec5SDimitry Andric // lock_first 29300b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( 29310b57cec5SDimitry Andric ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock, 29320b57cec5SDimitry Andric codeptr); 29330b57cec5SDimitry Andric } 29340b57cec5SDimitry Andric } else { 29350b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_nest_lock) { 29360b57cec5SDimitry Andric // lock_next 29370b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( 29380b57cec5SDimitry Andric ompt_scope_begin, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 29390b57cec5SDimitry Andric } 29400b57cec5SDimitry Andric } 29410b57cec5SDimitry Andric } 29420b57cec5SDimitry Andric #endif 29430b57cec5SDimitry Andric 29440b57cec5SDimitry Andric #else // KMP_USE_DYNAMIC_LOCK 29450b57cec5SDimitry Andric int acquire_status; 29460b57cec5SDimitry Andric kmp_user_lock_p lck; 29470b57cec5SDimitry Andric 29480b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 29490b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) + sizeof(lck->tas.lk.depth_locked) <= 29500b57cec5SDimitry Andric OMP_NEST_LOCK_T_SIZE)) { 29510b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 29520b57cec5SDimitry Andric } 29530b57cec5SDimitry Andric #if KMP_USE_FUTEX 29540b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 29550b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) + sizeof(lck->futex.lk.depth_locked) <= 29560b57cec5SDimitry Andric OMP_NEST_LOCK_T_SIZE)) { 29570b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 29580b57cec5SDimitry Andric } 29590b57cec5SDimitry Andric #endif 29600b57cec5SDimitry Andric else { 29610b57cec5SDimitry Andric lck = __kmp_lookup_user_lock(user_lock, "omp_set_nest_lock"); 29620b57cec5SDimitry Andric } 29630b57cec5SDimitry Andric 29640b57cec5SDimitry Andric #if USE_ITT_BUILD 29650b57cec5SDimitry Andric __kmp_itt_lock_acquiring(lck); 29660b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 29670b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 29680b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 29690b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 29700b57cec5SDimitry Andric if (!codeptr) 29710b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 29720b57cec5SDimitry Andric if (ompt_enabled.enabled) { 29730b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquire) { 29740b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( 29750b57cec5SDimitry Andric ompt_mutex_nest_lock, omp_lock_hint_none, 29760b57cec5SDimitry Andric __ompt_get_mutex_impl_type(), (ompt_wait_id_t)(uintptr_t)lck, 29770b57cec5SDimitry Andric codeptr); 29780b57cec5SDimitry Andric } 29790b57cec5SDimitry Andric } 29800b57cec5SDimitry Andric #endif 29810b57cec5SDimitry Andric 29820b57cec5SDimitry Andric ACQUIRE_NESTED_LOCK(lck, gtid, &acquire_status); 29830b57cec5SDimitry Andric 29840b57cec5SDimitry Andric #if USE_ITT_BUILD 29850b57cec5SDimitry Andric __kmp_itt_lock_acquired(lck); 29860b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 29870b57cec5SDimitry Andric 29880b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 29890b57cec5SDimitry Andric if (ompt_enabled.enabled) { 29900b57cec5SDimitry Andric if (acquire_status == KMP_LOCK_ACQUIRED_FIRST) { 29910b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquired) { 29920b57cec5SDimitry Andric // lock_first 29930b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( 29940b57cec5SDimitry Andric ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); 29950b57cec5SDimitry Andric } 29960b57cec5SDimitry Andric } else { 29970b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_nest_lock) { 29980b57cec5SDimitry Andric // lock_next 29990b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( 30000b57cec5SDimitry Andric ompt_scope_begin, (ompt_wait_id_t)(uintptr_t)lck, codeptr); 30010b57cec5SDimitry Andric } 30020b57cec5SDimitry Andric } 30030b57cec5SDimitry Andric } 30040b57cec5SDimitry Andric #endif 30050b57cec5SDimitry Andric 30060b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 30070b57cec5SDimitry Andric } 30080b57cec5SDimitry Andric 30090b57cec5SDimitry Andric void __kmpc_unset_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { 30100b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 30110b57cec5SDimitry Andric 30120b57cec5SDimitry Andric int tag = KMP_EXTRACT_D_TAG(user_lock); 30130b57cec5SDimitry Andric #if USE_ITT_BUILD 30140b57cec5SDimitry Andric __kmp_itt_lock_releasing((kmp_user_lock_p)user_lock); 30150b57cec5SDimitry Andric #endif 30160b57cec5SDimitry Andric #if KMP_USE_INLINED_TAS 30170b57cec5SDimitry Andric if (tag == locktag_tas && !__kmp_env_consistency_check) { 30180b57cec5SDimitry Andric KMP_RELEASE_TAS_LOCK(user_lock, gtid); 30190b57cec5SDimitry Andric } else 30200b57cec5SDimitry Andric #elif KMP_USE_INLINED_FUTEX 30210b57cec5SDimitry Andric if (tag == locktag_futex && !__kmp_env_consistency_check) { 30220b57cec5SDimitry Andric KMP_RELEASE_FUTEX_LOCK(user_lock, gtid); 30230b57cec5SDimitry Andric } else 30240b57cec5SDimitry Andric #endif 30250b57cec5SDimitry Andric { 30260b57cec5SDimitry Andric __kmp_direct_unset[tag]((kmp_dyna_lock_t *)user_lock, gtid); 30270b57cec5SDimitry Andric } 30280b57cec5SDimitry Andric 30290b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 30300b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 30310b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 30320b57cec5SDimitry Andric if (!codeptr) 30330b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 30340b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_released) { 30350b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( 30360b57cec5SDimitry Andric ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 30370b57cec5SDimitry Andric } 30380b57cec5SDimitry Andric #endif 30390b57cec5SDimitry Andric 30400b57cec5SDimitry Andric #else // KMP_USE_DYNAMIC_LOCK 30410b57cec5SDimitry Andric 30420b57cec5SDimitry Andric kmp_user_lock_p lck; 30430b57cec5SDimitry Andric 30440b57cec5SDimitry Andric /* Can't use serial interval since not block structured */ 30450b57cec5SDimitry Andric /* release the lock */ 30460b57cec5SDimitry Andric 30470b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 30480b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) <= OMP_LOCK_T_SIZE)) { 30490b57cec5SDimitry Andric #if KMP_OS_LINUX && \ 30500b57cec5SDimitry Andric (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_ARM || KMP_ARCH_AARCH64) 30510b57cec5SDimitry Andric // "fast" path implemented to fix customer performance issue 30520b57cec5SDimitry Andric #if USE_ITT_BUILD 30530b57cec5SDimitry Andric __kmp_itt_lock_releasing((kmp_user_lock_p)user_lock); 30540b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 30550b57cec5SDimitry Andric TCW_4(((kmp_user_lock_p)user_lock)->tas.lk.poll, 0); 30560b57cec5SDimitry Andric KMP_MB(); 30570b57cec5SDimitry Andric 30580b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 30590b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 30600b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 30610b57cec5SDimitry Andric if (!codeptr) 30620b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 30630b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_released) { 30640b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( 30650b57cec5SDimitry Andric ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); 30660b57cec5SDimitry Andric } 30670b57cec5SDimitry Andric #endif 30680b57cec5SDimitry Andric 30690b57cec5SDimitry Andric return; 30700b57cec5SDimitry Andric #else 30710b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 30720b57cec5SDimitry Andric #endif 30730b57cec5SDimitry Andric } 30740b57cec5SDimitry Andric #if KMP_USE_FUTEX 30750b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 30760b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) <= OMP_LOCK_T_SIZE)) { 30770b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 30780b57cec5SDimitry Andric } 30790b57cec5SDimitry Andric #endif 30800b57cec5SDimitry Andric else { 30810b57cec5SDimitry Andric lck = __kmp_lookup_user_lock(user_lock, "omp_unset_lock"); 30820b57cec5SDimitry Andric } 30830b57cec5SDimitry Andric 30840b57cec5SDimitry Andric #if USE_ITT_BUILD 30850b57cec5SDimitry Andric __kmp_itt_lock_releasing(lck); 30860b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 30870b57cec5SDimitry Andric 30880b57cec5SDimitry Andric RELEASE_LOCK(lck, gtid); 30890b57cec5SDimitry Andric 30900b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 30910b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 30920b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 30930b57cec5SDimitry Andric if (!codeptr) 30940b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 30950b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_released) { 30960b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( 30970b57cec5SDimitry Andric ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); 30980b57cec5SDimitry Andric } 30990b57cec5SDimitry Andric #endif 31000b57cec5SDimitry Andric 31010b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 31020b57cec5SDimitry Andric } 31030b57cec5SDimitry Andric 31040b57cec5SDimitry Andric /* release the lock */ 31050b57cec5SDimitry Andric void __kmpc_unset_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { 31060b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 31070b57cec5SDimitry Andric 31080b57cec5SDimitry Andric #if USE_ITT_BUILD 31090b57cec5SDimitry Andric __kmp_itt_lock_releasing((kmp_user_lock_p)user_lock); 31100b57cec5SDimitry Andric #endif 31110b57cec5SDimitry Andric int release_status = 31120b57cec5SDimitry Andric KMP_D_LOCK_FUNC(user_lock, unset)((kmp_dyna_lock_t *)user_lock, gtid); 31130b57cec5SDimitry Andric (void)release_status; 31140b57cec5SDimitry Andric 31150b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 31160b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 31170b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 31180b57cec5SDimitry Andric if (!codeptr) 31190b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 31200b57cec5SDimitry Andric if (ompt_enabled.enabled) { 31210b57cec5SDimitry Andric if (release_status == KMP_LOCK_RELEASED) { 31220b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_released) { 31230b57cec5SDimitry Andric // release_lock_last 31240b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( 31250b57cec5SDimitry Andric ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock, 31260b57cec5SDimitry Andric codeptr); 31270b57cec5SDimitry Andric } 31280b57cec5SDimitry Andric } else if (ompt_enabled.ompt_callback_nest_lock) { 31290b57cec5SDimitry Andric // release_lock_prev 31300b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( 31310b57cec5SDimitry Andric ompt_scope_end, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 31320b57cec5SDimitry Andric } 31330b57cec5SDimitry Andric } 31340b57cec5SDimitry Andric #endif 31350b57cec5SDimitry Andric 31360b57cec5SDimitry Andric #else // KMP_USE_DYNAMIC_LOCK 31370b57cec5SDimitry Andric 31380b57cec5SDimitry Andric kmp_user_lock_p lck; 31390b57cec5SDimitry Andric 31400b57cec5SDimitry Andric /* Can't use serial interval since not block structured */ 31410b57cec5SDimitry Andric 31420b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 31430b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) + sizeof(lck->tas.lk.depth_locked) <= 31440b57cec5SDimitry Andric OMP_NEST_LOCK_T_SIZE)) { 31450b57cec5SDimitry Andric #if KMP_OS_LINUX && \ 31460b57cec5SDimitry Andric (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_ARM || KMP_ARCH_AARCH64) 31470b57cec5SDimitry Andric // "fast" path implemented to fix customer performance issue 31480b57cec5SDimitry Andric kmp_tas_lock_t *tl = (kmp_tas_lock_t *)user_lock; 31490b57cec5SDimitry Andric #if USE_ITT_BUILD 31500b57cec5SDimitry Andric __kmp_itt_lock_releasing((kmp_user_lock_p)user_lock); 31510b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 31520b57cec5SDimitry Andric 31530b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 31540b57cec5SDimitry Andric int release_status = KMP_LOCK_STILL_HELD; 31550b57cec5SDimitry Andric #endif 31560b57cec5SDimitry Andric 31570b57cec5SDimitry Andric if (--(tl->lk.depth_locked) == 0) { 31580b57cec5SDimitry Andric TCW_4(tl->lk.poll, 0); 31590b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 31600b57cec5SDimitry Andric release_status = KMP_LOCK_RELEASED; 31610b57cec5SDimitry Andric #endif 31620b57cec5SDimitry Andric } 31630b57cec5SDimitry Andric KMP_MB(); 31640b57cec5SDimitry Andric 31650b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 31660b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 31670b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 31680b57cec5SDimitry Andric if (!codeptr) 31690b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 31700b57cec5SDimitry Andric if (ompt_enabled.enabled) { 31710b57cec5SDimitry Andric if (release_status == KMP_LOCK_RELEASED) { 31720b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_released) { 31730b57cec5SDimitry Andric // release_lock_last 31740b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( 31750b57cec5SDimitry Andric ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); 31760b57cec5SDimitry Andric } 31770b57cec5SDimitry Andric } else if (ompt_enabled.ompt_callback_nest_lock) { 31780b57cec5SDimitry Andric // release_lock_previous 31790b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( 31800b57cec5SDimitry Andric ompt_mutex_scope_end, (ompt_wait_id_t)(uintptr_t)lck, codeptr); 31810b57cec5SDimitry Andric } 31820b57cec5SDimitry Andric } 31830b57cec5SDimitry Andric #endif 31840b57cec5SDimitry Andric 31850b57cec5SDimitry Andric return; 31860b57cec5SDimitry Andric #else 31870b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 31880b57cec5SDimitry Andric #endif 31890b57cec5SDimitry Andric } 31900b57cec5SDimitry Andric #if KMP_USE_FUTEX 31910b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 31920b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) + sizeof(lck->futex.lk.depth_locked) <= 31930b57cec5SDimitry Andric OMP_NEST_LOCK_T_SIZE)) { 31940b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 31950b57cec5SDimitry Andric } 31960b57cec5SDimitry Andric #endif 31970b57cec5SDimitry Andric else { 31980b57cec5SDimitry Andric lck = __kmp_lookup_user_lock(user_lock, "omp_unset_nest_lock"); 31990b57cec5SDimitry Andric } 32000b57cec5SDimitry Andric 32010b57cec5SDimitry Andric #if USE_ITT_BUILD 32020b57cec5SDimitry Andric __kmp_itt_lock_releasing(lck); 32030b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 32040b57cec5SDimitry Andric 32050b57cec5SDimitry Andric int release_status; 32060b57cec5SDimitry Andric release_status = RELEASE_NESTED_LOCK(lck, gtid); 32070b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 32080b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 32090b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 32100b57cec5SDimitry Andric if (!codeptr) 32110b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 32120b57cec5SDimitry Andric if (ompt_enabled.enabled) { 32130b57cec5SDimitry Andric if (release_status == KMP_LOCK_RELEASED) { 32140b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_released) { 32150b57cec5SDimitry Andric // release_lock_last 32160b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( 32170b57cec5SDimitry Andric ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); 32180b57cec5SDimitry Andric } 32190b57cec5SDimitry Andric } else if (ompt_enabled.ompt_callback_nest_lock) { 32200b57cec5SDimitry Andric // release_lock_previous 32210b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( 32220b57cec5SDimitry Andric ompt_mutex_scope_end, (ompt_wait_id_t)(uintptr_t)lck, codeptr); 32230b57cec5SDimitry Andric } 32240b57cec5SDimitry Andric } 32250b57cec5SDimitry Andric #endif 32260b57cec5SDimitry Andric 32270b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 32280b57cec5SDimitry Andric } 32290b57cec5SDimitry Andric 32300b57cec5SDimitry Andric /* try to acquire the lock */ 32310b57cec5SDimitry Andric int __kmpc_test_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { 32320b57cec5SDimitry Andric KMP_COUNT_BLOCK(OMP_test_lock); 32330b57cec5SDimitry Andric 32340b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 32350b57cec5SDimitry Andric int rc; 32360b57cec5SDimitry Andric int tag = KMP_EXTRACT_D_TAG(user_lock); 32370b57cec5SDimitry Andric #if USE_ITT_BUILD 32380b57cec5SDimitry Andric __kmp_itt_lock_acquiring((kmp_user_lock_p)user_lock); 32390b57cec5SDimitry Andric #endif 32400b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 32410b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 32420b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 32430b57cec5SDimitry Andric if (!codeptr) 32440b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 32450b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquire) { 32460b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( 324706c3fb27SDimitry Andric ompt_mutex_test_lock, omp_lock_hint_none, 32480b57cec5SDimitry Andric __ompt_get_mutex_impl_type(user_lock), 32490b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 32500b57cec5SDimitry Andric } 32510b57cec5SDimitry Andric #endif 32520b57cec5SDimitry Andric #if KMP_USE_INLINED_TAS 32530b57cec5SDimitry Andric if (tag == locktag_tas && !__kmp_env_consistency_check) { 32540b57cec5SDimitry Andric KMP_TEST_TAS_LOCK(user_lock, gtid, rc); 32550b57cec5SDimitry Andric } else 32560b57cec5SDimitry Andric #elif KMP_USE_INLINED_FUTEX 32570b57cec5SDimitry Andric if (tag == locktag_futex && !__kmp_env_consistency_check) { 32580b57cec5SDimitry Andric KMP_TEST_FUTEX_LOCK(user_lock, gtid, rc); 32590b57cec5SDimitry Andric } else 32600b57cec5SDimitry Andric #endif 32610b57cec5SDimitry Andric { 32620b57cec5SDimitry Andric rc = __kmp_direct_test[tag]((kmp_dyna_lock_t *)user_lock, gtid); 32630b57cec5SDimitry Andric } 32640b57cec5SDimitry Andric if (rc) { 32650b57cec5SDimitry Andric #if USE_ITT_BUILD 32660b57cec5SDimitry Andric __kmp_itt_lock_acquired((kmp_user_lock_p)user_lock); 32670b57cec5SDimitry Andric #endif 32680b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 32690b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquired) { 32700b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( 327106c3fb27SDimitry Andric ompt_mutex_test_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 32720b57cec5SDimitry Andric } 32730b57cec5SDimitry Andric #endif 32740b57cec5SDimitry Andric return FTN_TRUE; 32750b57cec5SDimitry Andric } else { 32760b57cec5SDimitry Andric #if USE_ITT_BUILD 32770b57cec5SDimitry Andric __kmp_itt_lock_cancelled((kmp_user_lock_p)user_lock); 32780b57cec5SDimitry Andric #endif 32790b57cec5SDimitry Andric return FTN_FALSE; 32800b57cec5SDimitry Andric } 32810b57cec5SDimitry Andric 32820b57cec5SDimitry Andric #else // KMP_USE_DYNAMIC_LOCK 32830b57cec5SDimitry Andric 32840b57cec5SDimitry Andric kmp_user_lock_p lck; 32850b57cec5SDimitry Andric int rc; 32860b57cec5SDimitry Andric 32870b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 32880b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) <= OMP_LOCK_T_SIZE)) { 32890b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 32900b57cec5SDimitry Andric } 32910b57cec5SDimitry Andric #if KMP_USE_FUTEX 32920b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 32930b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) <= OMP_LOCK_T_SIZE)) { 32940b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 32950b57cec5SDimitry Andric } 32960b57cec5SDimitry Andric #endif 32970b57cec5SDimitry Andric else { 32980b57cec5SDimitry Andric lck = __kmp_lookup_user_lock(user_lock, "omp_test_lock"); 32990b57cec5SDimitry Andric } 33000b57cec5SDimitry Andric 33010b57cec5SDimitry Andric #if USE_ITT_BUILD 33020b57cec5SDimitry Andric __kmp_itt_lock_acquiring(lck); 33030b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 33040b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 33050b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 33060b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 33070b57cec5SDimitry Andric if (!codeptr) 33080b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 33090b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquire) { 33100b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( 331106c3fb27SDimitry Andric ompt_mutex_test_lock, omp_lock_hint_none, __ompt_get_mutex_impl_type(), 33120b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)lck, codeptr); 33130b57cec5SDimitry Andric } 33140b57cec5SDimitry Andric #endif 33150b57cec5SDimitry Andric 33160b57cec5SDimitry Andric rc = TEST_LOCK(lck, gtid); 33170b57cec5SDimitry Andric #if USE_ITT_BUILD 33180b57cec5SDimitry Andric if (rc) { 33190b57cec5SDimitry Andric __kmp_itt_lock_acquired(lck); 33200b57cec5SDimitry Andric } else { 33210b57cec5SDimitry Andric __kmp_itt_lock_cancelled(lck); 33220b57cec5SDimitry Andric } 33230b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 33240b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 33250b57cec5SDimitry Andric if (rc && ompt_enabled.ompt_callback_mutex_acquired) { 33260b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( 332706c3fb27SDimitry Andric ompt_mutex_test_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); 33280b57cec5SDimitry Andric } 33290b57cec5SDimitry Andric #endif 33300b57cec5SDimitry Andric 33310b57cec5SDimitry Andric return (rc ? FTN_TRUE : FTN_FALSE); 33320b57cec5SDimitry Andric 33330b57cec5SDimitry Andric /* Can't use serial interval since not block structured */ 33340b57cec5SDimitry Andric 33350b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 33360b57cec5SDimitry Andric } 33370b57cec5SDimitry Andric 33380b57cec5SDimitry Andric /* try to acquire the lock */ 33390b57cec5SDimitry Andric int __kmpc_test_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { 33400b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 33410b57cec5SDimitry Andric int rc; 33420b57cec5SDimitry Andric #if USE_ITT_BUILD 33430b57cec5SDimitry Andric __kmp_itt_lock_acquiring((kmp_user_lock_p)user_lock); 33440b57cec5SDimitry Andric #endif 33450b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 33460b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 33470b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 33480b57cec5SDimitry Andric if (!codeptr) 33490b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 33500b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquire) { 33510b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( 335206c3fb27SDimitry Andric ompt_mutex_test_nest_lock, omp_lock_hint_none, 33530b57cec5SDimitry Andric __ompt_get_mutex_impl_type(user_lock), 33540b57cec5SDimitry Andric (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 33550b57cec5SDimitry Andric } 33560b57cec5SDimitry Andric #endif 33570b57cec5SDimitry Andric rc = KMP_D_LOCK_FUNC(user_lock, test)((kmp_dyna_lock_t *)user_lock, gtid); 33580b57cec5SDimitry Andric #if USE_ITT_BUILD 33590b57cec5SDimitry Andric if (rc) { 33600b57cec5SDimitry Andric __kmp_itt_lock_acquired((kmp_user_lock_p)user_lock); 33610b57cec5SDimitry Andric } else { 33620b57cec5SDimitry Andric __kmp_itt_lock_cancelled((kmp_user_lock_p)user_lock); 33630b57cec5SDimitry Andric } 33640b57cec5SDimitry Andric #endif 33650b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 33660b57cec5SDimitry Andric if (ompt_enabled.enabled && rc) { 33670b57cec5SDimitry Andric if (rc == 1) { 33680b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquired) { 33690b57cec5SDimitry Andric // lock_first 33700b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( 337106c3fb27SDimitry Andric ompt_mutex_test_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock, 33720b57cec5SDimitry Andric codeptr); 33730b57cec5SDimitry Andric } 33740b57cec5SDimitry Andric } else { 33750b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_nest_lock) { 33760b57cec5SDimitry Andric // lock_next 33770b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( 33780b57cec5SDimitry Andric ompt_scope_begin, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); 33790b57cec5SDimitry Andric } 33800b57cec5SDimitry Andric } 33810b57cec5SDimitry Andric } 33820b57cec5SDimitry Andric #endif 33830b57cec5SDimitry Andric return rc; 33840b57cec5SDimitry Andric 33850b57cec5SDimitry Andric #else // KMP_USE_DYNAMIC_LOCK 33860b57cec5SDimitry Andric 33870b57cec5SDimitry Andric kmp_user_lock_p lck; 33880b57cec5SDimitry Andric int rc; 33890b57cec5SDimitry Andric 33900b57cec5SDimitry Andric if ((__kmp_user_lock_kind == lk_tas) && 33910b57cec5SDimitry Andric (sizeof(lck->tas.lk.poll) + sizeof(lck->tas.lk.depth_locked) <= 33920b57cec5SDimitry Andric OMP_NEST_LOCK_T_SIZE)) { 33930b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 33940b57cec5SDimitry Andric } 33950b57cec5SDimitry Andric #if KMP_USE_FUTEX 33960b57cec5SDimitry Andric else if ((__kmp_user_lock_kind == lk_futex) && 33970b57cec5SDimitry Andric (sizeof(lck->futex.lk.poll) + sizeof(lck->futex.lk.depth_locked) <= 33980b57cec5SDimitry Andric OMP_NEST_LOCK_T_SIZE)) { 33990b57cec5SDimitry Andric lck = (kmp_user_lock_p)user_lock; 34000b57cec5SDimitry Andric } 34010b57cec5SDimitry Andric #endif 34020b57cec5SDimitry Andric else { 34030b57cec5SDimitry Andric lck = __kmp_lookup_user_lock(user_lock, "omp_test_nest_lock"); 34040b57cec5SDimitry Andric } 34050b57cec5SDimitry Andric 34060b57cec5SDimitry Andric #if USE_ITT_BUILD 34070b57cec5SDimitry Andric __kmp_itt_lock_acquiring(lck); 34080b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 34090b57cec5SDimitry Andric 34100b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 34110b57cec5SDimitry Andric // This is the case, if called from omp_init_lock_with_hint: 34120b57cec5SDimitry Andric void *codeptr = OMPT_LOAD_RETURN_ADDRESS(gtid); 34130b57cec5SDimitry Andric if (!codeptr) 34140b57cec5SDimitry Andric codeptr = OMPT_GET_RETURN_ADDRESS(0); 34150b57cec5SDimitry Andric if (ompt_enabled.enabled) && 34160b57cec5SDimitry Andric ompt_enabled.ompt_callback_mutex_acquire) { 34170b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( 341806c3fb27SDimitry Andric ompt_mutex_test_nest_lock, omp_lock_hint_none, 34190b57cec5SDimitry Andric __ompt_get_mutex_impl_type(), (ompt_wait_id_t)(uintptr_t)lck, 34200b57cec5SDimitry Andric codeptr); 34210b57cec5SDimitry Andric } 34220b57cec5SDimitry Andric #endif 34230b57cec5SDimitry Andric 34240b57cec5SDimitry Andric rc = TEST_NESTED_LOCK(lck, gtid); 34250b57cec5SDimitry Andric #if USE_ITT_BUILD 34260b57cec5SDimitry Andric if (rc) { 34270b57cec5SDimitry Andric __kmp_itt_lock_acquired(lck); 34280b57cec5SDimitry Andric } else { 34290b57cec5SDimitry Andric __kmp_itt_lock_cancelled(lck); 34300b57cec5SDimitry Andric } 34310b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */ 34320b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 34330b57cec5SDimitry Andric if (ompt_enabled.enabled && rc) { 34340b57cec5SDimitry Andric if (rc == 1) { 34350b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_mutex_acquired) { 34360b57cec5SDimitry Andric // lock_first 34370b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( 343806c3fb27SDimitry Andric ompt_mutex_test_nest_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); 34390b57cec5SDimitry Andric } 34400b57cec5SDimitry Andric } else { 34410b57cec5SDimitry Andric if (ompt_enabled.ompt_callback_nest_lock) { 34420b57cec5SDimitry Andric // lock_next 34430b57cec5SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( 34440b57cec5SDimitry Andric ompt_mutex_scope_begin, (ompt_wait_id_t)(uintptr_t)lck, codeptr); 34450b57cec5SDimitry Andric } 34460b57cec5SDimitry Andric } 34470b57cec5SDimitry Andric } 34480b57cec5SDimitry Andric #endif 34490b57cec5SDimitry Andric return rc; 34500b57cec5SDimitry Andric 34510b57cec5SDimitry Andric /* Can't use serial interval since not block structured */ 34520b57cec5SDimitry Andric 34530b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 34540b57cec5SDimitry Andric } 34550b57cec5SDimitry Andric 34560b57cec5SDimitry Andric // Interface to fast scalable reduce methods routines 34570b57cec5SDimitry Andric 34580b57cec5SDimitry Andric // keep the selected method in a thread local structure for cross-function 34590b57cec5SDimitry Andric // usage: will be used in __kmpc_end_reduce* functions; 34600b57cec5SDimitry Andric // another solution: to re-determine the method one more time in 34610b57cec5SDimitry Andric // __kmpc_end_reduce* functions (new prototype required then) 34620b57cec5SDimitry Andric // AT: which solution is better? 34630b57cec5SDimitry Andric #define __KMP_SET_REDUCTION_METHOD(gtid, rmethod) \ 34640b57cec5SDimitry Andric ((__kmp_threads[(gtid)]->th.th_local.packed_reduction_method) = (rmethod)) 34650b57cec5SDimitry Andric 34660b57cec5SDimitry Andric #define __KMP_GET_REDUCTION_METHOD(gtid) \ 34670b57cec5SDimitry Andric (__kmp_threads[(gtid)]->th.th_local.packed_reduction_method) 34680b57cec5SDimitry Andric 34690b57cec5SDimitry Andric // description of the packed_reduction_method variable: look at the macros in 34700b57cec5SDimitry Andric // kmp.h 34710b57cec5SDimitry Andric 34720b57cec5SDimitry Andric // used in a critical section reduce block 34730b57cec5SDimitry Andric static __forceinline void 34740b57cec5SDimitry Andric __kmp_enter_critical_section_reduce_block(ident_t *loc, kmp_int32 global_tid, 34750b57cec5SDimitry Andric kmp_critical_name *crit) { 34760b57cec5SDimitry Andric 34770b57cec5SDimitry Andric // this lock was visible to a customer and to the threading profile tool as a 34780b57cec5SDimitry Andric // serial overhead span (although it's used for an internal purpose only) 34790b57cec5SDimitry Andric // why was it visible in previous implementation? 34800b57cec5SDimitry Andric // should we keep it visible in new reduce block? 34810b57cec5SDimitry Andric kmp_user_lock_p lck; 34820b57cec5SDimitry Andric 34830b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 34840b57cec5SDimitry Andric 34850b57cec5SDimitry Andric kmp_dyna_lock_t *lk = (kmp_dyna_lock_t *)crit; 34860b57cec5SDimitry Andric // Check if it is initialized. 34870b57cec5SDimitry Andric if (*lk == 0) { 34880b57cec5SDimitry Andric if (KMP_IS_D_LOCK(__kmp_user_lock_seq)) { 34890b57cec5SDimitry Andric KMP_COMPARE_AND_STORE_ACQ32((volatile kmp_int32 *)crit, 0, 34900b57cec5SDimitry Andric KMP_GET_D_TAG(__kmp_user_lock_seq)); 34910b57cec5SDimitry Andric } else { 34920b57cec5SDimitry Andric __kmp_init_indirect_csptr(crit, loc, global_tid, 34930b57cec5SDimitry Andric KMP_GET_I_TAG(__kmp_user_lock_seq)); 34940b57cec5SDimitry Andric } 34950b57cec5SDimitry Andric } 34960b57cec5SDimitry Andric // Branch for accessing the actual lock object and set operation. This 34970b57cec5SDimitry Andric // branching is inevitable since this lock initialization does not follow the 34980b57cec5SDimitry Andric // normal dispatch path (lock table is not used). 34990b57cec5SDimitry Andric if (KMP_EXTRACT_D_TAG(lk) != 0) { 35000b57cec5SDimitry Andric lck = (kmp_user_lock_p)lk; 35010b57cec5SDimitry Andric KMP_DEBUG_ASSERT(lck != NULL); 35020b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 35030b57cec5SDimitry Andric __kmp_push_sync(global_tid, ct_critical, loc, lck, __kmp_user_lock_seq); 35040b57cec5SDimitry Andric } 35050b57cec5SDimitry Andric KMP_D_LOCK_FUNC(lk, set)(lk, global_tid); 35060b57cec5SDimitry Andric } else { 35070b57cec5SDimitry Andric kmp_indirect_lock_t *ilk = *((kmp_indirect_lock_t **)lk); 35080b57cec5SDimitry Andric lck = ilk->lock; 35090b57cec5SDimitry Andric KMP_DEBUG_ASSERT(lck != NULL); 35100b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 35110b57cec5SDimitry Andric __kmp_push_sync(global_tid, ct_critical, loc, lck, __kmp_user_lock_seq); 35120b57cec5SDimitry Andric } 35130b57cec5SDimitry Andric KMP_I_LOCK_FUNC(ilk, set)(lck, global_tid); 35140b57cec5SDimitry Andric } 35150b57cec5SDimitry Andric 35160b57cec5SDimitry Andric #else // KMP_USE_DYNAMIC_LOCK 35170b57cec5SDimitry Andric 35180b57cec5SDimitry Andric // We know that the fast reduction code is only emitted by Intel compilers 35190b57cec5SDimitry Andric // with 32 byte critical sections. If there isn't enough space, then we 35200b57cec5SDimitry Andric // have to use a pointer. 35210b57cec5SDimitry Andric if (__kmp_base_user_lock_size <= INTEL_CRITICAL_SIZE) { 35220b57cec5SDimitry Andric lck = (kmp_user_lock_p)crit; 35230b57cec5SDimitry Andric } else { 35240b57cec5SDimitry Andric lck = __kmp_get_critical_section_ptr(crit, loc, global_tid); 35250b57cec5SDimitry Andric } 35260b57cec5SDimitry Andric KMP_DEBUG_ASSERT(lck != NULL); 35270b57cec5SDimitry Andric 35280b57cec5SDimitry Andric if (__kmp_env_consistency_check) 35290b57cec5SDimitry Andric __kmp_push_sync(global_tid, ct_critical, loc, lck); 35300b57cec5SDimitry Andric 35310b57cec5SDimitry Andric __kmp_acquire_user_lock_with_checks(lck, global_tid); 35320b57cec5SDimitry Andric 35330b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 35340b57cec5SDimitry Andric } 35350b57cec5SDimitry Andric 35360b57cec5SDimitry Andric // used in a critical section reduce block 35370b57cec5SDimitry Andric static __forceinline void 35380b57cec5SDimitry Andric __kmp_end_critical_section_reduce_block(ident_t *loc, kmp_int32 global_tid, 35390b57cec5SDimitry Andric kmp_critical_name *crit) { 35400b57cec5SDimitry Andric 35410b57cec5SDimitry Andric kmp_user_lock_p lck; 35420b57cec5SDimitry Andric 35430b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 35440b57cec5SDimitry Andric 35450b57cec5SDimitry Andric if (KMP_IS_D_LOCK(__kmp_user_lock_seq)) { 35460b57cec5SDimitry Andric lck = (kmp_user_lock_p)crit; 35470b57cec5SDimitry Andric if (__kmp_env_consistency_check) 35480b57cec5SDimitry Andric __kmp_pop_sync(global_tid, ct_critical, loc); 35490b57cec5SDimitry Andric KMP_D_LOCK_FUNC(lck, unset)((kmp_dyna_lock_t *)lck, global_tid); 35500b57cec5SDimitry Andric } else { 35510b57cec5SDimitry Andric kmp_indirect_lock_t *ilk = 35520b57cec5SDimitry Andric (kmp_indirect_lock_t *)TCR_PTR(*((kmp_indirect_lock_t **)crit)); 35530b57cec5SDimitry Andric if (__kmp_env_consistency_check) 35540b57cec5SDimitry Andric __kmp_pop_sync(global_tid, ct_critical, loc); 35550b57cec5SDimitry Andric KMP_I_LOCK_FUNC(ilk, unset)(ilk->lock, global_tid); 35560b57cec5SDimitry Andric } 35570b57cec5SDimitry Andric 35580b57cec5SDimitry Andric #else // KMP_USE_DYNAMIC_LOCK 35590b57cec5SDimitry Andric 35600b57cec5SDimitry Andric // We know that the fast reduction code is only emitted by Intel compilers 35610b57cec5SDimitry Andric // with 32 byte critical sections. If there isn't enough space, then we have 35620b57cec5SDimitry Andric // to use a pointer. 35630b57cec5SDimitry Andric if (__kmp_base_user_lock_size > 32) { 35640b57cec5SDimitry Andric lck = *((kmp_user_lock_p *)crit); 35650b57cec5SDimitry Andric KMP_ASSERT(lck != NULL); 35660b57cec5SDimitry Andric } else { 35670b57cec5SDimitry Andric lck = (kmp_user_lock_p)crit; 35680b57cec5SDimitry Andric } 35690b57cec5SDimitry Andric 35700b57cec5SDimitry Andric if (__kmp_env_consistency_check) 35710b57cec5SDimitry Andric __kmp_pop_sync(global_tid, ct_critical, loc); 35720b57cec5SDimitry Andric 35730b57cec5SDimitry Andric __kmp_release_user_lock_with_checks(lck, global_tid); 35740b57cec5SDimitry Andric 35750b57cec5SDimitry Andric #endif // KMP_USE_DYNAMIC_LOCK 35760b57cec5SDimitry Andric } // __kmp_end_critical_section_reduce_block 35770b57cec5SDimitry Andric 35780b57cec5SDimitry Andric static __forceinline int 35790b57cec5SDimitry Andric __kmp_swap_teams_for_teams_reduction(kmp_info_t *th, kmp_team_t **team_p, 35800b57cec5SDimitry Andric int *task_state) { 35810b57cec5SDimitry Andric kmp_team_t *team; 35820b57cec5SDimitry Andric 35830b57cec5SDimitry Andric // Check if we are inside the teams construct? 35840b57cec5SDimitry Andric if (th->th.th_teams_microtask) { 35850b57cec5SDimitry Andric *team_p = team = th->th.th_team; 35860b57cec5SDimitry Andric if (team->t.t_level == th->th.th_teams_level) { 35870b57cec5SDimitry Andric // This is reduction at teams construct. 35880b57cec5SDimitry Andric KMP_DEBUG_ASSERT(!th->th.th_info.ds.ds_tid); // AC: check that tid == 0 35890b57cec5SDimitry Andric // Let's swap teams temporarily for the reduction. 35900b57cec5SDimitry Andric th->th.th_info.ds.ds_tid = team->t.t_master_tid; 35910b57cec5SDimitry Andric th->th.th_team = team->t.t_parent; 35920b57cec5SDimitry Andric th->th.th_team_nproc = th->th.th_team->t.t_nproc; 35930b57cec5SDimitry Andric th->th.th_task_team = th->th.th_team->t.t_task_team[0]; 35940b57cec5SDimitry Andric *task_state = th->th.th_task_state; 35950b57cec5SDimitry Andric th->th.th_task_state = 0; 35960b57cec5SDimitry Andric 35970b57cec5SDimitry Andric return 1; 35980b57cec5SDimitry Andric } 35990b57cec5SDimitry Andric } 36000b57cec5SDimitry Andric return 0; 36010b57cec5SDimitry Andric } 36020b57cec5SDimitry Andric 36030b57cec5SDimitry Andric static __forceinline void 36040b57cec5SDimitry Andric __kmp_restore_swapped_teams(kmp_info_t *th, kmp_team_t *team, int task_state) { 36050b57cec5SDimitry Andric // Restore thread structure swapped in __kmp_swap_teams_for_teams_reduction. 36060b57cec5SDimitry Andric th->th.th_info.ds.ds_tid = 0; 36070b57cec5SDimitry Andric th->th.th_team = team; 36080b57cec5SDimitry Andric th->th.th_team_nproc = team->t.t_nproc; 36090b57cec5SDimitry Andric th->th.th_task_team = team->t.t_task_team[task_state]; 3610e8d8bef9SDimitry Andric __kmp_type_convert(task_state, &(th->th.th_task_state)); 36110b57cec5SDimitry Andric } 36120b57cec5SDimitry Andric 36130b57cec5SDimitry Andric /* 2.a.i. Reduce Block without a terminating barrier */ 36140b57cec5SDimitry Andric /*! 36150b57cec5SDimitry Andric @ingroup SYNCHRONIZATION 36160b57cec5SDimitry Andric @param loc source location information 36170b57cec5SDimitry Andric @param global_tid global thread number 36180b57cec5SDimitry Andric @param num_vars number of items (variables) to be reduced 36190b57cec5SDimitry Andric @param reduce_size size of data in bytes to be reduced 36200b57cec5SDimitry Andric @param reduce_data pointer to data to be reduced 36210b57cec5SDimitry Andric @param reduce_func callback function providing reduction operation on two 36220b57cec5SDimitry Andric operands and returning result of reduction in lhs_data 36230b57cec5SDimitry Andric @param lck pointer to the unique lock data structure 3624fe6060f1SDimitry Andric @result 1 for the primary thread, 0 for all other team threads, 2 for all team 36250b57cec5SDimitry Andric threads if atomic reduction needed 36260b57cec5SDimitry Andric 36270b57cec5SDimitry Andric The nowait version is used for a reduce clause with the nowait argument. 36280b57cec5SDimitry Andric */ 36290b57cec5SDimitry Andric kmp_int32 36300b57cec5SDimitry Andric __kmpc_reduce_nowait(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars, 36310b57cec5SDimitry Andric size_t reduce_size, void *reduce_data, 36320b57cec5SDimitry Andric void (*reduce_func)(void *lhs_data, void *rhs_data), 36330b57cec5SDimitry Andric kmp_critical_name *lck) { 36340b57cec5SDimitry Andric 36350b57cec5SDimitry Andric KMP_COUNT_BLOCK(REDUCE_nowait); 36360b57cec5SDimitry Andric int retval = 0; 36370b57cec5SDimitry Andric PACKED_REDUCTION_METHOD_T packed_reduction_method; 36380b57cec5SDimitry Andric kmp_info_t *th; 36390b57cec5SDimitry Andric kmp_team_t *team; 36400b57cec5SDimitry Andric int teams_swapped = 0, task_state; 36410b57cec5SDimitry Andric KA_TRACE(10, ("__kmpc_reduce_nowait() enter: called T#%d\n", global_tid)); 3642e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 36430b57cec5SDimitry Andric 36440b57cec5SDimitry Andric // why do we need this initialization here at all? 36450b57cec5SDimitry Andric // Reduction clause can not be used as a stand-alone directive. 36460b57cec5SDimitry Andric 36470b57cec5SDimitry Andric // do not call __kmp_serial_initialize(), it will be called by 36480b57cec5SDimitry Andric // __kmp_parallel_initialize() if needed 36490b57cec5SDimitry Andric // possible detection of false-positive race by the threadchecker ??? 36500b57cec5SDimitry Andric if (!TCR_4(__kmp_init_parallel)) 36510b57cec5SDimitry Andric __kmp_parallel_initialize(); 36520b57cec5SDimitry Andric 36530b57cec5SDimitry Andric __kmp_resume_if_soft_paused(); 36540b57cec5SDimitry Andric 36550b57cec5SDimitry Andric // check correctness of reduce block nesting 36560b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 36570b57cec5SDimitry Andric if (__kmp_env_consistency_check) 36580b57cec5SDimitry Andric __kmp_push_sync(global_tid, ct_reduce, loc, NULL, 0); 36590b57cec5SDimitry Andric #else 36600b57cec5SDimitry Andric if (__kmp_env_consistency_check) 36610b57cec5SDimitry Andric __kmp_push_sync(global_tid, ct_reduce, loc, NULL); 36620b57cec5SDimitry Andric #endif 36630b57cec5SDimitry Andric 36640b57cec5SDimitry Andric th = __kmp_thread_from_gtid(global_tid); 36650b57cec5SDimitry Andric teams_swapped = __kmp_swap_teams_for_teams_reduction(th, &team, &task_state); 36660b57cec5SDimitry Andric 36670b57cec5SDimitry Andric // packed_reduction_method value will be reused by __kmp_end_reduce* function, 36680b57cec5SDimitry Andric // the value should be kept in a variable 36690b57cec5SDimitry Andric // the variable should be either a construct-specific or thread-specific 36700b57cec5SDimitry Andric // property, not a team specific property 36710b57cec5SDimitry Andric // (a thread can reach the next reduce block on the next construct, reduce 36720b57cec5SDimitry Andric // method may differ on the next construct) 36730b57cec5SDimitry Andric // an ident_t "loc" parameter could be used as a construct-specific property 36740b57cec5SDimitry Andric // (what if loc == 0?) 36750b57cec5SDimitry Andric // (if both construct-specific and team-specific variables were shared, 36760b57cec5SDimitry Andric // then unness extra syncs should be needed) 36770b57cec5SDimitry Andric // a thread-specific variable is better regarding two issues above (next 36780b57cec5SDimitry Andric // construct and extra syncs) 36790b57cec5SDimitry Andric // a thread-specific "th_local.reduction_method" variable is used currently 36800b57cec5SDimitry Andric // each thread executes 'determine' and 'set' lines (no need to execute by one 36810b57cec5SDimitry Andric // thread, to avoid unness extra syncs) 36820b57cec5SDimitry Andric 36830b57cec5SDimitry Andric packed_reduction_method = __kmp_determine_reduction_method( 36840b57cec5SDimitry Andric loc, global_tid, num_vars, reduce_size, reduce_data, reduce_func, lck); 36850b57cec5SDimitry Andric __KMP_SET_REDUCTION_METHOD(global_tid, packed_reduction_method); 36860b57cec5SDimitry Andric 3687480093f4SDimitry Andric OMPT_REDUCTION_DECL(th, global_tid); 36880b57cec5SDimitry Andric if (packed_reduction_method == critical_reduce_block) { 36890b57cec5SDimitry Andric 3690480093f4SDimitry Andric OMPT_REDUCTION_BEGIN; 3691480093f4SDimitry Andric 36920b57cec5SDimitry Andric __kmp_enter_critical_section_reduce_block(loc, global_tid, lck); 36930b57cec5SDimitry Andric retval = 1; 36940b57cec5SDimitry Andric 36950b57cec5SDimitry Andric } else if (packed_reduction_method == empty_reduce_block) { 36960b57cec5SDimitry Andric 3697480093f4SDimitry Andric OMPT_REDUCTION_BEGIN; 3698480093f4SDimitry Andric 36990b57cec5SDimitry Andric // usage: if team size == 1, no synchronization is required ( Intel 37000b57cec5SDimitry Andric // platforms only ) 37010b57cec5SDimitry Andric retval = 1; 37020b57cec5SDimitry Andric 37030b57cec5SDimitry Andric } else if (packed_reduction_method == atomic_reduce_block) { 37040b57cec5SDimitry Andric 37050b57cec5SDimitry Andric retval = 2; 37060b57cec5SDimitry Andric 37070b57cec5SDimitry Andric // all threads should do this pop here (because __kmpc_end_reduce_nowait() 37080b57cec5SDimitry Andric // won't be called by the code gen) 37090b57cec5SDimitry Andric // (it's not quite good, because the checking block has been closed by 37100b57cec5SDimitry Andric // this 'pop', 37110b57cec5SDimitry Andric // but atomic operation has not been executed yet, will be executed 37120b57cec5SDimitry Andric // slightly later, literally on next instruction) 37130b57cec5SDimitry Andric if (__kmp_env_consistency_check) 37140b57cec5SDimitry Andric __kmp_pop_sync(global_tid, ct_reduce, loc); 37150b57cec5SDimitry Andric 37160b57cec5SDimitry Andric } else if (TEST_REDUCTION_METHOD(packed_reduction_method, 37170b57cec5SDimitry Andric tree_reduce_block)) { 37180b57cec5SDimitry Andric 37190b57cec5SDimitry Andric // AT: performance issue: a real barrier here 3720fe6060f1SDimitry Andric // AT: (if primary thread is slow, other threads are blocked here waiting for 3721fe6060f1SDimitry Andric // the primary thread to come and release them) 37220b57cec5SDimitry Andric // AT: (it's not what a customer might expect specifying NOWAIT clause) 37230b57cec5SDimitry Andric // AT: (specifying NOWAIT won't result in improvement of performance, it'll 37240b57cec5SDimitry Andric // be confusing to a customer) 37250b57cec5SDimitry Andric // AT: another implementation of *barrier_gather*nowait() (or some other design) 37260b57cec5SDimitry Andric // might go faster and be more in line with sense of NOWAIT 37270b57cec5SDimitry Andric // AT: TO DO: do epcc test and compare times 37280b57cec5SDimitry Andric 37290b57cec5SDimitry Andric // this barrier should be invisible to a customer and to the threading profile 37300b57cec5SDimitry Andric // tool (it's neither a terminating barrier nor customer's code, it's 37310b57cec5SDimitry Andric // used for an internal purpose) 37320b57cec5SDimitry Andric #if OMPT_SUPPORT 37330b57cec5SDimitry Andric // JP: can this barrier potentially leed to task scheduling? 37340b57cec5SDimitry Andric // JP: as long as there is a barrier in the implementation, OMPT should and 37350b57cec5SDimitry Andric // will provide the barrier events 37360b57cec5SDimitry Andric // so we set-up the necessary frame/return addresses. 37370b57cec5SDimitry Andric ompt_frame_t *ompt_frame; 37380b57cec5SDimitry Andric if (ompt_enabled.enabled) { 37390b57cec5SDimitry Andric __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL); 37400b57cec5SDimitry Andric if (ompt_frame->enter_frame.ptr == NULL) 37410b57cec5SDimitry Andric ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0); 37420b57cec5SDimitry Andric } 3743e8d8bef9SDimitry Andric OMPT_STORE_RETURN_ADDRESS(global_tid); 37440b57cec5SDimitry Andric #endif 37450b57cec5SDimitry Andric #if USE_ITT_NOTIFY 37460b57cec5SDimitry Andric __kmp_threads[global_tid]->th.th_ident = loc; 37470b57cec5SDimitry Andric #endif 37480b57cec5SDimitry Andric retval = 37490b57cec5SDimitry Andric __kmp_barrier(UNPACK_REDUCTION_BARRIER(packed_reduction_method), 37500b57cec5SDimitry Andric global_tid, FALSE, reduce_size, reduce_data, reduce_func); 37510b57cec5SDimitry Andric retval = (retval != 0) ? (0) : (1); 37520b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 37530b57cec5SDimitry Andric if (ompt_enabled.enabled) { 37540b57cec5SDimitry Andric ompt_frame->enter_frame = ompt_data_none; 37550b57cec5SDimitry Andric } 37560b57cec5SDimitry Andric #endif 37570b57cec5SDimitry Andric 3758fe6060f1SDimitry Andric // all other workers except primary thread should do this pop here 37590b57cec5SDimitry Andric // ( none of other workers will get to __kmpc_end_reduce_nowait() ) 37600b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 37610b57cec5SDimitry Andric if (retval == 0) { 37620b57cec5SDimitry Andric __kmp_pop_sync(global_tid, ct_reduce, loc); 37630b57cec5SDimitry Andric } 37640b57cec5SDimitry Andric } 37650b57cec5SDimitry Andric 37660b57cec5SDimitry Andric } else { 37670b57cec5SDimitry Andric 37680b57cec5SDimitry Andric // should never reach this block 37690b57cec5SDimitry Andric KMP_ASSERT(0); // "unexpected method" 37700b57cec5SDimitry Andric } 37710b57cec5SDimitry Andric if (teams_swapped) { 37720b57cec5SDimitry Andric __kmp_restore_swapped_teams(th, team, task_state); 37730b57cec5SDimitry Andric } 37740b57cec5SDimitry Andric KA_TRACE( 37750b57cec5SDimitry Andric 10, 37760b57cec5SDimitry Andric ("__kmpc_reduce_nowait() exit: called T#%d: method %08x, returns %08x\n", 37770b57cec5SDimitry Andric global_tid, packed_reduction_method, retval)); 37780b57cec5SDimitry Andric 37790b57cec5SDimitry Andric return retval; 37800b57cec5SDimitry Andric } 37810b57cec5SDimitry Andric 37820b57cec5SDimitry Andric /*! 37830b57cec5SDimitry Andric @ingroup SYNCHRONIZATION 37840b57cec5SDimitry Andric @param loc source location information 37850b57cec5SDimitry Andric @param global_tid global thread id. 37860b57cec5SDimitry Andric @param lck pointer to the unique lock data structure 37870b57cec5SDimitry Andric 37880b57cec5SDimitry Andric Finish the execution of a reduce nowait. 37890b57cec5SDimitry Andric */ 37900b57cec5SDimitry Andric void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 37910b57cec5SDimitry Andric kmp_critical_name *lck) { 37920b57cec5SDimitry Andric 37930b57cec5SDimitry Andric PACKED_REDUCTION_METHOD_T packed_reduction_method; 37940b57cec5SDimitry Andric 37950b57cec5SDimitry Andric KA_TRACE(10, ("__kmpc_end_reduce_nowait() enter: called T#%d\n", global_tid)); 3796e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 37970b57cec5SDimitry Andric 37980b57cec5SDimitry Andric packed_reduction_method = __KMP_GET_REDUCTION_METHOD(global_tid); 37990b57cec5SDimitry Andric 3800480093f4SDimitry Andric OMPT_REDUCTION_DECL(__kmp_thread_from_gtid(global_tid), global_tid); 3801480093f4SDimitry Andric 38020b57cec5SDimitry Andric if (packed_reduction_method == critical_reduce_block) { 38030b57cec5SDimitry Andric 38040b57cec5SDimitry Andric __kmp_end_critical_section_reduce_block(loc, global_tid, lck); 3805480093f4SDimitry Andric OMPT_REDUCTION_END; 38060b57cec5SDimitry Andric 38070b57cec5SDimitry Andric } else if (packed_reduction_method == empty_reduce_block) { 38080b57cec5SDimitry Andric 38090b57cec5SDimitry Andric // usage: if team size == 1, no synchronization is required ( on Intel 38100b57cec5SDimitry Andric // platforms only ) 38110b57cec5SDimitry Andric 3812480093f4SDimitry Andric OMPT_REDUCTION_END; 3813480093f4SDimitry Andric 38140b57cec5SDimitry Andric } else if (packed_reduction_method == atomic_reduce_block) { 38150b57cec5SDimitry Andric 3816fe6060f1SDimitry Andric // neither primary thread nor other workers should get here 38170b57cec5SDimitry Andric // (code gen does not generate this call in case 2: atomic reduce block) 38180b57cec5SDimitry Andric // actually it's better to remove this elseif at all; 38190b57cec5SDimitry Andric // after removal this value will checked by the 'else' and will assert 38200b57cec5SDimitry Andric 38210b57cec5SDimitry Andric } else if (TEST_REDUCTION_METHOD(packed_reduction_method, 38220b57cec5SDimitry Andric tree_reduce_block)) { 38230b57cec5SDimitry Andric 3824fe6060f1SDimitry Andric // only primary thread gets here 3825480093f4SDimitry Andric // OMPT: tree reduction is annotated in the barrier code 38260b57cec5SDimitry Andric 38270b57cec5SDimitry Andric } else { 38280b57cec5SDimitry Andric 38290b57cec5SDimitry Andric // should never reach this block 38300b57cec5SDimitry Andric KMP_ASSERT(0); // "unexpected method" 38310b57cec5SDimitry Andric } 38320b57cec5SDimitry Andric 38330b57cec5SDimitry Andric if (__kmp_env_consistency_check) 38340b57cec5SDimitry Andric __kmp_pop_sync(global_tid, ct_reduce, loc); 38350b57cec5SDimitry Andric 38360b57cec5SDimitry Andric KA_TRACE(10, ("__kmpc_end_reduce_nowait() exit: called T#%d: method %08x\n", 38370b57cec5SDimitry Andric global_tid, packed_reduction_method)); 38380b57cec5SDimitry Andric 38390b57cec5SDimitry Andric return; 38400b57cec5SDimitry Andric } 38410b57cec5SDimitry Andric 38420b57cec5SDimitry Andric /* 2.a.ii. Reduce Block with a terminating barrier */ 38430b57cec5SDimitry Andric 38440b57cec5SDimitry Andric /*! 38450b57cec5SDimitry Andric @ingroup SYNCHRONIZATION 38460b57cec5SDimitry Andric @param loc source location information 38470b57cec5SDimitry Andric @param global_tid global thread number 38480b57cec5SDimitry Andric @param num_vars number of items (variables) to be reduced 38490b57cec5SDimitry Andric @param reduce_size size of data in bytes to be reduced 38500b57cec5SDimitry Andric @param reduce_data pointer to data to be reduced 38510b57cec5SDimitry Andric @param reduce_func callback function providing reduction operation on two 38520b57cec5SDimitry Andric operands and returning result of reduction in lhs_data 38530b57cec5SDimitry Andric @param lck pointer to the unique lock data structure 3854fe6060f1SDimitry Andric @result 1 for the primary thread, 0 for all other team threads, 2 for all team 38550b57cec5SDimitry Andric threads if atomic reduction needed 38560b57cec5SDimitry Andric 38570b57cec5SDimitry Andric A blocking reduce that includes an implicit barrier. 38580b57cec5SDimitry Andric */ 38590b57cec5SDimitry Andric kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars, 38600b57cec5SDimitry Andric size_t reduce_size, void *reduce_data, 38610b57cec5SDimitry Andric void (*reduce_func)(void *lhs_data, void *rhs_data), 38620b57cec5SDimitry Andric kmp_critical_name *lck) { 38630b57cec5SDimitry Andric KMP_COUNT_BLOCK(REDUCE_wait); 38640b57cec5SDimitry Andric int retval = 0; 38650b57cec5SDimitry Andric PACKED_REDUCTION_METHOD_T packed_reduction_method; 38660b57cec5SDimitry Andric kmp_info_t *th; 38670b57cec5SDimitry Andric kmp_team_t *team; 38680b57cec5SDimitry Andric int teams_swapped = 0, task_state; 38690b57cec5SDimitry Andric 38700b57cec5SDimitry Andric KA_TRACE(10, ("__kmpc_reduce() enter: called T#%d\n", global_tid)); 3871e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 38720b57cec5SDimitry Andric 38730b57cec5SDimitry Andric // why do we need this initialization here at all? 38740b57cec5SDimitry Andric // Reduction clause can not be a stand-alone directive. 38750b57cec5SDimitry Andric 38760b57cec5SDimitry Andric // do not call __kmp_serial_initialize(), it will be called by 38770b57cec5SDimitry Andric // __kmp_parallel_initialize() if needed 38780b57cec5SDimitry Andric // possible detection of false-positive race by the threadchecker ??? 38790b57cec5SDimitry Andric if (!TCR_4(__kmp_init_parallel)) 38800b57cec5SDimitry Andric __kmp_parallel_initialize(); 38810b57cec5SDimitry Andric 38820b57cec5SDimitry Andric __kmp_resume_if_soft_paused(); 38830b57cec5SDimitry Andric 38840b57cec5SDimitry Andric // check correctness of reduce block nesting 38850b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK 38860b57cec5SDimitry Andric if (__kmp_env_consistency_check) 38870b57cec5SDimitry Andric __kmp_push_sync(global_tid, ct_reduce, loc, NULL, 0); 38880b57cec5SDimitry Andric #else 38890b57cec5SDimitry Andric if (__kmp_env_consistency_check) 38900b57cec5SDimitry Andric __kmp_push_sync(global_tid, ct_reduce, loc, NULL); 38910b57cec5SDimitry Andric #endif 38920b57cec5SDimitry Andric 38930b57cec5SDimitry Andric th = __kmp_thread_from_gtid(global_tid); 38940b57cec5SDimitry Andric teams_swapped = __kmp_swap_teams_for_teams_reduction(th, &team, &task_state); 38950b57cec5SDimitry Andric 38960b57cec5SDimitry Andric packed_reduction_method = __kmp_determine_reduction_method( 38970b57cec5SDimitry Andric loc, global_tid, num_vars, reduce_size, reduce_data, reduce_func, lck); 38980b57cec5SDimitry Andric __KMP_SET_REDUCTION_METHOD(global_tid, packed_reduction_method); 38990b57cec5SDimitry Andric 3900480093f4SDimitry Andric OMPT_REDUCTION_DECL(th, global_tid); 3901480093f4SDimitry Andric 39020b57cec5SDimitry Andric if (packed_reduction_method == critical_reduce_block) { 39030b57cec5SDimitry Andric 3904480093f4SDimitry Andric OMPT_REDUCTION_BEGIN; 39050b57cec5SDimitry Andric __kmp_enter_critical_section_reduce_block(loc, global_tid, lck); 39060b57cec5SDimitry Andric retval = 1; 39070b57cec5SDimitry Andric 39080b57cec5SDimitry Andric } else if (packed_reduction_method == empty_reduce_block) { 39090b57cec5SDimitry Andric 3910480093f4SDimitry Andric OMPT_REDUCTION_BEGIN; 39110b57cec5SDimitry Andric // usage: if team size == 1, no synchronization is required ( Intel 39120b57cec5SDimitry Andric // platforms only ) 39130b57cec5SDimitry Andric retval = 1; 39140b57cec5SDimitry Andric 39150b57cec5SDimitry Andric } else if (packed_reduction_method == atomic_reduce_block) { 39160b57cec5SDimitry Andric 39170b57cec5SDimitry Andric retval = 2; 39180b57cec5SDimitry Andric 39190b57cec5SDimitry Andric } else if (TEST_REDUCTION_METHOD(packed_reduction_method, 39200b57cec5SDimitry Andric tree_reduce_block)) { 39210b57cec5SDimitry Andric 39220b57cec5SDimitry Andric // case tree_reduce_block: 39230b57cec5SDimitry Andric // this barrier should be visible to a customer and to the threading profile 39240b57cec5SDimitry Andric // tool (it's a terminating barrier on constructs if NOWAIT not specified) 39250b57cec5SDimitry Andric #if OMPT_SUPPORT 39260b57cec5SDimitry Andric ompt_frame_t *ompt_frame; 39270b57cec5SDimitry Andric if (ompt_enabled.enabled) { 39280b57cec5SDimitry Andric __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL); 39290b57cec5SDimitry Andric if (ompt_frame->enter_frame.ptr == NULL) 39300b57cec5SDimitry Andric ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0); 39310b57cec5SDimitry Andric } 3932e8d8bef9SDimitry Andric OMPT_STORE_RETURN_ADDRESS(global_tid); 39330b57cec5SDimitry Andric #endif 39340b57cec5SDimitry Andric #if USE_ITT_NOTIFY 39350b57cec5SDimitry Andric __kmp_threads[global_tid]->th.th_ident = 39360b57cec5SDimitry Andric loc; // needed for correct notification of frames 39370b57cec5SDimitry Andric #endif 39380b57cec5SDimitry Andric retval = 39390b57cec5SDimitry Andric __kmp_barrier(UNPACK_REDUCTION_BARRIER(packed_reduction_method), 39400b57cec5SDimitry Andric global_tid, TRUE, reduce_size, reduce_data, reduce_func); 39410b57cec5SDimitry Andric retval = (retval != 0) ? (0) : (1); 39420b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 39430b57cec5SDimitry Andric if (ompt_enabled.enabled) { 39440b57cec5SDimitry Andric ompt_frame->enter_frame = ompt_data_none; 39450b57cec5SDimitry Andric } 39460b57cec5SDimitry Andric #endif 39470b57cec5SDimitry Andric 3948fe6060f1SDimitry Andric // all other workers except primary thread should do this pop here 3949fe6060f1SDimitry Andric // (none of other workers except primary will enter __kmpc_end_reduce()) 39500b57cec5SDimitry Andric if (__kmp_env_consistency_check) { 3951fe6060f1SDimitry Andric if (retval == 0) { // 0: all other workers; 1: primary thread 39520b57cec5SDimitry Andric __kmp_pop_sync(global_tid, ct_reduce, loc); 39530b57cec5SDimitry Andric } 39540b57cec5SDimitry Andric } 39550b57cec5SDimitry Andric 39560b57cec5SDimitry Andric } else { 39570b57cec5SDimitry Andric 39580b57cec5SDimitry Andric // should never reach this block 39590b57cec5SDimitry Andric KMP_ASSERT(0); // "unexpected method" 39600b57cec5SDimitry Andric } 39610b57cec5SDimitry Andric if (teams_swapped) { 39620b57cec5SDimitry Andric __kmp_restore_swapped_teams(th, team, task_state); 39630b57cec5SDimitry Andric } 39640b57cec5SDimitry Andric 39650b57cec5SDimitry Andric KA_TRACE(10, 39660b57cec5SDimitry Andric ("__kmpc_reduce() exit: called T#%d: method %08x, returns %08x\n", 39670b57cec5SDimitry Andric global_tid, packed_reduction_method, retval)); 39680b57cec5SDimitry Andric return retval; 39690b57cec5SDimitry Andric } 39700b57cec5SDimitry Andric 39710b57cec5SDimitry Andric /*! 39720b57cec5SDimitry Andric @ingroup SYNCHRONIZATION 39730b57cec5SDimitry Andric @param loc source location information 39740b57cec5SDimitry Andric @param global_tid global thread id. 39750b57cec5SDimitry Andric @param lck pointer to the unique lock data structure 39760b57cec5SDimitry Andric 39770b57cec5SDimitry Andric Finish the execution of a blocking reduce. 39780b57cec5SDimitry Andric The <tt>lck</tt> pointer must be the same as that used in the corresponding 39790b57cec5SDimitry Andric start function. 39800b57cec5SDimitry Andric */ 39810b57cec5SDimitry Andric void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 39820b57cec5SDimitry Andric kmp_critical_name *lck) { 39830b57cec5SDimitry Andric 39840b57cec5SDimitry Andric PACKED_REDUCTION_METHOD_T packed_reduction_method; 39850b57cec5SDimitry Andric kmp_info_t *th; 39860b57cec5SDimitry Andric kmp_team_t *team; 39870b57cec5SDimitry Andric int teams_swapped = 0, task_state; 39880b57cec5SDimitry Andric 39890b57cec5SDimitry Andric KA_TRACE(10, ("__kmpc_end_reduce() enter: called T#%d\n", global_tid)); 3990e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(global_tid); 39910b57cec5SDimitry Andric 39920b57cec5SDimitry Andric th = __kmp_thread_from_gtid(global_tid); 39930b57cec5SDimitry Andric teams_swapped = __kmp_swap_teams_for_teams_reduction(th, &team, &task_state); 39940b57cec5SDimitry Andric 39950b57cec5SDimitry Andric packed_reduction_method = __KMP_GET_REDUCTION_METHOD(global_tid); 39960b57cec5SDimitry Andric 39970b57cec5SDimitry Andric // this barrier should be visible to a customer and to the threading profile 39980b57cec5SDimitry Andric // tool (it's a terminating barrier on constructs if NOWAIT not specified) 3999480093f4SDimitry Andric OMPT_REDUCTION_DECL(th, global_tid); 40000b57cec5SDimitry Andric 40010b57cec5SDimitry Andric if (packed_reduction_method == critical_reduce_block) { 40020b57cec5SDimitry Andric __kmp_end_critical_section_reduce_block(loc, global_tid, lck); 40030b57cec5SDimitry Andric 4004480093f4SDimitry Andric OMPT_REDUCTION_END; 4005480093f4SDimitry Andric 40060b57cec5SDimitry Andric // TODO: implicit barrier: should be exposed 40070b57cec5SDimitry Andric #if OMPT_SUPPORT 40080b57cec5SDimitry Andric ompt_frame_t *ompt_frame; 40090b57cec5SDimitry Andric if (ompt_enabled.enabled) { 40100b57cec5SDimitry Andric __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL); 40110b57cec5SDimitry Andric if (ompt_frame->enter_frame.ptr == NULL) 40120b57cec5SDimitry Andric ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0); 40130b57cec5SDimitry Andric } 4014e8d8bef9SDimitry Andric OMPT_STORE_RETURN_ADDRESS(global_tid); 40150b57cec5SDimitry Andric #endif 40160b57cec5SDimitry Andric #if USE_ITT_NOTIFY 40170b57cec5SDimitry Andric __kmp_threads[global_tid]->th.th_ident = loc; 40180b57cec5SDimitry Andric #endif 40190b57cec5SDimitry Andric __kmp_barrier(bs_plain_barrier, global_tid, FALSE, 0, NULL, NULL); 40200b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 40210b57cec5SDimitry Andric if (ompt_enabled.enabled) { 40220b57cec5SDimitry Andric ompt_frame->enter_frame = ompt_data_none; 40230b57cec5SDimitry Andric } 40240b57cec5SDimitry Andric #endif 40250b57cec5SDimitry Andric 40260b57cec5SDimitry Andric } else if (packed_reduction_method == empty_reduce_block) { 40270b57cec5SDimitry Andric 4028480093f4SDimitry Andric OMPT_REDUCTION_END; 4029480093f4SDimitry Andric 40300b57cec5SDimitry Andric // usage: if team size==1, no synchronization is required (Intel platforms only) 40310b57cec5SDimitry Andric 40320b57cec5SDimitry Andric // TODO: implicit barrier: should be exposed 40330b57cec5SDimitry Andric #if OMPT_SUPPORT 40340b57cec5SDimitry Andric ompt_frame_t *ompt_frame; 40350b57cec5SDimitry Andric if (ompt_enabled.enabled) { 40360b57cec5SDimitry Andric __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL); 40370b57cec5SDimitry Andric if (ompt_frame->enter_frame.ptr == NULL) 40380b57cec5SDimitry Andric ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0); 40390b57cec5SDimitry Andric } 4040e8d8bef9SDimitry Andric OMPT_STORE_RETURN_ADDRESS(global_tid); 40410b57cec5SDimitry Andric #endif 40420b57cec5SDimitry Andric #if USE_ITT_NOTIFY 40430b57cec5SDimitry Andric __kmp_threads[global_tid]->th.th_ident = loc; 40440b57cec5SDimitry Andric #endif 40450b57cec5SDimitry Andric __kmp_barrier(bs_plain_barrier, global_tid, FALSE, 0, NULL, NULL); 40460b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 40470b57cec5SDimitry Andric if (ompt_enabled.enabled) { 40480b57cec5SDimitry Andric ompt_frame->enter_frame = ompt_data_none; 40490b57cec5SDimitry Andric } 40500b57cec5SDimitry Andric #endif 40510b57cec5SDimitry Andric 40520b57cec5SDimitry Andric } else if (packed_reduction_method == atomic_reduce_block) { 40530b57cec5SDimitry Andric 40540b57cec5SDimitry Andric #if OMPT_SUPPORT 40550b57cec5SDimitry Andric ompt_frame_t *ompt_frame; 40560b57cec5SDimitry Andric if (ompt_enabled.enabled) { 40570b57cec5SDimitry Andric __ompt_get_task_info_internal(0, NULL, NULL, &ompt_frame, NULL, NULL); 40580b57cec5SDimitry Andric if (ompt_frame->enter_frame.ptr == NULL) 40590b57cec5SDimitry Andric ompt_frame->enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0); 40600b57cec5SDimitry Andric } 4061e8d8bef9SDimitry Andric OMPT_STORE_RETURN_ADDRESS(global_tid); 40620b57cec5SDimitry Andric #endif 40630b57cec5SDimitry Andric // TODO: implicit barrier: should be exposed 40640b57cec5SDimitry Andric #if USE_ITT_NOTIFY 40650b57cec5SDimitry Andric __kmp_threads[global_tid]->th.th_ident = loc; 40660b57cec5SDimitry Andric #endif 40670b57cec5SDimitry Andric __kmp_barrier(bs_plain_barrier, global_tid, FALSE, 0, NULL, NULL); 40680b57cec5SDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 40690b57cec5SDimitry Andric if (ompt_enabled.enabled) { 40700b57cec5SDimitry Andric ompt_frame->enter_frame = ompt_data_none; 40710b57cec5SDimitry Andric } 40720b57cec5SDimitry Andric #endif 40730b57cec5SDimitry Andric 40740b57cec5SDimitry Andric } else if (TEST_REDUCTION_METHOD(packed_reduction_method, 40750b57cec5SDimitry Andric tree_reduce_block)) { 40760b57cec5SDimitry Andric 4077fe6060f1SDimitry Andric // only primary thread executes here (primary releases all other workers) 40780b57cec5SDimitry Andric __kmp_end_split_barrier(UNPACK_REDUCTION_BARRIER(packed_reduction_method), 40790b57cec5SDimitry Andric global_tid); 40800b57cec5SDimitry Andric 40810b57cec5SDimitry Andric } else { 40820b57cec5SDimitry Andric 40830b57cec5SDimitry Andric // should never reach this block 40840b57cec5SDimitry Andric KMP_ASSERT(0); // "unexpected method" 40850b57cec5SDimitry Andric } 40860b57cec5SDimitry Andric if (teams_swapped) { 40870b57cec5SDimitry Andric __kmp_restore_swapped_teams(th, team, task_state); 40880b57cec5SDimitry Andric } 40890b57cec5SDimitry Andric 40900b57cec5SDimitry Andric if (__kmp_env_consistency_check) 40910b57cec5SDimitry Andric __kmp_pop_sync(global_tid, ct_reduce, loc); 40920b57cec5SDimitry Andric 40930b57cec5SDimitry Andric KA_TRACE(10, ("__kmpc_end_reduce() exit: called T#%d: method %08x\n", 40940b57cec5SDimitry Andric global_tid, packed_reduction_method)); 40950b57cec5SDimitry Andric 40960b57cec5SDimitry Andric return; 40970b57cec5SDimitry Andric } 40980b57cec5SDimitry Andric 40990b57cec5SDimitry Andric #undef __KMP_GET_REDUCTION_METHOD 41000b57cec5SDimitry Andric #undef __KMP_SET_REDUCTION_METHOD 41010b57cec5SDimitry Andric 41020b57cec5SDimitry Andric /* end of interface to fast scalable reduce routines */ 41030b57cec5SDimitry Andric 41040b57cec5SDimitry Andric kmp_uint64 __kmpc_get_taskid() { 41050b57cec5SDimitry Andric 41060b57cec5SDimitry Andric kmp_int32 gtid; 41070b57cec5SDimitry Andric kmp_info_t *thread; 41080b57cec5SDimitry Andric 41090b57cec5SDimitry Andric gtid = __kmp_get_gtid(); 41100b57cec5SDimitry Andric if (gtid < 0) { 41110b57cec5SDimitry Andric return 0; 41120b57cec5SDimitry Andric } 41130b57cec5SDimitry Andric thread = __kmp_thread_from_gtid(gtid); 41140b57cec5SDimitry Andric return thread->th.th_current_task->td_task_id; 41150b57cec5SDimitry Andric 41160b57cec5SDimitry Andric } // __kmpc_get_taskid 41170b57cec5SDimitry Andric 41180b57cec5SDimitry Andric kmp_uint64 __kmpc_get_parent_taskid() { 41190b57cec5SDimitry Andric 41200b57cec5SDimitry Andric kmp_int32 gtid; 41210b57cec5SDimitry Andric kmp_info_t *thread; 41220b57cec5SDimitry Andric kmp_taskdata_t *parent_task; 41230b57cec5SDimitry Andric 41240b57cec5SDimitry Andric gtid = __kmp_get_gtid(); 41250b57cec5SDimitry Andric if (gtid < 0) { 41260b57cec5SDimitry Andric return 0; 41270b57cec5SDimitry Andric } 41280b57cec5SDimitry Andric thread = __kmp_thread_from_gtid(gtid); 41290b57cec5SDimitry Andric parent_task = thread->th.th_current_task->td_parent; 41300b57cec5SDimitry Andric return (parent_task == NULL ? 0 : parent_task->td_task_id); 41310b57cec5SDimitry Andric 41320b57cec5SDimitry Andric } // __kmpc_get_parent_taskid 41330b57cec5SDimitry Andric 41340b57cec5SDimitry Andric /*! 41350b57cec5SDimitry Andric @ingroup WORK_SHARING 41360b57cec5SDimitry Andric @param loc source location information. 41370b57cec5SDimitry Andric @param gtid global thread number. 41380b57cec5SDimitry Andric @param num_dims number of associated doacross loops. 41390b57cec5SDimitry Andric @param dims info on loops bounds. 41400b57cec5SDimitry Andric 41410b57cec5SDimitry Andric Initialize doacross loop information. 41420b57cec5SDimitry Andric Expect compiler send us inclusive bounds, 41430b57cec5SDimitry Andric e.g. for(i=2;i<9;i+=2) lo=2, up=8, st=2. 41440b57cec5SDimitry Andric */ 41450b57cec5SDimitry Andric void __kmpc_doacross_init(ident_t *loc, int gtid, int num_dims, 41460b57cec5SDimitry Andric const struct kmp_dim *dims) { 4147e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(gtid); 41480b57cec5SDimitry Andric int j, idx; 41490b57cec5SDimitry Andric kmp_int64 last, trace_count; 41500b57cec5SDimitry Andric kmp_info_t *th = __kmp_threads[gtid]; 41510b57cec5SDimitry Andric kmp_team_t *team = th->th.th_team; 41520b57cec5SDimitry Andric kmp_uint32 *flags; 41530b57cec5SDimitry Andric kmp_disp_t *pr_buf = th->th.th_dispatch; 41540b57cec5SDimitry Andric dispatch_shared_info_t *sh_buf; 41550b57cec5SDimitry Andric 41560b57cec5SDimitry Andric KA_TRACE( 41570b57cec5SDimitry Andric 20, 41580b57cec5SDimitry Andric ("__kmpc_doacross_init() enter: called T#%d, num dims %d, active %d\n", 41590b57cec5SDimitry Andric gtid, num_dims, !team->t.t_serialized)); 41600b57cec5SDimitry Andric KMP_DEBUG_ASSERT(dims != NULL); 41610b57cec5SDimitry Andric KMP_DEBUG_ASSERT(num_dims > 0); 41620b57cec5SDimitry Andric 41630b57cec5SDimitry Andric if (team->t.t_serialized) { 41640b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_init() exit: serialized team\n")); 41650b57cec5SDimitry Andric return; // no dependencies if team is serialized 41660b57cec5SDimitry Andric } 41670b57cec5SDimitry Andric KMP_DEBUG_ASSERT(team->t.t_nproc > 1); 41680b57cec5SDimitry Andric idx = pr_buf->th_doacross_buf_idx++; // Increment index of shared buffer for 41690b57cec5SDimitry Andric // the next loop 41700b57cec5SDimitry Andric sh_buf = &team->t.t_disp_buffer[idx % __kmp_dispatch_num_buffers]; 41710b57cec5SDimitry Andric 41720b57cec5SDimitry Andric // Save bounds info into allocated private buffer 41730b57cec5SDimitry Andric KMP_DEBUG_ASSERT(pr_buf->th_doacross_info == NULL); 41740b57cec5SDimitry Andric pr_buf->th_doacross_info = (kmp_int64 *)__kmp_thread_malloc( 41750b57cec5SDimitry Andric th, sizeof(kmp_int64) * (4 * num_dims + 1)); 41760b57cec5SDimitry Andric KMP_DEBUG_ASSERT(pr_buf->th_doacross_info != NULL); 41770b57cec5SDimitry Andric pr_buf->th_doacross_info[0] = 41780b57cec5SDimitry Andric (kmp_int64)num_dims; // first element is number of dimensions 41790b57cec5SDimitry Andric // Save also address of num_done in order to access it later without knowing 41800b57cec5SDimitry Andric // the buffer index 41810b57cec5SDimitry Andric pr_buf->th_doacross_info[1] = (kmp_int64)&sh_buf->doacross_num_done; 41820b57cec5SDimitry Andric pr_buf->th_doacross_info[2] = dims[0].lo; 41830b57cec5SDimitry Andric pr_buf->th_doacross_info[3] = dims[0].up; 41840b57cec5SDimitry Andric pr_buf->th_doacross_info[4] = dims[0].st; 41850b57cec5SDimitry Andric last = 5; 41860b57cec5SDimitry Andric for (j = 1; j < num_dims; ++j) { 41870b57cec5SDimitry Andric kmp_int64 41880b57cec5SDimitry Andric range_length; // To keep ranges of all dimensions but the first dims[0] 41890b57cec5SDimitry Andric if (dims[j].st == 1) { // most common case 41900b57cec5SDimitry Andric // AC: should we care of ranges bigger than LLONG_MAX? (not for now) 41910b57cec5SDimitry Andric range_length = dims[j].up - dims[j].lo + 1; 41920b57cec5SDimitry Andric } else { 41930b57cec5SDimitry Andric if (dims[j].st > 0) { 41940b57cec5SDimitry Andric KMP_DEBUG_ASSERT(dims[j].up > dims[j].lo); 41950b57cec5SDimitry Andric range_length = (kmp_uint64)(dims[j].up - dims[j].lo) / dims[j].st + 1; 41960b57cec5SDimitry Andric } else { // negative increment 41970b57cec5SDimitry Andric KMP_DEBUG_ASSERT(dims[j].lo > dims[j].up); 41980b57cec5SDimitry Andric range_length = 41990b57cec5SDimitry Andric (kmp_uint64)(dims[j].lo - dims[j].up) / (-dims[j].st) + 1; 42000b57cec5SDimitry Andric } 42010b57cec5SDimitry Andric } 42020b57cec5SDimitry Andric pr_buf->th_doacross_info[last++] = range_length; 42030b57cec5SDimitry Andric pr_buf->th_doacross_info[last++] = dims[j].lo; 42040b57cec5SDimitry Andric pr_buf->th_doacross_info[last++] = dims[j].up; 42050b57cec5SDimitry Andric pr_buf->th_doacross_info[last++] = dims[j].st; 42060b57cec5SDimitry Andric } 42070b57cec5SDimitry Andric 42080b57cec5SDimitry Andric // Compute total trip count. 42090b57cec5SDimitry Andric // Start with range of dims[0] which we don't need to keep in the buffer. 42100b57cec5SDimitry Andric if (dims[0].st == 1) { // most common case 42110b57cec5SDimitry Andric trace_count = dims[0].up - dims[0].lo + 1; 42120b57cec5SDimitry Andric } else if (dims[0].st > 0) { 42130b57cec5SDimitry Andric KMP_DEBUG_ASSERT(dims[0].up > dims[0].lo); 42140b57cec5SDimitry Andric trace_count = (kmp_uint64)(dims[0].up - dims[0].lo) / dims[0].st + 1; 42150b57cec5SDimitry Andric } else { // negative increment 42160b57cec5SDimitry Andric KMP_DEBUG_ASSERT(dims[0].lo > dims[0].up); 42170b57cec5SDimitry Andric trace_count = (kmp_uint64)(dims[0].lo - dims[0].up) / (-dims[0].st) + 1; 42180b57cec5SDimitry Andric } 42190b57cec5SDimitry Andric for (j = 1; j < num_dims; ++j) { 42200b57cec5SDimitry Andric trace_count *= pr_buf->th_doacross_info[4 * j + 1]; // use kept ranges 42210b57cec5SDimitry Andric } 42220b57cec5SDimitry Andric KMP_DEBUG_ASSERT(trace_count > 0); 42230b57cec5SDimitry Andric 42240b57cec5SDimitry Andric // Check if shared buffer is not occupied by other loop (idx - 42250b57cec5SDimitry Andric // __kmp_dispatch_num_buffers) 42260b57cec5SDimitry Andric if (idx != sh_buf->doacross_buf_idx) { 42270b57cec5SDimitry Andric // Shared buffer is occupied, wait for it to be free 42280b57cec5SDimitry Andric __kmp_wait_4((volatile kmp_uint32 *)&sh_buf->doacross_buf_idx, idx, 42290b57cec5SDimitry Andric __kmp_eq_4, NULL); 42300b57cec5SDimitry Andric } 42310b57cec5SDimitry Andric #if KMP_32_BIT_ARCH 42320b57cec5SDimitry Andric // Check if we are the first thread. After the CAS the first thread gets 0, 42330b57cec5SDimitry Andric // others get 1 if initialization is in progress, allocated pointer otherwise. 42340b57cec5SDimitry Andric // Treat pointer as volatile integer (value 0 or 1) until memory is allocated. 42350b57cec5SDimitry Andric flags = (kmp_uint32 *)KMP_COMPARE_AND_STORE_RET32( 42360b57cec5SDimitry Andric (volatile kmp_int32 *)&sh_buf->doacross_flags, NULL, 1); 42370b57cec5SDimitry Andric #else 42380b57cec5SDimitry Andric flags = (kmp_uint32 *)KMP_COMPARE_AND_STORE_RET64( 42390b57cec5SDimitry Andric (volatile kmp_int64 *)&sh_buf->doacross_flags, NULL, 1LL); 42400b57cec5SDimitry Andric #endif 42410b57cec5SDimitry Andric if (flags == NULL) { 42420b57cec5SDimitry Andric // we are the first thread, allocate the array of flags 4243e8d8bef9SDimitry Andric size_t size = 4244e8d8bef9SDimitry Andric (size_t)trace_count / 8 + 8; // in bytes, use single bit per iteration 42450b57cec5SDimitry Andric flags = (kmp_uint32 *)__kmp_thread_calloc(th, size, 1); 42460b57cec5SDimitry Andric KMP_MB(); 42470b57cec5SDimitry Andric sh_buf->doacross_flags = flags; 42480b57cec5SDimitry Andric } else if (flags == (kmp_uint32 *)1) { 42490b57cec5SDimitry Andric #if KMP_32_BIT_ARCH 42500b57cec5SDimitry Andric // initialization is still in progress, need to wait 42510b57cec5SDimitry Andric while (*(volatile kmp_int32 *)&sh_buf->doacross_flags == 1) 42520b57cec5SDimitry Andric #else 42530b57cec5SDimitry Andric while (*(volatile kmp_int64 *)&sh_buf->doacross_flags == 1LL) 42540b57cec5SDimitry Andric #endif 42550b57cec5SDimitry Andric KMP_YIELD(TRUE); 42560b57cec5SDimitry Andric KMP_MB(); 42570b57cec5SDimitry Andric } else { 42580b57cec5SDimitry Andric KMP_MB(); 42590b57cec5SDimitry Andric } 42600b57cec5SDimitry Andric KMP_DEBUG_ASSERT(sh_buf->doacross_flags > (kmp_uint32 *)1); // check ptr value 42610b57cec5SDimitry Andric pr_buf->th_doacross_flags = 42620b57cec5SDimitry Andric sh_buf->doacross_flags; // save private copy in order to not 42630b57cec5SDimitry Andric // touch shared buffer on each iteration 42640b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_init() exit: T#%d\n", gtid)); 42650b57cec5SDimitry Andric } 42660b57cec5SDimitry Andric 42670b57cec5SDimitry Andric void __kmpc_doacross_wait(ident_t *loc, int gtid, const kmp_int64 *vec) { 4268e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(gtid); 4269e8d8bef9SDimitry Andric kmp_int64 shft; 4270e8d8bef9SDimitry Andric size_t num_dims, i; 42710b57cec5SDimitry Andric kmp_uint32 flag; 42720b57cec5SDimitry Andric kmp_int64 iter_number; // iteration number of "collapsed" loop nest 42730b57cec5SDimitry Andric kmp_info_t *th = __kmp_threads[gtid]; 42740b57cec5SDimitry Andric kmp_team_t *team = th->th.th_team; 42750b57cec5SDimitry Andric kmp_disp_t *pr_buf; 42760b57cec5SDimitry Andric kmp_int64 lo, up, st; 42770b57cec5SDimitry Andric 42780b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_wait() enter: called T#%d\n", gtid)); 42790b57cec5SDimitry Andric if (team->t.t_serialized) { 42800b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_wait() exit: serialized team\n")); 42810b57cec5SDimitry Andric return; // no dependencies if team is serialized 42820b57cec5SDimitry Andric } 42830b57cec5SDimitry Andric 42840b57cec5SDimitry Andric // calculate sequential iteration number and check out-of-bounds condition 42850b57cec5SDimitry Andric pr_buf = th->th.th_dispatch; 42860b57cec5SDimitry Andric KMP_DEBUG_ASSERT(pr_buf->th_doacross_info != NULL); 4287e8d8bef9SDimitry Andric num_dims = (size_t)pr_buf->th_doacross_info[0]; 42880b57cec5SDimitry Andric lo = pr_buf->th_doacross_info[2]; 42890b57cec5SDimitry Andric up = pr_buf->th_doacross_info[3]; 42900b57cec5SDimitry Andric st = pr_buf->th_doacross_info[4]; 42915ffd83dbSDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 4292*0fca6ea1SDimitry Andric SimpleVLA<ompt_dependence_t> deps(num_dims); 42935ffd83dbSDimitry Andric #endif 42940b57cec5SDimitry Andric if (st == 1) { // most common case 42950b57cec5SDimitry Andric if (vec[0] < lo || vec[0] > up) { 42960b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_wait() exit: T#%d iter %lld is out of " 42970b57cec5SDimitry Andric "bounds [%lld,%lld]\n", 42980b57cec5SDimitry Andric gtid, vec[0], lo, up)); 42990b57cec5SDimitry Andric return; 43000b57cec5SDimitry Andric } 43010b57cec5SDimitry Andric iter_number = vec[0] - lo; 43020b57cec5SDimitry Andric } else if (st > 0) { 43030b57cec5SDimitry Andric if (vec[0] < lo || vec[0] > up) { 43040b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_wait() exit: T#%d iter %lld is out of " 43050b57cec5SDimitry Andric "bounds [%lld,%lld]\n", 43060b57cec5SDimitry Andric gtid, vec[0], lo, up)); 43070b57cec5SDimitry Andric return; 43080b57cec5SDimitry Andric } 43090b57cec5SDimitry Andric iter_number = (kmp_uint64)(vec[0] - lo) / st; 43100b57cec5SDimitry Andric } else { // negative increment 43110b57cec5SDimitry Andric if (vec[0] > lo || vec[0] < up) { 43120b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_wait() exit: T#%d iter %lld is out of " 43130b57cec5SDimitry Andric "bounds [%lld,%lld]\n", 43140b57cec5SDimitry Andric gtid, vec[0], lo, up)); 43150b57cec5SDimitry Andric return; 43160b57cec5SDimitry Andric } 43170b57cec5SDimitry Andric iter_number = (kmp_uint64)(lo - vec[0]) / (-st); 43180b57cec5SDimitry Andric } 43195ffd83dbSDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 43205ffd83dbSDimitry Andric deps[0].variable.value = iter_number; 43215ffd83dbSDimitry Andric deps[0].dependence_type = ompt_dependence_type_sink; 43225ffd83dbSDimitry Andric #endif 43230b57cec5SDimitry Andric for (i = 1; i < num_dims; ++i) { 43240b57cec5SDimitry Andric kmp_int64 iter, ln; 4325e8d8bef9SDimitry Andric size_t j = i * 4; 43260b57cec5SDimitry Andric ln = pr_buf->th_doacross_info[j + 1]; 43270b57cec5SDimitry Andric lo = pr_buf->th_doacross_info[j + 2]; 43280b57cec5SDimitry Andric up = pr_buf->th_doacross_info[j + 3]; 43290b57cec5SDimitry Andric st = pr_buf->th_doacross_info[j + 4]; 43300b57cec5SDimitry Andric if (st == 1) { 43310b57cec5SDimitry Andric if (vec[i] < lo || vec[i] > up) { 43320b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_wait() exit: T#%d iter %lld is out of " 43330b57cec5SDimitry Andric "bounds [%lld,%lld]\n", 43340b57cec5SDimitry Andric gtid, vec[i], lo, up)); 43350b57cec5SDimitry Andric return; 43360b57cec5SDimitry Andric } 43370b57cec5SDimitry Andric iter = vec[i] - lo; 43380b57cec5SDimitry Andric } else if (st > 0) { 43390b57cec5SDimitry Andric if (vec[i] < lo || vec[i] > up) { 43400b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_wait() exit: T#%d iter %lld is out of " 43410b57cec5SDimitry Andric "bounds [%lld,%lld]\n", 43420b57cec5SDimitry Andric gtid, vec[i], lo, up)); 43430b57cec5SDimitry Andric return; 43440b57cec5SDimitry Andric } 43450b57cec5SDimitry Andric iter = (kmp_uint64)(vec[i] - lo) / st; 43460b57cec5SDimitry Andric } else { // st < 0 43470b57cec5SDimitry Andric if (vec[i] > lo || vec[i] < up) { 43480b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_wait() exit: T#%d iter %lld is out of " 43490b57cec5SDimitry Andric "bounds [%lld,%lld]\n", 43500b57cec5SDimitry Andric gtid, vec[i], lo, up)); 43510b57cec5SDimitry Andric return; 43520b57cec5SDimitry Andric } 43530b57cec5SDimitry Andric iter = (kmp_uint64)(lo - vec[i]) / (-st); 43540b57cec5SDimitry Andric } 43550b57cec5SDimitry Andric iter_number = iter + ln * iter_number; 43565ffd83dbSDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 43575ffd83dbSDimitry Andric deps[i].variable.value = iter; 43585ffd83dbSDimitry Andric deps[i].dependence_type = ompt_dependence_type_sink; 43595ffd83dbSDimitry Andric #endif 43600b57cec5SDimitry Andric } 43610b57cec5SDimitry Andric shft = iter_number % 32; // use 32-bit granularity 43620b57cec5SDimitry Andric iter_number >>= 5; // divided by 32 43630b57cec5SDimitry Andric flag = 1 << shft; 43640b57cec5SDimitry Andric while ((flag & pr_buf->th_doacross_flags[iter_number]) == 0) { 43650b57cec5SDimitry Andric KMP_YIELD(TRUE); 43660b57cec5SDimitry Andric } 43670b57cec5SDimitry Andric KMP_MB(); 43685ffd83dbSDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 43695ffd83dbSDimitry Andric if (ompt_enabled.ompt_callback_dependences) { 43705ffd83dbSDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_dependences)( 4371e8d8bef9SDimitry Andric &(OMPT_CUR_TASK_INFO(th)->task_data), deps, (kmp_uint32)num_dims); 43725ffd83dbSDimitry Andric } 43735ffd83dbSDimitry Andric #endif 43740b57cec5SDimitry Andric KA_TRACE(20, 43750b57cec5SDimitry Andric ("__kmpc_doacross_wait() exit: T#%d wait for iter %lld completed\n", 43760b57cec5SDimitry Andric gtid, (iter_number << 5) + shft)); 43770b57cec5SDimitry Andric } 43780b57cec5SDimitry Andric 43790b57cec5SDimitry Andric void __kmpc_doacross_post(ident_t *loc, int gtid, const kmp_int64 *vec) { 4380e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(gtid); 4381e8d8bef9SDimitry Andric kmp_int64 shft; 4382e8d8bef9SDimitry Andric size_t num_dims, i; 43830b57cec5SDimitry Andric kmp_uint32 flag; 43840b57cec5SDimitry Andric kmp_int64 iter_number; // iteration number of "collapsed" loop nest 43850b57cec5SDimitry Andric kmp_info_t *th = __kmp_threads[gtid]; 43860b57cec5SDimitry Andric kmp_team_t *team = th->th.th_team; 43870b57cec5SDimitry Andric kmp_disp_t *pr_buf; 43880b57cec5SDimitry Andric kmp_int64 lo, st; 43890b57cec5SDimitry Andric 43900b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_post() enter: called T#%d\n", gtid)); 43910b57cec5SDimitry Andric if (team->t.t_serialized) { 43920b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_post() exit: serialized team\n")); 43930b57cec5SDimitry Andric return; // no dependencies if team is serialized 43940b57cec5SDimitry Andric } 43950b57cec5SDimitry Andric 43960b57cec5SDimitry Andric // calculate sequential iteration number (same as in "wait" but no 43970b57cec5SDimitry Andric // out-of-bounds checks) 43980b57cec5SDimitry Andric pr_buf = th->th.th_dispatch; 43990b57cec5SDimitry Andric KMP_DEBUG_ASSERT(pr_buf->th_doacross_info != NULL); 4400e8d8bef9SDimitry Andric num_dims = (size_t)pr_buf->th_doacross_info[0]; 44010b57cec5SDimitry Andric lo = pr_buf->th_doacross_info[2]; 44020b57cec5SDimitry Andric st = pr_buf->th_doacross_info[4]; 44035ffd83dbSDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 4404*0fca6ea1SDimitry Andric SimpleVLA<ompt_dependence_t> deps(num_dims); 44055ffd83dbSDimitry Andric #endif 44060b57cec5SDimitry Andric if (st == 1) { // most common case 44070b57cec5SDimitry Andric iter_number = vec[0] - lo; 44080b57cec5SDimitry Andric } else if (st > 0) { 44090b57cec5SDimitry Andric iter_number = (kmp_uint64)(vec[0] - lo) / st; 44100b57cec5SDimitry Andric } else { // negative increment 44110b57cec5SDimitry Andric iter_number = (kmp_uint64)(lo - vec[0]) / (-st); 44120b57cec5SDimitry Andric } 44135ffd83dbSDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 44145ffd83dbSDimitry Andric deps[0].variable.value = iter_number; 44155ffd83dbSDimitry Andric deps[0].dependence_type = ompt_dependence_type_source; 44165ffd83dbSDimitry Andric #endif 44170b57cec5SDimitry Andric for (i = 1; i < num_dims; ++i) { 44180b57cec5SDimitry Andric kmp_int64 iter, ln; 4419e8d8bef9SDimitry Andric size_t j = i * 4; 44200b57cec5SDimitry Andric ln = pr_buf->th_doacross_info[j + 1]; 44210b57cec5SDimitry Andric lo = pr_buf->th_doacross_info[j + 2]; 44220b57cec5SDimitry Andric st = pr_buf->th_doacross_info[j + 4]; 44230b57cec5SDimitry Andric if (st == 1) { 44240b57cec5SDimitry Andric iter = vec[i] - lo; 44250b57cec5SDimitry Andric } else if (st > 0) { 44260b57cec5SDimitry Andric iter = (kmp_uint64)(vec[i] - lo) / st; 44270b57cec5SDimitry Andric } else { // st < 0 44280b57cec5SDimitry Andric iter = (kmp_uint64)(lo - vec[i]) / (-st); 44290b57cec5SDimitry Andric } 44300b57cec5SDimitry Andric iter_number = iter + ln * iter_number; 44315ffd83dbSDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 44325ffd83dbSDimitry Andric deps[i].variable.value = iter; 44335ffd83dbSDimitry Andric deps[i].dependence_type = ompt_dependence_type_source; 44345ffd83dbSDimitry Andric #endif 44350b57cec5SDimitry Andric } 44365ffd83dbSDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 44375ffd83dbSDimitry Andric if (ompt_enabled.ompt_callback_dependences) { 44385ffd83dbSDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_dependences)( 4439e8d8bef9SDimitry Andric &(OMPT_CUR_TASK_INFO(th)->task_data), deps, (kmp_uint32)num_dims); 44405ffd83dbSDimitry Andric } 44415ffd83dbSDimitry Andric #endif 44420b57cec5SDimitry Andric shft = iter_number % 32; // use 32-bit granularity 44430b57cec5SDimitry Andric iter_number >>= 5; // divided by 32 44440b57cec5SDimitry Andric flag = 1 << shft; 44450b57cec5SDimitry Andric KMP_MB(); 44460b57cec5SDimitry Andric if ((flag & pr_buf->th_doacross_flags[iter_number]) == 0) 44470b57cec5SDimitry Andric KMP_TEST_THEN_OR32(&pr_buf->th_doacross_flags[iter_number], flag); 44480b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_post() exit: T#%d iter %lld posted\n", gtid, 44490b57cec5SDimitry Andric (iter_number << 5) + shft)); 44500b57cec5SDimitry Andric } 44510b57cec5SDimitry Andric 44520b57cec5SDimitry Andric void __kmpc_doacross_fini(ident_t *loc, int gtid) { 4453e8d8bef9SDimitry Andric __kmp_assert_valid_gtid(gtid); 44540b57cec5SDimitry Andric kmp_int32 num_done; 44550b57cec5SDimitry Andric kmp_info_t *th = __kmp_threads[gtid]; 44560b57cec5SDimitry Andric kmp_team_t *team = th->th.th_team; 44570b57cec5SDimitry Andric kmp_disp_t *pr_buf = th->th.th_dispatch; 44580b57cec5SDimitry Andric 44590b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_fini() enter: called T#%d\n", gtid)); 44600b57cec5SDimitry Andric if (team->t.t_serialized) { 44610b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_fini() exit: serialized team %p\n", team)); 44620b57cec5SDimitry Andric return; // nothing to do 44630b57cec5SDimitry Andric } 4464e8d8bef9SDimitry Andric num_done = 4465e8d8bef9SDimitry Andric KMP_TEST_THEN_INC32((kmp_uintptr_t)(pr_buf->th_doacross_info[1])) + 1; 44660b57cec5SDimitry Andric if (num_done == th->th.th_team_nproc) { 44670b57cec5SDimitry Andric // we are the last thread, need to free shared resources 44680b57cec5SDimitry Andric int idx = pr_buf->th_doacross_buf_idx - 1; 44690b57cec5SDimitry Andric dispatch_shared_info_t *sh_buf = 44700b57cec5SDimitry Andric &team->t.t_disp_buffer[idx % __kmp_dispatch_num_buffers]; 44710b57cec5SDimitry Andric KMP_DEBUG_ASSERT(pr_buf->th_doacross_info[1] == 44720b57cec5SDimitry Andric (kmp_int64)&sh_buf->doacross_num_done); 44730b57cec5SDimitry Andric KMP_DEBUG_ASSERT(num_done == sh_buf->doacross_num_done); 44740b57cec5SDimitry Andric KMP_DEBUG_ASSERT(idx == sh_buf->doacross_buf_idx); 44750b57cec5SDimitry Andric __kmp_thread_free(th, CCAST(kmp_uint32 *, sh_buf->doacross_flags)); 44760b57cec5SDimitry Andric sh_buf->doacross_flags = NULL; 44770b57cec5SDimitry Andric sh_buf->doacross_num_done = 0; 44780b57cec5SDimitry Andric sh_buf->doacross_buf_idx += 44790b57cec5SDimitry Andric __kmp_dispatch_num_buffers; // free buffer for future re-use 44800b57cec5SDimitry Andric } 44810b57cec5SDimitry Andric // free private resources (need to keep buffer index forever) 44820b57cec5SDimitry Andric pr_buf->th_doacross_flags = NULL; 44830b57cec5SDimitry Andric __kmp_thread_free(th, (void *)pr_buf->th_doacross_info); 44840b57cec5SDimitry Andric pr_buf->th_doacross_info = NULL; 44850b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_doacross_fini() exit: T#%d\n", gtid)); 44860b57cec5SDimitry Andric } 44870b57cec5SDimitry Andric 4488349cc55cSDimitry Andric /* OpenMP 5.1 Memory Management routines */ 44890b57cec5SDimitry Andric void *omp_alloc(size_t size, omp_allocator_handle_t allocator) { 4490349cc55cSDimitry Andric return __kmp_alloc(__kmp_entry_gtid(), 0, size, allocator); 4491349cc55cSDimitry Andric } 4492349cc55cSDimitry Andric 4493349cc55cSDimitry Andric void *omp_aligned_alloc(size_t align, size_t size, 4494349cc55cSDimitry Andric omp_allocator_handle_t allocator) { 4495349cc55cSDimitry Andric return __kmp_alloc(__kmp_entry_gtid(), align, size, allocator); 44960b57cec5SDimitry Andric } 44970b57cec5SDimitry Andric 4498e8d8bef9SDimitry Andric void *omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t allocator) { 4499349cc55cSDimitry Andric return __kmp_calloc(__kmp_entry_gtid(), 0, nmemb, size, allocator); 4500349cc55cSDimitry Andric } 4501349cc55cSDimitry Andric 4502349cc55cSDimitry Andric void *omp_aligned_calloc(size_t align, size_t nmemb, size_t size, 4503349cc55cSDimitry Andric omp_allocator_handle_t allocator) { 4504349cc55cSDimitry Andric return __kmp_calloc(__kmp_entry_gtid(), align, nmemb, size, allocator); 4505e8d8bef9SDimitry Andric } 4506e8d8bef9SDimitry Andric 4507e8d8bef9SDimitry Andric void *omp_realloc(void *ptr, size_t size, omp_allocator_handle_t allocator, 4508e8d8bef9SDimitry Andric omp_allocator_handle_t free_allocator) { 4509349cc55cSDimitry Andric return __kmp_realloc(__kmp_entry_gtid(), ptr, size, allocator, 4510e8d8bef9SDimitry Andric free_allocator); 4511e8d8bef9SDimitry Andric } 4512e8d8bef9SDimitry Andric 45130b57cec5SDimitry Andric void omp_free(void *ptr, omp_allocator_handle_t allocator) { 4514349cc55cSDimitry Andric ___kmpc_free(__kmp_entry_gtid(), ptr, allocator); 45150b57cec5SDimitry Andric } 4516349cc55cSDimitry Andric /* end of OpenMP 5.1 Memory Management routines */ 45170b57cec5SDimitry Andric 45180b57cec5SDimitry Andric int __kmpc_get_target_offload(void) { 45190b57cec5SDimitry Andric if (!__kmp_init_serial) { 45200b57cec5SDimitry Andric __kmp_serial_initialize(); 45210b57cec5SDimitry Andric } 45220b57cec5SDimitry Andric return __kmp_target_offload; 45230b57cec5SDimitry Andric } 45240b57cec5SDimitry Andric 45250b57cec5SDimitry Andric int __kmpc_pause_resource(kmp_pause_status_t level) { 45260b57cec5SDimitry Andric if (!__kmp_init_serial) { 45270b57cec5SDimitry Andric return 1; // Can't pause if runtime is not initialized 45280b57cec5SDimitry Andric } 45290b57cec5SDimitry Andric return __kmp_pause_resource(level); 45300b57cec5SDimitry Andric } 4531fe6060f1SDimitry Andric 4532fe6060f1SDimitry Andric void __kmpc_error(ident_t *loc, int severity, const char *message) { 4533fe6060f1SDimitry Andric if (!__kmp_init_serial) 4534fe6060f1SDimitry Andric __kmp_serial_initialize(); 4535fe6060f1SDimitry Andric 4536fe6060f1SDimitry Andric KMP_ASSERT(severity == severity_warning || severity == severity_fatal); 4537fe6060f1SDimitry Andric 4538fe6060f1SDimitry Andric #if OMPT_SUPPORT 4539fe6060f1SDimitry Andric if (ompt_enabled.enabled && ompt_enabled.ompt_callback_error) { 4540fe6060f1SDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_error)( 4541fe6060f1SDimitry Andric (ompt_severity_t)severity, message, KMP_STRLEN(message), 4542fe6060f1SDimitry Andric OMPT_GET_RETURN_ADDRESS(0)); 4543fe6060f1SDimitry Andric } 4544fe6060f1SDimitry Andric #endif // OMPT_SUPPORT 4545fe6060f1SDimitry Andric 4546fe6060f1SDimitry Andric char *src_loc; 4547fe6060f1SDimitry Andric if (loc && loc->psource) { 4548fe6060f1SDimitry Andric kmp_str_loc_t str_loc = __kmp_str_loc_init(loc->psource, false); 4549fe6060f1SDimitry Andric src_loc = 4550bdd1243dSDimitry Andric __kmp_str_format("%s:%d:%d", str_loc.file, str_loc.line, str_loc.col); 4551fe6060f1SDimitry Andric __kmp_str_loc_free(&str_loc); 4552fe6060f1SDimitry Andric } else { 4553fe6060f1SDimitry Andric src_loc = __kmp_str_format("unknown"); 4554fe6060f1SDimitry Andric } 4555fe6060f1SDimitry Andric 4556fe6060f1SDimitry Andric if (severity == severity_warning) 4557fe6060f1SDimitry Andric KMP_WARNING(UserDirectedWarning, src_loc, message); 4558fe6060f1SDimitry Andric else 4559fe6060f1SDimitry Andric KMP_FATAL(UserDirectedError, src_loc, message); 4560fe6060f1SDimitry Andric 4561fe6060f1SDimitry Andric __kmp_str_free(&src_loc); 4562fe6060f1SDimitry Andric } 4563fe6060f1SDimitry Andric 4564349cc55cSDimitry Andric // Mark begin of scope directive. 4565349cc55cSDimitry Andric void __kmpc_scope(ident_t *loc, kmp_int32 gtid, void *reserved) { 4566349cc55cSDimitry Andric // reserved is for extension of scope directive and not used. 4567349cc55cSDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 4568349cc55cSDimitry Andric if (ompt_enabled.enabled && ompt_enabled.ompt_callback_work) { 4569349cc55cSDimitry Andric kmp_team_t *team = __kmp_threads[gtid]->th.th_team; 4570349cc55cSDimitry Andric int tid = __kmp_tid_from_gtid(gtid); 4571349cc55cSDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_work)( 4572349cc55cSDimitry Andric ompt_work_scope, ompt_scope_begin, 4573349cc55cSDimitry Andric &(team->t.ompt_team_info.parallel_data), 4574349cc55cSDimitry Andric &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data), 1, 4575349cc55cSDimitry Andric OMPT_GET_RETURN_ADDRESS(0)); 4576349cc55cSDimitry Andric } 4577349cc55cSDimitry Andric #endif // OMPT_SUPPORT && OMPT_OPTIONAL 4578349cc55cSDimitry Andric } 4579349cc55cSDimitry Andric 4580349cc55cSDimitry Andric // Mark end of scope directive 4581349cc55cSDimitry Andric void __kmpc_end_scope(ident_t *loc, kmp_int32 gtid, void *reserved) { 4582349cc55cSDimitry Andric // reserved is for extension of scope directive and not used. 4583349cc55cSDimitry Andric #if OMPT_SUPPORT && OMPT_OPTIONAL 4584349cc55cSDimitry Andric if (ompt_enabled.enabled && ompt_enabled.ompt_callback_work) { 4585349cc55cSDimitry Andric kmp_team_t *team = __kmp_threads[gtid]->th.th_team; 4586349cc55cSDimitry Andric int tid = __kmp_tid_from_gtid(gtid); 4587349cc55cSDimitry Andric ompt_callbacks.ompt_callback(ompt_callback_work)( 4588349cc55cSDimitry Andric ompt_work_scope, ompt_scope_end, 4589349cc55cSDimitry Andric &(team->t.ompt_team_info.parallel_data), 4590349cc55cSDimitry Andric &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data), 1, 4591349cc55cSDimitry Andric OMPT_GET_RETURN_ADDRESS(0)); 4592349cc55cSDimitry Andric } 4593349cc55cSDimitry Andric #endif // OMPT_SUPPORT && OMPT_OPTIONAL 4594349cc55cSDimitry Andric } 4595349cc55cSDimitry Andric 4596fe6060f1SDimitry Andric #ifdef KMP_USE_VERSION_SYMBOLS 4597fe6060f1SDimitry Andric // For GOMP compatibility there are two versions of each omp_* API. 4598fe6060f1SDimitry Andric // One is the plain C symbol and one is the Fortran symbol with an appended 4599fe6060f1SDimitry Andric // underscore. When we implement a specific ompc_* version of an omp_* 4600fe6060f1SDimitry Andric // function, we want the plain GOMP versioned symbol to alias the ompc_* version 4601fe6060f1SDimitry Andric // instead of the Fortran versions in kmp_ftn_entry.h 4602fe6060f1SDimitry Andric extern "C" { 4603fe6060f1SDimitry Andric // Have to undef these from omp.h so they aren't translated into 4604fe6060f1SDimitry Andric // their ompc counterparts in the KMP_VERSION_OMPC_SYMBOL macros below 4605fe6060f1SDimitry Andric #ifdef omp_set_affinity_format 4606fe6060f1SDimitry Andric #undef omp_set_affinity_format 4607fe6060f1SDimitry Andric #endif 4608fe6060f1SDimitry Andric #ifdef omp_get_affinity_format 4609fe6060f1SDimitry Andric #undef omp_get_affinity_format 4610fe6060f1SDimitry Andric #endif 4611fe6060f1SDimitry Andric #ifdef omp_display_affinity 4612fe6060f1SDimitry Andric #undef omp_display_affinity 4613fe6060f1SDimitry Andric #endif 4614fe6060f1SDimitry Andric #ifdef omp_capture_affinity 4615fe6060f1SDimitry Andric #undef omp_capture_affinity 4616fe6060f1SDimitry Andric #endif 4617fe6060f1SDimitry Andric KMP_VERSION_OMPC_SYMBOL(ompc_set_affinity_format, omp_set_affinity_format, 50, 4618fe6060f1SDimitry Andric "OMP_5.0"); 4619fe6060f1SDimitry Andric KMP_VERSION_OMPC_SYMBOL(ompc_get_affinity_format, omp_get_affinity_format, 50, 4620fe6060f1SDimitry Andric "OMP_5.0"); 4621fe6060f1SDimitry Andric KMP_VERSION_OMPC_SYMBOL(ompc_display_affinity, omp_display_affinity, 50, 4622fe6060f1SDimitry Andric "OMP_5.0"); 4623fe6060f1SDimitry Andric KMP_VERSION_OMPC_SYMBOL(ompc_capture_affinity, omp_capture_affinity, 50, 4624fe6060f1SDimitry Andric "OMP_5.0"); 4625fe6060f1SDimitry Andric } // extern "C" 4626fe6060f1SDimitry Andric #endif 4627