10b57cec5SDimitry Andric /*
20b57cec5SDimitry Andric  * kmp_runtime.cpp -- KPTS runtime support library
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 #include "kmp.h"
140b57cec5SDimitry Andric #include "kmp_affinity.h"
150b57cec5SDimitry Andric #include "kmp_atomic.h"
160b57cec5SDimitry Andric #include "kmp_environment.h"
170b57cec5SDimitry Andric #include "kmp_error.h"
180b57cec5SDimitry Andric #include "kmp_i18n.h"
190b57cec5SDimitry Andric #include "kmp_io.h"
200b57cec5SDimitry Andric #include "kmp_itt.h"
210b57cec5SDimitry Andric #include "kmp_settings.h"
220b57cec5SDimitry Andric #include "kmp_stats.h"
230b57cec5SDimitry Andric #include "kmp_str.h"
240b57cec5SDimitry Andric #include "kmp_wait_release.h"
250b57cec5SDimitry Andric #include "kmp_wrapper_getpid.h"
260b57cec5SDimitry Andric #include "kmp_dispatch.h"
275f757f3fSDimitry Andric #include "kmp_utils.h"
280b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED
290b57cec5SDimitry Andric #include "kmp_dispatch_hier.h"
300b57cec5SDimitry Andric #endif
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric #if OMPT_SUPPORT
330b57cec5SDimitry Andric #include "ompt-specific.h"
340b57cec5SDimitry Andric #endif
35fe6060f1SDimitry Andric #if OMPD_SUPPORT
36fe6060f1SDimitry Andric #include "ompd-specific.h"
37fe6060f1SDimitry Andric #endif
380b57cec5SDimitry Andric 
39d409305fSDimitry Andric #if OMP_PROFILING_SUPPORT
40e8d8bef9SDimitry Andric #include "llvm/Support/TimeProfiler.h"
41e8d8bef9SDimitry Andric static char *ProfileTraceFile = nullptr;
42e8d8bef9SDimitry Andric #endif
43e8d8bef9SDimitry Andric 
440b57cec5SDimitry Andric /* these are temporary issues to be dealt with */
450b57cec5SDimitry Andric #define KMP_USE_PRCTL 0
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric #if KMP_OS_WINDOWS
480b57cec5SDimitry Andric #include <process.h>
490b57cec5SDimitry Andric #endif
500b57cec5SDimitry Andric 
515f757f3fSDimitry Andric #ifndef KMP_USE_SHM
525f757f3fSDimitry Andric // Windows and WASI do not need these include files as they don't use shared
535f757f3fSDimitry Andric // memory.
54e8d8bef9SDimitry Andric #else
55e8d8bef9SDimitry Andric #include <sys/mman.h>
56e8d8bef9SDimitry Andric #include <sys/stat.h>
57e8d8bef9SDimitry Andric #include <fcntl.h>
58e8d8bef9SDimitry Andric #define SHM_SIZE 1024
59e8d8bef9SDimitry Andric #endif
60e8d8bef9SDimitry Andric 
610b57cec5SDimitry Andric #if defined(KMP_GOMP_COMPAT)
620b57cec5SDimitry Andric char const __kmp_version_alt_comp[] =
630b57cec5SDimitry Andric     KMP_VERSION_PREFIX "alternative compiler support: yes";
640b57cec5SDimitry Andric #endif /* defined(KMP_GOMP_COMPAT) */
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric char const __kmp_version_omp_api[] =
670b57cec5SDimitry Andric     KMP_VERSION_PREFIX "API version: 5.0 (201611)";
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric #ifdef KMP_DEBUG
700b57cec5SDimitry Andric char const __kmp_version_lock[] =
710b57cec5SDimitry Andric     KMP_VERSION_PREFIX "lock type: run time selectable";
720b57cec5SDimitry Andric #endif /* KMP_DEBUG */
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric #define KMP_MIN(x, y) ((x) < (y) ? (x) : (y))
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric #if KMP_USE_MONITOR
790b57cec5SDimitry Andric kmp_info_t __kmp_monitor;
800b57cec5SDimitry Andric #endif
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric /* Forward declarations */
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric void __kmp_cleanup(void);
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric static void __kmp_initialize_info(kmp_info_t *, kmp_team_t *, int tid,
870b57cec5SDimitry Andric                                   int gtid);
880b57cec5SDimitry Andric static void __kmp_initialize_team(kmp_team_t *team, int new_nproc,
890b57cec5SDimitry Andric                                   kmp_internal_control_t *new_icvs,
900b57cec5SDimitry Andric                                   ident_t *loc);
910b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
920b57cec5SDimitry Andric static void __kmp_partition_places(kmp_team_t *team,
930b57cec5SDimitry Andric                                    int update_master_only = 0);
940b57cec5SDimitry Andric #endif
950b57cec5SDimitry Andric static void __kmp_do_serial_initialize(void);
960b57cec5SDimitry Andric void __kmp_fork_barrier(int gtid, int tid);
970b57cec5SDimitry Andric void __kmp_join_barrier(int gtid);
980b57cec5SDimitry Andric void __kmp_setup_icv_copy(kmp_team_t *team, int new_nproc,
990b57cec5SDimitry Andric                           kmp_internal_control_t *new_icvs, ident_t *loc);
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric #ifdef USE_LOAD_BALANCE
1020b57cec5SDimitry Andric static int __kmp_load_balance_nproc(kmp_root_t *root, int set_nproc);
1030b57cec5SDimitry Andric #endif
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric static int __kmp_expand_threads(int nNeed);
1060b57cec5SDimitry Andric #if KMP_OS_WINDOWS
1070b57cec5SDimitry Andric static int __kmp_unregister_root_other_thread(int gtid);
1080b57cec5SDimitry Andric #endif
1090b57cec5SDimitry Andric static void __kmp_reap_thread(kmp_info_t *thread, int is_root);
1100b57cec5SDimitry Andric kmp_info_t *__kmp_thread_pool_insert_pt = NULL;
1110b57cec5SDimitry Andric 
112349cc55cSDimitry Andric void __kmp_resize_dist_barrier(kmp_team_t *team, int old_nthreads,
113349cc55cSDimitry Andric                                int new_nthreads);
114349cc55cSDimitry Andric void __kmp_add_threads_to_team(kmp_team_t *team, int new_nthreads);
115349cc55cSDimitry Andric 
1160b57cec5SDimitry Andric /* Calculate the identifier of the current thread */
1170b57cec5SDimitry Andric /* fast (and somewhat portable) way to get unique identifier of executing
1180b57cec5SDimitry Andric    thread. Returns KMP_GTID_DNE if we haven't been assigned a gtid. */
__kmp_get_global_thread_id()1190b57cec5SDimitry Andric int __kmp_get_global_thread_id() {
1200b57cec5SDimitry Andric   int i;
1210b57cec5SDimitry Andric   kmp_info_t **other_threads;
1220b57cec5SDimitry Andric   size_t stack_data;
1230b57cec5SDimitry Andric   char *stack_addr;
1240b57cec5SDimitry Andric   size_t stack_size;
1250b57cec5SDimitry Andric   char *stack_base;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   KA_TRACE(
1280b57cec5SDimitry Andric       1000,
1290b57cec5SDimitry Andric       ("*** __kmp_get_global_thread_id: entering, nproc=%d  all_nproc=%d\n",
1300b57cec5SDimitry Andric        __kmp_nth, __kmp_all_nth));
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   /* JPH - to handle the case where __kmpc_end(0) is called immediately prior to
1330b57cec5SDimitry Andric      a parallel region, made it return KMP_GTID_DNE to force serial_initialize
1340b57cec5SDimitry Andric      by caller. Had to handle KMP_GTID_DNE at all call-sites, or else guarantee
1350b57cec5SDimitry Andric      __kmp_init_gtid for this to work. */
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   if (!TCR_4(__kmp_init_gtid))
1380b57cec5SDimitry Andric     return KMP_GTID_DNE;
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric #ifdef KMP_TDATA_GTID
1410b57cec5SDimitry Andric   if (TCR_4(__kmp_gtid_mode) >= 3) {
1420b57cec5SDimitry Andric     KA_TRACE(1000, ("*** __kmp_get_global_thread_id: using TDATA\n"));
1430b57cec5SDimitry Andric     return __kmp_gtid;
1440b57cec5SDimitry Andric   }
1450b57cec5SDimitry Andric #endif
1460b57cec5SDimitry Andric   if (TCR_4(__kmp_gtid_mode) >= 2) {
1470b57cec5SDimitry Andric     KA_TRACE(1000, ("*** __kmp_get_global_thread_id: using keyed TLS\n"));
1480b57cec5SDimitry Andric     return __kmp_gtid_get_specific();
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric   KA_TRACE(1000, ("*** __kmp_get_global_thread_id: using internal alg.\n"));
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   stack_addr = (char *)&stack_data;
1530b57cec5SDimitry Andric   other_threads = __kmp_threads;
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   /* ATT: The code below is a source of potential bugs due to unsynchronized
1560b57cec5SDimitry Andric      access to __kmp_threads array. For example:
1570b57cec5SDimitry Andric      1. Current thread loads other_threads[i] to thr and checks it, it is
1580b57cec5SDimitry Andric         non-NULL.
1590b57cec5SDimitry Andric      2. Current thread is suspended by OS.
1600b57cec5SDimitry Andric      3. Another thread unregisters and finishes (debug versions of free()
1610b57cec5SDimitry Andric         may fill memory with something like 0xEF).
1620b57cec5SDimitry Andric      4. Current thread is resumed.
1630b57cec5SDimitry Andric      5. Current thread reads junk from *thr.
1640b57cec5SDimitry Andric      TODO: Fix it.  --ln  */
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   for (i = 0; i < __kmp_threads_capacity; i++) {
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric     kmp_info_t *thr = (kmp_info_t *)TCR_SYNC_PTR(other_threads[i]);
1690b57cec5SDimitry Andric     if (!thr)
1700b57cec5SDimitry Andric       continue;
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric     stack_size = (size_t)TCR_PTR(thr->th.th_info.ds.ds_stacksize);
1730b57cec5SDimitry Andric     stack_base = (char *)TCR_PTR(thr->th.th_info.ds.ds_stackbase);
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric     /* stack grows down -- search through all of the active threads */
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric     if (stack_addr <= stack_base) {
1780b57cec5SDimitry Andric       size_t stack_diff = stack_base - stack_addr;
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric       if (stack_diff <= stack_size) {
1810b57cec5SDimitry Andric         /* The only way we can be closer than the allocated */
1820b57cec5SDimitry Andric         /* stack size is if we are running on this thread. */
1835f757f3fSDimitry Andric         // __kmp_gtid_get_specific can return negative value because this
1845f757f3fSDimitry Andric         // function can be called by thread destructor. However, before the
1855f757f3fSDimitry Andric         // thread destructor is called, the value of the corresponding
1865f757f3fSDimitry Andric         // thread-specific data will be reset to NULL.
1875f757f3fSDimitry Andric         KMP_DEBUG_ASSERT(__kmp_gtid_get_specific() < 0 ||
1885f757f3fSDimitry Andric                          __kmp_gtid_get_specific() == i);
1890b57cec5SDimitry Andric         return i;
1900b57cec5SDimitry Andric       }
1910b57cec5SDimitry Andric     }
1920b57cec5SDimitry Andric   }
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   /* get specific to try and determine our gtid */
1950b57cec5SDimitry Andric   KA_TRACE(1000,
1960b57cec5SDimitry Andric            ("*** __kmp_get_global_thread_id: internal alg. failed to find "
1970b57cec5SDimitry Andric             "thread, using TLS\n"));
1980b57cec5SDimitry Andric   i = __kmp_gtid_get_specific();
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric   /*fprintf( stderr, "=== %d\n", i );  */ /* GROO */
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   /* if we havn't been assigned a gtid, then return code */
2030b57cec5SDimitry Andric   if (i < 0)
2040b57cec5SDimitry Andric     return i;
2050b57cec5SDimitry Andric 
2065f757f3fSDimitry Andric   // other_threads[i] can be nullptr at this point because the corresponding
2075f757f3fSDimitry Andric   // thread could have already been destructed. It can happen when this function
2085f757f3fSDimitry Andric   // is called in end library routine.
2095f757f3fSDimitry Andric   if (!TCR_SYNC_PTR(other_threads[i]))
2105f757f3fSDimitry Andric     return i;
2115f757f3fSDimitry Andric 
2120b57cec5SDimitry Andric   /* dynamically updated stack window for uber threads to avoid get_specific
2130b57cec5SDimitry Andric      call */
2140b57cec5SDimitry Andric   if (!TCR_4(other_threads[i]->th.th_info.ds.ds_stackgrow)) {
2150b57cec5SDimitry Andric     KMP_FATAL(StackOverflow, i);
2160b57cec5SDimitry Andric   }
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   stack_base = (char *)other_threads[i]->th.th_info.ds.ds_stackbase;
2190b57cec5SDimitry Andric   if (stack_addr > stack_base) {
2200b57cec5SDimitry Andric     TCW_PTR(other_threads[i]->th.th_info.ds.ds_stackbase, stack_addr);
2210b57cec5SDimitry Andric     TCW_PTR(other_threads[i]->th.th_info.ds.ds_stacksize,
2220b57cec5SDimitry Andric             other_threads[i]->th.th_info.ds.ds_stacksize + stack_addr -
2230b57cec5SDimitry Andric                 stack_base);
2240b57cec5SDimitry Andric   } else {
2250b57cec5SDimitry Andric     TCW_PTR(other_threads[i]->th.th_info.ds.ds_stacksize,
2260b57cec5SDimitry Andric             stack_base - stack_addr);
2270b57cec5SDimitry Andric   }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   /* Reprint stack bounds for ubermaster since they have been refined */
2300b57cec5SDimitry Andric   if (__kmp_storage_map) {
2310b57cec5SDimitry Andric     char *stack_end = (char *)other_threads[i]->th.th_info.ds.ds_stackbase;
2320b57cec5SDimitry Andric     char *stack_beg = stack_end - other_threads[i]->th.th_info.ds.ds_stacksize;
2330b57cec5SDimitry Andric     __kmp_print_storage_map_gtid(i, stack_beg, stack_end,
2340b57cec5SDimitry Andric                                  other_threads[i]->th.th_info.ds.ds_stacksize,
2350b57cec5SDimitry Andric                                  "th_%d stack (refinement)", i);
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric   return i;
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric 
__kmp_get_global_thread_id_reg()2400b57cec5SDimitry Andric int __kmp_get_global_thread_id_reg() {
2410b57cec5SDimitry Andric   int gtid;
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   if (!__kmp_init_serial) {
2440b57cec5SDimitry Andric     gtid = KMP_GTID_DNE;
2450b57cec5SDimitry Andric   } else
2460b57cec5SDimitry Andric #ifdef KMP_TDATA_GTID
2470b57cec5SDimitry Andric       if (TCR_4(__kmp_gtid_mode) >= 3) {
2480b57cec5SDimitry Andric     KA_TRACE(1000, ("*** __kmp_get_global_thread_id_reg: using TDATA\n"));
2490b57cec5SDimitry Andric     gtid = __kmp_gtid;
2500b57cec5SDimitry Andric   } else
2510b57cec5SDimitry Andric #endif
2520b57cec5SDimitry Andric       if (TCR_4(__kmp_gtid_mode) >= 2) {
2530b57cec5SDimitry Andric     KA_TRACE(1000, ("*** __kmp_get_global_thread_id_reg: using keyed TLS\n"));
2540b57cec5SDimitry Andric     gtid = __kmp_gtid_get_specific();
2550b57cec5SDimitry Andric   } else {
2560b57cec5SDimitry Andric     KA_TRACE(1000,
2570b57cec5SDimitry Andric              ("*** __kmp_get_global_thread_id_reg: using internal alg.\n"));
2580b57cec5SDimitry Andric     gtid = __kmp_get_global_thread_id();
2590b57cec5SDimitry Andric   }
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   /* we must be a new uber master sibling thread */
2620b57cec5SDimitry Andric   if (gtid == KMP_GTID_DNE) {
2630b57cec5SDimitry Andric     KA_TRACE(10,
2640b57cec5SDimitry Andric              ("__kmp_get_global_thread_id_reg: Encountered new root thread. "
2650b57cec5SDimitry Andric               "Registering a new gtid.\n"));
2660b57cec5SDimitry Andric     __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
2670b57cec5SDimitry Andric     if (!__kmp_init_serial) {
2680b57cec5SDimitry Andric       __kmp_do_serial_initialize();
2690b57cec5SDimitry Andric       gtid = __kmp_gtid_get_specific();
2700b57cec5SDimitry Andric     } else {
2710b57cec5SDimitry Andric       gtid = __kmp_register_root(FALSE);
2720b57cec5SDimitry Andric     }
2730b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_initz_lock);
2740b57cec5SDimitry Andric     /*__kmp_printf( "+++ %d\n", gtid ); */ /* GROO */
2750b57cec5SDimitry Andric   }
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(gtid >= 0);
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   return gtid;
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric /* caller must hold forkjoin_lock */
__kmp_check_stack_overlap(kmp_info_t * th)2830b57cec5SDimitry Andric void __kmp_check_stack_overlap(kmp_info_t *th) {
2840b57cec5SDimitry Andric   int f;
2850b57cec5SDimitry Andric   char *stack_beg = NULL;
2860b57cec5SDimitry Andric   char *stack_end = NULL;
2870b57cec5SDimitry Andric   int gtid;
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_check_stack_overlap: called\n"));
2900b57cec5SDimitry Andric   if (__kmp_storage_map) {
2910b57cec5SDimitry Andric     stack_end = (char *)th->th.th_info.ds.ds_stackbase;
2920b57cec5SDimitry Andric     stack_beg = stack_end - th->th.th_info.ds.ds_stacksize;
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric     gtid = __kmp_gtid_from_thread(th);
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric     if (gtid == KMP_GTID_MONITOR) {
2970b57cec5SDimitry Andric       __kmp_print_storage_map_gtid(
2980b57cec5SDimitry Andric           gtid, stack_beg, stack_end, th->th.th_info.ds.ds_stacksize,
2990b57cec5SDimitry Andric           "th_%s stack (%s)", "mon",
3000b57cec5SDimitry Andric           (th->th.th_info.ds.ds_stackgrow) ? "initial" : "actual");
3010b57cec5SDimitry Andric     } else {
3020b57cec5SDimitry Andric       __kmp_print_storage_map_gtid(
3030b57cec5SDimitry Andric           gtid, stack_beg, stack_end, th->th.th_info.ds.ds_stacksize,
3040b57cec5SDimitry Andric           "th_%d stack (%s)", gtid,
3050b57cec5SDimitry Andric           (th->th.th_info.ds.ds_stackgrow) ? "initial" : "actual");
3060b57cec5SDimitry Andric     }
3070b57cec5SDimitry Andric   }
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   /* No point in checking ubermaster threads since they use refinement and
3100b57cec5SDimitry Andric    * cannot overlap */
3110b57cec5SDimitry Andric   gtid = __kmp_gtid_from_thread(th);
3120b57cec5SDimitry Andric   if (__kmp_env_checks == TRUE && !KMP_UBER_GTID(gtid)) {
3130b57cec5SDimitry Andric     KA_TRACE(10,
3140b57cec5SDimitry Andric              ("__kmp_check_stack_overlap: performing extensive checking\n"));
3150b57cec5SDimitry Andric     if (stack_beg == NULL) {
3160b57cec5SDimitry Andric       stack_end = (char *)th->th.th_info.ds.ds_stackbase;
3170b57cec5SDimitry Andric       stack_beg = stack_end - th->th.th_info.ds.ds_stacksize;
3180b57cec5SDimitry Andric     }
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric     for (f = 0; f < __kmp_threads_capacity; f++) {
3210b57cec5SDimitry Andric       kmp_info_t *f_th = (kmp_info_t *)TCR_SYNC_PTR(__kmp_threads[f]);
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric       if (f_th && f_th != th) {
3240b57cec5SDimitry Andric         char *other_stack_end =
3250b57cec5SDimitry Andric             (char *)TCR_PTR(f_th->th.th_info.ds.ds_stackbase);
3260b57cec5SDimitry Andric         char *other_stack_beg =
3270b57cec5SDimitry Andric             other_stack_end - (size_t)TCR_PTR(f_th->th.th_info.ds.ds_stacksize);
3280b57cec5SDimitry Andric         if ((stack_beg > other_stack_beg && stack_beg < other_stack_end) ||
3290b57cec5SDimitry Andric             (stack_end > other_stack_beg && stack_end < other_stack_end)) {
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric           /* Print the other stack values before the abort */
3320b57cec5SDimitry Andric           if (__kmp_storage_map)
3330b57cec5SDimitry Andric             __kmp_print_storage_map_gtid(
3340b57cec5SDimitry Andric                 -1, other_stack_beg, other_stack_end,
3350b57cec5SDimitry Andric                 (size_t)TCR_PTR(f_th->th.th_info.ds.ds_stacksize),
3360b57cec5SDimitry Andric                 "th_%d stack (overlapped)", __kmp_gtid_from_thread(f_th));
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric           __kmp_fatal(KMP_MSG(StackOverlap), KMP_HNT(ChangeStackLimit),
3390b57cec5SDimitry Andric                       __kmp_msg_null);
3400b57cec5SDimitry Andric         }
3410b57cec5SDimitry Andric       }
3420b57cec5SDimitry Andric     }
3430b57cec5SDimitry Andric   }
3440b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_check_stack_overlap: returning\n"));
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
3480b57cec5SDimitry Andric 
__kmp_infinite_loop(void)3490b57cec5SDimitry Andric void __kmp_infinite_loop(void) {
3500b57cec5SDimitry Andric   static int done = FALSE;
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric   while (!done) {
3530b57cec5SDimitry Andric     KMP_YIELD(TRUE);
3540b57cec5SDimitry Andric   }
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric #define MAX_MESSAGE 512
3580b57cec5SDimitry Andric 
__kmp_print_storage_map_gtid(int gtid,void * p1,void * p2,size_t size,char const * format,...)3590b57cec5SDimitry Andric void __kmp_print_storage_map_gtid(int gtid, void *p1, void *p2, size_t size,
3600b57cec5SDimitry Andric                                   char const *format, ...) {
3610b57cec5SDimitry Andric   char buffer[MAX_MESSAGE];
3620b57cec5SDimitry Andric   va_list ap;
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   va_start(ap, format);
3650b57cec5SDimitry Andric   KMP_SNPRINTF(buffer, sizeof(buffer), "OMP storage map: %p %p%8lu %s\n", p1,
3660b57cec5SDimitry Andric                p2, (unsigned long)size, format);
3670b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
3680b57cec5SDimitry Andric   __kmp_vprintf(kmp_err, buffer, ap);
3690b57cec5SDimitry Andric #if KMP_PRINT_DATA_PLACEMENT
3700b57cec5SDimitry Andric   int node;
3710b57cec5SDimitry Andric   if (gtid >= 0) {
3720b57cec5SDimitry Andric     if (p1 <= p2 && (char *)p2 - (char *)p1 == size) {
3730b57cec5SDimitry Andric       if (__kmp_storage_map_verbose) {
3740b57cec5SDimitry Andric         node = __kmp_get_host_node(p1);
3750b57cec5SDimitry Andric         if (node < 0) /* doesn't work, so don't try this next time */
3760b57cec5SDimitry Andric           __kmp_storage_map_verbose = FALSE;
3770b57cec5SDimitry Andric         else {
3780b57cec5SDimitry Andric           char *last;
3790b57cec5SDimitry Andric           int lastNode;
3800b57cec5SDimitry Andric           int localProc = __kmp_get_cpu_from_gtid(gtid);
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric           const int page_size = KMP_GET_PAGE_SIZE();
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric           p1 = (void *)((size_t)p1 & ~((size_t)page_size - 1));
3850b57cec5SDimitry Andric           p2 = (void *)(((size_t)p2 - 1) & ~((size_t)page_size - 1));
3860b57cec5SDimitry Andric           if (localProc >= 0)
3870b57cec5SDimitry Andric             __kmp_printf_no_lock("  GTID %d localNode %d\n", gtid,
3880b57cec5SDimitry Andric                                  localProc >> 1);
3890b57cec5SDimitry Andric           else
3900b57cec5SDimitry Andric             __kmp_printf_no_lock("  GTID %d\n", gtid);
3910b57cec5SDimitry Andric #if KMP_USE_PRCTL
3920b57cec5SDimitry Andric           /* The more elaborate format is disabled for now because of the prctl
3930b57cec5SDimitry Andric            * hanging bug. */
3940b57cec5SDimitry Andric           do {
3950b57cec5SDimitry Andric             last = p1;
3960b57cec5SDimitry Andric             lastNode = node;
3970b57cec5SDimitry Andric             /* This loop collates adjacent pages with the same host node. */
3980b57cec5SDimitry Andric             do {
3990b57cec5SDimitry Andric               (char *)p1 += page_size;
4000b57cec5SDimitry Andric             } while (p1 <= p2 && (node = __kmp_get_host_node(p1)) == lastNode);
4010b57cec5SDimitry Andric             __kmp_printf_no_lock("    %p-%p memNode %d\n", last, (char *)p1 - 1,
4020b57cec5SDimitry Andric                                  lastNode);
4030b57cec5SDimitry Andric           } while (p1 <= p2);
4040b57cec5SDimitry Andric #else
4050b57cec5SDimitry Andric           __kmp_printf_no_lock("    %p-%p memNode %d\n", p1,
4060b57cec5SDimitry Andric                                (char *)p1 + (page_size - 1),
4070b57cec5SDimitry Andric                                __kmp_get_host_node(p1));
4080b57cec5SDimitry Andric           if (p1 < p2) {
4090b57cec5SDimitry Andric             __kmp_printf_no_lock("    %p-%p memNode %d\n", p2,
4100b57cec5SDimitry Andric                                  (char *)p2 + (page_size - 1),
4110b57cec5SDimitry Andric                                  __kmp_get_host_node(p2));
4120b57cec5SDimitry Andric           }
4130b57cec5SDimitry Andric #endif
4140b57cec5SDimitry Andric         }
4150b57cec5SDimitry Andric       }
4160b57cec5SDimitry Andric     } else
4170b57cec5SDimitry Andric       __kmp_printf_no_lock("  %s\n", KMP_I18N_STR(StorageMapWarning));
4180b57cec5SDimitry Andric   }
4190b57cec5SDimitry Andric #endif /* KMP_PRINT_DATA_PLACEMENT */
4200b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_stdio_lock);
42106c3fb27SDimitry Andric 
42206c3fb27SDimitry Andric   va_end(ap);
4230b57cec5SDimitry Andric }
4240b57cec5SDimitry Andric 
__kmp_warn(char const * format,...)4250b57cec5SDimitry Andric void __kmp_warn(char const *format, ...) {
4260b57cec5SDimitry Andric   char buffer[MAX_MESSAGE];
4270b57cec5SDimitry Andric   va_list ap;
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   if (__kmp_generate_warnings == kmp_warnings_off) {
4300b57cec5SDimitry Andric     return;
4310b57cec5SDimitry Andric   }
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric   va_start(ap, format);
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   KMP_SNPRINTF(buffer, sizeof(buffer), "OMP warning: %s\n", format);
4360b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
4370b57cec5SDimitry Andric   __kmp_vprintf(kmp_err, buffer, ap);
4380b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_stdio_lock);
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric   va_end(ap);
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric 
__kmp_abort_process()4430b57cec5SDimitry Andric void __kmp_abort_process() {
4440b57cec5SDimitry Andric   // Later threads may stall here, but that's ok because abort() will kill them.
4450b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_exit_lock);
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric   if (__kmp_debug_buf) {
4480b57cec5SDimitry Andric     __kmp_dump_debug_buffer();
4490b57cec5SDimitry Andric   }
4500b57cec5SDimitry Andric 
4515f757f3fSDimitry Andric #if KMP_OS_WINDOWS
4520b57cec5SDimitry Andric   // Let other threads know of abnormal termination and prevent deadlock
4530b57cec5SDimitry Andric   // if abort happened during library initialization or shutdown
4540b57cec5SDimitry Andric   __kmp_global.g.g_abort = SIGABRT;
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric   /* On Windows* OS by default abort() causes pop-up error box, which stalls
4570b57cec5SDimitry Andric      nightly testing. Unfortunately, we cannot reliably suppress pop-up error
4580b57cec5SDimitry Andric      boxes. _set_abort_behavior() works well, but this function is not
4590b57cec5SDimitry Andric      available in VS7 (this is not problem for DLL, but it is a problem for
4600b57cec5SDimitry Andric      static OpenMP RTL). SetErrorMode (and so, timelimit utility) does not
4610b57cec5SDimitry Andric      help, at least in some versions of MS C RTL.
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric      It seems following sequence is the only way to simulate abort() and
4640b57cec5SDimitry Andric      avoid pop-up error box. */
4650b57cec5SDimitry Andric   raise(SIGABRT);
4660b57cec5SDimitry Andric   _exit(3); // Just in case, if signal ignored, exit anyway.
4675f757f3fSDimitry Andric #else
468e8d8bef9SDimitry Andric   __kmp_unregister_library();
4690b57cec5SDimitry Andric   abort();
4705f757f3fSDimitry Andric #endif
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric   __kmp_infinite_loop();
4730b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_exit_lock);
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric } // __kmp_abort_process
4760b57cec5SDimitry Andric 
__kmp_abort_thread(void)4770b57cec5SDimitry Andric void __kmp_abort_thread(void) {
4780b57cec5SDimitry Andric   // TODO: Eliminate g_abort global variable and this function.
4790b57cec5SDimitry Andric   // In case of abort just call abort(), it will kill all the threads.
4800b57cec5SDimitry Andric   __kmp_infinite_loop();
4810b57cec5SDimitry Andric } // __kmp_abort_thread
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric /* Print out the storage map for the major kmp_info_t thread data structures
4840b57cec5SDimitry Andric    that are allocated together. */
4850b57cec5SDimitry Andric 
__kmp_print_thread_storage_map(kmp_info_t * thr,int gtid)4860b57cec5SDimitry Andric static void __kmp_print_thread_storage_map(kmp_info_t *thr, int gtid) {
4870b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(gtid, thr, thr + 1, sizeof(kmp_info_t), "th_%d",
4880b57cec5SDimitry Andric                                gtid);
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(gtid, &thr->th.th_info, &thr->th.th_team,
4910b57cec5SDimitry Andric                                sizeof(kmp_desc_t), "th_%d.th_info", gtid);
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(gtid, &thr->th.th_local, &thr->th.th_pri_head,
4940b57cec5SDimitry Andric                                sizeof(kmp_local_t), "th_%d.th_local", gtid);
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(
4970b57cec5SDimitry Andric       gtid, &thr->th.th_bar[0], &thr->th.th_bar[bs_last_barrier],
4980b57cec5SDimitry Andric       sizeof(kmp_balign_t) * bs_last_barrier, "th_%d.th_bar", gtid);
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(gtid, &thr->th.th_bar[bs_plain_barrier],
5010b57cec5SDimitry Andric                                &thr->th.th_bar[bs_plain_barrier + 1],
5020b57cec5SDimitry Andric                                sizeof(kmp_balign_t), "th_%d.th_bar[plain]",
5030b57cec5SDimitry Andric                                gtid);
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(gtid, &thr->th.th_bar[bs_forkjoin_barrier],
5060b57cec5SDimitry Andric                                &thr->th.th_bar[bs_forkjoin_barrier + 1],
5070b57cec5SDimitry Andric                                sizeof(kmp_balign_t), "th_%d.th_bar[forkjoin]",
5080b57cec5SDimitry Andric                                gtid);
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric #if KMP_FAST_REDUCTION_BARRIER
5110b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(gtid, &thr->th.th_bar[bs_reduction_barrier],
5120b57cec5SDimitry Andric                                &thr->th.th_bar[bs_reduction_barrier + 1],
5130b57cec5SDimitry Andric                                sizeof(kmp_balign_t), "th_%d.th_bar[reduction]",
5140b57cec5SDimitry Andric                                gtid);
5150b57cec5SDimitry Andric #endif // KMP_FAST_REDUCTION_BARRIER
5160b57cec5SDimitry Andric }
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric /* Print out the storage map for the major kmp_team_t team data structures
5190b57cec5SDimitry Andric    that are allocated together. */
5200b57cec5SDimitry Andric 
__kmp_print_team_storage_map(const char * header,kmp_team_t * team,int team_id,int num_thr)5210b57cec5SDimitry Andric static void __kmp_print_team_storage_map(const char *header, kmp_team_t *team,
5220b57cec5SDimitry Andric                                          int team_id, int num_thr) {
5230b57cec5SDimitry Andric   int num_disp_buff = team->t.t_max_nproc > 1 ? __kmp_dispatch_num_buffers : 2;
5240b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(-1, team, team + 1, sizeof(kmp_team_t), "%s_%d",
5250b57cec5SDimitry Andric                                header, team_id);
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(-1, &team->t.t_bar[0],
5280b57cec5SDimitry Andric                                &team->t.t_bar[bs_last_barrier],
5290b57cec5SDimitry Andric                                sizeof(kmp_balign_team_t) * bs_last_barrier,
5300b57cec5SDimitry Andric                                "%s_%d.t_bar", header, team_id);
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(-1, &team->t.t_bar[bs_plain_barrier],
5330b57cec5SDimitry Andric                                &team->t.t_bar[bs_plain_barrier + 1],
5340b57cec5SDimitry Andric                                sizeof(kmp_balign_team_t), "%s_%d.t_bar[plain]",
5350b57cec5SDimitry Andric                                header, team_id);
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(-1, &team->t.t_bar[bs_forkjoin_barrier],
5380b57cec5SDimitry Andric                                &team->t.t_bar[bs_forkjoin_barrier + 1],
5390b57cec5SDimitry Andric                                sizeof(kmp_balign_team_t),
5400b57cec5SDimitry Andric                                "%s_%d.t_bar[forkjoin]", header, team_id);
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric #if KMP_FAST_REDUCTION_BARRIER
5430b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(-1, &team->t.t_bar[bs_reduction_barrier],
5440b57cec5SDimitry Andric                                &team->t.t_bar[bs_reduction_barrier + 1],
5450b57cec5SDimitry Andric                                sizeof(kmp_balign_team_t),
5460b57cec5SDimitry Andric                                "%s_%d.t_bar[reduction]", header, team_id);
5470b57cec5SDimitry Andric #endif // KMP_FAST_REDUCTION_BARRIER
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(
5500b57cec5SDimitry Andric       -1, &team->t.t_dispatch[0], &team->t.t_dispatch[num_thr],
5510b57cec5SDimitry Andric       sizeof(kmp_disp_t) * num_thr, "%s_%d.t_dispatch", header, team_id);
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(
5540b57cec5SDimitry Andric       -1, &team->t.t_threads[0], &team->t.t_threads[num_thr],
5550b57cec5SDimitry Andric       sizeof(kmp_info_t *) * num_thr, "%s_%d.t_threads", header, team_id);
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   __kmp_print_storage_map_gtid(-1, &team->t.t_disp_buffer[0],
5580b57cec5SDimitry Andric                                &team->t.t_disp_buffer[num_disp_buff],
5590b57cec5SDimitry Andric                                sizeof(dispatch_shared_info_t) * num_disp_buff,
5600b57cec5SDimitry Andric                                "%s_%d.t_disp_buffer", header, team_id);
5610b57cec5SDimitry Andric }
5620b57cec5SDimitry Andric 
__kmp_init_allocator()563fe6060f1SDimitry Andric static void __kmp_init_allocator() {
564fe6060f1SDimitry Andric   __kmp_init_memkind();
565fe6060f1SDimitry Andric   __kmp_init_target_mem();
566fe6060f1SDimitry Andric }
__kmp_fini_allocator()5670b57cec5SDimitry Andric static void __kmp_fini_allocator() { __kmp_fini_memkind(); }
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
5700b57cec5SDimitry Andric 
57106c3fb27SDimitry Andric #if ENABLE_LIBOMPTARGET
__kmp_init_omptarget()57206c3fb27SDimitry Andric static void __kmp_init_omptarget() {
57306c3fb27SDimitry Andric   __kmp_init_target_task();
57406c3fb27SDimitry Andric }
57506c3fb27SDimitry Andric #endif
57606c3fb27SDimitry Andric 
57706c3fb27SDimitry Andric /* ------------------------------------------------------------------------ */
57806c3fb27SDimitry Andric 
5790b57cec5SDimitry Andric #if KMP_DYNAMIC_LIB
5800b57cec5SDimitry Andric #if KMP_OS_WINDOWS
5810b57cec5SDimitry Andric 
DllMain(HINSTANCE hInstDLL,DWORD fdwReason,LPVOID lpReserved)5820b57cec5SDimitry Andric BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved) {
5830b57cec5SDimitry Andric   //__kmp_acquire_bootstrap_lock( &__kmp_initz_lock );
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric   switch (fdwReason) {
5860b57cec5SDimitry Andric 
5870b57cec5SDimitry Andric   case DLL_PROCESS_ATTACH:
5880b57cec5SDimitry Andric     KA_TRACE(10, ("DllMain: PROCESS_ATTACH\n"));
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric     return TRUE;
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric   case DLL_PROCESS_DETACH:
5930b57cec5SDimitry Andric     KA_TRACE(10, ("DllMain: PROCESS_DETACH T#%d\n", __kmp_gtid_get_specific()));
5940b57cec5SDimitry Andric 
595fe6060f1SDimitry Andric     // According to Windows* documentation for DllMain entry point:
596fe6060f1SDimitry Andric     // for DLL_PROCESS_DETACH, lpReserved is used for telling the difference:
597fe6060f1SDimitry Andric     //   lpReserved == NULL when FreeLibrary() is called,
598fe6060f1SDimitry Andric     //   lpReserved != NULL when the process is terminated.
599fe6060f1SDimitry Andric     // When FreeLibrary() is called, worker threads remain alive. So the
600fe6060f1SDimitry Andric     // runtime's state is consistent and executing proper shutdown is OK.
601fe6060f1SDimitry Andric     // When the process is terminated, worker threads have exited or been
602fe6060f1SDimitry Andric     // forcefully terminated by the OS and only the shutdown thread remains.
603fe6060f1SDimitry Andric     // This can leave the runtime in an inconsistent state.
604fe6060f1SDimitry Andric     // Hence, only attempt proper cleanup when FreeLibrary() is called.
605fe6060f1SDimitry Andric     // Otherwise, rely on OS to reclaim resources.
606fe6060f1SDimitry Andric     if (lpReserved == NULL)
6070b57cec5SDimitry Andric       __kmp_internal_end_library(__kmp_gtid_get_specific());
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric     return TRUE;
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric   case DLL_THREAD_ATTACH:
6120b57cec5SDimitry Andric     KA_TRACE(10, ("DllMain: THREAD_ATTACH\n"));
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric     /* if we want to register new siblings all the time here call
6150b57cec5SDimitry Andric      * __kmp_get_gtid(); */
6160b57cec5SDimitry Andric     return TRUE;
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric   case DLL_THREAD_DETACH:
6190b57cec5SDimitry Andric     KA_TRACE(10, ("DllMain: THREAD_DETACH T#%d\n", __kmp_gtid_get_specific()));
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric     __kmp_internal_end_thread(__kmp_gtid_get_specific());
6220b57cec5SDimitry Andric     return TRUE;
6230b57cec5SDimitry Andric   }
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric   return TRUE;
6260b57cec5SDimitry Andric }
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */
6290b57cec5SDimitry Andric #endif /* KMP_DYNAMIC_LIB */
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric /* __kmp_parallel_deo -- Wait until it's our turn. */
__kmp_parallel_deo(int * gtid_ref,int * cid_ref,ident_t * loc_ref)6320b57cec5SDimitry Andric void __kmp_parallel_deo(int *gtid_ref, int *cid_ref, ident_t *loc_ref) {
6330b57cec5SDimitry Andric   int gtid = *gtid_ref;
6340b57cec5SDimitry Andric #ifdef BUILD_PARALLEL_ORDERED
6350b57cec5SDimitry Andric   kmp_team_t *team = __kmp_team_from_gtid(gtid);
6360b57cec5SDimitry Andric #endif /* BUILD_PARALLEL_ORDERED */
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric   if (__kmp_env_consistency_check) {
6390b57cec5SDimitry Andric     if (__kmp_threads[gtid]->th.th_root->r.r_active)
6400b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK
6410b57cec5SDimitry Andric       __kmp_push_sync(gtid, ct_ordered_in_parallel, loc_ref, NULL, 0);
6420b57cec5SDimitry Andric #else
6430b57cec5SDimitry Andric       __kmp_push_sync(gtid, ct_ordered_in_parallel, loc_ref, NULL);
6440b57cec5SDimitry Andric #endif
6450b57cec5SDimitry Andric   }
6460b57cec5SDimitry Andric #ifdef BUILD_PARALLEL_ORDERED
6470b57cec5SDimitry Andric   if (!team->t.t_serialized) {
6480b57cec5SDimitry Andric     KMP_MB();
6490b57cec5SDimitry Andric     KMP_WAIT(&team->t.t_ordered.dt.t_value, __kmp_tid_from_gtid(gtid), KMP_EQ,
6500b57cec5SDimitry Andric              NULL);
6510b57cec5SDimitry Andric     KMP_MB();
6520b57cec5SDimitry Andric   }
6530b57cec5SDimitry Andric #endif /* BUILD_PARALLEL_ORDERED */
6540b57cec5SDimitry Andric }
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric /* __kmp_parallel_dxo -- Signal the next task. */
__kmp_parallel_dxo(int * gtid_ref,int * cid_ref,ident_t * loc_ref)6570b57cec5SDimitry Andric void __kmp_parallel_dxo(int *gtid_ref, int *cid_ref, ident_t *loc_ref) {
6580b57cec5SDimitry Andric   int gtid = *gtid_ref;
6590b57cec5SDimitry Andric #ifdef BUILD_PARALLEL_ORDERED
6600b57cec5SDimitry Andric   int tid = __kmp_tid_from_gtid(gtid);
6610b57cec5SDimitry Andric   kmp_team_t *team = __kmp_team_from_gtid(gtid);
6620b57cec5SDimitry Andric #endif /* BUILD_PARALLEL_ORDERED */
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric   if (__kmp_env_consistency_check) {
6650b57cec5SDimitry Andric     if (__kmp_threads[gtid]->th.th_root->r.r_active)
6660b57cec5SDimitry Andric       __kmp_pop_sync(gtid, ct_ordered_in_parallel, loc_ref);
6670b57cec5SDimitry Andric   }
6680b57cec5SDimitry Andric #ifdef BUILD_PARALLEL_ORDERED
6690b57cec5SDimitry Andric   if (!team->t.t_serialized) {
6700b57cec5SDimitry Andric     KMP_MB(); /* Flush all pending memory write invalidates.  */
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric     /* use the tid of the next thread in this team */
6730b57cec5SDimitry Andric     /* TODO replace with general release procedure */
6740b57cec5SDimitry Andric     team->t.t_ordered.dt.t_value = ((tid + 1) % team->t.t_nproc);
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric     KMP_MB(); /* Flush all pending memory write invalidates.  */
6770b57cec5SDimitry Andric   }
6780b57cec5SDimitry Andric #endif /* BUILD_PARALLEL_ORDERED */
6790b57cec5SDimitry Andric }
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
6820b57cec5SDimitry Andric /* The BARRIER for a SINGLE process section is always explicit   */
6830b57cec5SDimitry Andric 
__kmp_enter_single(int gtid,ident_t * id_ref,int push_ws)6840b57cec5SDimitry Andric int __kmp_enter_single(int gtid, ident_t *id_ref, int push_ws) {
6850b57cec5SDimitry Andric   int status;
6860b57cec5SDimitry Andric   kmp_info_t *th;
6870b57cec5SDimitry Andric   kmp_team_t *team;
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric   if (!TCR_4(__kmp_init_parallel))
6900b57cec5SDimitry Andric     __kmp_parallel_initialize();
6910b57cec5SDimitry Andric   __kmp_resume_if_soft_paused();
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric   th = __kmp_threads[gtid];
6940b57cec5SDimitry Andric   team = th->th.th_team;
6950b57cec5SDimitry Andric   status = 0;
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric   th->th.th_ident = id_ref;
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric   if (team->t.t_serialized) {
7000b57cec5SDimitry Andric     status = 1;
7010b57cec5SDimitry Andric   } else {
7020b57cec5SDimitry Andric     kmp_int32 old_this = th->th.th_local.this_construct;
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric     ++th->th.th_local.this_construct;
7050b57cec5SDimitry Andric     /* try to set team count to thread count--success means thread got the
7060b57cec5SDimitry Andric        single block */
7070b57cec5SDimitry Andric     /* TODO: Should this be acquire or release? */
7080b57cec5SDimitry Andric     if (team->t.t_construct == old_this) {
7090b57cec5SDimitry Andric       status = __kmp_atomic_compare_store_acq(&team->t.t_construct, old_this,
7100b57cec5SDimitry Andric                                               th->th.th_local.this_construct);
7110b57cec5SDimitry Andric     }
7120b57cec5SDimitry Andric #if USE_ITT_BUILD
7130b57cec5SDimitry Andric     if (__itt_metadata_add_ptr && __kmp_forkjoin_frames_mode == 3 &&
7140b57cec5SDimitry Andric         KMP_MASTER_GTID(gtid) && th->th.th_teams_microtask == NULL &&
715fe6060f1SDimitry Andric         team->t.t_active_level == 1) {
716fe6060f1SDimitry Andric       // Only report metadata by primary thread of active team at level 1
7170b57cec5SDimitry Andric       __kmp_itt_metadata_single(id_ref);
7180b57cec5SDimitry Andric     }
7190b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
7200b57cec5SDimitry Andric   }
7210b57cec5SDimitry Andric 
7220b57cec5SDimitry Andric   if (__kmp_env_consistency_check) {
7230b57cec5SDimitry Andric     if (status && push_ws) {
7240b57cec5SDimitry Andric       __kmp_push_workshare(gtid, ct_psingle, id_ref);
7250b57cec5SDimitry Andric     } else {
7260b57cec5SDimitry Andric       __kmp_check_workshare(gtid, ct_psingle, id_ref);
7270b57cec5SDimitry Andric     }
7280b57cec5SDimitry Andric   }
7290b57cec5SDimitry Andric #if USE_ITT_BUILD
7300b57cec5SDimitry Andric   if (status) {
7310b57cec5SDimitry Andric     __kmp_itt_single_start(gtid);
7320b57cec5SDimitry Andric   }
7330b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
7340b57cec5SDimitry Andric   return status;
7350b57cec5SDimitry Andric }
7360b57cec5SDimitry Andric 
__kmp_exit_single(int gtid)7370b57cec5SDimitry Andric void __kmp_exit_single(int gtid) {
7380b57cec5SDimitry Andric #if USE_ITT_BUILD
7390b57cec5SDimitry Andric   __kmp_itt_single_end(gtid);
7400b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
7410b57cec5SDimitry Andric   if (__kmp_env_consistency_check)
7420b57cec5SDimitry Andric     __kmp_pop_workshare(gtid, ct_psingle, NULL);
7430b57cec5SDimitry Andric }
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric /* determine if we can go parallel or must use a serialized parallel region and
7460b57cec5SDimitry Andric  * how many threads we can use
7470b57cec5SDimitry Andric  * set_nproc is the number of threads requested for the team
7480b57cec5SDimitry Andric  * returns 0 if we should serialize or only use one thread,
7490b57cec5SDimitry Andric  * otherwise the number of threads to use
7500b57cec5SDimitry Andric  * The forkjoin lock is held by the caller. */
__kmp_reserve_threads(kmp_root_t * root,kmp_team_t * parent_team,int master_tid,int set_nthreads,int enter_teams)7510b57cec5SDimitry Andric static int __kmp_reserve_threads(kmp_root_t *root, kmp_team_t *parent_team,
7520b57cec5SDimitry Andric                                  int master_tid, int set_nthreads,
7530b57cec5SDimitry Andric                                  int enter_teams) {
7540b57cec5SDimitry Andric   int capacity;
7550b57cec5SDimitry Andric   int new_nthreads;
7560b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_init_serial);
7570b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(root && parent_team);
7580b57cec5SDimitry Andric   kmp_info_t *this_thr = parent_team->t.t_threads[master_tid];
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric   // If dyn-var is set, dynamically adjust the number of desired threads,
7610b57cec5SDimitry Andric   // according to the method specified by dynamic_mode.
7620b57cec5SDimitry Andric   new_nthreads = set_nthreads;
7630b57cec5SDimitry Andric   if (!get__dynamic_2(parent_team, master_tid)) {
7640b57cec5SDimitry Andric     ;
7650b57cec5SDimitry Andric   }
7660b57cec5SDimitry Andric #ifdef USE_LOAD_BALANCE
7670b57cec5SDimitry Andric   else if (__kmp_global.g.g_dynamic_mode == dynamic_load_balance) {
7680b57cec5SDimitry Andric     new_nthreads = __kmp_load_balance_nproc(root, set_nthreads);
7690b57cec5SDimitry Andric     if (new_nthreads == 1) {
7700b57cec5SDimitry Andric       KC_TRACE(10, ("__kmp_reserve_threads: T#%d load balance reduced "
7710b57cec5SDimitry Andric                     "reservation to 1 thread\n",
7720b57cec5SDimitry Andric                     master_tid));
7730b57cec5SDimitry Andric       return 1;
7740b57cec5SDimitry Andric     }
7750b57cec5SDimitry Andric     if (new_nthreads < set_nthreads) {
7760b57cec5SDimitry Andric       KC_TRACE(10, ("__kmp_reserve_threads: T#%d load balance reduced "
7770b57cec5SDimitry Andric                     "reservation to %d threads\n",
7780b57cec5SDimitry Andric                     master_tid, new_nthreads));
7790b57cec5SDimitry Andric     }
7800b57cec5SDimitry Andric   }
7810b57cec5SDimitry Andric #endif /* USE_LOAD_BALANCE */
7820b57cec5SDimitry Andric   else if (__kmp_global.g.g_dynamic_mode == dynamic_thread_limit) {
7830b57cec5SDimitry Andric     new_nthreads = __kmp_avail_proc - __kmp_nth +
7840b57cec5SDimitry Andric                    (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc);
7850b57cec5SDimitry Andric     if (new_nthreads <= 1) {
7860b57cec5SDimitry Andric       KC_TRACE(10, ("__kmp_reserve_threads: T#%d thread limit reduced "
7870b57cec5SDimitry Andric                     "reservation to 1 thread\n",
7880b57cec5SDimitry Andric                     master_tid));
7890b57cec5SDimitry Andric       return 1;
7900b57cec5SDimitry Andric     }
7910b57cec5SDimitry Andric     if (new_nthreads < set_nthreads) {
7920b57cec5SDimitry Andric       KC_TRACE(10, ("__kmp_reserve_threads: T#%d thread limit reduced "
7930b57cec5SDimitry Andric                     "reservation to %d threads\n",
7940b57cec5SDimitry Andric                     master_tid, new_nthreads));
7950b57cec5SDimitry Andric     } else {
7960b57cec5SDimitry Andric       new_nthreads = set_nthreads;
7970b57cec5SDimitry Andric     }
7980b57cec5SDimitry Andric   } else if (__kmp_global.g.g_dynamic_mode == dynamic_random) {
7990b57cec5SDimitry Andric     if (set_nthreads > 2) {
8000b57cec5SDimitry Andric       new_nthreads = __kmp_get_random(parent_team->t.t_threads[master_tid]);
8010b57cec5SDimitry Andric       new_nthreads = (new_nthreads % set_nthreads) + 1;
8020b57cec5SDimitry Andric       if (new_nthreads == 1) {
8030b57cec5SDimitry Andric         KC_TRACE(10, ("__kmp_reserve_threads: T#%d dynamic random reduced "
8040b57cec5SDimitry Andric                       "reservation to 1 thread\n",
8050b57cec5SDimitry Andric                       master_tid));
8060b57cec5SDimitry Andric         return 1;
8070b57cec5SDimitry Andric       }
8080b57cec5SDimitry Andric       if (new_nthreads < set_nthreads) {
8090b57cec5SDimitry Andric         KC_TRACE(10, ("__kmp_reserve_threads: T#%d dynamic random reduced "
8100b57cec5SDimitry Andric                       "reservation to %d threads\n",
8110b57cec5SDimitry Andric                       master_tid, new_nthreads));
8120b57cec5SDimitry Andric       }
8130b57cec5SDimitry Andric     }
8140b57cec5SDimitry Andric   } else {
8150b57cec5SDimitry Andric     KMP_ASSERT(0);
8160b57cec5SDimitry Andric   }
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric   // Respect KMP_ALL_THREADS/KMP_DEVICE_THREAD_LIMIT.
8190b57cec5SDimitry Andric   if (__kmp_nth + new_nthreads -
8200b57cec5SDimitry Andric           (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc) >
8210b57cec5SDimitry Andric       __kmp_max_nth) {
8220b57cec5SDimitry Andric     int tl_nthreads = __kmp_max_nth - __kmp_nth +
8230b57cec5SDimitry Andric                       (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc);
8240b57cec5SDimitry Andric     if (tl_nthreads <= 0) {
8250b57cec5SDimitry Andric       tl_nthreads = 1;
8260b57cec5SDimitry Andric     }
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric     // If dyn-var is false, emit a 1-time warning.
8290b57cec5SDimitry Andric     if (!get__dynamic_2(parent_team, master_tid) && (!__kmp_reserve_warn)) {
8300b57cec5SDimitry Andric       __kmp_reserve_warn = 1;
8310b57cec5SDimitry Andric       __kmp_msg(kmp_ms_warning,
8320b57cec5SDimitry Andric                 KMP_MSG(CantFormThrTeam, set_nthreads, tl_nthreads),
8330b57cec5SDimitry Andric                 KMP_HNT(Unset_ALL_THREADS), __kmp_msg_null);
8340b57cec5SDimitry Andric     }
8350b57cec5SDimitry Andric     if (tl_nthreads == 1) {
8360b57cec5SDimitry Andric       KC_TRACE(10, ("__kmp_reserve_threads: T#%d KMP_DEVICE_THREAD_LIMIT "
8370b57cec5SDimitry Andric                     "reduced reservation to 1 thread\n",
8380b57cec5SDimitry Andric                     master_tid));
8390b57cec5SDimitry Andric       return 1;
8400b57cec5SDimitry Andric     }
8410b57cec5SDimitry Andric     KC_TRACE(10, ("__kmp_reserve_threads: T#%d KMP_DEVICE_THREAD_LIMIT reduced "
8420b57cec5SDimitry Andric                   "reservation to %d threads\n",
8430b57cec5SDimitry Andric                   master_tid, tl_nthreads));
8440b57cec5SDimitry Andric     new_nthreads = tl_nthreads;
8450b57cec5SDimitry Andric   }
8460b57cec5SDimitry Andric 
8470b57cec5SDimitry Andric   // Respect OMP_THREAD_LIMIT
8480b57cec5SDimitry Andric   int cg_nthreads = this_thr->th.th_cg_roots->cg_nthreads;
8490b57cec5SDimitry Andric   int max_cg_threads = this_thr->th.th_cg_roots->cg_thread_limit;
8500b57cec5SDimitry Andric   if (cg_nthreads + new_nthreads -
8510b57cec5SDimitry Andric           (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc) >
8520b57cec5SDimitry Andric       max_cg_threads) {
8530b57cec5SDimitry Andric     int tl_nthreads = max_cg_threads - cg_nthreads +
8540b57cec5SDimitry Andric                       (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc);
8550b57cec5SDimitry Andric     if (tl_nthreads <= 0) {
8560b57cec5SDimitry Andric       tl_nthreads = 1;
8570b57cec5SDimitry Andric     }
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric     // If dyn-var is false, emit a 1-time warning.
8600b57cec5SDimitry Andric     if (!get__dynamic_2(parent_team, master_tid) && (!__kmp_reserve_warn)) {
8610b57cec5SDimitry Andric       __kmp_reserve_warn = 1;
8620b57cec5SDimitry Andric       __kmp_msg(kmp_ms_warning,
8630b57cec5SDimitry Andric                 KMP_MSG(CantFormThrTeam, set_nthreads, tl_nthreads),
8640b57cec5SDimitry Andric                 KMP_HNT(Unset_ALL_THREADS), __kmp_msg_null);
8650b57cec5SDimitry Andric     }
8660b57cec5SDimitry Andric     if (tl_nthreads == 1) {
8670b57cec5SDimitry Andric       KC_TRACE(10, ("__kmp_reserve_threads: T#%d OMP_THREAD_LIMIT "
8680b57cec5SDimitry Andric                     "reduced reservation to 1 thread\n",
8690b57cec5SDimitry Andric                     master_tid));
8700b57cec5SDimitry Andric       return 1;
8710b57cec5SDimitry Andric     }
8720b57cec5SDimitry Andric     KC_TRACE(10, ("__kmp_reserve_threads: T#%d OMP_THREAD_LIMIT reduced "
8730b57cec5SDimitry Andric                   "reservation to %d threads\n",
8740b57cec5SDimitry Andric                   master_tid, tl_nthreads));
8750b57cec5SDimitry Andric     new_nthreads = tl_nthreads;
8760b57cec5SDimitry Andric   }
8770b57cec5SDimitry Andric 
8780b57cec5SDimitry Andric   // Check if the threads array is large enough, or needs expanding.
8790b57cec5SDimitry Andric   // See comment in __kmp_register_root() about the adjustment if
8800b57cec5SDimitry Andric   // __kmp_threads[0] == NULL.
8810b57cec5SDimitry Andric   capacity = __kmp_threads_capacity;
8820b57cec5SDimitry Andric   if (TCR_PTR(__kmp_threads[0]) == NULL) {
8830b57cec5SDimitry Andric     --capacity;
8840b57cec5SDimitry Andric   }
885d409305fSDimitry Andric   // If it is not for initializing the hidden helper team, we need to take
886d409305fSDimitry Andric   // __kmp_hidden_helper_threads_num out of the capacity because it is included
887d409305fSDimitry Andric   // in __kmp_threads_capacity.
888d409305fSDimitry Andric   if (__kmp_enable_hidden_helper && !TCR_4(__kmp_init_hidden_helper_threads)) {
889d409305fSDimitry Andric     capacity -= __kmp_hidden_helper_threads_num;
890d409305fSDimitry Andric   }
8910b57cec5SDimitry Andric   if (__kmp_nth + new_nthreads -
8920b57cec5SDimitry Andric           (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc) >
8930b57cec5SDimitry Andric       capacity) {
8940b57cec5SDimitry Andric     // Expand the threads array.
8950b57cec5SDimitry Andric     int slotsRequired = __kmp_nth + new_nthreads -
8960b57cec5SDimitry Andric                         (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc) -
8970b57cec5SDimitry Andric                         capacity;
8980b57cec5SDimitry Andric     int slotsAdded = __kmp_expand_threads(slotsRequired);
8990b57cec5SDimitry Andric     if (slotsAdded < slotsRequired) {
9000b57cec5SDimitry Andric       // The threads array was not expanded enough.
9010b57cec5SDimitry Andric       new_nthreads -= (slotsRequired - slotsAdded);
9020b57cec5SDimitry Andric       KMP_ASSERT(new_nthreads >= 1);
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric       // If dyn-var is false, emit a 1-time warning.
9050b57cec5SDimitry Andric       if (!get__dynamic_2(parent_team, master_tid) && (!__kmp_reserve_warn)) {
9060b57cec5SDimitry Andric         __kmp_reserve_warn = 1;
9070b57cec5SDimitry Andric         if (__kmp_tp_cached) {
9080b57cec5SDimitry Andric           __kmp_msg(kmp_ms_warning,
9090b57cec5SDimitry Andric                     KMP_MSG(CantFormThrTeam, set_nthreads, new_nthreads),
9100b57cec5SDimitry Andric                     KMP_HNT(Set_ALL_THREADPRIVATE, __kmp_tp_capacity),
9110b57cec5SDimitry Andric                     KMP_HNT(PossibleSystemLimitOnThreads), __kmp_msg_null);
9120b57cec5SDimitry Andric         } else {
9130b57cec5SDimitry Andric           __kmp_msg(kmp_ms_warning,
9140b57cec5SDimitry Andric                     KMP_MSG(CantFormThrTeam, set_nthreads, new_nthreads),
9150b57cec5SDimitry Andric                     KMP_HNT(SystemLimitOnThreads), __kmp_msg_null);
9160b57cec5SDimitry Andric         }
9170b57cec5SDimitry Andric       }
9180b57cec5SDimitry Andric     }
9190b57cec5SDimitry Andric   }
9200b57cec5SDimitry Andric 
9210b57cec5SDimitry Andric #ifdef KMP_DEBUG
9220b57cec5SDimitry Andric   if (new_nthreads == 1) {
9230b57cec5SDimitry Andric     KC_TRACE(10,
9240b57cec5SDimitry Andric              ("__kmp_reserve_threads: T#%d serializing team after reclaiming "
9250b57cec5SDimitry Andric               "dead roots and rechecking; requested %d threads\n",
9260b57cec5SDimitry Andric               __kmp_get_gtid(), set_nthreads));
9270b57cec5SDimitry Andric   } else {
9280b57cec5SDimitry Andric     KC_TRACE(10, ("__kmp_reserve_threads: T#%d allocating %d threads; requested"
9290b57cec5SDimitry Andric                   " %d threads\n",
9300b57cec5SDimitry Andric                   __kmp_get_gtid(), new_nthreads, set_nthreads));
9310b57cec5SDimitry Andric   }
9320b57cec5SDimitry Andric #endif // KMP_DEBUG
9330b57cec5SDimitry Andric   return new_nthreads;
9340b57cec5SDimitry Andric }
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric /* Allocate threads from the thread pool and assign them to the new team. We are
9370b57cec5SDimitry Andric    assured that there are enough threads available, because we checked on that
9380b57cec5SDimitry Andric    earlier within critical section forkjoin */
__kmp_fork_team_threads(kmp_root_t * root,kmp_team_t * team,kmp_info_t * master_th,int master_gtid,int fork_teams_workers)9390b57cec5SDimitry Andric static void __kmp_fork_team_threads(kmp_root_t *root, kmp_team_t *team,
940349cc55cSDimitry Andric                                     kmp_info_t *master_th, int master_gtid,
941349cc55cSDimitry Andric                                     int fork_teams_workers) {
9420b57cec5SDimitry Andric   int i;
9430b57cec5SDimitry Andric   int use_hot_team;
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_fork_team_threads: new_nprocs = %d\n", team->t.t_nproc));
9460b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(master_gtid == __kmp_get_gtid());
9470b57cec5SDimitry Andric   KMP_MB();
9480b57cec5SDimitry Andric 
949fe6060f1SDimitry Andric   /* first, let's setup the primary thread */
9500b57cec5SDimitry Andric   master_th->th.th_info.ds.ds_tid = 0;
9510b57cec5SDimitry Andric   master_th->th.th_team = team;
9520b57cec5SDimitry Andric   master_th->th.th_team_nproc = team->t.t_nproc;
9530b57cec5SDimitry Andric   master_th->th.th_team_master = master_th;
9540b57cec5SDimitry Andric   master_th->th.th_team_serialized = FALSE;
9550b57cec5SDimitry Andric   master_th->th.th_dispatch = &team->t.t_dispatch[0];
9560b57cec5SDimitry Andric 
9570b57cec5SDimitry Andric /* make sure we are not the optimized hot team */
9580b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
9590b57cec5SDimitry Andric   use_hot_team = 0;
9600b57cec5SDimitry Andric   kmp_hot_team_ptr_t *hot_teams = master_th->th.th_hot_teams;
9610b57cec5SDimitry Andric   if (hot_teams) { // hot teams array is not allocated if
9620b57cec5SDimitry Andric     // KMP_HOT_TEAMS_MAX_LEVEL=0
9630b57cec5SDimitry Andric     int level = team->t.t_active_level - 1; // index in array of hot teams
9640b57cec5SDimitry Andric     if (master_th->th.th_teams_microtask) { // are we inside the teams?
9650b57cec5SDimitry Andric       if (master_th->th.th_teams_size.nteams > 1) {
9660b57cec5SDimitry Andric         ++level; // level was not increased in teams construct for
9670b57cec5SDimitry Andric         // team_of_masters
9680b57cec5SDimitry Andric       }
9690b57cec5SDimitry Andric       if (team->t.t_pkfn != (microtask_t)__kmp_teams_master &&
9700b57cec5SDimitry Andric           master_th->th.th_teams_level == team->t.t_level) {
9710b57cec5SDimitry Andric         ++level; // level was not increased in teams construct for
9720b57cec5SDimitry Andric         // team_of_workers before the parallel
9730b57cec5SDimitry Andric       } // team->t.t_level will be increased inside parallel
9740b57cec5SDimitry Andric     }
9750b57cec5SDimitry Andric     if (level < __kmp_hot_teams_max_level) {
9760b57cec5SDimitry Andric       if (hot_teams[level].hot_team) {
9770b57cec5SDimitry Andric         // hot team has already been allocated for given level
9780b57cec5SDimitry Andric         KMP_DEBUG_ASSERT(hot_teams[level].hot_team == team);
9790b57cec5SDimitry Andric         use_hot_team = 1; // the team is ready to use
9800b57cec5SDimitry Andric       } else {
9810b57cec5SDimitry Andric         use_hot_team = 0; // AC: threads are not allocated yet
9820b57cec5SDimitry Andric         hot_teams[level].hot_team = team; // remember new hot team
9830b57cec5SDimitry Andric         hot_teams[level].hot_team_nth = team->t.t_nproc;
9840b57cec5SDimitry Andric       }
9850b57cec5SDimitry Andric     } else {
9860b57cec5SDimitry Andric       use_hot_team = 0;
9870b57cec5SDimitry Andric     }
9880b57cec5SDimitry Andric   }
9890b57cec5SDimitry Andric #else
9900b57cec5SDimitry Andric   use_hot_team = team == root->r.r_hot_team;
9910b57cec5SDimitry Andric #endif
9920b57cec5SDimitry Andric   if (!use_hot_team) {
9930b57cec5SDimitry Andric 
994fe6060f1SDimitry Andric     /* install the primary thread */
9950b57cec5SDimitry Andric     team->t.t_threads[0] = master_th;
9960b57cec5SDimitry Andric     __kmp_initialize_info(master_th, team, 0, master_gtid);
9970b57cec5SDimitry Andric 
9980b57cec5SDimitry Andric     /* now, install the worker threads */
9990b57cec5SDimitry Andric     for (i = 1; i < team->t.t_nproc; i++) {
10000b57cec5SDimitry Andric 
10010b57cec5SDimitry Andric       /* fork or reallocate a new thread and install it in team */
10020b57cec5SDimitry Andric       kmp_info_t *thr = __kmp_allocate_thread(root, team, i);
10030b57cec5SDimitry Andric       team->t.t_threads[i] = thr;
10040b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(thr);
10050b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(thr->th.th_team == team);
10060b57cec5SDimitry Andric       /* align team and thread arrived states */
10070b57cec5SDimitry Andric       KA_TRACE(20, ("__kmp_fork_team_threads: T#%d(%d:%d) init arrived "
10080b57cec5SDimitry Andric                     "T#%d(%d:%d) join =%llu, plain=%llu\n",
10090b57cec5SDimitry Andric                     __kmp_gtid_from_tid(0, team), team->t.t_id, 0,
10100b57cec5SDimitry Andric                     __kmp_gtid_from_tid(i, team), team->t.t_id, i,
10110b57cec5SDimitry Andric                     team->t.t_bar[bs_forkjoin_barrier].b_arrived,
10120b57cec5SDimitry Andric                     team->t.t_bar[bs_plain_barrier].b_arrived));
10130b57cec5SDimitry Andric       thr->th.th_teams_microtask = master_th->th.th_teams_microtask;
10140b57cec5SDimitry Andric       thr->th.th_teams_level = master_th->th.th_teams_level;
10150b57cec5SDimitry Andric       thr->th.th_teams_size = master_th->th.th_teams_size;
10160b57cec5SDimitry Andric       { // Initialize threads' barrier data.
10170b57cec5SDimitry Andric         int b;
10180b57cec5SDimitry Andric         kmp_balign_t *balign = team->t.t_threads[i]->th.th_bar;
10190b57cec5SDimitry Andric         for (b = 0; b < bs_last_barrier; ++b) {
10200b57cec5SDimitry Andric           balign[b].bb.b_arrived = team->t.t_bar[b].b_arrived;
10210b57cec5SDimitry Andric           KMP_DEBUG_ASSERT(balign[b].bb.wait_flag != KMP_BARRIER_PARENT_FLAG);
10220b57cec5SDimitry Andric #if USE_DEBUGGER
10230b57cec5SDimitry Andric           balign[b].bb.b_worker_arrived = team->t.t_bar[b].b_team_arrived;
10240b57cec5SDimitry Andric #endif
10250b57cec5SDimitry Andric         }
10260b57cec5SDimitry Andric       }
10270b57cec5SDimitry Andric     }
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
1030349cc55cSDimitry Andric     // Do not partition the places list for teams construct workers who
1031349cc55cSDimitry Andric     // haven't actually been forked to do real work yet. This partitioning
1032349cc55cSDimitry Andric     // will take place in the parallel region nested within the teams construct.
1033349cc55cSDimitry Andric     if (!fork_teams_workers) {
10340b57cec5SDimitry Andric       __kmp_partition_places(team);
1035349cc55cSDimitry Andric     }
10360b57cec5SDimitry Andric #endif
1037bdd1243dSDimitry Andric 
1038bdd1243dSDimitry Andric     if (team->t.t_nproc > 1 &&
1039bdd1243dSDimitry Andric         __kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
1040bdd1243dSDimitry Andric       team->t.b->update_num_threads(team->t.t_nproc);
1041bdd1243dSDimitry Andric       __kmp_add_threads_to_team(team, team->t.t_nproc);
1042bdd1243dSDimitry Andric     }
10430b57cec5SDimitry Andric   }
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric   if (__kmp_display_affinity && team->t.t_display_affinity != 1) {
10460b57cec5SDimitry Andric     for (i = 0; i < team->t.t_nproc; i++) {
10470b57cec5SDimitry Andric       kmp_info_t *thr = team->t.t_threads[i];
10480b57cec5SDimitry Andric       if (thr->th.th_prev_num_threads != team->t.t_nproc ||
10490b57cec5SDimitry Andric           thr->th.th_prev_level != team->t.t_level) {
10500b57cec5SDimitry Andric         team->t.t_display_affinity = 1;
10510b57cec5SDimitry Andric         break;
10520b57cec5SDimitry Andric       }
10530b57cec5SDimitry Andric     }
10540b57cec5SDimitry Andric   }
10550b57cec5SDimitry Andric 
10560b57cec5SDimitry Andric   KMP_MB();
10570b57cec5SDimitry Andric }
10580b57cec5SDimitry Andric 
10590b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
10600b57cec5SDimitry Andric // Propagate any changes to the floating point control registers out to the team
10610b57cec5SDimitry Andric // We try to avoid unnecessary writes to the relevant cache line in the team
10620b57cec5SDimitry Andric // structure, so we don't make changes unless they are needed.
propagateFPControl(kmp_team_t * team)10630b57cec5SDimitry Andric inline static void propagateFPControl(kmp_team_t *team) {
10640b57cec5SDimitry Andric   if (__kmp_inherit_fp_control) {
10650b57cec5SDimitry Andric     kmp_int16 x87_fpu_control_word;
10660b57cec5SDimitry Andric     kmp_uint32 mxcsr;
10670b57cec5SDimitry Andric 
1068fe6060f1SDimitry Andric     // Get primary thread's values of FPU control flags (both X87 and vector)
10690b57cec5SDimitry Andric     __kmp_store_x87_fpu_control_word(&x87_fpu_control_word);
10700b57cec5SDimitry Andric     __kmp_store_mxcsr(&mxcsr);
10710b57cec5SDimitry Andric     mxcsr &= KMP_X86_MXCSR_MASK;
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric     // There is no point looking at t_fp_control_saved here.
10740b57cec5SDimitry Andric     // If it is TRUE, we still have to update the values if they are different
10750b57cec5SDimitry Andric     // from those we now have. If it is FALSE we didn't save anything yet, but
10760b57cec5SDimitry Andric     // our objective is the same. We have to ensure that the values in the team
10770b57cec5SDimitry Andric     // are the same as those we have.
10780b57cec5SDimitry Andric     // So, this code achieves what we need whether or not t_fp_control_saved is
10790b57cec5SDimitry Andric     // true. By checking whether the value needs updating we avoid unnecessary
10800b57cec5SDimitry Andric     // writes that would put the cache-line into a written state, causing all
10810b57cec5SDimitry Andric     // threads in the team to have to read it again.
10820b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_x87_fpu_control_word, x87_fpu_control_word);
10830b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_mxcsr, mxcsr);
10840b57cec5SDimitry Andric     // Although we don't use this value, other code in the runtime wants to know
10850b57cec5SDimitry Andric     // whether it should restore them. So we must ensure it is correct.
10860b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_fp_control_saved, TRUE);
10870b57cec5SDimitry Andric   } else {
10880b57cec5SDimitry Andric     // Similarly here. Don't write to this cache-line in the team structure
10890b57cec5SDimitry Andric     // unless we have to.
10900b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_fp_control_saved, FALSE);
10910b57cec5SDimitry Andric   }
10920b57cec5SDimitry Andric }
10930b57cec5SDimitry Andric 
10940b57cec5SDimitry Andric // Do the opposite, setting the hardware registers to the updated values from
10950b57cec5SDimitry Andric // the team.
updateHWFPControl(kmp_team_t * team)10960b57cec5SDimitry Andric inline static void updateHWFPControl(kmp_team_t *team) {
10970b57cec5SDimitry Andric   if (__kmp_inherit_fp_control && team->t.t_fp_control_saved) {
10980b57cec5SDimitry Andric     // Only reset the fp control regs if they have been changed in the team.
10990b57cec5SDimitry Andric     // the parallel region that we are exiting.
11000b57cec5SDimitry Andric     kmp_int16 x87_fpu_control_word;
11010b57cec5SDimitry Andric     kmp_uint32 mxcsr;
11020b57cec5SDimitry Andric     __kmp_store_x87_fpu_control_word(&x87_fpu_control_word);
11030b57cec5SDimitry Andric     __kmp_store_mxcsr(&mxcsr);
11040b57cec5SDimitry Andric     mxcsr &= KMP_X86_MXCSR_MASK;
11050b57cec5SDimitry Andric 
11060b57cec5SDimitry Andric     if (team->t.t_x87_fpu_control_word != x87_fpu_control_word) {
11070b57cec5SDimitry Andric       __kmp_clear_x87_fpu_status_word();
11080b57cec5SDimitry Andric       __kmp_load_x87_fpu_control_word(&team->t.t_x87_fpu_control_word);
11090b57cec5SDimitry Andric     }
11100b57cec5SDimitry Andric 
11110b57cec5SDimitry Andric     if (team->t.t_mxcsr != mxcsr) {
11120b57cec5SDimitry Andric       __kmp_load_mxcsr(&team->t.t_mxcsr);
11130b57cec5SDimitry Andric     }
11140b57cec5SDimitry Andric   }
11150b57cec5SDimitry Andric }
11160b57cec5SDimitry Andric #else
11170b57cec5SDimitry Andric #define propagateFPControl(x) ((void)0)
11180b57cec5SDimitry Andric #define updateHWFPControl(x) ((void)0)
11190b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
11200b57cec5SDimitry Andric 
11210b57cec5SDimitry Andric static void __kmp_alloc_argv_entries(int argc, kmp_team_t *team,
11220b57cec5SDimitry Andric                                      int realloc); // forward declaration
11230b57cec5SDimitry Andric 
11240b57cec5SDimitry Andric /* Run a parallel region that has been serialized, so runs only in a team of the
1125fe6060f1SDimitry Andric    single primary thread. */
__kmp_serialized_parallel(ident_t * loc,kmp_int32 global_tid)11260b57cec5SDimitry Andric void __kmp_serialized_parallel(ident_t *loc, kmp_int32 global_tid) {
11270b57cec5SDimitry Andric   kmp_info_t *this_thr;
11280b57cec5SDimitry Andric   kmp_team_t *serial_team;
11290b57cec5SDimitry Andric 
11300b57cec5SDimitry Andric   KC_TRACE(10, ("__kmpc_serialized_parallel: called by T#%d\n", global_tid));
11310b57cec5SDimitry Andric 
11320b57cec5SDimitry Andric   /* Skip all this code for autopar serialized loops since it results in
11330b57cec5SDimitry Andric      unacceptable overhead */
11340b57cec5SDimitry Andric   if (loc != NULL && (loc->flags & KMP_IDENT_AUTOPAR))
11350b57cec5SDimitry Andric     return;
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric   if (!TCR_4(__kmp_init_parallel))
11380b57cec5SDimitry Andric     __kmp_parallel_initialize();
11390b57cec5SDimitry Andric   __kmp_resume_if_soft_paused();
11400b57cec5SDimitry Andric 
11410b57cec5SDimitry Andric   this_thr = __kmp_threads[global_tid];
11420b57cec5SDimitry Andric   serial_team = this_thr->th.th_serial_team;
11430b57cec5SDimitry Andric 
11440b57cec5SDimitry Andric   /* utilize the serialized team held by this thread */
11450b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(serial_team);
11460b57cec5SDimitry Andric   KMP_MB();
11470b57cec5SDimitry Andric 
11480b57cec5SDimitry Andric   if (__kmp_tasking_mode != tskm_immediate_exec) {
11490b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(
11500b57cec5SDimitry Andric         this_thr->th.th_task_team ==
11510b57cec5SDimitry Andric         this_thr->th.th_team->t.t_task_team[this_thr->th.th_task_state]);
11520b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(serial_team->t.t_task_team[this_thr->th.th_task_state] ==
11530b57cec5SDimitry Andric                      NULL);
11540b57cec5SDimitry Andric     KA_TRACE(20, ("__kmpc_serialized_parallel: T#%d pushing task_team %p / "
11550b57cec5SDimitry Andric                   "team %p, new task_team = NULL\n",
11560b57cec5SDimitry Andric                   global_tid, this_thr->th.th_task_team, this_thr->th.th_team));
11570b57cec5SDimitry Andric     this_thr->th.th_task_team = NULL;
11580b57cec5SDimitry Andric   }
11590b57cec5SDimitry Andric 
11600b57cec5SDimitry Andric   kmp_proc_bind_t proc_bind = this_thr->th.th_set_proc_bind;
11610b57cec5SDimitry Andric   if (this_thr->th.th_current_task->td_icvs.proc_bind == proc_bind_false) {
11620b57cec5SDimitry Andric     proc_bind = proc_bind_false;
11630b57cec5SDimitry Andric   } else if (proc_bind == proc_bind_default) {
11640b57cec5SDimitry Andric     // No proc_bind clause was specified, so use the current value
11650b57cec5SDimitry Andric     // of proc-bind-var for this parallel region.
11660b57cec5SDimitry Andric     proc_bind = this_thr->th.th_current_task->td_icvs.proc_bind;
11670b57cec5SDimitry Andric   }
11680b57cec5SDimitry Andric   // Reset for next parallel region
11690b57cec5SDimitry Andric   this_thr->th.th_set_proc_bind = proc_bind_default;
11700b57cec5SDimitry Andric 
117106c3fb27SDimitry Andric   // Reset num_threads for next parallel region
117206c3fb27SDimitry Andric   this_thr->th.th_set_nproc = 0;
117306c3fb27SDimitry Andric 
11740b57cec5SDimitry Andric #if OMPT_SUPPORT
11750b57cec5SDimitry Andric   ompt_data_t ompt_parallel_data = ompt_data_none;
11760b57cec5SDimitry Andric   void *codeptr = OMPT_LOAD_RETURN_ADDRESS(global_tid);
11770b57cec5SDimitry Andric   if (ompt_enabled.enabled &&
11780b57cec5SDimitry Andric       this_thr->th.ompt_thread_info.state != ompt_state_overhead) {
11790b57cec5SDimitry Andric 
11800b57cec5SDimitry Andric     ompt_task_info_t *parent_task_info;
11810b57cec5SDimitry Andric     parent_task_info = OMPT_CUR_TASK_INFO(this_thr);
11820b57cec5SDimitry Andric 
11830b57cec5SDimitry Andric     parent_task_info->frame.enter_frame.ptr = OMPT_GET_FRAME_ADDRESS(0);
11840b57cec5SDimitry Andric     if (ompt_enabled.ompt_callback_parallel_begin) {
11850b57cec5SDimitry Andric       int team_size = 1;
11860b57cec5SDimitry Andric 
11870b57cec5SDimitry Andric       ompt_callbacks.ompt_callback(ompt_callback_parallel_begin)(
11880b57cec5SDimitry Andric           &(parent_task_info->task_data), &(parent_task_info->frame),
1189489b1cf2SDimitry Andric           &ompt_parallel_data, team_size,
1190489b1cf2SDimitry Andric           ompt_parallel_invoker_program | ompt_parallel_team, codeptr);
11910b57cec5SDimitry Andric     }
11920b57cec5SDimitry Andric   }
11930b57cec5SDimitry Andric #endif // OMPT_SUPPORT
11940b57cec5SDimitry Andric 
11950b57cec5SDimitry Andric   if (this_thr->th.th_team != serial_team) {
11960b57cec5SDimitry Andric     // Nested level will be an index in the nested nthreads array
11970b57cec5SDimitry Andric     int level = this_thr->th.th_team->t.t_level;
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric     if (serial_team->t.t_serialized) {
12000b57cec5SDimitry Andric       /* this serial team was already used
12010b57cec5SDimitry Andric          TODO increase performance by making this locks more specific */
12020b57cec5SDimitry Andric       kmp_team_t *new_team;
12030b57cec5SDimitry Andric 
12040b57cec5SDimitry Andric       __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
12050b57cec5SDimitry Andric 
12060b57cec5SDimitry Andric       new_team =
12070b57cec5SDimitry Andric           __kmp_allocate_team(this_thr->th.th_root, 1, 1,
12080b57cec5SDimitry Andric #if OMPT_SUPPORT
12090b57cec5SDimitry Andric                               ompt_parallel_data,
12100b57cec5SDimitry Andric #endif
12110b57cec5SDimitry Andric                               proc_bind, &this_thr->th.th_current_task->td_icvs,
12120b57cec5SDimitry Andric                               0 USE_NESTED_HOT_ARG(NULL));
12130b57cec5SDimitry Andric       __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
12140b57cec5SDimitry Andric       KMP_ASSERT(new_team);
12150b57cec5SDimitry Andric 
12160b57cec5SDimitry Andric       /* setup new serialized team and install it */
12170b57cec5SDimitry Andric       new_team->t.t_threads[0] = this_thr;
12180b57cec5SDimitry Andric       new_team->t.t_parent = this_thr->th.th_team;
12190b57cec5SDimitry Andric       serial_team = new_team;
12200b57cec5SDimitry Andric       this_thr->th.th_serial_team = serial_team;
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric       KF_TRACE(
12230b57cec5SDimitry Andric           10,
12240b57cec5SDimitry Andric           ("__kmpc_serialized_parallel: T#%d allocated new serial team %p\n",
12250b57cec5SDimitry Andric            global_tid, serial_team));
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric       /* TODO the above breaks the requirement that if we run out of resources,
12280b57cec5SDimitry Andric          then we can still guarantee that serialized teams are ok, since we may
12290b57cec5SDimitry Andric          need to allocate a new one */
12300b57cec5SDimitry Andric     } else {
12310b57cec5SDimitry Andric       KF_TRACE(
12320b57cec5SDimitry Andric           10,
12330b57cec5SDimitry Andric           ("__kmpc_serialized_parallel: T#%d reusing cached serial team %p\n",
12340b57cec5SDimitry Andric            global_tid, serial_team));
12350b57cec5SDimitry Andric     }
12360b57cec5SDimitry Andric 
12370b57cec5SDimitry Andric     /* we have to initialize this serial team */
12380b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(serial_team->t.t_threads);
12390b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(serial_team->t.t_threads[0] == this_thr);
12400b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(this_thr->th.th_team != serial_team);
12410b57cec5SDimitry Andric     serial_team->t.t_ident = loc;
12420b57cec5SDimitry Andric     serial_team->t.t_serialized = 1;
12430b57cec5SDimitry Andric     serial_team->t.t_nproc = 1;
12440b57cec5SDimitry Andric     serial_team->t.t_parent = this_thr->th.th_team;
12450b57cec5SDimitry Andric     serial_team->t.t_sched.sched = this_thr->th.th_team->t.t_sched.sched;
12460b57cec5SDimitry Andric     this_thr->th.th_team = serial_team;
12470b57cec5SDimitry Andric     serial_team->t.t_master_tid = this_thr->th.th_info.ds.ds_tid;
12480b57cec5SDimitry Andric 
1249349cc55cSDimitry Andric     KF_TRACE(10, ("__kmpc_serialized_parallel: T#%d curtask=%p\n", global_tid,
12500b57cec5SDimitry Andric                   this_thr->th.th_current_task));
12510b57cec5SDimitry Andric     KMP_ASSERT(this_thr->th.th_current_task->td_flags.executing == 1);
12520b57cec5SDimitry Andric     this_thr->th.th_current_task->td_flags.executing = 0;
12530b57cec5SDimitry Andric 
12540b57cec5SDimitry Andric     __kmp_push_current_task_to_thread(this_thr, serial_team, 0);
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric     /* TODO: GEH: do ICVs work for nested serialized teams? Don't we need an
12570b57cec5SDimitry Andric        implicit task for each serialized task represented by
12580b57cec5SDimitry Andric        team->t.t_serialized? */
12590b57cec5SDimitry Andric     copy_icvs(&this_thr->th.th_current_task->td_icvs,
12600b57cec5SDimitry Andric               &this_thr->th.th_current_task->td_parent->td_icvs);
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric     // Thread value exists in the nested nthreads array for the next nested
12630b57cec5SDimitry Andric     // level
12640b57cec5SDimitry Andric     if (__kmp_nested_nth.used && (level + 1 < __kmp_nested_nth.used)) {
12650b57cec5SDimitry Andric       this_thr->th.th_current_task->td_icvs.nproc =
12660b57cec5SDimitry Andric           __kmp_nested_nth.nth[level + 1];
12670b57cec5SDimitry Andric     }
12680b57cec5SDimitry Andric 
12690b57cec5SDimitry Andric     if (__kmp_nested_proc_bind.used &&
12700b57cec5SDimitry Andric         (level + 1 < __kmp_nested_proc_bind.used)) {
12710b57cec5SDimitry Andric       this_thr->th.th_current_task->td_icvs.proc_bind =
12720b57cec5SDimitry Andric           __kmp_nested_proc_bind.bind_types[level + 1];
12730b57cec5SDimitry Andric     }
12740b57cec5SDimitry Andric 
12750b57cec5SDimitry Andric #if USE_DEBUGGER
12760b57cec5SDimitry Andric     serial_team->t.t_pkfn = (microtask_t)(~0); // For the debugger.
12770b57cec5SDimitry Andric #endif
12780b57cec5SDimitry Andric     this_thr->th.th_info.ds.ds_tid = 0;
12790b57cec5SDimitry Andric 
12800b57cec5SDimitry Andric     /* set thread cache values */
12810b57cec5SDimitry Andric     this_thr->th.th_team_nproc = 1;
12820b57cec5SDimitry Andric     this_thr->th.th_team_master = this_thr;
12830b57cec5SDimitry Andric     this_thr->th.th_team_serialized = 1;
12840b57cec5SDimitry Andric 
12850b57cec5SDimitry Andric     serial_team->t.t_level = serial_team->t.t_parent->t.t_level + 1;
12860b57cec5SDimitry Andric     serial_team->t.t_active_level = serial_team->t.t_parent->t.t_active_level;
12870b57cec5SDimitry Andric     serial_team->t.t_def_allocator = this_thr->th.th_def_allocator; // save
12880b57cec5SDimitry Andric 
12890b57cec5SDimitry Andric     propagateFPControl(serial_team);
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric     /* check if we need to allocate dispatch buffers stack */
12920b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(serial_team->t.t_dispatch);
12930b57cec5SDimitry Andric     if (!serial_team->t.t_dispatch->th_disp_buffer) {
12940b57cec5SDimitry Andric       serial_team->t.t_dispatch->th_disp_buffer =
12950b57cec5SDimitry Andric           (dispatch_private_info_t *)__kmp_allocate(
12960b57cec5SDimitry Andric               sizeof(dispatch_private_info_t));
12970b57cec5SDimitry Andric     }
12980b57cec5SDimitry Andric     this_thr->th.th_dispatch = serial_team->t.t_dispatch;
12990b57cec5SDimitry Andric 
13000b57cec5SDimitry Andric     KMP_MB();
13010b57cec5SDimitry Andric 
13020b57cec5SDimitry Andric   } else {
13030b57cec5SDimitry Andric     /* this serialized team is already being used,
13040b57cec5SDimitry Andric      * that's fine, just add another nested level */
13050b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(this_thr->th.th_team == serial_team);
13060b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(serial_team->t.t_threads);
13070b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(serial_team->t.t_threads[0] == this_thr);
13080b57cec5SDimitry Andric     ++serial_team->t.t_serialized;
13090b57cec5SDimitry Andric     this_thr->th.th_team_serialized = serial_team->t.t_serialized;
13100b57cec5SDimitry Andric 
13110b57cec5SDimitry Andric     // Nested level will be an index in the nested nthreads array
13120b57cec5SDimitry Andric     int level = this_thr->th.th_team->t.t_level;
13130b57cec5SDimitry Andric     // Thread value exists in the nested nthreads array for the next nested
13140b57cec5SDimitry Andric     // level
13150b57cec5SDimitry Andric     if (__kmp_nested_nth.used && (level + 1 < __kmp_nested_nth.used)) {
13160b57cec5SDimitry Andric       this_thr->th.th_current_task->td_icvs.nproc =
13170b57cec5SDimitry Andric           __kmp_nested_nth.nth[level + 1];
13180b57cec5SDimitry Andric     }
13190b57cec5SDimitry Andric     serial_team->t.t_level++;
13200b57cec5SDimitry Andric     KF_TRACE(10, ("__kmpc_serialized_parallel: T#%d increasing nesting level "
13210b57cec5SDimitry Andric                   "of serial team %p to %d\n",
13220b57cec5SDimitry Andric                   global_tid, serial_team, serial_team->t.t_level));
13230b57cec5SDimitry Andric 
13240b57cec5SDimitry Andric     /* allocate/push dispatch buffers stack */
13250b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(serial_team->t.t_dispatch);
13260b57cec5SDimitry Andric     {
13270b57cec5SDimitry Andric       dispatch_private_info_t *disp_buffer =
13280b57cec5SDimitry Andric           (dispatch_private_info_t *)__kmp_allocate(
13290b57cec5SDimitry Andric               sizeof(dispatch_private_info_t));
13300b57cec5SDimitry Andric       disp_buffer->next = serial_team->t.t_dispatch->th_disp_buffer;
13310b57cec5SDimitry Andric       serial_team->t.t_dispatch->th_disp_buffer = disp_buffer;
13320b57cec5SDimitry Andric     }
13330b57cec5SDimitry Andric     this_thr->th.th_dispatch = serial_team->t.t_dispatch;
13340b57cec5SDimitry Andric 
13350b57cec5SDimitry Andric     KMP_MB();
13360b57cec5SDimitry Andric   }
13370b57cec5SDimitry Andric   KMP_CHECK_UPDATE(serial_team->t.t_cancel_request, cancel_noreq);
13380b57cec5SDimitry Andric 
13390b57cec5SDimitry Andric   // Perform the display affinity functionality for
13400b57cec5SDimitry Andric   // serialized parallel regions
13410b57cec5SDimitry Andric   if (__kmp_display_affinity) {
13420b57cec5SDimitry Andric     if (this_thr->th.th_prev_level != serial_team->t.t_level ||
13430b57cec5SDimitry Andric         this_thr->th.th_prev_num_threads != 1) {
13440b57cec5SDimitry Andric       // NULL means use the affinity-format-var ICV
13450b57cec5SDimitry Andric       __kmp_aux_display_affinity(global_tid, NULL);
13460b57cec5SDimitry Andric       this_thr->th.th_prev_level = serial_team->t.t_level;
13470b57cec5SDimitry Andric       this_thr->th.th_prev_num_threads = 1;
13480b57cec5SDimitry Andric     }
13490b57cec5SDimitry Andric   }
13500b57cec5SDimitry Andric 
13510b57cec5SDimitry Andric   if (__kmp_env_consistency_check)
13520b57cec5SDimitry Andric     __kmp_push_parallel(global_tid, NULL);
13530b57cec5SDimitry Andric #if OMPT_SUPPORT
13540b57cec5SDimitry Andric   serial_team->t.ompt_team_info.master_return_address = codeptr;
13550b57cec5SDimitry Andric   if (ompt_enabled.enabled &&
13560b57cec5SDimitry Andric       this_thr->th.ompt_thread_info.state != ompt_state_overhead) {
1357fe6060f1SDimitry Andric     OMPT_CUR_TASK_INFO(this_thr)->frame.exit_frame.ptr =
1358fe6060f1SDimitry Andric         OMPT_GET_FRAME_ADDRESS(0);
13590b57cec5SDimitry Andric 
13600b57cec5SDimitry Andric     ompt_lw_taskteam_t lw_taskteam;
13610b57cec5SDimitry Andric     __ompt_lw_taskteam_init(&lw_taskteam, this_thr, global_tid,
13620b57cec5SDimitry Andric                             &ompt_parallel_data, codeptr);
13630b57cec5SDimitry Andric 
13640b57cec5SDimitry Andric     __ompt_lw_taskteam_link(&lw_taskteam, this_thr, 1);
13650b57cec5SDimitry Andric     // don't use lw_taskteam after linking. content was swaped
13660b57cec5SDimitry Andric 
13670b57cec5SDimitry Andric     /* OMPT implicit task begin */
13680b57cec5SDimitry Andric     if (ompt_enabled.ompt_callback_implicit_task) {
13690b57cec5SDimitry Andric       ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
13700b57cec5SDimitry Andric           ompt_scope_begin, OMPT_CUR_TEAM_DATA(this_thr),
1371fe6060f1SDimitry Andric           OMPT_CUR_TASK_DATA(this_thr), 1, __kmp_tid_from_gtid(global_tid),
1372fe6060f1SDimitry Andric           ompt_task_implicit); // TODO: Can this be ompt_task_initial?
1373fe6060f1SDimitry Andric       OMPT_CUR_TASK_INFO(this_thr)->thread_num =
1374fe6060f1SDimitry Andric           __kmp_tid_from_gtid(global_tid);
13750b57cec5SDimitry Andric     }
13760b57cec5SDimitry Andric 
13770b57cec5SDimitry Andric     /* OMPT state */
13780b57cec5SDimitry Andric     this_thr->th.ompt_thread_info.state = ompt_state_work_parallel;
1379fe6060f1SDimitry Andric     OMPT_CUR_TASK_INFO(this_thr)->frame.exit_frame.ptr =
1380fe6060f1SDimitry Andric         OMPT_GET_FRAME_ADDRESS(0);
13810b57cec5SDimitry Andric   }
13820b57cec5SDimitry Andric #endif
13830b57cec5SDimitry Andric }
13840b57cec5SDimitry Andric 
1385bdd1243dSDimitry Andric // Test if this fork is for a team closely nested in a teams construct
__kmp_is_fork_in_teams(kmp_info_t * master_th,microtask_t microtask,int level,int teams_level,kmp_va_list ap)1386bdd1243dSDimitry Andric static inline bool __kmp_is_fork_in_teams(kmp_info_t *master_th,
1387bdd1243dSDimitry Andric                                           microtask_t microtask, int level,
1388bdd1243dSDimitry Andric                                           int teams_level, kmp_va_list ap) {
1389bdd1243dSDimitry Andric   return (master_th->th.th_teams_microtask && ap &&
1390bdd1243dSDimitry Andric           microtask != (microtask_t)__kmp_teams_master && level == teams_level);
1391bdd1243dSDimitry Andric }
1392bdd1243dSDimitry Andric 
1393bdd1243dSDimitry Andric // Test if this fork is for the teams construct, i.e. to form the outer league
1394bdd1243dSDimitry Andric // of teams
__kmp_is_entering_teams(int active_level,int level,int teams_level,kmp_va_list ap)1395bdd1243dSDimitry Andric static inline bool __kmp_is_entering_teams(int active_level, int level,
1396bdd1243dSDimitry Andric                                            int teams_level, kmp_va_list ap) {
1397bdd1243dSDimitry Andric   return ((ap == NULL && active_level == 0) ||
1398bdd1243dSDimitry Andric           (ap && teams_level > 0 && teams_level == level));
1399bdd1243dSDimitry Andric }
1400bdd1243dSDimitry Andric 
1401bdd1243dSDimitry Andric // AC: This is start of parallel that is nested inside teams construct.
1402bdd1243dSDimitry Andric // The team is actual (hot), all workers are ready at the fork barrier.
1403bdd1243dSDimitry Andric // No lock needed to initialize the team a bit, then free workers.
1404bdd1243dSDimitry Andric static inline int
__kmp_fork_in_teams(ident_t * loc,int gtid,kmp_team_t * parent_team,kmp_int32 argc,kmp_info_t * master_th,kmp_root_t * root,enum fork_context_e call_context,microtask_t microtask,launch_t invoker,int master_set_numthreads,int level,ompt_data_t ompt_parallel_data,void * return_address,kmp_va_list ap)1405bdd1243dSDimitry Andric __kmp_fork_in_teams(ident_t *loc, int gtid, kmp_team_t *parent_team,
1406bdd1243dSDimitry Andric                     kmp_int32 argc, kmp_info_t *master_th, kmp_root_t *root,
1407bdd1243dSDimitry Andric                     enum fork_context_e call_context, microtask_t microtask,
1408bdd1243dSDimitry Andric                     launch_t invoker, int master_set_numthreads, int level,
1409bdd1243dSDimitry Andric #if OMPT_SUPPORT
1410bdd1243dSDimitry Andric                     ompt_data_t ompt_parallel_data, void *return_address,
1411bdd1243dSDimitry Andric #endif
1412bdd1243dSDimitry Andric                     kmp_va_list ap) {
1413bdd1243dSDimitry Andric   void **argv;
1414bdd1243dSDimitry Andric   int i;
1415bdd1243dSDimitry Andric 
1416bdd1243dSDimitry Andric   parent_team->t.t_ident = loc;
1417bdd1243dSDimitry Andric   __kmp_alloc_argv_entries(argc, parent_team, TRUE);
1418bdd1243dSDimitry Andric   parent_team->t.t_argc = argc;
1419bdd1243dSDimitry Andric   argv = (void **)parent_team->t.t_argv;
1420bdd1243dSDimitry Andric   for (i = argc - 1; i >= 0; --i) {
1421bdd1243dSDimitry Andric     *argv++ = va_arg(kmp_va_deref(ap), void *);
1422bdd1243dSDimitry Andric   }
1423bdd1243dSDimitry Andric   // Increment our nested depth levels, but not increase the serialization
1424bdd1243dSDimitry Andric   if (parent_team == master_th->th.th_serial_team) {
1425bdd1243dSDimitry Andric     // AC: we are in serialized parallel
1426bdd1243dSDimitry Andric     __kmpc_serialized_parallel(loc, gtid);
1427bdd1243dSDimitry Andric     KMP_DEBUG_ASSERT(parent_team->t.t_serialized > 1);
1428bdd1243dSDimitry Andric 
1429bdd1243dSDimitry Andric     if (call_context == fork_context_gnu) {
1430bdd1243dSDimitry Andric       // AC: need to decrement t_serialized for enquiry functions to work
1431bdd1243dSDimitry Andric       // correctly, will restore at join time
1432bdd1243dSDimitry Andric       parent_team->t.t_serialized--;
1433bdd1243dSDimitry Andric       return TRUE;
1434bdd1243dSDimitry Andric     }
1435bdd1243dSDimitry Andric 
1436bdd1243dSDimitry Andric #if OMPD_SUPPORT
1437bdd1243dSDimitry Andric     parent_team->t.t_pkfn = microtask;
1438bdd1243dSDimitry Andric #endif
1439bdd1243dSDimitry Andric 
1440bdd1243dSDimitry Andric #if OMPT_SUPPORT
1441bdd1243dSDimitry Andric     void *dummy;
1442bdd1243dSDimitry Andric     void **exit_frame_p;
1443bdd1243dSDimitry Andric     ompt_data_t *implicit_task_data;
1444bdd1243dSDimitry Andric     ompt_lw_taskteam_t lw_taskteam;
1445bdd1243dSDimitry Andric 
1446bdd1243dSDimitry Andric     if (ompt_enabled.enabled) {
1447bdd1243dSDimitry Andric       __ompt_lw_taskteam_init(&lw_taskteam, master_th, gtid,
1448bdd1243dSDimitry Andric                               &ompt_parallel_data, return_address);
1449bdd1243dSDimitry Andric       exit_frame_p = &(lw_taskteam.ompt_task_info.frame.exit_frame.ptr);
1450bdd1243dSDimitry Andric 
1451bdd1243dSDimitry Andric       __ompt_lw_taskteam_link(&lw_taskteam, master_th, 0);
1452bdd1243dSDimitry Andric       // Don't use lw_taskteam after linking. Content was swapped.
1453bdd1243dSDimitry Andric 
1454bdd1243dSDimitry Andric       /* OMPT implicit task begin */
1455bdd1243dSDimitry Andric       implicit_task_data = OMPT_CUR_TASK_DATA(master_th);
1456bdd1243dSDimitry Andric       if (ompt_enabled.ompt_callback_implicit_task) {
1457bdd1243dSDimitry Andric         OMPT_CUR_TASK_INFO(master_th)->thread_num = __kmp_tid_from_gtid(gtid);
1458bdd1243dSDimitry Andric         ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1459bdd1243dSDimitry Andric             ompt_scope_begin, OMPT_CUR_TEAM_DATA(master_th), implicit_task_data,
1460bdd1243dSDimitry Andric             1, OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_implicit);
1461bdd1243dSDimitry Andric       }
1462bdd1243dSDimitry Andric 
1463bdd1243dSDimitry Andric       /* OMPT state */
1464bdd1243dSDimitry Andric       master_th->th.ompt_thread_info.state = ompt_state_work_parallel;
1465bdd1243dSDimitry Andric     } else {
1466bdd1243dSDimitry Andric       exit_frame_p = &dummy;
1467bdd1243dSDimitry Andric     }
1468bdd1243dSDimitry Andric #endif
1469bdd1243dSDimitry Andric 
1470bdd1243dSDimitry Andric     // AC: need to decrement t_serialized for enquiry functions to work
1471bdd1243dSDimitry Andric     // correctly, will restore at join time
1472bdd1243dSDimitry Andric     parent_team->t.t_serialized--;
1473bdd1243dSDimitry Andric 
1474bdd1243dSDimitry Andric     {
1475bdd1243dSDimitry Andric       KMP_TIME_PARTITIONED_BLOCK(OMP_parallel);
1476bdd1243dSDimitry Andric       KMP_SET_THREAD_STATE_BLOCK(IMPLICIT_TASK);
1477bdd1243dSDimitry Andric       __kmp_invoke_microtask(microtask, gtid, 0, argc, parent_team->t.t_argv
1478bdd1243dSDimitry Andric #if OMPT_SUPPORT
1479bdd1243dSDimitry Andric                              ,
1480bdd1243dSDimitry Andric                              exit_frame_p
1481bdd1243dSDimitry Andric #endif
1482bdd1243dSDimitry Andric                              );
1483bdd1243dSDimitry Andric     }
1484bdd1243dSDimitry Andric 
1485bdd1243dSDimitry Andric #if OMPT_SUPPORT
1486bdd1243dSDimitry Andric     if (ompt_enabled.enabled) {
1487bdd1243dSDimitry Andric       *exit_frame_p = NULL;
1488bdd1243dSDimitry Andric       OMPT_CUR_TASK_INFO(master_th)->frame.exit_frame = ompt_data_none;
1489bdd1243dSDimitry Andric       if (ompt_enabled.ompt_callback_implicit_task) {
1490bdd1243dSDimitry Andric         ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1491bdd1243dSDimitry Andric             ompt_scope_end, NULL, implicit_task_data, 1,
1492bdd1243dSDimitry Andric             OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_implicit);
1493bdd1243dSDimitry Andric       }
1494bdd1243dSDimitry Andric       ompt_parallel_data = *OMPT_CUR_TEAM_DATA(master_th);
1495bdd1243dSDimitry Andric       __ompt_lw_taskteam_unlink(master_th);
1496bdd1243dSDimitry Andric       if (ompt_enabled.ompt_callback_parallel_end) {
1497bdd1243dSDimitry Andric         ompt_callbacks.ompt_callback(ompt_callback_parallel_end)(
1498bdd1243dSDimitry Andric             &ompt_parallel_data, OMPT_CUR_TASK_DATA(master_th),
1499bdd1243dSDimitry Andric             OMPT_INVOKER(call_context) | ompt_parallel_team, return_address);
1500bdd1243dSDimitry Andric       }
1501bdd1243dSDimitry Andric       master_th->th.ompt_thread_info.state = ompt_state_overhead;
1502bdd1243dSDimitry Andric     }
1503bdd1243dSDimitry Andric #endif
1504bdd1243dSDimitry Andric     return TRUE;
1505bdd1243dSDimitry Andric   }
1506bdd1243dSDimitry Andric 
1507bdd1243dSDimitry Andric   parent_team->t.t_pkfn = microtask;
1508bdd1243dSDimitry Andric   parent_team->t.t_invoke = invoker;
1509bdd1243dSDimitry Andric   KMP_ATOMIC_INC(&root->r.r_in_parallel);
1510bdd1243dSDimitry Andric   parent_team->t.t_active_level++;
1511bdd1243dSDimitry Andric   parent_team->t.t_level++;
1512bdd1243dSDimitry Andric   parent_team->t.t_def_allocator = master_th->th.th_def_allocator; // save
1513bdd1243dSDimitry Andric 
1514bdd1243dSDimitry Andric   // If the threads allocated to the team are less than the thread limit, update
1515bdd1243dSDimitry Andric   // the thread limit here. th_teams_size.nth is specific to this team nested
1516bdd1243dSDimitry Andric   // in a teams construct, the team is fully created, and we're about to do
1517bdd1243dSDimitry Andric   // the actual fork. Best to do this here so that the subsequent uses below
1518bdd1243dSDimitry Andric   // and in the join have the correct value.
1519bdd1243dSDimitry Andric   master_th->th.th_teams_size.nth = parent_team->t.t_nproc;
1520bdd1243dSDimitry Andric 
1521bdd1243dSDimitry Andric #if OMPT_SUPPORT
1522bdd1243dSDimitry Andric   if (ompt_enabled.enabled) {
1523bdd1243dSDimitry Andric     ompt_lw_taskteam_t lw_taskteam;
1524bdd1243dSDimitry Andric     __ompt_lw_taskteam_init(&lw_taskteam, master_th, gtid, &ompt_parallel_data,
1525bdd1243dSDimitry Andric                             return_address);
1526bdd1243dSDimitry Andric     __ompt_lw_taskteam_link(&lw_taskteam, master_th, 1, true);
1527bdd1243dSDimitry Andric   }
1528bdd1243dSDimitry Andric #endif
1529bdd1243dSDimitry Andric 
1530bdd1243dSDimitry Andric   /* Change number of threads in the team if requested */
1531bdd1243dSDimitry Andric   if (master_set_numthreads) { // The parallel has num_threads clause
1532bdd1243dSDimitry Andric     if (master_set_numthreads <= master_th->th.th_teams_size.nth) {
1533bdd1243dSDimitry Andric       // AC: only can reduce number of threads dynamically, can't increase
1534bdd1243dSDimitry Andric       kmp_info_t **other_threads = parent_team->t.t_threads;
1535bdd1243dSDimitry Andric       // NOTE: if using distributed barrier, we need to run this code block
1536bdd1243dSDimitry Andric       // even when the team size appears not to have changed from the max.
1537bdd1243dSDimitry Andric       int old_proc = master_th->th.th_teams_size.nth;
1538bdd1243dSDimitry Andric       if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
1539bdd1243dSDimitry Andric         __kmp_resize_dist_barrier(parent_team, old_proc, master_set_numthreads);
1540bdd1243dSDimitry Andric         __kmp_add_threads_to_team(parent_team, master_set_numthreads);
1541bdd1243dSDimitry Andric       }
1542bdd1243dSDimitry Andric       parent_team->t.t_nproc = master_set_numthreads;
1543bdd1243dSDimitry Andric       for (i = 0; i < master_set_numthreads; ++i) {
1544bdd1243dSDimitry Andric         other_threads[i]->th.th_team_nproc = master_set_numthreads;
1545bdd1243dSDimitry Andric       }
1546bdd1243dSDimitry Andric     }
1547bdd1243dSDimitry Andric     // Keep extra threads hot in the team for possible next parallels
1548bdd1243dSDimitry Andric     master_th->th.th_set_nproc = 0;
1549bdd1243dSDimitry Andric   }
1550bdd1243dSDimitry Andric 
1551bdd1243dSDimitry Andric #if USE_DEBUGGER
1552bdd1243dSDimitry Andric   if (__kmp_debugging) { // Let debugger override number of threads.
1553bdd1243dSDimitry Andric     int nth = __kmp_omp_num_threads(loc);
1554bdd1243dSDimitry Andric     if (nth > 0) { // 0 means debugger doesn't want to change num threads
1555bdd1243dSDimitry Andric       master_set_numthreads = nth;
1556bdd1243dSDimitry Andric     }
1557bdd1243dSDimitry Andric   }
1558bdd1243dSDimitry Andric #endif
1559bdd1243dSDimitry Andric 
1560bdd1243dSDimitry Andric   // Figure out the proc_bind policy for the nested parallel within teams
1561bdd1243dSDimitry Andric   kmp_proc_bind_t proc_bind = master_th->th.th_set_proc_bind;
1562bdd1243dSDimitry Andric   // proc_bind_default means don't update
1563bdd1243dSDimitry Andric   kmp_proc_bind_t proc_bind_icv = proc_bind_default;
1564bdd1243dSDimitry Andric   if (master_th->th.th_current_task->td_icvs.proc_bind == proc_bind_false) {
1565bdd1243dSDimitry Andric     proc_bind = proc_bind_false;
1566bdd1243dSDimitry Andric   } else {
1567bdd1243dSDimitry Andric     // No proc_bind clause specified; use current proc-bind-var
1568bdd1243dSDimitry Andric     if (proc_bind == proc_bind_default) {
1569bdd1243dSDimitry Andric       proc_bind = master_th->th.th_current_task->td_icvs.proc_bind;
1570bdd1243dSDimitry Andric     }
1571bdd1243dSDimitry Andric     /* else: The proc_bind policy was specified explicitly on parallel clause.
1572bdd1243dSDimitry Andric        This overrides proc-bind-var for this parallel region, but does not
1573bdd1243dSDimitry Andric        change proc-bind-var. */
1574bdd1243dSDimitry Andric     // Figure the value of proc-bind-var for the child threads.
1575bdd1243dSDimitry Andric     if ((level + 1 < __kmp_nested_proc_bind.used) &&
1576bdd1243dSDimitry Andric         (__kmp_nested_proc_bind.bind_types[level + 1] !=
1577bdd1243dSDimitry Andric          master_th->th.th_current_task->td_icvs.proc_bind)) {
1578bdd1243dSDimitry Andric       proc_bind_icv = __kmp_nested_proc_bind.bind_types[level + 1];
1579bdd1243dSDimitry Andric     }
1580bdd1243dSDimitry Andric   }
1581bdd1243dSDimitry Andric   KMP_CHECK_UPDATE(parent_team->t.t_proc_bind, proc_bind);
1582bdd1243dSDimitry Andric   // Need to change the bind-var ICV to correct value for each implicit task
1583bdd1243dSDimitry Andric   if (proc_bind_icv != proc_bind_default &&
1584bdd1243dSDimitry Andric       master_th->th.th_current_task->td_icvs.proc_bind != proc_bind_icv) {
1585bdd1243dSDimitry Andric     kmp_info_t **other_threads = parent_team->t.t_threads;
1586bdd1243dSDimitry Andric     for (i = 0; i < master_th->th.th_team_nproc; ++i) {
1587bdd1243dSDimitry Andric       other_threads[i]->th.th_current_task->td_icvs.proc_bind = proc_bind_icv;
1588bdd1243dSDimitry Andric     }
1589bdd1243dSDimitry Andric   }
1590bdd1243dSDimitry Andric   // Reset for next parallel region
1591bdd1243dSDimitry Andric   master_th->th.th_set_proc_bind = proc_bind_default;
1592bdd1243dSDimitry Andric 
1593bdd1243dSDimitry Andric #if USE_ITT_BUILD && USE_ITT_NOTIFY
1594bdd1243dSDimitry Andric   if (((__itt_frame_submit_v3_ptr && __itt_get_timestamp_ptr) ||
1595bdd1243dSDimitry Andric        KMP_ITT_DEBUG) &&
1596bdd1243dSDimitry Andric       __kmp_forkjoin_frames_mode == 3 &&
1597bdd1243dSDimitry Andric       parent_team->t.t_active_level == 1 // only report frames at level 1
1598bdd1243dSDimitry Andric       && master_th->th.th_teams_size.nteams == 1) {
1599bdd1243dSDimitry Andric     kmp_uint64 tmp_time = __itt_get_timestamp();
1600bdd1243dSDimitry Andric     master_th->th.th_frame_time = tmp_time;
1601bdd1243dSDimitry Andric     parent_team->t.t_region_time = tmp_time;
1602bdd1243dSDimitry Andric   }
1603bdd1243dSDimitry Andric   if (__itt_stack_caller_create_ptr) {
1604bdd1243dSDimitry Andric     KMP_DEBUG_ASSERT(parent_team->t.t_stack_id == NULL);
1605bdd1243dSDimitry Andric     // create new stack stitching id before entering fork barrier
1606bdd1243dSDimitry Andric     parent_team->t.t_stack_id = __kmp_itt_stack_caller_create();
1607bdd1243dSDimitry Andric   }
1608bdd1243dSDimitry Andric #endif /* USE_ITT_BUILD && USE_ITT_NOTIFY */
1609bdd1243dSDimitry Andric #if KMP_AFFINITY_SUPPORTED
1610bdd1243dSDimitry Andric   __kmp_partition_places(parent_team);
1611bdd1243dSDimitry Andric #endif
1612bdd1243dSDimitry Andric 
1613bdd1243dSDimitry Andric   KF_TRACE(10, ("__kmp_fork_in_teams: before internal fork: root=%p, team=%p, "
1614bdd1243dSDimitry Andric                 "master_th=%p, gtid=%d\n",
1615bdd1243dSDimitry Andric                 root, parent_team, master_th, gtid));
1616bdd1243dSDimitry Andric   __kmp_internal_fork(loc, gtid, parent_team);
1617bdd1243dSDimitry Andric   KF_TRACE(10, ("__kmp_fork_in_teams: after internal fork: root=%p, team=%p, "
1618bdd1243dSDimitry Andric                 "master_th=%p, gtid=%d\n",
1619bdd1243dSDimitry Andric                 root, parent_team, master_th, gtid));
1620bdd1243dSDimitry Andric 
1621bdd1243dSDimitry Andric   if (call_context == fork_context_gnu)
1622bdd1243dSDimitry Andric     return TRUE;
1623bdd1243dSDimitry Andric 
1624bdd1243dSDimitry Andric   /* Invoke microtask for PRIMARY thread */
1625bdd1243dSDimitry Andric   KA_TRACE(20, ("__kmp_fork_in_teams: T#%d(%d:0) invoke microtask = %p\n", gtid,
1626bdd1243dSDimitry Andric                 parent_team->t.t_id, parent_team->t.t_pkfn));
1627bdd1243dSDimitry Andric 
1628bdd1243dSDimitry Andric   if (!parent_team->t.t_invoke(gtid)) {
1629bdd1243dSDimitry Andric     KMP_ASSERT2(0, "cannot invoke microtask for PRIMARY thread");
1630bdd1243dSDimitry Andric   }
1631bdd1243dSDimitry Andric   KA_TRACE(20, ("__kmp_fork_in_teams: T#%d(%d:0) done microtask = %p\n", gtid,
1632bdd1243dSDimitry Andric                 parent_team->t.t_id, parent_team->t.t_pkfn));
1633bdd1243dSDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
1634bdd1243dSDimitry Andric 
1635bdd1243dSDimitry Andric   KA_TRACE(20, ("__kmp_fork_in_teams: parallel exit T#%d\n", gtid));
1636bdd1243dSDimitry Andric 
1637bdd1243dSDimitry Andric   return TRUE;
1638bdd1243dSDimitry Andric }
1639bdd1243dSDimitry Andric 
1640bdd1243dSDimitry Andric // Create a serialized parallel region
1641bdd1243dSDimitry Andric static inline int
__kmp_serial_fork_call(ident_t * loc,int gtid,enum fork_context_e call_context,kmp_int32 argc,microtask_t microtask,launch_t invoker,kmp_info_t * master_th,kmp_team_t * parent_team,ompt_data_t * ompt_parallel_data,void ** return_address,ompt_data_t ** parent_task_data,kmp_va_list ap)1642bdd1243dSDimitry Andric __kmp_serial_fork_call(ident_t *loc, int gtid, enum fork_context_e call_context,
1643bdd1243dSDimitry Andric                        kmp_int32 argc, microtask_t microtask, launch_t invoker,
1644bdd1243dSDimitry Andric                        kmp_info_t *master_th, kmp_team_t *parent_team,
1645bdd1243dSDimitry Andric #if OMPT_SUPPORT
1646bdd1243dSDimitry Andric                        ompt_data_t *ompt_parallel_data, void **return_address,
1647bdd1243dSDimitry Andric                        ompt_data_t **parent_task_data,
1648bdd1243dSDimitry Andric #endif
1649bdd1243dSDimitry Andric                        kmp_va_list ap) {
1650bdd1243dSDimitry Andric   kmp_team_t *team;
1651bdd1243dSDimitry Andric   int i;
1652bdd1243dSDimitry Andric   void **argv;
1653bdd1243dSDimitry Andric 
1654bdd1243dSDimitry Andric /* josh todo: hypothetical question: what do we do for OS X*? */
1655bdd1243dSDimitry Andric #if KMP_OS_LINUX &&                                                            \
1656bdd1243dSDimitry Andric     (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_ARM || KMP_ARCH_AARCH64)
16575f757f3fSDimitry Andric   SimpleVLA<void *> args(argc);
1658bdd1243dSDimitry Andric #else
1659bdd1243dSDimitry Andric   void **args = (void **)KMP_ALLOCA(argc * sizeof(void *));
1660bdd1243dSDimitry Andric #endif /* KMP_OS_LINUX && ( KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_ARM || \
1661bdd1243dSDimitry Andric           KMP_ARCH_AARCH64) */
1662bdd1243dSDimitry Andric 
1663bdd1243dSDimitry Andric   KA_TRACE(
1664bdd1243dSDimitry Andric       20, ("__kmp_serial_fork_call: T#%d serializing parallel region\n", gtid));
1665bdd1243dSDimitry Andric 
1666bdd1243dSDimitry Andric   __kmpc_serialized_parallel(loc, gtid);
1667bdd1243dSDimitry Andric 
1668bdd1243dSDimitry Andric #if OMPD_SUPPORT
1669bdd1243dSDimitry Andric   master_th->th.th_serial_team->t.t_pkfn = microtask;
1670bdd1243dSDimitry Andric #endif
1671bdd1243dSDimitry Andric 
1672bdd1243dSDimitry Andric   if (call_context == fork_context_intel) {
1673bdd1243dSDimitry Andric     /* TODO this sucks, use the compiler itself to pass args! :) */
1674bdd1243dSDimitry Andric     master_th->th.th_serial_team->t.t_ident = loc;
1675bdd1243dSDimitry Andric     if (!ap) {
1676bdd1243dSDimitry Andric       // revert change made in __kmpc_serialized_parallel()
1677bdd1243dSDimitry Andric       master_th->th.th_serial_team->t.t_level--;
1678bdd1243dSDimitry Andric // Get args from parent team for teams construct
1679bdd1243dSDimitry Andric 
1680bdd1243dSDimitry Andric #if OMPT_SUPPORT
1681bdd1243dSDimitry Andric       void *dummy;
1682bdd1243dSDimitry Andric       void **exit_frame_p;
1683bdd1243dSDimitry Andric       ompt_task_info_t *task_info;
1684bdd1243dSDimitry Andric       ompt_lw_taskteam_t lw_taskteam;
1685bdd1243dSDimitry Andric 
1686bdd1243dSDimitry Andric       if (ompt_enabled.enabled) {
1687bdd1243dSDimitry Andric         __ompt_lw_taskteam_init(&lw_taskteam, master_th, gtid,
1688bdd1243dSDimitry Andric                                 ompt_parallel_data, *return_address);
1689bdd1243dSDimitry Andric 
1690bdd1243dSDimitry Andric         __ompt_lw_taskteam_link(&lw_taskteam, master_th, 0);
1691bdd1243dSDimitry Andric         // don't use lw_taskteam after linking. content was swaped
1692bdd1243dSDimitry Andric         task_info = OMPT_CUR_TASK_INFO(master_th);
1693bdd1243dSDimitry Andric         exit_frame_p = &(task_info->frame.exit_frame.ptr);
1694bdd1243dSDimitry Andric         if (ompt_enabled.ompt_callback_implicit_task) {
1695bdd1243dSDimitry Andric           OMPT_CUR_TASK_INFO(master_th)->thread_num = __kmp_tid_from_gtid(gtid);
1696bdd1243dSDimitry Andric           ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1697bdd1243dSDimitry Andric               ompt_scope_begin, OMPT_CUR_TEAM_DATA(master_th),
1698bdd1243dSDimitry Andric               &(task_info->task_data), 1,
1699bdd1243dSDimitry Andric               OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_implicit);
1700bdd1243dSDimitry Andric         }
1701bdd1243dSDimitry Andric 
1702bdd1243dSDimitry Andric         /* OMPT state */
1703bdd1243dSDimitry Andric         master_th->th.ompt_thread_info.state = ompt_state_work_parallel;
1704bdd1243dSDimitry Andric       } else {
1705bdd1243dSDimitry Andric         exit_frame_p = &dummy;
1706bdd1243dSDimitry Andric       }
1707bdd1243dSDimitry Andric #endif
1708bdd1243dSDimitry Andric 
1709bdd1243dSDimitry Andric       {
1710bdd1243dSDimitry Andric         KMP_TIME_PARTITIONED_BLOCK(OMP_parallel);
1711bdd1243dSDimitry Andric         KMP_SET_THREAD_STATE_BLOCK(IMPLICIT_TASK);
1712bdd1243dSDimitry Andric         __kmp_invoke_microtask(microtask, gtid, 0, argc, parent_team->t.t_argv
1713bdd1243dSDimitry Andric #if OMPT_SUPPORT
1714bdd1243dSDimitry Andric                                ,
1715bdd1243dSDimitry Andric                                exit_frame_p
1716bdd1243dSDimitry Andric #endif
1717bdd1243dSDimitry Andric                                );
1718bdd1243dSDimitry Andric       }
1719bdd1243dSDimitry Andric 
1720bdd1243dSDimitry Andric #if OMPT_SUPPORT
1721bdd1243dSDimitry Andric       if (ompt_enabled.enabled) {
1722bdd1243dSDimitry Andric         *exit_frame_p = NULL;
1723bdd1243dSDimitry Andric         if (ompt_enabled.ompt_callback_implicit_task) {
1724bdd1243dSDimitry Andric           ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1725bdd1243dSDimitry Andric               ompt_scope_end, NULL, &(task_info->task_data), 1,
1726bdd1243dSDimitry Andric               OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_implicit);
1727bdd1243dSDimitry Andric         }
1728bdd1243dSDimitry Andric         *ompt_parallel_data = *OMPT_CUR_TEAM_DATA(master_th);
1729bdd1243dSDimitry Andric         __ompt_lw_taskteam_unlink(master_th);
1730bdd1243dSDimitry Andric         if (ompt_enabled.ompt_callback_parallel_end) {
1731bdd1243dSDimitry Andric           ompt_callbacks.ompt_callback(ompt_callback_parallel_end)(
1732bdd1243dSDimitry Andric               ompt_parallel_data, *parent_task_data,
1733bdd1243dSDimitry Andric               OMPT_INVOKER(call_context) | ompt_parallel_team, *return_address);
1734bdd1243dSDimitry Andric         }
1735bdd1243dSDimitry Andric         master_th->th.ompt_thread_info.state = ompt_state_overhead;
1736bdd1243dSDimitry Andric       }
1737bdd1243dSDimitry Andric #endif
1738bdd1243dSDimitry Andric     } else if (microtask == (microtask_t)__kmp_teams_master) {
1739bdd1243dSDimitry Andric       KMP_DEBUG_ASSERT(master_th->th.th_team == master_th->th.th_serial_team);
1740bdd1243dSDimitry Andric       team = master_th->th.th_team;
1741bdd1243dSDimitry Andric       // team->t.t_pkfn = microtask;
1742bdd1243dSDimitry Andric       team->t.t_invoke = invoker;
1743bdd1243dSDimitry Andric       __kmp_alloc_argv_entries(argc, team, TRUE);
1744bdd1243dSDimitry Andric       team->t.t_argc = argc;
1745bdd1243dSDimitry Andric       argv = (void **)team->t.t_argv;
1746bdd1243dSDimitry Andric       if (ap) {
1747bdd1243dSDimitry Andric         for (i = argc - 1; i >= 0; --i)
1748bdd1243dSDimitry Andric           *argv++ = va_arg(kmp_va_deref(ap), void *);
1749bdd1243dSDimitry Andric       } else {
1750bdd1243dSDimitry Andric         for (i = 0; i < argc; ++i)
1751bdd1243dSDimitry Andric           // Get args from parent team for teams construct
1752bdd1243dSDimitry Andric           argv[i] = parent_team->t.t_argv[i];
1753bdd1243dSDimitry Andric       }
1754bdd1243dSDimitry Andric       // AC: revert change made in __kmpc_serialized_parallel()
1755bdd1243dSDimitry Andric       //     because initial code in teams should have level=0
1756bdd1243dSDimitry Andric       team->t.t_level--;
1757bdd1243dSDimitry Andric       // AC: call special invoker for outer "parallel" of teams construct
1758bdd1243dSDimitry Andric       invoker(gtid);
1759bdd1243dSDimitry Andric #if OMPT_SUPPORT
1760bdd1243dSDimitry Andric       if (ompt_enabled.enabled) {
1761bdd1243dSDimitry Andric         ompt_task_info_t *task_info = OMPT_CUR_TASK_INFO(master_th);
1762bdd1243dSDimitry Andric         if (ompt_enabled.ompt_callback_implicit_task) {
1763bdd1243dSDimitry Andric           ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1764bdd1243dSDimitry Andric               ompt_scope_end, NULL, &(task_info->task_data), 0,
1765bdd1243dSDimitry Andric               OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_initial);
1766bdd1243dSDimitry Andric         }
1767bdd1243dSDimitry Andric         if (ompt_enabled.ompt_callback_parallel_end) {
1768bdd1243dSDimitry Andric           ompt_callbacks.ompt_callback(ompt_callback_parallel_end)(
1769bdd1243dSDimitry Andric               ompt_parallel_data, *parent_task_data,
1770bdd1243dSDimitry Andric               OMPT_INVOKER(call_context) | ompt_parallel_league,
1771bdd1243dSDimitry Andric               *return_address);
1772bdd1243dSDimitry Andric         }
1773bdd1243dSDimitry Andric         master_th->th.ompt_thread_info.state = ompt_state_overhead;
1774bdd1243dSDimitry Andric       }
1775bdd1243dSDimitry Andric #endif
1776bdd1243dSDimitry Andric     } else {
1777bdd1243dSDimitry Andric       argv = args;
1778bdd1243dSDimitry Andric       for (i = argc - 1; i >= 0; --i)
1779bdd1243dSDimitry Andric         *argv++ = va_arg(kmp_va_deref(ap), void *);
1780bdd1243dSDimitry Andric       KMP_MB();
1781bdd1243dSDimitry Andric 
1782bdd1243dSDimitry Andric #if OMPT_SUPPORT
1783bdd1243dSDimitry Andric       void *dummy;
1784bdd1243dSDimitry Andric       void **exit_frame_p;
1785bdd1243dSDimitry Andric       ompt_task_info_t *task_info;
1786bdd1243dSDimitry Andric       ompt_lw_taskteam_t lw_taskteam;
1787bdd1243dSDimitry Andric       ompt_data_t *implicit_task_data;
1788bdd1243dSDimitry Andric 
1789bdd1243dSDimitry Andric       if (ompt_enabled.enabled) {
1790bdd1243dSDimitry Andric         __ompt_lw_taskteam_init(&lw_taskteam, master_th, gtid,
1791bdd1243dSDimitry Andric                                 ompt_parallel_data, *return_address);
1792bdd1243dSDimitry Andric         __ompt_lw_taskteam_link(&lw_taskteam, master_th, 0);
1793bdd1243dSDimitry Andric         // don't use lw_taskteam after linking. content was swaped
1794bdd1243dSDimitry Andric         task_info = OMPT_CUR_TASK_INFO(master_th);
1795bdd1243dSDimitry Andric         exit_frame_p = &(task_info->frame.exit_frame.ptr);
1796bdd1243dSDimitry Andric 
1797bdd1243dSDimitry Andric         /* OMPT implicit task begin */
1798bdd1243dSDimitry Andric         implicit_task_data = OMPT_CUR_TASK_DATA(master_th);
1799bdd1243dSDimitry Andric         if (ompt_enabled.ompt_callback_implicit_task) {
1800bdd1243dSDimitry Andric           ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1801bdd1243dSDimitry Andric               ompt_scope_begin, OMPT_CUR_TEAM_DATA(master_th),
1802bdd1243dSDimitry Andric               implicit_task_data, 1, __kmp_tid_from_gtid(gtid),
1803bdd1243dSDimitry Andric               ompt_task_implicit);
1804bdd1243dSDimitry Andric           OMPT_CUR_TASK_INFO(master_th)->thread_num = __kmp_tid_from_gtid(gtid);
1805bdd1243dSDimitry Andric         }
1806bdd1243dSDimitry Andric 
1807bdd1243dSDimitry Andric         /* OMPT state */
1808bdd1243dSDimitry Andric         master_th->th.ompt_thread_info.state = ompt_state_work_parallel;
1809bdd1243dSDimitry Andric       } else {
1810bdd1243dSDimitry Andric         exit_frame_p = &dummy;
1811bdd1243dSDimitry Andric       }
1812bdd1243dSDimitry Andric #endif
1813bdd1243dSDimitry Andric 
1814bdd1243dSDimitry Andric       {
1815bdd1243dSDimitry Andric         KMP_TIME_PARTITIONED_BLOCK(OMP_parallel);
1816bdd1243dSDimitry Andric         KMP_SET_THREAD_STATE_BLOCK(IMPLICIT_TASK);
1817bdd1243dSDimitry Andric         __kmp_invoke_microtask(microtask, gtid, 0, argc, args
1818bdd1243dSDimitry Andric #if OMPT_SUPPORT
1819bdd1243dSDimitry Andric                                ,
1820bdd1243dSDimitry Andric                                exit_frame_p
1821bdd1243dSDimitry Andric #endif
1822bdd1243dSDimitry Andric                                );
1823bdd1243dSDimitry Andric       }
1824bdd1243dSDimitry Andric 
1825bdd1243dSDimitry Andric #if OMPT_SUPPORT
1826bdd1243dSDimitry Andric       if (ompt_enabled.enabled) {
1827bdd1243dSDimitry Andric         *exit_frame_p = NULL;
1828bdd1243dSDimitry Andric         if (ompt_enabled.ompt_callback_implicit_task) {
1829bdd1243dSDimitry Andric           ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
1830bdd1243dSDimitry Andric               ompt_scope_end, NULL, &(task_info->task_data), 1,
1831bdd1243dSDimitry Andric               OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_implicit);
1832bdd1243dSDimitry Andric         }
1833bdd1243dSDimitry Andric 
1834bdd1243dSDimitry Andric         *ompt_parallel_data = *OMPT_CUR_TEAM_DATA(master_th);
1835bdd1243dSDimitry Andric         __ompt_lw_taskteam_unlink(master_th);
1836bdd1243dSDimitry Andric         if (ompt_enabled.ompt_callback_parallel_end) {
1837bdd1243dSDimitry Andric           ompt_callbacks.ompt_callback(ompt_callback_parallel_end)(
1838bdd1243dSDimitry Andric               ompt_parallel_data, *parent_task_data,
1839bdd1243dSDimitry Andric               OMPT_INVOKER(call_context) | ompt_parallel_team, *return_address);
1840bdd1243dSDimitry Andric         }
1841bdd1243dSDimitry Andric         master_th->th.ompt_thread_info.state = ompt_state_overhead;
1842bdd1243dSDimitry Andric       }
1843bdd1243dSDimitry Andric #endif
1844bdd1243dSDimitry Andric     }
1845bdd1243dSDimitry Andric   } else if (call_context == fork_context_gnu) {
1846bdd1243dSDimitry Andric #if OMPT_SUPPORT
1847bdd1243dSDimitry Andric     if (ompt_enabled.enabled) {
1848bdd1243dSDimitry Andric       ompt_lw_taskteam_t lwt;
1849bdd1243dSDimitry Andric       __ompt_lw_taskteam_init(&lwt, master_th, gtid, ompt_parallel_data,
1850bdd1243dSDimitry Andric                               *return_address);
1851bdd1243dSDimitry Andric 
1852bdd1243dSDimitry Andric       lwt.ompt_task_info.frame.exit_frame = ompt_data_none;
1853bdd1243dSDimitry Andric       __ompt_lw_taskteam_link(&lwt, master_th, 1);
1854bdd1243dSDimitry Andric     }
1855bdd1243dSDimitry Andric // don't use lw_taskteam after linking. content was swaped
1856bdd1243dSDimitry Andric #endif
1857bdd1243dSDimitry Andric 
1858bdd1243dSDimitry Andric     // we were called from GNU native code
1859bdd1243dSDimitry Andric     KA_TRACE(20, ("__kmp_serial_fork_call: T#%d serial exit\n", gtid));
1860bdd1243dSDimitry Andric     return FALSE;
1861bdd1243dSDimitry Andric   } else {
1862bdd1243dSDimitry Andric     KMP_ASSERT2(call_context < fork_context_last,
1863bdd1243dSDimitry Andric                 "__kmp_serial_fork_call: unknown fork_context parameter");
1864bdd1243dSDimitry Andric   }
1865bdd1243dSDimitry Andric 
1866bdd1243dSDimitry Andric   KA_TRACE(20, ("__kmp_serial_fork_call: T#%d serial exit\n", gtid));
1867bdd1243dSDimitry Andric   KMP_MB();
1868bdd1243dSDimitry Andric   return FALSE;
1869bdd1243dSDimitry Andric }
1870bdd1243dSDimitry Andric 
18710b57cec5SDimitry Andric /* most of the work for a fork */
18720b57cec5SDimitry Andric /* return true if we really went parallel, false if serialized */
__kmp_fork_call(ident_t * loc,int gtid,enum fork_context_e call_context,kmp_int32 argc,microtask_t microtask,launch_t invoker,kmp_va_list ap)18730b57cec5SDimitry Andric int __kmp_fork_call(ident_t *loc, int gtid,
18740b57cec5SDimitry Andric                     enum fork_context_e call_context, // Intel, GNU, ...
18750b57cec5SDimitry Andric                     kmp_int32 argc, microtask_t microtask, launch_t invoker,
187616794618SDimitry Andric                     kmp_va_list ap) {
18770b57cec5SDimitry Andric   void **argv;
18780b57cec5SDimitry Andric   int i;
18790b57cec5SDimitry Andric   int master_tid;
18800b57cec5SDimitry Andric   int master_this_cons;
18810b57cec5SDimitry Andric   kmp_team_t *team;
18820b57cec5SDimitry Andric   kmp_team_t *parent_team;
18830b57cec5SDimitry Andric   kmp_info_t *master_th;
18840b57cec5SDimitry Andric   kmp_root_t *root;
18850b57cec5SDimitry Andric   int nthreads;
18860b57cec5SDimitry Andric   int master_active;
18870b57cec5SDimitry Andric   int master_set_numthreads;
18885f757f3fSDimitry Andric   int task_thread_limit = 0;
18890b57cec5SDimitry Andric   int level;
18900b57cec5SDimitry Andric   int active_level;
18910b57cec5SDimitry Andric   int teams_level;
18920b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
18930b57cec5SDimitry Andric   kmp_hot_team_ptr_t **p_hot_teams;
18940b57cec5SDimitry Andric #endif
18950b57cec5SDimitry Andric   { // KMP_TIME_BLOCK
18960b57cec5SDimitry Andric     KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_fork_call);
18970b57cec5SDimitry Andric     KMP_COUNT_VALUE(OMP_PARALLEL_args, argc);
18980b57cec5SDimitry Andric 
18990b57cec5SDimitry Andric     KA_TRACE(20, ("__kmp_fork_call: enter T#%d\n", gtid));
19000b57cec5SDimitry Andric     if (__kmp_stkpadding > 0 && __kmp_root[gtid] != NULL) {
19010b57cec5SDimitry Andric       /* Some systems prefer the stack for the root thread(s) to start with */
19020b57cec5SDimitry Andric       /* some gap from the parent stack to prevent false sharing. */
19030b57cec5SDimitry Andric       void *dummy = KMP_ALLOCA(__kmp_stkpadding);
19040b57cec5SDimitry Andric       /* These 2 lines below are so this does not get optimized out */
19050b57cec5SDimitry Andric       if (__kmp_stkpadding > KMP_MAX_STKPADDING)
19060b57cec5SDimitry Andric         __kmp_stkpadding += (short)((kmp_int64)dummy);
19070b57cec5SDimitry Andric     }
19080b57cec5SDimitry Andric 
19090b57cec5SDimitry Andric     /* initialize if needed */
19100b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(
19110b57cec5SDimitry Andric         __kmp_init_serial); // AC: potentially unsafe, not in sync with shutdown
19120b57cec5SDimitry Andric     if (!TCR_4(__kmp_init_parallel))
19130b57cec5SDimitry Andric       __kmp_parallel_initialize();
19140b57cec5SDimitry Andric     __kmp_resume_if_soft_paused();
19150b57cec5SDimitry Andric 
19160b57cec5SDimitry Andric     /* setup current data */
1917bdd1243dSDimitry Andric     // AC: potentially unsafe, not in sync with library shutdown,
1918bdd1243dSDimitry Andric     // __kmp_threads can be freed
1919bdd1243dSDimitry Andric     master_th = __kmp_threads[gtid];
1920bdd1243dSDimitry Andric 
19210b57cec5SDimitry Andric     parent_team = master_th->th.th_team;
19220b57cec5SDimitry Andric     master_tid = master_th->th.th_info.ds.ds_tid;
19230b57cec5SDimitry Andric     master_this_cons = master_th->th.th_local.this_construct;
19240b57cec5SDimitry Andric     root = master_th->th.th_root;
19250b57cec5SDimitry Andric     master_active = root->r.r_active;
19260b57cec5SDimitry Andric     master_set_numthreads = master_th->th.th_set_nproc;
19275f757f3fSDimitry Andric     task_thread_limit =
19285f757f3fSDimitry Andric         master_th->th.th_current_task->td_icvs.task_thread_limit;
19290b57cec5SDimitry Andric 
19300b57cec5SDimitry Andric #if OMPT_SUPPORT
19310b57cec5SDimitry Andric     ompt_data_t ompt_parallel_data = ompt_data_none;
19320b57cec5SDimitry Andric     ompt_data_t *parent_task_data;
19330b57cec5SDimitry Andric     ompt_frame_t *ompt_frame;
19340b57cec5SDimitry Andric     void *return_address = NULL;
19350b57cec5SDimitry Andric 
19360b57cec5SDimitry Andric     if (ompt_enabled.enabled) {
19370b57cec5SDimitry Andric       __ompt_get_task_info_internal(0, NULL, &parent_task_data, &ompt_frame,
19380b57cec5SDimitry Andric                                     NULL, NULL);
19390b57cec5SDimitry Andric       return_address = OMPT_LOAD_RETURN_ADDRESS(gtid);
19400b57cec5SDimitry Andric     }
19410b57cec5SDimitry Andric #endif
19420b57cec5SDimitry Andric 
1943fe6060f1SDimitry Andric     // Assign affinity to root thread if it hasn't happened yet
1944fe6060f1SDimitry Andric     __kmp_assign_root_init_mask();
1945fe6060f1SDimitry Andric 
19460b57cec5SDimitry Andric     // Nested level will be an index in the nested nthreads array
19470b57cec5SDimitry Andric     level = parent_team->t.t_level;
19480b57cec5SDimitry Andric     // used to launch non-serial teams even if nested is not allowed
19490b57cec5SDimitry Andric     active_level = parent_team->t.t_active_level;
19500b57cec5SDimitry Andric     // needed to check nesting inside the teams
19510b57cec5SDimitry Andric     teams_level = master_th->th.th_teams_level;
19520b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
19530b57cec5SDimitry Andric     p_hot_teams = &master_th->th.th_hot_teams;
19540b57cec5SDimitry Andric     if (*p_hot_teams == NULL && __kmp_hot_teams_max_level > 0) {
19550b57cec5SDimitry Andric       *p_hot_teams = (kmp_hot_team_ptr_t *)__kmp_allocate(
19560b57cec5SDimitry Andric           sizeof(kmp_hot_team_ptr_t) * __kmp_hot_teams_max_level);
19570b57cec5SDimitry Andric       (*p_hot_teams)[0].hot_team = root->r.r_hot_team;
19580b57cec5SDimitry Andric       // it is either actual or not needed (when active_level > 0)
19590b57cec5SDimitry Andric       (*p_hot_teams)[0].hot_team_nth = 1;
19600b57cec5SDimitry Andric     }
19610b57cec5SDimitry Andric #endif
19620b57cec5SDimitry Andric 
19630b57cec5SDimitry Andric #if OMPT_SUPPORT
19640b57cec5SDimitry Andric     if (ompt_enabled.enabled) {
19650b57cec5SDimitry Andric       if (ompt_enabled.ompt_callback_parallel_begin) {
19660b57cec5SDimitry Andric         int team_size = master_set_numthreads
19670b57cec5SDimitry Andric                             ? master_set_numthreads
19680b57cec5SDimitry Andric                             : get__nproc_2(parent_team, master_tid);
1969489b1cf2SDimitry Andric         int flags = OMPT_INVOKER(call_context) |
1970489b1cf2SDimitry Andric                     ((microtask == (microtask_t)__kmp_teams_master)
1971489b1cf2SDimitry Andric                          ? ompt_parallel_league
1972489b1cf2SDimitry Andric                          : ompt_parallel_team);
19730b57cec5SDimitry Andric         ompt_callbacks.ompt_callback(ompt_callback_parallel_begin)(
1974489b1cf2SDimitry Andric             parent_task_data, ompt_frame, &ompt_parallel_data, team_size, flags,
1975489b1cf2SDimitry Andric             return_address);
19760b57cec5SDimitry Andric       }
19770b57cec5SDimitry Andric       master_th->th.ompt_thread_info.state = ompt_state_overhead;
19780b57cec5SDimitry Andric     }
19790b57cec5SDimitry Andric #endif
19800b57cec5SDimitry Andric 
19810b57cec5SDimitry Andric     master_th->th.th_ident = loc;
19820b57cec5SDimitry Andric 
1983bdd1243dSDimitry Andric     // Parallel closely nested in teams construct:
1984bdd1243dSDimitry Andric     if (__kmp_is_fork_in_teams(master_th, microtask, level, teams_level, ap)) {
1985bdd1243dSDimitry Andric       return __kmp_fork_in_teams(loc, gtid, parent_team, argc, master_th, root,
1986bdd1243dSDimitry Andric                                  call_context, microtask, invoker,
1987bdd1243dSDimitry Andric                                  master_set_numthreads, level,
19880b57cec5SDimitry Andric #if OMPT_SUPPORT
1989bdd1243dSDimitry Andric                                  ompt_parallel_data, return_address,
19900b57cec5SDimitry Andric #endif
1991bdd1243dSDimitry Andric                                  ap);
1992bdd1243dSDimitry Andric     } // End parallel closely nested in teams construct
19930b57cec5SDimitry Andric 
19940b57cec5SDimitry Andric #if KMP_DEBUG
19950b57cec5SDimitry Andric     if (__kmp_tasking_mode != tskm_immediate_exec) {
19960b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(master_th->th.th_task_team ==
19970b57cec5SDimitry Andric                        parent_team->t.t_task_team[master_th->th.th_task_state]);
19980b57cec5SDimitry Andric     }
19990b57cec5SDimitry Andric #endif
20000b57cec5SDimitry Andric 
2001349cc55cSDimitry Andric     // Need this to happen before we determine the number of threads, not while
2002349cc55cSDimitry Andric     // we are allocating the team
2003349cc55cSDimitry Andric     //__kmp_push_current_task_to_thread(master_th, parent_team, 0);
2004bdd1243dSDimitry Andric 
2005bdd1243dSDimitry Andric     // Determine the number of threads
2006bdd1243dSDimitry Andric     int enter_teams =
2007bdd1243dSDimitry Andric         __kmp_is_entering_teams(active_level, level, teams_level, ap);
2008bdd1243dSDimitry Andric     if ((!enter_teams &&
2009bdd1243dSDimitry Andric          (parent_team->t.t_active_level >=
2010bdd1243dSDimitry Andric           master_th->th.th_current_task->td_icvs.max_active_levels)) ||
2011bdd1243dSDimitry Andric         (__kmp_library == library_serial)) {
2012bdd1243dSDimitry Andric       KC_TRACE(10, ("__kmp_fork_call: T#%d serializing team\n", gtid));
20130b57cec5SDimitry Andric       nthreads = 1;
20140b57cec5SDimitry Andric     } else {
2015349cc55cSDimitry Andric       nthreads = master_set_numthreads
20160b57cec5SDimitry Andric                      ? master_set_numthreads
2017349cc55cSDimitry Andric                      // TODO: get nproc directly from current task
2018349cc55cSDimitry Andric                      : get__nproc_2(parent_team, master_tid);
20195f757f3fSDimitry Andric       // Use the thread_limit set for the current target task if exists, else go
20205f757f3fSDimitry Andric       // with the deduced nthreads
20215f757f3fSDimitry Andric       nthreads = task_thread_limit > 0 && task_thread_limit < nthreads
20225f757f3fSDimitry Andric                      ? task_thread_limit
20235f757f3fSDimitry Andric                      : nthreads;
20240b57cec5SDimitry Andric       // Check if we need to take forkjoin lock? (no need for serialized
2025bdd1243dSDimitry Andric       // parallel out of teams construct).
20260b57cec5SDimitry Andric       if (nthreads > 1) {
20270b57cec5SDimitry Andric         /* determine how many new threads we can use */
20280b57cec5SDimitry Andric         __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
20290b57cec5SDimitry Andric         /* AC: If we execute teams from parallel region (on host), then teams
20300b57cec5SDimitry Andric            should be created but each can only have 1 thread if nesting is
20310b57cec5SDimitry Andric            disabled. If teams called from serial region, then teams and their
20320b57cec5SDimitry Andric            threads should be created regardless of the nesting setting. */
20330b57cec5SDimitry Andric         nthreads = __kmp_reserve_threads(root, parent_team, master_tid,
20340b57cec5SDimitry Andric                                          nthreads, enter_teams);
20350b57cec5SDimitry Andric         if (nthreads == 1) {
20360b57cec5SDimitry Andric           // Free lock for single thread execution here; for multi-thread
20370b57cec5SDimitry Andric           // execution it will be freed later after team of threads created
20380b57cec5SDimitry Andric           // and initialized
20390b57cec5SDimitry Andric           __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
20400b57cec5SDimitry Andric         }
20410b57cec5SDimitry Andric       }
20420b57cec5SDimitry Andric     }
20430b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(nthreads > 0);
20440b57cec5SDimitry Andric 
20450b57cec5SDimitry Andric     // If we temporarily changed the set number of threads then restore it now
20460b57cec5SDimitry Andric     master_th->th.th_set_nproc = 0;
20470b57cec5SDimitry Andric 
20480b57cec5SDimitry Andric     if (nthreads == 1) {
2049bdd1243dSDimitry Andric       return __kmp_serial_fork_call(loc, gtid, call_context, argc, microtask,
2050bdd1243dSDimitry Andric                                     invoker, master_th, parent_team,
20510b57cec5SDimitry Andric #if OMPT_SUPPORT
2052bdd1243dSDimitry Andric                                     &ompt_parallel_data, &return_address,
2053bdd1243dSDimitry Andric                                     &parent_task_data,
20540b57cec5SDimitry Andric #endif
2055bdd1243dSDimitry Andric                                     ap);
20560b57cec5SDimitry Andric     } // if (nthreads == 1)
20570b57cec5SDimitry Andric 
20580b57cec5SDimitry Andric     // GEH: only modify the executing flag in the case when not serialized
20590b57cec5SDimitry Andric     //      serialized case is handled in kmpc_serialized_parallel
20600b57cec5SDimitry Andric     KF_TRACE(10, ("__kmp_fork_call: parent_team_aclevel=%d, master_th=%p, "
20610b57cec5SDimitry Andric                   "curtask=%p, curtask_max_aclevel=%d\n",
20620b57cec5SDimitry Andric                   parent_team->t.t_active_level, master_th,
20630b57cec5SDimitry Andric                   master_th->th.th_current_task,
20640b57cec5SDimitry Andric                   master_th->th.th_current_task->td_icvs.max_active_levels));
20650b57cec5SDimitry Andric     // TODO: GEH - cannot do this assertion because root thread not set up as
20660b57cec5SDimitry Andric     // executing
20670b57cec5SDimitry Andric     // KMP_ASSERT( master_th->th.th_current_task->td_flags.executing == 1 );
20680b57cec5SDimitry Andric     master_th->th.th_current_task->td_flags.executing = 0;
20690b57cec5SDimitry Andric 
20700b57cec5SDimitry Andric     if (!master_th->th.th_teams_microtask || level > teams_level) {
20710b57cec5SDimitry Andric       /* Increment our nested depth level */
20720b57cec5SDimitry Andric       KMP_ATOMIC_INC(&root->r.r_in_parallel);
20730b57cec5SDimitry Andric     }
20740b57cec5SDimitry Andric 
20750b57cec5SDimitry Andric     // See if we need to make a copy of the ICVs.
20760b57cec5SDimitry Andric     int nthreads_icv = master_th->th.th_current_task->td_icvs.nproc;
20770b57cec5SDimitry Andric     if ((level + 1 < __kmp_nested_nth.used) &&
20780b57cec5SDimitry Andric         (__kmp_nested_nth.nth[level + 1] != nthreads_icv)) {
20790b57cec5SDimitry Andric       nthreads_icv = __kmp_nested_nth.nth[level + 1];
20800b57cec5SDimitry Andric     } else {
20810b57cec5SDimitry Andric       nthreads_icv = 0; // don't update
20820b57cec5SDimitry Andric     }
20830b57cec5SDimitry Andric 
20840b57cec5SDimitry Andric     // Figure out the proc_bind_policy for the new team.
20850b57cec5SDimitry Andric     kmp_proc_bind_t proc_bind = master_th->th.th_set_proc_bind;
2086349cc55cSDimitry Andric     // proc_bind_default means don't update
2087349cc55cSDimitry Andric     kmp_proc_bind_t proc_bind_icv = proc_bind_default;
20880b57cec5SDimitry Andric     if (master_th->th.th_current_task->td_icvs.proc_bind == proc_bind_false) {
20890b57cec5SDimitry Andric       proc_bind = proc_bind_false;
20900b57cec5SDimitry Andric     } else {
20910b57cec5SDimitry Andric       // No proc_bind clause specified; use current proc-bind-var for this
20920b57cec5SDimitry Andric       // parallel region
2093349cc55cSDimitry Andric       if (proc_bind == proc_bind_default) {
20940b57cec5SDimitry Andric         proc_bind = master_th->th.th_current_task->td_icvs.proc_bind;
20950b57cec5SDimitry Andric       }
2096349cc55cSDimitry Andric       // Have teams construct take proc_bind value from KMP_TEAMS_PROC_BIND
2097349cc55cSDimitry Andric       if (master_th->th.th_teams_microtask &&
2098349cc55cSDimitry Andric           microtask == (microtask_t)__kmp_teams_master) {
2099349cc55cSDimitry Andric         proc_bind = __kmp_teams_proc_bind;
2100349cc55cSDimitry Andric       }
21010b57cec5SDimitry Andric       /* else: The proc_bind policy was specified explicitly on parallel clause.
21020b57cec5SDimitry Andric          This overrides proc-bind-var for this parallel region, but does not
21030b57cec5SDimitry Andric          change proc-bind-var. */
21040b57cec5SDimitry Andric       // Figure the value of proc-bind-var for the child threads.
21050b57cec5SDimitry Andric       if ((level + 1 < __kmp_nested_proc_bind.used) &&
21060b57cec5SDimitry Andric           (__kmp_nested_proc_bind.bind_types[level + 1] !=
21070b57cec5SDimitry Andric            master_th->th.th_current_task->td_icvs.proc_bind)) {
2108349cc55cSDimitry Andric         // Do not modify the proc bind icv for the two teams construct forks
2109349cc55cSDimitry Andric         // They just let the proc bind icv pass through
2110349cc55cSDimitry Andric         if (!master_th->th.th_teams_microtask ||
2111349cc55cSDimitry Andric             !(microtask == (microtask_t)__kmp_teams_master || ap == NULL))
21120b57cec5SDimitry Andric           proc_bind_icv = __kmp_nested_proc_bind.bind_types[level + 1];
21130b57cec5SDimitry Andric       }
21140b57cec5SDimitry Andric     }
21150b57cec5SDimitry Andric 
21160b57cec5SDimitry Andric     // Reset for next parallel region
21170b57cec5SDimitry Andric     master_th->th.th_set_proc_bind = proc_bind_default;
21180b57cec5SDimitry Andric 
21190b57cec5SDimitry Andric     if ((nthreads_icv > 0) || (proc_bind_icv != proc_bind_default)) {
21200b57cec5SDimitry Andric       kmp_internal_control_t new_icvs;
21210b57cec5SDimitry Andric       copy_icvs(&new_icvs, &master_th->th.th_current_task->td_icvs);
21220b57cec5SDimitry Andric       new_icvs.next = NULL;
21230b57cec5SDimitry Andric       if (nthreads_icv > 0) {
21240b57cec5SDimitry Andric         new_icvs.nproc = nthreads_icv;
21250b57cec5SDimitry Andric       }
21260b57cec5SDimitry Andric       if (proc_bind_icv != proc_bind_default) {
21270b57cec5SDimitry Andric         new_icvs.proc_bind = proc_bind_icv;
21280b57cec5SDimitry Andric       }
21290b57cec5SDimitry Andric 
21300b57cec5SDimitry Andric       /* allocate a new parallel team */
21310b57cec5SDimitry Andric       KF_TRACE(10, ("__kmp_fork_call: before __kmp_allocate_team\n"));
21320b57cec5SDimitry Andric       team = __kmp_allocate_team(root, nthreads, nthreads,
21330b57cec5SDimitry Andric #if OMPT_SUPPORT
21340b57cec5SDimitry Andric                                  ompt_parallel_data,
21350b57cec5SDimitry Andric #endif
21360b57cec5SDimitry Andric                                  proc_bind, &new_icvs,
21370b57cec5SDimitry Andric                                  argc USE_NESTED_HOT_ARG(master_th));
2138349cc55cSDimitry Andric       if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar)
2139349cc55cSDimitry Andric         copy_icvs((kmp_internal_control_t *)team->t.b->team_icvs, &new_icvs);
21400b57cec5SDimitry Andric     } else {
21410b57cec5SDimitry Andric       /* allocate a new parallel team */
21420b57cec5SDimitry Andric       KF_TRACE(10, ("__kmp_fork_call: before __kmp_allocate_team\n"));
21430b57cec5SDimitry Andric       team = __kmp_allocate_team(root, nthreads, nthreads,
21440b57cec5SDimitry Andric #if OMPT_SUPPORT
21450b57cec5SDimitry Andric                                  ompt_parallel_data,
21460b57cec5SDimitry Andric #endif
21470b57cec5SDimitry Andric                                  proc_bind,
21480b57cec5SDimitry Andric                                  &master_th->th.th_current_task->td_icvs,
21490b57cec5SDimitry Andric                                  argc USE_NESTED_HOT_ARG(master_th));
2150349cc55cSDimitry Andric       if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar)
2151349cc55cSDimitry Andric         copy_icvs((kmp_internal_control_t *)team->t.b->team_icvs,
2152349cc55cSDimitry Andric                   &master_th->th.th_current_task->td_icvs);
21530b57cec5SDimitry Andric     }
21540b57cec5SDimitry Andric     KF_TRACE(
21550b57cec5SDimitry Andric         10, ("__kmp_fork_call: after __kmp_allocate_team - team = %p\n", team));
21560b57cec5SDimitry Andric 
21570b57cec5SDimitry Andric     /* setup the new team */
21580b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_master_tid, master_tid);
21590b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_master_this_cons, master_this_cons);
21600b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_ident, loc);
21610b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_parent, parent_team);
21620b57cec5SDimitry Andric     KMP_CHECK_UPDATE_SYNC(team->t.t_pkfn, microtask);
21630b57cec5SDimitry Andric #if OMPT_SUPPORT
21640b57cec5SDimitry Andric     KMP_CHECK_UPDATE_SYNC(team->t.ompt_team_info.master_return_address,
21650b57cec5SDimitry Andric                           return_address);
21660b57cec5SDimitry Andric #endif
21670b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_invoke, invoker); // TODO move to root, maybe
21680b57cec5SDimitry Andric     // TODO: parent_team->t.t_level == INT_MAX ???
21690b57cec5SDimitry Andric     if (!master_th->th.th_teams_microtask || level > teams_level) {
21700b57cec5SDimitry Andric       int new_level = parent_team->t.t_level + 1;
21710b57cec5SDimitry Andric       KMP_CHECK_UPDATE(team->t.t_level, new_level);
21720b57cec5SDimitry Andric       new_level = parent_team->t.t_active_level + 1;
21730b57cec5SDimitry Andric       KMP_CHECK_UPDATE(team->t.t_active_level, new_level);
21740b57cec5SDimitry Andric     } else {
21750b57cec5SDimitry Andric       // AC: Do not increase parallel level at start of the teams construct
21760b57cec5SDimitry Andric       int new_level = parent_team->t.t_level;
21770b57cec5SDimitry Andric       KMP_CHECK_UPDATE(team->t.t_level, new_level);
21780b57cec5SDimitry Andric       new_level = parent_team->t.t_active_level;
21790b57cec5SDimitry Andric       KMP_CHECK_UPDATE(team->t.t_active_level, new_level);
21800b57cec5SDimitry Andric     }
21810b57cec5SDimitry Andric     kmp_r_sched_t new_sched = get__sched_2(parent_team, master_tid);
2182fe6060f1SDimitry Andric     // set primary thread's schedule as new run-time schedule
21830b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_sched.sched, new_sched.sched);
21840b57cec5SDimitry Andric 
21850b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_cancel_request, cancel_noreq);
21860b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_def_allocator, master_th->th.th_def_allocator);
21870b57cec5SDimitry Andric 
21880b57cec5SDimitry Andric     // Update the floating point rounding in the team if required.
21890b57cec5SDimitry Andric     propagateFPControl(team);
2190fe6060f1SDimitry Andric #if OMPD_SUPPORT
2191fe6060f1SDimitry Andric     if (ompd_state & OMPD_ENABLE_BP)
2192fe6060f1SDimitry Andric       ompd_bp_parallel_begin();
2193fe6060f1SDimitry Andric #endif
21940b57cec5SDimitry Andric 
21950b57cec5SDimitry Andric     if (__kmp_tasking_mode != tskm_immediate_exec) {
2196fe6060f1SDimitry Andric       // Set primary thread's task team to team's task team. Unless this is hot
2197fe6060f1SDimitry Andric       // team, it should be NULL.
21980b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(master_th->th.th_task_team ==
21990b57cec5SDimitry Andric                        parent_team->t.t_task_team[master_th->th.th_task_state]);
2200fe6060f1SDimitry Andric       KA_TRACE(20, ("__kmp_fork_call: Primary T#%d pushing task_team %p / team "
22010b57cec5SDimitry Andric                     "%p, new task_team %p / team %p\n",
22020b57cec5SDimitry Andric                     __kmp_gtid_from_thread(master_th),
22030b57cec5SDimitry Andric                     master_th->th.th_task_team, parent_team,
22040b57cec5SDimitry Andric                     team->t.t_task_team[master_th->th.th_task_state], team));
22050b57cec5SDimitry Andric 
22060b57cec5SDimitry Andric       if (active_level || master_th->th.th_task_team) {
2207fe6060f1SDimitry Andric         // Take a memo of primary thread's task_state
22080b57cec5SDimitry Andric         KMP_DEBUG_ASSERT(master_th->th.th_task_state_memo_stack);
22090b57cec5SDimitry Andric         if (master_th->th.th_task_state_top >=
22100b57cec5SDimitry Andric             master_th->th.th_task_state_stack_sz) { // increase size
22110b57cec5SDimitry Andric           kmp_uint32 new_size = 2 * master_th->th.th_task_state_stack_sz;
22120b57cec5SDimitry Andric           kmp_uint8 *old_stack, *new_stack;
22130b57cec5SDimitry Andric           kmp_uint32 i;
22140b57cec5SDimitry Andric           new_stack = (kmp_uint8 *)__kmp_allocate(new_size);
22150b57cec5SDimitry Andric           for (i = 0; i < master_th->th.th_task_state_stack_sz; ++i) {
22160b57cec5SDimitry Andric             new_stack[i] = master_th->th.th_task_state_memo_stack[i];
22170b57cec5SDimitry Andric           }
22180b57cec5SDimitry Andric           for (i = master_th->th.th_task_state_stack_sz; i < new_size;
22190b57cec5SDimitry Andric                ++i) { // zero-init rest of stack
22200b57cec5SDimitry Andric             new_stack[i] = 0;
22210b57cec5SDimitry Andric           }
22220b57cec5SDimitry Andric           old_stack = master_th->th.th_task_state_memo_stack;
22230b57cec5SDimitry Andric           master_th->th.th_task_state_memo_stack = new_stack;
22240b57cec5SDimitry Andric           master_th->th.th_task_state_stack_sz = new_size;
22250b57cec5SDimitry Andric           __kmp_free(old_stack);
22260b57cec5SDimitry Andric         }
2227fe6060f1SDimitry Andric         // Store primary thread's task_state on stack
22280b57cec5SDimitry Andric         master_th->th
22290b57cec5SDimitry Andric             .th_task_state_memo_stack[master_th->th.th_task_state_top] =
22300b57cec5SDimitry Andric             master_th->th.th_task_state;
22310b57cec5SDimitry Andric         master_th->th.th_task_state_top++;
22320b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
22330b57cec5SDimitry Andric         if (master_th->th.th_hot_teams &&
22340b57cec5SDimitry Andric             active_level < __kmp_hot_teams_max_level &&
22350b57cec5SDimitry Andric             team == master_th->th.th_hot_teams[active_level].hot_team) {
2236fe6060f1SDimitry Andric           // Restore primary thread's nested state if nested hot team
22370b57cec5SDimitry Andric           master_th->th.th_task_state =
22380b57cec5SDimitry Andric               master_th->th
22390b57cec5SDimitry Andric                   .th_task_state_memo_stack[master_th->th.th_task_state_top];
22400b57cec5SDimitry Andric         } else {
22410b57cec5SDimitry Andric #endif
22420b57cec5SDimitry Andric           master_th->th.th_task_state = 0;
22430b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
22440b57cec5SDimitry Andric         }
22450b57cec5SDimitry Andric #endif
22460b57cec5SDimitry Andric       }
22470b57cec5SDimitry Andric #if !KMP_NESTED_HOT_TEAMS
22480b57cec5SDimitry Andric       KMP_DEBUG_ASSERT((master_th->th.th_task_team == NULL) ||
22490b57cec5SDimitry Andric                        (team == root->r.r_hot_team));
22500b57cec5SDimitry Andric #endif
22510b57cec5SDimitry Andric     }
22520b57cec5SDimitry Andric 
22530b57cec5SDimitry Andric     KA_TRACE(
22540b57cec5SDimitry Andric         20,
22550b57cec5SDimitry Andric         ("__kmp_fork_call: T#%d(%d:%d)->(%d:0) created a team of %d threads\n",
22560b57cec5SDimitry Andric          gtid, parent_team->t.t_id, team->t.t_master_tid, team->t.t_id,
22570b57cec5SDimitry Andric          team->t.t_nproc));
22580b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(team != root->r.r_hot_team ||
22590b57cec5SDimitry Andric                      (team->t.t_master_tid == 0 &&
22600b57cec5SDimitry Andric                       (team->t.t_parent == root->r.r_root_team ||
22610b57cec5SDimitry Andric                        team->t.t_parent->t.t_serialized)));
22620b57cec5SDimitry Andric     KMP_MB();
22630b57cec5SDimitry Andric 
22640b57cec5SDimitry Andric     /* now, setup the arguments */
22650b57cec5SDimitry Andric     argv = (void **)team->t.t_argv;
22660b57cec5SDimitry Andric     if (ap) {
22670b57cec5SDimitry Andric       for (i = argc - 1; i >= 0; --i) {
226816794618SDimitry Andric         void *new_argv = va_arg(kmp_va_deref(ap), void *);
22690b57cec5SDimitry Andric         KMP_CHECK_UPDATE(*argv, new_argv);
22700b57cec5SDimitry Andric         argv++;
22710b57cec5SDimitry Andric       }
22720b57cec5SDimitry Andric     } else {
22730b57cec5SDimitry Andric       for (i = 0; i < argc; ++i) {
22740b57cec5SDimitry Andric         // Get args from parent team for teams construct
22750b57cec5SDimitry Andric         KMP_CHECK_UPDATE(argv[i], team->t.t_parent->t.t_argv[i]);
22760b57cec5SDimitry Andric       }
22770b57cec5SDimitry Andric     }
22780b57cec5SDimitry Andric 
22790b57cec5SDimitry Andric     /* now actually fork the threads */
22800b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_master_active, master_active);
22810b57cec5SDimitry Andric     if (!root->r.r_active) // Only do assignment if it prevents cache ping-pong
22820b57cec5SDimitry Andric       root->r.r_active = TRUE;
22830b57cec5SDimitry Andric 
2284349cc55cSDimitry Andric     __kmp_fork_team_threads(root, team, master_th, gtid, !ap);
22850b57cec5SDimitry Andric     __kmp_setup_icv_copy(team, nthreads,
22860b57cec5SDimitry Andric                          &master_th->th.th_current_task->td_icvs, loc);
22870b57cec5SDimitry Andric 
22880b57cec5SDimitry Andric #if OMPT_SUPPORT
22890b57cec5SDimitry Andric     master_th->th.ompt_thread_info.state = ompt_state_work_parallel;
22900b57cec5SDimitry Andric #endif
22910b57cec5SDimitry Andric 
22920b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
22930b57cec5SDimitry Andric 
22940b57cec5SDimitry Andric #if USE_ITT_BUILD
22950b57cec5SDimitry Andric     if (team->t.t_active_level == 1 // only report frames at level 1
22960b57cec5SDimitry Andric         && !master_th->th.th_teams_microtask) { // not in teams construct
22970b57cec5SDimitry Andric #if USE_ITT_NOTIFY
22980b57cec5SDimitry Andric       if ((__itt_frame_submit_v3_ptr || KMP_ITT_DEBUG) &&
22990b57cec5SDimitry Andric           (__kmp_forkjoin_frames_mode == 3 ||
23000b57cec5SDimitry Andric            __kmp_forkjoin_frames_mode == 1)) {
23010b57cec5SDimitry Andric         kmp_uint64 tmp_time = 0;
23020b57cec5SDimitry Andric         if (__itt_get_timestamp_ptr)
23030b57cec5SDimitry Andric           tmp_time = __itt_get_timestamp();
23040b57cec5SDimitry Andric         // Internal fork - report frame begin
23050b57cec5SDimitry Andric         master_th->th.th_frame_time = tmp_time;
23060b57cec5SDimitry Andric         if (__kmp_forkjoin_frames_mode == 3)
23070b57cec5SDimitry Andric           team->t.t_region_time = tmp_time;
23080b57cec5SDimitry Andric       } else
23090b57cec5SDimitry Andric // only one notification scheme (either "submit" or "forking/joined", not both)
23100b57cec5SDimitry Andric #endif /* USE_ITT_NOTIFY */
23110b57cec5SDimitry Andric         if ((__itt_frame_begin_v3_ptr || KMP_ITT_DEBUG) &&
23120b57cec5SDimitry Andric             __kmp_forkjoin_frames && !__kmp_forkjoin_frames_mode) {
23130b57cec5SDimitry Andric           // Mark start of "parallel" region for Intel(R) VTune(TM) analyzer.
23140b57cec5SDimitry Andric           __kmp_itt_region_forking(gtid, team->t.t_nproc, 0);
23150b57cec5SDimitry Andric         }
23160b57cec5SDimitry Andric     }
23170b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
23180b57cec5SDimitry Andric 
23190b57cec5SDimitry Andric     /* now go on and do the work */
23200b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(team == __kmp_threads[gtid]->th.th_team);
23210b57cec5SDimitry Andric     KMP_MB();
23220b57cec5SDimitry Andric     KF_TRACE(10,
23230b57cec5SDimitry Andric              ("__kmp_internal_fork : root=%p, team=%p, master_th=%p, gtid=%d\n",
23240b57cec5SDimitry Andric               root, team, master_th, gtid));
23250b57cec5SDimitry Andric 
23260b57cec5SDimitry Andric #if USE_ITT_BUILD
23270b57cec5SDimitry Andric     if (__itt_stack_caller_create_ptr) {
2328fe6060f1SDimitry Andric       // create new stack stitching id before entering fork barrier
2329fe6060f1SDimitry Andric       if (!enter_teams) {
2330fe6060f1SDimitry Andric         KMP_DEBUG_ASSERT(team->t.t_stack_id == NULL);
2331fe6060f1SDimitry Andric         team->t.t_stack_id = __kmp_itt_stack_caller_create();
2332fe6060f1SDimitry Andric       } else if (parent_team->t.t_serialized) {
2333fe6060f1SDimitry Andric         // keep stack stitching id in the serialized parent_team;
2334fe6060f1SDimitry Andric         // current team will be used for parallel inside the teams;
2335fe6060f1SDimitry Andric         // if parent_team is active, then it already keeps stack stitching id
2336fe6060f1SDimitry Andric         // for the league of teams
2337fe6060f1SDimitry Andric         KMP_DEBUG_ASSERT(parent_team->t.t_stack_id == NULL);
2338fe6060f1SDimitry Andric         parent_team->t.t_stack_id = __kmp_itt_stack_caller_create();
2339fe6060f1SDimitry Andric       }
23400b57cec5SDimitry Andric     }
23410b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
23420b57cec5SDimitry Andric 
2343fe6060f1SDimitry Andric     // AC: skip __kmp_internal_fork at teams construct, let only primary
23440b57cec5SDimitry Andric     // threads execute
23450b57cec5SDimitry Andric     if (ap) {
23460b57cec5SDimitry Andric       __kmp_internal_fork(loc, gtid, team);
23470b57cec5SDimitry Andric       KF_TRACE(10, ("__kmp_internal_fork : after : root=%p, team=%p, "
23480b57cec5SDimitry Andric                     "master_th=%p, gtid=%d\n",
23490b57cec5SDimitry Andric                     root, team, master_th, gtid));
23500b57cec5SDimitry Andric     }
23510b57cec5SDimitry Andric 
23520b57cec5SDimitry Andric     if (call_context == fork_context_gnu) {
23530b57cec5SDimitry Andric       KA_TRACE(20, ("__kmp_fork_call: parallel exit T#%d\n", gtid));
23540b57cec5SDimitry Andric       return TRUE;
23550b57cec5SDimitry Andric     }
23560b57cec5SDimitry Andric 
2357fe6060f1SDimitry Andric     /* Invoke microtask for PRIMARY thread */
23580b57cec5SDimitry Andric     KA_TRACE(20, ("__kmp_fork_call: T#%d(%d:0) invoke microtask = %p\n", gtid,
23590b57cec5SDimitry Andric                   team->t.t_id, team->t.t_pkfn));
23600b57cec5SDimitry Andric   } // END of timer KMP_fork_call block
23610b57cec5SDimitry Andric 
23620b57cec5SDimitry Andric #if KMP_STATS_ENABLED
23630b57cec5SDimitry Andric   // If beginning a teams construct, then change thread state
23640b57cec5SDimitry Andric   stats_state_e previous_state = KMP_GET_THREAD_STATE();
23650b57cec5SDimitry Andric   if (!ap) {
23660b57cec5SDimitry Andric     KMP_SET_THREAD_STATE(stats_state_e::TEAMS_REGION);
23670b57cec5SDimitry Andric   }
23680b57cec5SDimitry Andric #endif
23690b57cec5SDimitry Andric 
23700b57cec5SDimitry Andric   if (!team->t.t_invoke(gtid)) {
2371fe6060f1SDimitry Andric     KMP_ASSERT2(0, "cannot invoke microtask for PRIMARY thread");
23720b57cec5SDimitry Andric   }
23730b57cec5SDimitry Andric 
23740b57cec5SDimitry Andric #if KMP_STATS_ENABLED
23750b57cec5SDimitry Andric   // If was beginning of a teams construct, then reset thread state
23760b57cec5SDimitry Andric   if (!ap) {
23770b57cec5SDimitry Andric     KMP_SET_THREAD_STATE(previous_state);
23780b57cec5SDimitry Andric   }
23790b57cec5SDimitry Andric #endif
23800b57cec5SDimitry Andric 
23810b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_fork_call: T#%d(%d:0) done microtask = %p\n", gtid,
23820b57cec5SDimitry Andric                 team->t.t_id, team->t.t_pkfn));
23830b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
23840b57cec5SDimitry Andric 
23850b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_fork_call: parallel exit T#%d\n", gtid));
23860b57cec5SDimitry Andric #if OMPT_SUPPORT
23870b57cec5SDimitry Andric   if (ompt_enabled.enabled) {
23880b57cec5SDimitry Andric     master_th->th.ompt_thread_info.state = ompt_state_overhead;
23890b57cec5SDimitry Andric   }
23900b57cec5SDimitry Andric #endif
23910b57cec5SDimitry Andric 
23920b57cec5SDimitry Andric   return TRUE;
23930b57cec5SDimitry Andric }
23940b57cec5SDimitry Andric 
23950b57cec5SDimitry Andric #if OMPT_SUPPORT
__kmp_join_restore_state(kmp_info_t * thread,kmp_team_t * team)23960b57cec5SDimitry Andric static inline void __kmp_join_restore_state(kmp_info_t *thread,
23970b57cec5SDimitry Andric                                             kmp_team_t *team) {
23980b57cec5SDimitry Andric   // restore state outside the region
23990b57cec5SDimitry Andric   thread->th.ompt_thread_info.state =
24000b57cec5SDimitry Andric       ((team->t.t_serialized) ? ompt_state_work_serial
24010b57cec5SDimitry Andric                               : ompt_state_work_parallel);
24020b57cec5SDimitry Andric }
24030b57cec5SDimitry Andric 
__kmp_join_ompt(int gtid,kmp_info_t * thread,kmp_team_t * team,ompt_data_t * parallel_data,int flags,void * codeptr)24040b57cec5SDimitry Andric static inline void __kmp_join_ompt(int gtid, kmp_info_t *thread,
24050b57cec5SDimitry Andric                                    kmp_team_t *team, ompt_data_t *parallel_data,
2406489b1cf2SDimitry Andric                                    int flags, void *codeptr) {
24070b57cec5SDimitry Andric   ompt_task_info_t *task_info = __ompt_get_task_info_object(0);
24080b57cec5SDimitry Andric   if (ompt_enabled.ompt_callback_parallel_end) {
24090b57cec5SDimitry Andric     ompt_callbacks.ompt_callback(ompt_callback_parallel_end)(
2410489b1cf2SDimitry Andric         parallel_data, &(task_info->task_data), flags, codeptr);
24110b57cec5SDimitry Andric   }
24120b57cec5SDimitry Andric 
24130b57cec5SDimitry Andric   task_info->frame.enter_frame = ompt_data_none;
24140b57cec5SDimitry Andric   __kmp_join_restore_state(thread, team);
24150b57cec5SDimitry Andric }
24160b57cec5SDimitry Andric #endif
24170b57cec5SDimitry Andric 
__kmp_join_call(ident_t * loc,int gtid,enum fork_context_e fork_context,int exit_teams)24180b57cec5SDimitry Andric void __kmp_join_call(ident_t *loc, int gtid
24190b57cec5SDimitry Andric #if OMPT_SUPPORT
24200b57cec5SDimitry Andric                      ,
24210b57cec5SDimitry Andric                      enum fork_context_e fork_context
24220b57cec5SDimitry Andric #endif
24230b57cec5SDimitry Andric                      ,
24240b57cec5SDimitry Andric                      int exit_teams) {
24250b57cec5SDimitry Andric   KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_join_call);
24260b57cec5SDimitry Andric   kmp_team_t *team;
24270b57cec5SDimitry Andric   kmp_team_t *parent_team;
24280b57cec5SDimitry Andric   kmp_info_t *master_th;
24290b57cec5SDimitry Andric   kmp_root_t *root;
24300b57cec5SDimitry Andric   int master_active;
24310b57cec5SDimitry Andric 
24320b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_join_call: enter T#%d\n", gtid));
24330b57cec5SDimitry Andric 
24340b57cec5SDimitry Andric   /* setup current data */
24350b57cec5SDimitry Andric   master_th = __kmp_threads[gtid];
24360b57cec5SDimitry Andric   root = master_th->th.th_root;
24370b57cec5SDimitry Andric   team = master_th->th.th_team;
24380b57cec5SDimitry Andric   parent_team = team->t.t_parent;
24390b57cec5SDimitry Andric 
24400b57cec5SDimitry Andric   master_th->th.th_ident = loc;
24410b57cec5SDimitry Andric 
24420b57cec5SDimitry Andric #if OMPT_SUPPORT
2443489b1cf2SDimitry Andric   void *team_microtask = (void *)team->t.t_pkfn;
2444e8d8bef9SDimitry Andric   // For GOMP interface with serialized parallel, need the
2445e8d8bef9SDimitry Andric   // __kmpc_end_serialized_parallel to call hooks for OMPT end-implicit-task
2446e8d8bef9SDimitry Andric   // and end-parallel events.
2447e8d8bef9SDimitry Andric   if (ompt_enabled.enabled &&
2448e8d8bef9SDimitry Andric       !(team->t.t_serialized && fork_context == fork_context_gnu)) {
24490b57cec5SDimitry Andric     master_th->th.ompt_thread_info.state = ompt_state_overhead;
24500b57cec5SDimitry Andric   }
24510b57cec5SDimitry Andric #endif
24520b57cec5SDimitry Andric 
24530b57cec5SDimitry Andric #if KMP_DEBUG
24540b57cec5SDimitry Andric   if (__kmp_tasking_mode != tskm_immediate_exec && !exit_teams) {
24550b57cec5SDimitry Andric     KA_TRACE(20, ("__kmp_join_call: T#%d, old team = %p old task_team = %p, "
24560b57cec5SDimitry Andric                   "th_task_team = %p\n",
24570b57cec5SDimitry Andric                   __kmp_gtid_from_thread(master_th), team,
24580b57cec5SDimitry Andric                   team->t.t_task_team[master_th->th.th_task_state],
24590b57cec5SDimitry Andric                   master_th->th.th_task_team));
24600b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(master_th->th.th_task_team ==
24610b57cec5SDimitry Andric                      team->t.t_task_team[master_th->th.th_task_state]);
24620b57cec5SDimitry Andric   }
24630b57cec5SDimitry Andric #endif
24640b57cec5SDimitry Andric 
24650b57cec5SDimitry Andric   if (team->t.t_serialized) {
24660b57cec5SDimitry Andric     if (master_th->th.th_teams_microtask) {
24670b57cec5SDimitry Andric       // We are in teams construct
24680b57cec5SDimitry Andric       int level = team->t.t_level;
24690b57cec5SDimitry Andric       int tlevel = master_th->th.th_teams_level;
24700b57cec5SDimitry Andric       if (level == tlevel) {
24710b57cec5SDimitry Andric         // AC: we haven't incremented it earlier at start of teams construct,
24720b57cec5SDimitry Andric         //     so do it here - at the end of teams construct
24730b57cec5SDimitry Andric         team->t.t_level++;
24740b57cec5SDimitry Andric       } else if (level == tlevel + 1) {
24750b57cec5SDimitry Andric         // AC: we are exiting parallel inside teams, need to increment
24760b57cec5SDimitry Andric         // serialization in order to restore it in the next call to
24770b57cec5SDimitry Andric         // __kmpc_end_serialized_parallel
24780b57cec5SDimitry Andric         team->t.t_serialized++;
24790b57cec5SDimitry Andric       }
24800b57cec5SDimitry Andric     }
24810b57cec5SDimitry Andric     __kmpc_end_serialized_parallel(loc, gtid);
24820b57cec5SDimitry Andric 
24830b57cec5SDimitry Andric #if OMPT_SUPPORT
24840b57cec5SDimitry Andric     if (ompt_enabled.enabled) {
2485bdd1243dSDimitry Andric       if (fork_context == fork_context_gnu) {
2486bdd1243dSDimitry Andric         __ompt_lw_taskteam_unlink(master_th);
2487bdd1243dSDimitry Andric       }
24880b57cec5SDimitry Andric       __kmp_join_restore_state(master_th, parent_team);
24890b57cec5SDimitry Andric     }
24900b57cec5SDimitry Andric #endif
24910b57cec5SDimitry Andric 
24920b57cec5SDimitry Andric     return;
24930b57cec5SDimitry Andric   }
24940b57cec5SDimitry Andric 
24950b57cec5SDimitry Andric   master_active = team->t.t_master_active;
24960b57cec5SDimitry Andric 
24970b57cec5SDimitry Andric   if (!exit_teams) {
24980b57cec5SDimitry Andric     // AC: No barrier for internal teams at exit from teams construct.
24990b57cec5SDimitry Andric     //     But there is barrier for external team (league).
25000b57cec5SDimitry Andric     __kmp_internal_join(loc, gtid, team);
2501fe6060f1SDimitry Andric #if USE_ITT_BUILD
2502fe6060f1SDimitry Andric     if (__itt_stack_caller_create_ptr) {
2503fe6060f1SDimitry Andric       KMP_DEBUG_ASSERT(team->t.t_stack_id != NULL);
2504fe6060f1SDimitry Andric       // destroy the stack stitching id after join barrier
2505fe6060f1SDimitry Andric       __kmp_itt_stack_caller_destroy((__itt_caller)team->t.t_stack_id);
2506fe6060f1SDimitry Andric       team->t.t_stack_id = NULL;
2507fe6060f1SDimitry Andric     }
2508fe6060f1SDimitry Andric #endif
25090b57cec5SDimitry Andric   } else {
25100b57cec5SDimitry Andric     master_th->th.th_task_state =
25110b57cec5SDimitry Andric         0; // AC: no tasking in teams (out of any parallel)
2512fe6060f1SDimitry Andric #if USE_ITT_BUILD
2513fe6060f1SDimitry Andric     if (__itt_stack_caller_create_ptr && parent_team->t.t_serialized) {
2514fe6060f1SDimitry Andric       KMP_DEBUG_ASSERT(parent_team->t.t_stack_id != NULL);
2515fe6060f1SDimitry Andric       // destroy the stack stitching id on exit from the teams construct
2516fe6060f1SDimitry Andric       // if parent_team is active, then the id will be destroyed later on
2517fe6060f1SDimitry Andric       // by master of the league of teams
2518fe6060f1SDimitry Andric       __kmp_itt_stack_caller_destroy((__itt_caller)parent_team->t.t_stack_id);
2519fe6060f1SDimitry Andric       parent_team->t.t_stack_id = NULL;
2520fe6060f1SDimitry Andric     }
2521fe6060f1SDimitry Andric #endif
25220b57cec5SDimitry Andric   }
25230b57cec5SDimitry Andric 
25240b57cec5SDimitry Andric   KMP_MB();
25250b57cec5SDimitry Andric 
25260b57cec5SDimitry Andric #if OMPT_SUPPORT
25270b57cec5SDimitry Andric   ompt_data_t *parallel_data = &(team->t.ompt_team_info.parallel_data);
25280b57cec5SDimitry Andric   void *codeptr = team->t.ompt_team_info.master_return_address;
25290b57cec5SDimitry Andric #endif
25300b57cec5SDimitry Andric 
25310b57cec5SDimitry Andric #if USE_ITT_BUILD
25320b57cec5SDimitry Andric   // Mark end of "parallel" region for Intel(R) VTune(TM) analyzer.
25330b57cec5SDimitry Andric   if (team->t.t_active_level == 1 &&
2534e8d8bef9SDimitry Andric       (!master_th->th.th_teams_microtask || /* not in teams construct */
2535e8d8bef9SDimitry Andric        master_th->th.th_teams_size.nteams == 1)) {
25360b57cec5SDimitry Andric     master_th->th.th_ident = loc;
25370b57cec5SDimitry Andric     // only one notification scheme (either "submit" or "forking/joined", not
25380b57cec5SDimitry Andric     // both)
25390b57cec5SDimitry Andric     if ((__itt_frame_submit_v3_ptr || KMP_ITT_DEBUG) &&
25400b57cec5SDimitry Andric         __kmp_forkjoin_frames_mode == 3)
25410b57cec5SDimitry Andric       __kmp_itt_frame_submit(gtid, team->t.t_region_time,
25420b57cec5SDimitry Andric                              master_th->th.th_frame_time, 0, loc,
25430b57cec5SDimitry Andric                              master_th->th.th_team_nproc, 1);
25440b57cec5SDimitry Andric     else if ((__itt_frame_end_v3_ptr || KMP_ITT_DEBUG) &&
25450b57cec5SDimitry Andric              !__kmp_forkjoin_frames_mode && __kmp_forkjoin_frames)
25460b57cec5SDimitry Andric       __kmp_itt_region_joined(gtid);
25470b57cec5SDimitry Andric   } // active_level == 1
25480b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
25490b57cec5SDimitry Andric 
2550349cc55cSDimitry Andric #if KMP_AFFINITY_SUPPORTED
2551349cc55cSDimitry Andric   if (!exit_teams) {
2552349cc55cSDimitry Andric     // Restore master thread's partition.
2553349cc55cSDimitry Andric     master_th->th.th_first_place = team->t.t_first_place;
2554349cc55cSDimitry Andric     master_th->th.th_last_place = team->t.t_last_place;
2555349cc55cSDimitry Andric   }
2556349cc55cSDimitry Andric #endif // KMP_AFFINITY_SUPPORTED
2557349cc55cSDimitry Andric 
25580b57cec5SDimitry Andric   if (master_th->th.th_teams_microtask && !exit_teams &&
25590b57cec5SDimitry Andric       team->t.t_pkfn != (microtask_t)__kmp_teams_master &&
25600b57cec5SDimitry Andric       team->t.t_level == master_th->th.th_teams_level + 1) {
25610b57cec5SDimitry Andric // AC: We need to leave the team structure intact at the end of parallel
25620b57cec5SDimitry Andric // inside the teams construct, so that at the next parallel same (hot) team
25630b57cec5SDimitry Andric // works, only adjust nesting levels
2564489b1cf2SDimitry Andric #if OMPT_SUPPORT
2565489b1cf2SDimitry Andric     ompt_data_t ompt_parallel_data = ompt_data_none;
2566489b1cf2SDimitry Andric     if (ompt_enabled.enabled) {
2567489b1cf2SDimitry Andric       ompt_task_info_t *task_info = __ompt_get_task_info_object(0);
2568489b1cf2SDimitry Andric       if (ompt_enabled.ompt_callback_implicit_task) {
2569489b1cf2SDimitry Andric         int ompt_team_size = team->t.t_nproc;
2570489b1cf2SDimitry Andric         ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
2571489b1cf2SDimitry Andric             ompt_scope_end, NULL, &(task_info->task_data), ompt_team_size,
2572489b1cf2SDimitry Andric             OMPT_CUR_TASK_INFO(master_th)->thread_num, ompt_task_implicit);
2573489b1cf2SDimitry Andric       }
2574489b1cf2SDimitry Andric       task_info->frame.exit_frame = ompt_data_none;
2575489b1cf2SDimitry Andric       task_info->task_data = ompt_data_none;
2576489b1cf2SDimitry Andric       ompt_parallel_data = *OMPT_CUR_TEAM_DATA(master_th);
2577489b1cf2SDimitry Andric       __ompt_lw_taskteam_unlink(master_th);
2578489b1cf2SDimitry Andric     }
2579489b1cf2SDimitry Andric #endif
25800b57cec5SDimitry Andric     /* Decrement our nested depth level */
25810b57cec5SDimitry Andric     team->t.t_level--;
25820b57cec5SDimitry Andric     team->t.t_active_level--;
25830b57cec5SDimitry Andric     KMP_ATOMIC_DEC(&root->r.r_in_parallel);
25840b57cec5SDimitry Andric 
25850b57cec5SDimitry Andric     // Restore number of threads in the team if needed. This code relies on
25860b57cec5SDimitry Andric     // the proper adjustment of th_teams_size.nth after the fork in
2587fe6060f1SDimitry Andric     // __kmp_teams_master on each teams primary thread in the case that
25880b57cec5SDimitry Andric     // __kmp_reserve_threads reduced it.
25890b57cec5SDimitry Andric     if (master_th->th.th_team_nproc < master_th->th.th_teams_size.nth) {
25900b57cec5SDimitry Andric       int old_num = master_th->th.th_team_nproc;
25910b57cec5SDimitry Andric       int new_num = master_th->th.th_teams_size.nth;
25920b57cec5SDimitry Andric       kmp_info_t **other_threads = team->t.t_threads;
25930b57cec5SDimitry Andric       team->t.t_nproc = new_num;
25940b57cec5SDimitry Andric       for (int i = 0; i < old_num; ++i) {
25950b57cec5SDimitry Andric         other_threads[i]->th.th_team_nproc = new_num;
25960b57cec5SDimitry Andric       }
25970b57cec5SDimitry Andric       // Adjust states of non-used threads of the team
25980b57cec5SDimitry Andric       for (int i = old_num; i < new_num; ++i) {
25990b57cec5SDimitry Andric         // Re-initialize thread's barrier data.
26000b57cec5SDimitry Andric         KMP_DEBUG_ASSERT(other_threads[i]);
26010b57cec5SDimitry Andric         kmp_balign_t *balign = other_threads[i]->th.th_bar;
26020b57cec5SDimitry Andric         for (int b = 0; b < bs_last_barrier; ++b) {
26030b57cec5SDimitry Andric           balign[b].bb.b_arrived = team->t.t_bar[b].b_arrived;
26040b57cec5SDimitry Andric           KMP_DEBUG_ASSERT(balign[b].bb.wait_flag != KMP_BARRIER_PARENT_FLAG);
26050b57cec5SDimitry Andric #if USE_DEBUGGER
26060b57cec5SDimitry Andric           balign[b].bb.b_worker_arrived = team->t.t_bar[b].b_team_arrived;
26070b57cec5SDimitry Andric #endif
26080b57cec5SDimitry Andric         }
26090b57cec5SDimitry Andric         if (__kmp_tasking_mode != tskm_immediate_exec) {
26100b57cec5SDimitry Andric           // Synchronize thread's task state
26110b57cec5SDimitry Andric           other_threads[i]->th.th_task_state = master_th->th.th_task_state;
26120b57cec5SDimitry Andric         }
26130b57cec5SDimitry Andric       }
26140b57cec5SDimitry Andric     }
26150b57cec5SDimitry Andric 
26160b57cec5SDimitry Andric #if OMPT_SUPPORT
26170b57cec5SDimitry Andric     if (ompt_enabled.enabled) {
2618489b1cf2SDimitry Andric       __kmp_join_ompt(gtid, master_th, parent_team, &ompt_parallel_data,
2619489b1cf2SDimitry Andric                       OMPT_INVOKER(fork_context) | ompt_parallel_team, codeptr);
26200b57cec5SDimitry Andric     }
26210b57cec5SDimitry Andric #endif
26220b57cec5SDimitry Andric 
26230b57cec5SDimitry Andric     return;
26240b57cec5SDimitry Andric   }
26250b57cec5SDimitry Andric 
26260b57cec5SDimitry Andric   /* do cleanup and restore the parent team */
26270b57cec5SDimitry Andric   master_th->th.th_info.ds.ds_tid = team->t.t_master_tid;
26280b57cec5SDimitry Andric   master_th->th.th_local.this_construct = team->t.t_master_this_cons;
26290b57cec5SDimitry Andric 
26300b57cec5SDimitry Andric   master_th->th.th_dispatch = &parent_team->t.t_dispatch[team->t.t_master_tid];
26310b57cec5SDimitry Andric 
26320b57cec5SDimitry Andric   /* jc: The following lock has instructions with REL and ACQ semantics,
26330b57cec5SDimitry Andric      separating the parallel user code called in this parallel region
26340b57cec5SDimitry Andric      from the serial user code called after this function returns. */
26350b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
26360b57cec5SDimitry Andric 
26370b57cec5SDimitry Andric   if (!master_th->th.th_teams_microtask ||
26380b57cec5SDimitry Andric       team->t.t_level > master_th->th.th_teams_level) {
26390b57cec5SDimitry Andric     /* Decrement our nested depth level */
26400b57cec5SDimitry Andric     KMP_ATOMIC_DEC(&root->r.r_in_parallel);
26410b57cec5SDimitry Andric   }
26420b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(root->r.r_in_parallel >= 0);
26430b57cec5SDimitry Andric 
26440b57cec5SDimitry Andric #if OMPT_SUPPORT
26450b57cec5SDimitry Andric   if (ompt_enabled.enabled) {
26460b57cec5SDimitry Andric     ompt_task_info_t *task_info = __ompt_get_task_info_object(0);
26470b57cec5SDimitry Andric     if (ompt_enabled.ompt_callback_implicit_task) {
2648489b1cf2SDimitry Andric       int flags = (team_microtask == (void *)__kmp_teams_master)
2649489b1cf2SDimitry Andric                       ? ompt_task_initial
2650489b1cf2SDimitry Andric                       : ompt_task_implicit;
2651489b1cf2SDimitry Andric       int ompt_team_size = (flags == ompt_task_initial) ? 0 : team->t.t_nproc;
26520b57cec5SDimitry Andric       ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
26530b57cec5SDimitry Andric           ompt_scope_end, NULL, &(task_info->task_data), ompt_team_size,
2654489b1cf2SDimitry Andric           OMPT_CUR_TASK_INFO(master_th)->thread_num, flags);
26550b57cec5SDimitry Andric     }
26560b57cec5SDimitry Andric     task_info->frame.exit_frame = ompt_data_none;
26570b57cec5SDimitry Andric     task_info->task_data = ompt_data_none;
26580b57cec5SDimitry Andric   }
26590b57cec5SDimitry Andric #endif
26600b57cec5SDimitry Andric 
26610b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_join_call1: T#%d, this_thread=%p team=%p\n", 0,
26620b57cec5SDimitry Andric                 master_th, team));
26630b57cec5SDimitry Andric   __kmp_pop_current_task_from_thread(master_th);
26640b57cec5SDimitry Andric 
26650b57cec5SDimitry Andric   master_th->th.th_def_allocator = team->t.t_def_allocator;
26660b57cec5SDimitry Andric 
2667fe6060f1SDimitry Andric #if OMPD_SUPPORT
2668fe6060f1SDimitry Andric   if (ompd_state & OMPD_ENABLE_BP)
2669fe6060f1SDimitry Andric     ompd_bp_parallel_end();
2670fe6060f1SDimitry Andric #endif
26710b57cec5SDimitry Andric   updateHWFPControl(team);
26720b57cec5SDimitry Andric 
26730b57cec5SDimitry Andric   if (root->r.r_active != master_active)
26740b57cec5SDimitry Andric     root->r.r_active = master_active;
26750b57cec5SDimitry Andric 
26760b57cec5SDimitry Andric   __kmp_free_team(root, team USE_NESTED_HOT_ARG(
26770b57cec5SDimitry Andric                             master_th)); // this will free worker threads
26780b57cec5SDimitry Andric 
26790b57cec5SDimitry Andric   /* this race was fun to find. make sure the following is in the critical
26800b57cec5SDimitry Andric      region otherwise assertions may fail occasionally since the old team may be
26810b57cec5SDimitry Andric      reallocated and the hierarchy appears inconsistent. it is actually safe to
26820b57cec5SDimitry Andric      run and won't cause any bugs, but will cause those assertion failures. it's
26830b57cec5SDimitry Andric      only one deref&assign so might as well put this in the critical region */
26840b57cec5SDimitry Andric   master_th->th.th_team = parent_team;
26850b57cec5SDimitry Andric   master_th->th.th_team_nproc = parent_team->t.t_nproc;
26860b57cec5SDimitry Andric   master_th->th.th_team_master = parent_team->t.t_threads[0];
26870b57cec5SDimitry Andric   master_th->th.th_team_serialized = parent_team->t.t_serialized;
26880b57cec5SDimitry Andric 
26890b57cec5SDimitry Andric   /* restore serialized team, if need be */
26900b57cec5SDimitry Andric   if (parent_team->t.t_serialized &&
26910b57cec5SDimitry Andric       parent_team != master_th->th.th_serial_team &&
26920b57cec5SDimitry Andric       parent_team != root->r.r_root_team) {
26930b57cec5SDimitry Andric     __kmp_free_team(root,
26940b57cec5SDimitry Andric                     master_th->th.th_serial_team USE_NESTED_HOT_ARG(NULL));
26950b57cec5SDimitry Andric     master_th->th.th_serial_team = parent_team;
26960b57cec5SDimitry Andric   }
26970b57cec5SDimitry Andric 
26980b57cec5SDimitry Andric   if (__kmp_tasking_mode != tskm_immediate_exec) {
26990b57cec5SDimitry Andric     if (master_th->th.th_task_state_top >
27000b57cec5SDimitry Andric         0) { // Restore task state from memo stack
27010b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(master_th->th.th_task_state_memo_stack);
2702fe6060f1SDimitry Andric       // Remember primary thread's state if we re-use this nested hot team
27030b57cec5SDimitry Andric       master_th->th.th_task_state_memo_stack[master_th->th.th_task_state_top] =
27040b57cec5SDimitry Andric           master_th->th.th_task_state;
27050b57cec5SDimitry Andric       --master_th->th.th_task_state_top; // pop
27060b57cec5SDimitry Andric       // Now restore state at this level
27070b57cec5SDimitry Andric       master_th->th.th_task_state =
27080b57cec5SDimitry Andric           master_th->th
27090b57cec5SDimitry Andric               .th_task_state_memo_stack[master_th->th.th_task_state_top];
2710bdd1243dSDimitry Andric     } else if (team != root->r.r_hot_team) {
2711bdd1243dSDimitry Andric       // Reset the task state of primary thread if we are not hot team because
2712bdd1243dSDimitry Andric       // in this case all the worker threads will be free, and their task state
2713bdd1243dSDimitry Andric       // will be reset. If not reset the primary's, the task state will be
2714bdd1243dSDimitry Andric       // inconsistent.
2715bdd1243dSDimitry Andric       master_th->th.th_task_state = 0;
27160b57cec5SDimitry Andric     }
2717fe6060f1SDimitry Andric     // Copy the task team from the parent team to the primary thread
27180b57cec5SDimitry Andric     master_th->th.th_task_team =
27190b57cec5SDimitry Andric         parent_team->t.t_task_team[master_th->th.th_task_state];
27200b57cec5SDimitry Andric     KA_TRACE(20,
2721fe6060f1SDimitry Andric              ("__kmp_join_call: Primary T#%d restoring task_team %p, team %p\n",
27220b57cec5SDimitry Andric               __kmp_gtid_from_thread(master_th), master_th->th.th_task_team,
27230b57cec5SDimitry Andric               parent_team));
27240b57cec5SDimitry Andric   }
27250b57cec5SDimitry Andric 
27260b57cec5SDimitry Andric   // TODO: GEH - cannot do this assertion because root thread not set up as
27270b57cec5SDimitry Andric   // executing
27280b57cec5SDimitry Andric   // KMP_ASSERT( master_th->th.th_current_task->td_flags.executing == 0 );
27290b57cec5SDimitry Andric   master_th->th.th_current_task->td_flags.executing = 1;
27300b57cec5SDimitry Andric 
27310b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
27320b57cec5SDimitry Andric 
2733fcaf7f86SDimitry Andric #if KMP_AFFINITY_SUPPORTED
2734bdd1243dSDimitry Andric   if (master_th->th.th_team->t.t_level == 0 && __kmp_affinity.flags.reset) {
2735fcaf7f86SDimitry Andric     __kmp_reset_root_init_mask(gtid);
2736fcaf7f86SDimitry Andric   }
2737fcaf7f86SDimitry Andric #endif
27380b57cec5SDimitry Andric #if OMPT_SUPPORT
2739489b1cf2SDimitry Andric   int flags =
2740489b1cf2SDimitry Andric       OMPT_INVOKER(fork_context) |
2741489b1cf2SDimitry Andric       ((team_microtask == (void *)__kmp_teams_master) ? ompt_parallel_league
2742489b1cf2SDimitry Andric                                                       : ompt_parallel_team);
27430b57cec5SDimitry Andric   if (ompt_enabled.enabled) {
2744489b1cf2SDimitry Andric     __kmp_join_ompt(gtid, master_th, parent_team, parallel_data, flags,
27450b57cec5SDimitry Andric                     codeptr);
27460b57cec5SDimitry Andric   }
27470b57cec5SDimitry Andric #endif
27480b57cec5SDimitry Andric 
27490b57cec5SDimitry Andric   KMP_MB();
27500b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_join_call: exit T#%d\n", gtid));
27510b57cec5SDimitry Andric }
27520b57cec5SDimitry Andric 
27530b57cec5SDimitry Andric /* Check whether we should push an internal control record onto the
27540b57cec5SDimitry Andric    serial team stack.  If so, do it.  */
__kmp_save_internal_controls(kmp_info_t * thread)27550b57cec5SDimitry Andric void __kmp_save_internal_controls(kmp_info_t *thread) {
27560b57cec5SDimitry Andric 
27570b57cec5SDimitry Andric   if (thread->th.th_team != thread->th.th_serial_team) {
27580b57cec5SDimitry Andric     return;
27590b57cec5SDimitry Andric   }
27600b57cec5SDimitry Andric   if (thread->th.th_team->t.t_serialized > 1) {
27610b57cec5SDimitry Andric     int push = 0;
27620b57cec5SDimitry Andric 
27630b57cec5SDimitry Andric     if (thread->th.th_team->t.t_control_stack_top == NULL) {
27640b57cec5SDimitry Andric       push = 1;
27650b57cec5SDimitry Andric     } else {
27660b57cec5SDimitry Andric       if (thread->th.th_team->t.t_control_stack_top->serial_nesting_level !=
27670b57cec5SDimitry Andric           thread->th.th_team->t.t_serialized) {
27680b57cec5SDimitry Andric         push = 1;
27690b57cec5SDimitry Andric       }
27700b57cec5SDimitry Andric     }
27710b57cec5SDimitry Andric     if (push) { /* push a record on the serial team's stack */
27720b57cec5SDimitry Andric       kmp_internal_control_t *control =
27730b57cec5SDimitry Andric           (kmp_internal_control_t *)__kmp_allocate(
27740b57cec5SDimitry Andric               sizeof(kmp_internal_control_t));
27750b57cec5SDimitry Andric 
27760b57cec5SDimitry Andric       copy_icvs(control, &thread->th.th_current_task->td_icvs);
27770b57cec5SDimitry Andric 
27780b57cec5SDimitry Andric       control->serial_nesting_level = thread->th.th_team->t.t_serialized;
27790b57cec5SDimitry Andric 
27800b57cec5SDimitry Andric       control->next = thread->th.th_team->t.t_control_stack_top;
27810b57cec5SDimitry Andric       thread->th.th_team->t.t_control_stack_top = control;
27820b57cec5SDimitry Andric     }
27830b57cec5SDimitry Andric   }
27840b57cec5SDimitry Andric }
27850b57cec5SDimitry Andric 
27860b57cec5SDimitry Andric /* Changes set_nproc */
__kmp_set_num_threads(int new_nth,int gtid)27870b57cec5SDimitry Andric void __kmp_set_num_threads(int new_nth, int gtid) {
27880b57cec5SDimitry Andric   kmp_info_t *thread;
27890b57cec5SDimitry Andric   kmp_root_t *root;
27900b57cec5SDimitry Andric 
27910b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_set_num_threads: new __kmp_nth = %d\n", new_nth));
27920b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_init_serial);
27930b57cec5SDimitry Andric 
27940b57cec5SDimitry Andric   if (new_nth < 1)
27950b57cec5SDimitry Andric     new_nth = 1;
27960b57cec5SDimitry Andric   else if (new_nth > __kmp_max_nth)
27970b57cec5SDimitry Andric     new_nth = __kmp_max_nth;
27980b57cec5SDimitry Andric 
27990b57cec5SDimitry Andric   KMP_COUNT_VALUE(OMP_set_numthreads, new_nth);
28000b57cec5SDimitry Andric   thread = __kmp_threads[gtid];
28010b57cec5SDimitry Andric   if (thread->th.th_current_task->td_icvs.nproc == new_nth)
28020b57cec5SDimitry Andric     return; // nothing to do
28030b57cec5SDimitry Andric 
28040b57cec5SDimitry Andric   __kmp_save_internal_controls(thread);
28050b57cec5SDimitry Andric 
28060b57cec5SDimitry Andric   set__nproc(thread, new_nth);
28070b57cec5SDimitry Andric 
28080b57cec5SDimitry Andric   // If this omp_set_num_threads() call will cause the hot team size to be
28090b57cec5SDimitry Andric   // reduced (in the absence of a num_threads clause), then reduce it now,
28100b57cec5SDimitry Andric   // rather than waiting for the next parallel region.
28110b57cec5SDimitry Andric   root = thread->th.th_root;
28120b57cec5SDimitry Andric   if (__kmp_init_parallel && (!root->r.r_active) &&
28130b57cec5SDimitry Andric       (root->r.r_hot_team->t.t_nproc > new_nth)
28140b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
28150b57cec5SDimitry Andric       && __kmp_hot_teams_max_level && !__kmp_hot_teams_mode
28160b57cec5SDimitry Andric #endif
28170b57cec5SDimitry Andric   ) {
28180b57cec5SDimitry Andric     kmp_team_t *hot_team = root->r.r_hot_team;
28190b57cec5SDimitry Andric     int f;
28200b57cec5SDimitry Andric 
28210b57cec5SDimitry Andric     __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
28220b57cec5SDimitry Andric 
2823349cc55cSDimitry Andric     if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
2824349cc55cSDimitry Andric       __kmp_resize_dist_barrier(hot_team, hot_team->t.t_nproc, new_nth);
2825349cc55cSDimitry Andric     }
28260b57cec5SDimitry Andric     // Release the extra threads we don't need any more.
28270b57cec5SDimitry Andric     for (f = new_nth; f < hot_team->t.t_nproc; f++) {
28280b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(hot_team->t.t_threads[f] != NULL);
28290b57cec5SDimitry Andric       if (__kmp_tasking_mode != tskm_immediate_exec) {
28300b57cec5SDimitry Andric         // When decreasing team size, threads no longer in the team should unref
28310b57cec5SDimitry Andric         // task team.
28320b57cec5SDimitry Andric         hot_team->t.t_threads[f]->th.th_task_team = NULL;
28330b57cec5SDimitry Andric       }
28340b57cec5SDimitry Andric       __kmp_free_thread(hot_team->t.t_threads[f]);
28350b57cec5SDimitry Andric       hot_team->t.t_threads[f] = NULL;
28360b57cec5SDimitry Andric     }
28370b57cec5SDimitry Andric     hot_team->t.t_nproc = new_nth;
28380b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
28390b57cec5SDimitry Andric     if (thread->th.th_hot_teams) {
28400b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(hot_team == thread->th.th_hot_teams[0].hot_team);
28410b57cec5SDimitry Andric       thread->th.th_hot_teams[0].hot_team_nth = new_nth;
28420b57cec5SDimitry Andric     }
28430b57cec5SDimitry Andric #endif
28440b57cec5SDimitry Andric 
2845349cc55cSDimitry Andric     if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
2846349cc55cSDimitry Andric       hot_team->t.b->update_num_threads(new_nth);
2847349cc55cSDimitry Andric       __kmp_add_threads_to_team(hot_team, new_nth);
2848349cc55cSDimitry Andric     }
2849349cc55cSDimitry Andric 
28500b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
28510b57cec5SDimitry Andric 
28520b57cec5SDimitry Andric     // Update the t_nproc field in the threads that are still active.
28530b57cec5SDimitry Andric     for (f = 0; f < new_nth; f++) {
28540b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(hot_team->t.t_threads[f] != NULL);
28550b57cec5SDimitry Andric       hot_team->t.t_threads[f]->th.th_team_nproc = new_nth;
28560b57cec5SDimitry Andric     }
28570b57cec5SDimitry Andric     // Special flag in case omp_set_num_threads() call
28580b57cec5SDimitry Andric     hot_team->t.t_size_changed = -1;
28590b57cec5SDimitry Andric   }
28600b57cec5SDimitry Andric }
28610b57cec5SDimitry Andric 
28620b57cec5SDimitry Andric /* Changes max_active_levels */
__kmp_set_max_active_levels(int gtid,int max_active_levels)28630b57cec5SDimitry Andric void __kmp_set_max_active_levels(int gtid, int max_active_levels) {
28640b57cec5SDimitry Andric   kmp_info_t *thread;
28650b57cec5SDimitry Andric 
28660b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_set_max_active_levels: new max_active_levels for thread "
28670b57cec5SDimitry Andric                 "%d = (%d)\n",
28680b57cec5SDimitry Andric                 gtid, max_active_levels));
28690b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_init_serial);
28700b57cec5SDimitry Andric 
28710b57cec5SDimitry Andric   // validate max_active_levels
28720b57cec5SDimitry Andric   if (max_active_levels < 0) {
28730b57cec5SDimitry Andric     KMP_WARNING(ActiveLevelsNegative, max_active_levels);
28740b57cec5SDimitry Andric     // We ignore this call if the user has specified a negative value.
28750b57cec5SDimitry Andric     // The current setting won't be changed. The last valid setting will be
28760b57cec5SDimitry Andric     // used. A warning will be issued (if warnings are allowed as controlled by
28770b57cec5SDimitry Andric     // the KMP_WARNINGS env var).
28780b57cec5SDimitry Andric     KF_TRACE(10, ("__kmp_set_max_active_levels: the call is ignored: new "
28790b57cec5SDimitry Andric                   "max_active_levels for thread %d = (%d)\n",
28800b57cec5SDimitry Andric                   gtid, max_active_levels));
28810b57cec5SDimitry Andric     return;
28820b57cec5SDimitry Andric   }
28830b57cec5SDimitry Andric   if (max_active_levels <= KMP_MAX_ACTIVE_LEVELS_LIMIT) {
28840b57cec5SDimitry Andric     // it's OK, the max_active_levels is within the valid range: [ 0;
28850b57cec5SDimitry Andric     // KMP_MAX_ACTIVE_LEVELS_LIMIT ]
28860b57cec5SDimitry Andric     // We allow a zero value. (implementation defined behavior)
28870b57cec5SDimitry Andric   } else {
28880b57cec5SDimitry Andric     KMP_WARNING(ActiveLevelsExceedLimit, max_active_levels,
28890b57cec5SDimitry Andric                 KMP_MAX_ACTIVE_LEVELS_LIMIT);
28900b57cec5SDimitry Andric     max_active_levels = KMP_MAX_ACTIVE_LEVELS_LIMIT;
28910b57cec5SDimitry Andric     // Current upper limit is MAX_INT. (implementation defined behavior)
28920b57cec5SDimitry Andric     // If the input exceeds the upper limit, we correct the input to be the
28930b57cec5SDimitry Andric     // upper limit. (implementation defined behavior)
28940b57cec5SDimitry Andric     // Actually, the flow should never get here until we use MAX_INT limit.
28950b57cec5SDimitry Andric   }
28960b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_set_max_active_levels: after validation: new "
28970b57cec5SDimitry Andric                 "max_active_levels for thread %d = (%d)\n",
28980b57cec5SDimitry Andric                 gtid, max_active_levels));
28990b57cec5SDimitry Andric 
29000b57cec5SDimitry Andric   thread = __kmp_threads[gtid];
29010b57cec5SDimitry Andric 
29020b57cec5SDimitry Andric   __kmp_save_internal_controls(thread);
29030b57cec5SDimitry Andric 
29040b57cec5SDimitry Andric   set__max_active_levels(thread, max_active_levels);
29050b57cec5SDimitry Andric }
29060b57cec5SDimitry Andric 
29070b57cec5SDimitry Andric /* Gets max_active_levels */
__kmp_get_max_active_levels(int gtid)29080b57cec5SDimitry Andric int __kmp_get_max_active_levels(int gtid) {
29090b57cec5SDimitry Andric   kmp_info_t *thread;
29100b57cec5SDimitry Andric 
29110b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_get_max_active_levels: thread %d\n", gtid));
29120b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_init_serial);
29130b57cec5SDimitry Andric 
29140b57cec5SDimitry Andric   thread = __kmp_threads[gtid];
29150b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(thread->th.th_current_task);
29160b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_get_max_active_levels: thread %d, curtask=%p, "
29170b57cec5SDimitry Andric                 "curtask_maxaclevel=%d\n",
29180b57cec5SDimitry Andric                 gtid, thread->th.th_current_task,
29190b57cec5SDimitry Andric                 thread->th.th_current_task->td_icvs.max_active_levels));
29200b57cec5SDimitry Andric   return thread->th.th_current_task->td_icvs.max_active_levels;
29210b57cec5SDimitry Andric }
29220b57cec5SDimitry Andric 
2923fe6060f1SDimitry Andric // nteams-var per-device ICV
__kmp_set_num_teams(int num_teams)2924fe6060f1SDimitry Andric void __kmp_set_num_teams(int num_teams) {
2925fe6060f1SDimitry Andric   if (num_teams > 0)
2926fe6060f1SDimitry Andric     __kmp_nteams = num_teams;
2927fe6060f1SDimitry Andric }
__kmp_get_max_teams(void)2928fe6060f1SDimitry Andric int __kmp_get_max_teams(void) { return __kmp_nteams; }
2929fe6060f1SDimitry Andric // teams-thread-limit-var per-device ICV
__kmp_set_teams_thread_limit(int limit)2930fe6060f1SDimitry Andric void __kmp_set_teams_thread_limit(int limit) {
2931fe6060f1SDimitry Andric   if (limit > 0)
2932fe6060f1SDimitry Andric     __kmp_teams_thread_limit = limit;
2933fe6060f1SDimitry Andric }
__kmp_get_teams_thread_limit(void)2934fe6060f1SDimitry Andric int __kmp_get_teams_thread_limit(void) { return __kmp_teams_thread_limit; }
2935fe6060f1SDimitry Andric 
29360b57cec5SDimitry Andric KMP_BUILD_ASSERT(sizeof(kmp_sched_t) == sizeof(int));
29370b57cec5SDimitry Andric KMP_BUILD_ASSERT(sizeof(enum sched_type) == sizeof(int));
29380b57cec5SDimitry Andric 
29390b57cec5SDimitry Andric /* Changes def_sched_var ICV values (run-time schedule kind and chunk) */
__kmp_set_schedule(int gtid,kmp_sched_t kind,int chunk)29400b57cec5SDimitry Andric void __kmp_set_schedule(int gtid, kmp_sched_t kind, int chunk) {
29410b57cec5SDimitry Andric   kmp_info_t *thread;
29420b57cec5SDimitry Andric   kmp_sched_t orig_kind;
29430b57cec5SDimitry Andric   //    kmp_team_t *team;
29440b57cec5SDimitry Andric 
29450b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_set_schedule: new schedule for thread %d = (%d, %d)\n",
29460b57cec5SDimitry Andric                 gtid, (int)kind, chunk));
29470b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_init_serial);
29480b57cec5SDimitry Andric 
29490b57cec5SDimitry Andric   // Check if the kind parameter is valid, correct if needed.
29500b57cec5SDimitry Andric   // Valid parameters should fit in one of two intervals - standard or extended:
29510b57cec5SDimitry Andric   //       <lower>, <valid>, <upper_std>, <lower_ext>, <valid>, <upper>
29520b57cec5SDimitry Andric   // 2008-01-25: 0,  1 - 4,       5,         100,     101 - 102, 103
29530b57cec5SDimitry Andric   orig_kind = kind;
29540b57cec5SDimitry Andric   kind = __kmp_sched_without_mods(kind);
29550b57cec5SDimitry Andric 
29560b57cec5SDimitry Andric   if (kind <= kmp_sched_lower || kind >= kmp_sched_upper ||
29570b57cec5SDimitry Andric       (kind <= kmp_sched_lower_ext && kind >= kmp_sched_upper_std)) {
29580b57cec5SDimitry Andric     // TODO: Hint needs attention in case we change the default schedule.
29590b57cec5SDimitry Andric     __kmp_msg(kmp_ms_warning, KMP_MSG(ScheduleKindOutOfRange, kind),
29600b57cec5SDimitry Andric               KMP_HNT(DefaultScheduleKindUsed, "static, no chunk"),
29610b57cec5SDimitry Andric               __kmp_msg_null);
29620b57cec5SDimitry Andric     kind = kmp_sched_default;
29630b57cec5SDimitry Andric     chunk = 0; // ignore chunk value in case of bad kind
29640b57cec5SDimitry Andric   }
29650b57cec5SDimitry Andric 
29660b57cec5SDimitry Andric   thread = __kmp_threads[gtid];
29670b57cec5SDimitry Andric 
29680b57cec5SDimitry Andric   __kmp_save_internal_controls(thread);
29690b57cec5SDimitry Andric 
29700b57cec5SDimitry Andric   if (kind < kmp_sched_upper_std) {
29710b57cec5SDimitry Andric     if (kind == kmp_sched_static && chunk < KMP_DEFAULT_CHUNK) {
29720b57cec5SDimitry Andric       // differ static chunked vs. unchunked:  chunk should be invalid to
29730b57cec5SDimitry Andric       // indicate unchunked schedule (which is the default)
29740b57cec5SDimitry Andric       thread->th.th_current_task->td_icvs.sched.r_sched_type = kmp_sch_static;
29750b57cec5SDimitry Andric     } else {
29760b57cec5SDimitry Andric       thread->th.th_current_task->td_icvs.sched.r_sched_type =
29770b57cec5SDimitry Andric           __kmp_sch_map[kind - kmp_sched_lower - 1];
29780b57cec5SDimitry Andric     }
29790b57cec5SDimitry Andric   } else {
29800b57cec5SDimitry Andric     //    __kmp_sch_map[ kind - kmp_sched_lower_ext + kmp_sched_upper_std -
29810b57cec5SDimitry Andric     //    kmp_sched_lower - 2 ];
29820b57cec5SDimitry Andric     thread->th.th_current_task->td_icvs.sched.r_sched_type =
29830b57cec5SDimitry Andric         __kmp_sch_map[kind - kmp_sched_lower_ext + kmp_sched_upper_std -
29840b57cec5SDimitry Andric                       kmp_sched_lower - 2];
29850b57cec5SDimitry Andric   }
29860b57cec5SDimitry Andric   __kmp_sched_apply_mods_intkind(
29870b57cec5SDimitry Andric       orig_kind, &(thread->th.th_current_task->td_icvs.sched.r_sched_type));
29880b57cec5SDimitry Andric   if (kind == kmp_sched_auto || chunk < 1) {
29890b57cec5SDimitry Andric     // ignore parameter chunk for schedule auto
29900b57cec5SDimitry Andric     thread->th.th_current_task->td_icvs.sched.chunk = KMP_DEFAULT_CHUNK;
29910b57cec5SDimitry Andric   } else {
29920b57cec5SDimitry Andric     thread->th.th_current_task->td_icvs.sched.chunk = chunk;
29930b57cec5SDimitry Andric   }
29940b57cec5SDimitry Andric }
29950b57cec5SDimitry Andric 
29960b57cec5SDimitry Andric /* Gets def_sched_var ICV values */
__kmp_get_schedule(int gtid,kmp_sched_t * kind,int * chunk)29970b57cec5SDimitry Andric void __kmp_get_schedule(int gtid, kmp_sched_t *kind, int *chunk) {
29980b57cec5SDimitry Andric   kmp_info_t *thread;
29990b57cec5SDimitry Andric   enum sched_type th_type;
30000b57cec5SDimitry Andric 
30010b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_get_schedule: thread %d\n", gtid));
30020b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_init_serial);
30030b57cec5SDimitry Andric 
30040b57cec5SDimitry Andric   thread = __kmp_threads[gtid];
30050b57cec5SDimitry Andric 
30060b57cec5SDimitry Andric   th_type = thread->th.th_current_task->td_icvs.sched.r_sched_type;
30070b57cec5SDimitry Andric   switch (SCHEDULE_WITHOUT_MODIFIERS(th_type)) {
30080b57cec5SDimitry Andric   case kmp_sch_static:
30090b57cec5SDimitry Andric   case kmp_sch_static_greedy:
30100b57cec5SDimitry Andric   case kmp_sch_static_balanced:
30110b57cec5SDimitry Andric     *kind = kmp_sched_static;
30120b57cec5SDimitry Andric     __kmp_sched_apply_mods_stdkind(kind, th_type);
30130b57cec5SDimitry Andric     *chunk = 0; // chunk was not set, try to show this fact via zero value
30140b57cec5SDimitry Andric     return;
30150b57cec5SDimitry Andric   case kmp_sch_static_chunked:
30160b57cec5SDimitry Andric     *kind = kmp_sched_static;
30170b57cec5SDimitry Andric     break;
30180b57cec5SDimitry Andric   case kmp_sch_dynamic_chunked:
30190b57cec5SDimitry Andric     *kind = kmp_sched_dynamic;
30200b57cec5SDimitry Andric     break;
30210b57cec5SDimitry Andric   case kmp_sch_guided_chunked:
30220b57cec5SDimitry Andric   case kmp_sch_guided_iterative_chunked:
30230b57cec5SDimitry Andric   case kmp_sch_guided_analytical_chunked:
30240b57cec5SDimitry Andric     *kind = kmp_sched_guided;
30250b57cec5SDimitry Andric     break;
30260b57cec5SDimitry Andric   case kmp_sch_auto:
30270b57cec5SDimitry Andric     *kind = kmp_sched_auto;
30280b57cec5SDimitry Andric     break;
30290b57cec5SDimitry Andric   case kmp_sch_trapezoidal:
30300b57cec5SDimitry Andric     *kind = kmp_sched_trapezoidal;
30310b57cec5SDimitry Andric     break;
30320b57cec5SDimitry Andric #if KMP_STATIC_STEAL_ENABLED
30330b57cec5SDimitry Andric   case kmp_sch_static_steal:
30340b57cec5SDimitry Andric     *kind = kmp_sched_static_steal;
30350b57cec5SDimitry Andric     break;
30360b57cec5SDimitry Andric #endif
30370b57cec5SDimitry Andric   default:
30380b57cec5SDimitry Andric     KMP_FATAL(UnknownSchedulingType, th_type);
30390b57cec5SDimitry Andric   }
30400b57cec5SDimitry Andric 
30410b57cec5SDimitry Andric   __kmp_sched_apply_mods_stdkind(kind, th_type);
30420b57cec5SDimitry Andric   *chunk = thread->th.th_current_task->td_icvs.sched.chunk;
30430b57cec5SDimitry Andric }
30440b57cec5SDimitry Andric 
__kmp_get_ancestor_thread_num(int gtid,int level)30450b57cec5SDimitry Andric int __kmp_get_ancestor_thread_num(int gtid, int level) {
30460b57cec5SDimitry Andric 
30470b57cec5SDimitry Andric   int ii, dd;
30480b57cec5SDimitry Andric   kmp_team_t *team;
30490b57cec5SDimitry Andric   kmp_info_t *thr;
30500b57cec5SDimitry Andric 
30510b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_get_ancestor_thread_num: thread %d %d\n", gtid, level));
30520b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_init_serial);
30530b57cec5SDimitry Andric 
30540b57cec5SDimitry Andric   // validate level
30550b57cec5SDimitry Andric   if (level == 0)
30560b57cec5SDimitry Andric     return 0;
30570b57cec5SDimitry Andric   if (level < 0)
30580b57cec5SDimitry Andric     return -1;
30590b57cec5SDimitry Andric   thr = __kmp_threads[gtid];
30600b57cec5SDimitry Andric   team = thr->th.th_team;
30610b57cec5SDimitry Andric   ii = team->t.t_level;
30620b57cec5SDimitry Andric   if (level > ii)
30630b57cec5SDimitry Andric     return -1;
30640b57cec5SDimitry Andric 
30650b57cec5SDimitry Andric   if (thr->th.th_teams_microtask) {
30660b57cec5SDimitry Andric     // AC: we are in teams region where multiple nested teams have same level
30670b57cec5SDimitry Andric     int tlevel = thr->th.th_teams_level; // the level of the teams construct
30680b57cec5SDimitry Andric     if (level <=
30690b57cec5SDimitry Andric         tlevel) { // otherwise usual algorithm works (will not touch the teams)
30700b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(ii >= tlevel);
30710b57cec5SDimitry Andric       // AC: As we need to pass by the teams league, we need to artificially
30720b57cec5SDimitry Andric       // increase ii
30730b57cec5SDimitry Andric       if (ii == tlevel) {
30740b57cec5SDimitry Andric         ii += 2; // three teams have same level
30750b57cec5SDimitry Andric       } else {
30760b57cec5SDimitry Andric         ii++; // two teams have same level
30770b57cec5SDimitry Andric       }
30780b57cec5SDimitry Andric     }
30790b57cec5SDimitry Andric   }
30800b57cec5SDimitry Andric 
30810b57cec5SDimitry Andric   if (ii == level)
30820b57cec5SDimitry Andric     return __kmp_tid_from_gtid(gtid);
30830b57cec5SDimitry Andric 
30840b57cec5SDimitry Andric   dd = team->t.t_serialized;
30850b57cec5SDimitry Andric   level++;
30860b57cec5SDimitry Andric   while (ii > level) {
30870b57cec5SDimitry Andric     for (dd = team->t.t_serialized; (dd > 0) && (ii > level); dd--, ii--) {
30880b57cec5SDimitry Andric     }
30890b57cec5SDimitry Andric     if ((team->t.t_serialized) && (!dd)) {
30900b57cec5SDimitry Andric       team = team->t.t_parent;
30910b57cec5SDimitry Andric       continue;
30920b57cec5SDimitry Andric     }
30930b57cec5SDimitry Andric     if (ii > level) {
30940b57cec5SDimitry Andric       team = team->t.t_parent;
30950b57cec5SDimitry Andric       dd = team->t.t_serialized;
30960b57cec5SDimitry Andric       ii--;
30970b57cec5SDimitry Andric     }
30980b57cec5SDimitry Andric   }
30990b57cec5SDimitry Andric 
31000b57cec5SDimitry Andric   return (dd > 1) ? (0) : (team->t.t_master_tid);
31010b57cec5SDimitry Andric }
31020b57cec5SDimitry Andric 
__kmp_get_team_size(int gtid,int level)31030b57cec5SDimitry Andric int __kmp_get_team_size(int gtid, int level) {
31040b57cec5SDimitry Andric 
31050b57cec5SDimitry Andric   int ii, dd;
31060b57cec5SDimitry Andric   kmp_team_t *team;
31070b57cec5SDimitry Andric   kmp_info_t *thr;
31080b57cec5SDimitry Andric 
31090b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_get_team_size: thread %d %d\n", gtid, level));
31100b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_init_serial);
31110b57cec5SDimitry Andric 
31120b57cec5SDimitry Andric   // validate level
31130b57cec5SDimitry Andric   if (level == 0)
31140b57cec5SDimitry Andric     return 1;
31150b57cec5SDimitry Andric   if (level < 0)
31160b57cec5SDimitry Andric     return -1;
31170b57cec5SDimitry Andric   thr = __kmp_threads[gtid];
31180b57cec5SDimitry Andric   team = thr->th.th_team;
31190b57cec5SDimitry Andric   ii = team->t.t_level;
31200b57cec5SDimitry Andric   if (level > ii)
31210b57cec5SDimitry Andric     return -1;
31220b57cec5SDimitry Andric 
31230b57cec5SDimitry Andric   if (thr->th.th_teams_microtask) {
31240b57cec5SDimitry Andric     // AC: we are in teams region where multiple nested teams have same level
31250b57cec5SDimitry Andric     int tlevel = thr->th.th_teams_level; // the level of the teams construct
31260b57cec5SDimitry Andric     if (level <=
31270b57cec5SDimitry Andric         tlevel) { // otherwise usual algorithm works (will not touch the teams)
31280b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(ii >= tlevel);
31290b57cec5SDimitry Andric       // AC: As we need to pass by the teams league, we need to artificially
31300b57cec5SDimitry Andric       // increase ii
31310b57cec5SDimitry Andric       if (ii == tlevel) {
31320b57cec5SDimitry Andric         ii += 2; // three teams have same level
31330b57cec5SDimitry Andric       } else {
31340b57cec5SDimitry Andric         ii++; // two teams have same level
31350b57cec5SDimitry Andric       }
31360b57cec5SDimitry Andric     }
31370b57cec5SDimitry Andric   }
31380b57cec5SDimitry Andric 
31390b57cec5SDimitry Andric   while (ii > level) {
31400b57cec5SDimitry Andric     for (dd = team->t.t_serialized; (dd > 0) && (ii > level); dd--, ii--) {
31410b57cec5SDimitry Andric     }
31420b57cec5SDimitry Andric     if (team->t.t_serialized && (!dd)) {
31430b57cec5SDimitry Andric       team = team->t.t_parent;
31440b57cec5SDimitry Andric       continue;
31450b57cec5SDimitry Andric     }
31460b57cec5SDimitry Andric     if (ii > level) {
31470b57cec5SDimitry Andric       team = team->t.t_parent;
31480b57cec5SDimitry Andric       ii--;
31490b57cec5SDimitry Andric     }
31500b57cec5SDimitry Andric   }
31510b57cec5SDimitry Andric 
31520b57cec5SDimitry Andric   return team->t.t_nproc;
31530b57cec5SDimitry Andric }
31540b57cec5SDimitry Andric 
__kmp_get_schedule_global()31550b57cec5SDimitry Andric kmp_r_sched_t __kmp_get_schedule_global() {
31560b57cec5SDimitry Andric   // This routine created because pairs (__kmp_sched, __kmp_chunk) and
31570b57cec5SDimitry Andric   // (__kmp_static, __kmp_guided) may be changed by kmp_set_defaults
31580b57cec5SDimitry Andric   // independently. So one can get the updated schedule here.
31590b57cec5SDimitry Andric 
31600b57cec5SDimitry Andric   kmp_r_sched_t r_sched;
31610b57cec5SDimitry Andric 
31620b57cec5SDimitry Andric   // create schedule from 4 globals: __kmp_sched, __kmp_chunk, __kmp_static,
31630b57cec5SDimitry Andric   // __kmp_guided. __kmp_sched should keep original value, so that user can set
31640b57cec5SDimitry Andric   // KMP_SCHEDULE multiple times, and thus have different run-time schedules in
31650b57cec5SDimitry Andric   // different roots (even in OMP 2.5)
31660b57cec5SDimitry Andric   enum sched_type s = SCHEDULE_WITHOUT_MODIFIERS(__kmp_sched);
31670b57cec5SDimitry Andric   enum sched_type sched_modifiers = SCHEDULE_GET_MODIFIERS(__kmp_sched);
31680b57cec5SDimitry Andric   if (s == kmp_sch_static) {
31690b57cec5SDimitry Andric     // replace STATIC with more detailed schedule (balanced or greedy)
31700b57cec5SDimitry Andric     r_sched.r_sched_type = __kmp_static;
31710b57cec5SDimitry Andric   } else if (s == kmp_sch_guided_chunked) {
31720b57cec5SDimitry Andric     // replace GUIDED with more detailed schedule (iterative or analytical)
31730b57cec5SDimitry Andric     r_sched.r_sched_type = __kmp_guided;
31740b57cec5SDimitry Andric   } else { // (STATIC_CHUNKED), or (DYNAMIC_CHUNKED), or other
31750b57cec5SDimitry Andric     r_sched.r_sched_type = __kmp_sched;
31760b57cec5SDimitry Andric   }
31770b57cec5SDimitry Andric   SCHEDULE_SET_MODIFIERS(r_sched.r_sched_type, sched_modifiers);
31780b57cec5SDimitry Andric 
31790b57cec5SDimitry Andric   if (__kmp_chunk < KMP_DEFAULT_CHUNK) {
31800b57cec5SDimitry Andric     // __kmp_chunk may be wrong here (if it was not ever set)
31810b57cec5SDimitry Andric     r_sched.chunk = KMP_DEFAULT_CHUNK;
31820b57cec5SDimitry Andric   } else {
31830b57cec5SDimitry Andric     r_sched.chunk = __kmp_chunk;
31840b57cec5SDimitry Andric   }
31850b57cec5SDimitry Andric 
31860b57cec5SDimitry Andric   return r_sched;
31870b57cec5SDimitry Andric }
31880b57cec5SDimitry Andric 
31890b57cec5SDimitry Andric /* Allocate (realloc == FALSE) * or reallocate (realloc == TRUE)
31900b57cec5SDimitry Andric    at least argc number of *t_argv entries for the requested team. */
__kmp_alloc_argv_entries(int argc,kmp_team_t * team,int realloc)31910b57cec5SDimitry Andric static void __kmp_alloc_argv_entries(int argc, kmp_team_t *team, int realloc) {
31920b57cec5SDimitry Andric 
31930b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team);
31940b57cec5SDimitry Andric   if (!realloc || argc > team->t.t_max_argc) {
31950b57cec5SDimitry Andric 
31960b57cec5SDimitry Andric     KA_TRACE(100, ("__kmp_alloc_argv_entries: team %d: needed entries=%d, "
31970b57cec5SDimitry Andric                    "current entries=%d\n",
31980b57cec5SDimitry Andric                    team->t.t_id, argc, (realloc) ? team->t.t_max_argc : 0));
31990b57cec5SDimitry Andric     /* if previously allocated heap space for args, free them */
32000b57cec5SDimitry Andric     if (realloc && team->t.t_argv != &team->t.t_inline_argv[0])
32010b57cec5SDimitry Andric       __kmp_free((void *)team->t.t_argv);
32020b57cec5SDimitry Andric 
32030b57cec5SDimitry Andric     if (argc <= KMP_INLINE_ARGV_ENTRIES) {
32040b57cec5SDimitry Andric       /* use unused space in the cache line for arguments */
32050b57cec5SDimitry Andric       team->t.t_max_argc = KMP_INLINE_ARGV_ENTRIES;
32060b57cec5SDimitry Andric       KA_TRACE(100, ("__kmp_alloc_argv_entries: team %d: inline allocate %d "
32070b57cec5SDimitry Andric                      "argv entries\n",
32080b57cec5SDimitry Andric                      team->t.t_id, team->t.t_max_argc));
32090b57cec5SDimitry Andric       team->t.t_argv = &team->t.t_inline_argv[0];
32100b57cec5SDimitry Andric       if (__kmp_storage_map) {
32110b57cec5SDimitry Andric         __kmp_print_storage_map_gtid(
32120b57cec5SDimitry Andric             -1, &team->t.t_inline_argv[0],
32130b57cec5SDimitry Andric             &team->t.t_inline_argv[KMP_INLINE_ARGV_ENTRIES],
32140b57cec5SDimitry Andric             (sizeof(void *) * KMP_INLINE_ARGV_ENTRIES), "team_%d.t_inline_argv",
32150b57cec5SDimitry Andric             team->t.t_id);
32160b57cec5SDimitry Andric       }
32170b57cec5SDimitry Andric     } else {
32180b57cec5SDimitry Andric       /* allocate space for arguments in the heap */
32190b57cec5SDimitry Andric       team->t.t_max_argc = (argc <= (KMP_MIN_MALLOC_ARGV_ENTRIES >> 1))
32200b57cec5SDimitry Andric                                ? KMP_MIN_MALLOC_ARGV_ENTRIES
32210b57cec5SDimitry Andric                                : 2 * argc;
32220b57cec5SDimitry Andric       KA_TRACE(100, ("__kmp_alloc_argv_entries: team %d: dynamic allocate %d "
32230b57cec5SDimitry Andric                      "argv entries\n",
32240b57cec5SDimitry Andric                      team->t.t_id, team->t.t_max_argc));
32250b57cec5SDimitry Andric       team->t.t_argv =
32260b57cec5SDimitry Andric           (void **)__kmp_page_allocate(sizeof(void *) * team->t.t_max_argc);
32270b57cec5SDimitry Andric       if (__kmp_storage_map) {
32280b57cec5SDimitry Andric         __kmp_print_storage_map_gtid(-1, &team->t.t_argv[0],
32290b57cec5SDimitry Andric                                      &team->t.t_argv[team->t.t_max_argc],
32300b57cec5SDimitry Andric                                      sizeof(void *) * team->t.t_max_argc,
32310b57cec5SDimitry Andric                                      "team_%d.t_argv", team->t.t_id);
32320b57cec5SDimitry Andric       }
32330b57cec5SDimitry Andric     }
32340b57cec5SDimitry Andric   }
32350b57cec5SDimitry Andric }
32360b57cec5SDimitry Andric 
__kmp_allocate_team_arrays(kmp_team_t * team,int max_nth)32370b57cec5SDimitry Andric static void __kmp_allocate_team_arrays(kmp_team_t *team, int max_nth) {
32380b57cec5SDimitry Andric   int i;
32390b57cec5SDimitry Andric   int num_disp_buff = max_nth > 1 ? __kmp_dispatch_num_buffers : 2;
32400b57cec5SDimitry Andric   team->t.t_threads =
32410b57cec5SDimitry Andric       (kmp_info_t **)__kmp_allocate(sizeof(kmp_info_t *) * max_nth);
32420b57cec5SDimitry Andric   team->t.t_disp_buffer = (dispatch_shared_info_t *)__kmp_allocate(
32430b57cec5SDimitry Andric       sizeof(dispatch_shared_info_t) * num_disp_buff);
32440b57cec5SDimitry Andric   team->t.t_dispatch =
32450b57cec5SDimitry Andric       (kmp_disp_t *)__kmp_allocate(sizeof(kmp_disp_t) * max_nth);
32460b57cec5SDimitry Andric   team->t.t_implicit_task_taskdata =
32470b57cec5SDimitry Andric       (kmp_taskdata_t *)__kmp_allocate(sizeof(kmp_taskdata_t) * max_nth);
32480b57cec5SDimitry Andric   team->t.t_max_nproc = max_nth;
32490b57cec5SDimitry Andric 
32500b57cec5SDimitry Andric   /* setup dispatch buffers */
32510b57cec5SDimitry Andric   for (i = 0; i < num_disp_buff; ++i) {
32520b57cec5SDimitry Andric     team->t.t_disp_buffer[i].buffer_index = i;
32530b57cec5SDimitry Andric     team->t.t_disp_buffer[i].doacross_buf_idx = i;
32540b57cec5SDimitry Andric   }
32550b57cec5SDimitry Andric }
32560b57cec5SDimitry Andric 
__kmp_free_team_arrays(kmp_team_t * team)32570b57cec5SDimitry Andric static void __kmp_free_team_arrays(kmp_team_t *team) {
32580b57cec5SDimitry Andric   /* Note: this does not free the threads in t_threads (__kmp_free_threads) */
32590b57cec5SDimitry Andric   int i;
32600b57cec5SDimitry Andric   for (i = 0; i < team->t.t_max_nproc; ++i) {
32610b57cec5SDimitry Andric     if (team->t.t_dispatch[i].th_disp_buffer != NULL) {
32620b57cec5SDimitry Andric       __kmp_free(team->t.t_dispatch[i].th_disp_buffer);
32630b57cec5SDimitry Andric       team->t.t_dispatch[i].th_disp_buffer = NULL;
32640b57cec5SDimitry Andric     }
32650b57cec5SDimitry Andric   }
32660b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED
32670b57cec5SDimitry Andric   __kmp_dispatch_free_hierarchies(team);
32680b57cec5SDimitry Andric #endif
32690b57cec5SDimitry Andric   __kmp_free(team->t.t_threads);
32700b57cec5SDimitry Andric   __kmp_free(team->t.t_disp_buffer);
32710b57cec5SDimitry Andric   __kmp_free(team->t.t_dispatch);
32720b57cec5SDimitry Andric   __kmp_free(team->t.t_implicit_task_taskdata);
32730b57cec5SDimitry Andric   team->t.t_threads = NULL;
32740b57cec5SDimitry Andric   team->t.t_disp_buffer = NULL;
32750b57cec5SDimitry Andric   team->t.t_dispatch = NULL;
32760b57cec5SDimitry Andric   team->t.t_implicit_task_taskdata = 0;
32770b57cec5SDimitry Andric }
32780b57cec5SDimitry Andric 
__kmp_reallocate_team_arrays(kmp_team_t * team,int max_nth)32790b57cec5SDimitry Andric static void __kmp_reallocate_team_arrays(kmp_team_t *team, int max_nth) {
32800b57cec5SDimitry Andric   kmp_info_t **oldThreads = team->t.t_threads;
32810b57cec5SDimitry Andric 
32820b57cec5SDimitry Andric   __kmp_free(team->t.t_disp_buffer);
32830b57cec5SDimitry Andric   __kmp_free(team->t.t_dispatch);
32840b57cec5SDimitry Andric   __kmp_free(team->t.t_implicit_task_taskdata);
32850b57cec5SDimitry Andric   __kmp_allocate_team_arrays(team, max_nth);
32860b57cec5SDimitry Andric 
32870b57cec5SDimitry Andric   KMP_MEMCPY(team->t.t_threads, oldThreads,
32880b57cec5SDimitry Andric              team->t.t_nproc * sizeof(kmp_info_t *));
32890b57cec5SDimitry Andric 
32900b57cec5SDimitry Andric   __kmp_free(oldThreads);
32910b57cec5SDimitry Andric }
32920b57cec5SDimitry Andric 
__kmp_get_global_icvs(void)32930b57cec5SDimitry Andric static kmp_internal_control_t __kmp_get_global_icvs(void) {
32940b57cec5SDimitry Andric 
32950b57cec5SDimitry Andric   kmp_r_sched_t r_sched =
32960b57cec5SDimitry Andric       __kmp_get_schedule_global(); // get current state of scheduling globals
32970b57cec5SDimitry Andric 
32980b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_nested_proc_bind.used > 0);
32990b57cec5SDimitry Andric 
33000b57cec5SDimitry Andric   kmp_internal_control_t g_icvs = {
33010b57cec5SDimitry Andric     0, // int serial_nesting_level; //corresponds to value of th_team_serialized
33020b57cec5SDimitry Andric     (kmp_int8)__kmp_global.g.g_dynamic, // internal control for dynamic
33030b57cec5SDimitry Andric     // adjustment of threads (per thread)
33040b57cec5SDimitry Andric     (kmp_int8)__kmp_env_blocktime, // int bt_set; //internal control for
33050b57cec5SDimitry Andric     // whether blocktime is explicitly set
33060b57cec5SDimitry Andric     __kmp_dflt_blocktime, // int blocktime; //internal control for blocktime
33070b57cec5SDimitry Andric #if KMP_USE_MONITOR
33080b57cec5SDimitry Andric     __kmp_bt_intervals, // int bt_intervals; //internal control for blocktime
33090b57cec5SDimitry Andric // intervals
33100b57cec5SDimitry Andric #endif
33110b57cec5SDimitry Andric     __kmp_dflt_team_nth, // int nproc; //internal control for # of threads for
33120b57cec5SDimitry Andric     // next parallel region (per thread)
33130b57cec5SDimitry Andric     // (use a max ub on value if __kmp_parallel_initialize not called yet)
33140b57cec5SDimitry Andric     __kmp_cg_max_nth, // int thread_limit;
33155f757f3fSDimitry Andric     __kmp_task_max_nth, // int task_thread_limit; // to set the thread_limit
33165f757f3fSDimitry Andric     // on task. This is used in the case of target thread_limit
33170b57cec5SDimitry Andric     __kmp_dflt_max_active_levels, // int max_active_levels; //internal control
33180b57cec5SDimitry Andric     // for max_active_levels
33190b57cec5SDimitry Andric     r_sched, // kmp_r_sched_t sched; //internal control for runtime schedule
33200b57cec5SDimitry Andric     // {sched,chunk} pair
33210b57cec5SDimitry Andric     __kmp_nested_proc_bind.bind_types[0],
33220b57cec5SDimitry Andric     __kmp_default_device,
33230b57cec5SDimitry Andric     NULL // struct kmp_internal_control *next;
33240b57cec5SDimitry Andric   };
33250b57cec5SDimitry Andric 
33260b57cec5SDimitry Andric   return g_icvs;
33270b57cec5SDimitry Andric }
33280b57cec5SDimitry Andric 
__kmp_get_x_global_icvs(const kmp_team_t * team)33290b57cec5SDimitry Andric static kmp_internal_control_t __kmp_get_x_global_icvs(const kmp_team_t *team) {
33300b57cec5SDimitry Andric 
33310b57cec5SDimitry Andric   kmp_internal_control_t gx_icvs;
33320b57cec5SDimitry Andric   gx_icvs.serial_nesting_level =
33330b57cec5SDimitry Andric       0; // probably =team->t.t_serial like in save_inter_controls
33340b57cec5SDimitry Andric   copy_icvs(&gx_icvs, &team->t.t_threads[0]->th.th_current_task->td_icvs);
33350b57cec5SDimitry Andric   gx_icvs.next = NULL;
33360b57cec5SDimitry Andric 
33370b57cec5SDimitry Andric   return gx_icvs;
33380b57cec5SDimitry Andric }
33390b57cec5SDimitry Andric 
__kmp_initialize_root(kmp_root_t * root)33400b57cec5SDimitry Andric static void __kmp_initialize_root(kmp_root_t *root) {
33410b57cec5SDimitry Andric   int f;
33420b57cec5SDimitry Andric   kmp_team_t *root_team;
33430b57cec5SDimitry Andric   kmp_team_t *hot_team;
33440b57cec5SDimitry Andric   int hot_team_max_nth;
33450b57cec5SDimitry Andric   kmp_r_sched_t r_sched =
33460b57cec5SDimitry Andric       __kmp_get_schedule_global(); // get current state of scheduling globals
33470b57cec5SDimitry Andric   kmp_internal_control_t r_icvs = __kmp_get_global_icvs();
33480b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(root);
33490b57cec5SDimitry Andric   KMP_ASSERT(!root->r.r_begin);
33500b57cec5SDimitry Andric 
33510b57cec5SDimitry Andric   /* setup the root state structure */
33520b57cec5SDimitry Andric   __kmp_init_lock(&root->r.r_begin_lock);
33530b57cec5SDimitry Andric   root->r.r_begin = FALSE;
33540b57cec5SDimitry Andric   root->r.r_active = FALSE;
33550b57cec5SDimitry Andric   root->r.r_in_parallel = 0;
33560b57cec5SDimitry Andric   root->r.r_blocktime = __kmp_dflt_blocktime;
3357fe6060f1SDimitry Andric #if KMP_AFFINITY_SUPPORTED
3358fe6060f1SDimitry Andric   root->r.r_affinity_assigned = FALSE;
3359fe6060f1SDimitry Andric #endif
33600b57cec5SDimitry Andric 
33610b57cec5SDimitry Andric   /* setup the root team for this task */
33620b57cec5SDimitry Andric   /* allocate the root team structure */
33630b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_initialize_root: before root_team\n"));
33640b57cec5SDimitry Andric 
33650b57cec5SDimitry Andric   root_team =
33660b57cec5SDimitry Andric       __kmp_allocate_team(root,
33670b57cec5SDimitry Andric                           1, // new_nproc
33680b57cec5SDimitry Andric                           1, // max_nproc
33690b57cec5SDimitry Andric #if OMPT_SUPPORT
33700b57cec5SDimitry Andric                           ompt_data_none, // root parallel id
33710b57cec5SDimitry Andric #endif
33720b57cec5SDimitry Andric                           __kmp_nested_proc_bind.bind_types[0], &r_icvs,
33730b57cec5SDimitry Andric                           0 // argc
3374fe6060f1SDimitry Andric                           USE_NESTED_HOT_ARG(NULL) // primary thread is unknown
33750b57cec5SDimitry Andric       );
33760b57cec5SDimitry Andric #if USE_DEBUGGER
33770b57cec5SDimitry Andric   // Non-NULL value should be assigned to make the debugger display the root
33780b57cec5SDimitry Andric   // team.
33790b57cec5SDimitry Andric   TCW_SYNC_PTR(root_team->t.t_pkfn, (microtask_t)(~0));
33800b57cec5SDimitry Andric #endif
33810b57cec5SDimitry Andric 
33820b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_initialize_root: after root_team = %p\n", root_team));
33830b57cec5SDimitry Andric 
33840b57cec5SDimitry Andric   root->r.r_root_team = root_team;
33850b57cec5SDimitry Andric   root_team->t.t_control_stack_top = NULL;
33860b57cec5SDimitry Andric 
33870b57cec5SDimitry Andric   /* initialize root team */
33880b57cec5SDimitry Andric   root_team->t.t_threads[0] = NULL;
33890b57cec5SDimitry Andric   root_team->t.t_nproc = 1;
33900b57cec5SDimitry Andric   root_team->t.t_serialized = 1;
33910b57cec5SDimitry Andric   // TODO???: root_team->t.t_max_active_levels = __kmp_dflt_max_active_levels;
33920b57cec5SDimitry Andric   root_team->t.t_sched.sched = r_sched.sched;
33930b57cec5SDimitry Andric   KA_TRACE(
33940b57cec5SDimitry Andric       20,
33950b57cec5SDimitry Andric       ("__kmp_initialize_root: init root team %d arrived: join=%u, plain=%u\n",
33960b57cec5SDimitry Andric        root_team->t.t_id, KMP_INIT_BARRIER_STATE, KMP_INIT_BARRIER_STATE));
33970b57cec5SDimitry Andric 
33980b57cec5SDimitry Andric   /* setup the  hot team for this task */
33990b57cec5SDimitry Andric   /* allocate the hot team structure */
34000b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_initialize_root: before hot_team\n"));
34010b57cec5SDimitry Andric 
34020b57cec5SDimitry Andric   hot_team =
34030b57cec5SDimitry Andric       __kmp_allocate_team(root,
34040b57cec5SDimitry Andric                           1, // new_nproc
34050b57cec5SDimitry Andric                           __kmp_dflt_team_nth_ub * 2, // max_nproc
34060b57cec5SDimitry Andric #if OMPT_SUPPORT
34070b57cec5SDimitry Andric                           ompt_data_none, // root parallel id
34080b57cec5SDimitry Andric #endif
34090b57cec5SDimitry Andric                           __kmp_nested_proc_bind.bind_types[0], &r_icvs,
34100b57cec5SDimitry Andric                           0 // argc
3411fe6060f1SDimitry Andric                           USE_NESTED_HOT_ARG(NULL) // primary thread is unknown
34120b57cec5SDimitry Andric       );
34130b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_initialize_root: after hot_team = %p\n", hot_team));
34140b57cec5SDimitry Andric 
34150b57cec5SDimitry Andric   root->r.r_hot_team = hot_team;
34160b57cec5SDimitry Andric   root_team->t.t_control_stack_top = NULL;
34170b57cec5SDimitry Andric 
34180b57cec5SDimitry Andric   /* first-time initialization */
34190b57cec5SDimitry Andric   hot_team->t.t_parent = root_team;
34200b57cec5SDimitry Andric 
34210b57cec5SDimitry Andric   /* initialize hot team */
34220b57cec5SDimitry Andric   hot_team_max_nth = hot_team->t.t_max_nproc;
34230b57cec5SDimitry Andric   for (f = 0; f < hot_team_max_nth; ++f) {
34240b57cec5SDimitry Andric     hot_team->t.t_threads[f] = NULL;
34250b57cec5SDimitry Andric   }
34260b57cec5SDimitry Andric   hot_team->t.t_nproc = 1;
34270b57cec5SDimitry Andric   // TODO???: hot_team->t.t_max_active_levels = __kmp_dflt_max_active_levels;
34280b57cec5SDimitry Andric   hot_team->t.t_sched.sched = r_sched.sched;
34290b57cec5SDimitry Andric   hot_team->t.t_size_changed = 0;
34300b57cec5SDimitry Andric }
34310b57cec5SDimitry Andric 
34320b57cec5SDimitry Andric #ifdef KMP_DEBUG
34330b57cec5SDimitry Andric 
34340b57cec5SDimitry Andric typedef struct kmp_team_list_item {
34350b57cec5SDimitry Andric   kmp_team_p const *entry;
34360b57cec5SDimitry Andric   struct kmp_team_list_item *next;
34370b57cec5SDimitry Andric } kmp_team_list_item_t;
34380b57cec5SDimitry Andric typedef kmp_team_list_item_t *kmp_team_list_t;
34390b57cec5SDimitry Andric 
__kmp_print_structure_team_accum(kmp_team_list_t list,kmp_team_p const * team)34400b57cec5SDimitry Andric static void __kmp_print_structure_team_accum( // Add team to list of teams.
34410b57cec5SDimitry Andric     kmp_team_list_t list, // List of teams.
34420b57cec5SDimitry Andric     kmp_team_p const *team // Team to add.
34430b57cec5SDimitry Andric ) {
34440b57cec5SDimitry Andric 
34450b57cec5SDimitry Andric   // List must terminate with item where both entry and next are NULL.
34460b57cec5SDimitry Andric   // Team is added to the list only once.
34470b57cec5SDimitry Andric   // List is sorted in ascending order by team id.
34480b57cec5SDimitry Andric   // Team id is *not* a key.
34490b57cec5SDimitry Andric 
34500b57cec5SDimitry Andric   kmp_team_list_t l;
34510b57cec5SDimitry Andric 
34520b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(list != NULL);
34530b57cec5SDimitry Andric   if (team == NULL) {
34540b57cec5SDimitry Andric     return;
34550b57cec5SDimitry Andric   }
34560b57cec5SDimitry Andric 
34570b57cec5SDimitry Andric   __kmp_print_structure_team_accum(list, team->t.t_parent);
34580b57cec5SDimitry Andric   __kmp_print_structure_team_accum(list, team->t.t_next_pool);
34590b57cec5SDimitry Andric 
34600b57cec5SDimitry Andric   // Search list for the team.
34610b57cec5SDimitry Andric   l = list;
34620b57cec5SDimitry Andric   while (l->next != NULL && l->entry != team) {
34630b57cec5SDimitry Andric     l = l->next;
34640b57cec5SDimitry Andric   }
34650b57cec5SDimitry Andric   if (l->next != NULL) {
34660b57cec5SDimitry Andric     return; // Team has been added before, exit.
34670b57cec5SDimitry Andric   }
34680b57cec5SDimitry Andric 
34690b57cec5SDimitry Andric   // Team is not found. Search list again for insertion point.
34700b57cec5SDimitry Andric   l = list;
34710b57cec5SDimitry Andric   while (l->next != NULL && l->entry->t.t_id <= team->t.t_id) {
34720b57cec5SDimitry Andric     l = l->next;
34730b57cec5SDimitry Andric   }
34740b57cec5SDimitry Andric 
34750b57cec5SDimitry Andric   // Insert team.
34760b57cec5SDimitry Andric   {
34770b57cec5SDimitry Andric     kmp_team_list_item_t *item = (kmp_team_list_item_t *)KMP_INTERNAL_MALLOC(
34780b57cec5SDimitry Andric         sizeof(kmp_team_list_item_t));
34790b57cec5SDimitry Andric     *item = *l;
34800b57cec5SDimitry Andric     l->entry = team;
34810b57cec5SDimitry Andric     l->next = item;
34820b57cec5SDimitry Andric   }
34830b57cec5SDimitry Andric }
34840b57cec5SDimitry Andric 
__kmp_print_structure_team(char const * title,kmp_team_p const * team)34850b57cec5SDimitry Andric static void __kmp_print_structure_team(char const *title, kmp_team_p const *team
34860b57cec5SDimitry Andric 
34870b57cec5SDimitry Andric ) {
34880b57cec5SDimitry Andric   __kmp_printf("%s", title);
34890b57cec5SDimitry Andric   if (team != NULL) {
34900b57cec5SDimitry Andric     __kmp_printf("%2x %p\n", team->t.t_id, team);
34910b57cec5SDimitry Andric   } else {
34920b57cec5SDimitry Andric     __kmp_printf(" - (nil)\n");
34930b57cec5SDimitry Andric   }
34940b57cec5SDimitry Andric }
34950b57cec5SDimitry Andric 
__kmp_print_structure_thread(char const * title,kmp_info_p const * thread)34960b57cec5SDimitry Andric static void __kmp_print_structure_thread(char const *title,
34970b57cec5SDimitry Andric                                          kmp_info_p const *thread) {
34980b57cec5SDimitry Andric   __kmp_printf("%s", title);
34990b57cec5SDimitry Andric   if (thread != NULL) {
35000b57cec5SDimitry Andric     __kmp_printf("%2d %p\n", thread->th.th_info.ds.ds_gtid, thread);
35010b57cec5SDimitry Andric   } else {
35020b57cec5SDimitry Andric     __kmp_printf(" - (nil)\n");
35030b57cec5SDimitry Andric   }
35040b57cec5SDimitry Andric }
35050b57cec5SDimitry Andric 
__kmp_print_structure(void)35060b57cec5SDimitry Andric void __kmp_print_structure(void) {
35070b57cec5SDimitry Andric 
35080b57cec5SDimitry Andric   kmp_team_list_t list;
35090b57cec5SDimitry Andric 
35100b57cec5SDimitry Andric   // Initialize list of teams.
35110b57cec5SDimitry Andric   list =
35120b57cec5SDimitry Andric       (kmp_team_list_item_t *)KMP_INTERNAL_MALLOC(sizeof(kmp_team_list_item_t));
35130b57cec5SDimitry Andric   list->entry = NULL;
35140b57cec5SDimitry Andric   list->next = NULL;
35150b57cec5SDimitry Andric 
35160b57cec5SDimitry Andric   __kmp_printf("\n------------------------------\nGlobal Thread "
35170b57cec5SDimitry Andric                "Table\n------------------------------\n");
35180b57cec5SDimitry Andric   {
35190b57cec5SDimitry Andric     int gtid;
35200b57cec5SDimitry Andric     for (gtid = 0; gtid < __kmp_threads_capacity; ++gtid) {
35210b57cec5SDimitry Andric       __kmp_printf("%2d", gtid);
35220b57cec5SDimitry Andric       if (__kmp_threads != NULL) {
35230b57cec5SDimitry Andric         __kmp_printf(" %p", __kmp_threads[gtid]);
35240b57cec5SDimitry Andric       }
35250b57cec5SDimitry Andric       if (__kmp_root != NULL) {
35260b57cec5SDimitry Andric         __kmp_printf(" %p", __kmp_root[gtid]);
35270b57cec5SDimitry Andric       }
35280b57cec5SDimitry Andric       __kmp_printf("\n");
35290b57cec5SDimitry Andric     }
35300b57cec5SDimitry Andric   }
35310b57cec5SDimitry Andric 
35320b57cec5SDimitry Andric   // Print out __kmp_threads array.
35330b57cec5SDimitry Andric   __kmp_printf("\n------------------------------\nThreads\n--------------------"
35340b57cec5SDimitry Andric                "----------\n");
35350b57cec5SDimitry Andric   if (__kmp_threads != NULL) {
35360b57cec5SDimitry Andric     int gtid;
35370b57cec5SDimitry Andric     for (gtid = 0; gtid < __kmp_threads_capacity; ++gtid) {
35380b57cec5SDimitry Andric       kmp_info_t const *thread = __kmp_threads[gtid];
35390b57cec5SDimitry Andric       if (thread != NULL) {
35400b57cec5SDimitry Andric         __kmp_printf("GTID %2d %p:\n", gtid, thread);
35410b57cec5SDimitry Andric         __kmp_printf("    Our Root:        %p\n", thread->th.th_root);
35420b57cec5SDimitry Andric         __kmp_print_structure_team("    Our Team:     ", thread->th.th_team);
35430b57cec5SDimitry Andric         __kmp_print_structure_team("    Serial Team:  ",
35440b57cec5SDimitry Andric                                    thread->th.th_serial_team);
35450b57cec5SDimitry Andric         __kmp_printf("    Threads:      %2d\n", thread->th.th_team_nproc);
3546fe6060f1SDimitry Andric         __kmp_print_structure_thread("    Primary:      ",
35470b57cec5SDimitry Andric                                      thread->th.th_team_master);
35480b57cec5SDimitry Andric         __kmp_printf("    Serialized?:  %2d\n", thread->th.th_team_serialized);
35490b57cec5SDimitry Andric         __kmp_printf("    Set NProc:    %2d\n", thread->th.th_set_nproc);
35500b57cec5SDimitry Andric         __kmp_printf("    Set Proc Bind: %2d\n", thread->th.th_set_proc_bind);
35510b57cec5SDimitry Andric         __kmp_print_structure_thread("    Next in pool: ",
35520b57cec5SDimitry Andric                                      thread->th.th_next_pool);
35530b57cec5SDimitry Andric         __kmp_printf("\n");
35540b57cec5SDimitry Andric         __kmp_print_structure_team_accum(list, thread->th.th_team);
35550b57cec5SDimitry Andric         __kmp_print_structure_team_accum(list, thread->th.th_serial_team);
35560b57cec5SDimitry Andric       }
35570b57cec5SDimitry Andric     }
35580b57cec5SDimitry Andric   } else {
35590b57cec5SDimitry Andric     __kmp_printf("Threads array is not allocated.\n");
35600b57cec5SDimitry Andric   }
35610b57cec5SDimitry Andric 
35620b57cec5SDimitry Andric   // Print out __kmp_root array.
35630b57cec5SDimitry Andric   __kmp_printf("\n------------------------------\nUbers\n----------------------"
35640b57cec5SDimitry Andric                "--------\n");
35650b57cec5SDimitry Andric   if (__kmp_root != NULL) {
35660b57cec5SDimitry Andric     int gtid;
35670b57cec5SDimitry Andric     for (gtid = 0; gtid < __kmp_threads_capacity; ++gtid) {
35680b57cec5SDimitry Andric       kmp_root_t const *root = __kmp_root[gtid];
35690b57cec5SDimitry Andric       if (root != NULL) {
35700b57cec5SDimitry Andric         __kmp_printf("GTID %2d %p:\n", gtid, root);
35710b57cec5SDimitry Andric         __kmp_print_structure_team("    Root Team:    ", root->r.r_root_team);
35720b57cec5SDimitry Andric         __kmp_print_structure_team("    Hot Team:     ", root->r.r_hot_team);
35730b57cec5SDimitry Andric         __kmp_print_structure_thread("    Uber Thread:  ",
35740b57cec5SDimitry Andric                                      root->r.r_uber_thread);
35750b57cec5SDimitry Andric         __kmp_printf("    Active?:      %2d\n", root->r.r_active);
35760b57cec5SDimitry Andric         __kmp_printf("    In Parallel:  %2d\n",
35770b57cec5SDimitry Andric                      KMP_ATOMIC_LD_RLX(&root->r.r_in_parallel));
35780b57cec5SDimitry Andric         __kmp_printf("\n");
35790b57cec5SDimitry Andric         __kmp_print_structure_team_accum(list, root->r.r_root_team);
35800b57cec5SDimitry Andric         __kmp_print_structure_team_accum(list, root->r.r_hot_team);
35810b57cec5SDimitry Andric       }
35820b57cec5SDimitry Andric     }
35830b57cec5SDimitry Andric   } else {
35840b57cec5SDimitry Andric     __kmp_printf("Ubers array is not allocated.\n");
35850b57cec5SDimitry Andric   }
35860b57cec5SDimitry Andric 
35870b57cec5SDimitry Andric   __kmp_printf("\n------------------------------\nTeams\n----------------------"
35880b57cec5SDimitry Andric                "--------\n");
35890b57cec5SDimitry Andric   while (list->next != NULL) {
35900b57cec5SDimitry Andric     kmp_team_p const *team = list->entry;
35910b57cec5SDimitry Andric     int i;
35920b57cec5SDimitry Andric     __kmp_printf("Team %2x %p:\n", team->t.t_id, team);
35930b57cec5SDimitry Andric     __kmp_print_structure_team("    Parent Team:      ", team->t.t_parent);
3594fe6060f1SDimitry Andric     __kmp_printf("    Primary TID:      %2d\n", team->t.t_master_tid);
35950b57cec5SDimitry Andric     __kmp_printf("    Max threads:      %2d\n", team->t.t_max_nproc);
35960b57cec5SDimitry Andric     __kmp_printf("    Levels of serial: %2d\n", team->t.t_serialized);
35970b57cec5SDimitry Andric     __kmp_printf("    Number threads:   %2d\n", team->t.t_nproc);
35980b57cec5SDimitry Andric     for (i = 0; i < team->t.t_nproc; ++i) {
35990b57cec5SDimitry Andric       __kmp_printf("    Thread %2d:      ", i);
36000b57cec5SDimitry Andric       __kmp_print_structure_thread("", team->t.t_threads[i]);
36010b57cec5SDimitry Andric     }
36020b57cec5SDimitry Andric     __kmp_print_structure_team("    Next in pool:     ", team->t.t_next_pool);
36030b57cec5SDimitry Andric     __kmp_printf("\n");
36040b57cec5SDimitry Andric     list = list->next;
36050b57cec5SDimitry Andric   }
36060b57cec5SDimitry Andric 
36070b57cec5SDimitry Andric   // Print out __kmp_thread_pool and __kmp_team_pool.
36080b57cec5SDimitry Andric   __kmp_printf("\n------------------------------\nPools\n----------------------"
36090b57cec5SDimitry Andric                "--------\n");
36100b57cec5SDimitry Andric   __kmp_print_structure_thread("Thread pool:          ",
36110b57cec5SDimitry Andric                                CCAST(kmp_info_t *, __kmp_thread_pool));
36120b57cec5SDimitry Andric   __kmp_print_structure_team("Team pool:            ",
36130b57cec5SDimitry Andric                              CCAST(kmp_team_t *, __kmp_team_pool));
36140b57cec5SDimitry Andric   __kmp_printf("\n");
36150b57cec5SDimitry Andric 
36160b57cec5SDimitry Andric   // Free team list.
36170b57cec5SDimitry Andric   while (list != NULL) {
36180b57cec5SDimitry Andric     kmp_team_list_item_t *item = list;
36190b57cec5SDimitry Andric     list = list->next;
36200b57cec5SDimitry Andric     KMP_INTERNAL_FREE(item);
36210b57cec5SDimitry Andric   }
36220b57cec5SDimitry Andric }
36230b57cec5SDimitry Andric 
36240b57cec5SDimitry Andric #endif
36250b57cec5SDimitry Andric 
36260b57cec5SDimitry Andric //---------------------------------------------------------------------------
36270b57cec5SDimitry Andric //  Stuff for per-thread fast random number generator
36280b57cec5SDimitry Andric //  Table of primes
36290b57cec5SDimitry Andric static const unsigned __kmp_primes[] = {
36300b57cec5SDimitry Andric     0x9e3779b1, 0xffe6cc59, 0x2109f6dd, 0x43977ab5, 0xba5703f5, 0xb495a877,
36310b57cec5SDimitry Andric     0xe1626741, 0x79695e6b, 0xbc98c09f, 0xd5bee2b3, 0x287488f9, 0x3af18231,
36320b57cec5SDimitry Andric     0x9677cd4d, 0xbe3a6929, 0xadc6a877, 0xdcf0674b, 0xbe4d6fe9, 0x5f15e201,
36330b57cec5SDimitry Andric     0x99afc3fd, 0xf3f16801, 0xe222cfff, 0x24ba5fdb, 0x0620452d, 0x79f149e3,
36340b57cec5SDimitry Andric     0xc8b93f49, 0x972702cd, 0xb07dd827, 0x6c97d5ed, 0x085a3d61, 0x46eb5ea7,
36350b57cec5SDimitry Andric     0x3d9910ed, 0x2e687b5b, 0x29609227, 0x6eb081f1, 0x0954c4e1, 0x9d114db9,
36360b57cec5SDimitry Andric     0x542acfa9, 0xb3e6bd7b, 0x0742d917, 0xe9f3ffa7, 0x54581edb, 0xf2480f45,
36370b57cec5SDimitry Andric     0x0bb9288f, 0xef1affc7, 0x85fa0ca7, 0x3ccc14db, 0xe6baf34b, 0x343377f7,
36380b57cec5SDimitry Andric     0x5ca19031, 0xe6d9293b, 0xf0a9f391, 0x5d2e980b, 0xfc411073, 0xc3749363,
36390b57cec5SDimitry Andric     0xb892d829, 0x3549366b, 0x629750ad, 0xb98294e5, 0x892d9483, 0xc235baf3,
36400b57cec5SDimitry Andric     0x3d2402a3, 0x6bdef3c9, 0xbec333cd, 0x40c9520f};
36410b57cec5SDimitry Andric 
36420b57cec5SDimitry Andric //---------------------------------------------------------------------------
36430b57cec5SDimitry Andric //  __kmp_get_random: Get a random number using a linear congruential method.
__kmp_get_random(kmp_info_t * thread)36440b57cec5SDimitry Andric unsigned short __kmp_get_random(kmp_info_t *thread) {
36450b57cec5SDimitry Andric   unsigned x = thread->th.th_x;
3646e8d8bef9SDimitry Andric   unsigned short r = (unsigned short)(x >> 16);
36470b57cec5SDimitry Andric 
36480b57cec5SDimitry Andric   thread->th.th_x = x * thread->th.th_a + 1;
36490b57cec5SDimitry Andric 
36500b57cec5SDimitry Andric   KA_TRACE(30, ("__kmp_get_random: THREAD: %d, RETURN: %u\n",
36510b57cec5SDimitry Andric                 thread->th.th_info.ds.ds_tid, r));
36520b57cec5SDimitry Andric 
36530b57cec5SDimitry Andric   return r;
36540b57cec5SDimitry Andric }
36550b57cec5SDimitry Andric //--------------------------------------------------------
36560b57cec5SDimitry Andric // __kmp_init_random: Initialize a random number generator
__kmp_init_random(kmp_info_t * thread)36570b57cec5SDimitry Andric void __kmp_init_random(kmp_info_t *thread) {
36580b57cec5SDimitry Andric   unsigned seed = thread->th.th_info.ds.ds_tid;
36590b57cec5SDimitry Andric 
36600b57cec5SDimitry Andric   thread->th.th_a =
36610b57cec5SDimitry Andric       __kmp_primes[seed % (sizeof(__kmp_primes) / sizeof(__kmp_primes[0]))];
36620b57cec5SDimitry Andric   thread->th.th_x = (seed + 1) * thread->th.th_a + 1;
36630b57cec5SDimitry Andric   KA_TRACE(30,
36640b57cec5SDimitry Andric            ("__kmp_init_random: THREAD: %u; A: %u\n", seed, thread->th.th_a));
36650b57cec5SDimitry Andric }
36660b57cec5SDimitry Andric 
36670b57cec5SDimitry Andric #if KMP_OS_WINDOWS
36680b57cec5SDimitry Andric /* reclaim array entries for root threads that are already dead, returns number
36690b57cec5SDimitry Andric  * reclaimed */
__kmp_reclaim_dead_roots(void)36700b57cec5SDimitry Andric static int __kmp_reclaim_dead_roots(void) {
36710b57cec5SDimitry Andric   int i, r = 0;
36720b57cec5SDimitry Andric 
36730b57cec5SDimitry Andric   for (i = 0; i < __kmp_threads_capacity; ++i) {
36740b57cec5SDimitry Andric     if (KMP_UBER_GTID(i) &&
36750b57cec5SDimitry Andric         !__kmp_still_running((kmp_info_t *)TCR_SYNC_PTR(__kmp_threads[i])) &&
36760b57cec5SDimitry Andric         !__kmp_root[i]
36770b57cec5SDimitry Andric              ->r.r_active) { // AC: reclaim only roots died in non-active state
36780b57cec5SDimitry Andric       r += __kmp_unregister_root_other_thread(i);
36790b57cec5SDimitry Andric     }
36800b57cec5SDimitry Andric   }
36810b57cec5SDimitry Andric   return r;
36820b57cec5SDimitry Andric }
36830b57cec5SDimitry Andric #endif
36840b57cec5SDimitry Andric 
36850b57cec5SDimitry Andric /* This function attempts to create free entries in __kmp_threads and
36860b57cec5SDimitry Andric    __kmp_root, and returns the number of free entries generated.
36870b57cec5SDimitry Andric 
36880b57cec5SDimitry Andric    For Windows* OS static library, the first mechanism used is to reclaim array
36890b57cec5SDimitry Andric    entries for root threads that are already dead.
36900b57cec5SDimitry Andric 
36910b57cec5SDimitry Andric    On all platforms, expansion is attempted on the arrays __kmp_threads_ and
36920b57cec5SDimitry Andric    __kmp_root, with appropriate update to __kmp_threads_capacity. Array
36930b57cec5SDimitry Andric    capacity is increased by doubling with clipping to __kmp_tp_capacity, if
36940b57cec5SDimitry Andric    threadprivate cache array has been created. Synchronization with
36950b57cec5SDimitry Andric    __kmpc_threadprivate_cached is done using __kmp_tp_cached_lock.
36960b57cec5SDimitry Andric 
36970b57cec5SDimitry Andric    After any dead root reclamation, if the clipping value allows array expansion
36980b57cec5SDimitry Andric    to result in the generation of a total of nNeed free slots, the function does
36990b57cec5SDimitry Andric    that expansion. If not, nothing is done beyond the possible initial root
37000b57cec5SDimitry Andric    thread reclamation.
37010b57cec5SDimitry Andric 
37020b57cec5SDimitry Andric    If any argument is negative, the behavior is undefined. */
__kmp_expand_threads(int nNeed)37030b57cec5SDimitry Andric static int __kmp_expand_threads(int nNeed) {
37040b57cec5SDimitry Andric   int added = 0;
37050b57cec5SDimitry Andric   int minimumRequiredCapacity;
37060b57cec5SDimitry Andric   int newCapacity;
37070b57cec5SDimitry Andric   kmp_info_t **newThreads;
37080b57cec5SDimitry Andric   kmp_root_t **newRoot;
37090b57cec5SDimitry Andric 
37100b57cec5SDimitry Andric   // All calls to __kmp_expand_threads should be under __kmp_forkjoin_lock, so
37110b57cec5SDimitry Andric   // resizing __kmp_threads does not need additional protection if foreign
37120b57cec5SDimitry Andric   // threads are present
37130b57cec5SDimitry Andric 
37140b57cec5SDimitry Andric #if KMP_OS_WINDOWS && !KMP_DYNAMIC_LIB
37150b57cec5SDimitry Andric   /* only for Windows static library */
37160b57cec5SDimitry Andric   /* reclaim array entries for root threads that are already dead */
37170b57cec5SDimitry Andric   added = __kmp_reclaim_dead_roots();
37180b57cec5SDimitry Andric 
37190b57cec5SDimitry Andric   if (nNeed) {
37200b57cec5SDimitry Andric     nNeed -= added;
37210b57cec5SDimitry Andric     if (nNeed < 0)
37220b57cec5SDimitry Andric       nNeed = 0;
37230b57cec5SDimitry Andric   }
37240b57cec5SDimitry Andric #endif
37250b57cec5SDimitry Andric   if (nNeed <= 0)
37260b57cec5SDimitry Andric     return added;
37270b57cec5SDimitry Andric 
37280b57cec5SDimitry Andric   // Note that __kmp_threads_capacity is not bounded by __kmp_max_nth. If
37290b57cec5SDimitry Andric   // __kmp_max_nth is set to some value less than __kmp_sys_max_nth by the
37300b57cec5SDimitry Andric   // user via KMP_DEVICE_THREAD_LIMIT, then __kmp_threads_capacity may become
37310b57cec5SDimitry Andric   // > __kmp_max_nth in one of two ways:
37320b57cec5SDimitry Andric   //
37330b57cec5SDimitry Andric   // 1) The initialization thread (gtid = 0) exits.  __kmp_threads[0]
37345ffd83dbSDimitry Andric   //    may not be reused by another thread, so we may need to increase
37350b57cec5SDimitry Andric   //    __kmp_threads_capacity to __kmp_max_nth + 1.
37360b57cec5SDimitry Andric   //
37370b57cec5SDimitry Andric   // 2) New foreign root(s) are encountered.  We always register new foreign
37380b57cec5SDimitry Andric   //    roots. This may cause a smaller # of threads to be allocated at
37390b57cec5SDimitry Andric   //    subsequent parallel regions, but the worker threads hang around (and
37400b57cec5SDimitry Andric   //    eventually go to sleep) and need slots in the __kmp_threads[] array.
37410b57cec5SDimitry Andric   //
37420b57cec5SDimitry Andric   // Anyway, that is the reason for moving the check to see if
37430b57cec5SDimitry Andric   // __kmp_max_nth was exceeded into __kmp_reserve_threads()
37440b57cec5SDimitry Andric   // instead of having it performed here. -BB
37450b57cec5SDimitry Andric 
37460b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_sys_max_nth >= __kmp_threads_capacity);
37470b57cec5SDimitry Andric 
37480b57cec5SDimitry Andric   /* compute expansion headroom to check if we can expand */
37490b57cec5SDimitry Andric   if (__kmp_sys_max_nth - __kmp_threads_capacity < nNeed) {
37500b57cec5SDimitry Andric     /* possible expansion too small -- give up */
37510b57cec5SDimitry Andric     return added;
37520b57cec5SDimitry Andric   }
37530b57cec5SDimitry Andric   minimumRequiredCapacity = __kmp_threads_capacity + nNeed;
37540b57cec5SDimitry Andric 
37550b57cec5SDimitry Andric   newCapacity = __kmp_threads_capacity;
37560b57cec5SDimitry Andric   do {
37570b57cec5SDimitry Andric     newCapacity = newCapacity <= (__kmp_sys_max_nth >> 1) ? (newCapacity << 1)
37580b57cec5SDimitry Andric                                                           : __kmp_sys_max_nth;
37590b57cec5SDimitry Andric   } while (newCapacity < minimumRequiredCapacity);
37600b57cec5SDimitry Andric   newThreads = (kmp_info_t **)__kmp_allocate(
37610b57cec5SDimitry Andric       (sizeof(kmp_info_t *) + sizeof(kmp_root_t *)) * newCapacity + CACHE_LINE);
37620b57cec5SDimitry Andric   newRoot =
37630b57cec5SDimitry Andric       (kmp_root_t **)((char *)newThreads + sizeof(kmp_info_t *) * newCapacity);
37640b57cec5SDimitry Andric   KMP_MEMCPY(newThreads, __kmp_threads,
37650b57cec5SDimitry Andric              __kmp_threads_capacity * sizeof(kmp_info_t *));
37660b57cec5SDimitry Andric   KMP_MEMCPY(newRoot, __kmp_root,
37670b57cec5SDimitry Andric              __kmp_threads_capacity * sizeof(kmp_root_t *));
376881ad6265SDimitry Andric   // Put old __kmp_threads array on a list. Any ongoing references to the old
376981ad6265SDimitry Andric   // list will be valid. This list is cleaned up at library shutdown.
377081ad6265SDimitry Andric   kmp_old_threads_list_t *node =
377181ad6265SDimitry Andric       (kmp_old_threads_list_t *)__kmp_allocate(sizeof(kmp_old_threads_list_t));
377281ad6265SDimitry Andric   node->threads = __kmp_threads;
377381ad6265SDimitry Andric   node->next = __kmp_old_threads_list;
377481ad6265SDimitry Andric   __kmp_old_threads_list = node;
37750b57cec5SDimitry Andric 
37760b57cec5SDimitry Andric   *(kmp_info_t * *volatile *)&__kmp_threads = newThreads;
37770b57cec5SDimitry Andric   *(kmp_root_t * *volatile *)&__kmp_root = newRoot;
37780b57cec5SDimitry Andric   added += newCapacity - __kmp_threads_capacity;
37790b57cec5SDimitry Andric   *(volatile int *)&__kmp_threads_capacity = newCapacity;
37800b57cec5SDimitry Andric 
37810b57cec5SDimitry Andric   if (newCapacity > __kmp_tp_capacity) {
37820b57cec5SDimitry Andric     __kmp_acquire_bootstrap_lock(&__kmp_tp_cached_lock);
37830b57cec5SDimitry Andric     if (__kmp_tp_cached && newCapacity > __kmp_tp_capacity) {
37840b57cec5SDimitry Andric       __kmp_threadprivate_resize_cache(newCapacity);
37850b57cec5SDimitry Andric     } else { // increase __kmp_tp_capacity to correspond with kmp_threads size
37860b57cec5SDimitry Andric       *(volatile int *)&__kmp_tp_capacity = newCapacity;
37870b57cec5SDimitry Andric     }
37880b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_tp_cached_lock);
37890b57cec5SDimitry Andric   }
37900b57cec5SDimitry Andric 
37910b57cec5SDimitry Andric   return added;
37920b57cec5SDimitry Andric }
37930b57cec5SDimitry Andric 
37940b57cec5SDimitry Andric /* Register the current thread as a root thread and obtain our gtid. We must
37950b57cec5SDimitry Andric    have the __kmp_initz_lock held at this point. Argument TRUE only if are the
37960b57cec5SDimitry Andric    thread that calls from __kmp_do_serial_initialize() */
__kmp_register_root(int initial_thread)37970b57cec5SDimitry Andric int __kmp_register_root(int initial_thread) {
37980b57cec5SDimitry Andric   kmp_info_t *root_thread;
37990b57cec5SDimitry Andric   kmp_root_t *root;
38000b57cec5SDimitry Andric   int gtid;
38010b57cec5SDimitry Andric   int capacity;
38020b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
38030b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_register_root: entered\n"));
38040b57cec5SDimitry Andric   KMP_MB();
38050b57cec5SDimitry Andric 
38060b57cec5SDimitry Andric   /* 2007-03-02:
38070b57cec5SDimitry Andric      If initial thread did not invoke OpenMP RTL yet, and this thread is not an
38080b57cec5SDimitry Andric      initial one, "__kmp_all_nth >= __kmp_threads_capacity" condition does not
38090b57cec5SDimitry Andric      work as expected -- it may return false (that means there is at least one
38100b57cec5SDimitry Andric      empty slot in __kmp_threads array), but it is possible the only free slot
38110b57cec5SDimitry Andric      is #0, which is reserved for initial thread and so cannot be used for this
38120b57cec5SDimitry Andric      one. Following code workarounds this bug.
38130b57cec5SDimitry Andric 
38140b57cec5SDimitry Andric      However, right solution seems to be not reserving slot #0 for initial
38150b57cec5SDimitry Andric      thread because:
38160b57cec5SDimitry Andric      (1) there is no magic in slot #0,
38170b57cec5SDimitry Andric      (2) we cannot detect initial thread reliably (the first thread which does
38180b57cec5SDimitry Andric         serial initialization may be not a real initial thread).
38190b57cec5SDimitry Andric   */
38200b57cec5SDimitry Andric   capacity = __kmp_threads_capacity;
38210b57cec5SDimitry Andric   if (!initial_thread && TCR_PTR(__kmp_threads[0]) == NULL) {
38220b57cec5SDimitry Andric     --capacity;
38230b57cec5SDimitry Andric   }
38240b57cec5SDimitry Andric 
3825d409305fSDimitry Andric   // If it is not for initializing the hidden helper team, we need to take
3826d409305fSDimitry Andric   // __kmp_hidden_helper_threads_num out of the capacity because it is included
3827d409305fSDimitry Andric   // in __kmp_threads_capacity.
3828d409305fSDimitry Andric   if (__kmp_enable_hidden_helper && !TCR_4(__kmp_init_hidden_helper_threads)) {
3829d409305fSDimitry Andric     capacity -= __kmp_hidden_helper_threads_num;
3830d409305fSDimitry Andric   }
3831d409305fSDimitry Andric 
38320b57cec5SDimitry Andric   /* see if there are too many threads */
38330b57cec5SDimitry Andric   if (__kmp_all_nth >= capacity && !__kmp_expand_threads(1)) {
38340b57cec5SDimitry Andric     if (__kmp_tp_cached) {
38350b57cec5SDimitry Andric       __kmp_fatal(KMP_MSG(CantRegisterNewThread),
38360b57cec5SDimitry Andric                   KMP_HNT(Set_ALL_THREADPRIVATE, __kmp_tp_capacity),
38370b57cec5SDimitry Andric                   KMP_HNT(PossibleSystemLimitOnThreads), __kmp_msg_null);
38380b57cec5SDimitry Andric     } else {
38390b57cec5SDimitry Andric       __kmp_fatal(KMP_MSG(CantRegisterNewThread), KMP_HNT(SystemLimitOnThreads),
38400b57cec5SDimitry Andric                   __kmp_msg_null);
38410b57cec5SDimitry Andric     }
38420b57cec5SDimitry Andric   }
38430b57cec5SDimitry Andric 
3844e8d8bef9SDimitry Andric   // When hidden helper task is enabled, __kmp_threads is organized as follows:
3845e8d8bef9SDimitry Andric   // 0: initial thread, also a regular OpenMP thread.
3846e8d8bef9SDimitry Andric   // [1, __kmp_hidden_helper_threads_num]: slots for hidden helper threads.
3847e8d8bef9SDimitry Andric   // [__kmp_hidden_helper_threads_num + 1, __kmp_threads_capacity): slots for
3848e8d8bef9SDimitry Andric   // regular OpenMP threads.
3849e8d8bef9SDimitry Andric   if (TCR_4(__kmp_init_hidden_helper_threads)) {
3850e8d8bef9SDimitry Andric     // Find an available thread slot for hidden helper thread. Slots for hidden
3851e8d8bef9SDimitry Andric     // helper threads start from 1 to __kmp_hidden_helper_threads_num.
3852e8d8bef9SDimitry Andric     for (gtid = 1; TCR_PTR(__kmp_threads[gtid]) != NULL &&
3853e8d8bef9SDimitry Andric                    gtid <= __kmp_hidden_helper_threads_num;
38540b57cec5SDimitry Andric          gtid++)
38550b57cec5SDimitry Andric       ;
3856e8d8bef9SDimitry Andric     KMP_ASSERT(gtid <= __kmp_hidden_helper_threads_num);
3857e8d8bef9SDimitry Andric     KA_TRACE(1, ("__kmp_register_root: found slot in threads array for "
3858e8d8bef9SDimitry Andric                  "hidden helper thread: T#%d\n",
3859e8d8bef9SDimitry Andric                  gtid));
3860e8d8bef9SDimitry Andric   } else {
3861e8d8bef9SDimitry Andric     /* find an available thread slot */
3862e8d8bef9SDimitry Andric     // Don't reassign the zero slot since we need that to only be used by
3863e8d8bef9SDimitry Andric     // initial thread. Slots for hidden helper threads should also be skipped.
3864d409305fSDimitry Andric     if (initial_thread && TCR_PTR(__kmp_threads[0]) == NULL) {
3865e8d8bef9SDimitry Andric       gtid = 0;
3866e8d8bef9SDimitry Andric     } else {
3867e8d8bef9SDimitry Andric       for (gtid = __kmp_hidden_helper_threads_num + 1;
3868e8d8bef9SDimitry Andric            TCR_PTR(__kmp_threads[gtid]) != NULL; gtid++)
3869e8d8bef9SDimitry Andric         ;
3870e8d8bef9SDimitry Andric     }
3871e8d8bef9SDimitry Andric     KA_TRACE(
3872e8d8bef9SDimitry Andric         1, ("__kmp_register_root: found slot in threads array: T#%d\n", gtid));
38730b57cec5SDimitry Andric     KMP_ASSERT(gtid < __kmp_threads_capacity);
3874e8d8bef9SDimitry Andric   }
38750b57cec5SDimitry Andric 
38760b57cec5SDimitry Andric   /* update global accounting */
38770b57cec5SDimitry Andric   __kmp_all_nth++;
38780b57cec5SDimitry Andric   TCW_4(__kmp_nth, __kmp_nth + 1);
38790b57cec5SDimitry Andric 
38800b57cec5SDimitry Andric   // if __kmp_adjust_gtid_mode is set, then we use method #1 (sp search) for low
38810b57cec5SDimitry Andric   // numbers of procs, and method #2 (keyed API call) for higher numbers.
38820b57cec5SDimitry Andric   if (__kmp_adjust_gtid_mode) {
38830b57cec5SDimitry Andric     if (__kmp_all_nth >= __kmp_tls_gtid_min) {
38840b57cec5SDimitry Andric       if (TCR_4(__kmp_gtid_mode) != 2) {
38850b57cec5SDimitry Andric         TCW_4(__kmp_gtid_mode, 2);
38860b57cec5SDimitry Andric       }
38870b57cec5SDimitry Andric     } else {
38880b57cec5SDimitry Andric       if (TCR_4(__kmp_gtid_mode) != 1) {
38890b57cec5SDimitry Andric         TCW_4(__kmp_gtid_mode, 1);
38900b57cec5SDimitry Andric       }
38910b57cec5SDimitry Andric     }
38920b57cec5SDimitry Andric   }
38930b57cec5SDimitry Andric 
38940b57cec5SDimitry Andric #ifdef KMP_ADJUST_BLOCKTIME
38950b57cec5SDimitry Andric   /* Adjust blocktime to zero if necessary            */
38960b57cec5SDimitry Andric   /* Middle initialization might not have occurred yet */
38970b57cec5SDimitry Andric   if (!__kmp_env_blocktime && (__kmp_avail_proc > 0)) {
38980b57cec5SDimitry Andric     if (__kmp_nth > __kmp_avail_proc) {
38990b57cec5SDimitry Andric       __kmp_zero_bt = TRUE;
39000b57cec5SDimitry Andric     }
39010b57cec5SDimitry Andric   }
39020b57cec5SDimitry Andric #endif /* KMP_ADJUST_BLOCKTIME */
39030b57cec5SDimitry Andric 
39040b57cec5SDimitry Andric   /* setup this new hierarchy */
39050b57cec5SDimitry Andric   if (!(root = __kmp_root[gtid])) {
39060b57cec5SDimitry Andric     root = __kmp_root[gtid] = (kmp_root_t *)__kmp_allocate(sizeof(kmp_root_t));
39070b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(!root->r.r_root_team);
39080b57cec5SDimitry Andric   }
39090b57cec5SDimitry Andric 
39100b57cec5SDimitry Andric #if KMP_STATS_ENABLED
39110b57cec5SDimitry Andric   // Initialize stats as soon as possible (right after gtid assignment).
39120b57cec5SDimitry Andric   __kmp_stats_thread_ptr = __kmp_stats_list->push_back(gtid);
39130b57cec5SDimitry Andric   __kmp_stats_thread_ptr->startLife();
39140b57cec5SDimitry Andric   KMP_SET_THREAD_STATE(SERIAL_REGION);
39150b57cec5SDimitry Andric   KMP_INIT_PARTITIONED_TIMERS(OMP_serial);
39160b57cec5SDimitry Andric #endif
39170b57cec5SDimitry Andric   __kmp_initialize_root(root);
39180b57cec5SDimitry Andric 
39190b57cec5SDimitry Andric   /* setup new root thread structure */
39200b57cec5SDimitry Andric   if (root->r.r_uber_thread) {
39210b57cec5SDimitry Andric     root_thread = root->r.r_uber_thread;
39220b57cec5SDimitry Andric   } else {
39230b57cec5SDimitry Andric     root_thread = (kmp_info_t *)__kmp_allocate(sizeof(kmp_info_t));
39240b57cec5SDimitry Andric     if (__kmp_storage_map) {
39250b57cec5SDimitry Andric       __kmp_print_thread_storage_map(root_thread, gtid);
39260b57cec5SDimitry Andric     }
39270b57cec5SDimitry Andric     root_thread->th.th_info.ds.ds_gtid = gtid;
39280b57cec5SDimitry Andric #if OMPT_SUPPORT
39290b57cec5SDimitry Andric     root_thread->th.ompt_thread_info.thread_data = ompt_data_none;
39300b57cec5SDimitry Andric #endif
39310b57cec5SDimitry Andric     root_thread->th.th_root = root;
39320b57cec5SDimitry Andric     if (__kmp_env_consistency_check) {
39330b57cec5SDimitry Andric       root_thread->th.th_cons = __kmp_allocate_cons_stack(gtid);
39340b57cec5SDimitry Andric     }
39350b57cec5SDimitry Andric #if USE_FAST_MEMORY
39360b57cec5SDimitry Andric     __kmp_initialize_fast_memory(root_thread);
39370b57cec5SDimitry Andric #endif /* USE_FAST_MEMORY */
39380b57cec5SDimitry Andric 
39390b57cec5SDimitry Andric #if KMP_USE_BGET
39400b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(root_thread->th.th_local.bget_data == NULL);
39410b57cec5SDimitry Andric     __kmp_initialize_bget(root_thread);
39420b57cec5SDimitry Andric #endif
39430b57cec5SDimitry Andric     __kmp_init_random(root_thread); // Initialize random number generator
39440b57cec5SDimitry Andric   }
39450b57cec5SDimitry Andric 
39460b57cec5SDimitry Andric   /* setup the serial team held in reserve by the root thread */
39470b57cec5SDimitry Andric   if (!root_thread->th.th_serial_team) {
39480b57cec5SDimitry Andric     kmp_internal_control_t r_icvs = __kmp_get_global_icvs();
39490b57cec5SDimitry Andric     KF_TRACE(10, ("__kmp_register_root: before serial_team\n"));
39500b57cec5SDimitry Andric     root_thread->th.th_serial_team = __kmp_allocate_team(
39510b57cec5SDimitry Andric         root, 1, 1,
39520b57cec5SDimitry Andric #if OMPT_SUPPORT
39530b57cec5SDimitry Andric         ompt_data_none, // root parallel id
39540b57cec5SDimitry Andric #endif
39550b57cec5SDimitry Andric         proc_bind_default, &r_icvs, 0 USE_NESTED_HOT_ARG(NULL));
39560b57cec5SDimitry Andric   }
39570b57cec5SDimitry Andric   KMP_ASSERT(root_thread->th.th_serial_team);
39580b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_register_root: after serial_team = %p\n",
39590b57cec5SDimitry Andric                 root_thread->th.th_serial_team));
39600b57cec5SDimitry Andric 
39610b57cec5SDimitry Andric   /* drop root_thread into place */
39620b57cec5SDimitry Andric   TCW_SYNC_PTR(__kmp_threads[gtid], root_thread);
39630b57cec5SDimitry Andric 
39640b57cec5SDimitry Andric   root->r.r_root_team->t.t_threads[0] = root_thread;
39650b57cec5SDimitry Andric   root->r.r_hot_team->t.t_threads[0] = root_thread;
39660b57cec5SDimitry Andric   root_thread->th.th_serial_team->t.t_threads[0] = root_thread;
39670b57cec5SDimitry Andric   // AC: the team created in reserve, not for execution (it is unused for now).
39680b57cec5SDimitry Andric   root_thread->th.th_serial_team->t.t_serialized = 0;
39690b57cec5SDimitry Andric   root->r.r_uber_thread = root_thread;
39700b57cec5SDimitry Andric 
39710b57cec5SDimitry Andric   /* initialize the thread, get it ready to go */
39720b57cec5SDimitry Andric   __kmp_initialize_info(root_thread, root->r.r_root_team, 0, gtid);
39730b57cec5SDimitry Andric   TCW_4(__kmp_init_gtid, TRUE);
39740b57cec5SDimitry Andric 
3975fe6060f1SDimitry Andric   /* prepare the primary thread for get_gtid() */
39760b57cec5SDimitry Andric   __kmp_gtid_set_specific(gtid);
39770b57cec5SDimitry Andric 
39780b57cec5SDimitry Andric #if USE_ITT_BUILD
39790b57cec5SDimitry Andric   __kmp_itt_thread_name(gtid);
39800b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
39810b57cec5SDimitry Andric 
39820b57cec5SDimitry Andric #ifdef KMP_TDATA_GTID
39830b57cec5SDimitry Andric   __kmp_gtid = gtid;
39840b57cec5SDimitry Andric #endif
39850b57cec5SDimitry Andric   __kmp_create_worker(gtid, root_thread, __kmp_stksize);
39860b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_gtid_get_specific() == gtid);
39870b57cec5SDimitry Andric 
39880b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_register_root: T#%d init T#%d(%d:%d) arrived: join=%u, "
39890b57cec5SDimitry Andric                 "plain=%u\n",
39900b57cec5SDimitry Andric                 gtid, __kmp_gtid_from_tid(0, root->r.r_hot_team),
39910b57cec5SDimitry Andric                 root->r.r_hot_team->t.t_id, 0, KMP_INIT_BARRIER_STATE,
39920b57cec5SDimitry Andric                 KMP_INIT_BARRIER_STATE));
39930b57cec5SDimitry Andric   { // Initialize barrier data.
39940b57cec5SDimitry Andric     int b;
39950b57cec5SDimitry Andric     for (b = 0; b < bs_last_barrier; ++b) {
39960b57cec5SDimitry Andric       root_thread->th.th_bar[b].bb.b_arrived = KMP_INIT_BARRIER_STATE;
39970b57cec5SDimitry Andric #if USE_DEBUGGER
39980b57cec5SDimitry Andric       root_thread->th.th_bar[b].bb.b_worker_arrived = 0;
39990b57cec5SDimitry Andric #endif
40000b57cec5SDimitry Andric     }
40010b57cec5SDimitry Andric   }
40020b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(root->r.r_hot_team->t.t_bar[bs_forkjoin_barrier].b_arrived ==
40030b57cec5SDimitry Andric                    KMP_INIT_BARRIER_STATE);
40040b57cec5SDimitry Andric 
40050b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
40060b57cec5SDimitry Andric   root_thread->th.th_current_place = KMP_PLACE_UNDEFINED;
40070b57cec5SDimitry Andric   root_thread->th.th_new_place = KMP_PLACE_UNDEFINED;
40080b57cec5SDimitry Andric   root_thread->th.th_first_place = KMP_PLACE_UNDEFINED;
40090b57cec5SDimitry Andric   root_thread->th.th_last_place = KMP_PLACE_UNDEFINED;
40100b57cec5SDimitry Andric #endif /* KMP_AFFINITY_SUPPORTED */
40110b57cec5SDimitry Andric   root_thread->th.th_def_allocator = __kmp_def_allocator;
40120b57cec5SDimitry Andric   root_thread->th.th_prev_level = 0;
40130b57cec5SDimitry Andric   root_thread->th.th_prev_num_threads = 1;
40140b57cec5SDimitry Andric 
40150b57cec5SDimitry Andric   kmp_cg_root_t *tmp = (kmp_cg_root_t *)__kmp_allocate(sizeof(kmp_cg_root_t));
40160b57cec5SDimitry Andric   tmp->cg_root = root_thread;
40170b57cec5SDimitry Andric   tmp->cg_thread_limit = __kmp_cg_max_nth;
40180b57cec5SDimitry Andric   tmp->cg_nthreads = 1;
40190b57cec5SDimitry Andric   KA_TRACE(100, ("__kmp_register_root: Thread %p created node %p with"
40200b57cec5SDimitry Andric                  " cg_nthreads init to 1\n",
40210b57cec5SDimitry Andric                  root_thread, tmp));
40220b57cec5SDimitry Andric   tmp->up = NULL;
40230b57cec5SDimitry Andric   root_thread->th.th_cg_roots = tmp;
40240b57cec5SDimitry Andric 
40250b57cec5SDimitry Andric   __kmp_root_counter++;
40260b57cec5SDimitry Andric 
40270b57cec5SDimitry Andric #if OMPT_SUPPORT
40280b57cec5SDimitry Andric   if (!initial_thread && ompt_enabled.enabled) {
40290b57cec5SDimitry Andric 
40300b57cec5SDimitry Andric     kmp_info_t *root_thread = ompt_get_thread();
40310b57cec5SDimitry Andric 
40320b57cec5SDimitry Andric     ompt_set_thread_state(root_thread, ompt_state_overhead);
40330b57cec5SDimitry Andric 
40340b57cec5SDimitry Andric     if (ompt_enabled.ompt_callback_thread_begin) {
40350b57cec5SDimitry Andric       ompt_callbacks.ompt_callback(ompt_callback_thread_begin)(
40360b57cec5SDimitry Andric           ompt_thread_initial, __ompt_get_thread_data_internal());
40370b57cec5SDimitry Andric     }
40380b57cec5SDimitry Andric     ompt_data_t *task_data;
40390b57cec5SDimitry Andric     ompt_data_t *parallel_data;
4040fe6060f1SDimitry Andric     __ompt_get_task_info_internal(0, NULL, &task_data, NULL, &parallel_data,
4041fe6060f1SDimitry Andric                                   NULL);
40420b57cec5SDimitry Andric     if (ompt_enabled.ompt_callback_implicit_task) {
40430b57cec5SDimitry Andric       ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
40440b57cec5SDimitry Andric           ompt_scope_begin, parallel_data, task_data, 1, 1, ompt_task_initial);
40450b57cec5SDimitry Andric     }
40460b57cec5SDimitry Andric 
40470b57cec5SDimitry Andric     ompt_set_thread_state(root_thread, ompt_state_work_serial);
40480b57cec5SDimitry Andric   }
40490b57cec5SDimitry Andric #endif
4050fe6060f1SDimitry Andric #if OMPD_SUPPORT
4051fe6060f1SDimitry Andric   if (ompd_state & OMPD_ENABLE_BP)
4052fe6060f1SDimitry Andric     ompd_bp_thread_begin();
4053fe6060f1SDimitry Andric #endif
40540b57cec5SDimitry Andric 
40550b57cec5SDimitry Andric   KMP_MB();
40560b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
40570b57cec5SDimitry Andric 
40580b57cec5SDimitry Andric   return gtid;
40590b57cec5SDimitry Andric }
40600b57cec5SDimitry Andric 
40610b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
__kmp_free_hot_teams(kmp_root_t * root,kmp_info_t * thr,int level,const int max_level)40620b57cec5SDimitry Andric static int __kmp_free_hot_teams(kmp_root_t *root, kmp_info_t *thr, int level,
40630b57cec5SDimitry Andric                                 const int max_level) {
40640b57cec5SDimitry Andric   int i, n, nth;
40650b57cec5SDimitry Andric   kmp_hot_team_ptr_t *hot_teams = thr->th.th_hot_teams;
40660b57cec5SDimitry Andric   if (!hot_teams || !hot_teams[level].hot_team) {
40670b57cec5SDimitry Andric     return 0;
40680b57cec5SDimitry Andric   }
40690b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(level < max_level);
40700b57cec5SDimitry Andric   kmp_team_t *team = hot_teams[level].hot_team;
40710b57cec5SDimitry Andric   nth = hot_teams[level].hot_team_nth;
4072fe6060f1SDimitry Andric   n = nth - 1; // primary thread is not freed
40730b57cec5SDimitry Andric   if (level < max_level - 1) {
40740b57cec5SDimitry Andric     for (i = 0; i < nth; ++i) {
40750b57cec5SDimitry Andric       kmp_info_t *th = team->t.t_threads[i];
40760b57cec5SDimitry Andric       n += __kmp_free_hot_teams(root, th, level + 1, max_level);
40770b57cec5SDimitry Andric       if (i > 0 && th->th.th_hot_teams) {
40780b57cec5SDimitry Andric         __kmp_free(th->th.th_hot_teams);
40790b57cec5SDimitry Andric         th->th.th_hot_teams = NULL;
40800b57cec5SDimitry Andric       }
40810b57cec5SDimitry Andric     }
40820b57cec5SDimitry Andric   }
40830b57cec5SDimitry Andric   __kmp_free_team(root, team, NULL);
40840b57cec5SDimitry Andric   return n;
40850b57cec5SDimitry Andric }
40860b57cec5SDimitry Andric #endif
40870b57cec5SDimitry Andric 
40880b57cec5SDimitry Andric // Resets a root thread and clear its root and hot teams.
40890b57cec5SDimitry Andric // Returns the number of __kmp_threads entries directly and indirectly freed.
__kmp_reset_root(int gtid,kmp_root_t * root)40900b57cec5SDimitry Andric static int __kmp_reset_root(int gtid, kmp_root_t *root) {
40910b57cec5SDimitry Andric   kmp_team_t *root_team = root->r.r_root_team;
40920b57cec5SDimitry Andric   kmp_team_t *hot_team = root->r.r_hot_team;
40930b57cec5SDimitry Andric   int n = hot_team->t.t_nproc;
40940b57cec5SDimitry Andric   int i;
40950b57cec5SDimitry Andric 
40960b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(!root->r.r_active);
40970b57cec5SDimitry Andric 
40980b57cec5SDimitry Andric   root->r.r_root_team = NULL;
40990b57cec5SDimitry Andric   root->r.r_hot_team = NULL;
41000b57cec5SDimitry Andric   // __kmp_free_team() does not free hot teams, so we have to clear r_hot_team
41010b57cec5SDimitry Andric   // before call to __kmp_free_team().
41020b57cec5SDimitry Andric   __kmp_free_team(root, root_team USE_NESTED_HOT_ARG(NULL));
41030b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
41040b57cec5SDimitry Andric   if (__kmp_hot_teams_max_level >
41050b57cec5SDimitry Andric       0) { // need to free nested hot teams and their threads if any
41060b57cec5SDimitry Andric     for (i = 0; i < hot_team->t.t_nproc; ++i) {
41070b57cec5SDimitry Andric       kmp_info_t *th = hot_team->t.t_threads[i];
41080b57cec5SDimitry Andric       if (__kmp_hot_teams_max_level > 1) {
41090b57cec5SDimitry Andric         n += __kmp_free_hot_teams(root, th, 1, __kmp_hot_teams_max_level);
41100b57cec5SDimitry Andric       }
41110b57cec5SDimitry Andric       if (th->th.th_hot_teams) {
41120b57cec5SDimitry Andric         __kmp_free(th->th.th_hot_teams);
41130b57cec5SDimitry Andric         th->th.th_hot_teams = NULL;
41140b57cec5SDimitry Andric       }
41150b57cec5SDimitry Andric     }
41160b57cec5SDimitry Andric   }
41170b57cec5SDimitry Andric #endif
41180b57cec5SDimitry Andric   __kmp_free_team(root, hot_team USE_NESTED_HOT_ARG(NULL));
41190b57cec5SDimitry Andric 
41200b57cec5SDimitry Andric   // Before we can reap the thread, we need to make certain that all other
41210b57cec5SDimitry Andric   // threads in the teams that had this root as ancestor have stopped trying to
41220b57cec5SDimitry Andric   // steal tasks.
41230b57cec5SDimitry Andric   if (__kmp_tasking_mode != tskm_immediate_exec) {
41240b57cec5SDimitry Andric     __kmp_wait_to_unref_task_teams();
41250b57cec5SDimitry Andric   }
41260b57cec5SDimitry Andric 
41270b57cec5SDimitry Andric #if KMP_OS_WINDOWS
41280b57cec5SDimitry Andric   /* Close Handle of root duplicated in __kmp_create_worker (tr #62919) */
41290b57cec5SDimitry Andric   KA_TRACE(
41300b57cec5SDimitry Andric       10, ("__kmp_reset_root: free handle, th = %p, handle = %" KMP_UINTPTR_SPEC
41310b57cec5SDimitry Andric            "\n",
41320b57cec5SDimitry Andric            (LPVOID) & (root->r.r_uber_thread->th),
41330b57cec5SDimitry Andric            root->r.r_uber_thread->th.th_info.ds.ds_thread));
41340b57cec5SDimitry Andric   __kmp_free_handle(root->r.r_uber_thread->th.th_info.ds.ds_thread);
41350b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */
41360b57cec5SDimitry Andric 
4137fe6060f1SDimitry Andric #if OMPD_SUPPORT
4138fe6060f1SDimitry Andric   if (ompd_state & OMPD_ENABLE_BP)
4139fe6060f1SDimitry Andric     ompd_bp_thread_end();
4140fe6060f1SDimitry Andric #endif
4141fe6060f1SDimitry Andric 
41420b57cec5SDimitry Andric #if OMPT_SUPPORT
41430b57cec5SDimitry Andric   ompt_data_t *task_data;
41440b57cec5SDimitry Andric   ompt_data_t *parallel_data;
4145fe6060f1SDimitry Andric   __ompt_get_task_info_internal(0, NULL, &task_data, NULL, &parallel_data,
4146fe6060f1SDimitry Andric                                 NULL);
41470b57cec5SDimitry Andric   if (ompt_enabled.ompt_callback_implicit_task) {
41480b57cec5SDimitry Andric     ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
41490b57cec5SDimitry Andric         ompt_scope_end, parallel_data, task_data, 0, 1, ompt_task_initial);
41500b57cec5SDimitry Andric   }
41510b57cec5SDimitry Andric   if (ompt_enabled.ompt_callback_thread_end) {
41520b57cec5SDimitry Andric     ompt_callbacks.ompt_callback(ompt_callback_thread_end)(
41530b57cec5SDimitry Andric         &(root->r.r_uber_thread->th.ompt_thread_info.thread_data));
41540b57cec5SDimitry Andric   }
41550b57cec5SDimitry Andric #endif
41560b57cec5SDimitry Andric 
41570b57cec5SDimitry Andric   TCW_4(__kmp_nth,
41580b57cec5SDimitry Andric         __kmp_nth - 1); // __kmp_reap_thread will decrement __kmp_all_nth.
41590b57cec5SDimitry Andric   i = root->r.r_uber_thread->th.th_cg_roots->cg_nthreads--;
41600b57cec5SDimitry Andric   KA_TRACE(100, ("__kmp_reset_root: Thread %p decrement cg_nthreads on node %p"
41610b57cec5SDimitry Andric                  " to %d\n",
41620b57cec5SDimitry Andric                  root->r.r_uber_thread, root->r.r_uber_thread->th.th_cg_roots,
41630b57cec5SDimitry Andric                  root->r.r_uber_thread->th.th_cg_roots->cg_nthreads));
41640b57cec5SDimitry Andric   if (i == 1) {
41650b57cec5SDimitry Andric     // need to free contention group structure
41660b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(root->r.r_uber_thread ==
41670b57cec5SDimitry Andric                      root->r.r_uber_thread->th.th_cg_roots->cg_root);
41680b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(root->r.r_uber_thread->th.th_cg_roots->up == NULL);
41690b57cec5SDimitry Andric     __kmp_free(root->r.r_uber_thread->th.th_cg_roots);
41700b57cec5SDimitry Andric     root->r.r_uber_thread->th.th_cg_roots = NULL;
41710b57cec5SDimitry Andric   }
41720b57cec5SDimitry Andric   __kmp_reap_thread(root->r.r_uber_thread, 1);
41730b57cec5SDimitry Andric 
4174480093f4SDimitry Andric   // We canot put root thread to __kmp_thread_pool, so we have to reap it
4175480093f4SDimitry Andric   // instead of freeing.
41760b57cec5SDimitry Andric   root->r.r_uber_thread = NULL;
41770b57cec5SDimitry Andric   /* mark root as no longer in use */
41780b57cec5SDimitry Andric   root->r.r_begin = FALSE;
41790b57cec5SDimitry Andric 
41800b57cec5SDimitry Andric   return n;
41810b57cec5SDimitry Andric }
41820b57cec5SDimitry Andric 
__kmp_unregister_root_current_thread(int gtid)41830b57cec5SDimitry Andric void __kmp_unregister_root_current_thread(int gtid) {
41840b57cec5SDimitry Andric   KA_TRACE(1, ("__kmp_unregister_root_current_thread: enter T#%d\n", gtid));
41850b57cec5SDimitry Andric   /* this lock should be ok, since unregister_root_current_thread is never
41860b57cec5SDimitry Andric      called during an abort, only during a normal close. furthermore, if you
41870b57cec5SDimitry Andric      have the forkjoin lock, you should never try to get the initz lock */
41880b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
41890b57cec5SDimitry Andric   if (TCR_4(__kmp_global.g.g_done) || !__kmp_init_serial) {
41900b57cec5SDimitry Andric     KC_TRACE(10, ("__kmp_unregister_root_current_thread: already finished, "
41910b57cec5SDimitry Andric                   "exiting T#%d\n",
41920b57cec5SDimitry Andric                   gtid));
41930b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
41940b57cec5SDimitry Andric     return;
41950b57cec5SDimitry Andric   }
41960b57cec5SDimitry Andric   kmp_root_t *root = __kmp_root[gtid];
41970b57cec5SDimitry Andric 
41980b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_threads && __kmp_threads[gtid]);
41990b57cec5SDimitry Andric   KMP_ASSERT(KMP_UBER_GTID(gtid));
42000b57cec5SDimitry Andric   KMP_ASSERT(root == __kmp_threads[gtid]->th.th_root);
42010b57cec5SDimitry Andric   KMP_ASSERT(root->r.r_active == FALSE);
42020b57cec5SDimitry Andric 
42030b57cec5SDimitry Andric   KMP_MB();
42040b57cec5SDimitry Andric 
42050b57cec5SDimitry Andric   kmp_info_t *thread = __kmp_threads[gtid];
42060b57cec5SDimitry Andric   kmp_team_t *team = thread->th.th_team;
42070b57cec5SDimitry Andric   kmp_task_team_t *task_team = thread->th.th_task_team;
42080b57cec5SDimitry Andric 
42090b57cec5SDimitry Andric   // we need to wait for the proxy tasks before finishing the thread
421004eeddc0SDimitry Andric   if (task_team != NULL && (task_team->tt.tt_found_proxy_tasks ||
421104eeddc0SDimitry Andric                             task_team->tt.tt_hidden_helper_task_encountered)) {
42120b57cec5SDimitry Andric #if OMPT_SUPPORT
42130b57cec5SDimitry Andric     // the runtime is shutting down so we won't report any events
42140b57cec5SDimitry Andric     thread->th.ompt_thread_info.state = ompt_state_undefined;
42150b57cec5SDimitry Andric #endif
42160b57cec5SDimitry Andric     __kmp_task_team_wait(thread, team USE_ITT_BUILD_ARG(NULL));
42170b57cec5SDimitry Andric   }
42180b57cec5SDimitry Andric 
42190b57cec5SDimitry Andric   __kmp_reset_root(gtid, root);
42200b57cec5SDimitry Andric 
42210b57cec5SDimitry Andric   KMP_MB();
42220b57cec5SDimitry Andric   KC_TRACE(10,
42230b57cec5SDimitry Andric            ("__kmp_unregister_root_current_thread: T#%d unregistered\n", gtid));
42240b57cec5SDimitry Andric 
42250b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
42260b57cec5SDimitry Andric }
42270b57cec5SDimitry Andric 
42280b57cec5SDimitry Andric #if KMP_OS_WINDOWS
42290b57cec5SDimitry Andric /* __kmp_forkjoin_lock must be already held
42300b57cec5SDimitry Andric    Unregisters a root thread that is not the current thread.  Returns the number
42310b57cec5SDimitry Andric    of __kmp_threads entries freed as a result. */
__kmp_unregister_root_other_thread(int gtid)42320b57cec5SDimitry Andric static int __kmp_unregister_root_other_thread(int gtid) {
42330b57cec5SDimitry Andric   kmp_root_t *root = __kmp_root[gtid];
42340b57cec5SDimitry Andric   int r;
42350b57cec5SDimitry Andric 
42360b57cec5SDimitry Andric   KA_TRACE(1, ("__kmp_unregister_root_other_thread: enter T#%d\n", gtid));
42370b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_threads && __kmp_threads[gtid]);
42380b57cec5SDimitry Andric   KMP_ASSERT(KMP_UBER_GTID(gtid));
42390b57cec5SDimitry Andric   KMP_ASSERT(root == __kmp_threads[gtid]->th.th_root);
42400b57cec5SDimitry Andric   KMP_ASSERT(root->r.r_active == FALSE);
42410b57cec5SDimitry Andric 
42420b57cec5SDimitry Andric   r = __kmp_reset_root(gtid, root);
42430b57cec5SDimitry Andric   KC_TRACE(10,
42440b57cec5SDimitry Andric            ("__kmp_unregister_root_other_thread: T#%d unregistered\n", gtid));
42450b57cec5SDimitry Andric   return r;
42460b57cec5SDimitry Andric }
42470b57cec5SDimitry Andric #endif
42480b57cec5SDimitry Andric 
42490b57cec5SDimitry Andric #if KMP_DEBUG
__kmp_task_info()42500b57cec5SDimitry Andric void __kmp_task_info() {
42510b57cec5SDimitry Andric 
42520b57cec5SDimitry Andric   kmp_int32 gtid = __kmp_entry_gtid();
42530b57cec5SDimitry Andric   kmp_int32 tid = __kmp_tid_from_gtid(gtid);
42540b57cec5SDimitry Andric   kmp_info_t *this_thr = __kmp_threads[gtid];
42550b57cec5SDimitry Andric   kmp_team_t *steam = this_thr->th.th_serial_team;
42560b57cec5SDimitry Andric   kmp_team_t *team = this_thr->th.th_team;
42570b57cec5SDimitry Andric 
42580b57cec5SDimitry Andric   __kmp_printf(
42590b57cec5SDimitry Andric       "__kmp_task_info: gtid=%d tid=%d t_thread=%p team=%p steam=%p curtask=%p "
42600b57cec5SDimitry Andric       "ptask=%p\n",
42610b57cec5SDimitry Andric       gtid, tid, this_thr, team, steam, this_thr->th.th_current_task,
42620b57cec5SDimitry Andric       team->t.t_implicit_task_taskdata[tid].td_parent);
42630b57cec5SDimitry Andric }
42640b57cec5SDimitry Andric #endif // KMP_DEBUG
42650b57cec5SDimitry Andric 
42660b57cec5SDimitry Andric /* TODO optimize with one big memclr, take out what isn't needed, split
42670b57cec5SDimitry Andric    responsibility to workers as much as possible, and delay initialization of
42680b57cec5SDimitry Andric    features as much as possible  */
__kmp_initialize_info(kmp_info_t * this_thr,kmp_team_t * team,int tid,int gtid)42690b57cec5SDimitry Andric static void __kmp_initialize_info(kmp_info_t *this_thr, kmp_team_t *team,
42700b57cec5SDimitry Andric                                   int tid, int gtid) {
42710b57cec5SDimitry Andric   /* this_thr->th.th_info.ds.ds_gtid is setup in
42720b57cec5SDimitry Andric      kmp_allocate_thread/create_worker.
42730b57cec5SDimitry Andric      this_thr->th.th_serial_team is setup in __kmp_allocate_thread */
42740b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(this_thr != NULL);
42750b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(this_thr->th.th_serial_team);
42760b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team);
42770b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team->t.t_threads);
42780b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team->t.t_dispatch);
4279fe6060f1SDimitry Andric   kmp_info_t *master = team->t.t_threads[0];
42800b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(master);
42810b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(master->th.th_root);
42820b57cec5SDimitry Andric 
42830b57cec5SDimitry Andric   KMP_MB();
42840b57cec5SDimitry Andric 
42850b57cec5SDimitry Andric   TCW_SYNC_PTR(this_thr->th.th_team, team);
42860b57cec5SDimitry Andric 
42870b57cec5SDimitry Andric   this_thr->th.th_info.ds.ds_tid = tid;
42880b57cec5SDimitry Andric   this_thr->th.th_set_nproc = 0;
42890b57cec5SDimitry Andric   if (__kmp_tasking_mode != tskm_immediate_exec)
42900b57cec5SDimitry Andric     // When tasking is possible, threads are not safe to reap until they are
42910b57cec5SDimitry Andric     // done tasking; this will be set when tasking code is exited in wait
42920b57cec5SDimitry Andric     this_thr->th.th_reap_state = KMP_NOT_SAFE_TO_REAP;
42930b57cec5SDimitry Andric   else // no tasking --> always safe to reap
42940b57cec5SDimitry Andric     this_thr->th.th_reap_state = KMP_SAFE_TO_REAP;
42950b57cec5SDimitry Andric   this_thr->th.th_set_proc_bind = proc_bind_default;
42960b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
42970b57cec5SDimitry Andric   this_thr->th.th_new_place = this_thr->th.th_current_place;
42980b57cec5SDimitry Andric #endif
42990b57cec5SDimitry Andric   this_thr->th.th_root = master->th.th_root;
43000b57cec5SDimitry Andric 
43010b57cec5SDimitry Andric   /* setup the thread's cache of the team structure */
43020b57cec5SDimitry Andric   this_thr->th.th_team_nproc = team->t.t_nproc;
43030b57cec5SDimitry Andric   this_thr->th.th_team_master = master;
43040b57cec5SDimitry Andric   this_thr->th.th_team_serialized = team->t.t_serialized;
43050b57cec5SDimitry Andric 
43060b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team->t.t_implicit_task_taskdata);
43070b57cec5SDimitry Andric 
43080b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_initialize_info1: T#%d:%d this_thread=%p curtask=%p\n",
43090b57cec5SDimitry Andric                 tid, gtid, this_thr, this_thr->th.th_current_task));
43100b57cec5SDimitry Andric 
43110b57cec5SDimitry Andric   __kmp_init_implicit_task(this_thr->th.th_team_master->th.th_ident, this_thr,
43120b57cec5SDimitry Andric                            team, tid, TRUE);
43130b57cec5SDimitry Andric 
43140b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_initialize_info2: T#%d:%d this_thread=%p curtask=%p\n",
43150b57cec5SDimitry Andric                 tid, gtid, this_thr, this_thr->th.th_current_task));
43160b57cec5SDimitry Andric   // TODO: Initialize ICVs from parent; GEH - isn't that already done in
43170b57cec5SDimitry Andric   // __kmp_initialize_team()?
43180b57cec5SDimitry Andric 
43190b57cec5SDimitry Andric   /* TODO no worksharing in speculative threads */
43200b57cec5SDimitry Andric   this_thr->th.th_dispatch = &team->t.t_dispatch[tid];
43210b57cec5SDimitry Andric 
43220b57cec5SDimitry Andric   this_thr->th.th_local.this_construct = 0;
43230b57cec5SDimitry Andric 
43240b57cec5SDimitry Andric   if (!this_thr->th.th_pri_common) {
43250b57cec5SDimitry Andric     this_thr->th.th_pri_common =
43260b57cec5SDimitry Andric         (struct common_table *)__kmp_allocate(sizeof(struct common_table));
43270b57cec5SDimitry Andric     if (__kmp_storage_map) {
43280b57cec5SDimitry Andric       __kmp_print_storage_map_gtid(
43290b57cec5SDimitry Andric           gtid, this_thr->th.th_pri_common, this_thr->th.th_pri_common + 1,
43300b57cec5SDimitry Andric           sizeof(struct common_table), "th_%d.th_pri_common\n", gtid);
43310b57cec5SDimitry Andric     }
43320b57cec5SDimitry Andric     this_thr->th.th_pri_head = NULL;
43330b57cec5SDimitry Andric   }
43340b57cec5SDimitry Andric 
4335fe6060f1SDimitry Andric   if (this_thr != master && // Primary thread's CG root is initialized elsewhere
43360b57cec5SDimitry Andric       this_thr->th.th_cg_roots != master->th.th_cg_roots) { // CG root not set
4337fe6060f1SDimitry Andric     // Make new thread's CG root same as primary thread's
43380b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(master->th.th_cg_roots);
43390b57cec5SDimitry Andric     kmp_cg_root_t *tmp = this_thr->th.th_cg_roots;
43400b57cec5SDimitry Andric     if (tmp) {
43410b57cec5SDimitry Andric       // worker changes CG, need to check if old CG should be freed
43420b57cec5SDimitry Andric       int i = tmp->cg_nthreads--;
43430b57cec5SDimitry Andric       KA_TRACE(100, ("__kmp_initialize_info: Thread %p decrement cg_nthreads"
43440b57cec5SDimitry Andric                      " on node %p of thread %p to %d\n",
43450b57cec5SDimitry Andric                      this_thr, tmp, tmp->cg_root, tmp->cg_nthreads));
43460b57cec5SDimitry Andric       if (i == 1) {
43470b57cec5SDimitry Andric         __kmp_free(tmp); // last thread left CG --> free it
43480b57cec5SDimitry Andric       }
43490b57cec5SDimitry Andric     }
43500b57cec5SDimitry Andric     this_thr->th.th_cg_roots = master->th.th_cg_roots;
43510b57cec5SDimitry Andric     // Increment new thread's CG root's counter to add the new thread
43520b57cec5SDimitry Andric     this_thr->th.th_cg_roots->cg_nthreads++;
43530b57cec5SDimitry Andric     KA_TRACE(100, ("__kmp_initialize_info: Thread %p increment cg_nthreads on"
43540b57cec5SDimitry Andric                    " node %p of thread %p to %d\n",
43550b57cec5SDimitry Andric                    this_thr, this_thr->th.th_cg_roots,
43560b57cec5SDimitry Andric                    this_thr->th.th_cg_roots->cg_root,
43570b57cec5SDimitry Andric                    this_thr->th.th_cg_roots->cg_nthreads));
43580b57cec5SDimitry Andric     this_thr->th.th_current_task->td_icvs.thread_limit =
43590b57cec5SDimitry Andric         this_thr->th.th_cg_roots->cg_thread_limit;
43600b57cec5SDimitry Andric   }
43610b57cec5SDimitry Andric 
43620b57cec5SDimitry Andric   /* Initialize dynamic dispatch */
43630b57cec5SDimitry Andric   {
43640b57cec5SDimitry Andric     volatile kmp_disp_t *dispatch = this_thr->th.th_dispatch;
43650b57cec5SDimitry Andric     // Use team max_nproc since this will never change for the team.
43660b57cec5SDimitry Andric     size_t disp_size =
43670b57cec5SDimitry Andric         sizeof(dispatch_private_info_t) *
43680b57cec5SDimitry Andric         (team->t.t_max_nproc == 1 ? 1 : __kmp_dispatch_num_buffers);
43690b57cec5SDimitry Andric     KD_TRACE(10, ("__kmp_initialize_info: T#%d max_nproc: %d\n", gtid,
43700b57cec5SDimitry Andric                   team->t.t_max_nproc));
43710b57cec5SDimitry Andric     KMP_ASSERT(dispatch);
43720b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(team->t.t_dispatch);
43730b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(dispatch == &team->t.t_dispatch[tid]);
43740b57cec5SDimitry Andric 
43750b57cec5SDimitry Andric     dispatch->th_disp_index = 0;
43760b57cec5SDimitry Andric     dispatch->th_doacross_buf_idx = 0;
43770b57cec5SDimitry Andric     if (!dispatch->th_disp_buffer) {
43780b57cec5SDimitry Andric       dispatch->th_disp_buffer =
43790b57cec5SDimitry Andric           (dispatch_private_info_t *)__kmp_allocate(disp_size);
43800b57cec5SDimitry Andric 
43810b57cec5SDimitry Andric       if (__kmp_storage_map) {
43820b57cec5SDimitry Andric         __kmp_print_storage_map_gtid(
43830b57cec5SDimitry Andric             gtid, &dispatch->th_disp_buffer[0],
43840b57cec5SDimitry Andric             &dispatch->th_disp_buffer[team->t.t_max_nproc == 1
43850b57cec5SDimitry Andric                                           ? 1
43860b57cec5SDimitry Andric                                           : __kmp_dispatch_num_buffers],
4387fe6060f1SDimitry Andric             disp_size,
4388fe6060f1SDimitry Andric             "th_%d.th_dispatch.th_disp_buffer "
43890b57cec5SDimitry Andric             "(team_%d.t_dispatch[%d].th_disp_buffer)",
43900b57cec5SDimitry Andric             gtid, team->t.t_id, gtid);
43910b57cec5SDimitry Andric       }
43920b57cec5SDimitry Andric     } else {
43930b57cec5SDimitry Andric       memset(&dispatch->th_disp_buffer[0], '\0', disp_size);
43940b57cec5SDimitry Andric     }
43950b57cec5SDimitry Andric 
43960b57cec5SDimitry Andric     dispatch->th_dispatch_pr_current = 0;
43970b57cec5SDimitry Andric     dispatch->th_dispatch_sh_current = 0;
43980b57cec5SDimitry Andric 
43990b57cec5SDimitry Andric     dispatch->th_deo_fcn = 0; /* ORDERED     */
44000b57cec5SDimitry Andric     dispatch->th_dxo_fcn = 0; /* END ORDERED */
44010b57cec5SDimitry Andric   }
44020b57cec5SDimitry Andric 
44030b57cec5SDimitry Andric   this_thr->th.th_next_pool = NULL;
44040b57cec5SDimitry Andric 
44050b57cec5SDimitry Andric   if (!this_thr->th.th_task_state_memo_stack) {
44060b57cec5SDimitry Andric     size_t i;
44070b57cec5SDimitry Andric     this_thr->th.th_task_state_memo_stack =
44080b57cec5SDimitry Andric         (kmp_uint8 *)__kmp_allocate(4 * sizeof(kmp_uint8));
44090b57cec5SDimitry Andric     this_thr->th.th_task_state_top = 0;
44100b57cec5SDimitry Andric     this_thr->th.th_task_state_stack_sz = 4;
44110b57cec5SDimitry Andric     for (i = 0; i < this_thr->th.th_task_state_stack_sz;
44120b57cec5SDimitry Andric          ++i) // zero init the stack
44130b57cec5SDimitry Andric       this_thr->th.th_task_state_memo_stack[i] = 0;
44140b57cec5SDimitry Andric   }
44150b57cec5SDimitry Andric 
44160b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(!this_thr->th.th_spin_here);
44170b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(this_thr->th.th_next_waiting == 0);
44180b57cec5SDimitry Andric 
44190b57cec5SDimitry Andric   KMP_MB();
44200b57cec5SDimitry Andric }
44210b57cec5SDimitry Andric 
44220b57cec5SDimitry Andric /* allocate a new thread for the requesting team. this is only called from
44230b57cec5SDimitry Andric    within a forkjoin critical section. we will first try to get an available
44240b57cec5SDimitry Andric    thread from the thread pool. if none is available, we will fork a new one
44250b57cec5SDimitry Andric    assuming we are able to create a new one. this should be assured, as the
44260b57cec5SDimitry Andric    caller should check on this first. */
__kmp_allocate_thread(kmp_root_t * root,kmp_team_t * team,int new_tid)44270b57cec5SDimitry Andric kmp_info_t *__kmp_allocate_thread(kmp_root_t *root, kmp_team_t *team,
44280b57cec5SDimitry Andric                                   int new_tid) {
44290b57cec5SDimitry Andric   kmp_team_t *serial_team;
44300b57cec5SDimitry Andric   kmp_info_t *new_thr;
44310b57cec5SDimitry Andric   int new_gtid;
44320b57cec5SDimitry Andric 
44330b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_allocate_thread: T#%d\n", __kmp_get_gtid()));
44340b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(root && team);
44350b57cec5SDimitry Andric #if !KMP_NESTED_HOT_TEAMS
44360b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(KMP_MASTER_GTID(__kmp_get_gtid()));
44370b57cec5SDimitry Andric #endif
44380b57cec5SDimitry Andric   KMP_MB();
44390b57cec5SDimitry Andric 
44400b57cec5SDimitry Andric   /* first, try to get one from the thread pool */
44410b57cec5SDimitry Andric   if (__kmp_thread_pool) {
44420b57cec5SDimitry Andric     new_thr = CCAST(kmp_info_t *, __kmp_thread_pool);
44430b57cec5SDimitry Andric     __kmp_thread_pool = (volatile kmp_info_t *)new_thr->th.th_next_pool;
44440b57cec5SDimitry Andric     if (new_thr == __kmp_thread_pool_insert_pt) {
44450b57cec5SDimitry Andric       __kmp_thread_pool_insert_pt = NULL;
44460b57cec5SDimitry Andric     }
44470b57cec5SDimitry Andric     TCW_4(new_thr->th.th_in_pool, FALSE);
44480b57cec5SDimitry Andric     __kmp_suspend_initialize_thread(new_thr);
44490b57cec5SDimitry Andric     __kmp_lock_suspend_mx(new_thr);
44500b57cec5SDimitry Andric     if (new_thr->th.th_active_in_pool == TRUE) {
44510b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(new_thr->th.th_active == TRUE);
44520b57cec5SDimitry Andric       KMP_ATOMIC_DEC(&__kmp_thread_pool_active_nth);
44530b57cec5SDimitry Andric       new_thr->th.th_active_in_pool = FALSE;
44540b57cec5SDimitry Andric     }
44550b57cec5SDimitry Andric     __kmp_unlock_suspend_mx(new_thr);
44560b57cec5SDimitry Andric 
44570b57cec5SDimitry Andric     KA_TRACE(20, ("__kmp_allocate_thread: T#%d using thread T#%d\n",
44580b57cec5SDimitry Andric                   __kmp_get_gtid(), new_thr->th.th_info.ds.ds_gtid));
44590b57cec5SDimitry Andric     KMP_ASSERT(!new_thr->th.th_team);
44600b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(__kmp_nth < __kmp_threads_capacity);
44610b57cec5SDimitry Andric 
44620b57cec5SDimitry Andric     /* setup the thread structure */
44630b57cec5SDimitry Andric     __kmp_initialize_info(new_thr, team, new_tid,
44640b57cec5SDimitry Andric                           new_thr->th.th_info.ds.ds_gtid);
44650b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(new_thr->th.th_serial_team);
44660b57cec5SDimitry Andric 
44670b57cec5SDimitry Andric     TCW_4(__kmp_nth, __kmp_nth + 1);
44680b57cec5SDimitry Andric 
44690b57cec5SDimitry Andric     new_thr->th.th_task_state = 0;
44700b57cec5SDimitry Andric     new_thr->th.th_task_state_top = 0;
44710b57cec5SDimitry Andric     new_thr->th.th_task_state_stack_sz = 4;
44720b57cec5SDimitry Andric 
4473349cc55cSDimitry Andric     if (__kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
4474349cc55cSDimitry Andric       // Make sure pool thread has transitioned to waiting on own thread struct
4475349cc55cSDimitry Andric       KMP_DEBUG_ASSERT(new_thr->th.th_used_in_team.load() == 0);
4476349cc55cSDimitry Andric       // Thread activated in __kmp_allocate_team when increasing team size
4477349cc55cSDimitry Andric     }
4478349cc55cSDimitry Andric 
44790b57cec5SDimitry Andric #ifdef KMP_ADJUST_BLOCKTIME
44800b57cec5SDimitry Andric     /* Adjust blocktime back to zero if necessary */
44810b57cec5SDimitry Andric     /* Middle initialization might not have occurred yet */
44820b57cec5SDimitry Andric     if (!__kmp_env_blocktime && (__kmp_avail_proc > 0)) {
44830b57cec5SDimitry Andric       if (__kmp_nth > __kmp_avail_proc) {
44840b57cec5SDimitry Andric         __kmp_zero_bt = TRUE;
44850b57cec5SDimitry Andric       }
44860b57cec5SDimitry Andric     }
44870b57cec5SDimitry Andric #endif /* KMP_ADJUST_BLOCKTIME */
44880b57cec5SDimitry Andric 
44890b57cec5SDimitry Andric #if KMP_DEBUG
44900b57cec5SDimitry Andric     // If thread entered pool via __kmp_free_thread, wait_flag should !=
44910b57cec5SDimitry Andric     // KMP_BARRIER_PARENT_FLAG.
44920b57cec5SDimitry Andric     int b;
44930b57cec5SDimitry Andric     kmp_balign_t *balign = new_thr->th.th_bar;
44940b57cec5SDimitry Andric     for (b = 0; b < bs_last_barrier; ++b)
44950b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(balign[b].bb.wait_flag != KMP_BARRIER_PARENT_FLAG);
44960b57cec5SDimitry Andric #endif
44970b57cec5SDimitry Andric 
44980b57cec5SDimitry Andric     KF_TRACE(10, ("__kmp_allocate_thread: T#%d using thread %p T#%d\n",
44990b57cec5SDimitry Andric                   __kmp_get_gtid(), new_thr, new_thr->th.th_info.ds.ds_gtid));
45000b57cec5SDimitry Andric 
45010b57cec5SDimitry Andric     KMP_MB();
45020b57cec5SDimitry Andric     return new_thr;
45030b57cec5SDimitry Andric   }
45040b57cec5SDimitry Andric 
45050b57cec5SDimitry Andric   /* no, well fork a new one */
45060b57cec5SDimitry Andric   KMP_ASSERT(__kmp_nth == __kmp_all_nth);
45070b57cec5SDimitry Andric   KMP_ASSERT(__kmp_all_nth < __kmp_threads_capacity);
45080b57cec5SDimitry Andric 
45090b57cec5SDimitry Andric #if KMP_USE_MONITOR
45100b57cec5SDimitry Andric   // If this is the first worker thread the RTL is creating, then also
45110b57cec5SDimitry Andric   // launch the monitor thread.  We try to do this as early as possible.
45120b57cec5SDimitry Andric   if (!TCR_4(__kmp_init_monitor)) {
45130b57cec5SDimitry Andric     __kmp_acquire_bootstrap_lock(&__kmp_monitor_lock);
45140b57cec5SDimitry Andric     if (!TCR_4(__kmp_init_monitor)) {
45150b57cec5SDimitry Andric       KF_TRACE(10, ("before __kmp_create_monitor\n"));
45160b57cec5SDimitry Andric       TCW_4(__kmp_init_monitor, 1);
45170b57cec5SDimitry Andric       __kmp_create_monitor(&__kmp_monitor);
45180b57cec5SDimitry Andric       KF_TRACE(10, ("after __kmp_create_monitor\n"));
45190b57cec5SDimitry Andric #if KMP_OS_WINDOWS
45200b57cec5SDimitry Andric       // AC: wait until monitor has started. This is a fix for CQ232808.
45210b57cec5SDimitry Andric       // The reason is that if the library is loaded/unloaded in a loop with
45220b57cec5SDimitry Andric       // small (parallel) work in between, then there is high probability that
45230b57cec5SDimitry Andric       // monitor thread started after the library shutdown. At shutdown it is
4524fe6060f1SDimitry Andric       // too late to cope with the problem, because when the primary thread is
4525fe6060f1SDimitry Andric       // in DllMain (process detach) the monitor has no chances to start (it is
4526fe6060f1SDimitry Andric       // blocked), and primary thread has no means to inform the monitor that
4527fe6060f1SDimitry Andric       // the library has gone, because all the memory which the monitor can
4528fe6060f1SDimitry Andric       // access is going to be released/reset.
45290b57cec5SDimitry Andric       while (TCR_4(__kmp_init_monitor) < 2) {
45300b57cec5SDimitry Andric         KMP_YIELD(TRUE);
45310b57cec5SDimitry Andric       }
45320b57cec5SDimitry Andric       KF_TRACE(10, ("after monitor thread has started\n"));
45330b57cec5SDimitry Andric #endif
45340b57cec5SDimitry Andric     }
45350b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_monitor_lock);
45360b57cec5SDimitry Andric   }
45370b57cec5SDimitry Andric #endif
45380b57cec5SDimitry Andric 
45390b57cec5SDimitry Andric   KMP_MB();
4540e8d8bef9SDimitry Andric 
4541e8d8bef9SDimitry Andric   {
4542e8d8bef9SDimitry Andric     int new_start_gtid = TCR_4(__kmp_init_hidden_helper_threads)
4543e8d8bef9SDimitry Andric                              ? 1
4544e8d8bef9SDimitry Andric                              : __kmp_hidden_helper_threads_num + 1;
4545e8d8bef9SDimitry Andric 
4546e8d8bef9SDimitry Andric     for (new_gtid = new_start_gtid; TCR_PTR(__kmp_threads[new_gtid]) != NULL;
4547e8d8bef9SDimitry Andric          ++new_gtid) {
45480b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(new_gtid < __kmp_threads_capacity);
45490b57cec5SDimitry Andric     }
45500b57cec5SDimitry Andric 
4551e8d8bef9SDimitry Andric     if (TCR_4(__kmp_init_hidden_helper_threads)) {
4552e8d8bef9SDimitry Andric       KMP_DEBUG_ASSERT(new_gtid <= __kmp_hidden_helper_threads_num);
4553e8d8bef9SDimitry Andric     }
4554e8d8bef9SDimitry Andric   }
4555e8d8bef9SDimitry Andric 
45560b57cec5SDimitry Andric   /* allocate space for it. */
45570b57cec5SDimitry Andric   new_thr = (kmp_info_t *)__kmp_allocate(sizeof(kmp_info_t));
45580b57cec5SDimitry Andric 
45590b57cec5SDimitry Andric   TCW_SYNC_PTR(__kmp_threads[new_gtid], new_thr);
45600b57cec5SDimitry Andric 
4561e8d8bef9SDimitry Andric #if USE_ITT_BUILD && USE_ITT_NOTIFY && KMP_DEBUG
4562e8d8bef9SDimitry Andric   // suppress race conditions detection on synchronization flags in debug mode
4563e8d8bef9SDimitry Andric   // this helps to analyze library internals eliminating false positives
4564e8d8bef9SDimitry Andric   __itt_suppress_mark_range(
4565e8d8bef9SDimitry Andric       __itt_suppress_range, __itt_suppress_threading_errors,
4566e8d8bef9SDimitry Andric       &new_thr->th.th_sleep_loc, sizeof(new_thr->th.th_sleep_loc));
4567e8d8bef9SDimitry Andric   __itt_suppress_mark_range(
4568e8d8bef9SDimitry Andric       __itt_suppress_range, __itt_suppress_threading_errors,
4569e8d8bef9SDimitry Andric       &new_thr->th.th_reap_state, sizeof(new_thr->th.th_reap_state));
4570e8d8bef9SDimitry Andric #if KMP_OS_WINDOWS
4571e8d8bef9SDimitry Andric   __itt_suppress_mark_range(
4572e8d8bef9SDimitry Andric       __itt_suppress_range, __itt_suppress_threading_errors,
4573e8d8bef9SDimitry Andric       &new_thr->th.th_suspend_init, sizeof(new_thr->th.th_suspend_init));
4574e8d8bef9SDimitry Andric #else
4575e8d8bef9SDimitry Andric   __itt_suppress_mark_range(__itt_suppress_range,
4576e8d8bef9SDimitry Andric                             __itt_suppress_threading_errors,
4577e8d8bef9SDimitry Andric                             &new_thr->th.th_suspend_init_count,
4578e8d8bef9SDimitry Andric                             sizeof(new_thr->th.th_suspend_init_count));
4579e8d8bef9SDimitry Andric #endif
4580e8d8bef9SDimitry Andric   // TODO: check if we need to also suppress b_arrived flags
4581e8d8bef9SDimitry Andric   __itt_suppress_mark_range(__itt_suppress_range,
4582e8d8bef9SDimitry Andric                             __itt_suppress_threading_errors,
4583e8d8bef9SDimitry Andric                             CCAST(kmp_uint64 *, &new_thr->th.th_bar[0].bb.b_go),
4584e8d8bef9SDimitry Andric                             sizeof(new_thr->th.th_bar[0].bb.b_go));
4585e8d8bef9SDimitry Andric   __itt_suppress_mark_range(__itt_suppress_range,
4586e8d8bef9SDimitry Andric                             __itt_suppress_threading_errors,
4587e8d8bef9SDimitry Andric                             CCAST(kmp_uint64 *, &new_thr->th.th_bar[1].bb.b_go),
4588e8d8bef9SDimitry Andric                             sizeof(new_thr->th.th_bar[1].bb.b_go));
4589e8d8bef9SDimitry Andric   __itt_suppress_mark_range(__itt_suppress_range,
4590e8d8bef9SDimitry Andric                             __itt_suppress_threading_errors,
4591e8d8bef9SDimitry Andric                             CCAST(kmp_uint64 *, &new_thr->th.th_bar[2].bb.b_go),
4592e8d8bef9SDimitry Andric                             sizeof(new_thr->th.th_bar[2].bb.b_go));
4593e8d8bef9SDimitry Andric #endif /* USE_ITT_BUILD && USE_ITT_NOTIFY && KMP_DEBUG */
45940b57cec5SDimitry Andric   if (__kmp_storage_map) {
45950b57cec5SDimitry Andric     __kmp_print_thread_storage_map(new_thr, new_gtid);
45960b57cec5SDimitry Andric   }
45970b57cec5SDimitry Andric 
4598fe6060f1SDimitry Andric   // add the reserve serialized team, initialized from the team's primary thread
45990b57cec5SDimitry Andric   {
46000b57cec5SDimitry Andric     kmp_internal_control_t r_icvs = __kmp_get_x_global_icvs(team);
46010b57cec5SDimitry Andric     KF_TRACE(10, ("__kmp_allocate_thread: before th_serial/serial_team\n"));
46020b57cec5SDimitry Andric     new_thr->th.th_serial_team = serial_team =
46030b57cec5SDimitry Andric         (kmp_team_t *)__kmp_allocate_team(root, 1, 1,
46040b57cec5SDimitry Andric #if OMPT_SUPPORT
46050b57cec5SDimitry Andric                                           ompt_data_none, // root parallel id
46060b57cec5SDimitry Andric #endif
46070b57cec5SDimitry Andric                                           proc_bind_default, &r_icvs,
46080b57cec5SDimitry Andric                                           0 USE_NESTED_HOT_ARG(NULL));
46090b57cec5SDimitry Andric   }
46100b57cec5SDimitry Andric   KMP_ASSERT(serial_team);
46110b57cec5SDimitry Andric   serial_team->t.t_serialized = 0; // AC: the team created in reserve, not for
46120b57cec5SDimitry Andric   // execution (it is unused for now).
46130b57cec5SDimitry Andric   serial_team->t.t_threads[0] = new_thr;
46140b57cec5SDimitry Andric   KF_TRACE(10,
46150b57cec5SDimitry Andric            ("__kmp_allocate_thread: after th_serial/serial_team : new_thr=%p\n",
46160b57cec5SDimitry Andric             new_thr));
46170b57cec5SDimitry Andric 
46180b57cec5SDimitry Andric   /* setup the thread structures */
46190b57cec5SDimitry Andric   __kmp_initialize_info(new_thr, team, new_tid, new_gtid);
46200b57cec5SDimitry Andric 
46210b57cec5SDimitry Andric #if USE_FAST_MEMORY
46220b57cec5SDimitry Andric   __kmp_initialize_fast_memory(new_thr);
46230b57cec5SDimitry Andric #endif /* USE_FAST_MEMORY */
46240b57cec5SDimitry Andric 
46250b57cec5SDimitry Andric #if KMP_USE_BGET
46260b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(new_thr->th.th_local.bget_data == NULL);
46270b57cec5SDimitry Andric   __kmp_initialize_bget(new_thr);
46280b57cec5SDimitry Andric #endif
46290b57cec5SDimitry Andric 
46300b57cec5SDimitry Andric   __kmp_init_random(new_thr); // Initialize random number generator
46310b57cec5SDimitry Andric 
46320b57cec5SDimitry Andric   /* Initialize these only once when thread is grabbed for a team allocation */
46330b57cec5SDimitry Andric   KA_TRACE(20,
46340b57cec5SDimitry Andric            ("__kmp_allocate_thread: T#%d init go fork=%u, plain=%u\n",
46350b57cec5SDimitry Andric             __kmp_get_gtid(), KMP_INIT_BARRIER_STATE, KMP_INIT_BARRIER_STATE));
46360b57cec5SDimitry Andric 
46370b57cec5SDimitry Andric   int b;
46380b57cec5SDimitry Andric   kmp_balign_t *balign = new_thr->th.th_bar;
46390b57cec5SDimitry Andric   for (b = 0; b < bs_last_barrier; ++b) {
46400b57cec5SDimitry Andric     balign[b].bb.b_go = KMP_INIT_BARRIER_STATE;
46410b57cec5SDimitry Andric     balign[b].bb.team = NULL;
46420b57cec5SDimitry Andric     balign[b].bb.wait_flag = KMP_BARRIER_NOT_WAITING;
46430b57cec5SDimitry Andric     balign[b].bb.use_oncore_barrier = 0;
46440b57cec5SDimitry Andric   }
46450b57cec5SDimitry Andric 
4646349cc55cSDimitry Andric   TCW_PTR(new_thr->th.th_sleep_loc, NULL);
4647349cc55cSDimitry Andric   new_thr->th.th_sleep_loc_type = flag_unset;
4648349cc55cSDimitry Andric 
46490b57cec5SDimitry Andric   new_thr->th.th_spin_here = FALSE;
46500b57cec5SDimitry Andric   new_thr->th.th_next_waiting = 0;
46510b57cec5SDimitry Andric #if KMP_OS_UNIX
46520b57cec5SDimitry Andric   new_thr->th.th_blocking = false;
46530b57cec5SDimitry Andric #endif
46540b57cec5SDimitry Andric 
46550b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
46560b57cec5SDimitry Andric   new_thr->th.th_current_place = KMP_PLACE_UNDEFINED;
46570b57cec5SDimitry Andric   new_thr->th.th_new_place = KMP_PLACE_UNDEFINED;
46580b57cec5SDimitry Andric   new_thr->th.th_first_place = KMP_PLACE_UNDEFINED;
46590b57cec5SDimitry Andric   new_thr->th.th_last_place = KMP_PLACE_UNDEFINED;
46600b57cec5SDimitry Andric #endif
46610b57cec5SDimitry Andric   new_thr->th.th_def_allocator = __kmp_def_allocator;
46620b57cec5SDimitry Andric   new_thr->th.th_prev_level = 0;
46630b57cec5SDimitry Andric   new_thr->th.th_prev_num_threads = 1;
46640b57cec5SDimitry Andric 
46650b57cec5SDimitry Andric   TCW_4(new_thr->th.th_in_pool, FALSE);
46660b57cec5SDimitry Andric   new_thr->th.th_active_in_pool = FALSE;
46670b57cec5SDimitry Andric   TCW_4(new_thr->th.th_active, TRUE);
46680b57cec5SDimitry Andric 
46690b57cec5SDimitry Andric   /* adjust the global counters */
46700b57cec5SDimitry Andric   __kmp_all_nth++;
46710b57cec5SDimitry Andric   __kmp_nth++;
46720b57cec5SDimitry Andric 
46730b57cec5SDimitry Andric   // if __kmp_adjust_gtid_mode is set, then we use method #1 (sp search) for low
46740b57cec5SDimitry Andric   // numbers of procs, and method #2 (keyed API call) for higher numbers.
46750b57cec5SDimitry Andric   if (__kmp_adjust_gtid_mode) {
46760b57cec5SDimitry Andric     if (__kmp_all_nth >= __kmp_tls_gtid_min) {
46770b57cec5SDimitry Andric       if (TCR_4(__kmp_gtid_mode) != 2) {
46780b57cec5SDimitry Andric         TCW_4(__kmp_gtid_mode, 2);
46790b57cec5SDimitry Andric       }
46800b57cec5SDimitry Andric     } else {
46810b57cec5SDimitry Andric       if (TCR_4(__kmp_gtid_mode) != 1) {
46820b57cec5SDimitry Andric         TCW_4(__kmp_gtid_mode, 1);
46830b57cec5SDimitry Andric       }
46840b57cec5SDimitry Andric     }
46850b57cec5SDimitry Andric   }
46860b57cec5SDimitry Andric 
46870b57cec5SDimitry Andric #ifdef KMP_ADJUST_BLOCKTIME
46880b57cec5SDimitry Andric   /* Adjust blocktime back to zero if necessary       */
46890b57cec5SDimitry Andric   /* Middle initialization might not have occurred yet */
46900b57cec5SDimitry Andric   if (!__kmp_env_blocktime && (__kmp_avail_proc > 0)) {
46910b57cec5SDimitry Andric     if (__kmp_nth > __kmp_avail_proc) {
46920b57cec5SDimitry Andric       __kmp_zero_bt = TRUE;
46930b57cec5SDimitry Andric     }
46940b57cec5SDimitry Andric   }
46950b57cec5SDimitry Andric #endif /* KMP_ADJUST_BLOCKTIME */
46960b57cec5SDimitry Andric 
46975f757f3fSDimitry Andric #if KMP_AFFINITY_SUPPORTED
46985f757f3fSDimitry Andric   // Set the affinity and topology information for new thread
46995f757f3fSDimitry Andric   __kmp_affinity_set_init_mask(new_gtid, /*isa_root=*/FALSE);
47005f757f3fSDimitry Andric #endif
47015f757f3fSDimitry Andric 
47020b57cec5SDimitry Andric   /* actually fork it and create the new worker thread */
47030b57cec5SDimitry Andric   KF_TRACE(
47040b57cec5SDimitry Andric       10, ("__kmp_allocate_thread: before __kmp_create_worker: %p\n", new_thr));
47050b57cec5SDimitry Andric   __kmp_create_worker(new_gtid, new_thr, __kmp_stksize);
47060b57cec5SDimitry Andric   KF_TRACE(10,
47070b57cec5SDimitry Andric            ("__kmp_allocate_thread: after __kmp_create_worker: %p\n", new_thr));
47080b57cec5SDimitry Andric 
47090b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_allocate_thread: T#%d forked T#%d\n", __kmp_get_gtid(),
47100b57cec5SDimitry Andric                 new_gtid));
47110b57cec5SDimitry Andric   KMP_MB();
47120b57cec5SDimitry Andric   return new_thr;
47130b57cec5SDimitry Andric }
47140b57cec5SDimitry Andric 
47150b57cec5SDimitry Andric /* Reinitialize team for reuse.
47160b57cec5SDimitry Andric    The hot team code calls this case at every fork barrier, so EPCC barrier
47170b57cec5SDimitry Andric    test are extremely sensitive to changes in it, esp. writes to the team
47180b57cec5SDimitry Andric    struct, which cause a cache invalidation in all threads.
47190b57cec5SDimitry Andric    IF YOU TOUCH THIS ROUTINE, RUN EPCC C SYNCBENCH ON A BIG-IRON MACHINE!!! */
__kmp_reinitialize_team(kmp_team_t * team,kmp_internal_control_t * new_icvs,ident_t * loc)47200b57cec5SDimitry Andric static void __kmp_reinitialize_team(kmp_team_t *team,
47210b57cec5SDimitry Andric                                     kmp_internal_control_t *new_icvs,
47220b57cec5SDimitry Andric                                     ident_t *loc) {
47230b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_reinitialize_team: enter this_thread=%p team=%p\n",
47240b57cec5SDimitry Andric                 team->t.t_threads[0], team));
47250b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team && new_icvs);
47260b57cec5SDimitry Andric   KMP_DEBUG_ASSERT((!TCR_4(__kmp_init_parallel)) || new_icvs->nproc);
47270b57cec5SDimitry Andric   KMP_CHECK_UPDATE(team->t.t_ident, loc);
47280b57cec5SDimitry Andric 
47290b57cec5SDimitry Andric   KMP_CHECK_UPDATE(team->t.t_id, KMP_GEN_TEAM_ID());
4730fe6060f1SDimitry Andric   // Copy ICVs to the primary thread's implicit taskdata
47310b57cec5SDimitry Andric   __kmp_init_implicit_task(loc, team->t.t_threads[0], team, 0, FALSE);
47320b57cec5SDimitry Andric   copy_icvs(&team->t.t_implicit_task_taskdata[0].td_icvs, new_icvs);
47330b57cec5SDimitry Andric 
47340b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_reinitialize_team: exit this_thread=%p team=%p\n",
47350b57cec5SDimitry Andric                 team->t.t_threads[0], team));
47360b57cec5SDimitry Andric }
47370b57cec5SDimitry Andric 
47380b57cec5SDimitry Andric /* Initialize the team data structure.
47390b57cec5SDimitry Andric    This assumes the t_threads and t_max_nproc are already set.
47400b57cec5SDimitry Andric    Also, we don't touch the arguments */
__kmp_initialize_team(kmp_team_t * team,int new_nproc,kmp_internal_control_t * new_icvs,ident_t * loc)47410b57cec5SDimitry Andric static void __kmp_initialize_team(kmp_team_t *team, int new_nproc,
47420b57cec5SDimitry Andric                                   kmp_internal_control_t *new_icvs,
47430b57cec5SDimitry Andric                                   ident_t *loc) {
47440b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_initialize_team: enter: team=%p\n", team));
47450b57cec5SDimitry Andric 
47460b57cec5SDimitry Andric   /* verify */
47470b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team);
47480b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(new_nproc <= team->t.t_max_nproc);
47490b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team->t.t_threads);
47500b57cec5SDimitry Andric   KMP_MB();
47510b57cec5SDimitry Andric 
47520b57cec5SDimitry Andric   team->t.t_master_tid = 0; /* not needed */
47530b57cec5SDimitry Andric   /* team->t.t_master_bar;        not needed */
47540b57cec5SDimitry Andric   team->t.t_serialized = new_nproc > 1 ? 0 : 1;
47550b57cec5SDimitry Andric   team->t.t_nproc = new_nproc;
47560b57cec5SDimitry Andric 
47570b57cec5SDimitry Andric   /* team->t.t_parent     = NULL; TODO not needed & would mess up hot team */
47580b57cec5SDimitry Andric   team->t.t_next_pool = NULL;
47590b57cec5SDimitry Andric   /* memset( team->t.t_threads, 0, sizeof(kmp_info_t*)*new_nproc ); would mess
47600b57cec5SDimitry Andric    * up hot team */
47610b57cec5SDimitry Andric 
47620b57cec5SDimitry Andric   TCW_SYNC_PTR(team->t.t_pkfn, NULL); /* not needed */
47630b57cec5SDimitry Andric   team->t.t_invoke = NULL; /* not needed */
47640b57cec5SDimitry Andric 
47650b57cec5SDimitry Andric   // TODO???: team->t.t_max_active_levels       = new_max_active_levels;
47660b57cec5SDimitry Andric   team->t.t_sched.sched = new_icvs->sched.sched;
47670b57cec5SDimitry Andric 
47680b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
47690b57cec5SDimitry Andric   team->t.t_fp_control_saved = FALSE; /* not needed */
47700b57cec5SDimitry Andric   team->t.t_x87_fpu_control_word = 0; /* not needed */
47710b57cec5SDimitry Andric   team->t.t_mxcsr = 0; /* not needed */
47720b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
47730b57cec5SDimitry Andric 
47740b57cec5SDimitry Andric   team->t.t_construct = 0;
47750b57cec5SDimitry Andric 
47760b57cec5SDimitry Andric   team->t.t_ordered.dt.t_value = 0;
47770b57cec5SDimitry Andric   team->t.t_master_active = FALSE;
47780b57cec5SDimitry Andric 
47790b57cec5SDimitry Andric #ifdef KMP_DEBUG
47800b57cec5SDimitry Andric   team->t.t_copypriv_data = NULL; /* not necessary, but nice for debugging */
47810b57cec5SDimitry Andric #endif
47820b57cec5SDimitry Andric #if KMP_OS_WINDOWS
47830b57cec5SDimitry Andric   team->t.t_copyin_counter = 0; /* for barrier-free copyin implementation */
47840b57cec5SDimitry Andric #endif
47850b57cec5SDimitry Andric 
47860b57cec5SDimitry Andric   team->t.t_control_stack_top = NULL;
47870b57cec5SDimitry Andric 
47880b57cec5SDimitry Andric   __kmp_reinitialize_team(team, new_icvs, loc);
47890b57cec5SDimitry Andric 
47900b57cec5SDimitry Andric   KMP_MB();
47910b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_initialize_team: exit: team=%p\n", team));
47920b57cec5SDimitry Andric }
47930b57cec5SDimitry Andric 
47940b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
__kmp_set_thread_place(kmp_team_t * team,kmp_info_t * th,int first,int last,int newp)47955f757f3fSDimitry Andric static inline void __kmp_set_thread_place(kmp_team_t *team, kmp_info_t *th,
47965f757f3fSDimitry Andric                                           int first, int last, int newp) {
47975f757f3fSDimitry Andric   th->th.th_first_place = first;
47985f757f3fSDimitry Andric   th->th.th_last_place = last;
47995f757f3fSDimitry Andric   th->th.th_new_place = newp;
48005f757f3fSDimitry Andric   if (newp != th->th.th_current_place) {
48015f757f3fSDimitry Andric     if (__kmp_display_affinity && team->t.t_display_affinity != 1)
48025f757f3fSDimitry Andric       team->t.t_display_affinity = 1;
48035f757f3fSDimitry Andric     // Copy topology information associated with the new place
48045f757f3fSDimitry Andric     th->th.th_topology_ids = __kmp_affinity.ids[th->th.th_new_place];
48055f757f3fSDimitry Andric     th->th.th_topology_attrs = __kmp_affinity.attrs[th->th.th_new_place];
48065f757f3fSDimitry Andric   }
48075f757f3fSDimitry Andric }
48080b57cec5SDimitry Andric 
48090b57cec5SDimitry Andric // __kmp_partition_places() is the heart of the OpenMP 4.0 affinity mechanism.
4810fe6060f1SDimitry Andric // It calculates the worker + primary thread's partition based upon the parent
48110b57cec5SDimitry Andric // thread's partition, and binds each worker to a thread in their partition.
4812fe6060f1SDimitry Andric // The primary thread's partition should already include its current binding.
__kmp_partition_places(kmp_team_t * team,int update_master_only)48130b57cec5SDimitry Andric static void __kmp_partition_places(kmp_team_t *team, int update_master_only) {
4814fe6060f1SDimitry Andric   // Do not partition places for the hidden helper team
4815fe6060f1SDimitry Andric   if (KMP_HIDDEN_HELPER_TEAM(team))
4816fe6060f1SDimitry Andric     return;
4817fe6060f1SDimitry Andric   // Copy the primary thread's place partition to the team struct
48180b57cec5SDimitry Andric   kmp_info_t *master_th = team->t.t_threads[0];
48190b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(master_th != NULL);
48200b57cec5SDimitry Andric   kmp_proc_bind_t proc_bind = team->t.t_proc_bind;
48210b57cec5SDimitry Andric   int first_place = master_th->th.th_first_place;
48220b57cec5SDimitry Andric   int last_place = master_th->th.th_last_place;
48230b57cec5SDimitry Andric   int masters_place = master_th->th.th_current_place;
4824bdd1243dSDimitry Andric   int num_masks = __kmp_affinity.num_masks;
48250b57cec5SDimitry Andric   team->t.t_first_place = first_place;
48260b57cec5SDimitry Andric   team->t.t_last_place = last_place;
48270b57cec5SDimitry Andric 
48280b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_partition_places: enter: proc_bind = %d T#%d(%d:0) "
48290b57cec5SDimitry Andric                 "bound to place %d partition = [%d,%d]\n",
48300b57cec5SDimitry Andric                 proc_bind, __kmp_gtid_from_thread(team->t.t_threads[0]),
48310b57cec5SDimitry Andric                 team->t.t_id, masters_place, first_place, last_place));
48320b57cec5SDimitry Andric 
48330b57cec5SDimitry Andric   switch (proc_bind) {
48340b57cec5SDimitry Andric 
48350b57cec5SDimitry Andric   case proc_bind_default:
4836fe6060f1SDimitry Andric     // Serial teams might have the proc_bind policy set to proc_bind_default.
4837fe6060f1SDimitry Andric     // Not an issue -- we don't rebind primary thread for any proc_bind policy.
48380b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(team->t.t_nproc == 1);
48390b57cec5SDimitry Andric     break;
48400b57cec5SDimitry Andric 
4841fe6060f1SDimitry Andric   case proc_bind_primary: {
48420b57cec5SDimitry Andric     int f;
48430b57cec5SDimitry Andric     int n_th = team->t.t_nproc;
48440b57cec5SDimitry Andric     for (f = 1; f < n_th; f++) {
48450b57cec5SDimitry Andric       kmp_info_t *th = team->t.t_threads[f];
48460b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(th != NULL);
48475f757f3fSDimitry Andric       __kmp_set_thread_place(team, th, first_place, last_place, masters_place);
48480b57cec5SDimitry Andric 
4849fe6060f1SDimitry Andric       KA_TRACE(100, ("__kmp_partition_places: primary: T#%d(%d:%d) place %d "
48500b57cec5SDimitry Andric                      "partition = [%d,%d]\n",
48510b57cec5SDimitry Andric                      __kmp_gtid_from_thread(team->t.t_threads[f]), team->t.t_id,
48520b57cec5SDimitry Andric                      f, masters_place, first_place, last_place));
48530b57cec5SDimitry Andric     }
48540b57cec5SDimitry Andric   } break;
48550b57cec5SDimitry Andric 
48560b57cec5SDimitry Andric   case proc_bind_close: {
48570b57cec5SDimitry Andric     int f;
48580b57cec5SDimitry Andric     int n_th = team->t.t_nproc;
48590b57cec5SDimitry Andric     int n_places;
48600b57cec5SDimitry Andric     if (first_place <= last_place) {
48610b57cec5SDimitry Andric       n_places = last_place - first_place + 1;
48620b57cec5SDimitry Andric     } else {
4863bdd1243dSDimitry Andric       n_places = num_masks - first_place + last_place + 1;
48640b57cec5SDimitry Andric     }
48650b57cec5SDimitry Andric     if (n_th <= n_places) {
48660b57cec5SDimitry Andric       int place = masters_place;
48670b57cec5SDimitry Andric       for (f = 1; f < n_th; f++) {
48680b57cec5SDimitry Andric         kmp_info_t *th = team->t.t_threads[f];
48690b57cec5SDimitry Andric         KMP_DEBUG_ASSERT(th != NULL);
48700b57cec5SDimitry Andric 
48710b57cec5SDimitry Andric         if (place == last_place) {
48720b57cec5SDimitry Andric           place = first_place;
4873bdd1243dSDimitry Andric         } else if (place == (num_masks - 1)) {
48740b57cec5SDimitry Andric           place = 0;
48750b57cec5SDimitry Andric         } else {
48760b57cec5SDimitry Andric           place++;
48770b57cec5SDimitry Andric         }
48785f757f3fSDimitry Andric         __kmp_set_thread_place(team, th, first_place, last_place, place);
48790b57cec5SDimitry Andric 
48800b57cec5SDimitry Andric         KA_TRACE(100, ("__kmp_partition_places: close: T#%d(%d:%d) place %d "
48810b57cec5SDimitry Andric                        "partition = [%d,%d]\n",
48820b57cec5SDimitry Andric                        __kmp_gtid_from_thread(team->t.t_threads[f]),
48830b57cec5SDimitry Andric                        team->t.t_id, f, place, first_place, last_place));
48840b57cec5SDimitry Andric       }
48850b57cec5SDimitry Andric     } else {
48860b57cec5SDimitry Andric       int S, rem, gap, s_count;
48870b57cec5SDimitry Andric       S = n_th / n_places;
48880b57cec5SDimitry Andric       s_count = 0;
48890b57cec5SDimitry Andric       rem = n_th - (S * n_places);
48900b57cec5SDimitry Andric       gap = rem > 0 ? n_places / rem : n_places;
48910b57cec5SDimitry Andric       int place = masters_place;
48920b57cec5SDimitry Andric       int gap_ct = gap;
48930b57cec5SDimitry Andric       for (f = 0; f < n_th; f++) {
48940b57cec5SDimitry Andric         kmp_info_t *th = team->t.t_threads[f];
48950b57cec5SDimitry Andric         KMP_DEBUG_ASSERT(th != NULL);
48960b57cec5SDimitry Andric 
48975f757f3fSDimitry Andric         __kmp_set_thread_place(team, th, first_place, last_place, place);
48980b57cec5SDimitry Andric         s_count++;
48990b57cec5SDimitry Andric 
49000b57cec5SDimitry Andric         if ((s_count == S) && rem && (gap_ct == gap)) {
49010b57cec5SDimitry Andric           // do nothing, add an extra thread to place on next iteration
49020b57cec5SDimitry Andric         } else if ((s_count == S + 1) && rem && (gap_ct == gap)) {
49030b57cec5SDimitry Andric           // we added an extra thread to this place; move to next place
49040b57cec5SDimitry Andric           if (place == last_place) {
49050b57cec5SDimitry Andric             place = first_place;
4906bdd1243dSDimitry Andric           } else if (place == (num_masks - 1)) {
49070b57cec5SDimitry Andric             place = 0;
49080b57cec5SDimitry Andric           } else {
49090b57cec5SDimitry Andric             place++;
49100b57cec5SDimitry Andric           }
49110b57cec5SDimitry Andric           s_count = 0;
49120b57cec5SDimitry Andric           gap_ct = 1;
49130b57cec5SDimitry Andric           rem--;
49140b57cec5SDimitry Andric         } else if (s_count == S) { // place full; don't add extra
49150b57cec5SDimitry Andric           if (place == last_place) {
49160b57cec5SDimitry Andric             place = first_place;
4917bdd1243dSDimitry Andric           } else if (place == (num_masks - 1)) {
49180b57cec5SDimitry Andric             place = 0;
49190b57cec5SDimitry Andric           } else {
49200b57cec5SDimitry Andric             place++;
49210b57cec5SDimitry Andric           }
49220b57cec5SDimitry Andric           gap_ct++;
49230b57cec5SDimitry Andric           s_count = 0;
49240b57cec5SDimitry Andric         }
49250b57cec5SDimitry Andric 
49260b57cec5SDimitry Andric         KA_TRACE(100,
49270b57cec5SDimitry Andric                  ("__kmp_partition_places: close: T#%d(%d:%d) place %d "
49280b57cec5SDimitry Andric                   "partition = [%d,%d]\n",
49290b57cec5SDimitry Andric                   __kmp_gtid_from_thread(team->t.t_threads[f]), team->t.t_id, f,
49300b57cec5SDimitry Andric                   th->th.th_new_place, first_place, last_place));
49310b57cec5SDimitry Andric       }
49320b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(place == masters_place);
49330b57cec5SDimitry Andric     }
49340b57cec5SDimitry Andric   } break;
49350b57cec5SDimitry Andric 
49360b57cec5SDimitry Andric   case proc_bind_spread: {
49370b57cec5SDimitry Andric     int f;
49380b57cec5SDimitry Andric     int n_th = team->t.t_nproc;
49390b57cec5SDimitry Andric     int n_places;
49400b57cec5SDimitry Andric     int thidx;
49410b57cec5SDimitry Andric     if (first_place <= last_place) {
49420b57cec5SDimitry Andric       n_places = last_place - first_place + 1;
49430b57cec5SDimitry Andric     } else {
4944bdd1243dSDimitry Andric       n_places = num_masks - first_place + last_place + 1;
49450b57cec5SDimitry Andric     }
49460b57cec5SDimitry Andric     if (n_th <= n_places) {
49470b57cec5SDimitry Andric       int place = -1;
49480b57cec5SDimitry Andric 
4949bdd1243dSDimitry Andric       if (n_places != num_masks) {
49500b57cec5SDimitry Andric         int S = n_places / n_th;
49510b57cec5SDimitry Andric         int s_count, rem, gap, gap_ct;
49520b57cec5SDimitry Andric 
49530b57cec5SDimitry Andric         place = masters_place;
49540b57cec5SDimitry Andric         rem = n_places - n_th * S;
49550b57cec5SDimitry Andric         gap = rem ? n_th / rem : 1;
49560b57cec5SDimitry Andric         gap_ct = gap;
49570b57cec5SDimitry Andric         thidx = n_th;
49580b57cec5SDimitry Andric         if (update_master_only == 1)
49590b57cec5SDimitry Andric           thidx = 1;
49600b57cec5SDimitry Andric         for (f = 0; f < thidx; f++) {
49610b57cec5SDimitry Andric           kmp_info_t *th = team->t.t_threads[f];
49620b57cec5SDimitry Andric           KMP_DEBUG_ASSERT(th != NULL);
49630b57cec5SDimitry Andric 
49645f757f3fSDimitry Andric           int fplace = place, nplace = place;
49650b57cec5SDimitry Andric           s_count = 1;
49660b57cec5SDimitry Andric           while (s_count < S) {
49670b57cec5SDimitry Andric             if (place == last_place) {
49680b57cec5SDimitry Andric               place = first_place;
4969bdd1243dSDimitry Andric             } else if (place == (num_masks - 1)) {
49700b57cec5SDimitry Andric               place = 0;
49710b57cec5SDimitry Andric             } else {
49720b57cec5SDimitry Andric               place++;
49730b57cec5SDimitry Andric             }
49740b57cec5SDimitry Andric             s_count++;
49750b57cec5SDimitry Andric           }
49760b57cec5SDimitry Andric           if (rem && (gap_ct == gap)) {
49770b57cec5SDimitry Andric             if (place == last_place) {
49780b57cec5SDimitry Andric               place = first_place;
4979bdd1243dSDimitry Andric             } else if (place == (num_masks - 1)) {
49800b57cec5SDimitry Andric               place = 0;
49810b57cec5SDimitry Andric             } else {
49820b57cec5SDimitry Andric               place++;
49830b57cec5SDimitry Andric             }
49840b57cec5SDimitry Andric             rem--;
49850b57cec5SDimitry Andric             gap_ct = 0;
49860b57cec5SDimitry Andric           }
49875f757f3fSDimitry Andric           __kmp_set_thread_place(team, th, fplace, place, nplace);
49880b57cec5SDimitry Andric           gap_ct++;
49890b57cec5SDimitry Andric 
49900b57cec5SDimitry Andric           if (place == last_place) {
49910b57cec5SDimitry Andric             place = first_place;
4992bdd1243dSDimitry Andric           } else if (place == (num_masks - 1)) {
49930b57cec5SDimitry Andric             place = 0;
49940b57cec5SDimitry Andric           } else {
49950b57cec5SDimitry Andric             place++;
49960b57cec5SDimitry Andric           }
49970b57cec5SDimitry Andric 
49980b57cec5SDimitry Andric           KA_TRACE(100,
49990b57cec5SDimitry Andric                    ("__kmp_partition_places: spread: T#%d(%d:%d) place %d "
5000bdd1243dSDimitry Andric                     "partition = [%d,%d], num_masks: %u\n",
50010b57cec5SDimitry Andric                     __kmp_gtid_from_thread(team->t.t_threads[f]), team->t.t_id,
50020b57cec5SDimitry Andric                     f, th->th.th_new_place, th->th.th_first_place,
5003bdd1243dSDimitry Andric                     th->th.th_last_place, num_masks));
50040b57cec5SDimitry Andric         }
50050b57cec5SDimitry Andric       } else {
50060b57cec5SDimitry Andric         /* Having uniform space of available computation places I can create
50070b57cec5SDimitry Andric            T partitions of round(P/T) size and put threads into the first
50080b57cec5SDimitry Andric            place of each partition. */
50090b57cec5SDimitry Andric         double current = static_cast<double>(masters_place);
50100b57cec5SDimitry Andric         double spacing =
50110b57cec5SDimitry Andric             (static_cast<double>(n_places + 1) / static_cast<double>(n_th));
50120b57cec5SDimitry Andric         int first, last;
50130b57cec5SDimitry Andric         kmp_info_t *th;
50140b57cec5SDimitry Andric 
50150b57cec5SDimitry Andric         thidx = n_th + 1;
50160b57cec5SDimitry Andric         if (update_master_only == 1)
50170b57cec5SDimitry Andric           thidx = 1;
50180b57cec5SDimitry Andric         for (f = 0; f < thidx; f++) {
50190b57cec5SDimitry Andric           first = static_cast<int>(current);
50200b57cec5SDimitry Andric           last = static_cast<int>(current + spacing) - 1;
50210b57cec5SDimitry Andric           KMP_DEBUG_ASSERT(last >= first);
50220b57cec5SDimitry Andric           if (first >= n_places) {
50230b57cec5SDimitry Andric             if (masters_place) {
50240b57cec5SDimitry Andric               first -= n_places;
50250b57cec5SDimitry Andric               last -= n_places;
50260b57cec5SDimitry Andric               if (first == (masters_place + 1)) {
50270b57cec5SDimitry Andric                 KMP_DEBUG_ASSERT(f == n_th);
50280b57cec5SDimitry Andric                 first--;
50290b57cec5SDimitry Andric               }
50300b57cec5SDimitry Andric               if (last == masters_place) {
50310b57cec5SDimitry Andric                 KMP_DEBUG_ASSERT(f == (n_th - 1));
50320b57cec5SDimitry Andric                 last--;
50330b57cec5SDimitry Andric               }
50340b57cec5SDimitry Andric             } else {
50350b57cec5SDimitry Andric               KMP_DEBUG_ASSERT(f == n_th);
50360b57cec5SDimitry Andric               first = 0;
50370b57cec5SDimitry Andric               last = 0;
50380b57cec5SDimitry Andric             }
50390b57cec5SDimitry Andric           }
50400b57cec5SDimitry Andric           if (last >= n_places) {
50410b57cec5SDimitry Andric             last = (n_places - 1);
50420b57cec5SDimitry Andric           }
50430b57cec5SDimitry Andric           place = first;
50440b57cec5SDimitry Andric           current += spacing;
50450b57cec5SDimitry Andric           if (f < n_th) {
50460b57cec5SDimitry Andric             KMP_DEBUG_ASSERT(0 <= first);
50470b57cec5SDimitry Andric             KMP_DEBUG_ASSERT(n_places > first);
50480b57cec5SDimitry Andric             KMP_DEBUG_ASSERT(0 <= last);
50490b57cec5SDimitry Andric             KMP_DEBUG_ASSERT(n_places > last);
50500b57cec5SDimitry Andric             KMP_DEBUG_ASSERT(last_place >= first_place);
50510b57cec5SDimitry Andric             th = team->t.t_threads[f];
50520b57cec5SDimitry Andric             KMP_DEBUG_ASSERT(th);
50535f757f3fSDimitry Andric             __kmp_set_thread_place(team, th, first, last, place);
50540b57cec5SDimitry Andric             KA_TRACE(100,
50550b57cec5SDimitry Andric                      ("__kmp_partition_places: spread: T#%d(%d:%d) place %d "
50560b57cec5SDimitry Andric                       "partition = [%d,%d], spacing = %.4f\n",
50570b57cec5SDimitry Andric                       __kmp_gtid_from_thread(team->t.t_threads[f]),
50580b57cec5SDimitry Andric                       team->t.t_id, f, th->th.th_new_place,
50590b57cec5SDimitry Andric                       th->th.th_first_place, th->th.th_last_place, spacing));
50600b57cec5SDimitry Andric           }
50610b57cec5SDimitry Andric         }
50620b57cec5SDimitry Andric       }
50630b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(update_master_only || place == masters_place);
50640b57cec5SDimitry Andric     } else {
50650b57cec5SDimitry Andric       int S, rem, gap, s_count;
50660b57cec5SDimitry Andric       S = n_th / n_places;
50670b57cec5SDimitry Andric       s_count = 0;
50680b57cec5SDimitry Andric       rem = n_th - (S * n_places);
50690b57cec5SDimitry Andric       gap = rem > 0 ? n_places / rem : n_places;
50700b57cec5SDimitry Andric       int place = masters_place;
50710b57cec5SDimitry Andric       int gap_ct = gap;
50720b57cec5SDimitry Andric       thidx = n_th;
50730b57cec5SDimitry Andric       if (update_master_only == 1)
50740b57cec5SDimitry Andric         thidx = 1;
50750b57cec5SDimitry Andric       for (f = 0; f < thidx; f++) {
50760b57cec5SDimitry Andric         kmp_info_t *th = team->t.t_threads[f];
50770b57cec5SDimitry Andric         KMP_DEBUG_ASSERT(th != NULL);
50780b57cec5SDimitry Andric 
50795f757f3fSDimitry Andric         __kmp_set_thread_place(team, th, place, place, place);
50800b57cec5SDimitry Andric         s_count++;
50810b57cec5SDimitry Andric 
50820b57cec5SDimitry Andric         if ((s_count == S) && rem && (gap_ct == gap)) {
50830b57cec5SDimitry Andric           // do nothing, add an extra thread to place on next iteration
50840b57cec5SDimitry Andric         } else if ((s_count == S + 1) && rem && (gap_ct == gap)) {
50850b57cec5SDimitry Andric           // we added an extra thread to this place; move on to next place
50860b57cec5SDimitry Andric           if (place == last_place) {
50870b57cec5SDimitry Andric             place = first_place;
5088bdd1243dSDimitry Andric           } else if (place == (num_masks - 1)) {
50890b57cec5SDimitry Andric             place = 0;
50900b57cec5SDimitry Andric           } else {
50910b57cec5SDimitry Andric             place++;
50920b57cec5SDimitry Andric           }
50930b57cec5SDimitry Andric           s_count = 0;
50940b57cec5SDimitry Andric           gap_ct = 1;
50950b57cec5SDimitry Andric           rem--;
50960b57cec5SDimitry Andric         } else if (s_count == S) { // place is full; don't add extra thread
50970b57cec5SDimitry Andric           if (place == last_place) {
50980b57cec5SDimitry Andric             place = first_place;
5099bdd1243dSDimitry Andric           } else if (place == (num_masks - 1)) {
51000b57cec5SDimitry Andric             place = 0;
51010b57cec5SDimitry Andric           } else {
51020b57cec5SDimitry Andric             place++;
51030b57cec5SDimitry Andric           }
51040b57cec5SDimitry Andric           gap_ct++;
51050b57cec5SDimitry Andric           s_count = 0;
51060b57cec5SDimitry Andric         }
51070b57cec5SDimitry Andric 
51080b57cec5SDimitry Andric         KA_TRACE(100, ("__kmp_partition_places: spread: T#%d(%d:%d) place %d "
51090b57cec5SDimitry Andric                        "partition = [%d,%d]\n",
51100b57cec5SDimitry Andric                        __kmp_gtid_from_thread(team->t.t_threads[f]),
51110b57cec5SDimitry Andric                        team->t.t_id, f, th->th.th_new_place,
51120b57cec5SDimitry Andric                        th->th.th_first_place, th->th.th_last_place));
51130b57cec5SDimitry Andric       }
51140b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(update_master_only || place == masters_place);
51150b57cec5SDimitry Andric     }
51160b57cec5SDimitry Andric   } break;
51170b57cec5SDimitry Andric 
51180b57cec5SDimitry Andric   default:
51190b57cec5SDimitry Andric     break;
51200b57cec5SDimitry Andric   }
51210b57cec5SDimitry Andric 
51220b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_partition_places: exit T#%d\n", team->t.t_id));
51230b57cec5SDimitry Andric }
51240b57cec5SDimitry Andric 
51250b57cec5SDimitry Andric #endif // KMP_AFFINITY_SUPPORTED
51260b57cec5SDimitry Andric 
51270b57cec5SDimitry Andric /* allocate a new team data structure to use.  take one off of the free pool if
51280b57cec5SDimitry Andric    available */
51290b57cec5SDimitry Andric kmp_team_t *
__kmp_allocate_team(kmp_root_t * root,int new_nproc,int max_nproc,ompt_data_t ompt_parallel_data,kmp_proc_bind_t new_proc_bind,kmp_internal_control_t * new_icvs,int argc USE_NESTED_HOT_ARG (kmp_info_t * master))51300b57cec5SDimitry Andric __kmp_allocate_team(kmp_root_t *root, int new_nproc, int max_nproc,
51310b57cec5SDimitry Andric #if OMPT_SUPPORT
51320b57cec5SDimitry Andric                     ompt_data_t ompt_parallel_data,
51330b57cec5SDimitry Andric #endif
51340b57cec5SDimitry Andric                     kmp_proc_bind_t new_proc_bind,
51350b57cec5SDimitry Andric                     kmp_internal_control_t *new_icvs,
51360b57cec5SDimitry Andric                     int argc USE_NESTED_HOT_ARG(kmp_info_t *master)) {
51370b57cec5SDimitry Andric   KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(KMP_allocate_team);
51380b57cec5SDimitry Andric   int f;
51390b57cec5SDimitry Andric   kmp_team_t *team;
51400b57cec5SDimitry Andric   int use_hot_team = !root->r.r_active;
51410b57cec5SDimitry Andric   int level = 0;
5142349cc55cSDimitry Andric   int do_place_partition = 1;
51430b57cec5SDimitry Andric 
51440b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_allocate_team: called\n"));
51450b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(new_nproc >= 1 && argc >= 0);
51460b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(max_nproc >= new_nproc);
51470b57cec5SDimitry Andric   KMP_MB();
51480b57cec5SDimitry Andric 
51490b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
51500b57cec5SDimitry Andric   kmp_hot_team_ptr_t *hot_teams;
51510b57cec5SDimitry Andric   if (master) {
51520b57cec5SDimitry Andric     team = master->th.th_team;
51530b57cec5SDimitry Andric     level = team->t.t_active_level;
51540b57cec5SDimitry Andric     if (master->th.th_teams_microtask) { // in teams construct?
51550b57cec5SDimitry Andric       if (master->th.th_teams_size.nteams > 1 &&
51560b57cec5SDimitry Andric           ( // #teams > 1
51570b57cec5SDimitry Andric               team->t.t_pkfn ==
51580b57cec5SDimitry Andric                   (microtask_t)__kmp_teams_master || // inner fork of the teams
51590b57cec5SDimitry Andric               master->th.th_teams_level <
51600b57cec5SDimitry Andric                   team->t.t_level)) { // or nested parallel inside the teams
51610b57cec5SDimitry Andric         ++level; // not increment if #teams==1, or for outer fork of the teams;
51620b57cec5SDimitry Andric         // increment otherwise
51630b57cec5SDimitry Andric       }
5164349cc55cSDimitry Andric       // Do not perform the place partition if inner fork of the teams
5165349cc55cSDimitry Andric       // Wait until nested parallel region encountered inside teams construct
5166349cc55cSDimitry Andric       if ((master->th.th_teams_size.nteams == 1 &&
5167349cc55cSDimitry Andric            master->th.th_teams_level >= team->t.t_level) ||
5168349cc55cSDimitry Andric           (team->t.t_pkfn == (microtask_t)__kmp_teams_master))
5169349cc55cSDimitry Andric         do_place_partition = 0;
51700b57cec5SDimitry Andric     }
51710b57cec5SDimitry Andric     hot_teams = master->th.th_hot_teams;
51720b57cec5SDimitry Andric     if (level < __kmp_hot_teams_max_level && hot_teams &&
5173e8d8bef9SDimitry Andric         hot_teams[level].hot_team) {
5174e8d8bef9SDimitry Andric       // hot team has already been allocated for given level
51750b57cec5SDimitry Andric       use_hot_team = 1;
51760b57cec5SDimitry Andric     } else {
51770b57cec5SDimitry Andric       use_hot_team = 0;
51780b57cec5SDimitry Andric     }
5179e8d8bef9SDimitry Andric   } else {
5180e8d8bef9SDimitry Andric     // check we won't access uninitialized hot_teams, just in case
5181e8d8bef9SDimitry Andric     KMP_DEBUG_ASSERT(new_nproc == 1);
51820b57cec5SDimitry Andric   }
51830b57cec5SDimitry Andric #endif
51840b57cec5SDimitry Andric   // Optimization to use a "hot" team
51850b57cec5SDimitry Andric   if (use_hot_team && new_nproc > 1) {
51860b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(new_nproc <= max_nproc);
51870b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
51880b57cec5SDimitry Andric     team = hot_teams[level].hot_team;
51890b57cec5SDimitry Andric #else
51900b57cec5SDimitry Andric     team = root->r.r_hot_team;
51910b57cec5SDimitry Andric #endif
51920b57cec5SDimitry Andric #if KMP_DEBUG
51930b57cec5SDimitry Andric     if (__kmp_tasking_mode != tskm_immediate_exec) {
51940b57cec5SDimitry Andric       KA_TRACE(20, ("__kmp_allocate_team: hot team task_team[0] = %p "
51950b57cec5SDimitry Andric                     "task_team[1] = %p before reinit\n",
51960b57cec5SDimitry Andric                     team->t.t_task_team[0], team->t.t_task_team[1]));
51970b57cec5SDimitry Andric     }
51980b57cec5SDimitry Andric #endif
51990b57cec5SDimitry Andric 
5200349cc55cSDimitry Andric     if (team->t.t_nproc != new_nproc &&
5201349cc55cSDimitry Andric         __kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5202349cc55cSDimitry Andric       // Distributed barrier may need a resize
5203349cc55cSDimitry Andric       int old_nthr = team->t.t_nproc;
5204349cc55cSDimitry Andric       __kmp_resize_dist_barrier(team, old_nthr, new_nproc);
5205349cc55cSDimitry Andric     }
5206349cc55cSDimitry Andric 
5207349cc55cSDimitry Andric     // If not doing the place partition, then reset the team's proc bind
5208349cc55cSDimitry Andric     // to indicate that partitioning of all threads still needs to take place
5209349cc55cSDimitry Andric     if (do_place_partition == 0)
5210349cc55cSDimitry Andric       team->t.t_proc_bind = proc_bind_default;
52110b57cec5SDimitry Andric     // Has the number of threads changed?
52120b57cec5SDimitry Andric     /* Let's assume the most common case is that the number of threads is
52130b57cec5SDimitry Andric        unchanged, and put that case first. */
52140b57cec5SDimitry Andric     if (team->t.t_nproc == new_nproc) { // Check changes in number of threads
52150b57cec5SDimitry Andric       KA_TRACE(20, ("__kmp_allocate_team: reusing hot team\n"));
52160b57cec5SDimitry Andric       // This case can mean that omp_set_num_threads() was called and the hot
52170b57cec5SDimitry Andric       // team size was already reduced, so we check the special flag
52180b57cec5SDimitry Andric       if (team->t.t_size_changed == -1) {
52190b57cec5SDimitry Andric         team->t.t_size_changed = 1;
52200b57cec5SDimitry Andric       } else {
52210b57cec5SDimitry Andric         KMP_CHECK_UPDATE(team->t.t_size_changed, 0);
52220b57cec5SDimitry Andric       }
52230b57cec5SDimitry Andric 
52240b57cec5SDimitry Andric       // TODO???: team->t.t_max_active_levels = new_max_active_levels;
52250b57cec5SDimitry Andric       kmp_r_sched_t new_sched = new_icvs->sched;
5226fe6060f1SDimitry Andric       // set primary thread's schedule as new run-time schedule
52270b57cec5SDimitry Andric       KMP_CHECK_UPDATE(team->t.t_sched.sched, new_sched.sched);
52280b57cec5SDimitry Andric 
52290b57cec5SDimitry Andric       __kmp_reinitialize_team(team, new_icvs,
52300b57cec5SDimitry Andric                               root->r.r_uber_thread->th.th_ident);
52310b57cec5SDimitry Andric 
52320b57cec5SDimitry Andric       KF_TRACE(10, ("__kmp_allocate_team2: T#%d, this_thread=%p team=%p\n", 0,
52330b57cec5SDimitry Andric                     team->t.t_threads[0], team));
52340b57cec5SDimitry Andric       __kmp_push_current_task_to_thread(team->t.t_threads[0], team, 0);
52350b57cec5SDimitry Andric 
52360b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
52370b57cec5SDimitry Andric       if ((team->t.t_size_changed == 0) &&
52380b57cec5SDimitry Andric           (team->t.t_proc_bind == new_proc_bind)) {
52390b57cec5SDimitry Andric         if (new_proc_bind == proc_bind_spread) {
5240349cc55cSDimitry Andric           if (do_place_partition) {
5241349cc55cSDimitry Andric             // add flag to update only master for spread
5242349cc55cSDimitry Andric             __kmp_partition_places(team, 1);
5243349cc55cSDimitry Andric           }
52440b57cec5SDimitry Andric         }
52450b57cec5SDimitry Andric         KA_TRACE(200, ("__kmp_allocate_team: reusing hot team #%d bindings: "
52460b57cec5SDimitry Andric                        "proc_bind = %d, partition = [%d,%d]\n",
52470b57cec5SDimitry Andric                        team->t.t_id, new_proc_bind, team->t.t_first_place,
52480b57cec5SDimitry Andric                        team->t.t_last_place));
52490b57cec5SDimitry Andric       } else {
5250349cc55cSDimitry Andric         if (do_place_partition) {
52510b57cec5SDimitry Andric           KMP_CHECK_UPDATE(team->t.t_proc_bind, new_proc_bind);
52520b57cec5SDimitry Andric           __kmp_partition_places(team);
52530b57cec5SDimitry Andric         }
5254349cc55cSDimitry Andric       }
52550b57cec5SDimitry Andric #else
52560b57cec5SDimitry Andric       KMP_CHECK_UPDATE(team->t.t_proc_bind, new_proc_bind);
52570b57cec5SDimitry Andric #endif /* KMP_AFFINITY_SUPPORTED */
52580b57cec5SDimitry Andric     } else if (team->t.t_nproc > new_nproc) {
52590b57cec5SDimitry Andric       KA_TRACE(20,
52600b57cec5SDimitry Andric                ("__kmp_allocate_team: decreasing hot team thread count to %d\n",
52610b57cec5SDimitry Andric                 new_nproc));
52620b57cec5SDimitry Andric 
52630b57cec5SDimitry Andric       team->t.t_size_changed = 1;
5264349cc55cSDimitry Andric       if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5265349cc55cSDimitry Andric         // Barrier size already reduced earlier in this function
5266349cc55cSDimitry Andric         // Activate team threads via th_used_in_team
5267349cc55cSDimitry Andric         __kmp_add_threads_to_team(team, new_nproc);
5268349cc55cSDimitry Andric       }
52690b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
52700b57cec5SDimitry Andric       if (__kmp_hot_teams_mode == 0) {
52710b57cec5SDimitry Andric         // AC: saved number of threads should correspond to team's value in this
52720b57cec5SDimitry Andric         // mode, can be bigger in mode 1, when hot team has threads in reserve
52730b57cec5SDimitry Andric         KMP_DEBUG_ASSERT(hot_teams[level].hot_team_nth == team->t.t_nproc);
52740b57cec5SDimitry Andric         hot_teams[level].hot_team_nth = new_nproc;
52750b57cec5SDimitry Andric #endif // KMP_NESTED_HOT_TEAMS
52760b57cec5SDimitry Andric         /* release the extra threads we don't need any more */
52770b57cec5SDimitry Andric         for (f = new_nproc; f < team->t.t_nproc; f++) {
52780b57cec5SDimitry Andric           KMP_DEBUG_ASSERT(team->t.t_threads[f]);
52790b57cec5SDimitry Andric           if (__kmp_tasking_mode != tskm_immediate_exec) {
52800b57cec5SDimitry Andric             // When decreasing team size, threads no longer in the team should
52810b57cec5SDimitry Andric             // unref task team.
52820b57cec5SDimitry Andric             team->t.t_threads[f]->th.th_task_team = NULL;
52830b57cec5SDimitry Andric           }
52840b57cec5SDimitry Andric           __kmp_free_thread(team->t.t_threads[f]);
52850b57cec5SDimitry Andric           team->t.t_threads[f] = NULL;
52860b57cec5SDimitry Andric         }
52870b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
52880b57cec5SDimitry Andric       } // (__kmp_hot_teams_mode == 0)
52890b57cec5SDimitry Andric       else {
52900b57cec5SDimitry Andric         // When keeping extra threads in team, switch threads to wait on own
52910b57cec5SDimitry Andric         // b_go flag
52920b57cec5SDimitry Andric         for (f = new_nproc; f < team->t.t_nproc; ++f) {
52930b57cec5SDimitry Andric           KMP_DEBUG_ASSERT(team->t.t_threads[f]);
52940b57cec5SDimitry Andric           kmp_balign_t *balign = team->t.t_threads[f]->th.th_bar;
52950b57cec5SDimitry Andric           for (int b = 0; b < bs_last_barrier; ++b) {
52960b57cec5SDimitry Andric             if (balign[b].bb.wait_flag == KMP_BARRIER_PARENT_FLAG) {
52970b57cec5SDimitry Andric               balign[b].bb.wait_flag = KMP_BARRIER_SWITCH_TO_OWN_FLAG;
52980b57cec5SDimitry Andric             }
52990b57cec5SDimitry Andric             KMP_CHECK_UPDATE(balign[b].bb.leaf_kids, 0);
53000b57cec5SDimitry Andric           }
53010b57cec5SDimitry Andric         }
53020b57cec5SDimitry Andric       }
53030b57cec5SDimitry Andric #endif // KMP_NESTED_HOT_TEAMS
53040b57cec5SDimitry Andric       team->t.t_nproc = new_nproc;
53050b57cec5SDimitry Andric       // TODO???: team->t.t_max_active_levels = new_max_active_levels;
53060b57cec5SDimitry Andric       KMP_CHECK_UPDATE(team->t.t_sched.sched, new_icvs->sched.sched);
53070b57cec5SDimitry Andric       __kmp_reinitialize_team(team, new_icvs,
53080b57cec5SDimitry Andric                               root->r.r_uber_thread->th.th_ident);
53090b57cec5SDimitry Andric 
53100b57cec5SDimitry Andric       // Update remaining threads
53110b57cec5SDimitry Andric       for (f = 0; f < new_nproc; ++f) {
53120b57cec5SDimitry Andric         team->t.t_threads[f]->th.th_team_nproc = new_nproc;
53130b57cec5SDimitry Andric       }
53140b57cec5SDimitry Andric 
5315fe6060f1SDimitry Andric       // restore the current task state of the primary thread: should be the
53160b57cec5SDimitry Andric       // implicit task
53170b57cec5SDimitry Andric       KF_TRACE(10, ("__kmp_allocate_team: T#%d, this_thread=%p team=%p\n", 0,
53180b57cec5SDimitry Andric                     team->t.t_threads[0], team));
53190b57cec5SDimitry Andric 
53200b57cec5SDimitry Andric       __kmp_push_current_task_to_thread(team->t.t_threads[0], team, 0);
53210b57cec5SDimitry Andric 
53220b57cec5SDimitry Andric #ifdef KMP_DEBUG
53230b57cec5SDimitry Andric       for (f = 0; f < team->t.t_nproc; f++) {
53240b57cec5SDimitry Andric         KMP_DEBUG_ASSERT(team->t.t_threads[f] &&
53250b57cec5SDimitry Andric                          team->t.t_threads[f]->th.th_team_nproc ==
53260b57cec5SDimitry Andric                              team->t.t_nproc);
53270b57cec5SDimitry Andric       }
53280b57cec5SDimitry Andric #endif
53290b57cec5SDimitry Andric 
5330349cc55cSDimitry Andric       if (do_place_partition) {
53310b57cec5SDimitry Andric         KMP_CHECK_UPDATE(team->t.t_proc_bind, new_proc_bind);
53320b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
53330b57cec5SDimitry Andric         __kmp_partition_places(team);
53340b57cec5SDimitry Andric #endif
5335349cc55cSDimitry Andric       }
53360b57cec5SDimitry Andric     } else { // team->t.t_nproc < new_nproc
53370b57cec5SDimitry Andric 
53380b57cec5SDimitry Andric       KA_TRACE(20,
53390b57cec5SDimitry Andric                ("__kmp_allocate_team: increasing hot team thread count to %d\n",
53400b57cec5SDimitry Andric                 new_nproc));
5341349cc55cSDimitry Andric       int old_nproc = team->t.t_nproc; // save old value and use to update only
53420b57cec5SDimitry Andric       team->t.t_size_changed = 1;
53430b57cec5SDimitry Andric 
53440b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
53450b57cec5SDimitry Andric       int avail_threads = hot_teams[level].hot_team_nth;
53460b57cec5SDimitry Andric       if (new_nproc < avail_threads)
53470b57cec5SDimitry Andric         avail_threads = new_nproc;
53480b57cec5SDimitry Andric       kmp_info_t **other_threads = team->t.t_threads;
53490b57cec5SDimitry Andric       for (f = team->t.t_nproc; f < avail_threads; ++f) {
53500b57cec5SDimitry Andric         // Adjust barrier data of reserved threads (if any) of the team
53510b57cec5SDimitry Andric         // Other data will be set in __kmp_initialize_info() below.
53520b57cec5SDimitry Andric         int b;
53530b57cec5SDimitry Andric         kmp_balign_t *balign = other_threads[f]->th.th_bar;
53540b57cec5SDimitry Andric         for (b = 0; b < bs_last_barrier; ++b) {
53550b57cec5SDimitry Andric           balign[b].bb.b_arrived = team->t.t_bar[b].b_arrived;
53560b57cec5SDimitry Andric           KMP_DEBUG_ASSERT(balign[b].bb.wait_flag != KMP_BARRIER_PARENT_FLAG);
53570b57cec5SDimitry Andric #if USE_DEBUGGER
53580b57cec5SDimitry Andric           balign[b].bb.b_worker_arrived = team->t.t_bar[b].b_team_arrived;
53590b57cec5SDimitry Andric #endif
53600b57cec5SDimitry Andric         }
53610b57cec5SDimitry Andric       }
53620b57cec5SDimitry Andric       if (hot_teams[level].hot_team_nth >= new_nproc) {
53630b57cec5SDimitry Andric         // we have all needed threads in reserve, no need to allocate any
53640b57cec5SDimitry Andric         // this only possible in mode 1, cannot have reserved threads in mode 0
53650b57cec5SDimitry Andric         KMP_DEBUG_ASSERT(__kmp_hot_teams_mode == 1);
53660b57cec5SDimitry Andric         team->t.t_nproc = new_nproc; // just get reserved threads involved
53670b57cec5SDimitry Andric       } else {
5368349cc55cSDimitry Andric         // We may have some threads in reserve, but not enough;
5369349cc55cSDimitry Andric         // get reserved threads involved if any.
5370349cc55cSDimitry Andric         team->t.t_nproc = hot_teams[level].hot_team_nth;
53710b57cec5SDimitry Andric         hot_teams[level].hot_team_nth = new_nproc; // adjust hot team max size
53720b57cec5SDimitry Andric #endif // KMP_NESTED_HOT_TEAMS
53730b57cec5SDimitry Andric         if (team->t.t_max_nproc < new_nproc) {
53740b57cec5SDimitry Andric           /* reallocate larger arrays */
53750b57cec5SDimitry Andric           __kmp_reallocate_team_arrays(team, new_nproc);
53760b57cec5SDimitry Andric           __kmp_reinitialize_team(team, new_icvs, NULL);
53770b57cec5SDimitry Andric         }
53780b57cec5SDimitry Andric 
5379489b1cf2SDimitry Andric #if (KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED
5380fe6060f1SDimitry Andric         /* Temporarily set full mask for primary thread before creation of
5381fe6060f1SDimitry Andric            workers. The reason is that workers inherit the affinity from the
5382fe6060f1SDimitry Andric            primary thread, so if a lot of workers are created on the single
5383fe6060f1SDimitry Andric            core quickly, they don't get a chance to set their own affinity for
5384fe6060f1SDimitry Andric            a long time. */
538506c3fb27SDimitry Andric         kmp_affinity_raii_t new_temp_affinity{__kmp_affin_fullMask};
53860b57cec5SDimitry Andric #endif
53870b57cec5SDimitry Andric 
53880b57cec5SDimitry Andric         /* allocate new threads for the hot team */
53890b57cec5SDimitry Andric         for (f = team->t.t_nproc; f < new_nproc; f++) {
53900b57cec5SDimitry Andric           kmp_info_t *new_worker = __kmp_allocate_thread(root, team, f);
53910b57cec5SDimitry Andric           KMP_DEBUG_ASSERT(new_worker);
53920b57cec5SDimitry Andric           team->t.t_threads[f] = new_worker;
53930b57cec5SDimitry Andric 
53940b57cec5SDimitry Andric           KA_TRACE(20,
53950b57cec5SDimitry Andric                    ("__kmp_allocate_team: team %d init T#%d arrived: "
53960b57cec5SDimitry Andric                     "join=%llu, plain=%llu\n",
53970b57cec5SDimitry Andric                     team->t.t_id, __kmp_gtid_from_tid(f, team), team->t.t_id, f,
53980b57cec5SDimitry Andric                     team->t.t_bar[bs_forkjoin_barrier].b_arrived,
53990b57cec5SDimitry Andric                     team->t.t_bar[bs_plain_barrier].b_arrived));
54000b57cec5SDimitry Andric 
54010b57cec5SDimitry Andric           { // Initialize barrier data for new threads.
54020b57cec5SDimitry Andric             int b;
54030b57cec5SDimitry Andric             kmp_balign_t *balign = new_worker->th.th_bar;
54040b57cec5SDimitry Andric             for (b = 0; b < bs_last_barrier; ++b) {
54050b57cec5SDimitry Andric               balign[b].bb.b_arrived = team->t.t_bar[b].b_arrived;
54060b57cec5SDimitry Andric               KMP_DEBUG_ASSERT(balign[b].bb.wait_flag !=
54070b57cec5SDimitry Andric                                KMP_BARRIER_PARENT_FLAG);
54080b57cec5SDimitry Andric #if USE_DEBUGGER
54090b57cec5SDimitry Andric               balign[b].bb.b_worker_arrived = team->t.t_bar[b].b_team_arrived;
54100b57cec5SDimitry Andric #endif
54110b57cec5SDimitry Andric             }
54120b57cec5SDimitry Andric           }
54130b57cec5SDimitry Andric         }
54140b57cec5SDimitry Andric 
5415489b1cf2SDimitry Andric #if (KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED
5416fe6060f1SDimitry Andric         /* Restore initial primary thread's affinity mask */
541706c3fb27SDimitry Andric         new_temp_affinity.restore();
54180b57cec5SDimitry Andric #endif
54190b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
54200b57cec5SDimitry Andric       } // end of check of t_nproc vs. new_nproc vs. hot_team_nth
54210b57cec5SDimitry Andric #endif // KMP_NESTED_HOT_TEAMS
5422349cc55cSDimitry Andric       if (__kmp_barrier_release_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5423349cc55cSDimitry Andric         // Barrier size already increased earlier in this function
5424349cc55cSDimitry Andric         // Activate team threads via th_used_in_team
5425349cc55cSDimitry Andric         __kmp_add_threads_to_team(team, new_nproc);
5426349cc55cSDimitry Andric       }
54270b57cec5SDimitry Andric       /* make sure everyone is syncronized */
54280b57cec5SDimitry Andric       // new threads below
54290b57cec5SDimitry Andric       __kmp_initialize_team(team, new_nproc, new_icvs,
54300b57cec5SDimitry Andric                             root->r.r_uber_thread->th.th_ident);
54310b57cec5SDimitry Andric 
54320b57cec5SDimitry Andric       /* reinitialize the threads */
54330b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(team->t.t_nproc == new_nproc);
54340b57cec5SDimitry Andric       for (f = 0; f < team->t.t_nproc; ++f)
54350b57cec5SDimitry Andric         __kmp_initialize_info(team->t.t_threads[f], team, f,
54360b57cec5SDimitry Andric                               __kmp_gtid_from_tid(f, team));
54370b57cec5SDimitry Andric 
543806c3fb27SDimitry Andric       // set th_task_state for new threads in hot team with older thread's state
543906c3fb27SDimitry Andric       kmp_uint8 old_state = team->t.t_threads[old_nproc - 1]->th.th_task_state;
54400b57cec5SDimitry Andric       for (f = old_nproc; f < team->t.t_nproc; ++f)
54410b57cec5SDimitry Andric         team->t.t_threads[f]->th.th_task_state = old_state;
54420b57cec5SDimitry Andric 
54430b57cec5SDimitry Andric #ifdef KMP_DEBUG
54440b57cec5SDimitry Andric       for (f = 0; f < team->t.t_nproc; ++f) {
54450b57cec5SDimitry Andric         KMP_DEBUG_ASSERT(team->t.t_threads[f] &&
54460b57cec5SDimitry Andric                          team->t.t_threads[f]->th.th_team_nproc ==
54470b57cec5SDimitry Andric                              team->t.t_nproc);
54480b57cec5SDimitry Andric       }
54490b57cec5SDimitry Andric #endif
54500b57cec5SDimitry Andric 
5451349cc55cSDimitry Andric       if (do_place_partition) {
54520b57cec5SDimitry Andric         KMP_CHECK_UPDATE(team->t.t_proc_bind, new_proc_bind);
54530b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
54540b57cec5SDimitry Andric         __kmp_partition_places(team);
54550b57cec5SDimitry Andric #endif
5456349cc55cSDimitry Andric       }
54570b57cec5SDimitry Andric     } // Check changes in number of threads
54580b57cec5SDimitry Andric 
54590b57cec5SDimitry Andric     kmp_info_t *master = team->t.t_threads[0];
54600b57cec5SDimitry Andric     if (master->th.th_teams_microtask) {
54610b57cec5SDimitry Andric       for (f = 1; f < new_nproc; ++f) {
54620b57cec5SDimitry Andric         // propagate teams construct specific info to workers
54630b57cec5SDimitry Andric         kmp_info_t *thr = team->t.t_threads[f];
54640b57cec5SDimitry Andric         thr->th.th_teams_microtask = master->th.th_teams_microtask;
54650b57cec5SDimitry Andric         thr->th.th_teams_level = master->th.th_teams_level;
54660b57cec5SDimitry Andric         thr->th.th_teams_size = master->th.th_teams_size;
54670b57cec5SDimitry Andric       }
54680b57cec5SDimitry Andric     }
54690b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
54700b57cec5SDimitry Andric     if (level) {
54710b57cec5SDimitry Andric       // Sync barrier state for nested hot teams, not needed for outermost hot
54720b57cec5SDimitry Andric       // team.
54730b57cec5SDimitry Andric       for (f = 1; f < new_nproc; ++f) {
54740b57cec5SDimitry Andric         kmp_info_t *thr = team->t.t_threads[f];
54750b57cec5SDimitry Andric         int b;
54760b57cec5SDimitry Andric         kmp_balign_t *balign = thr->th.th_bar;
54770b57cec5SDimitry Andric         for (b = 0; b < bs_last_barrier; ++b) {
54780b57cec5SDimitry Andric           balign[b].bb.b_arrived = team->t.t_bar[b].b_arrived;
54790b57cec5SDimitry Andric           KMP_DEBUG_ASSERT(balign[b].bb.wait_flag != KMP_BARRIER_PARENT_FLAG);
54800b57cec5SDimitry Andric #if USE_DEBUGGER
54810b57cec5SDimitry Andric           balign[b].bb.b_worker_arrived = team->t.t_bar[b].b_team_arrived;
54820b57cec5SDimitry Andric #endif
54830b57cec5SDimitry Andric         }
54840b57cec5SDimitry Andric       }
54850b57cec5SDimitry Andric     }
54860b57cec5SDimitry Andric #endif // KMP_NESTED_HOT_TEAMS
54870b57cec5SDimitry Andric 
54880b57cec5SDimitry Andric     /* reallocate space for arguments if necessary */
54890b57cec5SDimitry Andric     __kmp_alloc_argv_entries(argc, team, TRUE);
54900b57cec5SDimitry Andric     KMP_CHECK_UPDATE(team->t.t_argc, argc);
54910b57cec5SDimitry Andric     // The hot team re-uses the previous task team,
54920b57cec5SDimitry Andric     // if untouched during the previous release->gather phase.
54930b57cec5SDimitry Andric 
54940b57cec5SDimitry Andric     KF_TRACE(10, (" hot_team = %p\n", team));
54950b57cec5SDimitry Andric 
54960b57cec5SDimitry Andric #if KMP_DEBUG
54970b57cec5SDimitry Andric     if (__kmp_tasking_mode != tskm_immediate_exec) {
54980b57cec5SDimitry Andric       KA_TRACE(20, ("__kmp_allocate_team: hot team task_team[0] = %p "
54990b57cec5SDimitry Andric                     "task_team[1] = %p after reinit\n",
55000b57cec5SDimitry Andric                     team->t.t_task_team[0], team->t.t_task_team[1]));
55010b57cec5SDimitry Andric     }
55020b57cec5SDimitry Andric #endif
55030b57cec5SDimitry Andric 
55040b57cec5SDimitry Andric #if OMPT_SUPPORT
55050b57cec5SDimitry Andric     __ompt_team_assign_id(team, ompt_parallel_data);
55060b57cec5SDimitry Andric #endif
55070b57cec5SDimitry Andric 
55080b57cec5SDimitry Andric     KMP_MB();
55090b57cec5SDimitry Andric 
55100b57cec5SDimitry Andric     return team;
55110b57cec5SDimitry Andric   }
55120b57cec5SDimitry Andric 
55130b57cec5SDimitry Andric   /* next, let's try to take one from the team pool */
55140b57cec5SDimitry Andric   KMP_MB();
55150b57cec5SDimitry Andric   for (team = CCAST(kmp_team_t *, __kmp_team_pool); (team);) {
55160b57cec5SDimitry Andric     /* TODO: consider resizing undersized teams instead of reaping them, now
55170b57cec5SDimitry Andric        that we have a resizing mechanism */
55180b57cec5SDimitry Andric     if (team->t.t_max_nproc >= max_nproc) {
55190b57cec5SDimitry Andric       /* take this team from the team pool */
55200b57cec5SDimitry Andric       __kmp_team_pool = team->t.t_next_pool;
55210b57cec5SDimitry Andric 
5522349cc55cSDimitry Andric       if (max_nproc > 1 &&
5523349cc55cSDimitry Andric           __kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5524349cc55cSDimitry Andric         if (!team->t.b) { // Allocate barrier structure
5525349cc55cSDimitry Andric           team->t.b = distributedBarrier::allocate(__kmp_dflt_team_nth_ub);
5526349cc55cSDimitry Andric         }
5527349cc55cSDimitry Andric       }
5528349cc55cSDimitry Andric 
55290b57cec5SDimitry Andric       /* setup the team for fresh use */
55300b57cec5SDimitry Andric       __kmp_initialize_team(team, new_nproc, new_icvs, NULL);
55310b57cec5SDimitry Andric 
55320b57cec5SDimitry Andric       KA_TRACE(20, ("__kmp_allocate_team: setting task_team[0] %p and "
55330b57cec5SDimitry Andric                     "task_team[1] %p to NULL\n",
55340b57cec5SDimitry Andric                     &team->t.t_task_team[0], &team->t.t_task_team[1]));
55350b57cec5SDimitry Andric       team->t.t_task_team[0] = NULL;
55360b57cec5SDimitry Andric       team->t.t_task_team[1] = NULL;
55370b57cec5SDimitry Andric 
55380b57cec5SDimitry Andric       /* reallocate space for arguments if necessary */
55390b57cec5SDimitry Andric       __kmp_alloc_argv_entries(argc, team, TRUE);
55400b57cec5SDimitry Andric       KMP_CHECK_UPDATE(team->t.t_argc, argc);
55410b57cec5SDimitry Andric 
55420b57cec5SDimitry Andric       KA_TRACE(
55430b57cec5SDimitry Andric           20, ("__kmp_allocate_team: team %d init arrived: join=%u, plain=%u\n",
55440b57cec5SDimitry Andric                team->t.t_id, KMP_INIT_BARRIER_STATE, KMP_INIT_BARRIER_STATE));
55450b57cec5SDimitry Andric       { // Initialize barrier data.
55460b57cec5SDimitry Andric         int b;
55470b57cec5SDimitry Andric         for (b = 0; b < bs_last_barrier; ++b) {
55480b57cec5SDimitry Andric           team->t.t_bar[b].b_arrived = KMP_INIT_BARRIER_STATE;
55490b57cec5SDimitry Andric #if USE_DEBUGGER
55500b57cec5SDimitry Andric           team->t.t_bar[b].b_master_arrived = 0;
55510b57cec5SDimitry Andric           team->t.t_bar[b].b_team_arrived = 0;
55520b57cec5SDimitry Andric #endif
55530b57cec5SDimitry Andric         }
55540b57cec5SDimitry Andric       }
55550b57cec5SDimitry Andric 
55560b57cec5SDimitry Andric       team->t.t_proc_bind = new_proc_bind;
55570b57cec5SDimitry Andric 
55580b57cec5SDimitry Andric       KA_TRACE(20, ("__kmp_allocate_team: using team from pool %d.\n",
55590b57cec5SDimitry Andric                     team->t.t_id));
55600b57cec5SDimitry Andric 
55610b57cec5SDimitry Andric #if OMPT_SUPPORT
55620b57cec5SDimitry Andric       __ompt_team_assign_id(team, ompt_parallel_data);
55630b57cec5SDimitry Andric #endif
55640b57cec5SDimitry Andric 
55650b57cec5SDimitry Andric       KMP_MB();
55660b57cec5SDimitry Andric 
55670b57cec5SDimitry Andric       return team;
55680b57cec5SDimitry Andric     }
55690b57cec5SDimitry Andric 
55700b57cec5SDimitry Andric     /* reap team if it is too small, then loop back and check the next one */
55710b57cec5SDimitry Andric     // not sure if this is wise, but, will be redone during the hot-teams
55720b57cec5SDimitry Andric     // rewrite.
55730b57cec5SDimitry Andric     /* TODO: Use technique to find the right size hot-team, don't reap them */
55740b57cec5SDimitry Andric     team = __kmp_reap_team(team);
55750b57cec5SDimitry Andric     __kmp_team_pool = team;
55760b57cec5SDimitry Andric   }
55770b57cec5SDimitry Andric 
55780b57cec5SDimitry Andric   /* nothing available in the pool, no matter, make a new team! */
55790b57cec5SDimitry Andric   KMP_MB();
55800b57cec5SDimitry Andric   team = (kmp_team_t *)__kmp_allocate(sizeof(kmp_team_t));
55810b57cec5SDimitry Andric 
55820b57cec5SDimitry Andric   /* and set it up */
55830b57cec5SDimitry Andric   team->t.t_max_nproc = max_nproc;
5584349cc55cSDimitry Andric   if (max_nproc > 1 &&
5585349cc55cSDimitry Andric       __kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5586349cc55cSDimitry Andric     // Allocate barrier structure
5587349cc55cSDimitry Andric     team->t.b = distributedBarrier::allocate(__kmp_dflt_team_nth_ub);
5588349cc55cSDimitry Andric   }
5589349cc55cSDimitry Andric 
55900b57cec5SDimitry Andric   /* NOTE well, for some reason allocating one big buffer and dividing it up
55910b57cec5SDimitry Andric      seems to really hurt performance a lot on the P4, so, let's not use this */
55920b57cec5SDimitry Andric   __kmp_allocate_team_arrays(team, max_nproc);
55930b57cec5SDimitry Andric 
55940b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_allocate_team: making a new team\n"));
55950b57cec5SDimitry Andric   __kmp_initialize_team(team, new_nproc, new_icvs, NULL);
55960b57cec5SDimitry Andric 
55970b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_allocate_team: setting task_team[0] %p and task_team[1] "
55980b57cec5SDimitry Andric                 "%p to NULL\n",
55990b57cec5SDimitry Andric                 &team->t.t_task_team[0], &team->t.t_task_team[1]));
56000b57cec5SDimitry Andric   team->t.t_task_team[0] = NULL; // to be removed, as __kmp_allocate zeroes
56010b57cec5SDimitry Andric   // memory, no need to duplicate
56020b57cec5SDimitry Andric   team->t.t_task_team[1] = NULL; // to be removed, as __kmp_allocate zeroes
56030b57cec5SDimitry Andric   // memory, no need to duplicate
56040b57cec5SDimitry Andric 
56050b57cec5SDimitry Andric   if (__kmp_storage_map) {
56060b57cec5SDimitry Andric     __kmp_print_team_storage_map("team", team, team->t.t_id, new_nproc);
56070b57cec5SDimitry Andric   }
56080b57cec5SDimitry Andric 
56090b57cec5SDimitry Andric   /* allocate space for arguments */
56100b57cec5SDimitry Andric   __kmp_alloc_argv_entries(argc, team, FALSE);
56110b57cec5SDimitry Andric   team->t.t_argc = argc;
56120b57cec5SDimitry Andric 
56130b57cec5SDimitry Andric   KA_TRACE(20,
56140b57cec5SDimitry Andric            ("__kmp_allocate_team: team %d init arrived: join=%u, plain=%u\n",
56150b57cec5SDimitry Andric             team->t.t_id, KMP_INIT_BARRIER_STATE, KMP_INIT_BARRIER_STATE));
56160b57cec5SDimitry Andric   { // Initialize barrier data.
56170b57cec5SDimitry Andric     int b;
56180b57cec5SDimitry Andric     for (b = 0; b < bs_last_barrier; ++b) {
56190b57cec5SDimitry Andric       team->t.t_bar[b].b_arrived = KMP_INIT_BARRIER_STATE;
56200b57cec5SDimitry Andric #if USE_DEBUGGER
56210b57cec5SDimitry Andric       team->t.t_bar[b].b_master_arrived = 0;
56220b57cec5SDimitry Andric       team->t.t_bar[b].b_team_arrived = 0;
56230b57cec5SDimitry Andric #endif
56240b57cec5SDimitry Andric     }
56250b57cec5SDimitry Andric   }
56260b57cec5SDimitry Andric 
56270b57cec5SDimitry Andric   team->t.t_proc_bind = new_proc_bind;
56280b57cec5SDimitry Andric 
56290b57cec5SDimitry Andric #if OMPT_SUPPORT
56300b57cec5SDimitry Andric   __ompt_team_assign_id(team, ompt_parallel_data);
56310b57cec5SDimitry Andric   team->t.ompt_serialized_team_info = NULL;
56320b57cec5SDimitry Andric #endif
56330b57cec5SDimitry Andric 
56340b57cec5SDimitry Andric   KMP_MB();
56350b57cec5SDimitry Andric 
56360b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_allocate_team: done creating a new team %d.\n",
56370b57cec5SDimitry Andric                 team->t.t_id));
56380b57cec5SDimitry Andric 
56390b57cec5SDimitry Andric   return team;
56400b57cec5SDimitry Andric }
56410b57cec5SDimitry Andric 
56420b57cec5SDimitry Andric /* TODO implement hot-teams at all levels */
56430b57cec5SDimitry Andric /* TODO implement lazy thread release on demand (disband request) */
56440b57cec5SDimitry Andric 
56450b57cec5SDimitry Andric /* free the team.  return it to the team pool.  release all the threads
56460b57cec5SDimitry Andric  * associated with it */
__kmp_free_team(kmp_root_t * root,kmp_team_t * team USE_NESTED_HOT_ARG (kmp_info_t * master))56470b57cec5SDimitry Andric void __kmp_free_team(kmp_root_t *root,
56480b57cec5SDimitry Andric                      kmp_team_t *team USE_NESTED_HOT_ARG(kmp_info_t *master)) {
56490b57cec5SDimitry Andric   int f;
56500b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_free_team: T#%d freeing team %d\n", __kmp_get_gtid(),
56510b57cec5SDimitry Andric                 team->t.t_id));
56520b57cec5SDimitry Andric 
56530b57cec5SDimitry Andric   /* verify state */
56540b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(root);
56550b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team);
56560b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team->t.t_nproc <= team->t.t_max_nproc);
56570b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team->t.t_threads);
56580b57cec5SDimitry Andric 
56590b57cec5SDimitry Andric   int use_hot_team = team == root->r.r_hot_team;
56600b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
56610b57cec5SDimitry Andric   int level;
56620b57cec5SDimitry Andric   if (master) {
56630b57cec5SDimitry Andric     level = team->t.t_active_level - 1;
56640b57cec5SDimitry Andric     if (master->th.th_teams_microtask) { // in teams construct?
56650b57cec5SDimitry Andric       if (master->th.th_teams_size.nteams > 1) {
56660b57cec5SDimitry Andric         ++level; // level was not increased in teams construct for
56670b57cec5SDimitry Andric         // team_of_masters
56680b57cec5SDimitry Andric       }
56690b57cec5SDimitry Andric       if (team->t.t_pkfn != (microtask_t)__kmp_teams_master &&
56700b57cec5SDimitry Andric           master->th.th_teams_level == team->t.t_level) {
56710b57cec5SDimitry Andric         ++level; // level was not increased in teams construct for
56720b57cec5SDimitry Andric         // team_of_workers before the parallel
56730b57cec5SDimitry Andric       } // team->t.t_level will be increased inside parallel
56740b57cec5SDimitry Andric     }
5675349cc55cSDimitry Andric #if KMP_DEBUG
5676349cc55cSDimitry Andric     kmp_hot_team_ptr_t *hot_teams = master->th.th_hot_teams;
5677349cc55cSDimitry Andric #endif
56780b57cec5SDimitry Andric     if (level < __kmp_hot_teams_max_level) {
56790b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(team == hot_teams[level].hot_team);
56800b57cec5SDimitry Andric       use_hot_team = 1;
56810b57cec5SDimitry Andric     }
56820b57cec5SDimitry Andric   }
56830b57cec5SDimitry Andric #endif // KMP_NESTED_HOT_TEAMS
56840b57cec5SDimitry Andric 
56850b57cec5SDimitry Andric   /* team is done working */
56860b57cec5SDimitry Andric   TCW_SYNC_PTR(team->t.t_pkfn,
56870b57cec5SDimitry Andric                NULL); // Important for Debugging Support Library.
56880b57cec5SDimitry Andric #if KMP_OS_WINDOWS
56890b57cec5SDimitry Andric   team->t.t_copyin_counter = 0; // init counter for possible reuse
56900b57cec5SDimitry Andric #endif
56910b57cec5SDimitry Andric   // Do not reset pointer to parent team to NULL for hot teams.
56920b57cec5SDimitry Andric 
56930b57cec5SDimitry Andric   /* if we are non-hot team, release our threads */
56940b57cec5SDimitry Andric   if (!use_hot_team) {
56950b57cec5SDimitry Andric     if (__kmp_tasking_mode != tskm_immediate_exec) {
56960b57cec5SDimitry Andric       // Wait for threads to reach reapable state
56970b57cec5SDimitry Andric       for (f = 1; f < team->t.t_nproc; ++f) {
56980b57cec5SDimitry Andric         KMP_DEBUG_ASSERT(team->t.t_threads[f]);
56990b57cec5SDimitry Andric         kmp_info_t *th = team->t.t_threads[f];
57000b57cec5SDimitry Andric         volatile kmp_uint32 *state = &th->th.th_reap_state;
57010b57cec5SDimitry Andric         while (*state != KMP_SAFE_TO_REAP) {
57020b57cec5SDimitry Andric #if KMP_OS_WINDOWS
57030b57cec5SDimitry Andric           // On Windows a thread can be killed at any time, check this
57040b57cec5SDimitry Andric           DWORD ecode;
57050b57cec5SDimitry Andric           if (!__kmp_is_thread_alive(th, &ecode)) {
57060b57cec5SDimitry Andric             *state = KMP_SAFE_TO_REAP; // reset the flag for dead thread
57070b57cec5SDimitry Andric             break;
57080b57cec5SDimitry Andric           }
57090b57cec5SDimitry Andric #endif
57100b57cec5SDimitry Andric           // first check if thread is sleeping
5711e8d8bef9SDimitry Andric           kmp_flag_64<> fl(&th->th.th_bar[bs_forkjoin_barrier].bb.b_go, th);
57120b57cec5SDimitry Andric           if (fl.is_sleeping())
57130b57cec5SDimitry Andric             fl.resume(__kmp_gtid_from_thread(th));
57140b57cec5SDimitry Andric           KMP_CPU_PAUSE();
57150b57cec5SDimitry Andric         }
57160b57cec5SDimitry Andric       }
57170b57cec5SDimitry Andric 
57180b57cec5SDimitry Andric       // Delete task teams
57190b57cec5SDimitry Andric       int tt_idx;
57200b57cec5SDimitry Andric       for (tt_idx = 0; tt_idx < 2; ++tt_idx) {
57210b57cec5SDimitry Andric         kmp_task_team_t *task_team = team->t.t_task_team[tt_idx];
57220b57cec5SDimitry Andric         if (task_team != NULL) {
57230b57cec5SDimitry Andric           for (f = 0; f < team->t.t_nproc; ++f) { // threads unref task teams
57240b57cec5SDimitry Andric             KMP_DEBUG_ASSERT(team->t.t_threads[f]);
57250b57cec5SDimitry Andric             team->t.t_threads[f]->th.th_task_team = NULL;
57260b57cec5SDimitry Andric           }
57270b57cec5SDimitry Andric           KA_TRACE(
57280b57cec5SDimitry Andric               20,
57290b57cec5SDimitry Andric               ("__kmp_free_team: T#%d deactivating task_team %p on team %d\n",
57300b57cec5SDimitry Andric                __kmp_get_gtid(), task_team, team->t.t_id));
57310b57cec5SDimitry Andric #if KMP_NESTED_HOT_TEAMS
57320b57cec5SDimitry Andric           __kmp_free_task_team(master, task_team);
57330b57cec5SDimitry Andric #endif
57340b57cec5SDimitry Andric           team->t.t_task_team[tt_idx] = NULL;
57350b57cec5SDimitry Andric         }
57360b57cec5SDimitry Andric       }
57370b57cec5SDimitry Andric     }
57380b57cec5SDimitry Andric 
57390b57cec5SDimitry Andric     // Reset pointer to parent team only for non-hot teams.
57400b57cec5SDimitry Andric     team->t.t_parent = NULL;
57410b57cec5SDimitry Andric     team->t.t_level = 0;
57420b57cec5SDimitry Andric     team->t.t_active_level = 0;
57430b57cec5SDimitry Andric 
57440b57cec5SDimitry Andric     /* free the worker threads */
57450b57cec5SDimitry Andric     for (f = 1; f < team->t.t_nproc; ++f) {
57460b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(team->t.t_threads[f]);
5747349cc55cSDimitry Andric       if (__kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5748349cc55cSDimitry Andric         KMP_COMPARE_AND_STORE_ACQ32(&(team->t.t_threads[f]->th.th_used_in_team),
5749349cc55cSDimitry Andric                                     1, 2);
5750349cc55cSDimitry Andric       }
57510b57cec5SDimitry Andric       __kmp_free_thread(team->t.t_threads[f]);
5752349cc55cSDimitry Andric     }
5753349cc55cSDimitry Andric 
5754349cc55cSDimitry Andric     if (__kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5755349cc55cSDimitry Andric       if (team->t.b) {
5756349cc55cSDimitry Andric         // wake up thread at old location
5757349cc55cSDimitry Andric         team->t.b->go_release();
5758349cc55cSDimitry Andric         if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) {
5759349cc55cSDimitry Andric           for (f = 1; f < team->t.t_nproc; ++f) {
5760349cc55cSDimitry Andric             if (team->t.b->sleep[f].sleep) {
5761349cc55cSDimitry Andric               __kmp_atomic_resume_64(
5762349cc55cSDimitry Andric                   team->t.t_threads[f]->th.th_info.ds.ds_gtid,
5763349cc55cSDimitry Andric                   (kmp_atomic_flag_64<> *)NULL);
5764349cc55cSDimitry Andric             }
5765349cc55cSDimitry Andric           }
5766349cc55cSDimitry Andric         }
5767349cc55cSDimitry Andric         // Wait for threads to be removed from team
5768349cc55cSDimitry Andric         for (int f = 1; f < team->t.t_nproc; ++f) {
5769349cc55cSDimitry Andric           while (team->t.t_threads[f]->th.th_used_in_team.load() != 0)
5770349cc55cSDimitry Andric             KMP_CPU_PAUSE();
5771349cc55cSDimitry Andric         }
5772349cc55cSDimitry Andric       }
5773349cc55cSDimitry Andric     }
5774349cc55cSDimitry Andric 
5775349cc55cSDimitry Andric     for (f = 1; f < team->t.t_nproc; ++f) {
57760b57cec5SDimitry Andric       team->t.t_threads[f] = NULL;
57770b57cec5SDimitry Andric     }
57780b57cec5SDimitry Andric 
5779349cc55cSDimitry Andric     if (team->t.t_max_nproc > 1 &&
5780349cc55cSDimitry Andric         __kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
5781349cc55cSDimitry Andric       distributedBarrier::deallocate(team->t.b);
5782349cc55cSDimitry Andric       team->t.b = NULL;
5783349cc55cSDimitry Andric     }
57840b57cec5SDimitry Andric     /* put the team back in the team pool */
57850b57cec5SDimitry Andric     /* TODO limit size of team pool, call reap_team if pool too large */
57860b57cec5SDimitry Andric     team->t.t_next_pool = CCAST(kmp_team_t *, __kmp_team_pool);
57870b57cec5SDimitry Andric     __kmp_team_pool = (volatile kmp_team_t *)team;
5788fe6060f1SDimitry Andric   } else { // Check if team was created for primary threads in teams construct
57890b57cec5SDimitry Andric     // See if first worker is a CG root
57900b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(team->t.t_threads[1] &&
57910b57cec5SDimitry Andric                      team->t.t_threads[1]->th.th_cg_roots);
57920b57cec5SDimitry Andric     if (team->t.t_threads[1]->th.th_cg_roots->cg_root == team->t.t_threads[1]) {
57930b57cec5SDimitry Andric       // Clean up the CG root nodes on workers so that this team can be re-used
57940b57cec5SDimitry Andric       for (f = 1; f < team->t.t_nproc; ++f) {
57950b57cec5SDimitry Andric         kmp_info_t *thr = team->t.t_threads[f];
57960b57cec5SDimitry Andric         KMP_DEBUG_ASSERT(thr && thr->th.th_cg_roots &&
57970b57cec5SDimitry Andric                          thr->th.th_cg_roots->cg_root == thr);
57980b57cec5SDimitry Andric         // Pop current CG root off list
57990b57cec5SDimitry Andric         kmp_cg_root_t *tmp = thr->th.th_cg_roots;
58000b57cec5SDimitry Andric         thr->th.th_cg_roots = tmp->up;
58010b57cec5SDimitry Andric         KA_TRACE(100, ("__kmp_free_team: Thread %p popping node %p and moving"
58020b57cec5SDimitry Andric                        " up to node %p. cg_nthreads was %d\n",
58030b57cec5SDimitry Andric                        thr, tmp, thr->th.th_cg_roots, tmp->cg_nthreads));
58040b57cec5SDimitry Andric         int i = tmp->cg_nthreads--;
58050b57cec5SDimitry Andric         if (i == 1) {
58060b57cec5SDimitry Andric           __kmp_free(tmp); // free CG if we are the last thread in it
58070b57cec5SDimitry Andric         }
58080b57cec5SDimitry Andric         // Restore current task's thread_limit from CG root
58090b57cec5SDimitry Andric         if (thr->th.th_cg_roots)
58100b57cec5SDimitry Andric           thr->th.th_current_task->td_icvs.thread_limit =
58110b57cec5SDimitry Andric               thr->th.th_cg_roots->cg_thread_limit;
58120b57cec5SDimitry Andric       }
58130b57cec5SDimitry Andric     }
58140b57cec5SDimitry Andric   }
58150b57cec5SDimitry Andric 
58160b57cec5SDimitry Andric   KMP_MB();
58170b57cec5SDimitry Andric }
58180b57cec5SDimitry Andric 
58190b57cec5SDimitry Andric /* reap the team.  destroy it, reclaim all its resources and free its memory */
__kmp_reap_team(kmp_team_t * team)58200b57cec5SDimitry Andric kmp_team_t *__kmp_reap_team(kmp_team_t *team) {
58210b57cec5SDimitry Andric   kmp_team_t *next_pool = team->t.t_next_pool;
58220b57cec5SDimitry Andric 
58230b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team);
58240b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team->t.t_dispatch);
58250b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team->t.t_disp_buffer);
58260b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team->t.t_threads);
58270b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team->t.t_argv);
58280b57cec5SDimitry Andric 
58290b57cec5SDimitry Andric   /* TODO clean the threads that are a part of this? */
58300b57cec5SDimitry Andric 
58310b57cec5SDimitry Andric   /* free stuff */
58320b57cec5SDimitry Andric   __kmp_free_team_arrays(team);
58330b57cec5SDimitry Andric   if (team->t.t_argv != &team->t.t_inline_argv[0])
58340b57cec5SDimitry Andric     __kmp_free((void *)team->t.t_argv);
58350b57cec5SDimitry Andric   __kmp_free(team);
58360b57cec5SDimitry Andric 
58370b57cec5SDimitry Andric   KMP_MB();
58380b57cec5SDimitry Andric   return next_pool;
58390b57cec5SDimitry Andric }
58400b57cec5SDimitry Andric 
58410b57cec5SDimitry Andric // Free the thread.  Don't reap it, just place it on the pool of available
58420b57cec5SDimitry Andric // threads.
58430b57cec5SDimitry Andric //
58440b57cec5SDimitry Andric // Changes for Quad issue 527845: We need a predictable OMP tid <-> gtid
58450b57cec5SDimitry Andric // binding for the affinity mechanism to be useful.
58460b57cec5SDimitry Andric //
58470b57cec5SDimitry Andric // Now, we always keep the free list (__kmp_thread_pool) sorted by gtid.
58480b57cec5SDimitry Andric // However, we want to avoid a potential performance problem by always
58490b57cec5SDimitry Andric // scanning through the list to find the correct point at which to insert
58500b57cec5SDimitry Andric // the thread (potential N**2 behavior).  To do this we keep track of the
58510b57cec5SDimitry Andric // last place a thread struct was inserted (__kmp_thread_pool_insert_pt).
58520b57cec5SDimitry Andric // With single-level parallelism, threads will always be added to the tail
58530b57cec5SDimitry Andric // of the list, kept track of by __kmp_thread_pool_insert_pt.  With nested
58540b57cec5SDimitry Andric // parallelism, all bets are off and we may need to scan through the entire
58550b57cec5SDimitry Andric // free list.
58560b57cec5SDimitry Andric //
58570b57cec5SDimitry Andric // This change also has a potentially large performance benefit, for some
58580b57cec5SDimitry Andric // applications.  Previously, as threads were freed from the hot team, they
58590b57cec5SDimitry Andric // would be placed back on the free list in inverse order.  If the hot team
58600b57cec5SDimitry Andric // grew back to it's original size, then the freed thread would be placed
58610b57cec5SDimitry Andric // back on the hot team in reverse order.  This could cause bad cache
58620b57cec5SDimitry Andric // locality problems on programs where the size of the hot team regularly
58630b57cec5SDimitry Andric // grew and shrunk.
58640b57cec5SDimitry Andric //
58655ffd83dbSDimitry Andric // Now, for single-level parallelism, the OMP tid is always == gtid.
__kmp_free_thread(kmp_info_t * this_th)58660b57cec5SDimitry Andric void __kmp_free_thread(kmp_info_t *this_th) {
58670b57cec5SDimitry Andric   int gtid;
58680b57cec5SDimitry Andric   kmp_info_t **scan;
58690b57cec5SDimitry Andric 
58700b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_free_thread: T#%d putting T#%d back on free pool.\n",
58710b57cec5SDimitry Andric                 __kmp_get_gtid(), this_th->th.th_info.ds.ds_gtid));
58720b57cec5SDimitry Andric 
58730b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(this_th);
58740b57cec5SDimitry Andric 
58750b57cec5SDimitry Andric   // When moving thread to pool, switch thread to wait on own b_go flag, and
58760b57cec5SDimitry Andric   // uninitialized (NULL team).
58770b57cec5SDimitry Andric   int b;
58780b57cec5SDimitry Andric   kmp_balign_t *balign = this_th->th.th_bar;
58790b57cec5SDimitry Andric   for (b = 0; b < bs_last_barrier; ++b) {
58800b57cec5SDimitry Andric     if (balign[b].bb.wait_flag == KMP_BARRIER_PARENT_FLAG)
58810b57cec5SDimitry Andric       balign[b].bb.wait_flag = KMP_BARRIER_SWITCH_TO_OWN_FLAG;
58820b57cec5SDimitry Andric     balign[b].bb.team = NULL;
58830b57cec5SDimitry Andric     balign[b].bb.leaf_kids = 0;
58840b57cec5SDimitry Andric   }
58850b57cec5SDimitry Andric   this_th->th.th_task_state = 0;
58860b57cec5SDimitry Andric   this_th->th.th_reap_state = KMP_SAFE_TO_REAP;
58870b57cec5SDimitry Andric 
58880b57cec5SDimitry Andric   /* put thread back on the free pool */
58890b57cec5SDimitry Andric   TCW_PTR(this_th->th.th_team, NULL);
58900b57cec5SDimitry Andric   TCW_PTR(this_th->th.th_root, NULL);
58910b57cec5SDimitry Andric   TCW_PTR(this_th->th.th_dispatch, NULL); /* NOT NEEDED */
58920b57cec5SDimitry Andric 
58930b57cec5SDimitry Andric   while (this_th->th.th_cg_roots) {
58940b57cec5SDimitry Andric     this_th->th.th_cg_roots->cg_nthreads--;
58950b57cec5SDimitry Andric     KA_TRACE(100, ("__kmp_free_thread: Thread %p decrement cg_nthreads on node"
58960b57cec5SDimitry Andric                    " %p of thread  %p to %d\n",
58970b57cec5SDimitry Andric                    this_th, this_th->th.th_cg_roots,
58980b57cec5SDimitry Andric                    this_th->th.th_cg_roots->cg_root,
58990b57cec5SDimitry Andric                    this_th->th.th_cg_roots->cg_nthreads));
59000b57cec5SDimitry Andric     kmp_cg_root_t *tmp = this_th->th.th_cg_roots;
59010b57cec5SDimitry Andric     if (tmp->cg_root == this_th) { // Thread is a cg_root
59020b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(tmp->cg_nthreads == 0);
59030b57cec5SDimitry Andric       KA_TRACE(
59040b57cec5SDimitry Andric           5, ("__kmp_free_thread: Thread %p freeing node %p\n", this_th, tmp));
59050b57cec5SDimitry Andric       this_th->th.th_cg_roots = tmp->up;
59060b57cec5SDimitry Andric       __kmp_free(tmp);
59070b57cec5SDimitry Andric     } else { // Worker thread
59080b57cec5SDimitry Andric       if (tmp->cg_nthreads == 0) { // last thread leaves contention group
59090b57cec5SDimitry Andric         __kmp_free(tmp);
59100b57cec5SDimitry Andric       }
59110b57cec5SDimitry Andric       this_th->th.th_cg_roots = NULL;
59120b57cec5SDimitry Andric       break;
59130b57cec5SDimitry Andric     }
59140b57cec5SDimitry Andric   }
59150b57cec5SDimitry Andric 
59160b57cec5SDimitry Andric   /* If the implicit task assigned to this thread can be used by other threads
59170b57cec5SDimitry Andric    * -> multiple threads can share the data and try to free the task at
59180b57cec5SDimitry Andric    * __kmp_reap_thread at exit. This duplicate use of the task data can happen
59190b57cec5SDimitry Andric    * with higher probability when hot team is disabled but can occurs even when
59200b57cec5SDimitry Andric    * the hot team is enabled */
59210b57cec5SDimitry Andric   __kmp_free_implicit_task(this_th);
59220b57cec5SDimitry Andric   this_th->th.th_current_task = NULL;
59230b57cec5SDimitry Andric 
59240b57cec5SDimitry Andric   // If the __kmp_thread_pool_insert_pt is already past the new insert
59250b57cec5SDimitry Andric   // point, then we need to re-scan the entire list.
59260b57cec5SDimitry Andric   gtid = this_th->th.th_info.ds.ds_gtid;
59270b57cec5SDimitry Andric   if (__kmp_thread_pool_insert_pt != NULL) {
59280b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(__kmp_thread_pool != NULL);
59290b57cec5SDimitry Andric     if (__kmp_thread_pool_insert_pt->th.th_info.ds.ds_gtid > gtid) {
59300b57cec5SDimitry Andric       __kmp_thread_pool_insert_pt = NULL;
59310b57cec5SDimitry Andric     }
59320b57cec5SDimitry Andric   }
59330b57cec5SDimitry Andric 
59340b57cec5SDimitry Andric   // Scan down the list to find the place to insert the thread.
59350b57cec5SDimitry Andric   // scan is the address of a link in the list, possibly the address of
59360b57cec5SDimitry Andric   // __kmp_thread_pool itself.
59370b57cec5SDimitry Andric   //
59385ffd83dbSDimitry Andric   // In the absence of nested parallelism, the for loop will have 0 iterations.
59390b57cec5SDimitry Andric   if (__kmp_thread_pool_insert_pt != NULL) {
59400b57cec5SDimitry Andric     scan = &(__kmp_thread_pool_insert_pt->th.th_next_pool);
59410b57cec5SDimitry Andric   } else {
59420b57cec5SDimitry Andric     scan = CCAST(kmp_info_t **, &__kmp_thread_pool);
59430b57cec5SDimitry Andric   }
59440b57cec5SDimitry Andric   for (; (*scan != NULL) && ((*scan)->th.th_info.ds.ds_gtid < gtid);
59450b57cec5SDimitry Andric        scan = &((*scan)->th.th_next_pool))
59460b57cec5SDimitry Andric     ;
59470b57cec5SDimitry Andric 
59480b57cec5SDimitry Andric   // Insert the new element on the list, and set __kmp_thread_pool_insert_pt
59490b57cec5SDimitry Andric   // to its address.
59500b57cec5SDimitry Andric   TCW_PTR(this_th->th.th_next_pool, *scan);
59510b57cec5SDimitry Andric   __kmp_thread_pool_insert_pt = *scan = this_th;
59520b57cec5SDimitry Andric   KMP_DEBUG_ASSERT((this_th->th.th_next_pool == NULL) ||
59530b57cec5SDimitry Andric                    (this_th->th.th_info.ds.ds_gtid <
59540b57cec5SDimitry Andric                     this_th->th.th_next_pool->th.th_info.ds.ds_gtid));
59550b57cec5SDimitry Andric   TCW_4(this_th->th.th_in_pool, TRUE);
59560b57cec5SDimitry Andric   __kmp_suspend_initialize_thread(this_th);
59570b57cec5SDimitry Andric   __kmp_lock_suspend_mx(this_th);
59580b57cec5SDimitry Andric   if (this_th->th.th_active == TRUE) {
59590b57cec5SDimitry Andric     KMP_ATOMIC_INC(&__kmp_thread_pool_active_nth);
59600b57cec5SDimitry Andric     this_th->th.th_active_in_pool = TRUE;
59610b57cec5SDimitry Andric   }
59620b57cec5SDimitry Andric #if KMP_DEBUG
59630b57cec5SDimitry Andric   else {
59640b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(this_th->th.th_active_in_pool == FALSE);
59650b57cec5SDimitry Andric   }
59660b57cec5SDimitry Andric #endif
59670b57cec5SDimitry Andric   __kmp_unlock_suspend_mx(this_th);
59680b57cec5SDimitry Andric 
59690b57cec5SDimitry Andric   TCW_4(__kmp_nth, __kmp_nth - 1);
59700b57cec5SDimitry Andric 
59710b57cec5SDimitry Andric #ifdef KMP_ADJUST_BLOCKTIME
59720b57cec5SDimitry Andric   /* Adjust blocktime back to user setting or default if necessary */
59730b57cec5SDimitry Andric   /* Middle initialization might never have occurred                */
59740b57cec5SDimitry Andric   if (!__kmp_env_blocktime && (__kmp_avail_proc > 0)) {
59750b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(__kmp_avail_proc > 0);
59760b57cec5SDimitry Andric     if (__kmp_nth <= __kmp_avail_proc) {
59770b57cec5SDimitry Andric       __kmp_zero_bt = FALSE;
59780b57cec5SDimitry Andric     }
59790b57cec5SDimitry Andric   }
59800b57cec5SDimitry Andric #endif /* KMP_ADJUST_BLOCKTIME */
59810b57cec5SDimitry Andric 
59820b57cec5SDimitry Andric   KMP_MB();
59830b57cec5SDimitry Andric }
59840b57cec5SDimitry Andric 
59850b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
59860b57cec5SDimitry Andric 
__kmp_launch_thread(kmp_info_t * this_thr)59870b57cec5SDimitry Andric void *__kmp_launch_thread(kmp_info_t *this_thr) {
5988d409305fSDimitry Andric #if OMP_PROFILING_SUPPORT
5989e8d8bef9SDimitry Andric   ProfileTraceFile = getenv("LIBOMPTARGET_PROFILE");
5990e8d8bef9SDimitry Andric   // TODO: add a configuration option for time granularity
5991e8d8bef9SDimitry Andric   if (ProfileTraceFile)
5992e8d8bef9SDimitry Andric     llvm::timeTraceProfilerInitialize(500 /* us */, "libomptarget");
5993e8d8bef9SDimitry Andric #endif
5994e8d8bef9SDimitry Andric 
59950b57cec5SDimitry Andric   int gtid = this_thr->th.th_info.ds.ds_gtid;
59960b57cec5SDimitry Andric   /*    void                 *stack_data;*/
5997489b1cf2SDimitry Andric   kmp_team_t **volatile pteam;
59980b57cec5SDimitry Andric 
59990b57cec5SDimitry Andric   KMP_MB();
60000b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_launch_thread: T#%d start\n", gtid));
60010b57cec5SDimitry Andric 
60020b57cec5SDimitry Andric   if (__kmp_env_consistency_check) {
60030b57cec5SDimitry Andric     this_thr->th.th_cons = __kmp_allocate_cons_stack(gtid); // ATT: Memory leak?
60040b57cec5SDimitry Andric   }
60050b57cec5SDimitry Andric 
6006fe6060f1SDimitry Andric #if OMPD_SUPPORT
6007fe6060f1SDimitry Andric   if (ompd_state & OMPD_ENABLE_BP)
6008fe6060f1SDimitry Andric     ompd_bp_thread_begin();
6009fe6060f1SDimitry Andric #endif
6010fe6060f1SDimitry Andric 
60110b57cec5SDimitry Andric #if OMPT_SUPPORT
6012fe6060f1SDimitry Andric   ompt_data_t *thread_data = nullptr;
60130b57cec5SDimitry Andric   if (ompt_enabled.enabled) {
60140b57cec5SDimitry Andric     thread_data = &(this_thr->th.ompt_thread_info.thread_data);
60150b57cec5SDimitry Andric     *thread_data = ompt_data_none;
60160b57cec5SDimitry Andric 
60170b57cec5SDimitry Andric     this_thr->th.ompt_thread_info.state = ompt_state_overhead;
60180b57cec5SDimitry Andric     this_thr->th.ompt_thread_info.wait_id = 0;
60190b57cec5SDimitry Andric     this_thr->th.ompt_thread_info.idle_frame = OMPT_GET_FRAME_ADDRESS(0);
6020489b1cf2SDimitry Andric     this_thr->th.ompt_thread_info.parallel_flags = 0;
60210b57cec5SDimitry Andric     if (ompt_enabled.ompt_callback_thread_begin) {
60220b57cec5SDimitry Andric       ompt_callbacks.ompt_callback(ompt_callback_thread_begin)(
60230b57cec5SDimitry Andric           ompt_thread_worker, thread_data);
60240b57cec5SDimitry Andric     }
60250b57cec5SDimitry Andric     this_thr->th.ompt_thread_info.state = ompt_state_idle;
60260b57cec5SDimitry Andric   }
60270b57cec5SDimitry Andric #endif
6028489b1cf2SDimitry Andric 
60290b57cec5SDimitry Andric   /* This is the place where threads wait for work */
60300b57cec5SDimitry Andric   while (!TCR_4(__kmp_global.g.g_done)) {
60310b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(this_thr == __kmp_threads[gtid]);
60320b57cec5SDimitry Andric     KMP_MB();
60330b57cec5SDimitry Andric 
60340b57cec5SDimitry Andric     /* wait for work to do */
60350b57cec5SDimitry Andric     KA_TRACE(20, ("__kmp_launch_thread: T#%d waiting for work\n", gtid));
60360b57cec5SDimitry Andric 
60370b57cec5SDimitry Andric     /* No tid yet since not part of a team */
60380b57cec5SDimitry Andric     __kmp_fork_barrier(gtid, KMP_GTID_DNE);
60390b57cec5SDimitry Andric 
60400b57cec5SDimitry Andric #if OMPT_SUPPORT
60410b57cec5SDimitry Andric     if (ompt_enabled.enabled) {
60420b57cec5SDimitry Andric       this_thr->th.ompt_thread_info.state = ompt_state_overhead;
60430b57cec5SDimitry Andric     }
60440b57cec5SDimitry Andric #endif
60450b57cec5SDimitry Andric 
6046489b1cf2SDimitry Andric     pteam = &this_thr->th.th_team;
60470b57cec5SDimitry Andric 
60480b57cec5SDimitry Andric     /* have we been allocated? */
60490b57cec5SDimitry Andric     if (TCR_SYNC_PTR(*pteam) && !TCR_4(__kmp_global.g.g_done)) {
60500b57cec5SDimitry Andric       /* we were just woken up, so run our new task */
60510b57cec5SDimitry Andric       if (TCR_SYNC_PTR((*pteam)->t.t_pkfn) != NULL) {
60520b57cec5SDimitry Andric         int rc;
60530b57cec5SDimitry Andric         KA_TRACE(20,
60540b57cec5SDimitry Andric                  ("__kmp_launch_thread: T#%d(%d:%d) invoke microtask = %p\n",
60550b57cec5SDimitry Andric                   gtid, (*pteam)->t.t_id, __kmp_tid_from_gtid(gtid),
60560b57cec5SDimitry Andric                   (*pteam)->t.t_pkfn));
60570b57cec5SDimitry Andric 
60580b57cec5SDimitry Andric         updateHWFPControl(*pteam);
60590b57cec5SDimitry Andric 
60600b57cec5SDimitry Andric #if OMPT_SUPPORT
60610b57cec5SDimitry Andric         if (ompt_enabled.enabled) {
60620b57cec5SDimitry Andric           this_thr->th.ompt_thread_info.state = ompt_state_work_parallel;
60630b57cec5SDimitry Andric         }
60640b57cec5SDimitry Andric #endif
60650b57cec5SDimitry Andric 
60660b57cec5SDimitry Andric         rc = (*pteam)->t.t_invoke(gtid);
60670b57cec5SDimitry Andric         KMP_ASSERT(rc);
60680b57cec5SDimitry Andric 
60690b57cec5SDimitry Andric         KMP_MB();
60700b57cec5SDimitry Andric         KA_TRACE(20, ("__kmp_launch_thread: T#%d(%d:%d) done microtask = %p\n",
60710b57cec5SDimitry Andric                       gtid, (*pteam)->t.t_id, __kmp_tid_from_gtid(gtid),
60720b57cec5SDimitry Andric                       (*pteam)->t.t_pkfn));
60730b57cec5SDimitry Andric       }
60740b57cec5SDimitry Andric #if OMPT_SUPPORT
60750b57cec5SDimitry Andric       if (ompt_enabled.enabled) {
60760b57cec5SDimitry Andric         /* no frame set while outside task */
60770b57cec5SDimitry Andric         __ompt_get_task_info_object(0)->frame.exit_frame = ompt_data_none;
60780b57cec5SDimitry Andric 
60790b57cec5SDimitry Andric         this_thr->th.ompt_thread_info.state = ompt_state_overhead;
60800b57cec5SDimitry Andric       }
60810b57cec5SDimitry Andric #endif
60820b57cec5SDimitry Andric       /* join barrier after parallel region */
60830b57cec5SDimitry Andric       __kmp_join_barrier(gtid);
60840b57cec5SDimitry Andric     }
60850b57cec5SDimitry Andric   }
60860b57cec5SDimitry Andric 
6087fe6060f1SDimitry Andric #if OMPD_SUPPORT
6088fe6060f1SDimitry Andric   if (ompd_state & OMPD_ENABLE_BP)
6089fe6060f1SDimitry Andric     ompd_bp_thread_end();
6090fe6060f1SDimitry Andric #endif
6091fe6060f1SDimitry Andric 
60920b57cec5SDimitry Andric #if OMPT_SUPPORT
60930b57cec5SDimitry Andric   if (ompt_enabled.ompt_callback_thread_end) {
60940b57cec5SDimitry Andric     ompt_callbacks.ompt_callback(ompt_callback_thread_end)(thread_data);
60950b57cec5SDimitry Andric   }
60960b57cec5SDimitry Andric #endif
60970b57cec5SDimitry Andric 
60980b57cec5SDimitry Andric   this_thr->th.th_task_team = NULL;
60990b57cec5SDimitry Andric   /* run the destructors for the threadprivate data for this thread */
61000b57cec5SDimitry Andric   __kmp_common_destroy_gtid(gtid);
61010b57cec5SDimitry Andric 
61020b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_launch_thread: T#%d done\n", gtid));
61030b57cec5SDimitry Andric   KMP_MB();
6104e8d8bef9SDimitry Andric 
6105d409305fSDimitry Andric #if OMP_PROFILING_SUPPORT
6106e8d8bef9SDimitry Andric   llvm::timeTraceProfilerFinishThread();
6107e8d8bef9SDimitry Andric #endif
61080b57cec5SDimitry Andric   return this_thr;
61090b57cec5SDimitry Andric }
61100b57cec5SDimitry Andric 
61110b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
61120b57cec5SDimitry Andric 
__kmp_internal_end_dest(void * specific_gtid)61130b57cec5SDimitry Andric void __kmp_internal_end_dest(void *specific_gtid) {
61140b57cec5SDimitry Andric   // Make sure no significant bits are lost
6115e8d8bef9SDimitry Andric   int gtid;
6116e8d8bef9SDimitry Andric   __kmp_type_convert((kmp_intptr_t)specific_gtid - 1, &gtid);
61170b57cec5SDimitry Andric 
61180b57cec5SDimitry Andric   KA_TRACE(30, ("__kmp_internal_end_dest: T#%d\n", gtid));
61190b57cec5SDimitry Andric   /* NOTE: the gtid is stored as gitd+1 in the thread-local-storage
61200b57cec5SDimitry Andric    * this is because 0 is reserved for the nothing-stored case */
61210b57cec5SDimitry Andric 
61220b57cec5SDimitry Andric   __kmp_internal_end_thread(gtid);
61230b57cec5SDimitry Andric }
61240b57cec5SDimitry Andric 
61250b57cec5SDimitry Andric #if KMP_OS_UNIX && KMP_DYNAMIC_LIB
61260b57cec5SDimitry Andric 
__kmp_internal_end_dtor(void)61270b57cec5SDimitry Andric __attribute__((destructor)) void __kmp_internal_end_dtor(void) {
61280b57cec5SDimitry Andric   __kmp_internal_end_atexit();
61290b57cec5SDimitry Andric }
61300b57cec5SDimitry Andric 
61310b57cec5SDimitry Andric #endif
61320b57cec5SDimitry Andric 
61330b57cec5SDimitry Andric /* [Windows] josh: when the atexit handler is called, there may still be more
61340b57cec5SDimitry Andric    than one thread alive */
__kmp_internal_end_atexit(void)61350b57cec5SDimitry Andric void __kmp_internal_end_atexit(void) {
61360b57cec5SDimitry Andric   KA_TRACE(30, ("__kmp_internal_end_atexit\n"));
61370b57cec5SDimitry Andric   /* [Windows]
61380b57cec5SDimitry Andric      josh: ideally, we want to completely shutdown the library in this atexit
61390b57cec5SDimitry Andric      handler, but stat code that depends on thread specific data for gtid fails
61400b57cec5SDimitry Andric      because that data becomes unavailable at some point during the shutdown, so
61410b57cec5SDimitry Andric      we call __kmp_internal_end_thread instead. We should eventually remove the
61420b57cec5SDimitry Andric      dependency on __kmp_get_specific_gtid in the stat code and use
61430b57cec5SDimitry Andric      __kmp_internal_end_library to cleanly shutdown the library.
61440b57cec5SDimitry Andric 
61450b57cec5SDimitry Andric      // TODO: Can some of this comment about GVS be removed?
61460b57cec5SDimitry Andric      I suspect that the offending stat code is executed when the calling thread
61470b57cec5SDimitry Andric      tries to clean up a dead root thread's data structures, resulting in GVS
61480b57cec5SDimitry Andric      code trying to close the GVS structures for that thread, but since the stat
61490b57cec5SDimitry Andric      code uses __kmp_get_specific_gtid to get the gtid with the assumption that
61500b57cec5SDimitry Andric      the calling thread is cleaning up itself instead of another thread, it get
61510b57cec5SDimitry Andric      confused. This happens because allowing a thread to unregister and cleanup
61520b57cec5SDimitry Andric      another thread is a recent modification for addressing an issue.
61530b57cec5SDimitry Andric      Based on the current design (20050722), a thread may end up
61540b57cec5SDimitry Andric      trying to unregister another thread only if thread death does not trigger
61550b57cec5SDimitry Andric      the calling of __kmp_internal_end_thread.  For Linux* OS, there is the
61560b57cec5SDimitry Andric      thread specific data destructor function to detect thread death. For
61570b57cec5SDimitry Andric      Windows dynamic, there is DllMain(THREAD_DETACH). For Windows static, there
61580b57cec5SDimitry Andric      is nothing.  Thus, the workaround is applicable only for Windows static
61590b57cec5SDimitry Andric      stat library. */
61600b57cec5SDimitry Andric   __kmp_internal_end_library(-1);
61610b57cec5SDimitry Andric #if KMP_OS_WINDOWS
61620b57cec5SDimitry Andric   __kmp_close_console();
61630b57cec5SDimitry Andric #endif
61640b57cec5SDimitry Andric }
61650b57cec5SDimitry Andric 
__kmp_reap_thread(kmp_info_t * thread,int is_root)61660b57cec5SDimitry Andric static void __kmp_reap_thread(kmp_info_t *thread, int is_root) {
61670b57cec5SDimitry Andric   // It is assumed __kmp_forkjoin_lock is acquired.
61680b57cec5SDimitry Andric 
61690b57cec5SDimitry Andric   int gtid;
61700b57cec5SDimitry Andric 
61710b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(thread != NULL);
61720b57cec5SDimitry Andric 
61730b57cec5SDimitry Andric   gtid = thread->th.th_info.ds.ds_gtid;
61740b57cec5SDimitry Andric 
61750b57cec5SDimitry Andric   if (!is_root) {
61760b57cec5SDimitry Andric     if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) {
61770b57cec5SDimitry Andric       /* Assume the threads are at the fork barrier here */
61780b57cec5SDimitry Andric       KA_TRACE(
61790b57cec5SDimitry Andric           20, ("__kmp_reap_thread: releasing T#%d from fork barrier for reap\n",
61800b57cec5SDimitry Andric                gtid));
6181349cc55cSDimitry Andric       if (__kmp_barrier_gather_pattern[bs_forkjoin_barrier] == bp_dist_bar) {
6182349cc55cSDimitry Andric         while (
6183349cc55cSDimitry Andric             !KMP_COMPARE_AND_STORE_ACQ32(&(thread->th.th_used_in_team), 0, 3))
6184349cc55cSDimitry Andric           KMP_CPU_PAUSE();
6185349cc55cSDimitry Andric         __kmp_resume_32(gtid, (kmp_flag_32<false, false> *)NULL);
6186349cc55cSDimitry Andric       } else {
6187349cc55cSDimitry Andric         /* Need release fence here to prevent seg faults for tree forkjoin
6188349cc55cSDimitry Andric            barrier (GEH) */
6189e8d8bef9SDimitry Andric         kmp_flag_64<> flag(&thread->th.th_bar[bs_forkjoin_barrier].bb.b_go,
6190e8d8bef9SDimitry Andric                            thread);
61910b57cec5SDimitry Andric         __kmp_release_64(&flag);
61920b57cec5SDimitry Andric       }
6193349cc55cSDimitry Andric     }
61940b57cec5SDimitry Andric 
61950b57cec5SDimitry Andric     // Terminate OS thread.
61960b57cec5SDimitry Andric     __kmp_reap_worker(thread);
61970b57cec5SDimitry Andric 
61980b57cec5SDimitry Andric     // The thread was killed asynchronously.  If it was actively
61990b57cec5SDimitry Andric     // spinning in the thread pool, decrement the global count.
62000b57cec5SDimitry Andric     //
62010b57cec5SDimitry Andric     // There is a small timing hole here - if the worker thread was just waking
62020b57cec5SDimitry Andric     // up after sleeping in the pool, had reset it's th_active_in_pool flag but
62030b57cec5SDimitry Andric     // not decremented the global counter __kmp_thread_pool_active_nth yet, then
62040b57cec5SDimitry Andric     // the global counter might not get updated.
62050b57cec5SDimitry Andric     //
62060b57cec5SDimitry Andric     // Currently, this can only happen as the library is unloaded,
62070b57cec5SDimitry Andric     // so there are no harmful side effects.
62080b57cec5SDimitry Andric     if (thread->th.th_active_in_pool) {
62090b57cec5SDimitry Andric       thread->th.th_active_in_pool = FALSE;
62100b57cec5SDimitry Andric       KMP_ATOMIC_DEC(&__kmp_thread_pool_active_nth);
62110b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(__kmp_thread_pool_active_nth >= 0);
62120b57cec5SDimitry Andric     }
62130b57cec5SDimitry Andric   }
62140b57cec5SDimitry Andric 
62150b57cec5SDimitry Andric   __kmp_free_implicit_task(thread);
62160b57cec5SDimitry Andric 
62170b57cec5SDimitry Andric // Free the fast memory for tasking
62180b57cec5SDimitry Andric #if USE_FAST_MEMORY
62190b57cec5SDimitry Andric   __kmp_free_fast_memory(thread);
62200b57cec5SDimitry Andric #endif /* USE_FAST_MEMORY */
62210b57cec5SDimitry Andric 
62220b57cec5SDimitry Andric   __kmp_suspend_uninitialize_thread(thread);
62230b57cec5SDimitry Andric 
62240b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_threads[gtid] == thread);
62250b57cec5SDimitry Andric   TCW_SYNC_PTR(__kmp_threads[gtid], NULL);
62260b57cec5SDimitry Andric 
62270b57cec5SDimitry Andric   --__kmp_all_nth;
62280b57cec5SDimitry Andric   // __kmp_nth was decremented when thread is added to the pool.
62290b57cec5SDimitry Andric 
62300b57cec5SDimitry Andric #ifdef KMP_ADJUST_BLOCKTIME
62310b57cec5SDimitry Andric   /* Adjust blocktime back to user setting or default if necessary */
62320b57cec5SDimitry Andric   /* Middle initialization might never have occurred                */
62330b57cec5SDimitry Andric   if (!__kmp_env_blocktime && (__kmp_avail_proc > 0)) {
62340b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(__kmp_avail_proc > 0);
62350b57cec5SDimitry Andric     if (__kmp_nth <= __kmp_avail_proc) {
62360b57cec5SDimitry Andric       __kmp_zero_bt = FALSE;
62370b57cec5SDimitry Andric     }
62380b57cec5SDimitry Andric   }
62390b57cec5SDimitry Andric #endif /* KMP_ADJUST_BLOCKTIME */
62400b57cec5SDimitry Andric 
62410b57cec5SDimitry Andric   /* free the memory being used */
62420b57cec5SDimitry Andric   if (__kmp_env_consistency_check) {
62430b57cec5SDimitry Andric     if (thread->th.th_cons) {
62440b57cec5SDimitry Andric       __kmp_free_cons_stack(thread->th.th_cons);
62450b57cec5SDimitry Andric       thread->th.th_cons = NULL;
62460b57cec5SDimitry Andric     }
62470b57cec5SDimitry Andric   }
62480b57cec5SDimitry Andric 
62490b57cec5SDimitry Andric   if (thread->th.th_pri_common != NULL) {
62500b57cec5SDimitry Andric     __kmp_free(thread->th.th_pri_common);
62510b57cec5SDimitry Andric     thread->th.th_pri_common = NULL;
62520b57cec5SDimitry Andric   }
62530b57cec5SDimitry Andric 
62540b57cec5SDimitry Andric   if (thread->th.th_task_state_memo_stack != NULL) {
62550b57cec5SDimitry Andric     __kmp_free(thread->th.th_task_state_memo_stack);
62560b57cec5SDimitry Andric     thread->th.th_task_state_memo_stack = NULL;
62570b57cec5SDimitry Andric   }
62580b57cec5SDimitry Andric 
62590b57cec5SDimitry Andric #if KMP_USE_BGET
62600b57cec5SDimitry Andric   if (thread->th.th_local.bget_data != NULL) {
62610b57cec5SDimitry Andric     __kmp_finalize_bget(thread);
62620b57cec5SDimitry Andric   }
62630b57cec5SDimitry Andric #endif
62640b57cec5SDimitry Andric 
62650b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
62660b57cec5SDimitry Andric   if (thread->th.th_affin_mask != NULL) {
62670b57cec5SDimitry Andric     KMP_CPU_FREE(thread->th.th_affin_mask);
62680b57cec5SDimitry Andric     thread->th.th_affin_mask = NULL;
62690b57cec5SDimitry Andric   }
62700b57cec5SDimitry Andric #endif /* KMP_AFFINITY_SUPPORTED */
62710b57cec5SDimitry Andric 
62720b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED
62730b57cec5SDimitry Andric   if (thread->th.th_hier_bar_data != NULL) {
62740b57cec5SDimitry Andric     __kmp_free(thread->th.th_hier_bar_data);
62750b57cec5SDimitry Andric     thread->th.th_hier_bar_data = NULL;
62760b57cec5SDimitry Andric   }
62770b57cec5SDimitry Andric #endif
62780b57cec5SDimitry Andric 
62790b57cec5SDimitry Andric   __kmp_reap_team(thread->th.th_serial_team);
62800b57cec5SDimitry Andric   thread->th.th_serial_team = NULL;
62810b57cec5SDimitry Andric   __kmp_free(thread);
62820b57cec5SDimitry Andric 
62830b57cec5SDimitry Andric   KMP_MB();
62840b57cec5SDimitry Andric 
62850b57cec5SDimitry Andric } // __kmp_reap_thread
62860b57cec5SDimitry Andric 
__kmp_itthash_clean(kmp_info_t * th)6287349cc55cSDimitry Andric static void __kmp_itthash_clean(kmp_info_t *th) {
6288349cc55cSDimitry Andric #if USE_ITT_NOTIFY
6289349cc55cSDimitry Andric   if (__kmp_itt_region_domains.count > 0) {
6290349cc55cSDimitry Andric     for (int i = 0; i < KMP_MAX_FRAME_DOMAINS; ++i) {
6291349cc55cSDimitry Andric       kmp_itthash_entry_t *bucket = __kmp_itt_region_domains.buckets[i];
6292349cc55cSDimitry Andric       while (bucket) {
6293349cc55cSDimitry Andric         kmp_itthash_entry_t *next = bucket->next_in_bucket;
6294349cc55cSDimitry Andric         __kmp_thread_free(th, bucket);
6295349cc55cSDimitry Andric         bucket = next;
6296349cc55cSDimitry Andric       }
6297349cc55cSDimitry Andric     }
6298349cc55cSDimitry Andric   }
6299349cc55cSDimitry Andric   if (__kmp_itt_barrier_domains.count > 0) {
6300349cc55cSDimitry Andric     for (int i = 0; i < KMP_MAX_FRAME_DOMAINS; ++i) {
6301349cc55cSDimitry Andric       kmp_itthash_entry_t *bucket = __kmp_itt_barrier_domains.buckets[i];
6302349cc55cSDimitry Andric       while (bucket) {
6303349cc55cSDimitry Andric         kmp_itthash_entry_t *next = bucket->next_in_bucket;
6304349cc55cSDimitry Andric         __kmp_thread_free(th, bucket);
6305349cc55cSDimitry Andric         bucket = next;
6306349cc55cSDimitry Andric       }
6307349cc55cSDimitry Andric     }
6308349cc55cSDimitry Andric   }
6309349cc55cSDimitry Andric #endif
6310349cc55cSDimitry Andric }
6311349cc55cSDimitry Andric 
__kmp_internal_end(void)63120b57cec5SDimitry Andric static void __kmp_internal_end(void) {
63130b57cec5SDimitry Andric   int i;
63140b57cec5SDimitry Andric 
63150b57cec5SDimitry Andric   /* First, unregister the library */
63160b57cec5SDimitry Andric   __kmp_unregister_library();
63170b57cec5SDimitry Andric 
63180b57cec5SDimitry Andric #if KMP_OS_WINDOWS
63190b57cec5SDimitry Andric   /* In Win static library, we can't tell when a root actually dies, so we
63200b57cec5SDimitry Andric      reclaim the data structures for any root threads that have died but not
63210b57cec5SDimitry Andric      unregistered themselves, in order to shut down cleanly.
63220b57cec5SDimitry Andric      In Win dynamic library we also can't tell when a thread dies.  */
63230b57cec5SDimitry Andric   __kmp_reclaim_dead_roots(); // AC: moved here to always clean resources of
63240b57cec5SDimitry Andric // dead roots
63250b57cec5SDimitry Andric #endif
63260b57cec5SDimitry Andric 
63270b57cec5SDimitry Andric   for (i = 0; i < __kmp_threads_capacity; i++)
63280b57cec5SDimitry Andric     if (__kmp_root[i])
63290b57cec5SDimitry Andric       if (__kmp_root[i]->r.r_active)
63300b57cec5SDimitry Andric         break;
63310b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
63320b57cec5SDimitry Andric   TCW_SYNC_4(__kmp_global.g.g_done, TRUE);
63330b57cec5SDimitry Andric 
63340b57cec5SDimitry Andric   if (i < __kmp_threads_capacity) {
63350b57cec5SDimitry Andric #if KMP_USE_MONITOR
63360b57cec5SDimitry Andric     // 2009-09-08 (lev): Other alive roots found. Why do we kill the monitor??
63370b57cec5SDimitry Andric     KMP_MB(); /* Flush all pending memory write invalidates.  */
63380b57cec5SDimitry Andric 
63390b57cec5SDimitry Andric     // Need to check that monitor was initialized before reaping it. If we are
63400b57cec5SDimitry Andric     // called form __kmp_atfork_child (which sets __kmp_init_parallel = 0), then
63410b57cec5SDimitry Andric     // __kmp_monitor will appear to contain valid data, but it is only valid in
63420b57cec5SDimitry Andric     // the parent process, not the child.
63430b57cec5SDimitry Andric     // New behavior (201008): instead of keying off of the flag
63440b57cec5SDimitry Andric     // __kmp_init_parallel, the monitor thread creation is keyed off
63450b57cec5SDimitry Andric     // of the new flag __kmp_init_monitor.
63460b57cec5SDimitry Andric     __kmp_acquire_bootstrap_lock(&__kmp_monitor_lock);
63470b57cec5SDimitry Andric     if (TCR_4(__kmp_init_monitor)) {
63480b57cec5SDimitry Andric       __kmp_reap_monitor(&__kmp_monitor);
63490b57cec5SDimitry Andric       TCW_4(__kmp_init_monitor, 0);
63500b57cec5SDimitry Andric     }
63510b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_monitor_lock);
63520b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_internal_end: monitor reaped\n"));
63530b57cec5SDimitry Andric #endif // KMP_USE_MONITOR
63540b57cec5SDimitry Andric   } else {
63550b57cec5SDimitry Andric /* TODO move this to cleanup code */
63560b57cec5SDimitry Andric #ifdef KMP_DEBUG
63570b57cec5SDimitry Andric     /* make sure that everything has properly ended */
63580b57cec5SDimitry Andric     for (i = 0; i < __kmp_threads_capacity; i++) {
63590b57cec5SDimitry Andric       if (__kmp_root[i]) {
63600b57cec5SDimitry Andric         //                    KMP_ASSERT( ! KMP_UBER_GTID( i ) );         // AC:
63610b57cec5SDimitry Andric         //                    there can be uber threads alive here
63620b57cec5SDimitry Andric         KMP_ASSERT(!__kmp_root[i]->r.r_active); // TODO: can they be active?
63630b57cec5SDimitry Andric       }
63640b57cec5SDimitry Andric     }
63650b57cec5SDimitry Andric #endif
63660b57cec5SDimitry Andric 
63670b57cec5SDimitry Andric     KMP_MB();
63680b57cec5SDimitry Andric 
63690b57cec5SDimitry Andric     // Reap the worker threads.
63700b57cec5SDimitry Andric     // This is valid for now, but be careful if threads are reaped sooner.
63710b57cec5SDimitry Andric     while (__kmp_thread_pool != NULL) { // Loop thru all the thread in the pool.
63720b57cec5SDimitry Andric       // Get the next thread from the pool.
63730b57cec5SDimitry Andric       kmp_info_t *thread = CCAST(kmp_info_t *, __kmp_thread_pool);
63740b57cec5SDimitry Andric       __kmp_thread_pool = thread->th.th_next_pool;
63750b57cec5SDimitry Andric       // Reap it.
63760b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(thread->th.th_reap_state == KMP_SAFE_TO_REAP);
63770b57cec5SDimitry Andric       thread->th.th_next_pool = NULL;
63780b57cec5SDimitry Andric       thread->th.th_in_pool = FALSE;
63790b57cec5SDimitry Andric       __kmp_reap_thread(thread, 0);
63800b57cec5SDimitry Andric     }
63810b57cec5SDimitry Andric     __kmp_thread_pool_insert_pt = NULL;
63820b57cec5SDimitry Andric 
63830b57cec5SDimitry Andric     // Reap teams.
63840b57cec5SDimitry Andric     while (__kmp_team_pool != NULL) { // Loop thru all the teams in the pool.
63850b57cec5SDimitry Andric       // Get the next team from the pool.
63860b57cec5SDimitry Andric       kmp_team_t *team = CCAST(kmp_team_t *, __kmp_team_pool);
63870b57cec5SDimitry Andric       __kmp_team_pool = team->t.t_next_pool;
63880b57cec5SDimitry Andric       // Reap it.
63890b57cec5SDimitry Andric       team->t.t_next_pool = NULL;
63900b57cec5SDimitry Andric       __kmp_reap_team(team);
63910b57cec5SDimitry Andric     }
63920b57cec5SDimitry Andric 
63930b57cec5SDimitry Andric     __kmp_reap_task_teams();
63940b57cec5SDimitry Andric 
63950b57cec5SDimitry Andric #if KMP_OS_UNIX
63960b57cec5SDimitry Andric     // Threads that are not reaped should not access any resources since they
63970b57cec5SDimitry Andric     // are going to be deallocated soon, so the shutdown sequence should wait
63980b57cec5SDimitry Andric     // until all threads either exit the final spin-waiting loop or begin
63990b57cec5SDimitry Andric     // sleeping after the given blocktime.
64000b57cec5SDimitry Andric     for (i = 0; i < __kmp_threads_capacity; i++) {
64010b57cec5SDimitry Andric       kmp_info_t *thr = __kmp_threads[i];
64020b57cec5SDimitry Andric       while (thr && KMP_ATOMIC_LD_ACQ(&thr->th.th_blocking))
64030b57cec5SDimitry Andric         KMP_CPU_PAUSE();
64040b57cec5SDimitry Andric     }
64050b57cec5SDimitry Andric #endif
64060b57cec5SDimitry Andric 
64070b57cec5SDimitry Andric     for (i = 0; i < __kmp_threads_capacity; ++i) {
64080b57cec5SDimitry Andric       // TBD: Add some checking...
64090b57cec5SDimitry Andric       // Something like KMP_DEBUG_ASSERT( __kmp_thread[ i ] == NULL );
64100b57cec5SDimitry Andric     }
64110b57cec5SDimitry Andric 
64120b57cec5SDimitry Andric     /* Make sure all threadprivate destructors get run by joining with all
64130b57cec5SDimitry Andric        worker threads before resetting this flag */
64140b57cec5SDimitry Andric     TCW_SYNC_4(__kmp_init_common, FALSE);
64150b57cec5SDimitry Andric 
64160b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_internal_end: all workers reaped\n"));
64170b57cec5SDimitry Andric     KMP_MB();
64180b57cec5SDimitry Andric 
64190b57cec5SDimitry Andric #if KMP_USE_MONITOR
64200b57cec5SDimitry Andric     // See note above: One of the possible fixes for CQ138434 / CQ140126
64210b57cec5SDimitry Andric     //
64220b57cec5SDimitry Andric     // FIXME: push both code fragments down and CSE them?
64230b57cec5SDimitry Andric     // push them into __kmp_cleanup() ?
64240b57cec5SDimitry Andric     __kmp_acquire_bootstrap_lock(&__kmp_monitor_lock);
64250b57cec5SDimitry Andric     if (TCR_4(__kmp_init_monitor)) {
64260b57cec5SDimitry Andric       __kmp_reap_monitor(&__kmp_monitor);
64270b57cec5SDimitry Andric       TCW_4(__kmp_init_monitor, 0);
64280b57cec5SDimitry Andric     }
64290b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_monitor_lock);
64300b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_internal_end: monitor reaped\n"));
64310b57cec5SDimitry Andric #endif
64320b57cec5SDimitry Andric   } /* else !__kmp_global.t_active */
64330b57cec5SDimitry Andric   TCW_4(__kmp_init_gtid, FALSE);
64340b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
64350b57cec5SDimitry Andric 
64360b57cec5SDimitry Andric   __kmp_cleanup();
64370b57cec5SDimitry Andric #if OMPT_SUPPORT
64380b57cec5SDimitry Andric   ompt_fini();
64390b57cec5SDimitry Andric #endif
64400b57cec5SDimitry Andric }
64410b57cec5SDimitry Andric 
__kmp_internal_end_library(int gtid_req)64420b57cec5SDimitry Andric void __kmp_internal_end_library(int gtid_req) {
64430b57cec5SDimitry Andric   /* if we have already cleaned up, don't try again, it wouldn't be pretty */
64440b57cec5SDimitry Andric   /* this shouldn't be a race condition because __kmp_internal_end() is the
64450b57cec5SDimitry Andric      only place to clear __kmp_serial_init */
64460b57cec5SDimitry Andric   /* we'll check this later too, after we get the lock */
64470b57cec5SDimitry Andric   // 2009-09-06: We do not set g_abort without setting g_done. This check looks
64485ffd83dbSDimitry Andric   // redundant, because the next check will work in any case.
64490b57cec5SDimitry Andric   if (__kmp_global.g.g_abort) {
64500b57cec5SDimitry Andric     KA_TRACE(11, ("__kmp_internal_end_library: abort, exiting\n"));
64510b57cec5SDimitry Andric     /* TODO abort? */
64520b57cec5SDimitry Andric     return;
64530b57cec5SDimitry Andric   }
64540b57cec5SDimitry Andric   if (TCR_4(__kmp_global.g.g_done) || !__kmp_init_serial) {
64550b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_internal_end_library: already finished\n"));
64560b57cec5SDimitry Andric     return;
64570b57cec5SDimitry Andric   }
64580b57cec5SDimitry Andric 
6459fe6060f1SDimitry Andric   // If hidden helper team has been initialized, we need to deinit it
6460fe6060f1SDimitry Andric   if (TCR_4(__kmp_init_hidden_helper) &&
6461fe6060f1SDimitry Andric       !TCR_4(__kmp_hidden_helper_team_done)) {
6462fe6060f1SDimitry Andric     TCW_SYNC_4(__kmp_hidden_helper_team_done, TRUE);
6463fe6060f1SDimitry Andric     // First release the main thread to let it continue its work
6464fe6060f1SDimitry Andric     __kmp_hidden_helper_main_thread_release();
6465fe6060f1SDimitry Andric     // Wait until the hidden helper team has been destroyed
6466fe6060f1SDimitry Andric     __kmp_hidden_helper_threads_deinitz_wait();
6467fe6060f1SDimitry Andric   }
6468fe6060f1SDimitry Andric 
64690b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
64700b57cec5SDimitry Andric   /* find out who we are and what we should do */
64710b57cec5SDimitry Andric   {
64720b57cec5SDimitry Andric     int gtid = (gtid_req >= 0) ? gtid_req : __kmp_gtid_get_specific();
64730b57cec5SDimitry Andric     KA_TRACE(
64740b57cec5SDimitry Andric         10, ("__kmp_internal_end_library: enter T#%d  (%d)\n", gtid, gtid_req));
64750b57cec5SDimitry Andric     if (gtid == KMP_GTID_SHUTDOWN) {
64760b57cec5SDimitry Andric       KA_TRACE(10, ("__kmp_internal_end_library: !__kmp_init_runtime, system "
64770b57cec5SDimitry Andric                     "already shutdown\n"));
64780b57cec5SDimitry Andric       return;
64790b57cec5SDimitry Andric     } else if (gtid == KMP_GTID_MONITOR) {
64800b57cec5SDimitry Andric       KA_TRACE(10, ("__kmp_internal_end_library: monitor thread, gtid not "
64810b57cec5SDimitry Andric                     "registered, or system shutdown\n"));
64820b57cec5SDimitry Andric       return;
64830b57cec5SDimitry Andric     } else if (gtid == KMP_GTID_DNE) {
64840b57cec5SDimitry Andric       KA_TRACE(10, ("__kmp_internal_end_library: gtid not registered or system "
64850b57cec5SDimitry Andric                     "shutdown\n"));
64860b57cec5SDimitry Andric       /* we don't know who we are, but we may still shutdown the library */
64870b57cec5SDimitry Andric     } else if (KMP_UBER_GTID(gtid)) {
64880b57cec5SDimitry Andric       /* unregister ourselves as an uber thread.  gtid is no longer valid */
64890b57cec5SDimitry Andric       if (__kmp_root[gtid]->r.r_active) {
64900b57cec5SDimitry Andric         __kmp_global.g.g_abort = -1;
64910b57cec5SDimitry Andric         TCW_SYNC_4(__kmp_global.g.g_done, TRUE);
6492e8d8bef9SDimitry Andric         __kmp_unregister_library();
64930b57cec5SDimitry Andric         KA_TRACE(10,
64940b57cec5SDimitry Andric                  ("__kmp_internal_end_library: root still active, abort T#%d\n",
64950b57cec5SDimitry Andric                   gtid));
64960b57cec5SDimitry Andric         return;
64970b57cec5SDimitry Andric       } else {
6498349cc55cSDimitry Andric         __kmp_itthash_clean(__kmp_threads[gtid]);
64990b57cec5SDimitry Andric         KA_TRACE(
65000b57cec5SDimitry Andric             10,
65010b57cec5SDimitry Andric             ("__kmp_internal_end_library: unregistering sibling T#%d\n", gtid));
65020b57cec5SDimitry Andric         __kmp_unregister_root_current_thread(gtid);
65030b57cec5SDimitry Andric       }
65040b57cec5SDimitry Andric     } else {
65050b57cec5SDimitry Andric /* worker threads may call this function through the atexit handler, if they
65060b57cec5SDimitry Andric  * call exit() */
65070b57cec5SDimitry Andric /* For now, skip the usual subsequent processing and just dump the debug buffer.
65080b57cec5SDimitry Andric    TODO: do a thorough shutdown instead */
65090b57cec5SDimitry Andric #ifdef DUMP_DEBUG_ON_EXIT
65100b57cec5SDimitry Andric       if (__kmp_debug_buf)
65110b57cec5SDimitry Andric         __kmp_dump_debug_buffer();
65120b57cec5SDimitry Andric #endif
6513e8d8bef9SDimitry Andric       // added unregister library call here when we switch to shm linux
6514e8d8bef9SDimitry Andric       // if we don't, it will leave lots of files in /dev/shm
6515e8d8bef9SDimitry Andric       // cleanup shared memory file before exiting.
6516e8d8bef9SDimitry Andric       __kmp_unregister_library();
65170b57cec5SDimitry Andric       return;
65180b57cec5SDimitry Andric     }
65190b57cec5SDimitry Andric   }
65200b57cec5SDimitry Andric   /* synchronize the termination process */
65210b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
65220b57cec5SDimitry Andric 
65230b57cec5SDimitry Andric   /* have we already finished */
65240b57cec5SDimitry Andric   if (__kmp_global.g.g_abort) {
65250b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_internal_end_library: abort, exiting\n"));
65260b57cec5SDimitry Andric     /* TODO abort? */
65270b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_initz_lock);
65280b57cec5SDimitry Andric     return;
65290b57cec5SDimitry Andric   }
65300b57cec5SDimitry Andric   if (TCR_4(__kmp_global.g.g_done) || !__kmp_init_serial) {
65310b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_initz_lock);
65320b57cec5SDimitry Andric     return;
65330b57cec5SDimitry Andric   }
65340b57cec5SDimitry Andric 
65350b57cec5SDimitry Andric   /* We need this lock to enforce mutex between this reading of
65360b57cec5SDimitry Andric      __kmp_threads_capacity and the writing by __kmp_register_root.
65370b57cec5SDimitry Andric      Alternatively, we can use a counter of roots that is atomically updated by
65380b57cec5SDimitry Andric      __kmp_get_global_thread_id_reg, __kmp_do_serial_initialize and
65390b57cec5SDimitry Andric      __kmp_internal_end_*.  */
65400b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
65410b57cec5SDimitry Andric 
65420b57cec5SDimitry Andric   /* now we can safely conduct the actual termination */
65430b57cec5SDimitry Andric   __kmp_internal_end();
65440b57cec5SDimitry Andric 
65450b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
65460b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
65470b57cec5SDimitry Andric 
65480b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_internal_end_library: exit\n"));
65490b57cec5SDimitry Andric 
65500b57cec5SDimitry Andric #ifdef DUMP_DEBUG_ON_EXIT
65510b57cec5SDimitry Andric   if (__kmp_debug_buf)
65520b57cec5SDimitry Andric     __kmp_dump_debug_buffer();
65530b57cec5SDimitry Andric #endif
65540b57cec5SDimitry Andric 
65550b57cec5SDimitry Andric #if KMP_OS_WINDOWS
65560b57cec5SDimitry Andric   __kmp_close_console();
65570b57cec5SDimitry Andric #endif
65580b57cec5SDimitry Andric 
65590b57cec5SDimitry Andric   __kmp_fini_allocator();
65600b57cec5SDimitry Andric 
65610b57cec5SDimitry Andric } // __kmp_internal_end_library
65620b57cec5SDimitry Andric 
__kmp_internal_end_thread(int gtid_req)65630b57cec5SDimitry Andric void __kmp_internal_end_thread(int gtid_req) {
65640b57cec5SDimitry Andric   int i;
65650b57cec5SDimitry Andric 
65660b57cec5SDimitry Andric   /* if we have already cleaned up, don't try again, it wouldn't be pretty */
65670b57cec5SDimitry Andric   /* this shouldn't be a race condition because __kmp_internal_end() is the
65680b57cec5SDimitry Andric    * only place to clear __kmp_serial_init */
65690b57cec5SDimitry Andric   /* we'll check this later too, after we get the lock */
65700b57cec5SDimitry Andric   // 2009-09-06: We do not set g_abort without setting g_done. This check looks
65710b57cec5SDimitry Andric   // redundant, because the next check will work in any case.
65720b57cec5SDimitry Andric   if (__kmp_global.g.g_abort) {
65730b57cec5SDimitry Andric     KA_TRACE(11, ("__kmp_internal_end_thread: abort, exiting\n"));
65740b57cec5SDimitry Andric     /* TODO abort? */
65750b57cec5SDimitry Andric     return;
65760b57cec5SDimitry Andric   }
65770b57cec5SDimitry Andric   if (TCR_4(__kmp_global.g.g_done) || !__kmp_init_serial) {
65780b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_internal_end_thread: already finished\n"));
65790b57cec5SDimitry Andric     return;
65800b57cec5SDimitry Andric   }
65810b57cec5SDimitry Andric 
6582e8d8bef9SDimitry Andric   // If hidden helper team has been initialized, we need to deinit it
6583fe6060f1SDimitry Andric   if (TCR_4(__kmp_init_hidden_helper) &&
6584fe6060f1SDimitry Andric       !TCR_4(__kmp_hidden_helper_team_done)) {
6585e8d8bef9SDimitry Andric     TCW_SYNC_4(__kmp_hidden_helper_team_done, TRUE);
6586e8d8bef9SDimitry Andric     // First release the main thread to let it continue its work
6587e8d8bef9SDimitry Andric     __kmp_hidden_helper_main_thread_release();
6588e8d8bef9SDimitry Andric     // Wait until the hidden helper team has been destroyed
6589e8d8bef9SDimitry Andric     __kmp_hidden_helper_threads_deinitz_wait();
6590e8d8bef9SDimitry Andric   }
6591e8d8bef9SDimitry Andric 
65920b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
65930b57cec5SDimitry Andric 
65940b57cec5SDimitry Andric   /* find out who we are and what we should do */
65950b57cec5SDimitry Andric   {
65960b57cec5SDimitry Andric     int gtid = (gtid_req >= 0) ? gtid_req : __kmp_gtid_get_specific();
65970b57cec5SDimitry Andric     KA_TRACE(10,
65980b57cec5SDimitry Andric              ("__kmp_internal_end_thread: enter T#%d  (%d)\n", gtid, gtid_req));
65990b57cec5SDimitry Andric     if (gtid == KMP_GTID_SHUTDOWN) {
66000b57cec5SDimitry Andric       KA_TRACE(10, ("__kmp_internal_end_thread: !__kmp_init_runtime, system "
66010b57cec5SDimitry Andric                     "already shutdown\n"));
66020b57cec5SDimitry Andric       return;
66030b57cec5SDimitry Andric     } else if (gtid == KMP_GTID_MONITOR) {
66040b57cec5SDimitry Andric       KA_TRACE(10, ("__kmp_internal_end_thread: monitor thread, gtid not "
66050b57cec5SDimitry Andric                     "registered, or system shutdown\n"));
66060b57cec5SDimitry Andric       return;
66070b57cec5SDimitry Andric     } else if (gtid == KMP_GTID_DNE) {
66080b57cec5SDimitry Andric       KA_TRACE(10, ("__kmp_internal_end_thread: gtid not registered or system "
66090b57cec5SDimitry Andric                     "shutdown\n"));
66100b57cec5SDimitry Andric       return;
66110b57cec5SDimitry Andric       /* we don't know who we are */
66120b57cec5SDimitry Andric     } else if (KMP_UBER_GTID(gtid)) {
66130b57cec5SDimitry Andric       /* unregister ourselves as an uber thread.  gtid is no longer valid */
66140b57cec5SDimitry Andric       if (__kmp_root[gtid]->r.r_active) {
66150b57cec5SDimitry Andric         __kmp_global.g.g_abort = -1;
66160b57cec5SDimitry Andric         TCW_SYNC_4(__kmp_global.g.g_done, TRUE);
66170b57cec5SDimitry Andric         KA_TRACE(10,
66180b57cec5SDimitry Andric                  ("__kmp_internal_end_thread: root still active, abort T#%d\n",
66190b57cec5SDimitry Andric                   gtid));
66200b57cec5SDimitry Andric         return;
66210b57cec5SDimitry Andric       } else {
66220b57cec5SDimitry Andric         KA_TRACE(10, ("__kmp_internal_end_thread: unregistering sibling T#%d\n",
66230b57cec5SDimitry Andric                       gtid));
66240b57cec5SDimitry Andric         __kmp_unregister_root_current_thread(gtid);
66250b57cec5SDimitry Andric       }
66260b57cec5SDimitry Andric     } else {
66270b57cec5SDimitry Andric       /* just a worker thread, let's leave */
66280b57cec5SDimitry Andric       KA_TRACE(10, ("__kmp_internal_end_thread: worker thread T#%d\n", gtid));
66290b57cec5SDimitry Andric 
66300b57cec5SDimitry Andric       if (gtid >= 0) {
66310b57cec5SDimitry Andric         __kmp_threads[gtid]->th.th_task_team = NULL;
66320b57cec5SDimitry Andric       }
66330b57cec5SDimitry Andric 
66340b57cec5SDimitry Andric       KA_TRACE(10,
66350b57cec5SDimitry Andric                ("__kmp_internal_end_thread: worker thread done, exiting T#%d\n",
66360b57cec5SDimitry Andric                 gtid));
66370b57cec5SDimitry Andric       return;
66380b57cec5SDimitry Andric     }
66390b57cec5SDimitry Andric   }
66400b57cec5SDimitry Andric #if KMP_DYNAMIC_LIB
66410b57cec5SDimitry Andric   if (__kmp_pause_status != kmp_hard_paused)
66420b57cec5SDimitry Andric   // AC: lets not shutdown the dynamic library at the exit of uber thread,
66430b57cec5SDimitry Andric   // because we will better shutdown later in the library destructor.
66440b57cec5SDimitry Andric   {
66450b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_internal_end_thread: exiting T#%d\n", gtid_req));
66460b57cec5SDimitry Andric     return;
66470b57cec5SDimitry Andric   }
66480b57cec5SDimitry Andric #endif
66490b57cec5SDimitry Andric   /* synchronize the termination process */
66500b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
66510b57cec5SDimitry Andric 
66520b57cec5SDimitry Andric   /* have we already finished */
66530b57cec5SDimitry Andric   if (__kmp_global.g.g_abort) {
66540b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_internal_end_thread: abort, exiting\n"));
66550b57cec5SDimitry Andric     /* TODO abort? */
66560b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_initz_lock);
66570b57cec5SDimitry Andric     return;
66580b57cec5SDimitry Andric   }
66590b57cec5SDimitry Andric   if (TCR_4(__kmp_global.g.g_done) || !__kmp_init_serial) {
66600b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_initz_lock);
66610b57cec5SDimitry Andric     return;
66620b57cec5SDimitry Andric   }
66630b57cec5SDimitry Andric 
66640b57cec5SDimitry Andric   /* We need this lock to enforce mutex between this reading of
66650b57cec5SDimitry Andric      __kmp_threads_capacity and the writing by __kmp_register_root.
66660b57cec5SDimitry Andric      Alternatively, we can use a counter of roots that is atomically updated by
66670b57cec5SDimitry Andric      __kmp_get_global_thread_id_reg, __kmp_do_serial_initialize and
66680b57cec5SDimitry Andric      __kmp_internal_end_*.  */
66690b57cec5SDimitry Andric 
66700b57cec5SDimitry Andric   /* should we finish the run-time?  are all siblings done? */
66710b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
66720b57cec5SDimitry Andric 
66730b57cec5SDimitry Andric   for (i = 0; i < __kmp_threads_capacity; ++i) {
66740b57cec5SDimitry Andric     if (KMP_UBER_GTID(i)) {
66750b57cec5SDimitry Andric       KA_TRACE(
66760b57cec5SDimitry Andric           10,
66770b57cec5SDimitry Andric           ("__kmp_internal_end_thread: remaining sibling task: gtid==%d\n", i));
66780b57cec5SDimitry Andric       __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
66790b57cec5SDimitry Andric       __kmp_release_bootstrap_lock(&__kmp_initz_lock);
66800b57cec5SDimitry Andric       return;
66810b57cec5SDimitry Andric     }
66820b57cec5SDimitry Andric   }
66830b57cec5SDimitry Andric 
66840b57cec5SDimitry Andric   /* now we can safely conduct the actual termination */
66850b57cec5SDimitry Andric 
66860b57cec5SDimitry Andric   __kmp_internal_end();
66870b57cec5SDimitry Andric 
66880b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
66890b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
66900b57cec5SDimitry Andric 
66910b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_internal_end_thread: exit T#%d\n", gtid_req));
66920b57cec5SDimitry Andric 
66930b57cec5SDimitry Andric #ifdef DUMP_DEBUG_ON_EXIT
66940b57cec5SDimitry Andric   if (__kmp_debug_buf)
66950b57cec5SDimitry Andric     __kmp_dump_debug_buffer();
66960b57cec5SDimitry Andric #endif
66970b57cec5SDimitry Andric } // __kmp_internal_end_thread
66980b57cec5SDimitry Andric 
66990b57cec5SDimitry Andric // -----------------------------------------------------------------------------
67000b57cec5SDimitry Andric // Library registration stuff.
67010b57cec5SDimitry Andric 
67020b57cec5SDimitry Andric static long __kmp_registration_flag = 0;
67030b57cec5SDimitry Andric // Random value used to indicate library initialization.
67040b57cec5SDimitry Andric static char *__kmp_registration_str = NULL;
67050b57cec5SDimitry Andric // Value to be saved in env var __KMP_REGISTERED_LIB_<pid>.
67060b57cec5SDimitry Andric 
__kmp_reg_status_name()67070b57cec5SDimitry Andric static inline char *__kmp_reg_status_name() {
67080b57cec5SDimitry Andric /* On RHEL 3u5 if linked statically, getpid() returns different values in
67090b57cec5SDimitry Andric    each thread. If registration and unregistration go in different threads
67100b57cec5SDimitry Andric    (omp_misc_other_root_exit.cpp test case), the name of registered_lib_env
67110b57cec5SDimitry Andric    env var can not be found, because the name will contain different pid. */
6712e8d8bef9SDimitry Andric // macOS* complains about name being too long with additional getuid()
6713e8d8bef9SDimitry Andric #if KMP_OS_UNIX && !KMP_OS_DARWIN && KMP_DYNAMIC_LIB
6714e8d8bef9SDimitry Andric   return __kmp_str_format("__KMP_REGISTERED_LIB_%d_%d", (int)getpid(),
6715e8d8bef9SDimitry Andric                           (int)getuid());
6716e8d8bef9SDimitry Andric #else
67170b57cec5SDimitry Andric   return __kmp_str_format("__KMP_REGISTERED_LIB_%d", (int)getpid());
6718e8d8bef9SDimitry Andric #endif
67190b57cec5SDimitry Andric } // __kmp_reg_status_get
67200b57cec5SDimitry Andric 
6721bdd1243dSDimitry Andric #if defined(KMP_USE_SHM)
67225f757f3fSDimitry Andric bool __kmp_shm_available = false;
67235f757f3fSDimitry Andric bool __kmp_tmp_available = false;
6724bdd1243dSDimitry Andric // If /dev/shm is not accessible, we will create a temporary file under /tmp.
6725bdd1243dSDimitry Andric char *temp_reg_status_file_name = nullptr;
6726bdd1243dSDimitry Andric #endif
6727bdd1243dSDimitry Andric 
__kmp_register_library_startup(void)67280b57cec5SDimitry Andric void __kmp_register_library_startup(void) {
67290b57cec5SDimitry Andric 
67300b57cec5SDimitry Andric   char *name = __kmp_reg_status_name(); // Name of the environment variable.
67310b57cec5SDimitry Andric   int done = 0;
67320b57cec5SDimitry Andric   union {
67330b57cec5SDimitry Andric     double dtime;
67340b57cec5SDimitry Andric     long ltime;
67350b57cec5SDimitry Andric   } time;
67360b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
67370b57cec5SDimitry Andric   __kmp_initialize_system_tick();
67380b57cec5SDimitry Andric #endif
67390b57cec5SDimitry Andric   __kmp_read_system_time(&time.dtime);
67400b57cec5SDimitry Andric   __kmp_registration_flag = 0xCAFE0000L | (time.ltime & 0x0000FFFFL);
67410b57cec5SDimitry Andric   __kmp_registration_str =
67420b57cec5SDimitry Andric       __kmp_str_format("%p-%lx-%s", &__kmp_registration_flag,
67430b57cec5SDimitry Andric                        __kmp_registration_flag, KMP_LIBRARY_FILE);
67440b57cec5SDimitry Andric 
67450b57cec5SDimitry Andric   KA_TRACE(50, ("__kmp_register_library_startup: %s=\"%s\"\n", name,
67460b57cec5SDimitry Andric                 __kmp_registration_str));
67470b57cec5SDimitry Andric 
67480b57cec5SDimitry Andric   while (!done) {
67490b57cec5SDimitry Andric 
67500b57cec5SDimitry Andric     char *value = NULL; // Actual value of the environment variable.
67510b57cec5SDimitry Andric 
6752349cc55cSDimitry Andric #if defined(KMP_USE_SHM)
67535f757f3fSDimitry Andric     char *shm_name = nullptr;
67545f757f3fSDimitry Andric     char *data1 = nullptr;
67555f757f3fSDimitry Andric     __kmp_shm_available = __kmp_detect_shm();
67565f757f3fSDimitry Andric     if (__kmp_shm_available) {
67575f757f3fSDimitry Andric       int fd1 = -1;
67585f757f3fSDimitry Andric       shm_name = __kmp_str_format("/%s", name);
6759e8d8bef9SDimitry Andric       int shm_preexist = 0;
67605f757f3fSDimitry Andric       fd1 = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR, 0666);
6761e8d8bef9SDimitry Andric       if ((fd1 == -1) && (errno == EEXIST)) {
6762e8d8bef9SDimitry Andric         // file didn't open because it already exists.
6763e8d8bef9SDimitry Andric         // try opening existing file
6764e8d8bef9SDimitry Andric         fd1 = shm_open(shm_name, O_RDWR, 0666);
6765e8d8bef9SDimitry Andric         if (fd1 == -1) { // file didn't open
67665f757f3fSDimitry Andric           KMP_WARNING(FunctionError, "Can't open SHM");
67675f757f3fSDimitry Andric           __kmp_shm_available = false;
67685f757f3fSDimitry Andric         } else { // able to open existing file
6769e8d8bef9SDimitry Andric           shm_preexist = 1;
6770e8d8bef9SDimitry Andric         }
6771e8d8bef9SDimitry Andric       }
67725f757f3fSDimitry Andric       if (__kmp_shm_available && shm_preexist == 0) { // SHM created, set size
67735f757f3fSDimitry Andric         if (ftruncate(fd1, SHM_SIZE) == -1) { // error occured setting size;
67745f757f3fSDimitry Andric           KMP_WARNING(FunctionError, "Can't set size of SHM");
67755f757f3fSDimitry Andric           __kmp_shm_available = false;
6776e8d8bef9SDimitry Andric         }
6777e8d8bef9SDimitry Andric       }
67785f757f3fSDimitry Andric       if (__kmp_shm_available) { // SHM exists, now map it
67795f757f3fSDimitry Andric         data1 = (char *)mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
67805f757f3fSDimitry Andric                              fd1, 0);
67815f757f3fSDimitry Andric         if (data1 == MAP_FAILED) { // failed to map shared memory
67825f757f3fSDimitry Andric           KMP_WARNING(FunctionError, "Can't map SHM");
67835f757f3fSDimitry Andric           __kmp_shm_available = false;
6784e8d8bef9SDimitry Andric         }
67855f757f3fSDimitry Andric       }
67865f757f3fSDimitry Andric       if (__kmp_shm_available) { // SHM mapped
6787e8d8bef9SDimitry Andric         if (shm_preexist == 0) { // set data to SHM, set value
6788e8d8bef9SDimitry Andric           KMP_STRCPY_S(data1, SHM_SIZE, __kmp_registration_str);
6789e8d8bef9SDimitry Andric         }
6790e8d8bef9SDimitry Andric         // Read value from either what we just wrote or existing file.
6791e8d8bef9SDimitry Andric         value = __kmp_str_format("%s", data1); // read value from SHM
6792e8d8bef9SDimitry Andric         munmap(data1, SHM_SIZE);
67935f757f3fSDimitry Andric       }
67945f757f3fSDimitry Andric       if (fd1 != -1)
6795e8d8bef9SDimitry Andric         close(fd1);
67965f757f3fSDimitry Andric     }
67975f757f3fSDimitry Andric     if (!__kmp_shm_available)
67985f757f3fSDimitry Andric       __kmp_tmp_available = __kmp_detect_tmp();
67995f757f3fSDimitry Andric     if (!__kmp_shm_available && __kmp_tmp_available) {
68005f757f3fSDimitry Andric       // SHM failed to work due to an error other than that the file already
68015f757f3fSDimitry Andric       // exists. Try to create a temp file under /tmp.
68025f757f3fSDimitry Andric       // If /tmp isn't accessible, fall back to using environment variable.
68035f757f3fSDimitry Andric       // TODO: /tmp might not always be the temporary directory. For now we will
68045f757f3fSDimitry Andric       // not consider TMPDIR.
68055f757f3fSDimitry Andric       int fd1 = -1;
68065f757f3fSDimitry Andric       temp_reg_status_file_name = __kmp_str_format("/tmp/%s", name);
68075f757f3fSDimitry Andric       int tmp_preexist = 0;
68085f757f3fSDimitry Andric       fd1 = open(temp_reg_status_file_name, O_CREAT | O_EXCL | O_RDWR, 0666);
68095f757f3fSDimitry Andric       if ((fd1 == -1) && (errno == EEXIST)) {
68105f757f3fSDimitry Andric         // file didn't open because it already exists.
68115f757f3fSDimitry Andric         // try opening existing file
68125f757f3fSDimitry Andric         fd1 = open(temp_reg_status_file_name, O_RDWR, 0666);
68135f757f3fSDimitry Andric         if (fd1 == -1) { // file didn't open if (fd1 == -1) {
68145f757f3fSDimitry Andric           KMP_WARNING(FunctionError, "Can't open TEMP");
68155f757f3fSDimitry Andric           __kmp_tmp_available = false;
68165f757f3fSDimitry Andric         } else {
68175f757f3fSDimitry Andric           tmp_preexist = 1;
68185f757f3fSDimitry Andric         }
68195f757f3fSDimitry Andric       }
68205f757f3fSDimitry Andric       if (__kmp_tmp_available && tmp_preexist == 0) {
68215f757f3fSDimitry Andric         // we created /tmp file now set size
68225f757f3fSDimitry Andric         if (ftruncate(fd1, SHM_SIZE) == -1) { // error occured setting size;
68235f757f3fSDimitry Andric           KMP_WARNING(FunctionError, "Can't set size of /tmp file");
68245f757f3fSDimitry Andric           __kmp_tmp_available = false;
68255f757f3fSDimitry Andric         }
68265f757f3fSDimitry Andric       }
68275f757f3fSDimitry Andric       if (__kmp_tmp_available) {
68285f757f3fSDimitry Andric         data1 = (char *)mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
68295f757f3fSDimitry Andric                              fd1, 0);
68305f757f3fSDimitry Andric         if (data1 == MAP_FAILED) { // failed to map /tmp
68315f757f3fSDimitry Andric           KMP_WARNING(FunctionError, "Can't map /tmp");
68325f757f3fSDimitry Andric           __kmp_tmp_available = false;
68335f757f3fSDimitry Andric         }
68345f757f3fSDimitry Andric       }
68355f757f3fSDimitry Andric       if (__kmp_tmp_available) {
68365f757f3fSDimitry Andric         if (tmp_preexist == 0) { // set data to TMP, set value
68375f757f3fSDimitry Andric           KMP_STRCPY_S(data1, SHM_SIZE, __kmp_registration_str);
68385f757f3fSDimitry Andric         }
68395f757f3fSDimitry Andric         // Read value from either what we just wrote or existing file.
68405f757f3fSDimitry Andric         value = __kmp_str_format("%s", data1); // read value from SHM
68415f757f3fSDimitry Andric         munmap(data1, SHM_SIZE);
68425f757f3fSDimitry Andric       }
68435f757f3fSDimitry Andric       if (fd1 != -1)
68445f757f3fSDimitry Andric         close(fd1);
68455f757f3fSDimitry Andric     }
68465f757f3fSDimitry Andric     if (!__kmp_shm_available && !__kmp_tmp_available) {
68475f757f3fSDimitry Andric       // no /dev/shm and no /tmp -- fall back to environment variable
68485f757f3fSDimitry Andric       // Set environment variable, but do not overwrite if it exists.
68495f757f3fSDimitry Andric       __kmp_env_set(name, __kmp_registration_str, 0);
68505f757f3fSDimitry Andric       // read value to see if it got set
68515f757f3fSDimitry Andric       value = __kmp_env_get(name);
68525f757f3fSDimitry Andric     }
6853e8d8bef9SDimitry Andric #else // Windows and unix with static library
68545f757f3fSDimitry Andric     // Set environment variable, but do not overwrite if it exists.
68550b57cec5SDimitry Andric     __kmp_env_set(name, __kmp_registration_str, 0);
6856e8d8bef9SDimitry Andric     // read value to see if it got set
68570b57cec5SDimitry Andric     value = __kmp_env_get(name);
6858e8d8bef9SDimitry Andric #endif
6859e8d8bef9SDimitry Andric 
68600b57cec5SDimitry Andric     if (value != NULL && strcmp(value, __kmp_registration_str) == 0) {
68610b57cec5SDimitry Andric       done = 1; // Ok, environment variable set successfully, exit the loop.
68620b57cec5SDimitry Andric     } else {
68630b57cec5SDimitry Andric       // Oops. Write failed. Another copy of OpenMP RTL is in memory.
68640b57cec5SDimitry Andric       // Check whether it alive or dead.
68650b57cec5SDimitry Andric       int neighbor = 0; // 0 -- unknown status, 1 -- alive, 2 -- dead.
68660b57cec5SDimitry Andric       char *tail = value;
68670b57cec5SDimitry Andric       char *flag_addr_str = NULL;
68680b57cec5SDimitry Andric       char *flag_val_str = NULL;
68690b57cec5SDimitry Andric       char const *file_name = NULL;
68700b57cec5SDimitry Andric       __kmp_str_split(tail, '-', &flag_addr_str, &tail);
68710b57cec5SDimitry Andric       __kmp_str_split(tail, '-', &flag_val_str, &tail);
68720b57cec5SDimitry Andric       file_name = tail;
68730b57cec5SDimitry Andric       if (tail != NULL) {
6874fe6060f1SDimitry Andric         unsigned long *flag_addr = 0;
6875fe6060f1SDimitry Andric         unsigned long flag_val = 0;
68760b57cec5SDimitry Andric         KMP_SSCANF(flag_addr_str, "%p", RCAST(void **, &flag_addr));
68770b57cec5SDimitry Andric         KMP_SSCANF(flag_val_str, "%lx", &flag_val);
68780b57cec5SDimitry Andric         if (flag_addr != 0 && flag_val != 0 && strcmp(file_name, "") != 0) {
68790b57cec5SDimitry Andric           // First, check whether environment-encoded address is mapped into
68800b57cec5SDimitry Andric           // addr space.
68810b57cec5SDimitry Andric           // If so, dereference it to see if it still has the right value.
68820b57cec5SDimitry Andric           if (__kmp_is_address_mapped(flag_addr) && *flag_addr == flag_val) {
68830b57cec5SDimitry Andric             neighbor = 1;
68840b57cec5SDimitry Andric           } else {
68850b57cec5SDimitry Andric             // If not, then we know the other copy of the library is no longer
68860b57cec5SDimitry Andric             // running.
68870b57cec5SDimitry Andric             neighbor = 2;
68880b57cec5SDimitry Andric           }
68890b57cec5SDimitry Andric         }
68900b57cec5SDimitry Andric       }
68910b57cec5SDimitry Andric       switch (neighbor) {
68920b57cec5SDimitry Andric       case 0: // Cannot parse environment variable -- neighbor status unknown.
68930b57cec5SDimitry Andric         // Assume it is the incompatible format of future version of the
68940b57cec5SDimitry Andric         // library. Assume the other library is alive.
68950b57cec5SDimitry Andric         // WARN( ... ); // TODO: Issue a warning.
68960b57cec5SDimitry Andric         file_name = "unknown library";
68970b57cec5SDimitry Andric         KMP_FALLTHROUGH();
68980b57cec5SDimitry Andric       // Attention! Falling to the next case. That's intentional.
68990b57cec5SDimitry Andric       case 1: { // Neighbor is alive.
69000b57cec5SDimitry Andric         // Check it is allowed.
69010b57cec5SDimitry Andric         char *duplicate_ok = __kmp_env_get("KMP_DUPLICATE_LIB_OK");
69020b57cec5SDimitry Andric         if (!__kmp_str_match_true(duplicate_ok)) {
69030b57cec5SDimitry Andric           // That's not allowed. Issue fatal error.
69040b57cec5SDimitry Andric           __kmp_fatal(KMP_MSG(DuplicateLibrary, KMP_LIBRARY_FILE, file_name),
69050b57cec5SDimitry Andric                       KMP_HNT(DuplicateLibrary), __kmp_msg_null);
69060b57cec5SDimitry Andric         }
69070b57cec5SDimitry Andric         KMP_INTERNAL_FREE(duplicate_ok);
69080b57cec5SDimitry Andric         __kmp_duplicate_library_ok = 1;
69090b57cec5SDimitry Andric         done = 1; // Exit the loop.
69100b57cec5SDimitry Andric       } break;
69110b57cec5SDimitry Andric       case 2: { // Neighbor is dead.
6912e8d8bef9SDimitry Andric 
6913349cc55cSDimitry Andric #if defined(KMP_USE_SHM)
69145f757f3fSDimitry Andric         if (__kmp_shm_available) { // close shared memory.
6915e8d8bef9SDimitry Andric           shm_unlink(shm_name); // this removes file in /dev/shm
69165f757f3fSDimitry Andric         } else if (__kmp_tmp_available) {
69175f757f3fSDimitry Andric           unlink(temp_reg_status_file_name); // this removes the temp file
69185f757f3fSDimitry Andric         } else {
69195f757f3fSDimitry Andric           // Clear the variable and try to register library again.
69205f757f3fSDimitry Andric           __kmp_env_unset(name);
69215f757f3fSDimitry Andric         }
6922e8d8bef9SDimitry Andric #else
69230b57cec5SDimitry Andric         // Clear the variable and try to register library again.
69240b57cec5SDimitry Andric         __kmp_env_unset(name);
6925e8d8bef9SDimitry Andric #endif
69260b57cec5SDimitry Andric       } break;
6927fe6060f1SDimitry Andric       default: {
6928fe6060f1SDimitry Andric         KMP_DEBUG_ASSERT(0);
6929fe6060f1SDimitry Andric       } break;
69300b57cec5SDimitry Andric       }
69310b57cec5SDimitry Andric     }
69320b57cec5SDimitry Andric     KMP_INTERNAL_FREE((void *)value);
6933349cc55cSDimitry Andric #if defined(KMP_USE_SHM)
69345f757f3fSDimitry Andric     if (shm_name)
6935e8d8bef9SDimitry Andric       KMP_INTERNAL_FREE((void *)shm_name);
6936e8d8bef9SDimitry Andric #endif
6937e8d8bef9SDimitry Andric   } // while
69380b57cec5SDimitry Andric   KMP_INTERNAL_FREE((void *)name);
69390b57cec5SDimitry Andric 
69400b57cec5SDimitry Andric } // func __kmp_register_library_startup
69410b57cec5SDimitry Andric 
__kmp_unregister_library(void)69420b57cec5SDimitry Andric void __kmp_unregister_library(void) {
69430b57cec5SDimitry Andric 
69440b57cec5SDimitry Andric   char *name = __kmp_reg_status_name();
6945e8d8bef9SDimitry Andric   char *value = NULL;
6946e8d8bef9SDimitry Andric 
6947349cc55cSDimitry Andric #if defined(KMP_USE_SHM)
69485f757f3fSDimitry Andric   char *shm_name = nullptr;
69495f757f3fSDimitry Andric   int fd1;
69505f757f3fSDimitry Andric   if (__kmp_shm_available) {
69515f757f3fSDimitry Andric     shm_name = __kmp_str_format("/%s", name);
69525f757f3fSDimitry Andric     fd1 = shm_open(shm_name, O_RDONLY, 0666);
69535f757f3fSDimitry Andric     if (fd1 != -1) { // File opened successfully
6954e8d8bef9SDimitry Andric       char *data1 = (char *)mmap(0, SHM_SIZE, PROT_READ, MAP_SHARED, fd1, 0);
6955e8d8bef9SDimitry Andric       if (data1 != MAP_FAILED) {
6956e8d8bef9SDimitry Andric         value = __kmp_str_format("%s", data1); // read value from SHM
6957e8d8bef9SDimitry Andric         munmap(data1, SHM_SIZE);
6958e8d8bef9SDimitry Andric       }
6959e8d8bef9SDimitry Andric       close(fd1);
69605f757f3fSDimitry Andric     }
69615f757f3fSDimitry Andric   } else if (__kmp_tmp_available) { // try /tmp
69625f757f3fSDimitry Andric     fd1 = open(temp_reg_status_file_name, O_RDONLY);
69635f757f3fSDimitry Andric     if (fd1 != -1) { // File opened successfully
69645f757f3fSDimitry Andric       char *data1 = (char *)mmap(0, SHM_SIZE, PROT_READ, MAP_SHARED, fd1, 0);
69655f757f3fSDimitry Andric       if (data1 != MAP_FAILED) {
69665f757f3fSDimitry Andric         value = __kmp_str_format("%s", data1); // read value from /tmp
69675f757f3fSDimitry Andric         munmap(data1, SHM_SIZE);
69685f757f3fSDimitry Andric       }
69695f757f3fSDimitry Andric       close(fd1);
69705f757f3fSDimitry Andric     }
69715f757f3fSDimitry Andric   } else { // fall back to envirable
69725f757f3fSDimitry Andric     value = __kmp_env_get(name);
69735f757f3fSDimitry Andric   }
6974e8d8bef9SDimitry Andric #else
6975e8d8bef9SDimitry Andric   value = __kmp_env_get(name);
6976e8d8bef9SDimitry Andric #endif
69770b57cec5SDimitry Andric 
69780b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_registration_flag != 0);
69790b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_registration_str != NULL);
69800b57cec5SDimitry Andric   if (value != NULL && strcmp(value, __kmp_registration_str) == 0) {
69810b57cec5SDimitry Andric //  Ok, this is our variable. Delete it.
6982349cc55cSDimitry Andric #if defined(KMP_USE_SHM)
69835f757f3fSDimitry Andric     if (__kmp_shm_available) {
6984e8d8bef9SDimitry Andric       shm_unlink(shm_name); // this removes file in /dev/shm
69855f757f3fSDimitry Andric     } else if (__kmp_tmp_available) {
6986bdd1243dSDimitry Andric       unlink(temp_reg_status_file_name); // this removes the temp file
69875f757f3fSDimitry Andric     } else {
69885f757f3fSDimitry Andric       __kmp_env_unset(name);
6989bdd1243dSDimitry Andric     }
6990e8d8bef9SDimitry Andric #else
69910b57cec5SDimitry Andric     __kmp_env_unset(name);
6992e8d8bef9SDimitry Andric #endif
69930b57cec5SDimitry Andric   }
69940b57cec5SDimitry Andric 
6995349cc55cSDimitry Andric #if defined(KMP_USE_SHM)
69965f757f3fSDimitry Andric   if (shm_name)
6997e8d8bef9SDimitry Andric     KMP_INTERNAL_FREE(shm_name);
69985f757f3fSDimitry Andric   if (temp_reg_status_file_name)
6999bdd1243dSDimitry Andric     KMP_INTERNAL_FREE(temp_reg_status_file_name);
7000e8d8bef9SDimitry Andric #endif
7001e8d8bef9SDimitry Andric 
70020b57cec5SDimitry Andric   KMP_INTERNAL_FREE(__kmp_registration_str);
70030b57cec5SDimitry Andric   KMP_INTERNAL_FREE(value);
70040b57cec5SDimitry Andric   KMP_INTERNAL_FREE(name);
70050b57cec5SDimitry Andric 
70060b57cec5SDimitry Andric   __kmp_registration_flag = 0;
70070b57cec5SDimitry Andric   __kmp_registration_str = NULL;
70080b57cec5SDimitry Andric 
70090b57cec5SDimitry Andric } // __kmp_unregister_library
70100b57cec5SDimitry Andric 
70110b57cec5SDimitry Andric // End of Library registration stuff.
70120b57cec5SDimitry Andric // -----------------------------------------------------------------------------
70130b57cec5SDimitry Andric 
70140b57cec5SDimitry Andric #if KMP_MIC_SUPPORTED
70150b57cec5SDimitry Andric 
__kmp_check_mic_type()70160b57cec5SDimitry Andric static void __kmp_check_mic_type() {
70170b57cec5SDimitry Andric   kmp_cpuid_t cpuid_state = {0};
70180b57cec5SDimitry Andric   kmp_cpuid_t *cs_p = &cpuid_state;
70190b57cec5SDimitry Andric   __kmp_x86_cpuid(1, 0, cs_p);
70200b57cec5SDimitry Andric   // We don't support mic1 at the moment
70210b57cec5SDimitry Andric   if ((cs_p->eax & 0xff0) == 0xB10) {
70220b57cec5SDimitry Andric     __kmp_mic_type = mic2;
70230b57cec5SDimitry Andric   } else if ((cs_p->eax & 0xf0ff0) == 0x50670) {
70240b57cec5SDimitry Andric     __kmp_mic_type = mic3;
70250b57cec5SDimitry Andric   } else {
70260b57cec5SDimitry Andric     __kmp_mic_type = non_mic;
70270b57cec5SDimitry Andric   }
70280b57cec5SDimitry Andric }
70290b57cec5SDimitry Andric 
70300b57cec5SDimitry Andric #endif /* KMP_MIC_SUPPORTED */
70310b57cec5SDimitry Andric 
7032e8d8bef9SDimitry Andric #if KMP_HAVE_UMWAIT
__kmp_user_level_mwait_init()7033e8d8bef9SDimitry Andric static void __kmp_user_level_mwait_init() {
7034e8d8bef9SDimitry Andric   struct kmp_cpuid buf;
7035e8d8bef9SDimitry Andric   __kmp_x86_cpuid(7, 0, &buf);
703604eeddc0SDimitry Andric   __kmp_waitpkg_enabled = ((buf.ecx >> 5) & 1);
703704eeddc0SDimitry Andric   __kmp_umwait_enabled = __kmp_waitpkg_enabled && __kmp_user_level_mwait;
703804eeddc0SDimitry Andric   __kmp_tpause_enabled = __kmp_waitpkg_enabled && (__kmp_tpause_state > 0);
7039e8d8bef9SDimitry Andric   KF_TRACE(30, ("__kmp_user_level_mwait_init: __kmp_umwait_enabled = %d\n",
7040e8d8bef9SDimitry Andric                 __kmp_umwait_enabled));
7041e8d8bef9SDimitry Andric }
7042e8d8bef9SDimitry Andric #elif KMP_HAVE_MWAIT
7043e8d8bef9SDimitry Andric #ifndef AT_INTELPHIUSERMWAIT
7044e8d8bef9SDimitry Andric // Spurious, non-existent value that should always fail to return anything.
7045e8d8bef9SDimitry Andric // Will be replaced with the correct value when we know that.
7046e8d8bef9SDimitry Andric #define AT_INTELPHIUSERMWAIT 10000
7047e8d8bef9SDimitry Andric #endif
7048e8d8bef9SDimitry Andric // getauxval() function is available in RHEL7 and SLES12. If a system with an
7049e8d8bef9SDimitry Andric // earlier OS is used to build the RTL, we'll use the following internal
7050e8d8bef9SDimitry Andric // function when the entry is not found.
7051e8d8bef9SDimitry Andric unsigned long getauxval(unsigned long) KMP_WEAK_ATTRIBUTE_EXTERNAL;
getauxval(unsigned long)7052e8d8bef9SDimitry Andric unsigned long getauxval(unsigned long) { return 0; }
7053e8d8bef9SDimitry Andric 
__kmp_user_level_mwait_init()7054e8d8bef9SDimitry Andric static void __kmp_user_level_mwait_init() {
7055e8d8bef9SDimitry Andric   // When getauxval() and correct value of AT_INTELPHIUSERMWAIT are available
7056e8d8bef9SDimitry Andric   // use them to find if the user-level mwait is enabled. Otherwise, forcibly
7057e8d8bef9SDimitry Andric   // set __kmp_mwait_enabled=TRUE on Intel MIC if the environment variable
7058e8d8bef9SDimitry Andric   // KMP_USER_LEVEL_MWAIT was set to TRUE.
7059e8d8bef9SDimitry Andric   if (__kmp_mic_type == mic3) {
7060e8d8bef9SDimitry Andric     unsigned long res = getauxval(AT_INTELPHIUSERMWAIT);
7061e8d8bef9SDimitry Andric     if ((res & 0x1) || __kmp_user_level_mwait) {
7062e8d8bef9SDimitry Andric       __kmp_mwait_enabled = TRUE;
7063e8d8bef9SDimitry Andric       if (__kmp_user_level_mwait) {
7064e8d8bef9SDimitry Andric         KMP_INFORM(EnvMwaitWarn);
7065e8d8bef9SDimitry Andric       }
7066e8d8bef9SDimitry Andric     } else {
7067e8d8bef9SDimitry Andric       __kmp_mwait_enabled = FALSE;
7068e8d8bef9SDimitry Andric     }
7069e8d8bef9SDimitry Andric   }
7070e8d8bef9SDimitry Andric   KF_TRACE(30, ("__kmp_user_level_mwait_init: __kmp_mic_type = %d, "
7071e8d8bef9SDimitry Andric                 "__kmp_mwait_enabled = %d\n",
7072e8d8bef9SDimitry Andric                 __kmp_mic_type, __kmp_mwait_enabled));
7073e8d8bef9SDimitry Andric }
7074e8d8bef9SDimitry Andric #endif /* KMP_HAVE_UMWAIT */
7075e8d8bef9SDimitry Andric 
__kmp_do_serial_initialize(void)70760b57cec5SDimitry Andric static void __kmp_do_serial_initialize(void) {
70770b57cec5SDimitry Andric   int i, gtid;
7078e8d8bef9SDimitry Andric   size_t size;
70790b57cec5SDimitry Andric 
70800b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_do_serial_initialize: enter\n"));
70810b57cec5SDimitry Andric 
70820b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(sizeof(kmp_int32) == 4);
70830b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(sizeof(kmp_uint32) == 4);
70840b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(sizeof(kmp_int64) == 8);
70850b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(sizeof(kmp_uint64) == 8);
70860b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(sizeof(kmp_intptr_t) == sizeof(void *));
70870b57cec5SDimitry Andric 
70880b57cec5SDimitry Andric #if OMPT_SUPPORT
70890b57cec5SDimitry Andric   ompt_pre_init();
70900b57cec5SDimitry Andric #endif
7091fe6060f1SDimitry Andric #if OMPD_SUPPORT
7092fe6060f1SDimitry Andric   __kmp_env_dump();
7093fe6060f1SDimitry Andric   ompd_init();
7094fe6060f1SDimitry Andric #endif
70950b57cec5SDimitry Andric 
70960b57cec5SDimitry Andric   __kmp_validate_locks();
70970b57cec5SDimitry Andric 
709806c3fb27SDimitry Andric #if ENABLE_LIBOMPTARGET
709906c3fb27SDimitry Andric   /* Initialize functions from libomptarget */
710006c3fb27SDimitry Andric   __kmp_init_omptarget();
710106c3fb27SDimitry Andric #endif
710206c3fb27SDimitry Andric 
71030b57cec5SDimitry Andric   /* Initialize internal memory allocator */
71040b57cec5SDimitry Andric   __kmp_init_allocator();
71050b57cec5SDimitry Andric 
7106fcaf7f86SDimitry Andric   /* Register the library startup via an environment variable or via mapped
7107fcaf7f86SDimitry Andric      shared memory file and check to see whether another copy of the library is
7108fcaf7f86SDimitry Andric      already registered. Since forked child process is often terminated, we
7109fcaf7f86SDimitry Andric      postpone the registration till middle initialization in the child */
7110fcaf7f86SDimitry Andric   if (__kmp_need_register_serial)
71110b57cec5SDimitry Andric     __kmp_register_library_startup();
71120b57cec5SDimitry Andric 
71130b57cec5SDimitry Andric   /* TODO reinitialization of library */
71140b57cec5SDimitry Andric   if (TCR_4(__kmp_global.g.g_done)) {
71150b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_do_serial_initialize: reinitialization of library\n"));
71160b57cec5SDimitry Andric   }
71170b57cec5SDimitry Andric 
71180b57cec5SDimitry Andric   __kmp_global.g.g_abort = 0;
71190b57cec5SDimitry Andric   TCW_SYNC_4(__kmp_global.g.g_done, FALSE);
71200b57cec5SDimitry Andric 
71210b57cec5SDimitry Andric /* initialize the locks */
71220b57cec5SDimitry Andric #if KMP_USE_ADAPTIVE_LOCKS
71230b57cec5SDimitry Andric #if KMP_DEBUG_ADAPTIVE_LOCKS
71240b57cec5SDimitry Andric   __kmp_init_speculative_stats();
71250b57cec5SDimitry Andric #endif
71260b57cec5SDimitry Andric #endif
71270b57cec5SDimitry Andric #if KMP_STATS_ENABLED
71280b57cec5SDimitry Andric   __kmp_stats_init();
71290b57cec5SDimitry Andric #endif
71300b57cec5SDimitry Andric   __kmp_init_lock(&__kmp_global_lock);
71310b57cec5SDimitry Andric   __kmp_init_queuing_lock(&__kmp_dispatch_lock);
71320b57cec5SDimitry Andric   __kmp_init_lock(&__kmp_debug_lock);
71330b57cec5SDimitry Andric   __kmp_init_atomic_lock(&__kmp_atomic_lock);
71340b57cec5SDimitry Andric   __kmp_init_atomic_lock(&__kmp_atomic_lock_1i);
71350b57cec5SDimitry Andric   __kmp_init_atomic_lock(&__kmp_atomic_lock_2i);
71360b57cec5SDimitry Andric   __kmp_init_atomic_lock(&__kmp_atomic_lock_4i);
71370b57cec5SDimitry Andric   __kmp_init_atomic_lock(&__kmp_atomic_lock_4r);
71380b57cec5SDimitry Andric   __kmp_init_atomic_lock(&__kmp_atomic_lock_8i);
71390b57cec5SDimitry Andric   __kmp_init_atomic_lock(&__kmp_atomic_lock_8r);
71400b57cec5SDimitry Andric   __kmp_init_atomic_lock(&__kmp_atomic_lock_8c);
71410b57cec5SDimitry Andric   __kmp_init_atomic_lock(&__kmp_atomic_lock_10r);
71420b57cec5SDimitry Andric   __kmp_init_atomic_lock(&__kmp_atomic_lock_16r);
71430b57cec5SDimitry Andric   __kmp_init_atomic_lock(&__kmp_atomic_lock_16c);
71440b57cec5SDimitry Andric   __kmp_init_atomic_lock(&__kmp_atomic_lock_20c);
71450b57cec5SDimitry Andric   __kmp_init_atomic_lock(&__kmp_atomic_lock_32c);
71460b57cec5SDimitry Andric   __kmp_init_bootstrap_lock(&__kmp_forkjoin_lock);
71470b57cec5SDimitry Andric   __kmp_init_bootstrap_lock(&__kmp_exit_lock);
71480b57cec5SDimitry Andric #if KMP_USE_MONITOR
71490b57cec5SDimitry Andric   __kmp_init_bootstrap_lock(&__kmp_monitor_lock);
71500b57cec5SDimitry Andric #endif
71510b57cec5SDimitry Andric   __kmp_init_bootstrap_lock(&__kmp_tp_cached_lock);
71520b57cec5SDimitry Andric 
71530b57cec5SDimitry Andric   /* conduct initialization and initial setup of configuration */
71540b57cec5SDimitry Andric 
71550b57cec5SDimitry Andric   __kmp_runtime_initialize();
71560b57cec5SDimitry Andric 
71570b57cec5SDimitry Andric #if KMP_MIC_SUPPORTED
71580b57cec5SDimitry Andric   __kmp_check_mic_type();
71590b57cec5SDimitry Andric #endif
71600b57cec5SDimitry Andric 
71610b57cec5SDimitry Andric // Some global variable initialization moved here from kmp_env_initialize()
71620b57cec5SDimitry Andric #ifdef KMP_DEBUG
71630b57cec5SDimitry Andric   kmp_diag = 0;
71640b57cec5SDimitry Andric #endif
71650b57cec5SDimitry Andric   __kmp_abort_delay = 0;
71660b57cec5SDimitry Andric 
71670b57cec5SDimitry Andric   // From __kmp_init_dflt_team_nth()
71680b57cec5SDimitry Andric   /* assume the entire machine will be used */
71690b57cec5SDimitry Andric   __kmp_dflt_team_nth_ub = __kmp_xproc;
71700b57cec5SDimitry Andric   if (__kmp_dflt_team_nth_ub < KMP_MIN_NTH) {
71710b57cec5SDimitry Andric     __kmp_dflt_team_nth_ub = KMP_MIN_NTH;
71720b57cec5SDimitry Andric   }
71730b57cec5SDimitry Andric   if (__kmp_dflt_team_nth_ub > __kmp_sys_max_nth) {
71740b57cec5SDimitry Andric     __kmp_dflt_team_nth_ub = __kmp_sys_max_nth;
71750b57cec5SDimitry Andric   }
71760b57cec5SDimitry Andric   __kmp_max_nth = __kmp_sys_max_nth;
71770b57cec5SDimitry Andric   __kmp_cg_max_nth = __kmp_sys_max_nth;
71780b57cec5SDimitry Andric   __kmp_teams_max_nth = __kmp_xproc; // set a "reasonable" default
71790b57cec5SDimitry Andric   if (__kmp_teams_max_nth > __kmp_sys_max_nth) {
71800b57cec5SDimitry Andric     __kmp_teams_max_nth = __kmp_sys_max_nth;
71810b57cec5SDimitry Andric   }
71820b57cec5SDimitry Andric 
71830b57cec5SDimitry Andric   // Three vars below moved here from __kmp_env_initialize() "KMP_BLOCKTIME"
71840b57cec5SDimitry Andric   // part
71850b57cec5SDimitry Andric   __kmp_dflt_blocktime = KMP_DEFAULT_BLOCKTIME;
71860b57cec5SDimitry Andric #if KMP_USE_MONITOR
71870b57cec5SDimitry Andric   __kmp_monitor_wakeups =
71880b57cec5SDimitry Andric       KMP_WAKEUPS_FROM_BLOCKTIME(__kmp_dflt_blocktime, __kmp_monitor_wakeups);
71890b57cec5SDimitry Andric   __kmp_bt_intervals =
71900b57cec5SDimitry Andric       KMP_INTERVALS_FROM_BLOCKTIME(__kmp_dflt_blocktime, __kmp_monitor_wakeups);
71910b57cec5SDimitry Andric #endif
71920b57cec5SDimitry Andric   // From "KMP_LIBRARY" part of __kmp_env_initialize()
71930b57cec5SDimitry Andric   __kmp_library = library_throughput;
71940b57cec5SDimitry Andric   // From KMP_SCHEDULE initialization
71950b57cec5SDimitry Andric   __kmp_static = kmp_sch_static_balanced;
71960b57cec5SDimitry Andric // AC: do not use analytical here, because it is non-monotonous
71970b57cec5SDimitry Andric //__kmp_guided = kmp_sch_guided_iterative_chunked;
71980b57cec5SDimitry Andric //__kmp_auto = kmp_sch_guided_analytical_chunked; // AC: it is the default, no
71990b57cec5SDimitry Andric // need to repeat assignment
72000b57cec5SDimitry Andric // Barrier initialization. Moved here from __kmp_env_initialize() Barrier branch
72010b57cec5SDimitry Andric // bit control and barrier method control parts
72020b57cec5SDimitry Andric #if KMP_FAST_REDUCTION_BARRIER
72030b57cec5SDimitry Andric #define kmp_reduction_barrier_gather_bb ((int)1)
72040b57cec5SDimitry Andric #define kmp_reduction_barrier_release_bb ((int)1)
7205349cc55cSDimitry Andric #define kmp_reduction_barrier_gather_pat __kmp_barrier_gather_pat_dflt
7206349cc55cSDimitry Andric #define kmp_reduction_barrier_release_pat __kmp_barrier_release_pat_dflt
72070b57cec5SDimitry Andric #endif // KMP_FAST_REDUCTION_BARRIER
72080b57cec5SDimitry Andric   for (i = bs_plain_barrier; i < bs_last_barrier; i++) {
72090b57cec5SDimitry Andric     __kmp_barrier_gather_branch_bits[i] = __kmp_barrier_gather_bb_dflt;
72100b57cec5SDimitry Andric     __kmp_barrier_release_branch_bits[i] = __kmp_barrier_release_bb_dflt;
72110b57cec5SDimitry Andric     __kmp_barrier_gather_pattern[i] = __kmp_barrier_gather_pat_dflt;
72120b57cec5SDimitry Andric     __kmp_barrier_release_pattern[i] = __kmp_barrier_release_pat_dflt;
72130b57cec5SDimitry Andric #if KMP_FAST_REDUCTION_BARRIER
72140b57cec5SDimitry Andric     if (i == bs_reduction_barrier) { // tested and confirmed on ALTIX only (
72150b57cec5SDimitry Andric       // lin_64 ): hyper,1
72160b57cec5SDimitry Andric       __kmp_barrier_gather_branch_bits[i] = kmp_reduction_barrier_gather_bb;
72170b57cec5SDimitry Andric       __kmp_barrier_release_branch_bits[i] = kmp_reduction_barrier_release_bb;
72180b57cec5SDimitry Andric       __kmp_barrier_gather_pattern[i] = kmp_reduction_barrier_gather_pat;
72190b57cec5SDimitry Andric       __kmp_barrier_release_pattern[i] = kmp_reduction_barrier_release_pat;
72200b57cec5SDimitry Andric     }
72210b57cec5SDimitry Andric #endif // KMP_FAST_REDUCTION_BARRIER
72220b57cec5SDimitry Andric   }
72230b57cec5SDimitry Andric #if KMP_FAST_REDUCTION_BARRIER
72240b57cec5SDimitry Andric #undef kmp_reduction_barrier_release_pat
72250b57cec5SDimitry Andric #undef kmp_reduction_barrier_gather_pat
72260b57cec5SDimitry Andric #undef kmp_reduction_barrier_release_bb
72270b57cec5SDimitry Andric #undef kmp_reduction_barrier_gather_bb
72280b57cec5SDimitry Andric #endif // KMP_FAST_REDUCTION_BARRIER
72290b57cec5SDimitry Andric #if KMP_MIC_SUPPORTED
72300b57cec5SDimitry Andric   if (__kmp_mic_type == mic2) { // KNC
72310b57cec5SDimitry Andric     // AC: plane=3,2, forkjoin=2,1 are optimal for 240 threads on KNC
72320b57cec5SDimitry Andric     __kmp_barrier_gather_branch_bits[bs_plain_barrier] = 3; // plain gather
72330b57cec5SDimitry Andric     __kmp_barrier_release_branch_bits[bs_forkjoin_barrier] =
72340b57cec5SDimitry Andric         1; // forkjoin release
72350b57cec5SDimitry Andric     __kmp_barrier_gather_pattern[bs_forkjoin_barrier] = bp_hierarchical_bar;
72360b57cec5SDimitry Andric     __kmp_barrier_release_pattern[bs_forkjoin_barrier] = bp_hierarchical_bar;
72370b57cec5SDimitry Andric   }
72380b57cec5SDimitry Andric #if KMP_FAST_REDUCTION_BARRIER
72390b57cec5SDimitry Andric   if (__kmp_mic_type == mic2) { // KNC
72400b57cec5SDimitry Andric     __kmp_barrier_gather_pattern[bs_reduction_barrier] = bp_hierarchical_bar;
72410b57cec5SDimitry Andric     __kmp_barrier_release_pattern[bs_reduction_barrier] = bp_hierarchical_bar;
72420b57cec5SDimitry Andric   }
72430b57cec5SDimitry Andric #endif // KMP_FAST_REDUCTION_BARRIER
72440b57cec5SDimitry Andric #endif // KMP_MIC_SUPPORTED
72450b57cec5SDimitry Andric 
72460b57cec5SDimitry Andric // From KMP_CHECKS initialization
72470b57cec5SDimitry Andric #ifdef KMP_DEBUG
72480b57cec5SDimitry Andric   __kmp_env_checks = TRUE; /* development versions have the extra checks */
72490b57cec5SDimitry Andric #else
72500b57cec5SDimitry Andric   __kmp_env_checks = FALSE; /* port versions do not have the extra checks */
72510b57cec5SDimitry Andric #endif
72520b57cec5SDimitry Andric 
72530b57cec5SDimitry Andric   // From "KMP_FOREIGN_THREADS_THREADPRIVATE" initialization
72540b57cec5SDimitry Andric   __kmp_foreign_tp = TRUE;
72550b57cec5SDimitry Andric 
72560b57cec5SDimitry Andric   __kmp_global.g.g_dynamic = FALSE;
72570b57cec5SDimitry Andric   __kmp_global.g.g_dynamic_mode = dynamic_default;
72580b57cec5SDimitry Andric 
7259fe6060f1SDimitry Andric   __kmp_init_nesting_mode();
7260fe6060f1SDimitry Andric 
72610b57cec5SDimitry Andric   __kmp_env_initialize(NULL);
72620b57cec5SDimitry Andric 
7263e8d8bef9SDimitry Andric #if KMP_HAVE_MWAIT || KMP_HAVE_UMWAIT
7264e8d8bef9SDimitry Andric   __kmp_user_level_mwait_init();
7265e8d8bef9SDimitry Andric #endif
72660b57cec5SDimitry Andric // Print all messages in message catalog for testing purposes.
72670b57cec5SDimitry Andric #ifdef KMP_DEBUG
72680b57cec5SDimitry Andric   char const *val = __kmp_env_get("KMP_DUMP_CATALOG");
72690b57cec5SDimitry Andric   if (__kmp_str_match_true(val)) {
72700b57cec5SDimitry Andric     kmp_str_buf_t buffer;
72710b57cec5SDimitry Andric     __kmp_str_buf_init(&buffer);
72720b57cec5SDimitry Andric     __kmp_i18n_dump_catalog(&buffer);
72730b57cec5SDimitry Andric     __kmp_printf("%s", buffer.str);
72740b57cec5SDimitry Andric     __kmp_str_buf_free(&buffer);
72750b57cec5SDimitry Andric   }
72760b57cec5SDimitry Andric   __kmp_env_free(&val);
72770b57cec5SDimitry Andric #endif
72780b57cec5SDimitry Andric 
72790b57cec5SDimitry Andric   __kmp_threads_capacity =
72800b57cec5SDimitry Andric       __kmp_initial_threads_capacity(__kmp_dflt_team_nth_ub);
72810b57cec5SDimitry Andric   // Moved here from __kmp_env_initialize() "KMP_ALL_THREADPRIVATE" part
72820b57cec5SDimitry Andric   __kmp_tp_capacity = __kmp_default_tp_capacity(
72830b57cec5SDimitry Andric       __kmp_dflt_team_nth_ub, __kmp_max_nth, __kmp_allThreadsSpecified);
72840b57cec5SDimitry Andric 
72850b57cec5SDimitry Andric   // If the library is shut down properly, both pools must be NULL. Just in
72860b57cec5SDimitry Andric   // case, set them to NULL -- some memory may leak, but subsequent code will
72870b57cec5SDimitry Andric   // work even if pools are not freed.
72880b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_thread_pool == NULL);
72890b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_thread_pool_insert_pt == NULL);
72900b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_team_pool == NULL);
72910b57cec5SDimitry Andric   __kmp_thread_pool = NULL;
72920b57cec5SDimitry Andric   __kmp_thread_pool_insert_pt = NULL;
72930b57cec5SDimitry Andric   __kmp_team_pool = NULL;
72940b57cec5SDimitry Andric 
72950b57cec5SDimitry Andric   /* Allocate all of the variable sized records */
72960b57cec5SDimitry Andric   /* NOTE: __kmp_threads_capacity entries are allocated, but the arrays are
72970b57cec5SDimitry Andric    * expandable */
72980b57cec5SDimitry Andric   /* Since allocation is cache-aligned, just add extra padding at the end */
72990b57cec5SDimitry Andric   size =
73000b57cec5SDimitry Andric       (sizeof(kmp_info_t *) + sizeof(kmp_root_t *)) * __kmp_threads_capacity +
73010b57cec5SDimitry Andric       CACHE_LINE;
73020b57cec5SDimitry Andric   __kmp_threads = (kmp_info_t **)__kmp_allocate(size);
73030b57cec5SDimitry Andric   __kmp_root = (kmp_root_t **)((char *)__kmp_threads +
73040b57cec5SDimitry Andric                                sizeof(kmp_info_t *) * __kmp_threads_capacity);
73050b57cec5SDimitry Andric 
73060b57cec5SDimitry Andric   /* init thread counts */
73070b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_all_nth ==
73080b57cec5SDimitry Andric                    0); // Asserts fail if the library is reinitializing and
73090b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_nth == 0); // something was wrong in termination.
73100b57cec5SDimitry Andric   __kmp_all_nth = 0;
73110b57cec5SDimitry Andric   __kmp_nth = 0;
73120b57cec5SDimitry Andric 
73130b57cec5SDimitry Andric   /* setup the uber master thread and hierarchy */
73140b57cec5SDimitry Andric   gtid = __kmp_register_root(TRUE);
73150b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_do_serial_initialize  T#%d\n", gtid));
73160b57cec5SDimitry Andric   KMP_ASSERT(KMP_UBER_GTID(gtid));
73170b57cec5SDimitry Andric   KMP_ASSERT(KMP_INITIAL_GTID(gtid));
73180b57cec5SDimitry Andric 
73190b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
73200b57cec5SDimitry Andric 
73210b57cec5SDimitry Andric   __kmp_common_initialize();
73220b57cec5SDimitry Andric 
73230b57cec5SDimitry Andric #if KMP_OS_UNIX
73240b57cec5SDimitry Andric   /* invoke the child fork handler */
73250b57cec5SDimitry Andric   __kmp_register_atfork();
73260b57cec5SDimitry Andric #endif
73270b57cec5SDimitry Andric 
7328bdd1243dSDimitry Andric #if !KMP_DYNAMIC_LIB ||                                                        \
7329bdd1243dSDimitry Andric     ((KMP_COMPILER_ICC || KMP_COMPILER_ICX) && KMP_OS_DARWIN)
73300b57cec5SDimitry Andric   {
73310b57cec5SDimitry Andric     /* Invoke the exit handler when the program finishes, only for static
7332bdd1243dSDimitry Andric        library and macOS* dynamic. For other dynamic libraries, we already
7333bdd1243dSDimitry Andric        have _fini and DllMain. */
73340b57cec5SDimitry Andric     int rc = atexit(__kmp_internal_end_atexit);
73350b57cec5SDimitry Andric     if (rc != 0) {
73360b57cec5SDimitry Andric       __kmp_fatal(KMP_MSG(FunctionError, "atexit()"), KMP_ERR(rc),
73370b57cec5SDimitry Andric                   __kmp_msg_null);
73380b57cec5SDimitry Andric     }
73390b57cec5SDimitry Andric   }
73400b57cec5SDimitry Andric #endif
73410b57cec5SDimitry Andric 
73420b57cec5SDimitry Andric #if KMP_HANDLE_SIGNALS
73430b57cec5SDimitry Andric #if KMP_OS_UNIX
73440b57cec5SDimitry Andric   /* NOTE: make sure that this is called before the user installs their own
73450b57cec5SDimitry Andric      signal handlers so that the user handlers are called first. this way they
73460b57cec5SDimitry Andric      can return false, not call our handler, avoid terminating the library, and
73470b57cec5SDimitry Andric      continue execution where they left off. */
73480b57cec5SDimitry Andric   __kmp_install_signals(FALSE);
73490b57cec5SDimitry Andric #endif /* KMP_OS_UNIX */
73500b57cec5SDimitry Andric #if KMP_OS_WINDOWS
73510b57cec5SDimitry Andric   __kmp_install_signals(TRUE);
73520b57cec5SDimitry Andric #endif /* KMP_OS_WINDOWS */
73530b57cec5SDimitry Andric #endif
73540b57cec5SDimitry Andric 
73550b57cec5SDimitry Andric   /* we have finished the serial initialization */
73560b57cec5SDimitry Andric   __kmp_init_counter++;
73570b57cec5SDimitry Andric 
73580b57cec5SDimitry Andric   __kmp_init_serial = TRUE;
73590b57cec5SDimitry Andric 
736006c3fb27SDimitry Andric   if (__kmp_version) {
736106c3fb27SDimitry Andric     __kmp_print_version_1();
736206c3fb27SDimitry Andric   }
736306c3fb27SDimitry Andric 
73640b57cec5SDimitry Andric   if (__kmp_settings) {
73650b57cec5SDimitry Andric     __kmp_env_print();
73660b57cec5SDimitry Andric   }
73670b57cec5SDimitry Andric 
73680b57cec5SDimitry Andric   if (__kmp_display_env || __kmp_display_env_verbose) {
73690b57cec5SDimitry Andric     __kmp_env_print_2();
73700b57cec5SDimitry Andric   }
73710b57cec5SDimitry Andric 
73720b57cec5SDimitry Andric #if OMPT_SUPPORT
73730b57cec5SDimitry Andric   ompt_post_init();
73740b57cec5SDimitry Andric #endif
73750b57cec5SDimitry Andric 
73760b57cec5SDimitry Andric   KMP_MB();
73770b57cec5SDimitry Andric 
73780b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_do_serial_initialize: exit\n"));
73790b57cec5SDimitry Andric }
73800b57cec5SDimitry Andric 
__kmp_serial_initialize(void)73810b57cec5SDimitry Andric void __kmp_serial_initialize(void) {
73820b57cec5SDimitry Andric   if (__kmp_init_serial) {
73830b57cec5SDimitry Andric     return;
73840b57cec5SDimitry Andric   }
73850b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
73860b57cec5SDimitry Andric   if (__kmp_init_serial) {
73870b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_initz_lock);
73880b57cec5SDimitry Andric     return;
73890b57cec5SDimitry Andric   }
73900b57cec5SDimitry Andric   __kmp_do_serial_initialize();
73910b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
73920b57cec5SDimitry Andric }
73930b57cec5SDimitry Andric 
__kmp_do_middle_initialize(void)73940b57cec5SDimitry Andric static void __kmp_do_middle_initialize(void) {
73950b57cec5SDimitry Andric   int i, j;
73960b57cec5SDimitry Andric   int prev_dflt_team_nth;
73970b57cec5SDimitry Andric 
73980b57cec5SDimitry Andric   if (!__kmp_init_serial) {
73990b57cec5SDimitry Andric     __kmp_do_serial_initialize();
74000b57cec5SDimitry Andric   }
74010b57cec5SDimitry Andric 
74020b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_middle_initialize: enter\n"));
74030b57cec5SDimitry Andric 
7404fcaf7f86SDimitry Andric   if (UNLIKELY(!__kmp_need_register_serial)) {
7405fcaf7f86SDimitry Andric     // We are in a forked child process. The registration was skipped during
7406fcaf7f86SDimitry Andric     // serial initialization in __kmp_atfork_child handler. Do it here.
7407fcaf7f86SDimitry Andric     __kmp_register_library_startup();
7408fcaf7f86SDimitry Andric   }
7409fcaf7f86SDimitry Andric 
74100b57cec5SDimitry Andric   // Save the previous value for the __kmp_dflt_team_nth so that
74110b57cec5SDimitry Andric   // we can avoid some reinitialization if it hasn't changed.
74120b57cec5SDimitry Andric   prev_dflt_team_nth = __kmp_dflt_team_nth;
74130b57cec5SDimitry Andric 
74140b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
74150b57cec5SDimitry Andric   // __kmp_affinity_initialize() will try to set __kmp_ncores to the
74160b57cec5SDimitry Andric   // number of cores on the machine.
7417bdd1243dSDimitry Andric   __kmp_affinity_initialize(__kmp_affinity);
74180b57cec5SDimitry Andric 
74190b57cec5SDimitry Andric #endif /* KMP_AFFINITY_SUPPORTED */
74200b57cec5SDimitry Andric 
74210b57cec5SDimitry Andric   KMP_ASSERT(__kmp_xproc > 0);
74220b57cec5SDimitry Andric   if (__kmp_avail_proc == 0) {
74230b57cec5SDimitry Andric     __kmp_avail_proc = __kmp_xproc;
74240b57cec5SDimitry Andric   }
74250b57cec5SDimitry Andric 
74260b57cec5SDimitry Andric   // If there were empty places in num_threads list (OMP_NUM_THREADS=,,2,3),
74270b57cec5SDimitry Andric   // correct them now
74280b57cec5SDimitry Andric   j = 0;
74290b57cec5SDimitry Andric   while ((j < __kmp_nested_nth.used) && !__kmp_nested_nth.nth[j]) {
74300b57cec5SDimitry Andric     __kmp_nested_nth.nth[j] = __kmp_dflt_team_nth = __kmp_dflt_team_nth_ub =
74310b57cec5SDimitry Andric         __kmp_avail_proc;
74320b57cec5SDimitry Andric     j++;
74330b57cec5SDimitry Andric   }
74340b57cec5SDimitry Andric 
74350b57cec5SDimitry Andric   if (__kmp_dflt_team_nth == 0) {
74360b57cec5SDimitry Andric #ifdef KMP_DFLT_NTH_CORES
74370b57cec5SDimitry Andric     // Default #threads = #cores
74380b57cec5SDimitry Andric     __kmp_dflt_team_nth = __kmp_ncores;
74390b57cec5SDimitry Andric     KA_TRACE(20, ("__kmp_middle_initialize: setting __kmp_dflt_team_nth = "
74400b57cec5SDimitry Andric                   "__kmp_ncores (%d)\n",
74410b57cec5SDimitry Andric                   __kmp_dflt_team_nth));
74420b57cec5SDimitry Andric #else
74430b57cec5SDimitry Andric     // Default #threads = #available OS procs
74440b57cec5SDimitry Andric     __kmp_dflt_team_nth = __kmp_avail_proc;
74450b57cec5SDimitry Andric     KA_TRACE(20, ("__kmp_middle_initialize: setting __kmp_dflt_team_nth = "
74460b57cec5SDimitry Andric                   "__kmp_avail_proc(%d)\n",
74470b57cec5SDimitry Andric                   __kmp_dflt_team_nth));
74480b57cec5SDimitry Andric #endif /* KMP_DFLT_NTH_CORES */
74490b57cec5SDimitry Andric   }
74500b57cec5SDimitry Andric 
74510b57cec5SDimitry Andric   if (__kmp_dflt_team_nth < KMP_MIN_NTH) {
74520b57cec5SDimitry Andric     __kmp_dflt_team_nth = KMP_MIN_NTH;
74530b57cec5SDimitry Andric   }
74540b57cec5SDimitry Andric   if (__kmp_dflt_team_nth > __kmp_sys_max_nth) {
74550b57cec5SDimitry Andric     __kmp_dflt_team_nth = __kmp_sys_max_nth;
74560b57cec5SDimitry Andric   }
74570b57cec5SDimitry Andric 
7458fe6060f1SDimitry Andric   if (__kmp_nesting_mode > 0)
7459fe6060f1SDimitry Andric     __kmp_set_nesting_mode_threads();
7460fe6060f1SDimitry Andric 
74610b57cec5SDimitry Andric   // There's no harm in continuing if the following check fails,
74620b57cec5SDimitry Andric   // but it indicates an error in the previous logic.
74630b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_dflt_team_nth <= __kmp_dflt_team_nth_ub);
74640b57cec5SDimitry Andric 
74650b57cec5SDimitry Andric   if (__kmp_dflt_team_nth != prev_dflt_team_nth) {
74660b57cec5SDimitry Andric     // Run through the __kmp_threads array and set the num threads icv for each
74670b57cec5SDimitry Andric     // root thread that is currently registered with the RTL (which has not
74680b57cec5SDimitry Andric     // already explicitly set its nthreads-var with a call to
74690b57cec5SDimitry Andric     // omp_set_num_threads()).
74700b57cec5SDimitry Andric     for (i = 0; i < __kmp_threads_capacity; i++) {
74710b57cec5SDimitry Andric       kmp_info_t *thread = __kmp_threads[i];
74720b57cec5SDimitry Andric       if (thread == NULL)
74730b57cec5SDimitry Andric         continue;
74740b57cec5SDimitry Andric       if (thread->th.th_current_task->td_icvs.nproc != 0)
74750b57cec5SDimitry Andric         continue;
74760b57cec5SDimitry Andric 
74770b57cec5SDimitry Andric       set__nproc(__kmp_threads[i], __kmp_dflt_team_nth);
74780b57cec5SDimitry Andric     }
74790b57cec5SDimitry Andric   }
74800b57cec5SDimitry Andric   KA_TRACE(
74810b57cec5SDimitry Andric       20,
74820b57cec5SDimitry Andric       ("__kmp_middle_initialize: final value for __kmp_dflt_team_nth = %d\n",
74830b57cec5SDimitry Andric        __kmp_dflt_team_nth));
74840b57cec5SDimitry Andric 
74850b57cec5SDimitry Andric #ifdef KMP_ADJUST_BLOCKTIME
74860b57cec5SDimitry Andric   /* Adjust blocktime to zero if necessary  now that __kmp_avail_proc is set */
74870b57cec5SDimitry Andric   if (!__kmp_env_blocktime && (__kmp_avail_proc > 0)) {
74880b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(__kmp_avail_proc > 0);
74890b57cec5SDimitry Andric     if (__kmp_nth > __kmp_avail_proc) {
74900b57cec5SDimitry Andric       __kmp_zero_bt = TRUE;
74910b57cec5SDimitry Andric     }
74920b57cec5SDimitry Andric   }
74930b57cec5SDimitry Andric #endif /* KMP_ADJUST_BLOCKTIME */
74940b57cec5SDimitry Andric 
74950b57cec5SDimitry Andric   /* we have finished middle initialization */
74960b57cec5SDimitry Andric   TCW_SYNC_4(__kmp_init_middle, TRUE);
74970b57cec5SDimitry Andric 
74980b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_do_middle_initialize: exit\n"));
74990b57cec5SDimitry Andric }
75000b57cec5SDimitry Andric 
__kmp_middle_initialize(void)75010b57cec5SDimitry Andric void __kmp_middle_initialize(void) {
75020b57cec5SDimitry Andric   if (__kmp_init_middle) {
75030b57cec5SDimitry Andric     return;
75040b57cec5SDimitry Andric   }
75050b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
75060b57cec5SDimitry Andric   if (__kmp_init_middle) {
75070b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_initz_lock);
75080b57cec5SDimitry Andric     return;
75090b57cec5SDimitry Andric   }
75100b57cec5SDimitry Andric   __kmp_do_middle_initialize();
75110b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
75120b57cec5SDimitry Andric }
75130b57cec5SDimitry Andric 
__kmp_parallel_initialize(void)75140b57cec5SDimitry Andric void __kmp_parallel_initialize(void) {
75150b57cec5SDimitry Andric   int gtid = __kmp_entry_gtid(); // this might be a new root
75160b57cec5SDimitry Andric 
75170b57cec5SDimitry Andric   /* synchronize parallel initialization (for sibling) */
75180b57cec5SDimitry Andric   if (TCR_4(__kmp_init_parallel))
75190b57cec5SDimitry Andric     return;
75200b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
75210b57cec5SDimitry Andric   if (TCR_4(__kmp_init_parallel)) {
75220b57cec5SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_initz_lock);
75230b57cec5SDimitry Andric     return;
75240b57cec5SDimitry Andric   }
75250b57cec5SDimitry Andric 
75260b57cec5SDimitry Andric   /* TODO reinitialization after we have already shut down */
75270b57cec5SDimitry Andric   if (TCR_4(__kmp_global.g.g_done)) {
75280b57cec5SDimitry Andric     KA_TRACE(
75290b57cec5SDimitry Andric         10,
75300b57cec5SDimitry Andric         ("__kmp_parallel_initialize: attempt to init while shutting down\n"));
75310b57cec5SDimitry Andric     __kmp_infinite_loop();
75320b57cec5SDimitry Andric   }
75330b57cec5SDimitry Andric 
75340b57cec5SDimitry Andric   /* jc: The lock __kmp_initz_lock is already held, so calling
75350b57cec5SDimitry Andric      __kmp_serial_initialize would cause a deadlock.  So we call
75360b57cec5SDimitry Andric      __kmp_do_serial_initialize directly. */
75370b57cec5SDimitry Andric   if (!__kmp_init_middle) {
75380b57cec5SDimitry Andric     __kmp_do_middle_initialize();
75390b57cec5SDimitry Andric   }
7540fe6060f1SDimitry Andric   __kmp_assign_root_init_mask();
75410b57cec5SDimitry Andric   __kmp_resume_if_hard_paused();
75420b57cec5SDimitry Andric 
75430b57cec5SDimitry Andric   /* begin initialization */
75440b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_parallel_initialize: enter\n"));
75450b57cec5SDimitry Andric   KMP_ASSERT(KMP_UBER_GTID(gtid));
75460b57cec5SDimitry Andric 
75470b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
75480b57cec5SDimitry Andric   // Save the FP control regs.
75490b57cec5SDimitry Andric   // Worker threads will set theirs to these values at thread startup.
75500b57cec5SDimitry Andric   __kmp_store_x87_fpu_control_word(&__kmp_init_x87_fpu_control_word);
75510b57cec5SDimitry Andric   __kmp_store_mxcsr(&__kmp_init_mxcsr);
75520b57cec5SDimitry Andric   __kmp_init_mxcsr &= KMP_X86_MXCSR_MASK;
75530b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
75540b57cec5SDimitry Andric 
75550b57cec5SDimitry Andric #if KMP_OS_UNIX
75560b57cec5SDimitry Andric #if KMP_HANDLE_SIGNALS
75570b57cec5SDimitry Andric   /*  must be after __kmp_serial_initialize  */
75580b57cec5SDimitry Andric   __kmp_install_signals(TRUE);
75590b57cec5SDimitry Andric #endif
75600b57cec5SDimitry Andric #endif
75610b57cec5SDimitry Andric 
75620b57cec5SDimitry Andric   __kmp_suspend_initialize();
75630b57cec5SDimitry Andric 
75640b57cec5SDimitry Andric #if defined(USE_LOAD_BALANCE)
75650b57cec5SDimitry Andric   if (__kmp_global.g.g_dynamic_mode == dynamic_default) {
75660b57cec5SDimitry Andric     __kmp_global.g.g_dynamic_mode = dynamic_load_balance;
75670b57cec5SDimitry Andric   }
75680b57cec5SDimitry Andric #else
75690b57cec5SDimitry Andric   if (__kmp_global.g.g_dynamic_mode == dynamic_default) {
75700b57cec5SDimitry Andric     __kmp_global.g.g_dynamic_mode = dynamic_thread_limit;
75710b57cec5SDimitry Andric   }
75720b57cec5SDimitry Andric #endif
75730b57cec5SDimitry Andric 
75740b57cec5SDimitry Andric   if (__kmp_version) {
75750b57cec5SDimitry Andric     __kmp_print_version_2();
75760b57cec5SDimitry Andric   }
75770b57cec5SDimitry Andric 
75780b57cec5SDimitry Andric   /* we have finished parallel initialization */
75790b57cec5SDimitry Andric   TCW_SYNC_4(__kmp_init_parallel, TRUE);
75800b57cec5SDimitry Andric 
75810b57cec5SDimitry Andric   KMP_MB();
75820b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_parallel_initialize: exit\n"));
75830b57cec5SDimitry Andric 
75840b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
75850b57cec5SDimitry Andric }
75860b57cec5SDimitry Andric 
__kmp_hidden_helper_initialize()7587e8d8bef9SDimitry Andric void __kmp_hidden_helper_initialize() {
7588e8d8bef9SDimitry Andric   if (TCR_4(__kmp_init_hidden_helper))
7589e8d8bef9SDimitry Andric     return;
7590e8d8bef9SDimitry Andric 
7591e8d8bef9SDimitry Andric   // __kmp_parallel_initialize is required before we initialize hidden helper
7592e8d8bef9SDimitry Andric   if (!TCR_4(__kmp_init_parallel))
7593e8d8bef9SDimitry Andric     __kmp_parallel_initialize();
7594e8d8bef9SDimitry Andric 
7595e8d8bef9SDimitry Andric   // Double check. Note that this double check should not be placed before
7596e8d8bef9SDimitry Andric   // __kmp_parallel_initialize as it will cause dead lock.
7597e8d8bef9SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
7598e8d8bef9SDimitry Andric   if (TCR_4(__kmp_init_hidden_helper)) {
7599e8d8bef9SDimitry Andric     __kmp_release_bootstrap_lock(&__kmp_initz_lock);
7600e8d8bef9SDimitry Andric     return;
7601e8d8bef9SDimitry Andric   }
7602e8d8bef9SDimitry Andric 
7603bdd1243dSDimitry Andric #if KMP_AFFINITY_SUPPORTED
7604bdd1243dSDimitry Andric   // Initialize hidden helper affinity settings.
7605bdd1243dSDimitry Andric   // The above __kmp_parallel_initialize() will initialize
7606bdd1243dSDimitry Andric   // regular affinity (and topology) if not already done.
7607bdd1243dSDimitry Andric   if (!__kmp_hh_affinity.flags.initialized)
7608bdd1243dSDimitry Andric     __kmp_affinity_initialize(__kmp_hh_affinity);
7609bdd1243dSDimitry Andric #endif
7610bdd1243dSDimitry Andric 
7611e8d8bef9SDimitry Andric   // Set the count of hidden helper tasks to be executed to zero
7612e8d8bef9SDimitry Andric   KMP_ATOMIC_ST_REL(&__kmp_unexecuted_hidden_helper_tasks, 0);
7613e8d8bef9SDimitry Andric 
7614e8d8bef9SDimitry Andric   // Set the global variable indicating that we're initializing hidden helper
7615e8d8bef9SDimitry Andric   // team/threads
7616e8d8bef9SDimitry Andric   TCW_SYNC_4(__kmp_init_hidden_helper_threads, TRUE);
7617e8d8bef9SDimitry Andric 
7618e8d8bef9SDimitry Andric   // Platform independent initialization
7619e8d8bef9SDimitry Andric   __kmp_do_initialize_hidden_helper_threads();
7620e8d8bef9SDimitry Andric 
7621e8d8bef9SDimitry Andric   // Wait here for the finish of initialization of hidden helper teams
7622e8d8bef9SDimitry Andric   __kmp_hidden_helper_threads_initz_wait();
7623e8d8bef9SDimitry Andric 
7624e8d8bef9SDimitry Andric   // We have finished hidden helper initialization
7625e8d8bef9SDimitry Andric   TCW_SYNC_4(__kmp_init_hidden_helper, TRUE);
7626e8d8bef9SDimitry Andric 
7627e8d8bef9SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
7628e8d8bef9SDimitry Andric }
7629e8d8bef9SDimitry Andric 
76300b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
76310b57cec5SDimitry Andric 
__kmp_run_before_invoked_task(int gtid,int tid,kmp_info_t * this_thr,kmp_team_t * team)76320b57cec5SDimitry Andric void __kmp_run_before_invoked_task(int gtid, int tid, kmp_info_t *this_thr,
76330b57cec5SDimitry Andric                                    kmp_team_t *team) {
76340b57cec5SDimitry Andric   kmp_disp_t *dispatch;
76350b57cec5SDimitry Andric 
76360b57cec5SDimitry Andric   KMP_MB();
76370b57cec5SDimitry Andric 
76380b57cec5SDimitry Andric   /* none of the threads have encountered any constructs, yet. */
76390b57cec5SDimitry Andric   this_thr->th.th_local.this_construct = 0;
76400b57cec5SDimitry Andric #if KMP_CACHE_MANAGE
76410b57cec5SDimitry Andric   KMP_CACHE_PREFETCH(&this_thr->th.th_bar[bs_forkjoin_barrier].bb.b_arrived);
76420b57cec5SDimitry Andric #endif /* KMP_CACHE_MANAGE */
76430b57cec5SDimitry Andric   dispatch = (kmp_disp_t *)TCR_PTR(this_thr->th.th_dispatch);
76440b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(dispatch);
76450b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team->t.t_dispatch);
76460b57cec5SDimitry Andric   // KMP_DEBUG_ASSERT( this_thr->th.th_dispatch == &team->t.t_dispatch[
76470b57cec5SDimitry Andric   // this_thr->th.th_info.ds.ds_tid ] );
76480b57cec5SDimitry Andric 
76490b57cec5SDimitry Andric   dispatch->th_disp_index = 0; /* reset the dispatch buffer counter */
76500b57cec5SDimitry Andric   dispatch->th_doacross_buf_idx = 0; // reset doacross dispatch buffer counter
76510b57cec5SDimitry Andric   if (__kmp_env_consistency_check)
76520b57cec5SDimitry Andric     __kmp_push_parallel(gtid, team->t.t_ident);
76530b57cec5SDimitry Andric 
76540b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
76550b57cec5SDimitry Andric }
76560b57cec5SDimitry Andric 
__kmp_run_after_invoked_task(int gtid,int tid,kmp_info_t * this_thr,kmp_team_t * team)76570b57cec5SDimitry Andric void __kmp_run_after_invoked_task(int gtid, int tid, kmp_info_t *this_thr,
76580b57cec5SDimitry Andric                                   kmp_team_t *team) {
76590b57cec5SDimitry Andric   if (__kmp_env_consistency_check)
76600b57cec5SDimitry Andric     __kmp_pop_parallel(gtid, team->t.t_ident);
76610b57cec5SDimitry Andric 
76620b57cec5SDimitry Andric   __kmp_finish_implicit_task(this_thr);
76630b57cec5SDimitry Andric }
76640b57cec5SDimitry Andric 
__kmp_invoke_task_func(int gtid)76650b57cec5SDimitry Andric int __kmp_invoke_task_func(int gtid) {
76660b57cec5SDimitry Andric   int rc;
76670b57cec5SDimitry Andric   int tid = __kmp_tid_from_gtid(gtid);
76680b57cec5SDimitry Andric   kmp_info_t *this_thr = __kmp_threads[gtid];
76690b57cec5SDimitry Andric   kmp_team_t *team = this_thr->th.th_team;
76700b57cec5SDimitry Andric 
76710b57cec5SDimitry Andric   __kmp_run_before_invoked_task(gtid, tid, this_thr, team);
76720b57cec5SDimitry Andric #if USE_ITT_BUILD
76730b57cec5SDimitry Andric   if (__itt_stack_caller_create_ptr) {
7674fe6060f1SDimitry Andric     // inform ittnotify about entering user's code
7675fe6060f1SDimitry Andric     if (team->t.t_stack_id != NULL) {
7676fe6060f1SDimitry Andric       __kmp_itt_stack_callee_enter((__itt_caller)team->t.t_stack_id);
7677fe6060f1SDimitry Andric     } else {
7678fe6060f1SDimitry Andric       KMP_DEBUG_ASSERT(team->t.t_parent->t.t_stack_id != NULL);
76790b57cec5SDimitry Andric       __kmp_itt_stack_callee_enter(
7680fe6060f1SDimitry Andric           (__itt_caller)team->t.t_parent->t.t_stack_id);
7681fe6060f1SDimitry Andric     }
76820b57cec5SDimitry Andric   }
76830b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
76840b57cec5SDimitry Andric #if INCLUDE_SSC_MARKS
76850b57cec5SDimitry Andric   SSC_MARK_INVOKING();
76860b57cec5SDimitry Andric #endif
76870b57cec5SDimitry Andric 
76880b57cec5SDimitry Andric #if OMPT_SUPPORT
76890b57cec5SDimitry Andric   void *dummy;
7690489b1cf2SDimitry Andric   void **exit_frame_p;
76910b57cec5SDimitry Andric   ompt_data_t *my_task_data;
76920b57cec5SDimitry Andric   ompt_data_t *my_parallel_data;
76930b57cec5SDimitry Andric   int ompt_team_size;
76940b57cec5SDimitry Andric 
76950b57cec5SDimitry Andric   if (ompt_enabled.enabled) {
7696fe6060f1SDimitry Andric     exit_frame_p = &(team->t.t_implicit_task_taskdata[tid]
7697fe6060f1SDimitry Andric                          .ompt_task_info.frame.exit_frame.ptr);
76980b57cec5SDimitry Andric   } else {
7699489b1cf2SDimitry Andric     exit_frame_p = &dummy;
77000b57cec5SDimitry Andric   }
77010b57cec5SDimitry Andric 
77020b57cec5SDimitry Andric   my_task_data =
77030b57cec5SDimitry Andric       &(team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data);
77040b57cec5SDimitry Andric   my_parallel_data = &(team->t.ompt_team_info.parallel_data);
77050b57cec5SDimitry Andric   if (ompt_enabled.ompt_callback_implicit_task) {
77060b57cec5SDimitry Andric     ompt_team_size = team->t.t_nproc;
77070b57cec5SDimitry Andric     ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
77080b57cec5SDimitry Andric         ompt_scope_begin, my_parallel_data, my_task_data, ompt_team_size,
7709489b1cf2SDimitry Andric         __kmp_tid_from_gtid(gtid), ompt_task_implicit);
77100b57cec5SDimitry Andric     OMPT_CUR_TASK_INFO(this_thr)->thread_num = __kmp_tid_from_gtid(gtid);
77110b57cec5SDimitry Andric   }
77120b57cec5SDimitry Andric #endif
77130b57cec5SDimitry Andric 
77140b57cec5SDimitry Andric #if KMP_STATS_ENABLED
77150b57cec5SDimitry Andric   stats_state_e previous_state = KMP_GET_THREAD_STATE();
77160b57cec5SDimitry Andric   if (previous_state == stats_state_e::TEAMS_REGION) {
77170b57cec5SDimitry Andric     KMP_PUSH_PARTITIONED_TIMER(OMP_teams);
77180b57cec5SDimitry Andric   } else {
77190b57cec5SDimitry Andric     KMP_PUSH_PARTITIONED_TIMER(OMP_parallel);
77200b57cec5SDimitry Andric   }
77210b57cec5SDimitry Andric   KMP_SET_THREAD_STATE(IMPLICIT_TASK);
77220b57cec5SDimitry Andric #endif
77230b57cec5SDimitry Andric 
77240b57cec5SDimitry Andric   rc = __kmp_invoke_microtask((microtask_t)TCR_SYNC_PTR(team->t.t_pkfn), gtid,
77250b57cec5SDimitry Andric                               tid, (int)team->t.t_argc, (void **)team->t.t_argv
77260b57cec5SDimitry Andric #if OMPT_SUPPORT
77270b57cec5SDimitry Andric                               ,
7728489b1cf2SDimitry Andric                               exit_frame_p
77290b57cec5SDimitry Andric #endif
77300b57cec5SDimitry Andric   );
77310b57cec5SDimitry Andric #if OMPT_SUPPORT
7732489b1cf2SDimitry Andric   *exit_frame_p = NULL;
7733489b1cf2SDimitry Andric   this_thr->th.ompt_thread_info.parallel_flags |= ompt_parallel_team;
77340b57cec5SDimitry Andric #endif
77350b57cec5SDimitry Andric 
77360b57cec5SDimitry Andric #if KMP_STATS_ENABLED
77370b57cec5SDimitry Andric   if (previous_state == stats_state_e::TEAMS_REGION) {
77380b57cec5SDimitry Andric     KMP_SET_THREAD_STATE(previous_state);
77390b57cec5SDimitry Andric   }
77400b57cec5SDimitry Andric   KMP_POP_PARTITIONED_TIMER();
77410b57cec5SDimitry Andric #endif
77420b57cec5SDimitry Andric 
77430b57cec5SDimitry Andric #if USE_ITT_BUILD
77440b57cec5SDimitry Andric   if (__itt_stack_caller_create_ptr) {
7745fe6060f1SDimitry Andric     // inform ittnotify about leaving user's code
7746fe6060f1SDimitry Andric     if (team->t.t_stack_id != NULL) {
7747fe6060f1SDimitry Andric       __kmp_itt_stack_callee_leave((__itt_caller)team->t.t_stack_id);
7748fe6060f1SDimitry Andric     } else {
7749fe6060f1SDimitry Andric       KMP_DEBUG_ASSERT(team->t.t_parent->t.t_stack_id != NULL);
77500b57cec5SDimitry Andric       __kmp_itt_stack_callee_leave(
7751fe6060f1SDimitry Andric           (__itt_caller)team->t.t_parent->t.t_stack_id);
7752fe6060f1SDimitry Andric     }
77530b57cec5SDimitry Andric   }
77540b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
77550b57cec5SDimitry Andric   __kmp_run_after_invoked_task(gtid, tid, this_thr, team);
77560b57cec5SDimitry Andric 
77570b57cec5SDimitry Andric   return rc;
77580b57cec5SDimitry Andric }
77590b57cec5SDimitry Andric 
__kmp_teams_master(int gtid)77600b57cec5SDimitry Andric void __kmp_teams_master(int gtid) {
7761fe6060f1SDimitry Andric   // This routine is called by all primary threads in teams construct
77620b57cec5SDimitry Andric   kmp_info_t *thr = __kmp_threads[gtid];
77630b57cec5SDimitry Andric   kmp_team_t *team = thr->th.th_team;
77640b57cec5SDimitry Andric   ident_t *loc = team->t.t_ident;
77650b57cec5SDimitry Andric   thr->th.th_set_nproc = thr->th.th_teams_size.nth;
77660b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(thr->th.th_teams_microtask);
77670b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(thr->th.th_set_nproc);
77680b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_teams_master: T#%d, Tid %d, microtask %p\n", gtid,
77690b57cec5SDimitry Andric                 __kmp_tid_from_gtid(gtid), thr->th.th_teams_microtask));
77700b57cec5SDimitry Andric 
77710b57cec5SDimitry Andric   // This thread is a new CG root.  Set up the proper variables.
77720b57cec5SDimitry Andric   kmp_cg_root_t *tmp = (kmp_cg_root_t *)__kmp_allocate(sizeof(kmp_cg_root_t));
77730b57cec5SDimitry Andric   tmp->cg_root = thr; // Make thr the CG root
7774fe6060f1SDimitry Andric   // Init to thread limit stored when league primary threads were forked
77750b57cec5SDimitry Andric   tmp->cg_thread_limit = thr->th.th_current_task->td_icvs.thread_limit;
77760b57cec5SDimitry Andric   tmp->cg_nthreads = 1; // Init counter to one active thread, this one
77770b57cec5SDimitry Andric   KA_TRACE(100, ("__kmp_teams_master: Thread %p created node %p and init"
77780b57cec5SDimitry Andric                  " cg_nthreads to 1\n",
77790b57cec5SDimitry Andric                  thr, tmp));
77800b57cec5SDimitry Andric   tmp->up = thr->th.th_cg_roots;
77810b57cec5SDimitry Andric   thr->th.th_cg_roots = tmp;
77820b57cec5SDimitry Andric 
77830b57cec5SDimitry Andric // Launch league of teams now, but not let workers execute
77840b57cec5SDimitry Andric // (they hang on fork barrier until next parallel)
77850b57cec5SDimitry Andric #if INCLUDE_SSC_MARKS
77860b57cec5SDimitry Andric   SSC_MARK_FORKING();
77870b57cec5SDimitry Andric #endif
77880b57cec5SDimitry Andric   __kmp_fork_call(loc, gtid, fork_context_intel, team->t.t_argc,
77890b57cec5SDimitry Andric                   (microtask_t)thr->th.th_teams_microtask, // "wrapped" task
77900b57cec5SDimitry Andric                   VOLATILE_CAST(launch_t) __kmp_invoke_task_func, NULL);
77910b57cec5SDimitry Andric #if INCLUDE_SSC_MARKS
77920b57cec5SDimitry Andric   SSC_MARK_JOINING();
77930b57cec5SDimitry Andric #endif
77940b57cec5SDimitry Andric   // If the team size was reduced from the limit, set it to the new size
77950b57cec5SDimitry Andric   if (thr->th.th_team_nproc < thr->th.th_teams_size.nth)
77960b57cec5SDimitry Andric     thr->th.th_teams_size.nth = thr->th.th_team_nproc;
77970b57cec5SDimitry Andric   // AC: last parameter "1" eliminates join barrier which won't work because
77980b57cec5SDimitry Andric   // worker threads are in a fork barrier waiting for more parallel regions
77990b57cec5SDimitry Andric   __kmp_join_call(loc, gtid
78000b57cec5SDimitry Andric #if OMPT_SUPPORT
78010b57cec5SDimitry Andric                   ,
78020b57cec5SDimitry Andric                   fork_context_intel
78030b57cec5SDimitry Andric #endif
78040b57cec5SDimitry Andric                   ,
78050b57cec5SDimitry Andric                   1);
78060b57cec5SDimitry Andric }
78070b57cec5SDimitry Andric 
__kmp_invoke_teams_master(int gtid)78080b57cec5SDimitry Andric int __kmp_invoke_teams_master(int gtid) {
78090b57cec5SDimitry Andric   kmp_info_t *this_thr = __kmp_threads[gtid];
78100b57cec5SDimitry Andric   kmp_team_t *team = this_thr->th.th_team;
78110b57cec5SDimitry Andric #if KMP_DEBUG
78120b57cec5SDimitry Andric   if (!__kmp_threads[gtid]->th.th_team->t.t_serialized)
78130b57cec5SDimitry Andric     KMP_DEBUG_ASSERT((void *)__kmp_threads[gtid]->th.th_team->t.t_pkfn ==
78140b57cec5SDimitry Andric                      (void *)__kmp_teams_master);
78150b57cec5SDimitry Andric #endif
78160b57cec5SDimitry Andric   __kmp_run_before_invoked_task(gtid, 0, this_thr, team);
7817489b1cf2SDimitry Andric #if OMPT_SUPPORT
7818489b1cf2SDimitry Andric   int tid = __kmp_tid_from_gtid(gtid);
7819489b1cf2SDimitry Andric   ompt_data_t *task_data =
7820489b1cf2SDimitry Andric       &team->t.t_implicit_task_taskdata[tid].ompt_task_info.task_data;
7821489b1cf2SDimitry Andric   ompt_data_t *parallel_data = &team->t.ompt_team_info.parallel_data;
7822489b1cf2SDimitry Andric   if (ompt_enabled.ompt_callback_implicit_task) {
7823489b1cf2SDimitry Andric     ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
7824489b1cf2SDimitry Andric         ompt_scope_begin, parallel_data, task_data, team->t.t_nproc, tid,
7825489b1cf2SDimitry Andric         ompt_task_initial);
7826489b1cf2SDimitry Andric     OMPT_CUR_TASK_INFO(this_thr)->thread_num = tid;
7827489b1cf2SDimitry Andric   }
7828489b1cf2SDimitry Andric #endif
78290b57cec5SDimitry Andric   __kmp_teams_master(gtid);
7830489b1cf2SDimitry Andric #if OMPT_SUPPORT
7831489b1cf2SDimitry Andric   this_thr->th.ompt_thread_info.parallel_flags |= ompt_parallel_league;
7832489b1cf2SDimitry Andric #endif
78330b57cec5SDimitry Andric   __kmp_run_after_invoked_task(gtid, 0, this_thr, team);
78340b57cec5SDimitry Andric   return 1;
78350b57cec5SDimitry Andric }
78360b57cec5SDimitry Andric 
78370b57cec5SDimitry Andric /* this sets the requested number of threads for the next parallel region
78380b57cec5SDimitry Andric    encountered by this team. since this should be enclosed in the forkjoin
7839480093f4SDimitry Andric    critical section it should avoid race conditions with asymmetrical nested
78400b57cec5SDimitry Andric    parallelism */
78410b57cec5SDimitry Andric 
__kmp_push_num_threads(ident_t * id,int gtid,int num_threads)78420b57cec5SDimitry Andric void __kmp_push_num_threads(ident_t *id, int gtid, int num_threads) {
78430b57cec5SDimitry Andric   kmp_info_t *thr = __kmp_threads[gtid];
78440b57cec5SDimitry Andric 
78450b57cec5SDimitry Andric   if (num_threads > 0)
78460b57cec5SDimitry Andric     thr->th.th_set_nproc = num_threads;
78470b57cec5SDimitry Andric }
78480b57cec5SDimitry Andric 
__kmp_push_thread_limit(kmp_info_t * thr,int num_teams,int num_threads)7849fe6060f1SDimitry Andric static void __kmp_push_thread_limit(kmp_info_t *thr, int num_teams,
7850fe6060f1SDimitry Andric                                     int num_threads) {
7851fe6060f1SDimitry Andric   KMP_DEBUG_ASSERT(thr);
7852fe6060f1SDimitry Andric   // Remember the number of threads for inner parallel regions
7853fe6060f1SDimitry Andric   if (!TCR_4(__kmp_init_middle))
7854fe6060f1SDimitry Andric     __kmp_middle_initialize(); // get internal globals calculated
7855fe6060f1SDimitry Andric   __kmp_assign_root_init_mask();
7856fe6060f1SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_avail_proc);
7857fe6060f1SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_dflt_team_nth);
7858fe6060f1SDimitry Andric 
7859fe6060f1SDimitry Andric   if (num_threads == 0) {
7860fe6060f1SDimitry Andric     if (__kmp_teams_thread_limit > 0) {
7861fe6060f1SDimitry Andric       num_threads = __kmp_teams_thread_limit;
7862fe6060f1SDimitry Andric     } else {
7863fe6060f1SDimitry Andric       num_threads = __kmp_avail_proc / num_teams;
7864fe6060f1SDimitry Andric     }
7865fe6060f1SDimitry Andric     // adjust num_threads w/o warning as it is not user setting
7866fe6060f1SDimitry Andric     // num_threads = min(num_threads, nthreads-var, thread-limit-var)
7867fe6060f1SDimitry Andric     // no thread_limit clause specified -  do not change thread-limit-var ICV
7868fe6060f1SDimitry Andric     if (num_threads > __kmp_dflt_team_nth) {
7869fe6060f1SDimitry Andric       num_threads = __kmp_dflt_team_nth; // honor nthreads-var ICV
7870fe6060f1SDimitry Andric     }
7871fe6060f1SDimitry Andric     if (num_threads > thr->th.th_current_task->td_icvs.thread_limit) {
7872fe6060f1SDimitry Andric       num_threads = thr->th.th_current_task->td_icvs.thread_limit;
7873fe6060f1SDimitry Andric     } // prevent team size to exceed thread-limit-var
7874fe6060f1SDimitry Andric     if (num_teams * num_threads > __kmp_teams_max_nth) {
7875fe6060f1SDimitry Andric       num_threads = __kmp_teams_max_nth / num_teams;
7876fe6060f1SDimitry Andric     }
7877fe6060f1SDimitry Andric     if (num_threads == 0) {
7878fe6060f1SDimitry Andric       num_threads = 1;
7879fe6060f1SDimitry Andric     }
7880fe6060f1SDimitry Andric   } else {
78810eae32dcSDimitry Andric     if (num_threads < 0) {
78820eae32dcSDimitry Andric       __kmp_msg(kmp_ms_warning, KMP_MSG(CantFormThrTeam, num_threads, 1),
78830eae32dcSDimitry Andric                 __kmp_msg_null);
78840eae32dcSDimitry Andric       num_threads = 1;
78850eae32dcSDimitry Andric     }
7886fe6060f1SDimitry Andric     // This thread will be the primary thread of the league primary threads
7887fe6060f1SDimitry Andric     // Store new thread limit; old limit is saved in th_cg_roots list
7888fe6060f1SDimitry Andric     thr->th.th_current_task->td_icvs.thread_limit = num_threads;
7889fe6060f1SDimitry Andric     // num_threads = min(num_threads, nthreads-var)
7890fe6060f1SDimitry Andric     if (num_threads > __kmp_dflt_team_nth) {
7891fe6060f1SDimitry Andric       num_threads = __kmp_dflt_team_nth; // honor nthreads-var ICV
7892fe6060f1SDimitry Andric     }
7893fe6060f1SDimitry Andric     if (num_teams * num_threads > __kmp_teams_max_nth) {
7894fe6060f1SDimitry Andric       int new_threads = __kmp_teams_max_nth / num_teams;
7895fe6060f1SDimitry Andric       if (new_threads == 0) {
7896fe6060f1SDimitry Andric         new_threads = 1;
7897fe6060f1SDimitry Andric       }
7898fe6060f1SDimitry Andric       if (new_threads != num_threads) {
7899fe6060f1SDimitry Andric         if (!__kmp_reserve_warn) { // user asked for too many threads
7900fe6060f1SDimitry Andric           __kmp_reserve_warn = 1; // conflicts with KMP_TEAMS_THREAD_LIMIT
7901fe6060f1SDimitry Andric           __kmp_msg(kmp_ms_warning,
7902fe6060f1SDimitry Andric                     KMP_MSG(CantFormThrTeam, num_threads, new_threads),
7903fe6060f1SDimitry Andric                     KMP_HNT(Unset_ALL_THREADS), __kmp_msg_null);
7904fe6060f1SDimitry Andric         }
7905fe6060f1SDimitry Andric       }
7906fe6060f1SDimitry Andric       num_threads = new_threads;
7907fe6060f1SDimitry Andric     }
7908fe6060f1SDimitry Andric   }
7909fe6060f1SDimitry Andric   thr->th.th_teams_size.nth = num_threads;
7910fe6060f1SDimitry Andric }
7911fe6060f1SDimitry Andric 
79120b57cec5SDimitry Andric /* this sets the requested number of teams for the teams region and/or
79130b57cec5SDimitry Andric    the number of threads for the next parallel region encountered  */
__kmp_push_num_teams(ident_t * id,int gtid,int num_teams,int num_threads)79140b57cec5SDimitry Andric void __kmp_push_num_teams(ident_t *id, int gtid, int num_teams,
79150b57cec5SDimitry Andric                           int num_threads) {
79160b57cec5SDimitry Andric   kmp_info_t *thr = __kmp_threads[gtid];
79170eae32dcSDimitry Andric   if (num_teams < 0) {
79180eae32dcSDimitry Andric     // OpenMP specification requires requested values to be positive,
79190eae32dcSDimitry Andric     // but people can send us any value, so we'd better check
79200eae32dcSDimitry Andric     __kmp_msg(kmp_ms_warning, KMP_MSG(NumTeamsNotPositive, num_teams, 1),
79210eae32dcSDimitry Andric               __kmp_msg_null);
79220eae32dcSDimitry Andric     num_teams = 1;
79230eae32dcSDimitry Andric   }
7924fe6060f1SDimitry Andric   if (num_teams == 0) {
7925fe6060f1SDimitry Andric     if (__kmp_nteams > 0) {
7926fe6060f1SDimitry Andric       num_teams = __kmp_nteams;
7927fe6060f1SDimitry Andric     } else {
79280b57cec5SDimitry Andric       num_teams = 1; // default number of teams is 1.
7929fe6060f1SDimitry Andric     }
7930fe6060f1SDimitry Andric   }
79310b57cec5SDimitry Andric   if (num_teams > __kmp_teams_max_nth) { // if too many teams requested?
79320b57cec5SDimitry Andric     if (!__kmp_reserve_warn) {
79330b57cec5SDimitry Andric       __kmp_reserve_warn = 1;
79340b57cec5SDimitry Andric       __kmp_msg(kmp_ms_warning,
79350b57cec5SDimitry Andric                 KMP_MSG(CantFormThrTeam, num_teams, __kmp_teams_max_nth),
79360b57cec5SDimitry Andric                 KMP_HNT(Unset_ALL_THREADS), __kmp_msg_null);
79370b57cec5SDimitry Andric     }
79380b57cec5SDimitry Andric     num_teams = __kmp_teams_max_nth;
79390b57cec5SDimitry Andric   }
79400b57cec5SDimitry Andric   // Set number of teams (number of threads in the outer "parallel" of the
79410b57cec5SDimitry Andric   // teams)
79420b57cec5SDimitry Andric   thr->th.th_set_nproc = thr->th.th_teams_size.nteams = num_teams;
79430b57cec5SDimitry Andric 
7944fe6060f1SDimitry Andric   __kmp_push_thread_limit(thr, num_teams, num_threads);
7945489b1cf2SDimitry Andric }
7946fe6060f1SDimitry Andric 
7947fe6060f1SDimitry Andric /* This sets the requested number of teams for the teams region and/or
7948fe6060f1SDimitry Andric    the number of threads for the next parallel region encountered  */
__kmp_push_num_teams_51(ident_t * id,int gtid,int num_teams_lb,int num_teams_ub,int num_threads)7949fe6060f1SDimitry Andric void __kmp_push_num_teams_51(ident_t *id, int gtid, int num_teams_lb,
7950fe6060f1SDimitry Andric                              int num_teams_ub, int num_threads) {
7951fe6060f1SDimitry Andric   kmp_info_t *thr = __kmp_threads[gtid];
7952fe6060f1SDimitry Andric   KMP_DEBUG_ASSERT(num_teams_lb >= 0 && num_teams_ub >= 0);
7953fe6060f1SDimitry Andric   KMP_DEBUG_ASSERT(num_teams_ub >= num_teams_lb);
7954fe6060f1SDimitry Andric   KMP_DEBUG_ASSERT(num_threads >= 0);
7955fe6060f1SDimitry Andric 
7956fe6060f1SDimitry Andric   if (num_teams_lb > num_teams_ub) {
7957fe6060f1SDimitry Andric     __kmp_fatal(KMP_MSG(FailedToCreateTeam, num_teams_lb, num_teams_ub),
7958fe6060f1SDimitry Andric                 KMP_HNT(SetNewBound, __kmp_teams_max_nth), __kmp_msg_null);
79590b57cec5SDimitry Andric   }
7960fe6060f1SDimitry Andric 
7961fe6060f1SDimitry Andric   int num_teams = 1; // defalt number of teams is 1.
7962fe6060f1SDimitry Andric 
7963fe6060f1SDimitry Andric   if (num_teams_lb == 0 && num_teams_ub > 0)
7964fe6060f1SDimitry Andric     num_teams_lb = num_teams_ub;
7965fe6060f1SDimitry Andric 
7966fe6060f1SDimitry Andric   if (num_teams_lb == 0 && num_teams_ub == 0) { // no num_teams clause
7967fe6060f1SDimitry Andric     num_teams = (__kmp_nteams > 0) ? __kmp_nteams : num_teams;
7968fe6060f1SDimitry Andric     if (num_teams > __kmp_teams_max_nth) {
7969fe6060f1SDimitry Andric       if (!__kmp_reserve_warn) {
7970fe6060f1SDimitry Andric         __kmp_reserve_warn = 1;
79710b57cec5SDimitry Andric         __kmp_msg(kmp_ms_warning,
7972fe6060f1SDimitry Andric                   KMP_MSG(CantFormThrTeam, num_teams, __kmp_teams_max_nth),
79730b57cec5SDimitry Andric                   KMP_HNT(Unset_ALL_THREADS), __kmp_msg_null);
79740b57cec5SDimitry Andric       }
7975fe6060f1SDimitry Andric       num_teams = __kmp_teams_max_nth;
7976fe6060f1SDimitry Andric     }
7977fe6060f1SDimitry Andric   } else if (num_teams_lb == num_teams_ub) { // requires exact number of teams
7978fe6060f1SDimitry Andric     num_teams = num_teams_ub;
7979fe6060f1SDimitry Andric   } else { // num_teams_lb <= num_teams <= num_teams_ub
79800eae32dcSDimitry Andric     if (num_threads <= 0) {
7981fe6060f1SDimitry Andric       if (num_teams_ub > __kmp_teams_max_nth) {
7982fe6060f1SDimitry Andric         num_teams = num_teams_lb;
7983fe6060f1SDimitry Andric       } else {
7984fe6060f1SDimitry Andric         num_teams = num_teams_ub;
7985fe6060f1SDimitry Andric       }
7986fe6060f1SDimitry Andric     } else {
7987fe6060f1SDimitry Andric       num_teams = (num_threads > __kmp_teams_max_nth)
7988fe6060f1SDimitry Andric                       ? num_teams
7989fe6060f1SDimitry Andric                       : __kmp_teams_max_nth / num_threads;
7990fe6060f1SDimitry Andric       if (num_teams < num_teams_lb) {
7991fe6060f1SDimitry Andric         num_teams = num_teams_lb;
7992fe6060f1SDimitry Andric       } else if (num_teams > num_teams_ub) {
7993fe6060f1SDimitry Andric         num_teams = num_teams_ub;
79940b57cec5SDimitry Andric       }
79950b57cec5SDimitry Andric     }
7996fe6060f1SDimitry Andric   }
7997fe6060f1SDimitry Andric   // Set number of teams (number of threads in the outer "parallel" of the
7998fe6060f1SDimitry Andric   // teams)
7999fe6060f1SDimitry Andric   thr->th.th_set_nproc = thr->th.th_teams_size.nteams = num_teams;
8000fe6060f1SDimitry Andric 
8001fe6060f1SDimitry Andric   __kmp_push_thread_limit(thr, num_teams, num_threads);
80020b57cec5SDimitry Andric }
80030b57cec5SDimitry Andric 
80040b57cec5SDimitry Andric // Set the proc_bind var to use in the following parallel region.
__kmp_push_proc_bind(ident_t * id,int gtid,kmp_proc_bind_t proc_bind)80050b57cec5SDimitry Andric void __kmp_push_proc_bind(ident_t *id, int gtid, kmp_proc_bind_t proc_bind) {
80060b57cec5SDimitry Andric   kmp_info_t *thr = __kmp_threads[gtid];
80070b57cec5SDimitry Andric   thr->th.th_set_proc_bind = proc_bind;
80080b57cec5SDimitry Andric }
80090b57cec5SDimitry Andric 
80100b57cec5SDimitry Andric /* Launch the worker threads into the microtask. */
80110b57cec5SDimitry Andric 
__kmp_internal_fork(ident_t * id,int gtid,kmp_team_t * team)80120b57cec5SDimitry Andric void __kmp_internal_fork(ident_t *id, int gtid, kmp_team_t *team) {
80130b57cec5SDimitry Andric   kmp_info_t *this_thr = __kmp_threads[gtid];
80140b57cec5SDimitry Andric 
80150b57cec5SDimitry Andric #ifdef KMP_DEBUG
80160b57cec5SDimitry Andric   int f;
80170b57cec5SDimitry Andric #endif /* KMP_DEBUG */
80180b57cec5SDimitry Andric 
80190b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team);
80200b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(this_thr->th.th_team == team);
80210b57cec5SDimitry Andric   KMP_ASSERT(KMP_MASTER_GTID(gtid));
80220b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
80230b57cec5SDimitry Andric 
80240b57cec5SDimitry Andric   team->t.t_construct = 0; /* no single directives seen yet */
80250b57cec5SDimitry Andric   team->t.t_ordered.dt.t_value =
80260b57cec5SDimitry Andric       0; /* thread 0 enters the ordered section first */
80270b57cec5SDimitry Andric 
80280b57cec5SDimitry Andric   /* Reset the identifiers on the dispatch buffer */
80290b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team->t.t_disp_buffer);
80300b57cec5SDimitry Andric   if (team->t.t_max_nproc > 1) {
80310b57cec5SDimitry Andric     int i;
80320b57cec5SDimitry Andric     for (i = 0; i < __kmp_dispatch_num_buffers; ++i) {
80330b57cec5SDimitry Andric       team->t.t_disp_buffer[i].buffer_index = i;
80340b57cec5SDimitry Andric       team->t.t_disp_buffer[i].doacross_buf_idx = i;
80350b57cec5SDimitry Andric     }
80360b57cec5SDimitry Andric   } else {
80370b57cec5SDimitry Andric     team->t.t_disp_buffer[0].buffer_index = 0;
80380b57cec5SDimitry Andric     team->t.t_disp_buffer[0].doacross_buf_idx = 0;
80390b57cec5SDimitry Andric   }
80400b57cec5SDimitry Andric 
80410b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
80420b57cec5SDimitry Andric   KMP_ASSERT(this_thr->th.th_team == team);
80430b57cec5SDimitry Andric 
80440b57cec5SDimitry Andric #ifdef KMP_DEBUG
80450b57cec5SDimitry Andric   for (f = 0; f < team->t.t_nproc; f++) {
80460b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(team->t.t_threads[f] &&
80470b57cec5SDimitry Andric                      team->t.t_threads[f]->th.th_team_nproc == team->t.t_nproc);
80480b57cec5SDimitry Andric   }
80490b57cec5SDimitry Andric #endif /* KMP_DEBUG */
80500b57cec5SDimitry Andric 
80510b57cec5SDimitry Andric   /* release the worker threads so they may begin working */
80520b57cec5SDimitry Andric   __kmp_fork_barrier(gtid, 0);
80530b57cec5SDimitry Andric }
80540b57cec5SDimitry Andric 
__kmp_internal_join(ident_t * id,int gtid,kmp_team_t * team)80550b57cec5SDimitry Andric void __kmp_internal_join(ident_t *id, int gtid, kmp_team_t *team) {
80560b57cec5SDimitry Andric   kmp_info_t *this_thr = __kmp_threads[gtid];
80570b57cec5SDimitry Andric 
80580b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(team);
80590b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(this_thr->th.th_team == team);
80600b57cec5SDimitry Andric   KMP_ASSERT(KMP_MASTER_GTID(gtid));
80610b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
80620b57cec5SDimitry Andric 
80630b57cec5SDimitry Andric   /* Join barrier after fork */
80640b57cec5SDimitry Andric 
80650b57cec5SDimitry Andric #ifdef KMP_DEBUG
80660b57cec5SDimitry Andric   if (__kmp_threads[gtid] &&
80670b57cec5SDimitry Andric       __kmp_threads[gtid]->th.th_team_nproc != team->t.t_nproc) {
80680b57cec5SDimitry Andric     __kmp_printf("GTID: %d, __kmp_threads[%d]=%p\n", gtid, gtid,
80690b57cec5SDimitry Andric                  __kmp_threads[gtid]);
80700b57cec5SDimitry Andric     __kmp_printf("__kmp_threads[%d]->th.th_team_nproc=%d, TEAM: %p, "
80710b57cec5SDimitry Andric                  "team->t.t_nproc=%d\n",
80720b57cec5SDimitry Andric                  gtid, __kmp_threads[gtid]->th.th_team_nproc, team,
80730b57cec5SDimitry Andric                  team->t.t_nproc);
80740b57cec5SDimitry Andric     __kmp_print_structure();
80750b57cec5SDimitry Andric   }
80760b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(__kmp_threads[gtid] &&
80770b57cec5SDimitry Andric                    __kmp_threads[gtid]->th.th_team_nproc == team->t.t_nproc);
80780b57cec5SDimitry Andric #endif /* KMP_DEBUG */
80790b57cec5SDimitry Andric 
80800b57cec5SDimitry Andric   __kmp_join_barrier(gtid); /* wait for everyone */
80810b57cec5SDimitry Andric #if OMPT_SUPPORT
80820b57cec5SDimitry Andric   if (ompt_enabled.enabled &&
80830b57cec5SDimitry Andric       this_thr->th.ompt_thread_info.state == ompt_state_wait_barrier_implicit) {
80840b57cec5SDimitry Andric     int ds_tid = this_thr->th.th_info.ds.ds_tid;
80850b57cec5SDimitry Andric     ompt_data_t *task_data = OMPT_CUR_TASK_DATA(this_thr);
80860b57cec5SDimitry Andric     this_thr->th.ompt_thread_info.state = ompt_state_overhead;
80870b57cec5SDimitry Andric #if OMPT_OPTIONAL
80880b57cec5SDimitry Andric     void *codeptr = NULL;
80890b57cec5SDimitry Andric     if (KMP_MASTER_TID(ds_tid) &&
80900b57cec5SDimitry Andric         (ompt_callbacks.ompt_callback(ompt_callback_sync_region_wait) ||
80910b57cec5SDimitry Andric          ompt_callbacks.ompt_callback(ompt_callback_sync_region)))
80920b57cec5SDimitry Andric       codeptr = OMPT_CUR_TEAM_INFO(this_thr)->master_return_address;
80930b57cec5SDimitry Andric 
80940b57cec5SDimitry Andric     if (ompt_enabled.ompt_callback_sync_region_wait) {
80950b57cec5SDimitry Andric       ompt_callbacks.ompt_callback(ompt_callback_sync_region_wait)(
80960b57cec5SDimitry Andric           ompt_sync_region_barrier_implicit, ompt_scope_end, NULL, task_data,
80970b57cec5SDimitry Andric           codeptr);
80980b57cec5SDimitry Andric     }
80990b57cec5SDimitry Andric     if (ompt_enabled.ompt_callback_sync_region) {
81000b57cec5SDimitry Andric       ompt_callbacks.ompt_callback(ompt_callback_sync_region)(
81010b57cec5SDimitry Andric           ompt_sync_region_barrier_implicit, ompt_scope_end, NULL, task_data,
81020b57cec5SDimitry Andric           codeptr);
81030b57cec5SDimitry Andric     }
81040b57cec5SDimitry Andric #endif
81050b57cec5SDimitry Andric     if (!KMP_MASTER_TID(ds_tid) && ompt_enabled.ompt_callback_implicit_task) {
81060b57cec5SDimitry Andric       ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
8107fe6060f1SDimitry Andric           ompt_scope_end, NULL, task_data, 0, ds_tid,
8108fe6060f1SDimitry Andric           ompt_task_implicit); // TODO: Can this be ompt_task_initial?
81090b57cec5SDimitry Andric     }
81100b57cec5SDimitry Andric   }
81110b57cec5SDimitry Andric #endif
81120b57cec5SDimitry Andric 
81130b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
81140b57cec5SDimitry Andric   KMP_ASSERT(this_thr->th.th_team == team);
81150b57cec5SDimitry Andric }
81160b57cec5SDimitry Andric 
81170b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
81180b57cec5SDimitry Andric 
81190b57cec5SDimitry Andric #ifdef USE_LOAD_BALANCE
81200b57cec5SDimitry Andric 
81210b57cec5SDimitry Andric // Return the worker threads actively spinning in the hot team, if we
81220b57cec5SDimitry Andric // are at the outermost level of parallelism.  Otherwise, return 0.
__kmp_active_hot_team_nproc(kmp_root_t * root)81230b57cec5SDimitry Andric static int __kmp_active_hot_team_nproc(kmp_root_t *root) {
81240b57cec5SDimitry Andric   int i;
81250b57cec5SDimitry Andric   int retval;
81260b57cec5SDimitry Andric   kmp_team_t *hot_team;
81270b57cec5SDimitry Andric 
81280b57cec5SDimitry Andric   if (root->r.r_active) {
81290b57cec5SDimitry Andric     return 0;
81300b57cec5SDimitry Andric   }
81310b57cec5SDimitry Andric   hot_team = root->r.r_hot_team;
81320b57cec5SDimitry Andric   if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME) {
8133fe6060f1SDimitry Andric     return hot_team->t.t_nproc - 1; // Don't count primary thread
81340b57cec5SDimitry Andric   }
81350b57cec5SDimitry Andric 
8136fe6060f1SDimitry Andric   // Skip the primary thread - it is accounted for elsewhere.
81370b57cec5SDimitry Andric   retval = 0;
81380b57cec5SDimitry Andric   for (i = 1; i < hot_team->t.t_nproc; i++) {
81390b57cec5SDimitry Andric     if (hot_team->t.t_threads[i]->th.th_active) {
81400b57cec5SDimitry Andric       retval++;
81410b57cec5SDimitry Andric     }
81420b57cec5SDimitry Andric   }
81430b57cec5SDimitry Andric   return retval;
81440b57cec5SDimitry Andric }
81450b57cec5SDimitry Andric 
81460b57cec5SDimitry Andric // Perform an automatic adjustment to the number of
81470b57cec5SDimitry Andric // threads used by the next parallel region.
__kmp_load_balance_nproc(kmp_root_t * root,int set_nproc)81480b57cec5SDimitry Andric static int __kmp_load_balance_nproc(kmp_root_t *root, int set_nproc) {
81490b57cec5SDimitry Andric   int retval;
81500b57cec5SDimitry Andric   int pool_active;
81510b57cec5SDimitry Andric   int hot_team_active;
81520b57cec5SDimitry Andric   int team_curr_active;
81530b57cec5SDimitry Andric   int system_active;
81540b57cec5SDimitry Andric 
81550b57cec5SDimitry Andric   KB_TRACE(20, ("__kmp_load_balance_nproc: called root:%p set_nproc:%d\n", root,
81560b57cec5SDimitry Andric                 set_nproc));
81570b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(root);
81580b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(root->r.r_root_team->t.t_threads[0]
81590b57cec5SDimitry Andric                        ->th.th_current_task->td_icvs.dynamic == TRUE);
81600b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(set_nproc > 1);
81610b57cec5SDimitry Andric 
81620b57cec5SDimitry Andric   if (set_nproc == 1) {
81630b57cec5SDimitry Andric     KB_TRACE(20, ("__kmp_load_balance_nproc: serial execution.\n"));
81640b57cec5SDimitry Andric     return 1;
81650b57cec5SDimitry Andric   }
81660b57cec5SDimitry Andric 
81670b57cec5SDimitry Andric   // Threads that are active in the thread pool, active in the hot team for this
81680b57cec5SDimitry Andric   // particular root (if we are at the outer par level), and the currently
8169fe6060f1SDimitry Andric   // executing thread (to become the primary thread) are available to add to the
8170fe6060f1SDimitry Andric   // new team, but are currently contributing to the system load, and must be
81710b57cec5SDimitry Andric   // accounted for.
81720b57cec5SDimitry Andric   pool_active = __kmp_thread_pool_active_nth;
81730b57cec5SDimitry Andric   hot_team_active = __kmp_active_hot_team_nproc(root);
81740b57cec5SDimitry Andric   team_curr_active = pool_active + hot_team_active + 1;
81750b57cec5SDimitry Andric 
81760b57cec5SDimitry Andric   // Check the system load.
81770b57cec5SDimitry Andric   system_active = __kmp_get_load_balance(__kmp_avail_proc + team_curr_active);
81780b57cec5SDimitry Andric   KB_TRACE(30, ("__kmp_load_balance_nproc: system active = %d pool active = %d "
81790b57cec5SDimitry Andric                 "hot team active = %d\n",
81800b57cec5SDimitry Andric                 system_active, pool_active, hot_team_active));
81810b57cec5SDimitry Andric 
81820b57cec5SDimitry Andric   if (system_active < 0) {
81830b57cec5SDimitry Andric     // There was an error reading the necessary info from /proc, so use the
81840b57cec5SDimitry Andric     // thread limit algorithm instead. Once we set __kmp_global.g.g_dynamic_mode
81850b57cec5SDimitry Andric     // = dynamic_thread_limit, we shouldn't wind up getting back here.
81860b57cec5SDimitry Andric     __kmp_global.g.g_dynamic_mode = dynamic_thread_limit;
81870b57cec5SDimitry Andric     KMP_WARNING(CantLoadBalUsing, "KMP_DYNAMIC_MODE=thread limit");
81880b57cec5SDimitry Andric 
81890b57cec5SDimitry Andric     // Make this call behave like the thread limit algorithm.
81900b57cec5SDimitry Andric     retval = __kmp_avail_proc - __kmp_nth +
81910b57cec5SDimitry Andric              (root->r.r_active ? 1 : root->r.r_hot_team->t.t_nproc);
81920b57cec5SDimitry Andric     if (retval > set_nproc) {
81930b57cec5SDimitry Andric       retval = set_nproc;
81940b57cec5SDimitry Andric     }
81950b57cec5SDimitry Andric     if (retval < KMP_MIN_NTH) {
81960b57cec5SDimitry Andric       retval = KMP_MIN_NTH;
81970b57cec5SDimitry Andric     }
81980b57cec5SDimitry Andric 
81990b57cec5SDimitry Andric     KB_TRACE(20, ("__kmp_load_balance_nproc: thread limit exit. retval:%d\n",
82000b57cec5SDimitry Andric                   retval));
82010b57cec5SDimitry Andric     return retval;
82020b57cec5SDimitry Andric   }
82030b57cec5SDimitry Andric 
82040b57cec5SDimitry Andric   // There is a slight delay in the load balance algorithm in detecting new
82050b57cec5SDimitry Andric   // running procs. The real system load at this instant should be at least as
82060b57cec5SDimitry Andric   // large as the #active omp thread that are available to add to the team.
82070b57cec5SDimitry Andric   if (system_active < team_curr_active) {
82080b57cec5SDimitry Andric     system_active = team_curr_active;
82090b57cec5SDimitry Andric   }
82100b57cec5SDimitry Andric   retval = __kmp_avail_proc - system_active + team_curr_active;
82110b57cec5SDimitry Andric   if (retval > set_nproc) {
82120b57cec5SDimitry Andric     retval = set_nproc;
82130b57cec5SDimitry Andric   }
82140b57cec5SDimitry Andric   if (retval < KMP_MIN_NTH) {
82150b57cec5SDimitry Andric     retval = KMP_MIN_NTH;
82160b57cec5SDimitry Andric   }
82170b57cec5SDimitry Andric 
82180b57cec5SDimitry Andric   KB_TRACE(20, ("__kmp_load_balance_nproc: exit. retval:%d\n", retval));
82190b57cec5SDimitry Andric   return retval;
82200b57cec5SDimitry Andric } // __kmp_load_balance_nproc()
82210b57cec5SDimitry Andric 
82220b57cec5SDimitry Andric #endif /* USE_LOAD_BALANCE */
82230b57cec5SDimitry Andric 
82240b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
82250b57cec5SDimitry Andric 
82260b57cec5SDimitry Andric /* NOTE: this is called with the __kmp_init_lock held */
__kmp_cleanup(void)82270b57cec5SDimitry Andric void __kmp_cleanup(void) {
82280b57cec5SDimitry Andric   int f;
82290b57cec5SDimitry Andric 
82300b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_cleanup: enter\n"));
82310b57cec5SDimitry Andric 
82320b57cec5SDimitry Andric   if (TCR_4(__kmp_init_parallel)) {
82330b57cec5SDimitry Andric #if KMP_HANDLE_SIGNALS
82340b57cec5SDimitry Andric     __kmp_remove_signals();
82350b57cec5SDimitry Andric #endif
82360b57cec5SDimitry Andric     TCW_4(__kmp_init_parallel, FALSE);
82370b57cec5SDimitry Andric   }
82380b57cec5SDimitry Andric 
82390b57cec5SDimitry Andric   if (TCR_4(__kmp_init_middle)) {
82400b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
82410b57cec5SDimitry Andric     __kmp_affinity_uninitialize();
82420b57cec5SDimitry Andric #endif /* KMP_AFFINITY_SUPPORTED */
82430b57cec5SDimitry Andric     __kmp_cleanup_hierarchy();
82440b57cec5SDimitry Andric     TCW_4(__kmp_init_middle, FALSE);
82450b57cec5SDimitry Andric   }
82460b57cec5SDimitry Andric 
82470b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_cleanup: go serial cleanup\n"));
82480b57cec5SDimitry Andric 
82490b57cec5SDimitry Andric   if (__kmp_init_serial) {
82500b57cec5SDimitry Andric     __kmp_runtime_destroy();
82510b57cec5SDimitry Andric     __kmp_init_serial = FALSE;
82520b57cec5SDimitry Andric   }
82530b57cec5SDimitry Andric 
82540b57cec5SDimitry Andric   __kmp_cleanup_threadprivate_caches();
82550b57cec5SDimitry Andric 
82560b57cec5SDimitry Andric   for (f = 0; f < __kmp_threads_capacity; f++) {
82570b57cec5SDimitry Andric     if (__kmp_root[f] != NULL) {
82580b57cec5SDimitry Andric       __kmp_free(__kmp_root[f]);
82590b57cec5SDimitry Andric       __kmp_root[f] = NULL;
82600b57cec5SDimitry Andric     }
82610b57cec5SDimitry Andric   }
82620b57cec5SDimitry Andric   __kmp_free(__kmp_threads);
82630b57cec5SDimitry Andric   // __kmp_threads and __kmp_root were allocated at once, as single block, so
82640b57cec5SDimitry Andric   // there is no need in freeing __kmp_root.
82650b57cec5SDimitry Andric   __kmp_threads = NULL;
82660b57cec5SDimitry Andric   __kmp_root = NULL;
82670b57cec5SDimitry Andric   __kmp_threads_capacity = 0;
82680b57cec5SDimitry Andric 
826981ad6265SDimitry Andric   // Free old __kmp_threads arrays if they exist.
827081ad6265SDimitry Andric   kmp_old_threads_list_t *ptr = __kmp_old_threads_list;
827181ad6265SDimitry Andric   while (ptr) {
827281ad6265SDimitry Andric     kmp_old_threads_list_t *next = ptr->next;
827381ad6265SDimitry Andric     __kmp_free(ptr->threads);
827481ad6265SDimitry Andric     __kmp_free(ptr);
827581ad6265SDimitry Andric     ptr = next;
827681ad6265SDimitry Andric   }
827781ad6265SDimitry Andric 
82780b57cec5SDimitry Andric #if KMP_USE_DYNAMIC_LOCK
82790b57cec5SDimitry Andric   __kmp_cleanup_indirect_user_locks();
82800b57cec5SDimitry Andric #else
82810b57cec5SDimitry Andric   __kmp_cleanup_user_locks();
82820b57cec5SDimitry Andric #endif
8283fe6060f1SDimitry Andric #if OMPD_SUPPORT
8284fe6060f1SDimitry Andric   if (ompd_state) {
8285fe6060f1SDimitry Andric     __kmp_free(ompd_env_block);
8286fe6060f1SDimitry Andric     ompd_env_block = NULL;
8287fe6060f1SDimitry Andric     ompd_env_block_size = 0;
8288fe6060f1SDimitry Andric   }
8289fe6060f1SDimitry Andric #endif
82900b57cec5SDimitry Andric 
82910b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
82920b57cec5SDimitry Andric   KMP_INTERNAL_FREE(CCAST(char *, __kmp_cpuinfo_file));
82930b57cec5SDimitry Andric   __kmp_cpuinfo_file = NULL;
82940b57cec5SDimitry Andric #endif /* KMP_AFFINITY_SUPPORTED */
82950b57cec5SDimitry Andric 
82960b57cec5SDimitry Andric #if KMP_USE_ADAPTIVE_LOCKS
82970b57cec5SDimitry Andric #if KMP_DEBUG_ADAPTIVE_LOCKS
82980b57cec5SDimitry Andric   __kmp_print_speculative_stats();
82990b57cec5SDimitry Andric #endif
83000b57cec5SDimitry Andric #endif
83010b57cec5SDimitry Andric   KMP_INTERNAL_FREE(__kmp_nested_nth.nth);
83020b57cec5SDimitry Andric   __kmp_nested_nth.nth = NULL;
83030b57cec5SDimitry Andric   __kmp_nested_nth.size = 0;
83040b57cec5SDimitry Andric   __kmp_nested_nth.used = 0;
83050b57cec5SDimitry Andric   KMP_INTERNAL_FREE(__kmp_nested_proc_bind.bind_types);
83060b57cec5SDimitry Andric   __kmp_nested_proc_bind.bind_types = NULL;
83070b57cec5SDimitry Andric   __kmp_nested_proc_bind.size = 0;
83080b57cec5SDimitry Andric   __kmp_nested_proc_bind.used = 0;
83090b57cec5SDimitry Andric   if (__kmp_affinity_format) {
83100b57cec5SDimitry Andric     KMP_INTERNAL_FREE(__kmp_affinity_format);
83110b57cec5SDimitry Andric     __kmp_affinity_format = NULL;
83120b57cec5SDimitry Andric   }
83130b57cec5SDimitry Andric 
83140b57cec5SDimitry Andric   __kmp_i18n_catclose();
83150b57cec5SDimitry Andric 
83160b57cec5SDimitry Andric #if KMP_USE_HIER_SCHED
83170b57cec5SDimitry Andric   __kmp_hier_scheds.deallocate();
83180b57cec5SDimitry Andric #endif
83190b57cec5SDimitry Andric 
83200b57cec5SDimitry Andric #if KMP_STATS_ENABLED
83210b57cec5SDimitry Andric   __kmp_stats_fini();
83220b57cec5SDimitry Andric #endif
83230b57cec5SDimitry Andric 
83240b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_cleanup: exit\n"));
83250b57cec5SDimitry Andric }
83260b57cec5SDimitry Andric 
83270b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
83280b57cec5SDimitry Andric 
__kmp_ignore_mppbeg(void)83290b57cec5SDimitry Andric int __kmp_ignore_mppbeg(void) {
83300b57cec5SDimitry Andric   char *env;
83310b57cec5SDimitry Andric 
83320b57cec5SDimitry Andric   if ((env = getenv("KMP_IGNORE_MPPBEG")) != NULL) {
83330b57cec5SDimitry Andric     if (__kmp_str_match_false(env))
83340b57cec5SDimitry Andric       return FALSE;
83350b57cec5SDimitry Andric   }
83360b57cec5SDimitry Andric   // By default __kmpc_begin() is no-op.
83370b57cec5SDimitry Andric   return TRUE;
83380b57cec5SDimitry Andric }
83390b57cec5SDimitry Andric 
__kmp_ignore_mppend(void)83400b57cec5SDimitry Andric int __kmp_ignore_mppend(void) {
83410b57cec5SDimitry Andric   char *env;
83420b57cec5SDimitry Andric 
83430b57cec5SDimitry Andric   if ((env = getenv("KMP_IGNORE_MPPEND")) != NULL) {
83440b57cec5SDimitry Andric     if (__kmp_str_match_false(env))
83450b57cec5SDimitry Andric       return FALSE;
83460b57cec5SDimitry Andric   }
83470b57cec5SDimitry Andric   // By default __kmpc_end() is no-op.
83480b57cec5SDimitry Andric   return TRUE;
83490b57cec5SDimitry Andric }
83500b57cec5SDimitry Andric 
__kmp_internal_begin(void)83510b57cec5SDimitry Andric void __kmp_internal_begin(void) {
83520b57cec5SDimitry Andric   int gtid;
83530b57cec5SDimitry Andric   kmp_root_t *root;
83540b57cec5SDimitry Andric 
83550b57cec5SDimitry Andric   /* this is a very important step as it will register new sibling threads
83560b57cec5SDimitry Andric      and assign these new uber threads a new gtid */
83570b57cec5SDimitry Andric   gtid = __kmp_entry_gtid();
83580b57cec5SDimitry Andric   root = __kmp_threads[gtid]->th.th_root;
83590b57cec5SDimitry Andric   KMP_ASSERT(KMP_UBER_GTID(gtid));
83600b57cec5SDimitry Andric 
83610b57cec5SDimitry Andric   if (root->r.r_begin)
83620b57cec5SDimitry Andric     return;
83630b57cec5SDimitry Andric   __kmp_acquire_lock(&root->r.r_begin_lock, gtid);
83640b57cec5SDimitry Andric   if (root->r.r_begin) {
83650b57cec5SDimitry Andric     __kmp_release_lock(&root->r.r_begin_lock, gtid);
83660b57cec5SDimitry Andric     return;
83670b57cec5SDimitry Andric   }
83680b57cec5SDimitry Andric 
83690b57cec5SDimitry Andric   root->r.r_begin = TRUE;
83700b57cec5SDimitry Andric 
83710b57cec5SDimitry Andric   __kmp_release_lock(&root->r.r_begin_lock, gtid);
83720b57cec5SDimitry Andric }
83730b57cec5SDimitry Andric 
83740b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
83750b57cec5SDimitry Andric 
__kmp_user_set_library(enum library_type arg)83760b57cec5SDimitry Andric void __kmp_user_set_library(enum library_type arg) {
83770b57cec5SDimitry Andric   int gtid;
83780b57cec5SDimitry Andric   kmp_root_t *root;
83790b57cec5SDimitry Andric   kmp_info_t *thread;
83800b57cec5SDimitry Andric 
83810b57cec5SDimitry Andric   /* first, make sure we are initialized so we can get our gtid */
83820b57cec5SDimitry Andric 
83830b57cec5SDimitry Andric   gtid = __kmp_entry_gtid();
83840b57cec5SDimitry Andric   thread = __kmp_threads[gtid];
83850b57cec5SDimitry Andric 
83860b57cec5SDimitry Andric   root = thread->th.th_root;
83870b57cec5SDimitry Andric 
83880b57cec5SDimitry Andric   KA_TRACE(20, ("__kmp_user_set_library: enter T#%d, arg: %d, %d\n", gtid, arg,
83890b57cec5SDimitry Andric                 library_serial));
83900b57cec5SDimitry Andric   if (root->r.r_in_parallel) { /* Must be called in serial section of top-level
83910b57cec5SDimitry Andric                                   thread */
83920b57cec5SDimitry Andric     KMP_WARNING(SetLibraryIncorrectCall);
83930b57cec5SDimitry Andric     return;
83940b57cec5SDimitry Andric   }
83950b57cec5SDimitry Andric 
83960b57cec5SDimitry Andric   switch (arg) {
83970b57cec5SDimitry Andric   case library_serial:
83980b57cec5SDimitry Andric     thread->th.th_set_nproc = 0;
83990b57cec5SDimitry Andric     set__nproc(thread, 1);
84000b57cec5SDimitry Andric     break;
84010b57cec5SDimitry Andric   case library_turnaround:
84020b57cec5SDimitry Andric     thread->th.th_set_nproc = 0;
84030b57cec5SDimitry Andric     set__nproc(thread, __kmp_dflt_team_nth ? __kmp_dflt_team_nth
84040b57cec5SDimitry Andric                                            : __kmp_dflt_team_nth_ub);
84050b57cec5SDimitry Andric     break;
84060b57cec5SDimitry Andric   case library_throughput:
84070b57cec5SDimitry Andric     thread->th.th_set_nproc = 0;
84080b57cec5SDimitry Andric     set__nproc(thread, __kmp_dflt_team_nth ? __kmp_dflt_team_nth
84090b57cec5SDimitry Andric                                            : __kmp_dflt_team_nth_ub);
84100b57cec5SDimitry Andric     break;
84110b57cec5SDimitry Andric   default:
84120b57cec5SDimitry Andric     KMP_FATAL(UnknownLibraryType, arg);
84130b57cec5SDimitry Andric   }
84140b57cec5SDimitry Andric 
84150b57cec5SDimitry Andric   __kmp_aux_set_library(arg);
84160b57cec5SDimitry Andric }
84170b57cec5SDimitry Andric 
__kmp_aux_set_stacksize(size_t arg)84180b57cec5SDimitry Andric void __kmp_aux_set_stacksize(size_t arg) {
84190b57cec5SDimitry Andric   if (!__kmp_init_serial)
84200b57cec5SDimitry Andric     __kmp_serial_initialize();
84210b57cec5SDimitry Andric 
84220b57cec5SDimitry Andric #if KMP_OS_DARWIN
84230b57cec5SDimitry Andric   if (arg & (0x1000 - 1)) {
84240b57cec5SDimitry Andric     arg &= ~(0x1000 - 1);
84250b57cec5SDimitry Andric     if (arg + 0x1000) /* check for overflow if we round up */
84260b57cec5SDimitry Andric       arg += 0x1000;
84270b57cec5SDimitry Andric   }
84280b57cec5SDimitry Andric #endif
84290b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
84300b57cec5SDimitry Andric 
84310b57cec5SDimitry Andric   /* only change the default stacksize before the first parallel region */
84320b57cec5SDimitry Andric   if (!TCR_4(__kmp_init_parallel)) {
84330b57cec5SDimitry Andric     size_t value = arg; /* argument is in bytes */
84340b57cec5SDimitry Andric 
84350b57cec5SDimitry Andric     if (value < __kmp_sys_min_stksize)
84360b57cec5SDimitry Andric       value = __kmp_sys_min_stksize;
84370b57cec5SDimitry Andric     else if (value > KMP_MAX_STKSIZE)
84380b57cec5SDimitry Andric       value = KMP_MAX_STKSIZE;
84390b57cec5SDimitry Andric 
84400b57cec5SDimitry Andric     __kmp_stksize = value;
84410b57cec5SDimitry Andric 
84420b57cec5SDimitry Andric     __kmp_env_stksize = TRUE; /* was KMP_STACKSIZE specified? */
84430b57cec5SDimitry Andric   }
84440b57cec5SDimitry Andric 
84450b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
84460b57cec5SDimitry Andric }
84470b57cec5SDimitry Andric 
84480b57cec5SDimitry Andric /* set the behaviour of the runtime library */
84490b57cec5SDimitry Andric /* TODO this can cause some odd behaviour with sibling parallelism... */
__kmp_aux_set_library(enum library_type arg)84500b57cec5SDimitry Andric void __kmp_aux_set_library(enum library_type arg) {
84510b57cec5SDimitry Andric   __kmp_library = arg;
84520b57cec5SDimitry Andric 
84530b57cec5SDimitry Andric   switch (__kmp_library) {
84540b57cec5SDimitry Andric   case library_serial: {
84550b57cec5SDimitry Andric     KMP_INFORM(LibraryIsSerial);
84560b57cec5SDimitry Andric   } break;
84570b57cec5SDimitry Andric   case library_turnaround:
84580b57cec5SDimitry Andric     if (__kmp_use_yield == 1 && !__kmp_use_yield_exp_set)
84590b57cec5SDimitry Andric       __kmp_use_yield = 2; // only yield when oversubscribed
84600b57cec5SDimitry Andric     break;
84610b57cec5SDimitry Andric   case library_throughput:
84620b57cec5SDimitry Andric     if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME)
846381ad6265SDimitry Andric       __kmp_dflt_blocktime = KMP_DEFAULT_BLOCKTIME;
84640b57cec5SDimitry Andric     break;
84650b57cec5SDimitry Andric   default:
84660b57cec5SDimitry Andric     KMP_FATAL(UnknownLibraryType, arg);
84670b57cec5SDimitry Andric   }
84680b57cec5SDimitry Andric }
84690b57cec5SDimitry Andric 
84700b57cec5SDimitry Andric /* Getting team information common for all team API */
84710b57cec5SDimitry Andric // Returns NULL if not in teams construct
__kmp_aux_get_team_info(int & teams_serialized)84720b57cec5SDimitry Andric static kmp_team_t *__kmp_aux_get_team_info(int &teams_serialized) {
84730b57cec5SDimitry Andric   kmp_info_t *thr = __kmp_entry_thread();
84740b57cec5SDimitry Andric   teams_serialized = 0;
84750b57cec5SDimitry Andric   if (thr->th.th_teams_microtask) {
84760b57cec5SDimitry Andric     kmp_team_t *team = thr->th.th_team;
84770b57cec5SDimitry Andric     int tlevel = thr->th.th_teams_level; // the level of the teams construct
84780b57cec5SDimitry Andric     int ii = team->t.t_level;
84790b57cec5SDimitry Andric     teams_serialized = team->t.t_serialized;
84800b57cec5SDimitry Andric     int level = tlevel + 1;
84810b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(ii >= tlevel);
84820b57cec5SDimitry Andric     while (ii > level) {
84830b57cec5SDimitry Andric       for (teams_serialized = team->t.t_serialized;
84840b57cec5SDimitry Andric            (teams_serialized > 0) && (ii > level); teams_serialized--, ii--) {
84850b57cec5SDimitry Andric       }
84860b57cec5SDimitry Andric       if (team->t.t_serialized && (!teams_serialized)) {
84870b57cec5SDimitry Andric         team = team->t.t_parent;
84880b57cec5SDimitry Andric         continue;
84890b57cec5SDimitry Andric       }
84900b57cec5SDimitry Andric       if (ii > level) {
84910b57cec5SDimitry Andric         team = team->t.t_parent;
84920b57cec5SDimitry Andric         ii--;
84930b57cec5SDimitry Andric       }
84940b57cec5SDimitry Andric     }
84950b57cec5SDimitry Andric     return team;
84960b57cec5SDimitry Andric   }
84970b57cec5SDimitry Andric   return NULL;
84980b57cec5SDimitry Andric }
84990b57cec5SDimitry Andric 
__kmp_aux_get_team_num()85000b57cec5SDimitry Andric int __kmp_aux_get_team_num() {
85010b57cec5SDimitry Andric   int serialized;
85020b57cec5SDimitry Andric   kmp_team_t *team = __kmp_aux_get_team_info(serialized);
85030b57cec5SDimitry Andric   if (team) {
85040b57cec5SDimitry Andric     if (serialized > 1) {
85050b57cec5SDimitry Andric       return 0; // teams region is serialized ( 1 team of 1 thread ).
85060b57cec5SDimitry Andric     } else {
85070b57cec5SDimitry Andric       return team->t.t_master_tid;
85080b57cec5SDimitry Andric     }
85090b57cec5SDimitry Andric   }
85100b57cec5SDimitry Andric   return 0;
85110b57cec5SDimitry Andric }
85120b57cec5SDimitry Andric 
__kmp_aux_get_num_teams()85130b57cec5SDimitry Andric int __kmp_aux_get_num_teams() {
85140b57cec5SDimitry Andric   int serialized;
85150b57cec5SDimitry Andric   kmp_team_t *team = __kmp_aux_get_team_info(serialized);
85160b57cec5SDimitry Andric   if (team) {
85170b57cec5SDimitry Andric     if (serialized > 1) {
85180b57cec5SDimitry Andric       return 1;
85190b57cec5SDimitry Andric     } else {
85200b57cec5SDimitry Andric       return team->t.t_parent->t.t_nproc;
85210b57cec5SDimitry Andric     }
85220b57cec5SDimitry Andric   }
85230b57cec5SDimitry Andric   return 1;
85240b57cec5SDimitry Andric }
85250b57cec5SDimitry Andric 
85260b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
85270b57cec5SDimitry Andric 
85280b57cec5SDimitry Andric /*
85290b57cec5SDimitry Andric  * Affinity Format Parser
85300b57cec5SDimitry Andric  *
85310b57cec5SDimitry Andric  * Field is in form of: %[[[0].]size]type
85320b57cec5SDimitry Andric  * % and type are required (%% means print a literal '%')
85330b57cec5SDimitry Andric  * type is either single char or long name surrounded by {},
85340b57cec5SDimitry Andric  * e.g., N or {num_threads}
85350b57cec5SDimitry Andric  * 0 => leading zeros
85360b57cec5SDimitry Andric  * . => right justified when size is specified
85370b57cec5SDimitry Andric  * by default output is left justified
85380b57cec5SDimitry Andric  * size is the *minimum* field length
85390b57cec5SDimitry Andric  * All other characters are printed as is
85400b57cec5SDimitry Andric  *
85410b57cec5SDimitry Andric  * Available field types:
85420b57cec5SDimitry Andric  * L {thread_level}      - omp_get_level()
85430b57cec5SDimitry Andric  * n {thread_num}        - omp_get_thread_num()
85440b57cec5SDimitry Andric  * h {host}              - name of host machine
85450b57cec5SDimitry Andric  * P {process_id}        - process id (integer)
85460b57cec5SDimitry Andric  * T {thread_identifier} - native thread identifier (integer)
85470b57cec5SDimitry Andric  * N {num_threads}       - omp_get_num_threads()
85480b57cec5SDimitry Andric  * A {ancestor_tnum}     - omp_get_ancestor_thread_num(omp_get_level()-1)
85490b57cec5SDimitry Andric  * a {thread_affinity}   - comma separated list of integers or integer ranges
85500b57cec5SDimitry Andric  *                         (values of affinity mask)
85510b57cec5SDimitry Andric  *
85520b57cec5SDimitry Andric  * Implementation-specific field types can be added
85530b57cec5SDimitry Andric  * If a type is unknown, print "undefined"
85540b57cec5SDimitry Andric  */
85550b57cec5SDimitry Andric 
85560b57cec5SDimitry Andric // Structure holding the short name, long name, and corresponding data type
85570b57cec5SDimitry Andric // for snprintf.  A table of these will represent the entire valid keyword
85580b57cec5SDimitry Andric // field types.
85590b57cec5SDimitry Andric typedef struct kmp_affinity_format_field_t {
85600b57cec5SDimitry Andric   char short_name; // from spec e.g., L -> thread level
85610b57cec5SDimitry Andric   const char *long_name; // from spec thread_level -> thread level
85620b57cec5SDimitry Andric   char field_format; // data type for snprintf (typically 'd' or 's'
85630b57cec5SDimitry Andric   // for integer or string)
85640b57cec5SDimitry Andric } kmp_affinity_format_field_t;
85650b57cec5SDimitry Andric 
85660b57cec5SDimitry Andric static const kmp_affinity_format_field_t __kmp_affinity_format_table[] = {
85670b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
85680b57cec5SDimitry Andric     {'A', "thread_affinity", 's'},
85690b57cec5SDimitry Andric #endif
85700b57cec5SDimitry Andric     {'t', "team_num", 'd'},
85710b57cec5SDimitry Andric     {'T', "num_teams", 'd'},
85720b57cec5SDimitry Andric     {'L', "nesting_level", 'd'},
85730b57cec5SDimitry Andric     {'n', "thread_num", 'd'},
85740b57cec5SDimitry Andric     {'N', "num_threads", 'd'},
85750b57cec5SDimitry Andric     {'a', "ancestor_tnum", 'd'},
85760b57cec5SDimitry Andric     {'H', "host", 's'},
85770b57cec5SDimitry Andric     {'P', "process_id", 'd'},
85780b57cec5SDimitry Andric     {'i', "native_thread_id", 'd'}};
85790b57cec5SDimitry Andric 
85800b57cec5SDimitry Andric // Return the number of characters it takes to hold field
__kmp_aux_capture_affinity_field(int gtid,const kmp_info_t * th,const char ** ptr,kmp_str_buf_t * field_buffer)85810b57cec5SDimitry Andric static int __kmp_aux_capture_affinity_field(int gtid, const kmp_info_t *th,
85820b57cec5SDimitry Andric                                             const char **ptr,
85830b57cec5SDimitry Andric                                             kmp_str_buf_t *field_buffer) {
85840b57cec5SDimitry Andric   int rc, format_index, field_value;
85850b57cec5SDimitry Andric   const char *width_left, *width_right;
85860b57cec5SDimitry Andric   bool pad_zeros, right_justify, parse_long_name, found_valid_name;
85870b57cec5SDimitry Andric   static const int FORMAT_SIZE = 20;
85880b57cec5SDimitry Andric   char format[FORMAT_SIZE] = {0};
85890b57cec5SDimitry Andric   char absolute_short_name = 0;
85900b57cec5SDimitry Andric 
85910b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(gtid >= 0);
85920b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(th);
85930b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(**ptr == '%');
85940b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(field_buffer);
85950b57cec5SDimitry Andric 
85960b57cec5SDimitry Andric   __kmp_str_buf_clear(field_buffer);
85970b57cec5SDimitry Andric 
85980b57cec5SDimitry Andric   // Skip the initial %
85990b57cec5SDimitry Andric   (*ptr)++;
86000b57cec5SDimitry Andric 
86010b57cec5SDimitry Andric   // Check for %% first
86020b57cec5SDimitry Andric   if (**ptr == '%') {
86030b57cec5SDimitry Andric     __kmp_str_buf_cat(field_buffer, "%", 1);
86040b57cec5SDimitry Andric     (*ptr)++; // skip over the second %
86050b57cec5SDimitry Andric     return 1;
86060b57cec5SDimitry Andric   }
86070b57cec5SDimitry Andric 
86080b57cec5SDimitry Andric   // Parse field modifiers if they are present
86090b57cec5SDimitry Andric   pad_zeros = false;
86100b57cec5SDimitry Andric   if (**ptr == '0') {
86110b57cec5SDimitry Andric     pad_zeros = true;
86120b57cec5SDimitry Andric     (*ptr)++; // skip over 0
86130b57cec5SDimitry Andric   }
86140b57cec5SDimitry Andric   right_justify = false;
86150b57cec5SDimitry Andric   if (**ptr == '.') {
86160b57cec5SDimitry Andric     right_justify = true;
86170b57cec5SDimitry Andric     (*ptr)++; // skip over .
86180b57cec5SDimitry Andric   }
86190b57cec5SDimitry Andric   // Parse width of field: [width_left, width_right)
86200b57cec5SDimitry Andric   width_left = width_right = NULL;
86210b57cec5SDimitry Andric   if (**ptr >= '0' && **ptr <= '9') {
86220b57cec5SDimitry Andric     width_left = *ptr;
86230b57cec5SDimitry Andric     SKIP_DIGITS(*ptr);
86240b57cec5SDimitry Andric     width_right = *ptr;
86250b57cec5SDimitry Andric   }
86260b57cec5SDimitry Andric 
86270b57cec5SDimitry Andric   // Create the format for KMP_SNPRINTF based on flags parsed above
86280b57cec5SDimitry Andric   format_index = 0;
86290b57cec5SDimitry Andric   format[format_index++] = '%';
86300b57cec5SDimitry Andric   if (!right_justify)
86310b57cec5SDimitry Andric     format[format_index++] = '-';
86320b57cec5SDimitry Andric   if (pad_zeros)
86330b57cec5SDimitry Andric     format[format_index++] = '0';
86340b57cec5SDimitry Andric   if (width_left && width_right) {
86350b57cec5SDimitry Andric     int i = 0;
86360b57cec5SDimitry Andric     // Only allow 8 digit number widths.
86370b57cec5SDimitry Andric     // This also prevents overflowing format variable
86380b57cec5SDimitry Andric     while (i < 8 && width_left < width_right) {
86390b57cec5SDimitry Andric       format[format_index++] = *width_left;
86400b57cec5SDimitry Andric       width_left++;
86410b57cec5SDimitry Andric       i++;
86420b57cec5SDimitry Andric     }
86430b57cec5SDimitry Andric   }
86440b57cec5SDimitry Andric 
86450b57cec5SDimitry Andric   // Parse a name (long or short)
86460b57cec5SDimitry Andric   // Canonicalize the name into absolute_short_name
86470b57cec5SDimitry Andric   found_valid_name = false;
86480b57cec5SDimitry Andric   parse_long_name = (**ptr == '{');
86490b57cec5SDimitry Andric   if (parse_long_name)
86500b57cec5SDimitry Andric     (*ptr)++; // skip initial left brace
86510b57cec5SDimitry Andric   for (size_t i = 0; i < sizeof(__kmp_affinity_format_table) /
86520b57cec5SDimitry Andric                              sizeof(__kmp_affinity_format_table[0]);
86530b57cec5SDimitry Andric        ++i) {
86540b57cec5SDimitry Andric     char short_name = __kmp_affinity_format_table[i].short_name;
86550b57cec5SDimitry Andric     const char *long_name = __kmp_affinity_format_table[i].long_name;
86560b57cec5SDimitry Andric     char field_format = __kmp_affinity_format_table[i].field_format;
86570b57cec5SDimitry Andric     if (parse_long_name) {
8658e8d8bef9SDimitry Andric       size_t length = KMP_STRLEN(long_name);
86590b57cec5SDimitry Andric       if (strncmp(*ptr, long_name, length) == 0) {
86600b57cec5SDimitry Andric         found_valid_name = true;
86610b57cec5SDimitry Andric         (*ptr) += length; // skip the long name
86620b57cec5SDimitry Andric       }
86630b57cec5SDimitry Andric     } else if (**ptr == short_name) {
86640b57cec5SDimitry Andric       found_valid_name = true;
86650b57cec5SDimitry Andric       (*ptr)++; // skip the short name
86660b57cec5SDimitry Andric     }
86670b57cec5SDimitry Andric     if (found_valid_name) {
86680b57cec5SDimitry Andric       format[format_index++] = field_format;
86690b57cec5SDimitry Andric       format[format_index++] = '\0';
86700b57cec5SDimitry Andric       absolute_short_name = short_name;
86710b57cec5SDimitry Andric       break;
86720b57cec5SDimitry Andric     }
86730b57cec5SDimitry Andric   }
86740b57cec5SDimitry Andric   if (parse_long_name) {
86750b57cec5SDimitry Andric     if (**ptr != '}') {
86760b57cec5SDimitry Andric       absolute_short_name = 0;
86770b57cec5SDimitry Andric     } else {
86780b57cec5SDimitry Andric       (*ptr)++; // skip over the right brace
86790b57cec5SDimitry Andric     }
86800b57cec5SDimitry Andric   }
86810b57cec5SDimitry Andric 
86820b57cec5SDimitry Andric   // Attempt to fill the buffer with the requested
86830b57cec5SDimitry Andric   // value using snprintf within __kmp_str_buf_print()
86840b57cec5SDimitry Andric   switch (absolute_short_name) {
86850b57cec5SDimitry Andric   case 't':
86860b57cec5SDimitry Andric     rc = __kmp_str_buf_print(field_buffer, format, __kmp_aux_get_team_num());
86870b57cec5SDimitry Andric     break;
86880b57cec5SDimitry Andric   case 'T':
86890b57cec5SDimitry Andric     rc = __kmp_str_buf_print(field_buffer, format, __kmp_aux_get_num_teams());
86900b57cec5SDimitry Andric     break;
86910b57cec5SDimitry Andric   case 'L':
86920b57cec5SDimitry Andric     rc = __kmp_str_buf_print(field_buffer, format, th->th.th_team->t.t_level);
86930b57cec5SDimitry Andric     break;
86940b57cec5SDimitry Andric   case 'n':
86950b57cec5SDimitry Andric     rc = __kmp_str_buf_print(field_buffer, format, __kmp_tid_from_gtid(gtid));
86960b57cec5SDimitry Andric     break;
86970b57cec5SDimitry Andric   case 'H': {
86980b57cec5SDimitry Andric     static const int BUFFER_SIZE = 256;
86990b57cec5SDimitry Andric     char buf[BUFFER_SIZE];
87000b57cec5SDimitry Andric     __kmp_expand_host_name(buf, BUFFER_SIZE);
87010b57cec5SDimitry Andric     rc = __kmp_str_buf_print(field_buffer, format, buf);
87020b57cec5SDimitry Andric   } break;
87030b57cec5SDimitry Andric   case 'P':
87040b57cec5SDimitry Andric     rc = __kmp_str_buf_print(field_buffer, format, getpid());
87050b57cec5SDimitry Andric     break;
87060b57cec5SDimitry Andric   case 'i':
87070b57cec5SDimitry Andric     rc = __kmp_str_buf_print(field_buffer, format, __kmp_gettid());
87080b57cec5SDimitry Andric     break;
87090b57cec5SDimitry Andric   case 'N':
87100b57cec5SDimitry Andric     rc = __kmp_str_buf_print(field_buffer, format, th->th.th_team->t.t_nproc);
87110b57cec5SDimitry Andric     break;
87120b57cec5SDimitry Andric   case 'a':
87130b57cec5SDimitry Andric     field_value =
87140b57cec5SDimitry Andric         __kmp_get_ancestor_thread_num(gtid, th->th.th_team->t.t_level - 1);
87150b57cec5SDimitry Andric     rc = __kmp_str_buf_print(field_buffer, format, field_value);
87160b57cec5SDimitry Andric     break;
87170b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
87180b57cec5SDimitry Andric   case 'A': {
87190b57cec5SDimitry Andric     kmp_str_buf_t buf;
87200b57cec5SDimitry Andric     __kmp_str_buf_init(&buf);
87210b57cec5SDimitry Andric     __kmp_affinity_str_buf_mask(&buf, th->th.th_affin_mask);
87220b57cec5SDimitry Andric     rc = __kmp_str_buf_print(field_buffer, format, buf.str);
87230b57cec5SDimitry Andric     __kmp_str_buf_free(&buf);
87240b57cec5SDimitry Andric   } break;
87250b57cec5SDimitry Andric #endif
87260b57cec5SDimitry Andric   default:
87270b57cec5SDimitry Andric     // According to spec, If an implementation does not have info for field
87280b57cec5SDimitry Andric     // type, then "undefined" is printed
87290b57cec5SDimitry Andric     rc = __kmp_str_buf_print(field_buffer, "%s", "undefined");
87300b57cec5SDimitry Andric     // Skip the field
87310b57cec5SDimitry Andric     if (parse_long_name) {
87320b57cec5SDimitry Andric       SKIP_TOKEN(*ptr);
87330b57cec5SDimitry Andric       if (**ptr == '}')
87340b57cec5SDimitry Andric         (*ptr)++;
87350b57cec5SDimitry Andric     } else {
87360b57cec5SDimitry Andric       (*ptr)++;
87370b57cec5SDimitry Andric     }
87380b57cec5SDimitry Andric   }
87390b57cec5SDimitry Andric 
87400b57cec5SDimitry Andric   KMP_ASSERT(format_index <= FORMAT_SIZE);
87410b57cec5SDimitry Andric   return rc;
87420b57cec5SDimitry Andric }
87430b57cec5SDimitry Andric 
87440b57cec5SDimitry Andric /*
87450b57cec5SDimitry Andric  * Return number of characters needed to hold the affinity string
87460b57cec5SDimitry Andric  * (not including null byte character)
87470b57cec5SDimitry Andric  * The resultant string is printed to buffer, which the caller can then
87480b57cec5SDimitry Andric  * handle afterwards
87490b57cec5SDimitry Andric  */
__kmp_aux_capture_affinity(int gtid,const char * format,kmp_str_buf_t * buffer)87500b57cec5SDimitry Andric size_t __kmp_aux_capture_affinity(int gtid, const char *format,
87510b57cec5SDimitry Andric                                   kmp_str_buf_t *buffer) {
87520b57cec5SDimitry Andric   const char *parse_ptr;
87530b57cec5SDimitry Andric   size_t retval;
87540b57cec5SDimitry Andric   const kmp_info_t *th;
87550b57cec5SDimitry Andric   kmp_str_buf_t field;
87560b57cec5SDimitry Andric 
87570b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(buffer);
87580b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(gtid >= 0);
87590b57cec5SDimitry Andric 
87600b57cec5SDimitry Andric   __kmp_str_buf_init(&field);
87610b57cec5SDimitry Andric   __kmp_str_buf_clear(buffer);
87620b57cec5SDimitry Andric 
87630b57cec5SDimitry Andric   th = __kmp_threads[gtid];
87640b57cec5SDimitry Andric   retval = 0;
87650b57cec5SDimitry Andric 
87660b57cec5SDimitry Andric   // If format is NULL or zero-length string, then we use
87670b57cec5SDimitry Andric   // affinity-format-var ICV
87680b57cec5SDimitry Andric   parse_ptr = format;
87690b57cec5SDimitry Andric   if (parse_ptr == NULL || *parse_ptr == '\0') {
87700b57cec5SDimitry Andric     parse_ptr = __kmp_affinity_format;
87710b57cec5SDimitry Andric   }
87720b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(parse_ptr);
87730b57cec5SDimitry Andric 
87740b57cec5SDimitry Andric   while (*parse_ptr != '\0') {
87750b57cec5SDimitry Andric     // Parse a field
87760b57cec5SDimitry Andric     if (*parse_ptr == '%') {
87770b57cec5SDimitry Andric       // Put field in the buffer
87780b57cec5SDimitry Andric       int rc = __kmp_aux_capture_affinity_field(gtid, th, &parse_ptr, &field);
87790b57cec5SDimitry Andric       __kmp_str_buf_catbuf(buffer, &field);
87800b57cec5SDimitry Andric       retval += rc;
87810b57cec5SDimitry Andric     } else {
87820b57cec5SDimitry Andric       // Put literal character in buffer
87830b57cec5SDimitry Andric       __kmp_str_buf_cat(buffer, parse_ptr, 1);
87840b57cec5SDimitry Andric       retval++;
87850b57cec5SDimitry Andric       parse_ptr++;
87860b57cec5SDimitry Andric     }
87870b57cec5SDimitry Andric   }
87880b57cec5SDimitry Andric   __kmp_str_buf_free(&field);
87890b57cec5SDimitry Andric   return retval;
87900b57cec5SDimitry Andric }
87910b57cec5SDimitry Andric 
87920b57cec5SDimitry Andric // Displays the affinity string to stdout
__kmp_aux_display_affinity(int gtid,const char * format)87930b57cec5SDimitry Andric void __kmp_aux_display_affinity(int gtid, const char *format) {
87940b57cec5SDimitry Andric   kmp_str_buf_t buf;
87950b57cec5SDimitry Andric   __kmp_str_buf_init(&buf);
87960b57cec5SDimitry Andric   __kmp_aux_capture_affinity(gtid, format, &buf);
87970b57cec5SDimitry Andric   __kmp_fprintf(kmp_out, "%s" KMP_END_OF_LINE, buf.str);
87980b57cec5SDimitry Andric   __kmp_str_buf_free(&buf);
87990b57cec5SDimitry Andric }
88000b57cec5SDimitry Andric 
88010b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
__kmp_aux_set_blocktime(int arg,kmp_info_t * thread,int tid)88020b57cec5SDimitry Andric void __kmp_aux_set_blocktime(int arg, kmp_info_t *thread, int tid) {
88035f757f3fSDimitry Andric   int blocktime = arg; /* argument is in microseconds */
88040b57cec5SDimitry Andric #if KMP_USE_MONITOR
88050b57cec5SDimitry Andric   int bt_intervals;
88060b57cec5SDimitry Andric #endif
8807e8d8bef9SDimitry Andric   kmp_int8 bt_set;
88080b57cec5SDimitry Andric 
88090b57cec5SDimitry Andric   __kmp_save_internal_controls(thread);
88100b57cec5SDimitry Andric 
88110b57cec5SDimitry Andric   /* Normalize and set blocktime for the teams */
88120b57cec5SDimitry Andric   if (blocktime < KMP_MIN_BLOCKTIME)
88130b57cec5SDimitry Andric     blocktime = KMP_MIN_BLOCKTIME;
88140b57cec5SDimitry Andric   else if (blocktime > KMP_MAX_BLOCKTIME)
88150b57cec5SDimitry Andric     blocktime = KMP_MAX_BLOCKTIME;
88160b57cec5SDimitry Andric 
88170b57cec5SDimitry Andric   set__blocktime_team(thread->th.th_team, tid, blocktime);
88180b57cec5SDimitry Andric   set__blocktime_team(thread->th.th_serial_team, 0, blocktime);
88190b57cec5SDimitry Andric 
88200b57cec5SDimitry Andric #if KMP_USE_MONITOR
88210b57cec5SDimitry Andric   /* Calculate and set blocktime intervals for the teams */
88220b57cec5SDimitry Andric   bt_intervals = KMP_INTERVALS_FROM_BLOCKTIME(blocktime, __kmp_monitor_wakeups);
88230b57cec5SDimitry Andric 
88240b57cec5SDimitry Andric   set__bt_intervals_team(thread->th.th_team, tid, bt_intervals);
88250b57cec5SDimitry Andric   set__bt_intervals_team(thread->th.th_serial_team, 0, bt_intervals);
88260b57cec5SDimitry Andric #endif
88270b57cec5SDimitry Andric 
88280b57cec5SDimitry Andric   /* Set whether blocktime has been set to "TRUE" */
88290b57cec5SDimitry Andric   bt_set = TRUE;
88300b57cec5SDimitry Andric 
88310b57cec5SDimitry Andric   set__bt_set_team(thread->th.th_team, tid, bt_set);
88320b57cec5SDimitry Andric   set__bt_set_team(thread->th.th_serial_team, 0, bt_set);
88330b57cec5SDimitry Andric #if KMP_USE_MONITOR
88340b57cec5SDimitry Andric   KF_TRACE(10, ("kmp_set_blocktime: T#%d(%d:%d), blocktime=%d, "
88350b57cec5SDimitry Andric                 "bt_intervals=%d, monitor_updates=%d\n",
88360b57cec5SDimitry Andric                 __kmp_gtid_from_tid(tid, thread->th.th_team),
88370b57cec5SDimitry Andric                 thread->th.th_team->t.t_id, tid, blocktime, bt_intervals,
88380b57cec5SDimitry Andric                 __kmp_monitor_wakeups));
88390b57cec5SDimitry Andric #else
88400b57cec5SDimitry Andric   KF_TRACE(10, ("kmp_set_blocktime: T#%d(%d:%d), blocktime=%d\n",
88410b57cec5SDimitry Andric                 __kmp_gtid_from_tid(tid, thread->th.th_team),
88420b57cec5SDimitry Andric                 thread->th.th_team->t.t_id, tid, blocktime));
88430b57cec5SDimitry Andric #endif
88440b57cec5SDimitry Andric }
88450b57cec5SDimitry Andric 
__kmp_aux_set_defaults(char const * str,size_t len)8846e8d8bef9SDimitry Andric void __kmp_aux_set_defaults(char const *str, size_t len) {
88470b57cec5SDimitry Andric   if (!__kmp_init_serial) {
88480b57cec5SDimitry Andric     __kmp_serial_initialize();
88490b57cec5SDimitry Andric   }
88500b57cec5SDimitry Andric   __kmp_env_initialize(str);
88510b57cec5SDimitry Andric 
88520b57cec5SDimitry Andric   if (__kmp_settings || __kmp_display_env || __kmp_display_env_verbose) {
88530b57cec5SDimitry Andric     __kmp_env_print();
88540b57cec5SDimitry Andric   }
88550b57cec5SDimitry Andric } // __kmp_aux_set_defaults
88560b57cec5SDimitry Andric 
88570b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
88580b57cec5SDimitry Andric /* internal fast reduction routines */
88590b57cec5SDimitry Andric 
88600b57cec5SDimitry Andric PACKED_REDUCTION_METHOD_T
__kmp_determine_reduction_method(ident_t * loc,kmp_int32 global_tid,kmp_int32 num_vars,size_t reduce_size,void * reduce_data,void (* reduce_func)(void * lhs_data,void * rhs_data),kmp_critical_name * lck)88610b57cec5SDimitry Andric __kmp_determine_reduction_method(
88620b57cec5SDimitry Andric     ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars, size_t reduce_size,
88630b57cec5SDimitry Andric     void *reduce_data, void (*reduce_func)(void *lhs_data, void *rhs_data),
88640b57cec5SDimitry Andric     kmp_critical_name *lck) {
88650b57cec5SDimitry Andric 
88660b57cec5SDimitry Andric   // Default reduction method: critical construct ( lck != NULL, like in current
88670b57cec5SDimitry Andric   // PAROPT )
88680b57cec5SDimitry Andric   // If ( reduce_data!=NULL && reduce_func!=NULL ): the tree-reduction method
88690b57cec5SDimitry Andric   // can be selected by RTL
88700b57cec5SDimitry Andric   // If loc->flags contains KMP_IDENT_ATOMIC_REDUCE, the atomic reduce method
88710b57cec5SDimitry Andric   // can be selected by RTL
88720b57cec5SDimitry Andric   // Finally, it's up to OpenMP RTL to make a decision on which method to select
88730b57cec5SDimitry Andric   // among generated by PAROPT.
88740b57cec5SDimitry Andric 
88750b57cec5SDimitry Andric   PACKED_REDUCTION_METHOD_T retval;
88760b57cec5SDimitry Andric 
88770b57cec5SDimitry Andric   int team_size;
88780b57cec5SDimitry Andric 
88790b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(lck); // it would be nice to test ( lck != 0 )
88800b57cec5SDimitry Andric 
88810b57cec5SDimitry Andric #define FAST_REDUCTION_ATOMIC_METHOD_GENERATED                                 \
888281ad6265SDimitry Andric   (loc &&                                                                      \
888381ad6265SDimitry Andric    ((loc->flags & (KMP_IDENT_ATOMIC_REDUCE)) == (KMP_IDENT_ATOMIC_REDUCE)))
88840b57cec5SDimitry Andric #define FAST_REDUCTION_TREE_METHOD_GENERATED ((reduce_data) && (reduce_func))
88850b57cec5SDimitry Andric 
88860b57cec5SDimitry Andric   retval = critical_reduce_block;
88870b57cec5SDimitry Andric 
88880b57cec5SDimitry Andric   // another choice of getting a team size (with 1 dynamic deference) is slower
88890b57cec5SDimitry Andric   team_size = __kmp_get_team_num_threads(global_tid);
88900b57cec5SDimitry Andric   if (team_size == 1) {
88910b57cec5SDimitry Andric 
88920b57cec5SDimitry Andric     retval = empty_reduce_block;
88930b57cec5SDimitry Andric 
88940b57cec5SDimitry Andric   } else {
88950b57cec5SDimitry Andric 
88960b57cec5SDimitry Andric     int atomic_available = FAST_REDUCTION_ATOMIC_METHOD_GENERATED;
88970b57cec5SDimitry Andric 
8898489b1cf2SDimitry Andric #if KMP_ARCH_X86_64 || KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 ||                   \
88995f757f3fSDimitry Andric     KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 ||             \
89005f757f3fSDimitry Andric     KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_WASM
89010b57cec5SDimitry Andric 
89020b57cec5SDimitry Andric #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
89035f757f3fSDimitry Andric     KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_DARWIN || KMP_OS_HURD ||        \
89041db9f3b2SDimitry Andric     KMP_OS_SOLARIS || KMP_OS_WASI || KMP_OS_AIX
89050b57cec5SDimitry Andric 
89060b57cec5SDimitry Andric     int teamsize_cutoff = 4;
89070b57cec5SDimitry Andric 
89080b57cec5SDimitry Andric #if KMP_MIC_SUPPORTED
89090b57cec5SDimitry Andric     if (__kmp_mic_type != non_mic) {
89100b57cec5SDimitry Andric       teamsize_cutoff = 8;
89110b57cec5SDimitry Andric     }
89120b57cec5SDimitry Andric #endif
89130b57cec5SDimitry Andric     int tree_available = FAST_REDUCTION_TREE_METHOD_GENERATED;
89140b57cec5SDimitry Andric     if (tree_available) {
89150b57cec5SDimitry Andric       if (team_size <= teamsize_cutoff) {
89160b57cec5SDimitry Andric         if (atomic_available) {
89170b57cec5SDimitry Andric           retval = atomic_reduce_block;
89180b57cec5SDimitry Andric         }
89190b57cec5SDimitry Andric       } else {
89200b57cec5SDimitry Andric         retval = TREE_REDUCE_BLOCK_WITH_REDUCTION_BARRIER;
89210b57cec5SDimitry Andric       }
89220b57cec5SDimitry Andric     } else if (atomic_available) {
89230b57cec5SDimitry Andric       retval = atomic_reduce_block;
89240b57cec5SDimitry Andric     }
89250b57cec5SDimitry Andric #else
89260b57cec5SDimitry Andric #error "Unknown or unsupported OS"
89270b57cec5SDimitry Andric #endif // KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||
89285f757f3fSDimitry Andric        // KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_DARWIN || KMP_OS_HURD ||
89291db9f3b2SDimitry Andric        // KMP_OS_SOLARIS || KMP_OS_WASI || KMP_OS_AIX
89300b57cec5SDimitry Andric 
89315f757f3fSDimitry Andric #elif KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_AARCH || KMP_ARCH_MIPS ||       \
89321db9f3b2SDimitry Andric     KMP_ARCH_WASM || KMP_ARCH_PPC
89330b57cec5SDimitry Andric 
8934b121cb00SDimitry Andric #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
89355f757f3fSDimitry Andric     KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_HURD || KMP_OS_SOLARIS ||       \
89361db9f3b2SDimitry Andric     KMP_OS_WASI || KMP_OS_AIX
89370b57cec5SDimitry Andric 
89380b57cec5SDimitry Andric     // basic tuning
89390b57cec5SDimitry Andric 
89400b57cec5SDimitry Andric     if (atomic_available) {
89410b57cec5SDimitry Andric       if (num_vars <= 2) { // && ( team_size <= 8 ) due to false-sharing ???
89420b57cec5SDimitry Andric         retval = atomic_reduce_block;
89430b57cec5SDimitry Andric       }
89440b57cec5SDimitry Andric     } // otherwise: use critical section
89450b57cec5SDimitry Andric 
89460b57cec5SDimitry Andric #elif KMP_OS_DARWIN
89470b57cec5SDimitry Andric 
89480b57cec5SDimitry Andric     int tree_available = FAST_REDUCTION_TREE_METHOD_GENERATED;
89490b57cec5SDimitry Andric     if (atomic_available && (num_vars <= 3)) {
89500b57cec5SDimitry Andric       retval = atomic_reduce_block;
89510b57cec5SDimitry Andric     } else if (tree_available) {
89520b57cec5SDimitry Andric       if ((reduce_size > (9 * sizeof(kmp_real64))) &&
89530b57cec5SDimitry Andric           (reduce_size < (2000 * sizeof(kmp_real64)))) {
89540b57cec5SDimitry Andric         retval = TREE_REDUCE_BLOCK_WITH_PLAIN_BARRIER;
89550b57cec5SDimitry Andric       }
89560b57cec5SDimitry Andric     } // otherwise: use critical section
89570b57cec5SDimitry Andric 
89580b57cec5SDimitry Andric #else
89590b57cec5SDimitry Andric #error "Unknown or unsupported OS"
89600b57cec5SDimitry Andric #endif
89610b57cec5SDimitry Andric 
89620b57cec5SDimitry Andric #else
89630b57cec5SDimitry Andric #error "Unknown or unsupported architecture"
89640b57cec5SDimitry Andric #endif
89650b57cec5SDimitry Andric   }
89660b57cec5SDimitry Andric 
89670b57cec5SDimitry Andric   // KMP_FORCE_REDUCTION
89680b57cec5SDimitry Andric 
89690b57cec5SDimitry Andric   // If the team is serialized (team_size == 1), ignore the forced reduction
89700b57cec5SDimitry Andric   // method and stay with the unsynchronized method (empty_reduce_block)
89710b57cec5SDimitry Andric   if (__kmp_force_reduction_method != reduction_method_not_defined &&
89720b57cec5SDimitry Andric       team_size != 1) {
89730b57cec5SDimitry Andric 
89740b57cec5SDimitry Andric     PACKED_REDUCTION_METHOD_T forced_retval = critical_reduce_block;
89750b57cec5SDimitry Andric 
89760b57cec5SDimitry Andric     int atomic_available, tree_available;
89770b57cec5SDimitry Andric 
89780b57cec5SDimitry Andric     switch ((forced_retval = __kmp_force_reduction_method)) {
89790b57cec5SDimitry Andric     case critical_reduce_block:
89800b57cec5SDimitry Andric       KMP_ASSERT(lck); // lck should be != 0
89810b57cec5SDimitry Andric       break;
89820b57cec5SDimitry Andric 
89830b57cec5SDimitry Andric     case atomic_reduce_block:
89840b57cec5SDimitry Andric       atomic_available = FAST_REDUCTION_ATOMIC_METHOD_GENERATED;
89850b57cec5SDimitry Andric       if (!atomic_available) {
89860b57cec5SDimitry Andric         KMP_WARNING(RedMethodNotSupported, "atomic");
89870b57cec5SDimitry Andric         forced_retval = critical_reduce_block;
89880b57cec5SDimitry Andric       }
89890b57cec5SDimitry Andric       break;
89900b57cec5SDimitry Andric 
89910b57cec5SDimitry Andric     case tree_reduce_block:
89920b57cec5SDimitry Andric       tree_available = FAST_REDUCTION_TREE_METHOD_GENERATED;
89930b57cec5SDimitry Andric       if (!tree_available) {
89940b57cec5SDimitry Andric         KMP_WARNING(RedMethodNotSupported, "tree");
89950b57cec5SDimitry Andric         forced_retval = critical_reduce_block;
89960b57cec5SDimitry Andric       } else {
89970b57cec5SDimitry Andric #if KMP_FAST_REDUCTION_BARRIER
89980b57cec5SDimitry Andric         forced_retval = TREE_REDUCE_BLOCK_WITH_REDUCTION_BARRIER;
89990b57cec5SDimitry Andric #endif
90000b57cec5SDimitry Andric       }
90010b57cec5SDimitry Andric       break;
90020b57cec5SDimitry Andric 
90030b57cec5SDimitry Andric     default:
90040b57cec5SDimitry Andric       KMP_ASSERT(0); // "unsupported method specified"
90050b57cec5SDimitry Andric     }
90060b57cec5SDimitry Andric 
90070b57cec5SDimitry Andric     retval = forced_retval;
90080b57cec5SDimitry Andric   }
90090b57cec5SDimitry Andric 
90100b57cec5SDimitry Andric   KA_TRACE(10, ("reduction method selected=%08x\n", retval));
90110b57cec5SDimitry Andric 
90120b57cec5SDimitry Andric #undef FAST_REDUCTION_TREE_METHOD_GENERATED
90130b57cec5SDimitry Andric #undef FAST_REDUCTION_ATOMIC_METHOD_GENERATED
90140b57cec5SDimitry Andric 
90150b57cec5SDimitry Andric   return (retval);
90160b57cec5SDimitry Andric }
90170b57cec5SDimitry Andric // this function is for testing set/get/determine reduce method
__kmp_get_reduce_method(void)90180b57cec5SDimitry Andric kmp_int32 __kmp_get_reduce_method(void) {
90190b57cec5SDimitry Andric   return ((__kmp_entry_thread()->th.th_local.packed_reduction_method) >> 8);
90200b57cec5SDimitry Andric }
90210b57cec5SDimitry Andric 
90220b57cec5SDimitry Andric // Soft pause sets up threads to ignore blocktime and just go to sleep.
90230b57cec5SDimitry Andric // Spin-wait code checks __kmp_pause_status and reacts accordingly.
__kmp_soft_pause()90240b57cec5SDimitry Andric void __kmp_soft_pause() { __kmp_pause_status = kmp_soft_paused; }
90250b57cec5SDimitry Andric 
90260b57cec5SDimitry Andric // Hard pause shuts down the runtime completely.  Resume happens naturally when
90270b57cec5SDimitry Andric // OpenMP is used subsequently.
__kmp_hard_pause()90280b57cec5SDimitry Andric void __kmp_hard_pause() {
90290b57cec5SDimitry Andric   __kmp_pause_status = kmp_hard_paused;
90300b57cec5SDimitry Andric   __kmp_internal_end_thread(-1);
90310b57cec5SDimitry Andric }
90320b57cec5SDimitry Andric 
90330b57cec5SDimitry Andric // Soft resume sets __kmp_pause_status, and wakes up all threads.
__kmp_resume_if_soft_paused()90340b57cec5SDimitry Andric void __kmp_resume_if_soft_paused() {
90350b57cec5SDimitry Andric   if (__kmp_pause_status == kmp_soft_paused) {
90360b57cec5SDimitry Andric     __kmp_pause_status = kmp_not_paused;
90370b57cec5SDimitry Andric 
90380b57cec5SDimitry Andric     for (int gtid = 1; gtid < __kmp_threads_capacity; ++gtid) {
90390b57cec5SDimitry Andric       kmp_info_t *thread = __kmp_threads[gtid];
90400b57cec5SDimitry Andric       if (thread) { // Wake it if sleeping
9041e8d8bef9SDimitry Andric         kmp_flag_64<> fl(&thread->th.th_bar[bs_forkjoin_barrier].bb.b_go,
9042e8d8bef9SDimitry Andric                          thread);
90430b57cec5SDimitry Andric         if (fl.is_sleeping())
90440b57cec5SDimitry Andric           fl.resume(gtid);
90450b57cec5SDimitry Andric         else if (__kmp_try_suspend_mx(thread)) { // got suspend lock
90460b57cec5SDimitry Andric           __kmp_unlock_suspend_mx(thread); // unlock it; it won't sleep
90470b57cec5SDimitry Andric         } else { // thread holds the lock and may sleep soon
90480b57cec5SDimitry Andric           do { // until either the thread sleeps, or we can get the lock
90490b57cec5SDimitry Andric             if (fl.is_sleeping()) {
90500b57cec5SDimitry Andric               fl.resume(gtid);
90510b57cec5SDimitry Andric               break;
90520b57cec5SDimitry Andric             } else if (__kmp_try_suspend_mx(thread)) {
90530b57cec5SDimitry Andric               __kmp_unlock_suspend_mx(thread);
90540b57cec5SDimitry Andric               break;
90550b57cec5SDimitry Andric             }
90560b57cec5SDimitry Andric           } while (1);
90570b57cec5SDimitry Andric         }
90580b57cec5SDimitry Andric       }
90590b57cec5SDimitry Andric     }
90600b57cec5SDimitry Andric   }
90610b57cec5SDimitry Andric }
90620b57cec5SDimitry Andric 
90630b57cec5SDimitry Andric // This function is called via __kmpc_pause_resource. Returns 0 if successful.
90640b57cec5SDimitry Andric // TODO: add warning messages
__kmp_pause_resource(kmp_pause_status_t level)90650b57cec5SDimitry Andric int __kmp_pause_resource(kmp_pause_status_t level) {
90660b57cec5SDimitry Andric   if (level == kmp_not_paused) { // requesting resume
90670b57cec5SDimitry Andric     if (__kmp_pause_status == kmp_not_paused) {
90680b57cec5SDimitry Andric       // error message about runtime not being paused, so can't resume
90690b57cec5SDimitry Andric       return 1;
90700b57cec5SDimitry Andric     } else {
90710b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(__kmp_pause_status == kmp_soft_paused ||
90720b57cec5SDimitry Andric                        __kmp_pause_status == kmp_hard_paused);
90730b57cec5SDimitry Andric       __kmp_pause_status = kmp_not_paused;
90740b57cec5SDimitry Andric       return 0;
90750b57cec5SDimitry Andric     }
90760b57cec5SDimitry Andric   } else if (level == kmp_soft_paused) { // requesting soft pause
90770b57cec5SDimitry Andric     if (__kmp_pause_status != kmp_not_paused) {
90780b57cec5SDimitry Andric       // error message about already being paused
90790b57cec5SDimitry Andric       return 1;
90800b57cec5SDimitry Andric     } else {
90810b57cec5SDimitry Andric       __kmp_soft_pause();
90820b57cec5SDimitry Andric       return 0;
90830b57cec5SDimitry Andric     }
90840b57cec5SDimitry Andric   } else if (level == kmp_hard_paused) { // requesting hard pause
90850b57cec5SDimitry Andric     if (__kmp_pause_status != kmp_not_paused) {
90860b57cec5SDimitry Andric       // error message about already being paused
90870b57cec5SDimitry Andric       return 1;
90880b57cec5SDimitry Andric     } else {
90890b57cec5SDimitry Andric       __kmp_hard_pause();
90900b57cec5SDimitry Andric       return 0;
90910b57cec5SDimitry Andric     }
90920b57cec5SDimitry Andric   } else {
90930b57cec5SDimitry Andric     // error message about invalid level
90940b57cec5SDimitry Andric     return 1;
90950b57cec5SDimitry Andric   }
90960b57cec5SDimitry Andric }
90975ffd83dbSDimitry Andric 
__kmp_omp_display_env(int verbose)90985ffd83dbSDimitry Andric void __kmp_omp_display_env(int verbose) {
90995ffd83dbSDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
91005ffd83dbSDimitry Andric   if (__kmp_init_serial == 0)
91015ffd83dbSDimitry Andric     __kmp_do_serial_initialize();
91025ffd83dbSDimitry Andric   __kmp_display_env_impl(!verbose, verbose);
91035ffd83dbSDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
91045ffd83dbSDimitry Andric }
9105e8d8bef9SDimitry Andric 
9106349cc55cSDimitry Andric // The team size is changing, so distributed barrier must be modified
__kmp_resize_dist_barrier(kmp_team_t * team,int old_nthreads,int new_nthreads)9107349cc55cSDimitry Andric void __kmp_resize_dist_barrier(kmp_team_t *team, int old_nthreads,
9108349cc55cSDimitry Andric                                int new_nthreads) {
9109349cc55cSDimitry Andric   KMP_DEBUG_ASSERT(__kmp_barrier_release_pattern[bs_forkjoin_barrier] ==
9110349cc55cSDimitry Andric                    bp_dist_bar);
9111349cc55cSDimitry Andric   kmp_info_t **other_threads = team->t.t_threads;
9112349cc55cSDimitry Andric 
9113349cc55cSDimitry Andric   // We want all the workers to stop waiting on the barrier while we adjust the
9114349cc55cSDimitry Andric   // size of the team.
9115349cc55cSDimitry Andric   for (int f = 1; f < old_nthreads; ++f) {
9116349cc55cSDimitry Andric     KMP_DEBUG_ASSERT(other_threads[f] != NULL);
9117349cc55cSDimitry Andric     // Ignore threads that are already inactive or not present in the team
9118349cc55cSDimitry Andric     if (team->t.t_threads[f]->th.th_used_in_team.load() == 0) {
9119349cc55cSDimitry Andric       // teams construct causes thread_limit to get passed in, and some of
9120349cc55cSDimitry Andric       // those could be inactive; just ignore them
9121349cc55cSDimitry Andric       continue;
9122349cc55cSDimitry Andric     }
9123349cc55cSDimitry Andric     // If thread is transitioning still to in_use state, wait for it
9124349cc55cSDimitry Andric     if (team->t.t_threads[f]->th.th_used_in_team.load() == 3) {
9125349cc55cSDimitry Andric       while (team->t.t_threads[f]->th.th_used_in_team.load() == 3)
9126349cc55cSDimitry Andric         KMP_CPU_PAUSE();
9127349cc55cSDimitry Andric     }
9128349cc55cSDimitry Andric     // The thread should be in_use now
9129349cc55cSDimitry Andric     KMP_DEBUG_ASSERT(team->t.t_threads[f]->th.th_used_in_team.load() == 1);
9130349cc55cSDimitry Andric     // Transition to unused state
9131349cc55cSDimitry Andric     team->t.t_threads[f]->th.th_used_in_team.store(2);
9132349cc55cSDimitry Andric     KMP_DEBUG_ASSERT(team->t.t_threads[f]->th.th_used_in_team.load() == 2);
9133349cc55cSDimitry Andric   }
9134349cc55cSDimitry Andric   // Release all the workers
913581ad6265SDimitry Andric   team->t.b->go_release();
9136349cc55cSDimitry Andric 
9137349cc55cSDimitry Andric   KMP_MFENCE();
9138349cc55cSDimitry Andric 
9139349cc55cSDimitry Andric   // Workers should see transition status 2 and move to 0; but may need to be
9140349cc55cSDimitry Andric   // woken up first
9141349cc55cSDimitry Andric   int count = old_nthreads - 1;
9142349cc55cSDimitry Andric   while (count > 0) {
9143349cc55cSDimitry Andric     count = old_nthreads - 1;
9144349cc55cSDimitry Andric     for (int f = 1; f < old_nthreads; ++f) {
9145349cc55cSDimitry Andric       if (other_threads[f]->th.th_used_in_team.load() != 0) {
9146349cc55cSDimitry Andric         if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) { // Wake up the workers
9147349cc55cSDimitry Andric           kmp_atomic_flag_64<> *flag = (kmp_atomic_flag_64<> *)CCAST(
9148349cc55cSDimitry Andric               void *, other_threads[f]->th.th_sleep_loc);
9149349cc55cSDimitry Andric           __kmp_atomic_resume_64(other_threads[f]->th.th_info.ds.ds_gtid, flag);
9150349cc55cSDimitry Andric         }
9151349cc55cSDimitry Andric       } else {
9152349cc55cSDimitry Andric         KMP_DEBUG_ASSERT(team->t.t_threads[f]->th.th_used_in_team.load() == 0);
9153349cc55cSDimitry Andric         count--;
9154349cc55cSDimitry Andric       }
9155349cc55cSDimitry Andric     }
9156349cc55cSDimitry Andric   }
9157349cc55cSDimitry Andric   // Now update the barrier size
9158349cc55cSDimitry Andric   team->t.b->update_num_threads(new_nthreads);
9159349cc55cSDimitry Andric   team->t.b->go_reset();
9160349cc55cSDimitry Andric }
9161349cc55cSDimitry Andric 
__kmp_add_threads_to_team(kmp_team_t * team,int new_nthreads)9162349cc55cSDimitry Andric void __kmp_add_threads_to_team(kmp_team_t *team, int new_nthreads) {
9163349cc55cSDimitry Andric   // Add the threads back to the team
9164349cc55cSDimitry Andric   KMP_DEBUG_ASSERT(team);
9165349cc55cSDimitry Andric   // Threads were paused and pointed at th_used_in_team temporarily during a
9166349cc55cSDimitry Andric   // resize of the team. We're going to set th_used_in_team to 3 to indicate to
9167349cc55cSDimitry Andric   // the thread that it should transition itself back into the team. Then, if
9168349cc55cSDimitry Andric   // blocktime isn't infinite, the thread could be sleeping, so we send a resume
9169349cc55cSDimitry Andric   // to wake it up.
9170349cc55cSDimitry Andric   for (int f = 1; f < new_nthreads; ++f) {
9171349cc55cSDimitry Andric     KMP_DEBUG_ASSERT(team->t.t_threads[f]);
9172349cc55cSDimitry Andric     KMP_COMPARE_AND_STORE_ACQ32(&(team->t.t_threads[f]->th.th_used_in_team), 0,
9173349cc55cSDimitry Andric                                 3);
9174349cc55cSDimitry Andric     if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) { // Wake up sleeping threads
9175349cc55cSDimitry Andric       __kmp_resume_32(team->t.t_threads[f]->th.th_info.ds.ds_gtid,
9176349cc55cSDimitry Andric                       (kmp_flag_32<false, false> *)NULL);
9177349cc55cSDimitry Andric     }
9178349cc55cSDimitry Andric   }
9179349cc55cSDimitry Andric   // The threads should be transitioning to the team; when they are done, they
9180349cc55cSDimitry Andric   // should have set th_used_in_team to 1. This loop forces master to wait until
9181349cc55cSDimitry Andric   // all threads have moved into the team and are waiting in the barrier.
9182349cc55cSDimitry Andric   int count = new_nthreads - 1;
9183349cc55cSDimitry Andric   while (count > 0) {
9184349cc55cSDimitry Andric     count = new_nthreads - 1;
9185349cc55cSDimitry Andric     for (int f = 1; f < new_nthreads; ++f) {
9186349cc55cSDimitry Andric       if (team->t.t_threads[f]->th.th_used_in_team.load() == 1) {
9187349cc55cSDimitry Andric         count--;
9188349cc55cSDimitry Andric       }
9189349cc55cSDimitry Andric     }
9190349cc55cSDimitry Andric   }
9191349cc55cSDimitry Andric }
9192349cc55cSDimitry Andric 
9193e8d8bef9SDimitry Andric // Globals and functions for hidden helper task
9194e8d8bef9SDimitry Andric kmp_info_t **__kmp_hidden_helper_threads;
9195e8d8bef9SDimitry Andric kmp_info_t *__kmp_hidden_helper_main_thread;
9196e8d8bef9SDimitry Andric std::atomic<kmp_int32> __kmp_unexecuted_hidden_helper_tasks;
9197e8d8bef9SDimitry Andric #if KMP_OS_LINUX
9198fe6060f1SDimitry Andric kmp_int32 __kmp_hidden_helper_threads_num = 8;
9199e8d8bef9SDimitry Andric kmp_int32 __kmp_enable_hidden_helper = TRUE;
9200e8d8bef9SDimitry Andric #else
9201fe6060f1SDimitry Andric kmp_int32 __kmp_hidden_helper_threads_num = 0;
9202e8d8bef9SDimitry Andric kmp_int32 __kmp_enable_hidden_helper = FALSE;
9203e8d8bef9SDimitry Andric #endif
9204e8d8bef9SDimitry Andric 
9205e8d8bef9SDimitry Andric namespace {
9206e8d8bef9SDimitry Andric std::atomic<kmp_int32> __kmp_hit_hidden_helper_threads_num;
9207e8d8bef9SDimitry Andric 
__kmp_hidden_helper_wrapper_fn(int * gtid,int *,...)9208e8d8bef9SDimitry Andric void __kmp_hidden_helper_wrapper_fn(int *gtid, int *, ...) {
9209e8d8bef9SDimitry Andric   // This is an explicit synchronization on all hidden helper threads in case
9210e8d8bef9SDimitry Andric   // that when a regular thread pushes a hidden helper task to one hidden
9211e8d8bef9SDimitry Andric   // helper thread, the thread has not been awaken once since they're released
9212e8d8bef9SDimitry Andric   // by the main thread after creating the team.
9213e8d8bef9SDimitry Andric   KMP_ATOMIC_INC(&__kmp_hit_hidden_helper_threads_num);
9214e8d8bef9SDimitry Andric   while (KMP_ATOMIC_LD_ACQ(&__kmp_hit_hidden_helper_threads_num) !=
9215e8d8bef9SDimitry Andric          __kmp_hidden_helper_threads_num)
9216e8d8bef9SDimitry Andric     ;
9217e8d8bef9SDimitry Andric 
9218e8d8bef9SDimitry Andric   // If main thread, then wait for signal
9219e8d8bef9SDimitry Andric   if (__kmpc_master(nullptr, *gtid)) {
9220e8d8bef9SDimitry Andric     // First, unset the initial state and release the initial thread
9221e8d8bef9SDimitry Andric     TCW_4(__kmp_init_hidden_helper_threads, FALSE);
9222e8d8bef9SDimitry Andric     __kmp_hidden_helper_initz_release();
9223e8d8bef9SDimitry Andric     __kmp_hidden_helper_main_thread_wait();
9224e8d8bef9SDimitry Andric     // Now wake up all worker threads
9225e8d8bef9SDimitry Andric     for (int i = 1; i < __kmp_hit_hidden_helper_threads_num; ++i) {
9226e8d8bef9SDimitry Andric       __kmp_hidden_helper_worker_thread_signal();
9227e8d8bef9SDimitry Andric     }
9228e8d8bef9SDimitry Andric   }
9229e8d8bef9SDimitry Andric }
9230e8d8bef9SDimitry Andric } // namespace
9231e8d8bef9SDimitry Andric 
__kmp_hidden_helper_threads_initz_routine()9232e8d8bef9SDimitry Andric void __kmp_hidden_helper_threads_initz_routine() {
9233e8d8bef9SDimitry Andric   // Create a new root for hidden helper team/threads
9234e8d8bef9SDimitry Andric   const int gtid = __kmp_register_root(TRUE);
9235e8d8bef9SDimitry Andric   __kmp_hidden_helper_main_thread = __kmp_threads[gtid];
9236e8d8bef9SDimitry Andric   __kmp_hidden_helper_threads = &__kmp_threads[gtid];
9237e8d8bef9SDimitry Andric   __kmp_hidden_helper_main_thread->th.th_set_nproc =
9238e8d8bef9SDimitry Andric       __kmp_hidden_helper_threads_num;
9239e8d8bef9SDimitry Andric 
9240e8d8bef9SDimitry Andric   KMP_ATOMIC_ST_REL(&__kmp_hit_hidden_helper_threads_num, 0);
9241e8d8bef9SDimitry Andric 
9242e8d8bef9SDimitry Andric   __kmpc_fork_call(nullptr, 0, __kmp_hidden_helper_wrapper_fn);
9243e8d8bef9SDimitry Andric 
9244e8d8bef9SDimitry Andric   // Set the initialization flag to FALSE
9245e8d8bef9SDimitry Andric   TCW_SYNC_4(__kmp_init_hidden_helper, FALSE);
9246e8d8bef9SDimitry Andric 
9247e8d8bef9SDimitry Andric   __kmp_hidden_helper_threads_deinitz_release();
9248e8d8bef9SDimitry Andric }
9249fe6060f1SDimitry Andric 
9250fe6060f1SDimitry Andric /* Nesting Mode:
9251fe6060f1SDimitry Andric    Set via KMP_NESTING_MODE, which takes an integer.
9252fe6060f1SDimitry Andric    Note: we skip duplicate topology levels, and skip levels with only
9253fe6060f1SDimitry Andric       one entity.
9254fe6060f1SDimitry Andric    KMP_NESTING_MODE=0 is the default, and doesn't use nesting mode.
9255fe6060f1SDimitry Andric    KMP_NESTING_MODE=1 sets as many nesting levels as there are distinct levels
9256fe6060f1SDimitry Andric       in the topology, and initializes the number of threads at each of those
9257fe6060f1SDimitry Andric       levels to the number of entities at each level, respectively, below the
9258fe6060f1SDimitry Andric       entity at the parent level.
9259fe6060f1SDimitry Andric    KMP_NESTING_MODE=N, where N>1, attempts to create up to N nesting levels,
9260fe6060f1SDimitry Andric       but starts with nesting OFF -- max-active-levels-var is 1 -- and requires
9261fe6060f1SDimitry Andric       the user to turn nesting on explicitly. This is an even more experimental
9262fe6060f1SDimitry Andric       option to this experimental feature, and may change or go away in the
9263fe6060f1SDimitry Andric       future.
9264fe6060f1SDimitry Andric */
9265fe6060f1SDimitry Andric 
9266fe6060f1SDimitry Andric // Allocate space to store nesting levels
__kmp_init_nesting_mode()9267fe6060f1SDimitry Andric void __kmp_init_nesting_mode() {
9268fe6060f1SDimitry Andric   int levels = KMP_HW_LAST;
9269fe6060f1SDimitry Andric   __kmp_nesting_mode_nlevels = levels;
9270fe6060f1SDimitry Andric   __kmp_nesting_nth_level = (int *)KMP_INTERNAL_MALLOC(levels * sizeof(int));
9271fe6060f1SDimitry Andric   for (int i = 0; i < levels; ++i)
9272fe6060f1SDimitry Andric     __kmp_nesting_nth_level[i] = 0;
9273fe6060f1SDimitry Andric   if (__kmp_nested_nth.size < levels) {
9274fe6060f1SDimitry Andric     __kmp_nested_nth.nth =
9275fe6060f1SDimitry Andric         (int *)KMP_INTERNAL_REALLOC(__kmp_nested_nth.nth, levels * sizeof(int));
9276fe6060f1SDimitry Andric     __kmp_nested_nth.size = levels;
9277fe6060f1SDimitry Andric   }
9278fe6060f1SDimitry Andric }
9279fe6060f1SDimitry Andric 
9280fe6060f1SDimitry Andric // Set # threads for top levels of nesting; must be called after topology set
__kmp_set_nesting_mode_threads()9281fe6060f1SDimitry Andric void __kmp_set_nesting_mode_threads() {
9282fe6060f1SDimitry Andric   kmp_info_t *thread = __kmp_threads[__kmp_entry_gtid()];
9283fe6060f1SDimitry Andric 
9284fe6060f1SDimitry Andric   if (__kmp_nesting_mode == 1)
9285fe6060f1SDimitry Andric     __kmp_nesting_mode_nlevels = KMP_MAX_ACTIVE_LEVELS_LIMIT;
9286fe6060f1SDimitry Andric   else if (__kmp_nesting_mode > 1)
9287fe6060f1SDimitry Andric     __kmp_nesting_mode_nlevels = __kmp_nesting_mode;
9288fe6060f1SDimitry Andric 
9289fe6060f1SDimitry Andric   if (__kmp_topology) { // use topology info
9290fe6060f1SDimitry Andric     int loc, hw_level;
9291fe6060f1SDimitry Andric     for (loc = 0, hw_level = 0; hw_level < __kmp_topology->get_depth() &&
9292fe6060f1SDimitry Andric                                 loc < __kmp_nesting_mode_nlevels;
9293fe6060f1SDimitry Andric          loc++, hw_level++) {
9294fe6060f1SDimitry Andric       __kmp_nesting_nth_level[loc] = __kmp_topology->get_ratio(hw_level);
9295fe6060f1SDimitry Andric       if (__kmp_nesting_nth_level[loc] == 1)
9296fe6060f1SDimitry Andric         loc--;
9297fe6060f1SDimitry Andric     }
9298fe6060f1SDimitry Andric     // Make sure all cores are used
9299fe6060f1SDimitry Andric     if (__kmp_nesting_mode > 1 && loc > 1) {
9300fe6060f1SDimitry Andric       int core_level = __kmp_topology->get_level(KMP_HW_CORE);
9301fe6060f1SDimitry Andric       int num_cores = __kmp_topology->get_count(core_level);
9302fe6060f1SDimitry Andric       int upper_levels = 1;
9303fe6060f1SDimitry Andric       for (int level = 0; level < loc - 1; ++level)
9304fe6060f1SDimitry Andric         upper_levels *= __kmp_nesting_nth_level[level];
9305fe6060f1SDimitry Andric       if (upper_levels * __kmp_nesting_nth_level[loc - 1] < num_cores)
9306fe6060f1SDimitry Andric         __kmp_nesting_nth_level[loc - 1] =
9307fe6060f1SDimitry Andric             num_cores / __kmp_nesting_nth_level[loc - 2];
9308fe6060f1SDimitry Andric     }
9309fe6060f1SDimitry Andric     __kmp_nesting_mode_nlevels = loc;
9310fe6060f1SDimitry Andric     __kmp_nested_nth.used = __kmp_nesting_mode_nlevels;
9311fe6060f1SDimitry Andric   } else { // no topology info available; provide a reasonable guesstimation
9312fe6060f1SDimitry Andric     if (__kmp_avail_proc >= 4) {
9313fe6060f1SDimitry Andric       __kmp_nesting_nth_level[0] = __kmp_avail_proc / 2;
9314fe6060f1SDimitry Andric       __kmp_nesting_nth_level[1] = 2;
9315fe6060f1SDimitry Andric       __kmp_nesting_mode_nlevels = 2;
9316fe6060f1SDimitry Andric     } else {
9317fe6060f1SDimitry Andric       __kmp_nesting_nth_level[0] = __kmp_avail_proc;
9318fe6060f1SDimitry Andric       __kmp_nesting_mode_nlevels = 1;
9319fe6060f1SDimitry Andric     }
9320fe6060f1SDimitry Andric     __kmp_nested_nth.used = __kmp_nesting_mode_nlevels;
9321fe6060f1SDimitry Andric   }
9322fe6060f1SDimitry Andric   for (int i = 0; i < __kmp_nesting_mode_nlevels; ++i) {
9323fe6060f1SDimitry Andric     __kmp_nested_nth.nth[i] = __kmp_nesting_nth_level[i];
9324fe6060f1SDimitry Andric   }
9325fe6060f1SDimitry Andric   set__nproc(thread, __kmp_nesting_nth_level[0]);
9326fe6060f1SDimitry Andric   if (__kmp_nesting_mode > 1 && __kmp_nesting_mode_nlevels > __kmp_nesting_mode)
9327fe6060f1SDimitry Andric     __kmp_nesting_mode_nlevels = __kmp_nesting_mode;
9328fe6060f1SDimitry Andric   if (get__max_active_levels(thread) > 1) {
9329fe6060f1SDimitry Andric     // if max levels was set, set nesting mode levels to same
9330fe6060f1SDimitry Andric     __kmp_nesting_mode_nlevels = get__max_active_levels(thread);
9331fe6060f1SDimitry Andric   }
9332fe6060f1SDimitry Andric   if (__kmp_nesting_mode == 1) // turn on nesting for this case only
9333fe6060f1SDimitry Andric     set__max_active_levels(thread, __kmp_nesting_mode_nlevels);
9334fe6060f1SDimitry Andric }
9335bdd1243dSDimitry Andric 
9336bdd1243dSDimitry Andric // Empty symbols to export (see exports_so.txt) when feature is disabled
9337bdd1243dSDimitry Andric extern "C" {
9338bdd1243dSDimitry Andric #if !KMP_STATS_ENABLED
__kmp_reset_stats()9339bdd1243dSDimitry Andric void __kmp_reset_stats() {}
9340bdd1243dSDimitry Andric #endif
9341bdd1243dSDimitry Andric #if !USE_DEBUGGER
9342bdd1243dSDimitry Andric int __kmp_omp_debug_struct_info = FALSE;
9343bdd1243dSDimitry Andric int __kmp_debugging = FALSE;
9344bdd1243dSDimitry Andric #endif
9345bdd1243dSDimitry Andric #if !USE_ITT_BUILD || !USE_ITT_NOTIFY
__kmp_itt_fini_ittlib()9346bdd1243dSDimitry Andric void __kmp_itt_fini_ittlib() {}
__kmp_itt_init_ittlib()9347bdd1243dSDimitry Andric void __kmp_itt_init_ittlib() {}
9348bdd1243dSDimitry Andric #endif
9349bdd1243dSDimitry Andric }
9350bdd1243dSDimitry Andric 
9351bdd1243dSDimitry Andric // end of file
9352