17cc577a4SJonathan Peyton /*
2de4749b7SJonathan Peyton  * z_Linux_util.cpp -- platform specific routines.
37cc577a4SJonathan Peyton  */
47cc577a4SJonathan Peyton 
57cc577a4SJonathan Peyton //===----------------------------------------------------------------------===//
67cc577a4SJonathan Peyton //
757b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
857b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
957b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
107cc577a4SJonathan Peyton //
117cc577a4SJonathan Peyton //===----------------------------------------------------------------------===//
127cc577a4SJonathan Peyton 
137cc577a4SJonathan Peyton #include "kmp.h"
147cc577a4SJonathan Peyton #include "kmp_affinity.h"
153041982dSJonathan Peyton #include "kmp_i18n.h"
163041982dSJonathan Peyton #include "kmp_io.h"
173041982dSJonathan Peyton #include "kmp_itt.h"
183041982dSJonathan Peyton #include "kmp_lock.h"
193041982dSJonathan Peyton #include "kmp_stats.h"
203041982dSJonathan Peyton #include "kmp_str.h"
213041982dSJonathan Peyton #include "kmp_wait_release.h"
223041982dSJonathan Peyton #include "kmp_wrapper_getpid.h"
237cc577a4SJonathan Peyton 
247e1ea993SKamil Rytarowski #if !KMP_OS_DRAGONFLY && !KMP_OS_FREEBSD && !KMP_OS_NETBSD && !KMP_OS_OPENBSD
257cc577a4SJonathan Peyton #include <alloca.h>
267cc577a4SJonathan Peyton #endif
277cc577a4SJonathan Peyton #include <math.h> // HUGE_VAL.
28f1b9ce27SHansang Bae #if KMP_OS_LINUX
299d64275aSShilei Tian #include <semaphore.h>
30f1b9ce27SHansang Bae #endif // KMP_OS_LINUX
317cc577a4SJonathan Peyton #include <sys/resource.h>
327cc577a4SJonathan Peyton #include <sys/syscall.h>
333041982dSJonathan Peyton #include <sys/time.h>
343041982dSJonathan Peyton #include <sys/times.h>
353041982dSJonathan Peyton #include <unistd.h>
367cc577a4SJonathan Peyton 
37d28f8672SJinsong Ji #if KMP_OS_LINUX
387cc577a4SJonathan Peyton #include <sys/sysinfo.h>
397cc577a4SJonathan Peyton #if KMP_USE_FUTEX
403041982dSJonathan Peyton // We should really include <futex.h>, but that causes compatibility problems on
413041982dSJonathan Peyton // different Linux* OS distributions that either require that you include (or
423041982dSJonathan Peyton // break when you try to include) <pci/types.h>. Since all we need is the two
433041982dSJonathan Peyton // macros below (which are part of the kernel ABI, so can't change) we just
443041982dSJonathan Peyton // define the constants here and don't include <futex.h>
457cc577a4SJonathan Peyton #ifndef FUTEX_WAIT
467cc577a4SJonathan Peyton #define FUTEX_WAIT 0
477cc577a4SJonathan Peyton #endif
487cc577a4SJonathan Peyton #ifndef FUTEX_WAKE
497cc577a4SJonathan Peyton #define FUTEX_WAKE 1
507cc577a4SJonathan Peyton #endif
517cc577a4SJonathan Peyton #endif
527cc577a4SJonathan Peyton #elif KMP_OS_DARWIN
537cc577a4SJonathan Peyton #include <mach/mach.h>
543041982dSJonathan Peyton #include <sys/sysctl.h>
55a56ac949SKamil Rytarowski #elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD
56fef62e1aSDavid Carlier #include <sys/types.h>
57fef62e1aSDavid Carlier #include <sys/sysctl.h>
58fef62e1aSDavid Carlier #include <sys/user.h>
597cc577a4SJonathan Peyton #include <pthread_np.h>
6027f6eedcSAndreyChurbanov #elif KMP_OS_NETBSD || KMP_OS_OPENBSD
61316f4238SKamil Rytarowski #include <sys/types.h>
62316f4238SKamil Rytarowski #include <sys/sysctl.h>
637cc577a4SJonathan Peyton #endif
647cc577a4SJonathan Peyton 
657cc577a4SJonathan Peyton #include <ctype.h>
663041982dSJonathan Peyton #include <dirent.h>
677cc577a4SJonathan Peyton #include <fcntl.h>
687cc577a4SJonathan Peyton 
697cc577a4SJonathan Peyton struct kmp_sys_timer {
707cc577a4SJonathan Peyton   struct timespec start;
717cc577a4SJonathan Peyton };
727cc577a4SJonathan Peyton 
737cc577a4SJonathan Peyton // Convert timespec to nanoseconds.
746b316febSTerry Wilmarth #define TS2NS(timespec)                                                        \
756b316febSTerry Wilmarth   (((timespec).tv_sec * (long int)1e9) + (timespec).tv_nsec)
767cc577a4SJonathan Peyton 
777cc577a4SJonathan Peyton static struct kmp_sys_timer __kmp_sys_timer_data;
787cc577a4SJonathan Peyton 
797cc577a4SJonathan Peyton #if KMP_HANDLE_SIGNALS
807cc577a4SJonathan Peyton typedef void (*sig_func_t)(int);
817cc577a4SJonathan Peyton STATIC_EFI2_WORKAROUND struct sigaction __kmp_sighldrs[NSIG];
827cc577a4SJonathan Peyton static sigset_t __kmp_sigset;
837cc577a4SJonathan Peyton #endif
847cc577a4SJonathan Peyton 
857cc577a4SJonathan Peyton static int __kmp_init_runtime = FALSE;
867cc577a4SJonathan Peyton 
877cc577a4SJonathan Peyton static int __kmp_fork_count = 0;
887cc577a4SJonathan Peyton 
897cc577a4SJonathan Peyton static pthread_condattr_t __kmp_suspend_cond_attr;
907cc577a4SJonathan Peyton static pthread_mutexattr_t __kmp_suspend_mutex_attr;
917cc577a4SJonathan Peyton 
927cc577a4SJonathan Peyton static kmp_cond_align_t __kmp_wait_cv;
937cc577a4SJonathan Peyton static kmp_mutex_align_t __kmp_wait_mx;
947cc577a4SJonathan Peyton 
9535d75aedSJonathan Peyton kmp_uint64 __kmp_ticks_per_msec = 1000000;
967cc577a4SJonathan Peyton 
977cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND
__kmp_print_cond(char * buffer,kmp_cond_align_t * cond)983041982dSJonathan Peyton static void __kmp_print_cond(char *buffer, kmp_cond_align_t *cond) {
997cc577a4SJonathan Peyton   KMP_SNPRINTF(buffer, 128, "(cond (lock (%ld, %d)), (descr (%p)))",
1007cc577a4SJonathan Peyton                cond->c_cond.__c_lock.__status, cond->c_cond.__c_lock.__spinlock,
1017cc577a4SJonathan Peyton                cond->c_cond.__c_waiting);
1027cc577a4SJonathan Peyton }
1037cc577a4SJonathan Peyton #endif
1047cc577a4SJonathan Peyton 
105f61f13d4SDavid Carlier #if ((KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED)
1067cc577a4SJonathan Peyton 
1073041982dSJonathan Peyton /* Affinity support */
1087cc577a4SJonathan Peyton 
__kmp_affinity_bind_thread(int which)1093041982dSJonathan Peyton void __kmp_affinity_bind_thread(int which) {
1107cc577a4SJonathan Peyton   KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
1117cc577a4SJonathan Peyton               "Illegal set affinity operation when not capable");
1127cc577a4SJonathan Peyton 
1137cc577a4SJonathan Peyton   kmp_affin_mask_t *mask;
1147cc577a4SJonathan Peyton   KMP_CPU_ALLOC_ON_STACK(mask);
1157cc577a4SJonathan Peyton   KMP_CPU_ZERO(mask);
1167cc577a4SJonathan Peyton   KMP_CPU_SET(which, mask);
1177cc577a4SJonathan Peyton   __kmp_set_system_affinity(mask, TRUE);
1187cc577a4SJonathan Peyton   KMP_CPU_FREE_FROM_STACK(mask);
1197cc577a4SJonathan Peyton }
1207cc577a4SJonathan Peyton 
1213041982dSJonathan Peyton /* Determine if we can access affinity functionality on this version of
1227cc577a4SJonathan Peyton  * Linux* OS by checking __NR_sched_{get,set}affinity system calls, and set
1233041982dSJonathan Peyton  * __kmp_affin_mask_size to the appropriate value (0 means not capable). */
__kmp_affinity_determine_capable(const char * env_var)1243041982dSJonathan Peyton void __kmp_affinity_determine_capable(const char *env_var) {
1257cc577a4SJonathan Peyton   // Check and see if the OS supports thread affinity.
1267cc577a4SJonathan Peyton 
127f61f13d4SDavid Carlier #if KMP_OS_LINUX
1287cc577a4SJonathan Peyton #define KMP_CPU_SET_SIZE_LIMIT (1024 * 1024)
12992baf414SPeyton, Jonathan L #define KMP_CPU_SET_TRY_SIZE CACHE_LINE
130f61f13d4SDavid Carlier #elif KMP_OS_FREEBSD
131f61f13d4SDavid Carlier #define KMP_CPU_SET_SIZE_LIMIT (sizeof(cpuset_t))
132f61f13d4SDavid Carlier #endif
1337cc577a4SJonathan Peyton 
134f61f13d4SDavid Carlier #if KMP_OS_LINUX
1356b316febSTerry Wilmarth   long gCode;
1367cc577a4SJonathan Peyton   unsigned char *buf;
1377cc577a4SJonathan Peyton   buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT);
13892baf414SPeyton, Jonathan L 
13992baf414SPeyton, Jonathan L   // If the syscall returns a suggestion for the size,
14092baf414SPeyton, Jonathan L   // then we don't have to search for an appropriate size.
14192baf414SPeyton, Jonathan L   gCode = syscall(__NR_sched_getaffinity, 0, KMP_CPU_SET_TRY_SIZE, buf);
1427cc577a4SJonathan Peyton   KA_TRACE(30, ("__kmp_affinity_determine_capable: "
1436b316febSTerry Wilmarth                 "initial getaffinity call returned %ld errno = %d\n",
1447cc577a4SJonathan Peyton                 gCode, errno));
1457cc577a4SJonathan Peyton 
14692baf414SPeyton, Jonathan L   if (gCode < 0 && errno != EINVAL) {
1477cc577a4SJonathan Peyton     // System call not supported
1483041982dSJonathan Peyton     if (__kmp_affinity_verbose ||
1493041982dSJonathan Peyton         (__kmp_affinity_warnings && (__kmp_affinity_type != affinity_none) &&
1503041982dSJonathan Peyton          (__kmp_affinity_type != affinity_default) &&
1513041982dSJonathan Peyton          (__kmp_affinity_type != affinity_disabled))) {
1527cc577a4SJonathan Peyton       int error = errno;
1537cc577a4SJonathan Peyton       kmp_msg_t err_code = KMP_ERR(error);
1543041982dSJonathan Peyton       __kmp_msg(kmp_ms_warning, KMP_MSG(GetAffSysCallNotSupported, env_var),
1553041982dSJonathan Peyton                 err_code, __kmp_msg_null);
1567cc577a4SJonathan Peyton       if (__kmp_generate_warnings == kmp_warnings_off) {
1577cc577a4SJonathan Peyton         __kmp_str_free(&err_code.str);
1587cc577a4SJonathan Peyton       }
1597cc577a4SJonathan Peyton     }
1607cc577a4SJonathan Peyton     KMP_AFFINITY_DISABLE();
1617cc577a4SJonathan Peyton     KMP_INTERNAL_FREE(buf);
1627cc577a4SJonathan Peyton     return;
16392baf414SPeyton, Jonathan L   } else if (gCode > 0) {
1643041982dSJonathan Peyton     // The optimal situation: the OS returns the size of the buffer it expects.
1657cc577a4SJonathan Peyton     KMP_AFFINITY_ENABLE(gCode);
1667cc577a4SJonathan Peyton     KA_TRACE(10, ("__kmp_affinity_determine_capable: "
1677cc577a4SJonathan Peyton                   "affinity supported (mask size %d)\n",
1687cc577a4SJonathan Peyton                   (int)__kmp_affin_mask_size));
1697cc577a4SJonathan Peyton     KMP_INTERNAL_FREE(buf);
1707cc577a4SJonathan Peyton     return;
1717cc577a4SJonathan Peyton   }
1727cc577a4SJonathan Peyton 
1737cc577a4SJonathan Peyton   // Call the getaffinity system call repeatedly with increasing set sizes
1747cc577a4SJonathan Peyton   // until we succeed, or reach an upper bound on the search.
1757cc577a4SJonathan Peyton   KA_TRACE(30, ("__kmp_affinity_determine_capable: "
1767cc577a4SJonathan Peyton                 "searching for proper set size\n"));
1777cc577a4SJonathan Peyton   int size;
1787cc577a4SJonathan Peyton   for (size = 1; size <= KMP_CPU_SET_SIZE_LIMIT; size *= 2) {
1797cc577a4SJonathan Peyton     gCode = syscall(__NR_sched_getaffinity, 0, size, buf);
1807cc577a4SJonathan Peyton     KA_TRACE(30, ("__kmp_affinity_determine_capable: "
1816b316febSTerry Wilmarth                   "getaffinity for mask size %ld returned %ld errno = %d\n",
1823041982dSJonathan Peyton                   size, gCode, errno));
1837cc577a4SJonathan Peyton 
1847cc577a4SJonathan Peyton     if (gCode < 0) {
1853041982dSJonathan Peyton       if (errno == ENOSYS) {
1867cc577a4SJonathan Peyton         // We shouldn't get here
1877cc577a4SJonathan Peyton         KA_TRACE(30, ("__kmp_affinity_determine_capable: "
1883041982dSJonathan Peyton                       "inconsistent OS call behavior: errno == ENOSYS for mask "
1893041982dSJonathan Peyton                       "size %d\n",
1907cc577a4SJonathan Peyton                       size));
1913041982dSJonathan Peyton         if (__kmp_affinity_verbose ||
1923041982dSJonathan Peyton             (__kmp_affinity_warnings &&
1933041982dSJonathan Peyton              (__kmp_affinity_type != affinity_none) &&
1943041982dSJonathan Peyton              (__kmp_affinity_type != affinity_default) &&
1953041982dSJonathan Peyton              (__kmp_affinity_type != affinity_disabled))) {
1967cc577a4SJonathan Peyton           int error = errno;
1977cc577a4SJonathan Peyton           kmp_msg_t err_code = KMP_ERR(error);
1983041982dSJonathan Peyton           __kmp_msg(kmp_ms_warning, KMP_MSG(GetAffSysCallNotSupported, env_var),
1993041982dSJonathan Peyton                     err_code, __kmp_msg_null);
2007cc577a4SJonathan Peyton           if (__kmp_generate_warnings == kmp_warnings_off) {
2017cc577a4SJonathan Peyton             __kmp_str_free(&err_code.str);
2027cc577a4SJonathan Peyton           }
2037cc577a4SJonathan Peyton         }
2047cc577a4SJonathan Peyton         KMP_AFFINITY_DISABLE();
2057cc577a4SJonathan Peyton         KMP_INTERNAL_FREE(buf);
2067cc577a4SJonathan Peyton         return;
2077cc577a4SJonathan Peyton       }
2087cc577a4SJonathan Peyton       continue;
2097cc577a4SJonathan Peyton     }
2107cc577a4SJonathan Peyton 
2117cc577a4SJonathan Peyton     KMP_AFFINITY_ENABLE(gCode);
2127cc577a4SJonathan Peyton     KA_TRACE(10, ("__kmp_affinity_determine_capable: "
2137cc577a4SJonathan Peyton                   "affinity supported (mask size %d)\n",
2147cc577a4SJonathan Peyton                   (int)__kmp_affin_mask_size));
2157cc577a4SJonathan Peyton     KMP_INTERNAL_FREE(buf);
2167cc577a4SJonathan Peyton     return;
2177cc577a4SJonathan Peyton   }
218f61f13d4SDavid Carlier #elif KMP_OS_FREEBSD
2196b316febSTerry Wilmarth   long gCode;
220f61f13d4SDavid Carlier   unsigned char *buf;
221f61f13d4SDavid Carlier   buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT);
222309b00a4SShilei Tian   gCode = pthread_getaffinity_np(pthread_self(), KMP_CPU_SET_SIZE_LIMIT,
223309b00a4SShilei Tian                                  reinterpret_cast<cpuset_t *>(buf));
224f61f13d4SDavid Carlier   KA_TRACE(30, ("__kmp_affinity_determine_capable: "
225f61f13d4SDavid Carlier                 "initial getaffinity call returned %d errno = %d\n",
226f61f13d4SDavid Carlier                 gCode, errno));
227f61f13d4SDavid Carlier   if (gCode == 0) {
228f61f13d4SDavid Carlier     KMP_AFFINITY_ENABLE(KMP_CPU_SET_SIZE_LIMIT);
229f61f13d4SDavid Carlier     KA_TRACE(10, ("__kmp_affinity_determine_capable: "
230ea99c099SDavid Carlier                   "affinity supported (mask size %d)\n",
231f61f13d4SDavid Carlier                   (int)__kmp_affin_mask_size));
232f61f13d4SDavid Carlier     KMP_INTERNAL_FREE(buf);
233f61f13d4SDavid Carlier     return;
234f61f13d4SDavid Carlier   }
235f61f13d4SDavid Carlier #endif
2367cc577a4SJonathan Peyton   KMP_INTERNAL_FREE(buf);
2377cc577a4SJonathan Peyton 
2387cc577a4SJonathan Peyton   // Affinity is not supported
2397cc577a4SJonathan Peyton   KMP_AFFINITY_DISABLE();
2407cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_affinity_determine_capable: "
2417cc577a4SJonathan Peyton                 "cannot determine mask size - affinity not supported\n"));
2423041982dSJonathan Peyton   if (__kmp_affinity_verbose ||
2433041982dSJonathan Peyton       (__kmp_affinity_warnings && (__kmp_affinity_type != affinity_none) &&
2443041982dSJonathan Peyton        (__kmp_affinity_type != affinity_default) &&
2453041982dSJonathan Peyton        (__kmp_affinity_type != affinity_disabled))) {
2467cc577a4SJonathan Peyton     KMP_WARNING(AffCantGetMaskSize, env_var);
2477cc577a4SJonathan Peyton   }
2487cc577a4SJonathan Peyton }
2497cc577a4SJonathan Peyton 
2507cc577a4SJonathan Peyton #endif // KMP_OS_LINUX && KMP_AFFINITY_SUPPORTED
2517cc577a4SJonathan Peyton 
2527cc577a4SJonathan Peyton #if KMP_USE_FUTEX
2537cc577a4SJonathan Peyton 
__kmp_futex_determine_capable()2543041982dSJonathan Peyton int __kmp_futex_determine_capable() {
2557cc577a4SJonathan Peyton   int loc = 0;
2566b316febSTerry Wilmarth   long rc = syscall(__NR_futex, &loc, FUTEX_WAKE, 1, NULL, NULL, 0);
2577cc577a4SJonathan Peyton   int retval = (rc == 0) || (errno != ENOSYS);
2587cc577a4SJonathan Peyton 
2593041982dSJonathan Peyton   KA_TRACE(10,
2603041982dSJonathan Peyton            ("__kmp_futex_determine_capable: rc = %d errno = %d\n", rc, errno));
2617cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_futex_determine_capable: futex syscall%s supported\n",
2627cc577a4SJonathan Peyton                 retval ? "" : " not"));
2637cc577a4SJonathan Peyton 
2647cc577a4SJonathan Peyton   return retval;
2657cc577a4SJonathan Peyton }
2667cc577a4SJonathan Peyton 
2677cc577a4SJonathan Peyton #endif // KMP_USE_FUTEX
2687cc577a4SJonathan Peyton 
2697cc577a4SJonathan Peyton #if (KMP_ARCH_X86 || KMP_ARCH_X86_64) && (!KMP_ASM_INTRINS)
2703041982dSJonathan Peyton /* Only 32-bit "add-exchange" instruction on IA-32 architecture causes us to
2713041982dSJonathan Peyton    use compare_and_store for these routines */
2727cc577a4SJonathan Peyton 
__kmp_test_then_or8(volatile kmp_int8 * p,kmp_int8 d)2733041982dSJonathan Peyton kmp_int8 __kmp_test_then_or8(volatile kmp_int8 *p, kmp_int8 d) {
2747cc577a4SJonathan Peyton   kmp_int8 old_value, new_value;
2757cc577a4SJonathan Peyton 
2767cc577a4SJonathan Peyton   old_value = TCR_1(*p);
2777cc577a4SJonathan Peyton   new_value = old_value | d;
2787cc577a4SJonathan Peyton 
2793041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
2807cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
2817cc577a4SJonathan Peyton     old_value = TCR_1(*p);
2827cc577a4SJonathan Peyton     new_value = old_value | d;
2837cc577a4SJonathan Peyton   }
2847cc577a4SJonathan Peyton   return old_value;
2857cc577a4SJonathan Peyton }
2867cc577a4SJonathan Peyton 
__kmp_test_then_and8(volatile kmp_int8 * p,kmp_int8 d)2873041982dSJonathan Peyton kmp_int8 __kmp_test_then_and8(volatile kmp_int8 *p, kmp_int8 d) {
2887cc577a4SJonathan Peyton   kmp_int8 old_value, new_value;
2897cc577a4SJonathan Peyton 
2907cc577a4SJonathan Peyton   old_value = TCR_1(*p);
2917cc577a4SJonathan Peyton   new_value = old_value & d;
2927cc577a4SJonathan Peyton 
2933041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
2947cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
2957cc577a4SJonathan Peyton     old_value = TCR_1(*p);
2967cc577a4SJonathan Peyton     new_value = old_value & d;
2977cc577a4SJonathan Peyton   }
2987cc577a4SJonathan Peyton   return old_value;
2997cc577a4SJonathan Peyton }
3007cc577a4SJonathan Peyton 
__kmp_test_then_or32(volatile kmp_uint32 * p,kmp_uint32 d)3015ba90c79SAndrey Churbanov kmp_uint32 __kmp_test_then_or32(volatile kmp_uint32 *p, kmp_uint32 d) {
3025ba90c79SAndrey Churbanov   kmp_uint32 old_value, new_value;
3037cc577a4SJonathan Peyton 
3047cc577a4SJonathan Peyton   old_value = TCR_4(*p);
3057cc577a4SJonathan Peyton   new_value = old_value | d;
3067cc577a4SJonathan Peyton 
3073041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL32(p, old_value, new_value)) {
3087cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
3097cc577a4SJonathan Peyton     old_value = TCR_4(*p);
3107cc577a4SJonathan Peyton     new_value = old_value | d;
3117cc577a4SJonathan Peyton   }
3127cc577a4SJonathan Peyton   return old_value;
3137cc577a4SJonathan Peyton }
3147cc577a4SJonathan Peyton 
__kmp_test_then_and32(volatile kmp_uint32 * p,kmp_uint32 d)3155ba90c79SAndrey Churbanov kmp_uint32 __kmp_test_then_and32(volatile kmp_uint32 *p, kmp_uint32 d) {
3165ba90c79SAndrey Churbanov   kmp_uint32 old_value, new_value;
3177cc577a4SJonathan Peyton 
3187cc577a4SJonathan Peyton   old_value = TCR_4(*p);
3197cc577a4SJonathan Peyton   new_value = old_value & d;
3207cc577a4SJonathan Peyton 
3213041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL32(p, old_value, new_value)) {
3227cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
3237cc577a4SJonathan Peyton     old_value = TCR_4(*p);
3247cc577a4SJonathan Peyton     new_value = old_value & d;
3257cc577a4SJonathan Peyton   }
3267cc577a4SJonathan Peyton   return old_value;
3277cc577a4SJonathan Peyton }
3287cc577a4SJonathan Peyton 
329928b8ea2SJonathan Peyton #if KMP_ARCH_X86
__kmp_test_then_add8(volatile kmp_int8 * p,kmp_int8 d)3303041982dSJonathan Peyton kmp_int8 __kmp_test_then_add8(volatile kmp_int8 *p, kmp_int8 d) {
3317cc577a4SJonathan Peyton   kmp_int8 old_value, new_value;
3327cc577a4SJonathan Peyton 
3337cc577a4SJonathan Peyton   old_value = TCR_1(*p);
3347cc577a4SJonathan Peyton   new_value = old_value + d;
3357cc577a4SJonathan Peyton 
3363041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
3377cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
3387cc577a4SJonathan Peyton     old_value = TCR_1(*p);
3397cc577a4SJonathan Peyton     new_value = old_value + d;
3407cc577a4SJonathan Peyton   }
3417cc577a4SJonathan Peyton   return old_value;
3427cc577a4SJonathan Peyton }
3437cc577a4SJonathan Peyton 
__kmp_test_then_add64(volatile kmp_int64 * p,kmp_int64 d)3443041982dSJonathan Peyton kmp_int64 __kmp_test_then_add64(volatile kmp_int64 *p, kmp_int64 d) {
3457cc577a4SJonathan Peyton   kmp_int64 old_value, new_value;
3467cc577a4SJonathan Peyton 
3477cc577a4SJonathan Peyton   old_value = TCR_8(*p);
3487cc577a4SJonathan Peyton   new_value = old_value + d;
3497cc577a4SJonathan Peyton 
3503041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
3517cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
3527cc577a4SJonathan Peyton     old_value = TCR_8(*p);
3537cc577a4SJonathan Peyton     new_value = old_value + d;
3547cc577a4SJonathan Peyton   }
3557cc577a4SJonathan Peyton   return old_value;
3567cc577a4SJonathan Peyton }
357928b8ea2SJonathan Peyton #endif /* KMP_ARCH_X86 */
3587cc577a4SJonathan Peyton 
__kmp_test_then_or64(volatile kmp_uint64 * p,kmp_uint64 d)3595ba90c79SAndrey Churbanov kmp_uint64 __kmp_test_then_or64(volatile kmp_uint64 *p, kmp_uint64 d) {
3605ba90c79SAndrey Churbanov   kmp_uint64 old_value, new_value;
3617cc577a4SJonathan Peyton 
3627cc577a4SJonathan Peyton   old_value = TCR_8(*p);
3637cc577a4SJonathan Peyton   new_value = old_value | d;
3643041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
3657cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
3667cc577a4SJonathan Peyton     old_value = TCR_8(*p);
3677cc577a4SJonathan Peyton     new_value = old_value | d;
3687cc577a4SJonathan Peyton   }
3697cc577a4SJonathan Peyton   return old_value;
3707cc577a4SJonathan Peyton }
3717cc577a4SJonathan Peyton 
__kmp_test_then_and64(volatile kmp_uint64 * p,kmp_uint64 d)3725ba90c79SAndrey Churbanov kmp_uint64 __kmp_test_then_and64(volatile kmp_uint64 *p, kmp_uint64 d) {
3735ba90c79SAndrey Churbanov   kmp_uint64 old_value, new_value;
3747cc577a4SJonathan Peyton 
3757cc577a4SJonathan Peyton   old_value = TCR_8(*p);
3767cc577a4SJonathan Peyton   new_value = old_value & d;
3773041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
3787cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
3797cc577a4SJonathan Peyton     old_value = TCR_8(*p);
3807cc577a4SJonathan Peyton     new_value = old_value & d;
3817cc577a4SJonathan Peyton   }
3827cc577a4SJonathan Peyton   return old_value;
3837cc577a4SJonathan Peyton }
3847cc577a4SJonathan Peyton 
3857cc577a4SJonathan Peyton #endif /* (KMP_ARCH_X86 || KMP_ARCH_X86_64) && (! KMP_ASM_INTRINS) */
3867cc577a4SJonathan Peyton 
__kmp_terminate_thread(int gtid)3873041982dSJonathan Peyton void __kmp_terminate_thread(int gtid) {
3887cc577a4SJonathan Peyton   int status;
3897cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[gtid];
3907cc577a4SJonathan Peyton 
3913041982dSJonathan Peyton   if (!th)
3923041982dSJonathan Peyton     return;
3937cc577a4SJonathan Peyton 
3947cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS
3957cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_terminate_thread: kill (%d)\n", gtid));
3967cc577a4SJonathan Peyton   status = pthread_cancel(th->th.th_info.ds.ds_thread);
3977cc577a4SJonathan Peyton   if (status != 0 && status != ESRCH) {
3986a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantTerminateWorkerThread), KMP_ERR(status),
3993041982dSJonathan Peyton                 __kmp_msg_null);
400bd3a7633SJonathan Peyton   }
4017cc577a4SJonathan Peyton #endif
402e47d32f1SJonathan Peyton   KMP_YIELD(TRUE);
4037cc577a4SJonathan Peyton } //
4047cc577a4SJonathan Peyton 
4053041982dSJonathan Peyton /* Set thread stack info according to values returned by pthread_getattr_np().
4063041982dSJonathan Peyton    If values are unreasonable, assume call failed and use incremental stack
4073041982dSJonathan Peyton    refinement method instead. Returns TRUE if the stack parameters could be
4083041982dSJonathan Peyton    determined exactly, FALSE if incremental refinement is necessary. */
__kmp_set_stack_info(int gtid,kmp_info_t * th)4093041982dSJonathan Peyton static kmp_int32 __kmp_set_stack_info(int gtid, kmp_info_t *th) {
4107cc577a4SJonathan Peyton   int stack_data;
411a56ac949SKamil Rytarowski #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
412a56ac949SKamil Rytarowski     KMP_OS_HURD
4137cc577a4SJonathan Peyton   pthread_attr_t attr;
4147cc577a4SJonathan Peyton   int status;
4157cc577a4SJonathan Peyton   size_t size = 0;
4167cc577a4SJonathan Peyton   void *addr = 0;
4177cc577a4SJonathan Peyton 
4183041982dSJonathan Peyton   /* Always do incremental stack refinement for ubermaster threads since the
4193041982dSJonathan Peyton      initial thread stack range can be reduced by sibling thread creation so
4203041982dSJonathan Peyton      pthread_attr_getstack may cause thread gtid aliasing */
4217cc577a4SJonathan Peyton   if (!KMP_UBER_GTID(gtid)) {
4227cc577a4SJonathan Peyton 
4237cc577a4SJonathan Peyton     /* Fetch the real thread attributes */
4247cc577a4SJonathan Peyton     status = pthread_attr_init(&attr);
4257cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_attr_init", status);
426a56ac949SKamil Rytarowski #if KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD
4277cc577a4SJonathan Peyton     status = pthread_attr_get_np(pthread_self(), &attr);
4287cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_attr_get_np", status);
4297cc577a4SJonathan Peyton #else
4307cc577a4SJonathan Peyton     status = pthread_getattr_np(pthread_self(), &attr);
4317cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_getattr_np", status);
4327cc577a4SJonathan Peyton #endif
4337cc577a4SJonathan Peyton     status = pthread_attr_getstack(&attr, &addr, &size);
4347cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_attr_getstack", status);
4353041982dSJonathan Peyton     KA_TRACE(60,
4363041982dSJonathan Peyton              ("__kmp_set_stack_info: T#%d pthread_attr_getstack returned size:"
4373041982dSJonathan Peyton               " %lu, low addr: %p\n",
4387cc577a4SJonathan Peyton               gtid, size, addr));
4397cc577a4SJonathan Peyton     status = pthread_attr_destroy(&attr);
4407cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_attr_destroy", status);
4417cc577a4SJonathan Peyton   }
4427cc577a4SJonathan Peyton 
4433041982dSJonathan Peyton   if (size != 0 && addr != 0) { // was stack parameter determination successful?
4447cc577a4SJonathan Peyton     /* Store the correct base and size */
4457cc577a4SJonathan Peyton     TCW_PTR(th->th.th_info.ds.ds_stackbase, (((char *)addr) + size));
4467cc577a4SJonathan Peyton     TCW_PTR(th->th.th_info.ds.ds_stacksize, size);
4477cc577a4SJonathan Peyton     TCW_4(th->th.th_info.ds.ds_stackgrow, FALSE);
4487cc577a4SJonathan Peyton     return TRUE;
4497cc577a4SJonathan Peyton   }
450309b00a4SShilei Tian #endif /* KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD  \
451309b00a4SShilei Tian           || KMP_OS_HURD */
4527cc577a4SJonathan Peyton   /* Use incremental refinement starting from initial conservative estimate */
4537cc577a4SJonathan Peyton   TCW_PTR(th->th.th_info.ds.ds_stacksize, 0);
4547cc577a4SJonathan Peyton   TCW_PTR(th->th.th_info.ds.ds_stackbase, &stack_data);
4557cc577a4SJonathan Peyton   TCW_4(th->th.th_info.ds.ds_stackgrow, TRUE);
4567cc577a4SJonathan Peyton   return FALSE;
4577cc577a4SJonathan Peyton }
4587cc577a4SJonathan Peyton 
__kmp_launch_worker(void * thr)4593041982dSJonathan Peyton static void *__kmp_launch_worker(void *thr) {
4607cc577a4SJonathan Peyton   int status, old_type, old_state;
4617cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS
4627cc577a4SJonathan Peyton   sigset_t new_set, old_set;
4637cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */
4647cc577a4SJonathan Peyton   void *exit_val;
465a56ac949SKamil Rytarowski #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
4667e1ea993SKamil Rytarowski     KMP_OS_OPENBSD || KMP_OS_HURD
4677cc577a4SJonathan Peyton   void *volatile padding = 0;
4687cc577a4SJonathan Peyton #endif
4697cc577a4SJonathan Peyton   int gtid;
4707cc577a4SJonathan Peyton 
4717cc577a4SJonathan Peyton   gtid = ((kmp_info_t *)thr)->th.th_info.ds.ds_gtid;
4727cc577a4SJonathan Peyton   __kmp_gtid_set_specific(gtid);
4737cc577a4SJonathan Peyton #ifdef KMP_TDATA_GTID
4747cc577a4SJonathan Peyton   __kmp_gtid = gtid;
4757cc577a4SJonathan Peyton #endif
4767cc577a4SJonathan Peyton #if KMP_STATS_ENABLED
47740039ac9SJonathan Peyton   // set thread local index to point to thread-specific stats
4787cc577a4SJonathan Peyton   __kmp_stats_thread_ptr = ((kmp_info_t *)thr)->th.th_stats;
479f0682ac4SJonathan Peyton   __kmp_stats_thread_ptr->startLife();
4807cc577a4SJonathan Peyton   KMP_SET_THREAD_STATE(IDLE);
4817cc577a4SJonathan Peyton   KMP_INIT_PARTITIONED_TIMERS(OMP_idle);
4827cc577a4SJonathan Peyton #endif
4837cc577a4SJonathan Peyton 
4847cc577a4SJonathan Peyton #if USE_ITT_BUILD
4857cc577a4SJonathan Peyton   __kmp_itt_thread_name(gtid);
4867cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
4877cc577a4SJonathan Peyton 
4887cc577a4SJonathan Peyton #if KMP_AFFINITY_SUPPORTED
4897cc577a4SJonathan Peyton   __kmp_affinity_set_init_mask(gtid, FALSE);
4907cc577a4SJonathan Peyton #endif
4917cc577a4SJonathan Peyton 
4927cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS
4937cc577a4SJonathan Peyton   status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_type);
4947cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_setcanceltype", status);
4953041982dSJonathan Peyton   // josh todo: isn't PTHREAD_CANCEL_ENABLE default for newly-created threads?
4967cc577a4SJonathan Peyton   status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state);
4977cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_setcancelstate", status);
4987cc577a4SJonathan Peyton #endif
4997cc577a4SJonathan Peyton 
5007cc577a4SJonathan Peyton #if KMP_ARCH_X86 || KMP_ARCH_X86_64
5013041982dSJonathan Peyton   // Set FP control regs to be a copy of the parallel initialization thread's.
5027cc577a4SJonathan Peyton   __kmp_clear_x87_fpu_status_word();
5037cc577a4SJonathan Peyton   __kmp_load_x87_fpu_control_word(&__kmp_init_x87_fpu_control_word);
5047cc577a4SJonathan Peyton   __kmp_load_mxcsr(&__kmp_init_mxcsr);
5057cc577a4SJonathan Peyton #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
5067cc577a4SJonathan Peyton 
5077cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS
5087cc577a4SJonathan Peyton   status = sigfillset(&new_set);
5097cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("sigfillset", status);
5107cc577a4SJonathan Peyton   status = pthread_sigmask(SIG_BLOCK, &new_set, &old_set);
5117cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_sigmask", status);
5127cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */
5137cc577a4SJonathan Peyton 
5147e1ea993SKamil Rytarowski #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
5157e1ea993SKamil Rytarowski     KMP_OS_OPENBSD
5167cc577a4SJonathan Peyton   if (__kmp_stkoffset > 0 && gtid > 0) {
5177cc577a4SJonathan Peyton     padding = KMP_ALLOCA(gtid * __kmp_stkoffset);
518cff21556SJoachim Protze     (void)padding;
5197cc577a4SJonathan Peyton   }
5207cc577a4SJonathan Peyton #endif
5217cc577a4SJonathan Peyton 
5227cc577a4SJonathan Peyton   KMP_MB();
5237cc577a4SJonathan Peyton   __kmp_set_stack_info(gtid, (kmp_info_t *)thr);
5247cc577a4SJonathan Peyton 
5257cc577a4SJonathan Peyton   __kmp_check_stack_overlap((kmp_info_t *)thr);
5267cc577a4SJonathan Peyton 
5277cc577a4SJonathan Peyton   exit_val = __kmp_launch_thread((kmp_info_t *)thr);
5287cc577a4SJonathan Peyton 
5297cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS
5307cc577a4SJonathan Peyton   status = pthread_sigmask(SIG_SETMASK, &old_set, NULL);
5317cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_sigmask", status);
5327cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */
5337cc577a4SJonathan Peyton 
5347cc577a4SJonathan Peyton   return exit_val;
5357cc577a4SJonathan Peyton }
5367cc577a4SJonathan Peyton 
5377cc577a4SJonathan Peyton #if KMP_USE_MONITOR
5387cc577a4SJonathan Peyton /* The monitor thread controls all of the threads in the complex */
5397cc577a4SJonathan Peyton 
__kmp_launch_monitor(void * thr)5403041982dSJonathan Peyton static void *__kmp_launch_monitor(void *thr) {
5417cc577a4SJonathan Peyton   int status, old_type, old_state;
5427cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS
5437cc577a4SJonathan Peyton   sigset_t new_set;
5447cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */
5457cc577a4SJonathan Peyton   struct timespec interval;
5467cc577a4SJonathan Peyton 
5477cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
5487cc577a4SJonathan Peyton 
5497cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_launch_monitor: #1 launched\n"));
5507cc577a4SJonathan Peyton 
5517cc577a4SJonathan Peyton   /* register us as the monitor thread */
5527cc577a4SJonathan Peyton   __kmp_gtid_set_specific(KMP_GTID_MONITOR);
5537cc577a4SJonathan Peyton #ifdef KMP_TDATA_GTID
5547cc577a4SJonathan Peyton   __kmp_gtid = KMP_GTID_MONITOR;
5557cc577a4SJonathan Peyton #endif
5567cc577a4SJonathan Peyton 
5577cc577a4SJonathan Peyton   KMP_MB();
5587cc577a4SJonathan Peyton 
5597cc577a4SJonathan Peyton #if USE_ITT_BUILD
5603041982dSJonathan Peyton   // Instruct Intel(R) Threading Tools to ignore monitor thread.
5613041982dSJonathan Peyton   __kmp_itt_thread_ignore();
5627cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
5637cc577a4SJonathan Peyton 
5643041982dSJonathan Peyton   __kmp_set_stack_info(((kmp_info_t *)thr)->th.th_info.ds.ds_gtid,
5653041982dSJonathan Peyton                        (kmp_info_t *)thr);
5667cc577a4SJonathan Peyton 
5677cc577a4SJonathan Peyton   __kmp_check_stack_overlap((kmp_info_t *)thr);
5687cc577a4SJonathan Peyton 
5697cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS
5707cc577a4SJonathan Peyton   status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_type);
5717cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_setcanceltype", status);
5723041982dSJonathan Peyton   // josh todo: isn't PTHREAD_CANCEL_ENABLE default for newly-created threads?
5737cc577a4SJonathan Peyton   status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state);
5747cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_setcancelstate", status);
5757cc577a4SJonathan Peyton #endif
5767cc577a4SJonathan Peyton 
5777cc577a4SJonathan Peyton #if KMP_REAL_TIME_FIX
5783041982dSJonathan Peyton   // This is a potential fix which allows application with real-time scheduling
5793041982dSJonathan Peyton   // policy work. However, decision about the fix is not made yet, so it is
5803041982dSJonathan Peyton   // disabled by default.
5817cc577a4SJonathan Peyton   { // Are program started with real-time scheduling policy?
5827cc577a4SJonathan Peyton     int sched = sched_getscheduler(0);
5837cc577a4SJonathan Peyton     if (sched == SCHED_FIFO || sched == SCHED_RR) {
5843041982dSJonathan Peyton       // Yes, we are a part of real-time application. Try to increase the
5853041982dSJonathan Peyton       // priority of the monitor.
5867cc577a4SJonathan Peyton       struct sched_param param;
5877cc577a4SJonathan Peyton       int max_priority = sched_get_priority_max(sched);
5887cc577a4SJonathan Peyton       int rc;
5897cc577a4SJonathan Peyton       KMP_WARNING(RealTimeSchedNotSupported);
5907cc577a4SJonathan Peyton       sched_getparam(0, &param);
5917cc577a4SJonathan Peyton       if (param.sched_priority < max_priority) {
5927cc577a4SJonathan Peyton         param.sched_priority += 1;
5937cc577a4SJonathan Peyton         rc = sched_setscheduler(0, sched, &param);
5947cc577a4SJonathan Peyton         if (rc != 0) {
5957cc577a4SJonathan Peyton           int error = errno;
5967cc577a4SJonathan Peyton           kmp_msg_t err_code = KMP_ERR(error);
5973041982dSJonathan Peyton           __kmp_msg(kmp_ms_warning, KMP_MSG(CantChangeMonitorPriority),
5983041982dSJonathan Peyton                     err_code, KMP_MSG(MonitorWillStarve), __kmp_msg_null);
5997cc577a4SJonathan Peyton           if (__kmp_generate_warnings == kmp_warnings_off) {
6007cc577a4SJonathan Peyton             __kmp_str_free(&err_code.str);
6017cc577a4SJonathan Peyton           }
602bd3a7633SJonathan Peyton         }
6037cc577a4SJonathan Peyton       } else {
6043041982dSJonathan Peyton         // We cannot abort here, because number of CPUs may be enough for all
6053041982dSJonathan Peyton         // the threads, including the monitor thread, so application could
6063041982dSJonathan Peyton         // potentially work...
6073041982dSJonathan Peyton         __kmp_msg(kmp_ms_warning, KMP_MSG(RunningAtMaxPriority),
6083041982dSJonathan Peyton                   KMP_MSG(MonitorWillStarve), KMP_HNT(RunningAtMaxPriority),
6093041982dSJonathan Peyton                   __kmp_msg_null);
610bd3a7633SJonathan Peyton       }
611bd3a7633SJonathan Peyton     }
6123041982dSJonathan Peyton     // AC: free thread that waits for monitor started
6133041982dSJonathan Peyton     TCW_4(__kmp_global.g.g_time.dt.t_value, 0);
6147cc577a4SJonathan Peyton   }
6157cc577a4SJonathan Peyton #endif // KMP_REAL_TIME_FIX
6167cc577a4SJonathan Peyton 
6177cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
6187cc577a4SJonathan Peyton 
6197cc577a4SJonathan Peyton   if (__kmp_monitor_wakeups == 1) {
6207cc577a4SJonathan Peyton     interval.tv_sec = 1;
6217cc577a4SJonathan Peyton     interval.tv_nsec = 0;
6227cc577a4SJonathan Peyton   } else {
6237cc577a4SJonathan Peyton     interval.tv_sec = 0;
6247cc577a4SJonathan Peyton     interval.tv_nsec = (KMP_NSEC_PER_SEC / __kmp_monitor_wakeups);
6257cc577a4SJonathan Peyton   }
6267cc577a4SJonathan Peyton 
6277cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_launch_monitor: #2 monitor\n"));
6287cc577a4SJonathan Peyton 
6297cc577a4SJonathan Peyton   while (!TCR_4(__kmp_global.g.g_done)) {
6307cc577a4SJonathan Peyton     struct timespec now;
6317cc577a4SJonathan Peyton     struct timeval tval;
6327cc577a4SJonathan Peyton 
6337cc577a4SJonathan Peyton     /*  This thread monitors the state of the system */
6347cc577a4SJonathan Peyton 
6357cc577a4SJonathan Peyton     KA_TRACE(15, ("__kmp_launch_monitor: update\n"));
6367cc577a4SJonathan Peyton 
6377cc577a4SJonathan Peyton     status = gettimeofday(&tval, NULL);
6387cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
6397cc577a4SJonathan Peyton     TIMEVAL_TO_TIMESPEC(&tval, &now);
6407cc577a4SJonathan Peyton 
6417cc577a4SJonathan Peyton     now.tv_sec += interval.tv_sec;
6427cc577a4SJonathan Peyton     now.tv_nsec += interval.tv_nsec;
6437cc577a4SJonathan Peyton 
6447cc577a4SJonathan Peyton     if (now.tv_nsec >= KMP_NSEC_PER_SEC) {
6457cc577a4SJonathan Peyton       now.tv_sec += 1;
6467cc577a4SJonathan Peyton       now.tv_nsec -= KMP_NSEC_PER_SEC;
6477cc577a4SJonathan Peyton     }
6487cc577a4SJonathan Peyton 
6497cc577a4SJonathan Peyton     status = pthread_mutex_lock(&__kmp_wait_mx.m_mutex);
6507cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
6517cc577a4SJonathan Peyton     // AC: the monitor should not fall asleep if g_done has been set
6527cc577a4SJonathan Peyton     if (!TCR_4(__kmp_global.g.g_done)) { // check once more under mutex
6533041982dSJonathan Peyton       status = pthread_cond_timedwait(&__kmp_wait_cv.c_cond,
6543041982dSJonathan Peyton                                       &__kmp_wait_mx.m_mutex, &now);
6557cc577a4SJonathan Peyton       if (status != 0) {
6567cc577a4SJonathan Peyton         if (status != ETIMEDOUT && status != EINTR) {
6577cc577a4SJonathan Peyton           KMP_SYSFAIL("pthread_cond_timedwait", status);
658bd3a7633SJonathan Peyton         }
659bd3a7633SJonathan Peyton       }
660bd3a7633SJonathan Peyton     }
6617cc577a4SJonathan Peyton     status = pthread_mutex_unlock(&__kmp_wait_mx.m_mutex);
6627cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
6637cc577a4SJonathan Peyton 
6647cc577a4SJonathan Peyton     TCW_4(__kmp_global.g.g_time.dt.t_value,
6657cc577a4SJonathan Peyton           TCR_4(__kmp_global.g.g_time.dt.t_value) + 1);
6667cc577a4SJonathan Peyton 
6677cc577a4SJonathan Peyton     KMP_MB(); /* Flush all pending memory write invalidates.  */
6687cc577a4SJonathan Peyton   }
6697cc577a4SJonathan Peyton 
6707cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_launch_monitor: #3 cleanup\n"));
6717cc577a4SJonathan Peyton 
6727cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS
6737cc577a4SJonathan Peyton   status = sigfillset(&new_set);
6747cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("sigfillset", status);
6757cc577a4SJonathan Peyton   status = pthread_sigmask(SIG_UNBLOCK, &new_set, NULL);
6767cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_sigmask", status);
6777cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */
6787cc577a4SJonathan Peyton 
6797cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_launch_monitor: #4 finished\n"));
6807cc577a4SJonathan Peyton 
6817cc577a4SJonathan Peyton   if (__kmp_global.g.g_abort != 0) {
6827cc577a4SJonathan Peyton     /* now we need to terminate the worker threads  */
6837cc577a4SJonathan Peyton     /* the value of t_abort is the signal we caught */
6847cc577a4SJonathan Peyton 
6857cc577a4SJonathan Peyton     int gtid;
6867cc577a4SJonathan Peyton 
6873041982dSJonathan Peyton     KA_TRACE(10, ("__kmp_launch_monitor: #5 terminate sig=%d\n",
6883041982dSJonathan Peyton                   __kmp_global.g.g_abort));
6897cc577a4SJonathan Peyton 
6907cc577a4SJonathan Peyton     /* terminate the OpenMP worker threads */
6917cc577a4SJonathan Peyton     /* TODO this is not valid for sibling threads!!
6927cc577a4SJonathan Peyton      * the uber master might not be 0 anymore.. */
6937cc577a4SJonathan Peyton     for (gtid = 1; gtid < __kmp_threads_capacity; ++gtid)
6947cc577a4SJonathan Peyton       __kmp_terminate_thread(gtid);
6957cc577a4SJonathan Peyton 
6967cc577a4SJonathan Peyton     __kmp_cleanup();
6977cc577a4SJonathan Peyton 
6983041982dSJonathan Peyton     KA_TRACE(10, ("__kmp_launch_monitor: #6 raise sig=%d\n",
6993041982dSJonathan Peyton                   __kmp_global.g.g_abort));
7007cc577a4SJonathan Peyton 
7017cc577a4SJonathan Peyton     if (__kmp_global.g.g_abort > 0)
7027cc577a4SJonathan Peyton       raise(__kmp_global.g.g_abort);
7037cc577a4SJonathan Peyton   }
7047cc577a4SJonathan Peyton 
7057cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_launch_monitor: #7 exit\n"));
7067cc577a4SJonathan Peyton 
7077cc577a4SJonathan Peyton   return thr;
7087cc577a4SJonathan Peyton }
7097cc577a4SJonathan Peyton #endif // KMP_USE_MONITOR
7107cc577a4SJonathan Peyton 
__kmp_create_worker(int gtid,kmp_info_t * th,size_t stack_size)7113041982dSJonathan Peyton void __kmp_create_worker(int gtid, kmp_info_t *th, size_t stack_size) {
7127cc577a4SJonathan Peyton   pthread_t handle;
7137cc577a4SJonathan Peyton   pthread_attr_t thread_attr;
7147cc577a4SJonathan Peyton   int status;
7157cc577a4SJonathan Peyton 
7167cc577a4SJonathan Peyton   th->th.th_info.ds.ds_gtid = gtid;
7177cc577a4SJonathan Peyton 
7187cc577a4SJonathan Peyton #if KMP_STATS_ENABLED
7197cc577a4SJonathan Peyton   // sets up worker thread stats
7207cc577a4SJonathan Peyton   __kmp_acquire_tas_lock(&__kmp_stats_lock, gtid);
7217cc577a4SJonathan Peyton 
7223041982dSJonathan Peyton   // th->th.th_stats is used to transfer thread-specific stats-pointer to
7233041982dSJonathan Peyton   // __kmp_launch_worker. So when thread is created (goes into
72440039ac9SJonathan Peyton   // __kmp_launch_worker) it will set its thread local pointer to
7253041982dSJonathan Peyton   // th->th.th_stats
7267cc577a4SJonathan Peyton   if (!KMP_UBER_GTID(gtid)) {
7277cc577a4SJonathan Peyton     th->th.th_stats = __kmp_stats_list->push_back(gtid);
7287cc577a4SJonathan Peyton   } else {
7293041982dSJonathan Peyton     // For root threads, __kmp_stats_thread_ptr is set in __kmp_register_root(),
7303041982dSJonathan Peyton     // so set the th->th.th_stats field to it.
7317cc577a4SJonathan Peyton     th->th.th_stats = __kmp_stats_thread_ptr;
7327cc577a4SJonathan Peyton   }
7337cc577a4SJonathan Peyton   __kmp_release_tas_lock(&__kmp_stats_lock, gtid);
7347cc577a4SJonathan Peyton 
7357cc577a4SJonathan Peyton #endif // KMP_STATS_ENABLED
7367cc577a4SJonathan Peyton 
7377cc577a4SJonathan Peyton   if (KMP_UBER_GTID(gtid)) {
7387cc577a4SJonathan Peyton     KA_TRACE(10, ("__kmp_create_worker: uber thread (%d)\n", gtid));
7397cc577a4SJonathan Peyton     th->th.th_info.ds.ds_thread = pthread_self();
7407cc577a4SJonathan Peyton     __kmp_set_stack_info(gtid, th);
7417cc577a4SJonathan Peyton     __kmp_check_stack_overlap(th);
7427cc577a4SJonathan Peyton     return;
743bd3a7633SJonathan Peyton   }
7447cc577a4SJonathan Peyton 
7457cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_worker: try to create thread (%d)\n", gtid));
7467cc577a4SJonathan Peyton 
7477cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
7487cc577a4SJonathan Peyton 
7497cc577a4SJonathan Peyton #ifdef KMP_THREAD_ATTR
7507cc577a4SJonathan Peyton   status = pthread_attr_init(&thread_attr);
7517cc577a4SJonathan Peyton   if (status != 0) {
7526a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantInitThreadAttrs), KMP_ERR(status), __kmp_msg_null);
753bd3a7633SJonathan Peyton   }
7547cc577a4SJonathan Peyton   status = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
7557cc577a4SJonathan Peyton   if (status != 0) {
7566a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantSetWorkerState), KMP_ERR(status), __kmp_msg_null);
757bd3a7633SJonathan Peyton   }
7587cc577a4SJonathan Peyton 
7597cc577a4SJonathan Peyton   /* Set stack size for this thread now.
7603041982dSJonathan Peyton      The multiple of 2 is there because on some machines, requesting an unusual
7613041982dSJonathan Peyton      stacksize causes the thread to have an offset before the dummy alloca()
7623041982dSJonathan Peyton      takes place to create the offset.  Since we want the user to have a
7633041982dSJonathan Peyton      sufficient stacksize AND support a stack offset, we alloca() twice the
7643041982dSJonathan Peyton      offset so that the upcoming alloca() does not eliminate any premade offset,
7653041982dSJonathan Peyton      and also gives the user the stack space they requested for all threads */
7667cc577a4SJonathan Peyton   stack_size += gtid * __kmp_stkoffset * 2;
7677cc577a4SJonathan Peyton 
7683d21a3afSYi Kong #if defined(__ANDROID__) && __ANDROID_API__ < 19
7693d21a3afSYi Kong   // Round the stack size to a multiple of the page size. Older versions of
7703d21a3afSYi Kong   // Android (until KitKat) would fail pthread_attr_setstacksize with EINVAL
7713d21a3afSYi Kong   // if the stack size was not a multiple of the page size.
7723d21a3afSYi Kong   stack_size = (stack_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
7733d21a3afSYi Kong #endif
7743d21a3afSYi Kong 
7757cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_worker: T#%d, default stacksize = %lu bytes, "
7767cc577a4SJonathan Peyton                 "__kmp_stksize = %lu bytes, final stacksize = %lu bytes\n",
7777cc577a4SJonathan Peyton                 gtid, KMP_DEFAULT_STKSIZE, __kmp_stksize, stack_size));
7787cc577a4SJonathan Peyton 
7797cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE
7807cc577a4SJonathan Peyton   status = pthread_attr_setstacksize(&thread_attr, stack_size);
7817cc577a4SJonathan Peyton #ifdef KMP_BACKUP_STKSIZE
7827cc577a4SJonathan Peyton   if (status != 0) {
7837cc577a4SJonathan Peyton     if (!__kmp_env_stksize) {
7847cc577a4SJonathan Peyton       stack_size = KMP_BACKUP_STKSIZE + gtid * __kmp_stkoffset;
7857cc577a4SJonathan Peyton       __kmp_stksize = KMP_BACKUP_STKSIZE;
7867cc577a4SJonathan Peyton       KA_TRACE(10, ("__kmp_create_worker: T#%d, default stacksize = %lu bytes, "
7877cc577a4SJonathan Peyton                     "__kmp_stksize = %lu bytes, (backup) final stacksize = %lu "
7887cc577a4SJonathan Peyton                     "bytes\n",
7893041982dSJonathan Peyton                     gtid, KMP_DEFAULT_STKSIZE, __kmp_stksize, stack_size));
7907cc577a4SJonathan Peyton       status = pthread_attr_setstacksize(&thread_attr, stack_size);
791bd3a7633SJonathan Peyton     }
792bd3a7633SJonathan Peyton   }
7937cc577a4SJonathan Peyton #endif /* KMP_BACKUP_STKSIZE */
7947cc577a4SJonathan Peyton   if (status != 0) {
7956a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantSetWorkerStackSize, stack_size), KMP_ERR(status),
7966a393f75SJonathan Peyton                 KMP_HNT(ChangeWorkerStackSize), __kmp_msg_null);
797bd3a7633SJonathan Peyton   }
7987cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
7997cc577a4SJonathan Peyton 
8007cc577a4SJonathan Peyton #endif /* KMP_THREAD_ATTR */
8017cc577a4SJonathan Peyton 
8023041982dSJonathan Peyton   status =
8033041982dSJonathan Peyton       pthread_create(&handle, &thread_attr, __kmp_launch_worker, (void *)th);
8047cc577a4SJonathan Peyton   if (status != 0 || !handle) { // ??? Why do we check handle??
8057cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE
8067cc577a4SJonathan Peyton     if (status == EINVAL) {
8076a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(CantSetWorkerStackSize, stack_size), KMP_ERR(status),
8086a393f75SJonathan Peyton                   KMP_HNT(IncreaseWorkerStackSize), __kmp_msg_null);
809bd3a7633SJonathan Peyton     }
8107cc577a4SJonathan Peyton     if (status == ENOMEM) {
8116a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(CantSetWorkerStackSize, stack_size), KMP_ERR(status),
8126a393f75SJonathan Peyton                   KMP_HNT(DecreaseWorkerStackSize), __kmp_msg_null);
813bd3a7633SJonathan Peyton     }
8147cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
8157cc577a4SJonathan Peyton     if (status == EAGAIN) {
8166a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(NoResourcesForWorkerThread), KMP_ERR(status),
8176a393f75SJonathan Peyton                   KMP_HNT(Decrease_NUM_THREADS), __kmp_msg_null);
818bd3a7633SJonathan Peyton     }
8197cc577a4SJonathan Peyton     KMP_SYSFAIL("pthread_create", status);
820bd3a7633SJonathan Peyton   }
8217cc577a4SJonathan Peyton 
8227cc577a4SJonathan Peyton   th->th.th_info.ds.ds_thread = handle;
8237cc577a4SJonathan Peyton 
8247cc577a4SJonathan Peyton #ifdef KMP_THREAD_ATTR
8257cc577a4SJonathan Peyton   status = pthread_attr_destroy(&thread_attr);
8267cc577a4SJonathan Peyton   if (status) {
8277cc577a4SJonathan Peyton     kmp_msg_t err_code = KMP_ERR(status);
8283041982dSJonathan Peyton     __kmp_msg(kmp_ms_warning, KMP_MSG(CantDestroyThreadAttrs), err_code,
8293041982dSJonathan Peyton               __kmp_msg_null);
8307cc577a4SJonathan Peyton     if (__kmp_generate_warnings == kmp_warnings_off) {
8317cc577a4SJonathan Peyton       __kmp_str_free(&err_code.str);
8327cc577a4SJonathan Peyton     }
833bd3a7633SJonathan Peyton   }
8347cc577a4SJonathan Peyton #endif /* KMP_THREAD_ATTR */
8357cc577a4SJonathan Peyton 
8367cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
8377cc577a4SJonathan Peyton 
8387cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_worker: done creating thread (%d)\n", gtid));
8397cc577a4SJonathan Peyton 
8407cc577a4SJonathan Peyton } // __kmp_create_worker
8417cc577a4SJonathan Peyton 
8427cc577a4SJonathan Peyton #if KMP_USE_MONITOR
__kmp_create_monitor(kmp_info_t * th)8433041982dSJonathan Peyton void __kmp_create_monitor(kmp_info_t *th) {
8447cc577a4SJonathan Peyton   pthread_t handle;
8457cc577a4SJonathan Peyton   pthread_attr_t thread_attr;
8467cc577a4SJonathan Peyton   size_t size;
8477cc577a4SJonathan Peyton   int status;
8487cc577a4SJonathan Peyton   int auto_adj_size = FALSE;
8497cc577a4SJonathan Peyton 
8507cc577a4SJonathan Peyton   if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME) {
8517cc577a4SJonathan Peyton     // We don't need monitor thread in case of MAX_BLOCKTIME
8523041982dSJonathan Peyton     KA_TRACE(10, ("__kmp_create_monitor: skipping monitor thread because of "
8533041982dSJonathan Peyton                   "MAX blocktime\n"));
8547cc577a4SJonathan Peyton     th->th.th_info.ds.ds_tid = 0; // this makes reap_monitor no-op
8557cc577a4SJonathan Peyton     th->th.th_info.ds.ds_gtid = 0;
8567cc577a4SJonathan Peyton     return;
8577cc577a4SJonathan Peyton   }
8587cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_monitor: try to create monitor\n"));
8597cc577a4SJonathan Peyton 
8607cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
8617cc577a4SJonathan Peyton 
8627cc577a4SJonathan Peyton   th->th.th_info.ds.ds_tid = KMP_GTID_MONITOR;
8637cc577a4SJonathan Peyton   th->th.th_info.ds.ds_gtid = KMP_GTID_MONITOR;
8647cc577a4SJonathan Peyton #if KMP_REAL_TIME_FIX
8653041982dSJonathan Peyton   TCW_4(__kmp_global.g.g_time.dt.t_value,
8663041982dSJonathan Peyton         -1); // Will use it for synchronization a bit later.
8677cc577a4SJonathan Peyton #else
8687cc577a4SJonathan Peyton   TCW_4(__kmp_global.g.g_time.dt.t_value, 0);
8697cc577a4SJonathan Peyton #endif // KMP_REAL_TIME_FIX
8707cc577a4SJonathan Peyton 
8717cc577a4SJonathan Peyton #ifdef KMP_THREAD_ATTR
8727cc577a4SJonathan Peyton   if (__kmp_monitor_stksize == 0) {
8737cc577a4SJonathan Peyton     __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE;
8747cc577a4SJonathan Peyton     auto_adj_size = TRUE;
8757cc577a4SJonathan Peyton   }
8767cc577a4SJonathan Peyton   status = pthread_attr_init(&thread_attr);
8777cc577a4SJonathan Peyton   if (status != 0) {
8786a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantInitThreadAttrs), KMP_ERR(status), __kmp_msg_null);
879bd3a7633SJonathan Peyton   }
8807cc577a4SJonathan Peyton   status = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
8817cc577a4SJonathan Peyton   if (status != 0) {
8826a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantSetMonitorState), KMP_ERR(status), __kmp_msg_null);
883bd3a7633SJonathan Peyton   }
8847cc577a4SJonathan Peyton 
8857cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE
8867cc577a4SJonathan Peyton   status = pthread_attr_getstacksize(&thread_attr, &size);
8877cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_attr_getstacksize", status);
8887cc577a4SJonathan Peyton #else
8897cc577a4SJonathan Peyton   size = __kmp_sys_min_stksize;
8907cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
8917cc577a4SJonathan Peyton #endif /* KMP_THREAD_ATTR */
8927cc577a4SJonathan Peyton 
8937cc577a4SJonathan Peyton   if (__kmp_monitor_stksize == 0) {
8947cc577a4SJonathan Peyton     __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE;
8957cc577a4SJonathan Peyton   }
8967cc577a4SJonathan Peyton   if (__kmp_monitor_stksize < __kmp_sys_min_stksize) {
8977cc577a4SJonathan Peyton     __kmp_monitor_stksize = __kmp_sys_min_stksize;
8987cc577a4SJonathan Peyton   }
8997cc577a4SJonathan Peyton 
9007cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_monitor: default stacksize = %lu bytes,"
9017cc577a4SJonathan Peyton                 "requested stacksize = %lu bytes\n",
9027cc577a4SJonathan Peyton                 size, __kmp_monitor_stksize));
9037cc577a4SJonathan Peyton 
9047cc577a4SJonathan Peyton retry:
9057cc577a4SJonathan Peyton 
9067cc577a4SJonathan Peyton /* Set stack size for this thread now. */
9077cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE
9087cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_monitor: setting stacksize = %lu bytes,",
9097cc577a4SJonathan Peyton                 __kmp_monitor_stksize));
9107cc577a4SJonathan Peyton   status = pthread_attr_setstacksize(&thread_attr, __kmp_monitor_stksize);
9117cc577a4SJonathan Peyton   if (status != 0) {
9127cc577a4SJonathan Peyton     if (auto_adj_size) {
9137cc577a4SJonathan Peyton       __kmp_monitor_stksize *= 2;
9147cc577a4SJonathan Peyton       goto retry;
9157cc577a4SJonathan Peyton     }
9167cc577a4SJonathan Peyton     kmp_msg_t err_code = KMP_ERR(status);
9173041982dSJonathan Peyton     __kmp_msg(kmp_ms_warning, // should this be fatal?  BB
9187cc577a4SJonathan Peyton               KMP_MSG(CantSetMonitorStackSize, (long int)__kmp_monitor_stksize),
9193041982dSJonathan Peyton               err_code, KMP_HNT(ChangeMonitorStackSize), __kmp_msg_null);
9207cc577a4SJonathan Peyton     if (__kmp_generate_warnings == kmp_warnings_off) {
9217cc577a4SJonathan Peyton       __kmp_str_free(&err_code.str);
9227cc577a4SJonathan Peyton     }
923bd3a7633SJonathan Peyton   }
9247cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
9257cc577a4SJonathan Peyton 
9263041982dSJonathan Peyton   status =
9273041982dSJonathan Peyton       pthread_create(&handle, &thread_attr, __kmp_launch_monitor, (void *)th);
9287cc577a4SJonathan Peyton 
9297cc577a4SJonathan Peyton   if (status != 0) {
9307cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE
9317cc577a4SJonathan Peyton     if (status == EINVAL) {
9327cc577a4SJonathan Peyton       if (auto_adj_size && (__kmp_monitor_stksize < (size_t)0x40000000)) {
9337cc577a4SJonathan Peyton         __kmp_monitor_stksize *= 2;
9347cc577a4SJonathan Peyton         goto retry;
9357cc577a4SJonathan Peyton       }
9366a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(CantSetMonitorStackSize, __kmp_monitor_stksize),
9376a393f75SJonathan Peyton                   KMP_ERR(status), KMP_HNT(IncreaseMonitorStackSize),
9386a393f75SJonathan Peyton                   __kmp_msg_null);
939bd3a7633SJonathan Peyton     }
9407cc577a4SJonathan Peyton     if (status == ENOMEM) {
9416a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(CantSetMonitorStackSize, __kmp_monitor_stksize),
9426a393f75SJonathan Peyton                   KMP_ERR(status), KMP_HNT(DecreaseMonitorStackSize),
9436a393f75SJonathan Peyton                   __kmp_msg_null);
944bd3a7633SJonathan Peyton     }
9457cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
9467cc577a4SJonathan Peyton     if (status == EAGAIN) {
9476a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(NoResourcesForMonitorThread), KMP_ERR(status),
9486a393f75SJonathan Peyton                   KMP_HNT(DecreaseNumberOfThreadsInUse), __kmp_msg_null);
949bd3a7633SJonathan Peyton     }
9507cc577a4SJonathan Peyton     KMP_SYSFAIL("pthread_create", status);
951bd3a7633SJonathan Peyton   }
9527cc577a4SJonathan Peyton 
9537cc577a4SJonathan Peyton   th->th.th_info.ds.ds_thread = handle;
9547cc577a4SJonathan Peyton 
9557cc577a4SJonathan Peyton #if KMP_REAL_TIME_FIX
9567cc577a4SJonathan Peyton   // Wait for the monitor thread is really started and set its *priority*.
9573041982dSJonathan Peyton   KMP_DEBUG_ASSERT(sizeof(kmp_uint32) ==
9583041982dSJonathan Peyton                    sizeof(__kmp_global.g.g_time.dt.t_value));
959e47d32f1SJonathan Peyton   __kmp_wait_4((kmp_uint32 volatile *)&__kmp_global.g.g_time.dt.t_value, -1,
960e47d32f1SJonathan Peyton                &__kmp_neq_4, NULL);
9617cc577a4SJonathan Peyton #endif // KMP_REAL_TIME_FIX
9627cc577a4SJonathan Peyton 
9637cc577a4SJonathan Peyton #ifdef KMP_THREAD_ATTR
9647cc577a4SJonathan Peyton   status = pthread_attr_destroy(&thread_attr);
9657cc577a4SJonathan Peyton   if (status != 0) {
9667cc577a4SJonathan Peyton     kmp_msg_t err_code = KMP_ERR(status);
9673041982dSJonathan Peyton     __kmp_msg(kmp_ms_warning, KMP_MSG(CantDestroyThreadAttrs), err_code,
9683041982dSJonathan Peyton               __kmp_msg_null);
9697cc577a4SJonathan Peyton     if (__kmp_generate_warnings == kmp_warnings_off) {
9707cc577a4SJonathan Peyton       __kmp_str_free(&err_code.str);
9717cc577a4SJonathan Peyton     }
972bd3a7633SJonathan Peyton   }
9737cc577a4SJonathan Peyton #endif
9747cc577a4SJonathan Peyton 
9757cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
9767cc577a4SJonathan Peyton 
9773041982dSJonathan Peyton   KA_TRACE(10, ("__kmp_create_monitor: monitor created %#.8lx\n",
9783041982dSJonathan Peyton                 th->th.th_info.ds.ds_thread));
9797cc577a4SJonathan Peyton 
9807cc577a4SJonathan Peyton } // __kmp_create_monitor
9817cc577a4SJonathan Peyton #endif // KMP_USE_MONITOR
9827cc577a4SJonathan Peyton 
__kmp_exit_thread(int exit_status)9833041982dSJonathan Peyton void __kmp_exit_thread(int exit_status) {
9847cc577a4SJonathan Peyton   pthread_exit((void *)(intptr_t)exit_status);
9857cc577a4SJonathan Peyton } // __kmp_exit_thread
9867cc577a4SJonathan Peyton 
9877cc577a4SJonathan Peyton #if KMP_USE_MONITOR
9887cc577a4SJonathan Peyton void __kmp_resume_monitor();
9897cc577a4SJonathan Peyton 
__kmp_reap_monitor(kmp_info_t * th)9903041982dSJonathan Peyton void __kmp_reap_monitor(kmp_info_t *th) {
9917cc577a4SJonathan Peyton   int status;
9927cc577a4SJonathan Peyton   void *exit_val;
9937cc577a4SJonathan Peyton 
9943041982dSJonathan Peyton   KA_TRACE(10, ("__kmp_reap_monitor: try to reap monitor thread with handle"
9953041982dSJonathan Peyton                 " %#.8lx\n",
9967cc577a4SJonathan Peyton                 th->th.th_info.ds.ds_thread));
9977cc577a4SJonathan Peyton 
9987cc577a4SJonathan Peyton   // If monitor has been created, its tid and gtid should be KMP_GTID_MONITOR.
9997cc577a4SJonathan Peyton   // If both tid and gtid are 0, it means the monitor did not ever start.
10007cc577a4SJonathan Peyton   // If both tid and gtid are KMP_GTID_DNE, the monitor has been shut down.
10017cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(th->th.th_info.ds.ds_tid == th->th.th_info.ds.ds_gtid);
10027cc577a4SJonathan Peyton   if (th->th.th_info.ds.ds_gtid != KMP_GTID_MONITOR) {
10037cc577a4SJonathan Peyton     KA_TRACE(10, ("__kmp_reap_monitor: monitor did not start, returning\n"));
10047cc577a4SJonathan Peyton     return;
1005bd3a7633SJonathan Peyton   }
10067cc577a4SJonathan Peyton 
10077cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
10087cc577a4SJonathan Peyton 
10093041982dSJonathan Peyton   /* First, check to see whether the monitor thread exists to wake it up. This
10103041982dSJonathan Peyton      is to avoid performance problem when the monitor sleeps during
10113041982dSJonathan Peyton      blocktime-size interval */
10127cc577a4SJonathan Peyton 
10137cc577a4SJonathan Peyton   status = pthread_kill(th->th.th_info.ds.ds_thread, 0);
10147cc577a4SJonathan Peyton   if (status != ESRCH) {
10157cc577a4SJonathan Peyton     __kmp_resume_monitor(); // Wake up the monitor thread
10167cc577a4SJonathan Peyton   }
10177cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_reap_monitor: try to join with monitor\n"));
10187cc577a4SJonathan Peyton   status = pthread_join(th->th.th_info.ds.ds_thread, &exit_val);
10197cc577a4SJonathan Peyton   if (exit_val != th) {
10206a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(ReapMonitorError), KMP_ERR(status), __kmp_msg_null);
10217cc577a4SJonathan Peyton   }
10227cc577a4SJonathan Peyton 
10237cc577a4SJonathan Peyton   th->th.th_info.ds.ds_tid = KMP_GTID_DNE;
10247cc577a4SJonathan Peyton   th->th.th_info.ds.ds_gtid = KMP_GTID_DNE;
10257cc577a4SJonathan Peyton 
10263041982dSJonathan Peyton   KA_TRACE(10, ("__kmp_reap_monitor: done reaping monitor thread with handle"
10273041982dSJonathan Peyton                 " %#.8lx\n",
10287cc577a4SJonathan Peyton                 th->th.th_info.ds.ds_thread));
10297cc577a4SJonathan Peyton 
10307cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
10317cc577a4SJonathan Peyton }
10327cc577a4SJonathan Peyton #endif // KMP_USE_MONITOR
10337cc577a4SJonathan Peyton 
__kmp_reap_worker(kmp_info_t * th)10343041982dSJonathan Peyton void __kmp_reap_worker(kmp_info_t *th) {
10357cc577a4SJonathan Peyton   int status;
10367cc577a4SJonathan Peyton   void *exit_val;
10377cc577a4SJonathan Peyton 
10387cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
10397cc577a4SJonathan Peyton 
10403041982dSJonathan Peyton   KA_TRACE(
10413041982dSJonathan Peyton       10, ("__kmp_reap_worker: try to reap T#%d\n", th->th.th_info.ds.ds_gtid));
10427cc577a4SJonathan Peyton 
10437cc577a4SJonathan Peyton   status = pthread_join(th->th.th_info.ds.ds_thread, &exit_val);
10447cc577a4SJonathan Peyton #ifdef KMP_DEBUG
10457cc577a4SJonathan Peyton   /* Don't expose these to the user until we understand when they trigger */
10467cc577a4SJonathan Peyton   if (status != 0) {
10476a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(ReapWorkerError), KMP_ERR(status), __kmp_msg_null);
10487cc577a4SJonathan Peyton   }
10497cc577a4SJonathan Peyton   if (exit_val != th) {
10503041982dSJonathan Peyton     KA_TRACE(10, ("__kmp_reap_worker: worker T#%d did not reap properly, "
10513041982dSJonathan Peyton                   "exit_val = %p\n",
10527cc577a4SJonathan Peyton                   th->th.th_info.ds.ds_gtid, exit_val));
10537cc577a4SJonathan Peyton   }
10548b81524cSAndreyChurbanov #else
10558b81524cSAndreyChurbanov   (void)status; // unused variable
10567cc577a4SJonathan Peyton #endif /* KMP_DEBUG */
10577cc577a4SJonathan Peyton 
10583041982dSJonathan Peyton   KA_TRACE(10, ("__kmp_reap_worker: done reaping T#%d\n",
10593041982dSJonathan Peyton                 th->th.th_info.ds.ds_gtid));
10607cc577a4SJonathan Peyton 
10617cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
10627cc577a4SJonathan Peyton }
10637cc577a4SJonathan Peyton 
10647cc577a4SJonathan Peyton #if KMP_HANDLE_SIGNALS
10657cc577a4SJonathan Peyton 
__kmp_null_handler(int signo)10663041982dSJonathan Peyton static void __kmp_null_handler(int signo) {
10677cc577a4SJonathan Peyton   //  Do nothing, for doing SIG_IGN-type actions.
10687cc577a4SJonathan Peyton } // __kmp_null_handler
10697cc577a4SJonathan Peyton 
__kmp_team_handler(int signo)10703041982dSJonathan Peyton static void __kmp_team_handler(int signo) {
10717cc577a4SJonathan Peyton   if (__kmp_global.g.g_abort == 0) {
10727cc577a4SJonathan Peyton /* Stage 1 signal handler, let's shut down all of the threads */
10737cc577a4SJonathan Peyton #ifdef KMP_DEBUG
10747cc577a4SJonathan Peyton     __kmp_debug_printf("__kmp_team_handler: caught signal = %d\n", signo);
10757cc577a4SJonathan Peyton #endif
10767cc577a4SJonathan Peyton     switch (signo) {
10777cc577a4SJonathan Peyton     case SIGHUP:
10787cc577a4SJonathan Peyton     case SIGINT:
10797cc577a4SJonathan Peyton     case SIGQUIT:
10807cc577a4SJonathan Peyton     case SIGILL:
10817cc577a4SJonathan Peyton     case SIGABRT:
10827cc577a4SJonathan Peyton     case SIGFPE:
10837cc577a4SJonathan Peyton     case SIGBUS:
10847cc577a4SJonathan Peyton     case SIGSEGV:
10857cc577a4SJonathan Peyton #ifdef SIGSYS
10867cc577a4SJonathan Peyton     case SIGSYS:
10877cc577a4SJonathan Peyton #endif
10887cc577a4SJonathan Peyton     case SIGTERM:
10897cc577a4SJonathan Peyton       if (__kmp_debug_buf) {
10907cc577a4SJonathan Peyton         __kmp_dump_debug_buffer();
1091bd3a7633SJonathan Peyton       }
10929615890dSTodd Erdner       __kmp_unregister_library(); // cleanup shared memory
10937cc577a4SJonathan Peyton       KMP_MB(); // Flush all pending memory write invalidates.
10947cc577a4SJonathan Peyton       TCW_4(__kmp_global.g.g_abort, signo);
10957cc577a4SJonathan Peyton       KMP_MB(); // Flush all pending memory write invalidates.
10967cc577a4SJonathan Peyton       TCW_4(__kmp_global.g.g_done, TRUE);
10977cc577a4SJonathan Peyton       KMP_MB(); // Flush all pending memory write invalidates.
10987cc577a4SJonathan Peyton       break;
10997cc577a4SJonathan Peyton     default:
11007cc577a4SJonathan Peyton #ifdef KMP_DEBUG
11017cc577a4SJonathan Peyton       __kmp_debug_printf("__kmp_team_handler: unknown signal type");
11027cc577a4SJonathan Peyton #endif
11037cc577a4SJonathan Peyton       break;
1104bd3a7633SJonathan Peyton     }
1105bd3a7633SJonathan Peyton   }
11067cc577a4SJonathan Peyton } // __kmp_team_handler
11077cc577a4SJonathan Peyton 
__kmp_sigaction(int signum,const struct sigaction * act,struct sigaction * oldact)11083041982dSJonathan Peyton static void __kmp_sigaction(int signum, const struct sigaction *act,
11093041982dSJonathan Peyton                             struct sigaction *oldact) {
11107cc577a4SJonathan Peyton   int rc = sigaction(signum, act, oldact);
11117cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("sigaction", rc);
11127cc577a4SJonathan Peyton }
11137cc577a4SJonathan Peyton 
__kmp_install_one_handler(int sig,sig_func_t handler_func,int parallel_init)11143041982dSJonathan Peyton static void __kmp_install_one_handler(int sig, sig_func_t handler_func,
11153041982dSJonathan Peyton                                       int parallel_init) {
11167cc577a4SJonathan Peyton   KMP_MB(); // Flush all pending memory write invalidates.
11173041982dSJonathan Peyton   KB_TRACE(60,
11183041982dSJonathan Peyton            ("__kmp_install_one_handler( %d, ..., %d )\n", sig, parallel_init));
11197cc577a4SJonathan Peyton   if (parallel_init) {
11207cc577a4SJonathan Peyton     struct sigaction new_action;
11217cc577a4SJonathan Peyton     struct sigaction old_action;
11227cc577a4SJonathan Peyton     new_action.sa_handler = handler_func;
11237cc577a4SJonathan Peyton     new_action.sa_flags = 0;
11247cc577a4SJonathan Peyton     sigfillset(&new_action.sa_mask);
11257cc577a4SJonathan Peyton     __kmp_sigaction(sig, &new_action, &old_action);
11267cc577a4SJonathan Peyton     if (old_action.sa_handler == __kmp_sighldrs[sig].sa_handler) {
11277cc577a4SJonathan Peyton       sigaddset(&__kmp_sigset, sig);
11287cc577a4SJonathan Peyton     } else {
11297cc577a4SJonathan Peyton       // Restore/keep user's handler if one previously installed.
11307cc577a4SJonathan Peyton       __kmp_sigaction(sig, &old_action, NULL);
1131bd3a7633SJonathan Peyton     }
11327cc577a4SJonathan Peyton   } else {
11337cc577a4SJonathan Peyton     // Save initial/system signal handlers to see if user handlers installed.
11347cc577a4SJonathan Peyton     __kmp_sigaction(sig, NULL, &__kmp_sighldrs[sig]);
1135bd3a7633SJonathan Peyton   }
11367cc577a4SJonathan Peyton   KMP_MB(); // Flush all pending memory write invalidates.
11377cc577a4SJonathan Peyton } // __kmp_install_one_handler
11387cc577a4SJonathan Peyton 
__kmp_remove_one_handler(int sig)11393041982dSJonathan Peyton static void __kmp_remove_one_handler(int sig) {
11407cc577a4SJonathan Peyton   KB_TRACE(60, ("__kmp_remove_one_handler( %d )\n", sig));
11417cc577a4SJonathan Peyton   if (sigismember(&__kmp_sigset, sig)) {
11427cc577a4SJonathan Peyton     struct sigaction old;
11437cc577a4SJonathan Peyton     KMP_MB(); // Flush all pending memory write invalidates.
11447cc577a4SJonathan Peyton     __kmp_sigaction(sig, &__kmp_sighldrs[sig], &old);
11453041982dSJonathan Peyton     if ((old.sa_handler != __kmp_team_handler) &&
11463041982dSJonathan Peyton         (old.sa_handler != __kmp_null_handler)) {
11477cc577a4SJonathan Peyton       // Restore the users signal handler.
11483041982dSJonathan Peyton       KB_TRACE(10, ("__kmp_remove_one_handler: oops, not our handler, "
11493041982dSJonathan Peyton                     "restoring: sig=%d\n",
11503041982dSJonathan Peyton                     sig));
11517cc577a4SJonathan Peyton       __kmp_sigaction(sig, &old, NULL);
1152bd3a7633SJonathan Peyton     }
11537cc577a4SJonathan Peyton     sigdelset(&__kmp_sigset, sig);
11547cc577a4SJonathan Peyton     KMP_MB(); // Flush all pending memory write invalidates.
1155bd3a7633SJonathan Peyton   }
11567cc577a4SJonathan Peyton } // __kmp_remove_one_handler
11577cc577a4SJonathan Peyton 
__kmp_install_signals(int parallel_init)11583041982dSJonathan Peyton void __kmp_install_signals(int parallel_init) {
11597cc577a4SJonathan Peyton   KB_TRACE(10, ("__kmp_install_signals( %d )\n", parallel_init));
11607cc577a4SJonathan Peyton   if (__kmp_handle_signals || !parallel_init) {
11613041982dSJonathan Peyton     // If ! parallel_init, we do not install handlers, just save original
11623041982dSJonathan Peyton     // handlers. Let us do it even __handle_signals is 0.
11637cc577a4SJonathan Peyton     sigemptyset(&__kmp_sigset);
11647cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGHUP, __kmp_team_handler, parallel_init);
11657cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGINT, __kmp_team_handler, parallel_init);
11667cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGQUIT, __kmp_team_handler, parallel_init);
11677cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGILL, __kmp_team_handler, parallel_init);
11687cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGABRT, __kmp_team_handler, parallel_init);
11697cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGFPE, __kmp_team_handler, parallel_init);
11707cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGBUS, __kmp_team_handler, parallel_init);
11717cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGSEGV, __kmp_team_handler, parallel_init);
11727cc577a4SJonathan Peyton #ifdef SIGSYS
11737cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGSYS, __kmp_team_handler, parallel_init);
11747cc577a4SJonathan Peyton #endif // SIGSYS
11757cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGTERM, __kmp_team_handler, parallel_init);
11767cc577a4SJonathan Peyton #ifdef SIGPIPE
11777cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGPIPE, __kmp_team_handler, parallel_init);
11787cc577a4SJonathan Peyton #endif // SIGPIPE
1179bd3a7633SJonathan Peyton   }
11807cc577a4SJonathan Peyton } // __kmp_install_signals
11817cc577a4SJonathan Peyton 
__kmp_remove_signals(void)11823041982dSJonathan Peyton void __kmp_remove_signals(void) {
11837cc577a4SJonathan Peyton   int sig;
11847cc577a4SJonathan Peyton   KB_TRACE(10, ("__kmp_remove_signals()\n"));
11857cc577a4SJonathan Peyton   for (sig = 1; sig < NSIG; ++sig) {
11867cc577a4SJonathan Peyton     __kmp_remove_one_handler(sig);
1187bd3a7633SJonathan Peyton   }
11887cc577a4SJonathan Peyton } // __kmp_remove_signals
11897cc577a4SJonathan Peyton 
11907cc577a4SJonathan Peyton #endif // KMP_HANDLE_SIGNALS
11917cc577a4SJonathan Peyton 
__kmp_enable(int new_state)11923041982dSJonathan Peyton void __kmp_enable(int new_state) {
11937cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS
11947cc577a4SJonathan Peyton   int status, old_state;
11957cc577a4SJonathan Peyton   status = pthread_setcancelstate(new_state, &old_state);
11967cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_setcancelstate", status);
11977cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(old_state == PTHREAD_CANCEL_DISABLE);
11987cc577a4SJonathan Peyton #endif
11997cc577a4SJonathan Peyton }
12007cc577a4SJonathan Peyton 
__kmp_disable(int * old_state)12013041982dSJonathan Peyton void __kmp_disable(int *old_state) {
12027cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS
12037cc577a4SJonathan Peyton   int status;
12047cc577a4SJonathan Peyton   status = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, old_state);
12057cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_setcancelstate", status);
12067cc577a4SJonathan Peyton #endif
12077cc577a4SJonathan Peyton }
12087cc577a4SJonathan Peyton 
__kmp_atfork_prepare(void)1209eaa9e40cSJonathan Peyton static void __kmp_atfork_prepare(void) {
1210eaa9e40cSJonathan Peyton   __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
1211eaa9e40cSJonathan Peyton   __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
12127cc577a4SJonathan Peyton }
12137cc577a4SJonathan Peyton 
__kmp_atfork_parent(void)1214eaa9e40cSJonathan Peyton static void __kmp_atfork_parent(void) {
1215eaa9e40cSJonathan Peyton   __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
1216171ca93cSHansang Bae   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
12177cc577a4SJonathan Peyton }
12187cc577a4SJonathan Peyton 
12193041982dSJonathan Peyton /* Reset the library so execution in the child starts "all over again" with
12207cc577a4SJonathan Peyton    clean data structures in initial states.  Don't worry about freeing memory
12213041982dSJonathan Peyton    allocated by parent, just abandon it to be safe. */
__kmp_atfork_child(void)12223041982dSJonathan Peyton static void __kmp_atfork_child(void) {
1223eaa9e40cSJonathan Peyton   __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
1224171ca93cSHansang Bae   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
12257cc577a4SJonathan Peyton   /* TODO make sure this is done right for nested/sibling */
12267cc577a4SJonathan Peyton   // ATT:  Memory leaks are here? TODO: Check it and fix.
12277cc577a4SJonathan Peyton   /* KMP_ASSERT( 0 ); */
12287cc577a4SJonathan Peyton 
12297cc577a4SJonathan Peyton   ++__kmp_fork_count;
12307cc577a4SJonathan Peyton 
1231072ccb72SJonathan Peyton #if KMP_AFFINITY_SUPPORTED
123250699284SDavid Carlier #if KMP_OS_LINUX || KMP_OS_FREEBSD
1233d330e630SJonathan Peyton   // reset the affinity in the child to the initial thread
1234d330e630SJonathan Peyton   // affinity in the parent
1235d330e630SJonathan Peyton   kmp_set_thread_affinity_mask_initial();
1236d330e630SJonathan Peyton #endif
1237c46becf5SJonathan Peyton   // Set default not to bind threads tightly in the child (we're expecting
1238072ccb72SJonathan Peyton   // over-subscription after the fork and this can improve things for
1239072ccb72SJonathan Peyton   // scripting languages that use OpenMP inside process-parallel code).
1240072ccb72SJonathan Peyton   __kmp_affinity_type = affinity_none;
1241072ccb72SJonathan Peyton   if (__kmp_nested_proc_bind.bind_types != NULL) {
1242072ccb72SJonathan Peyton     __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
1243072ccb72SJonathan Peyton   }
12445ebbb366SPeyton, Jonathan L   __kmp_affinity_masks = NULL;
12455ebbb366SPeyton, Jonathan L   __kmp_affinity_num_masks = 0;
1246072ccb72SJonathan Peyton #endif // KMP_AFFINITY_SUPPORTED
1247d330e630SJonathan Peyton 
12487cc577a4SJonathan Peyton #if KMP_USE_MONITOR
12497cc577a4SJonathan Peyton   __kmp_init_monitor = 0;
12507cc577a4SJonathan Peyton #endif
12517cc577a4SJonathan Peyton   __kmp_init_parallel = FALSE;
12527cc577a4SJonathan Peyton   __kmp_init_middle = FALSE;
12537cc577a4SJonathan Peyton   __kmp_init_serial = FALSE;
12547cc577a4SJonathan Peyton   TCW_4(__kmp_init_gtid, FALSE);
12557cc577a4SJonathan Peyton   __kmp_init_common = FALSE;
12567cc577a4SJonathan Peyton 
12577cc577a4SJonathan Peyton   TCW_4(__kmp_init_user_locks, FALSE);
12587cc577a4SJonathan Peyton #if !KMP_USE_DYNAMIC_LOCK
12597cc577a4SJonathan Peyton   __kmp_user_lock_table.used = 1;
12607cc577a4SJonathan Peyton   __kmp_user_lock_table.allocated = 0;
12617cc577a4SJonathan Peyton   __kmp_user_lock_table.table = NULL;
12627cc577a4SJonathan Peyton   __kmp_lock_blocks = NULL;
12637cc577a4SJonathan Peyton #endif
12647cc577a4SJonathan Peyton 
12657cc577a4SJonathan Peyton   __kmp_all_nth = 0;
12667cc577a4SJonathan Peyton   TCW_4(__kmp_nth, 0);
12677cc577a4SJonathan Peyton 
1268eaa9e40cSJonathan Peyton   __kmp_thread_pool = NULL;
1269eaa9e40cSJonathan Peyton   __kmp_thread_pool_insert_pt = NULL;
1270eaa9e40cSJonathan Peyton   __kmp_team_pool = NULL;
1271eaa9e40cSJonathan Peyton 
12723041982dSJonathan Peyton   /* Must actually zero all the *cache arguments passed to __kmpc_threadprivate
12733041982dSJonathan Peyton      here so threadprivate doesn't use stale data */
12747cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_atfork_child: checking cache address list %p\n",
12757cc577a4SJonathan Peyton                 __kmp_threadpriv_cache_list));
12767cc577a4SJonathan Peyton 
12777cc577a4SJonathan Peyton   while (__kmp_threadpriv_cache_list != NULL) {
12787cc577a4SJonathan Peyton 
12797cc577a4SJonathan Peyton     if (*__kmp_threadpriv_cache_list->addr != NULL) {
12807cc577a4SJonathan Peyton       KC_TRACE(50, ("__kmp_atfork_child: zeroing cache at address %p\n",
12817cc577a4SJonathan Peyton                     &(*__kmp_threadpriv_cache_list->addr)));
12827cc577a4SJonathan Peyton 
12837cc577a4SJonathan Peyton       *__kmp_threadpriv_cache_list->addr = NULL;
12847cc577a4SJonathan Peyton     }
12857cc577a4SJonathan Peyton     __kmp_threadpriv_cache_list = __kmp_threadpriv_cache_list->next;
12867cc577a4SJonathan Peyton   }
12877cc577a4SJonathan Peyton 
12887cc577a4SJonathan Peyton   __kmp_init_runtime = FALSE;
12897cc577a4SJonathan Peyton 
12907cc577a4SJonathan Peyton   /* reset statically initialized locks */
12917cc577a4SJonathan Peyton   __kmp_init_bootstrap_lock(&__kmp_initz_lock);
12927cc577a4SJonathan Peyton   __kmp_init_bootstrap_lock(&__kmp_stdio_lock);
12937cc577a4SJonathan Peyton   __kmp_init_bootstrap_lock(&__kmp_console_lock);
1294eaa9e40cSJonathan Peyton   __kmp_init_bootstrap_lock(&__kmp_task_team_lock);
1295eaa9e40cSJonathan Peyton 
12965388acd3SAndrey Churbanov #if USE_ITT_BUILD
1297eaa9e40cSJonathan Peyton   __kmp_itt_reset(); // reset ITT's global state
12985388acd3SAndrey Churbanov #endif /* USE_ITT_BUILD */
12997cc577a4SJonathan Peyton 
1300*a01d274fSAndreyChurbanov   {
1301*a01d274fSAndreyChurbanov     // Child process often get terminated without any use of OpenMP. That might
1302*a01d274fSAndreyChurbanov     // cause mapped shared memory file to be left unattended. Thus we postpone
1303*a01d274fSAndreyChurbanov     // library registration till middle initialization in the child process.
1304*a01d274fSAndreyChurbanov     __kmp_need_register_serial = FALSE;
1305171ca93cSHansang Bae     __kmp_serial_initialize();
1306*a01d274fSAndreyChurbanov   }
1307171ca93cSHansang Bae 
13087cc577a4SJonathan Peyton   /* This is necessary to make sure no stale data is left around */
13097cc577a4SJonathan Peyton   /* AC: customers complain that we use unsafe routines in the atfork
13107cc577a4SJonathan Peyton      handler. Mathworks: dlsym() is unsafe. We call dlsym and dlopen
13117cc577a4SJonathan Peyton      in dynamic_link when check the presence of shared tbbmalloc library.
13127cc577a4SJonathan Peyton      Suggestion is to make the library initialization lazier, similar
13137cc577a4SJonathan Peyton      to what done for __kmpc_begin(). */
13147cc577a4SJonathan Peyton   // TODO: synchronize all static initializations with regular library
1315de4749b7SJonathan Peyton   //       startup; look at kmp_global.cpp and etc.
13167cc577a4SJonathan Peyton   //__kmp_internal_begin ();
13177cc577a4SJonathan Peyton }
13187cc577a4SJonathan Peyton 
__kmp_register_atfork(void)13193041982dSJonathan Peyton void __kmp_register_atfork(void) {
13207cc577a4SJonathan Peyton   if (__kmp_need_register_atfork) {
13213041982dSJonathan Peyton     int status = pthread_atfork(__kmp_atfork_prepare, __kmp_atfork_parent,
13223041982dSJonathan Peyton                                 __kmp_atfork_child);
13237cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_atfork", status);
13247cc577a4SJonathan Peyton     __kmp_need_register_atfork = FALSE;
13257cc577a4SJonathan Peyton   }
13267cc577a4SJonathan Peyton }
13277cc577a4SJonathan Peyton 
__kmp_suspend_initialize(void)13283041982dSJonathan Peyton void __kmp_suspend_initialize(void) {
13297cc577a4SJonathan Peyton   int status;
13307cc577a4SJonathan Peyton   status = pthread_mutexattr_init(&__kmp_suspend_mutex_attr);
13317cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutexattr_init", status);
13327cc577a4SJonathan Peyton   status = pthread_condattr_init(&__kmp_suspend_cond_attr);
13337cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_condattr_init", status);
13347cc577a4SJonathan Peyton }
13357cc577a4SJonathan Peyton 
__kmp_suspend_initialize_thread(kmp_info_t * th)1336feac33ebSJonathan Peyton void __kmp_suspend_initialize_thread(kmp_info_t *th) {
1337f8f788b2SAndrey Churbanov   int old_value = KMP_ATOMIC_LD_RLX(&th->th.th_suspend_init_count);
1338f8f788b2SAndrey Churbanov   int new_value = __kmp_fork_count + 1;
1339f8f788b2SAndrey Churbanov   // Return if already initialized
1340f8f788b2SAndrey Churbanov   if (old_value == new_value)
1341f8f788b2SAndrey Churbanov     return;
1342f8f788b2SAndrey Churbanov   // Wait, then return if being initialized
1343309b00a4SShilei Tian   if (old_value == -1 || !__kmp_atomic_compare_store(
1344309b00a4SShilei Tian                              &th->th.th_suspend_init_count, old_value, -1)) {
1345f8f788b2SAndrey Churbanov     while (KMP_ATOMIC_LD_ACQ(&th->th.th_suspend_init_count) != new_value) {
1346f8f788b2SAndrey Churbanov       KMP_CPU_PAUSE();
1347f8f788b2SAndrey Churbanov     }
1348f8f788b2SAndrey Churbanov   } else {
1349f8f788b2SAndrey Churbanov     // Claim to be the initializer and do initializations
13507cc577a4SJonathan Peyton     int status;
13513041982dSJonathan Peyton     status = pthread_cond_init(&th->th.th_suspend_cv.c_cond,
13523041982dSJonathan Peyton                                &__kmp_suspend_cond_attr);
13537cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_cond_init", status);
13543041982dSJonathan Peyton     status = pthread_mutex_init(&th->th.th_suspend_mx.m_mutex,
13553041982dSJonathan Peyton                                 &__kmp_suspend_mutex_attr);
13567cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
1357f8f788b2SAndrey Churbanov     KMP_ATOMIC_ST_REL(&th->th.th_suspend_init_count, new_value);
1358bd3a7633SJonathan Peyton   }
13597cc577a4SJonathan Peyton }
13607cc577a4SJonathan Peyton 
__kmp_suspend_uninitialize_thread(kmp_info_t * th)13613041982dSJonathan Peyton void __kmp_suspend_uninitialize_thread(kmp_info_t *th) {
1362f8f788b2SAndrey Churbanov   if (KMP_ATOMIC_LD_ACQ(&th->th.th_suspend_init_count) > __kmp_fork_count) {
13633041982dSJonathan Peyton     /* this means we have initialize the suspension pthread objects for this
13643041982dSJonathan Peyton        thread in this instance of the process */
13657cc577a4SJonathan Peyton     int status;
13667cc577a4SJonathan Peyton 
13677cc577a4SJonathan Peyton     status = pthread_cond_destroy(&th->th.th_suspend_cv.c_cond);
13687cc577a4SJonathan Peyton     if (status != 0 && status != EBUSY) {
13697cc577a4SJonathan Peyton       KMP_SYSFAIL("pthread_cond_destroy", status);
1370bd3a7633SJonathan Peyton     }
13717cc577a4SJonathan Peyton     status = pthread_mutex_destroy(&th->th.th_suspend_mx.m_mutex);
13727cc577a4SJonathan Peyton     if (status != 0 && status != EBUSY) {
13737cc577a4SJonathan Peyton       KMP_SYSFAIL("pthread_mutex_destroy", status);
1374bd3a7633SJonathan Peyton     }
13757cc577a4SJonathan Peyton     --th->th.th_suspend_init_count;
1376f8f788b2SAndrey Churbanov     KMP_DEBUG_ASSERT(KMP_ATOMIC_LD_RLX(&th->th.th_suspend_init_count) ==
1377f8f788b2SAndrey Churbanov                      __kmp_fork_count);
13787cc577a4SJonathan Peyton   }
13797cc577a4SJonathan Peyton }
13807cc577a4SJonathan Peyton 
13819b8bb323SJonathan Peyton // return true if lock obtained, false otherwise
__kmp_try_suspend_mx(kmp_info_t * th)13829b8bb323SJonathan Peyton int __kmp_try_suspend_mx(kmp_info_t *th) {
13839b8bb323SJonathan Peyton   return (pthread_mutex_trylock(&th->th.th_suspend_mx.m_mutex) == 0);
13849b8bb323SJonathan Peyton }
13859b8bb323SJonathan Peyton 
__kmp_lock_suspend_mx(kmp_info_t * th)13869b8bb323SJonathan Peyton void __kmp_lock_suspend_mx(kmp_info_t *th) {
13879b8bb323SJonathan Peyton   int status = pthread_mutex_lock(&th->th.th_suspend_mx.m_mutex);
13889b8bb323SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
13899b8bb323SJonathan Peyton }
13909b8bb323SJonathan Peyton 
__kmp_unlock_suspend_mx(kmp_info_t * th)13919b8bb323SJonathan Peyton void __kmp_unlock_suspend_mx(kmp_info_t *th) {
13929b8bb323SJonathan Peyton   int status = pthread_mutex_unlock(&th->th.th_suspend_mx.m_mutex);
13939b8bb323SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
13949b8bb323SJonathan Peyton }
13959b8bb323SJonathan Peyton 
13967cc577a4SJonathan Peyton /* This routine puts the calling thread to sleep after setting the
13973041982dSJonathan Peyton    sleep bit for the indicated flag variable to true. */
13987cc577a4SJonathan Peyton template <class C>
__kmp_suspend_template(int th_gtid,C * flag)13993041982dSJonathan Peyton static inline void __kmp_suspend_template(int th_gtid, C *flag) {
14007cc577a4SJonathan Peyton   KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_suspend);
14017cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[th_gtid];
14027cc577a4SJonathan Peyton   int status;
14037cc577a4SJonathan Peyton   typename C::flag_t old_spin;
14047cc577a4SJonathan Peyton 
14053041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_suspend_template: T#%d enter for flag = %p\n", th_gtid,
14063041982dSJonathan Peyton                 flag->get()));
14077cc577a4SJonathan Peyton 
14087cc577a4SJonathan Peyton   __kmp_suspend_initialize_thread(th);
14097cc577a4SJonathan Peyton 
1410e0665a90STerry Wilmarth   __kmp_lock_suspend_mx(th);
14117cc577a4SJonathan Peyton 
14127cc577a4SJonathan Peyton   KF_TRACE(10, ("__kmp_suspend_template: T#%d setting sleep bit for spin(%p)\n",
14137cc577a4SJonathan Peyton                 th_gtid, flag->get()));
14147cc577a4SJonathan Peyton 
14153041982dSJonathan Peyton   /* TODO: shouldn't this use release semantics to ensure that
14163041982dSJonathan Peyton      __kmp_suspend_initialize_thread gets called first? */
14177cc577a4SJonathan Peyton   old_spin = flag->set_sleeping();
1418d8e4cb91STerry Wilmarth   TCW_PTR(th->th.th_sleep_loc, (void *)flag);
1419d8e4cb91STerry Wilmarth   th->th.th_sleep_loc_type = flag->get_type();
14209b8bb323SJonathan Peyton   if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME &&
14219b8bb323SJonathan Peyton       __kmp_pause_status != kmp_soft_paused) {
14229b8bb323SJonathan Peyton     flag->unset_sleeping();
1423d8e4cb91STerry Wilmarth     TCW_PTR(th->th.th_sleep_loc, NULL);
1424d8e4cb91STerry Wilmarth     th->th.th_sleep_loc_type = flag_unset;
1425e0665a90STerry Wilmarth     __kmp_unlock_suspend_mx(th);
14269b8bb323SJonathan Peyton     return;
14279b8bb323SJonathan Peyton   }
14283041982dSJonathan Peyton   KF_TRACE(5, ("__kmp_suspend_template: T#%d set sleep bit for spin(%p)==%x,"
14293041982dSJonathan Peyton                " was %x\n",
143037e2ef54SJonathan Peyton                th_gtid, flag->get(), flag->load(), old_spin));
14317cc577a4SJonathan Peyton 
1432d8e4cb91STerry Wilmarth   if (flag->done_check_val(old_spin) || flag->done_check()) {
1433d8e4cb91STerry Wilmarth     flag->unset_sleeping();
1434d8e4cb91STerry Wilmarth     TCW_PTR(th->th.th_sleep_loc, NULL);
1435d8e4cb91STerry Wilmarth     th->th.th_sleep_loc_type = flag_unset;
14363041982dSJonathan Peyton     KF_TRACE(5, ("__kmp_suspend_template: T#%d false alarm, reset sleep bit "
14373041982dSJonathan Peyton                  "for spin(%p)\n",
14387cc577a4SJonathan Peyton                  th_gtid, flag->get()));
14397cc577a4SJonathan Peyton   } else {
14407cc577a4SJonathan Peyton     /* Encapsulate in a loop as the documentation states that this may
14413041982dSJonathan Peyton        "with low probability" return when the condition variable has
14423041982dSJonathan Peyton        not been signaled or broadcast */
14437cc577a4SJonathan Peyton     int deactivated = FALSE;
14443041982dSJonathan Peyton 
14457cc577a4SJonathan Peyton     while (flag->is_sleeping()) {
14467cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND
14477cc577a4SJonathan Peyton       char buffer[128];
14487cc577a4SJonathan Peyton       __kmp_suspend_count++;
14497cc577a4SJonathan Peyton       __kmp_print_cond(buffer, &th->th.th_suspend_cv);
14503041982dSJonathan Peyton       __kmp_printf("__kmp_suspend_template: suspending T#%d: %s\n", th_gtid,
14513041982dSJonathan Peyton                    buffer);
14527cc577a4SJonathan Peyton #endif
14533041982dSJonathan Peyton       // Mark the thread as no longer active (only in the first iteration of the
14543041982dSJonathan Peyton       // loop).
14557cc577a4SJonathan Peyton       if (!deactivated) {
14567cc577a4SJonathan Peyton         th->th.th_active = FALSE;
14577cc577a4SJonathan Peyton         if (th->th.th_active_in_pool) {
14587cc577a4SJonathan Peyton           th->th.th_active_in_pool = FALSE;
145937e2ef54SJonathan Peyton           KMP_ATOMIC_DEC(&__kmp_thread_pool_active_nth);
14607cc577a4SJonathan Peyton           KMP_DEBUG_ASSERT(TCR_4(__kmp_thread_pool_active_nth) >= 0);
14617cc577a4SJonathan Peyton         }
14627cc577a4SJonathan Peyton         deactivated = TRUE;
14637cc577a4SJonathan Peyton       }
14647cc577a4SJonathan Peyton 
1465d8e4cb91STerry Wilmarth       KMP_DEBUG_ASSERT(th->th.th_sleep_loc);
1466d8e4cb91STerry Wilmarth       KMP_DEBUG_ASSERT(flag->get_type() == th->th.th_sleep_loc_type);
1467d8e4cb91STerry Wilmarth 
14687cc577a4SJonathan Peyton #if USE_SUSPEND_TIMEOUT
14697cc577a4SJonathan Peyton       struct timespec now;
14707cc577a4SJonathan Peyton       struct timeval tval;
14717cc577a4SJonathan Peyton       int msecs;
14727cc577a4SJonathan Peyton 
14737cc577a4SJonathan Peyton       status = gettimeofday(&tval, NULL);
14747cc577a4SJonathan Peyton       KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
14757cc577a4SJonathan Peyton       TIMEVAL_TO_TIMESPEC(&tval, &now);
14767cc577a4SJonathan Peyton 
14777cc577a4SJonathan Peyton       msecs = (4 * __kmp_dflt_blocktime) + 200;
14787cc577a4SJonathan Peyton       now.tv_sec += msecs / 1000;
14797cc577a4SJonathan Peyton       now.tv_nsec += (msecs % 1000) * 1000;
14807cc577a4SJonathan Peyton 
14813041982dSJonathan Peyton       KF_TRACE(15, ("__kmp_suspend_template: T#%d about to perform "
14823041982dSJonathan Peyton                     "pthread_cond_timedwait\n",
14837cc577a4SJonathan Peyton                     th_gtid));
14843041982dSJonathan Peyton       status = pthread_cond_timedwait(&th->th.th_suspend_cv.c_cond,
14853041982dSJonathan Peyton                                       &th->th.th_suspend_mx.m_mutex, &now);
14867cc577a4SJonathan Peyton #else
14873041982dSJonathan Peyton       KF_TRACE(15, ("__kmp_suspend_template: T#%d about to perform"
14883041982dSJonathan Peyton                     " pthread_cond_wait\n",
14897cc577a4SJonathan Peyton                     th_gtid));
14903041982dSJonathan Peyton       status = pthread_cond_wait(&th->th.th_suspend_cv.c_cond,
14913041982dSJonathan Peyton                                  &th->th.th_suspend_mx.m_mutex);
1492e0665a90STerry Wilmarth #endif // USE_SUSPEND_TIMEOUT
14937cc577a4SJonathan Peyton 
14947cc577a4SJonathan Peyton       if ((status != 0) && (status != EINTR) && (status != ETIMEDOUT)) {
14957cc577a4SJonathan Peyton         KMP_SYSFAIL("pthread_cond_wait", status);
14967cc577a4SJonathan Peyton       }
1497d8e4cb91STerry Wilmarth 
1498d8e4cb91STerry Wilmarth       KMP_DEBUG_ASSERT(flag->get_type() == flag->get_ptr_type());
1499d8e4cb91STerry Wilmarth 
1500d8e4cb91STerry Wilmarth       if (!flag->is_sleeping() &&
1501d8e4cb91STerry Wilmarth           ((status == EINTR) || (status == ETIMEDOUT))) {
1502d8e4cb91STerry Wilmarth         // if interrupt or timeout, and thread is no longer sleeping, we need to
1503d8e4cb91STerry Wilmarth         // make sure sleep_loc gets reset; however, this shouldn't be needed if
1504d8e4cb91STerry Wilmarth         // we woke up with resume
1505d8e4cb91STerry Wilmarth         flag->unset_sleeping();
1506d8e4cb91STerry Wilmarth         TCW_PTR(th->th.th_sleep_loc, NULL);
1507d8e4cb91STerry Wilmarth         th->th.th_sleep_loc_type = flag_unset;
1508d8e4cb91STerry Wilmarth       }
15097cc577a4SJonathan Peyton #ifdef KMP_DEBUG
15107cc577a4SJonathan Peyton       if (status == ETIMEDOUT) {
15117cc577a4SJonathan Peyton         if (flag->is_sleeping()) {
15123041982dSJonathan Peyton           KF_TRACE(100,
15133041982dSJonathan Peyton                    ("__kmp_suspend_template: T#%d timeout wakeup\n", th_gtid));
15147cc577a4SJonathan Peyton         } else {
15153041982dSJonathan Peyton           KF_TRACE(2, ("__kmp_suspend_template: T#%d timeout wakeup, sleep bit "
15163041982dSJonathan Peyton                        "not set!\n",
15177cc577a4SJonathan Peyton                        th_gtid));
1518d8e4cb91STerry Wilmarth           TCW_PTR(th->th.th_sleep_loc, NULL);
1519d8e4cb91STerry Wilmarth           th->th.th_sleep_loc_type = flag_unset;
15207cc577a4SJonathan Peyton         }
15217cc577a4SJonathan Peyton       } else if (flag->is_sleeping()) {
15223041982dSJonathan Peyton         KF_TRACE(100,
15233041982dSJonathan Peyton                  ("__kmp_suspend_template: T#%d spurious wakeup\n", th_gtid));
15247cc577a4SJonathan Peyton       }
15257cc577a4SJonathan Peyton #endif
15267cc577a4SJonathan Peyton     } // while
15277cc577a4SJonathan Peyton 
15287cc577a4SJonathan Peyton     // Mark the thread as active again (if it was previous marked as inactive)
15297cc577a4SJonathan Peyton     if (deactivated) {
15307cc577a4SJonathan Peyton       th->th.th_active = TRUE;
15317cc577a4SJonathan Peyton       if (TCR_4(th->th.th_in_pool)) {
153237e2ef54SJonathan Peyton         KMP_ATOMIC_INC(&__kmp_thread_pool_active_nth);
15337cc577a4SJonathan Peyton         th->th.th_active_in_pool = TRUE;
15347cc577a4SJonathan Peyton       }
15357cc577a4SJonathan Peyton     }
15367cc577a4SJonathan Peyton   }
1537d8e4cb91STerry Wilmarth   // We may have had the loop variable set before entering the loop body;
1538d8e4cb91STerry Wilmarth   // so we need to reset sleep_loc.
1539d8e4cb91STerry Wilmarth   TCW_PTR(th->th.th_sleep_loc, NULL);
1540d8e4cb91STerry Wilmarth   th->th.th_sleep_loc_type = flag_unset;
1541d8e4cb91STerry Wilmarth 
1542d8e4cb91STerry Wilmarth   KMP_DEBUG_ASSERT(!flag->is_sleeping());
1543d8e4cb91STerry Wilmarth   KMP_DEBUG_ASSERT(!th->th.th_sleep_loc);
15447cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND
15457cc577a4SJonathan Peyton   {
15467cc577a4SJonathan Peyton     char buffer[128];
15477cc577a4SJonathan Peyton     __kmp_print_cond(buffer, &th->th.th_suspend_cv);
15483041982dSJonathan Peyton     __kmp_printf("__kmp_suspend_template: T#%d has awakened: %s\n", th_gtid,
15493041982dSJonathan Peyton                  buffer);
15507cc577a4SJonathan Peyton   }
15517cc577a4SJonathan Peyton #endif
15527cc577a4SJonathan Peyton 
1553e0665a90STerry Wilmarth   __kmp_unlock_suspend_mx(th);
15547cc577a4SJonathan Peyton   KF_TRACE(30, ("__kmp_suspend_template: T#%d exit\n", th_gtid));
15557cc577a4SJonathan Peyton }
15567cc577a4SJonathan Peyton 
1557e0665a90STerry Wilmarth template <bool C, bool S>
__kmp_suspend_32(int th_gtid,kmp_flag_32<C,S> * flag)1558e0665a90STerry Wilmarth void __kmp_suspend_32(int th_gtid, kmp_flag_32<C, S> *flag) {
15597cc577a4SJonathan Peyton   __kmp_suspend_template(th_gtid, flag);
15607cc577a4SJonathan Peyton }
1561e0665a90STerry Wilmarth template <bool C, bool S>
__kmp_suspend_64(int th_gtid,kmp_flag_64<C,S> * flag)1562e0665a90STerry Wilmarth void __kmp_suspend_64(int th_gtid, kmp_flag_64<C, S> *flag) {
15637cc577a4SJonathan Peyton   __kmp_suspend_template(th_gtid, flag);
15647cc577a4SJonathan Peyton }
1565d8e4cb91STerry Wilmarth template <bool C, bool S>
__kmp_atomic_suspend_64(int th_gtid,kmp_atomic_flag_64<C,S> * flag)1566d8e4cb91STerry Wilmarth void __kmp_atomic_suspend_64(int th_gtid, kmp_atomic_flag_64<C, S> *flag) {
1567d8e4cb91STerry Wilmarth   __kmp_suspend_template(th_gtid, flag);
1568d8e4cb91STerry Wilmarth }
__kmp_suspend_oncore(int th_gtid,kmp_flag_oncore * flag)15697cc577a4SJonathan Peyton void __kmp_suspend_oncore(int th_gtid, kmp_flag_oncore *flag) {
15707cc577a4SJonathan Peyton   __kmp_suspend_template(th_gtid, flag);
15717cc577a4SJonathan Peyton }
15727cc577a4SJonathan Peyton 
1573e0665a90STerry Wilmarth template void __kmp_suspend_32<false, false>(int, kmp_flag_32<false, false> *);
1574e0665a90STerry Wilmarth template void __kmp_suspend_64<false, true>(int, kmp_flag_64<false, true> *);
1575e0665a90STerry Wilmarth template void __kmp_suspend_64<true, false>(int, kmp_flag_64<true, false> *);
1576d8e4cb91STerry Wilmarth template void
1577d8e4cb91STerry Wilmarth __kmp_atomic_suspend_64<false, true>(int, kmp_atomic_flag_64<false, true> *);
1578d8e4cb91STerry Wilmarth template void
1579d8e4cb91STerry Wilmarth __kmp_atomic_suspend_64<true, false>(int, kmp_atomic_flag_64<true, false> *);
1580e0665a90STerry Wilmarth 
15817cc577a4SJonathan Peyton /* This routine signals the thread specified by target_gtid to wake up
15823041982dSJonathan Peyton    after setting the sleep bit indicated by the flag argument to FALSE.
15833041982dSJonathan Peyton    The target thread must already have called __kmp_suspend_template() */
15847cc577a4SJonathan Peyton template <class C>
__kmp_resume_template(int target_gtid,C * flag)15853041982dSJonathan Peyton static inline void __kmp_resume_template(int target_gtid, C *flag) {
15867cc577a4SJonathan Peyton   KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_resume);
15877cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[target_gtid];
15887cc577a4SJonathan Peyton   int status;
15897cc577a4SJonathan Peyton 
15907cc577a4SJonathan Peyton #ifdef KMP_DEBUG
15917cc577a4SJonathan Peyton   int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
15927cc577a4SJonathan Peyton #endif
15937cc577a4SJonathan Peyton 
15943041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_resume_template: T#%d wants to wakeup T#%d enter\n",
15953041982dSJonathan Peyton                 gtid, target_gtid));
15967cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(gtid != target_gtid);
15977cc577a4SJonathan Peyton 
15987cc577a4SJonathan Peyton   __kmp_suspend_initialize_thread(th);
15995644f734SAndreyChurbanov 
1600e0665a90STerry Wilmarth   __kmp_lock_suspend_mx(th);
16017cc577a4SJonathan Peyton 
1602d8e4cb91STerry Wilmarth   if (!flag || flag != th->th.th_sleep_loc) {
1603d8e4cb91STerry Wilmarth     // coming from __kmp_null_resume_wrapper, or thread is now sleeping on a
1604d8e4cb91STerry Wilmarth     // different location; wake up at new location
1605c47afcd9SAndrey Churbanov     flag = (C *)CCAST(void *, th->th.th_sleep_loc);
16067cc577a4SJonathan Peyton   }
16077cc577a4SJonathan Peyton 
16083041982dSJonathan Peyton   // First, check if the flag is null or its type has changed. If so, someone
16093041982dSJonathan Peyton   // else woke it up.
1610d8e4cb91STerry Wilmarth   if (!flag) { // Thread doesn't appear to be sleeping on anything
16113041982dSJonathan Peyton     KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already "
16123041982dSJonathan Peyton                  "awake: flag(%p)\n",
1613d8e4cb91STerry Wilmarth                  gtid, target_gtid, (void *)NULL));
1614e0665a90STerry Wilmarth     __kmp_unlock_suspend_mx(th);
16157cc577a4SJonathan Peyton     return;
1616d8e4cb91STerry Wilmarth   } else if (flag->get_type() != th->th.th_sleep_loc_type) {
1617d8e4cb91STerry Wilmarth     // Flag type does not appear to match this function template; possibly the
1618d8e4cb91STerry Wilmarth     // thread is sleeping on something else. Try null resume again.
1619d8e4cb91STerry Wilmarth     KF_TRACE(
1620d8e4cb91STerry Wilmarth         5,
1621d8e4cb91STerry Wilmarth         ("__kmp_resume_template: T#%d retrying, thread T#%d Mismatch flag(%p), "
1622d8e4cb91STerry Wilmarth          "spin(%p) type=%d ptr_type=%d\n",
1623d8e4cb91STerry Wilmarth          gtid, target_gtid, flag, flag->get(), flag->get_type(),
1624d8e4cb91STerry Wilmarth          th->th.th_sleep_loc_type));
1625d8e4cb91STerry Wilmarth     __kmp_unlock_suspend_mx(th);
1626d8e4cb91STerry Wilmarth     __kmp_null_resume_wrapper(th);
1627d8e4cb91STerry Wilmarth     return;
16283041982dSJonathan Peyton   } else { // if multiple threads are sleeping, flag should be internally
16293041982dSJonathan Peyton     // referring to a specific thread here
1630d8e4cb91STerry Wilmarth     if (!flag->is_sleeping()) {
16313041982dSJonathan Peyton       KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already "
1632d8e4cb91STerry Wilmarth                    "awake: flag(%p): %u\n",
1633d8e4cb91STerry Wilmarth                    gtid, target_gtid, flag->get(), (unsigned int)flag->load()));
1634e0665a90STerry Wilmarth       __kmp_unlock_suspend_mx(th);
16357cc577a4SJonathan Peyton       return;
16367cc577a4SJonathan Peyton     }
16374eb90e89SJohannes Doerfert   }
1638d8e4cb91STerry Wilmarth   KMP_DEBUG_ASSERT(flag);
1639d8e4cb91STerry Wilmarth   flag->unset_sleeping();
16404eb90e89SJohannes Doerfert   TCW_PTR(th->th.th_sleep_loc, NULL);
1641d8e4cb91STerry Wilmarth   th->th.th_sleep_loc_type = flag_unset;
1642d8e4cb91STerry Wilmarth 
1643d8e4cb91STerry Wilmarth   KF_TRACE(5, ("__kmp_resume_template: T#%d about to wakeup T#%d, reset "
1644d8e4cb91STerry Wilmarth                "sleep bit for flag's loc(%p): %u\n",
1645d8e4cb91STerry Wilmarth                gtid, target_gtid, flag->get(), (unsigned int)flag->load()));
16467cc577a4SJonathan Peyton 
16477cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND
16487cc577a4SJonathan Peyton   {
16497cc577a4SJonathan Peyton     char buffer[128];
16507cc577a4SJonathan Peyton     __kmp_print_cond(buffer, &th->th.th_suspend_cv);
16513041982dSJonathan Peyton     __kmp_printf("__kmp_resume_template: T#%d resuming T#%d: %s\n", gtid,
16523041982dSJonathan Peyton                  target_gtid, buffer);
16537cc577a4SJonathan Peyton   }
16547cc577a4SJonathan Peyton #endif
16557cc577a4SJonathan Peyton   status = pthread_cond_signal(&th->th.th_suspend_cv.c_cond);
16567cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_cond_signal", status);
1657e0665a90STerry Wilmarth   __kmp_unlock_suspend_mx(th);
16583041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_resume_template: T#%d exiting after signaling wake up"
16593041982dSJonathan Peyton                 " for T#%d\n",
16607cc577a4SJonathan Peyton                 gtid, target_gtid));
16617cc577a4SJonathan Peyton }
16627cc577a4SJonathan Peyton 
1663e0665a90STerry Wilmarth template <bool C, bool S>
__kmp_resume_32(int target_gtid,kmp_flag_32<C,S> * flag)1664e0665a90STerry Wilmarth void __kmp_resume_32(int target_gtid, kmp_flag_32<C, S> *flag) {
16657cc577a4SJonathan Peyton   __kmp_resume_template(target_gtid, flag);
16667cc577a4SJonathan Peyton }
1667e0665a90STerry Wilmarth template <bool C, bool S>
__kmp_resume_64(int target_gtid,kmp_flag_64<C,S> * flag)1668e0665a90STerry Wilmarth void __kmp_resume_64(int target_gtid, kmp_flag_64<C, S> *flag) {
16697cc577a4SJonathan Peyton   __kmp_resume_template(target_gtid, flag);
16707cc577a4SJonathan Peyton }
1671d8e4cb91STerry Wilmarth template <bool C, bool S>
__kmp_atomic_resume_64(int target_gtid,kmp_atomic_flag_64<C,S> * flag)1672d8e4cb91STerry Wilmarth void __kmp_atomic_resume_64(int target_gtid, kmp_atomic_flag_64<C, S> *flag) {
1673d8e4cb91STerry Wilmarth   __kmp_resume_template(target_gtid, flag);
1674d8e4cb91STerry Wilmarth }
__kmp_resume_oncore(int target_gtid,kmp_flag_oncore * flag)16757cc577a4SJonathan Peyton void __kmp_resume_oncore(int target_gtid, kmp_flag_oncore *flag) {
16767cc577a4SJonathan Peyton   __kmp_resume_template(target_gtid, flag);
16777cc577a4SJonathan Peyton }
16787cc577a4SJonathan Peyton 
1679e0665a90STerry Wilmarth template void __kmp_resume_32<false, true>(int, kmp_flag_32<false, true> *);
1680d8e4cb91STerry Wilmarth template void __kmp_resume_32<false, false>(int, kmp_flag_32<false, false> *);
1681e0665a90STerry Wilmarth template void __kmp_resume_64<false, true>(int, kmp_flag_64<false, true> *);
1682d8e4cb91STerry Wilmarth template void
1683d8e4cb91STerry Wilmarth __kmp_atomic_resume_64<false, true>(int, kmp_atomic_flag_64<false, true> *);
1684e0665a90STerry Wilmarth 
16857cc577a4SJonathan Peyton #if KMP_USE_MONITOR
__kmp_resume_monitor()16863041982dSJonathan Peyton void __kmp_resume_monitor() {
16877cc577a4SJonathan Peyton   KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_resume);
16887cc577a4SJonathan Peyton   int status;
16897cc577a4SJonathan Peyton #ifdef KMP_DEBUG
16907cc577a4SJonathan Peyton   int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
16913041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_resume_monitor: T#%d wants to wakeup T#%d enter\n", gtid,
16923041982dSJonathan Peyton                 KMP_GTID_MONITOR));
16937cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(gtid != KMP_GTID_MONITOR);
16947cc577a4SJonathan Peyton #endif
16957cc577a4SJonathan Peyton   status = pthread_mutex_lock(&__kmp_wait_mx.m_mutex);
16967cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
16977cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND
16987cc577a4SJonathan Peyton   {
16997cc577a4SJonathan Peyton     char buffer[128];
17007cc577a4SJonathan Peyton     __kmp_print_cond(buffer, &__kmp_wait_cv.c_cond);
17013041982dSJonathan Peyton     __kmp_printf("__kmp_resume_monitor: T#%d resuming T#%d: %s\n", gtid,
17023041982dSJonathan Peyton                  KMP_GTID_MONITOR, buffer);
17037cc577a4SJonathan Peyton   }
17047cc577a4SJonathan Peyton #endif
17057cc577a4SJonathan Peyton   status = pthread_cond_signal(&__kmp_wait_cv.c_cond);
17067cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_cond_signal", status);
17077cc577a4SJonathan Peyton   status = pthread_mutex_unlock(&__kmp_wait_mx.m_mutex);
17087cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
17093041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_resume_monitor: T#%d exiting after signaling wake up"
17103041982dSJonathan Peyton                 " for T#%d\n",
17117cc577a4SJonathan Peyton                 gtid, KMP_GTID_MONITOR));
17127cc577a4SJonathan Peyton }
17137cc577a4SJonathan Peyton #endif // KMP_USE_MONITOR
17147cc577a4SJonathan Peyton 
__kmp_yield()1715e47d32f1SJonathan Peyton void __kmp_yield() { sched_yield(); }
17167cc577a4SJonathan Peyton 
__kmp_gtid_set_specific(int gtid)17173041982dSJonathan Peyton void __kmp_gtid_set_specific(int gtid) {
17187cc577a4SJonathan Peyton   if (__kmp_init_gtid) {
17197cc577a4SJonathan Peyton     int status;
17203041982dSJonathan Peyton     status = pthread_setspecific(__kmp_gtid_threadprivate_key,
17213041982dSJonathan Peyton                                  (void *)(intptr_t)(gtid + 1));
17227cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_setspecific", status);
17237cc577a4SJonathan Peyton   } else {
17247cc577a4SJonathan Peyton     KA_TRACE(50, ("__kmp_gtid_set_specific: runtime shutdown, returning\n"));
17257cc577a4SJonathan Peyton   }
17267cc577a4SJonathan Peyton }
17277cc577a4SJonathan Peyton 
__kmp_gtid_get_specific()17283041982dSJonathan Peyton int __kmp_gtid_get_specific() {
17297cc577a4SJonathan Peyton   int gtid;
17307cc577a4SJonathan Peyton   if (!__kmp_init_gtid) {
17313041982dSJonathan Peyton     KA_TRACE(50, ("__kmp_gtid_get_specific: runtime shutdown, returning "
17323041982dSJonathan Peyton                   "KMP_GTID_SHUTDOWN\n"));
17337cc577a4SJonathan Peyton     return KMP_GTID_SHUTDOWN;
17347cc577a4SJonathan Peyton   }
17357cc577a4SJonathan Peyton   gtid = (int)(size_t)pthread_getspecific(__kmp_gtid_threadprivate_key);
17367cc577a4SJonathan Peyton   if (gtid == 0) {
17377cc577a4SJonathan Peyton     gtid = KMP_GTID_DNE;
17383041982dSJonathan Peyton   } else {
17397cc577a4SJonathan Peyton     gtid--;
17407cc577a4SJonathan Peyton   }
17417cc577a4SJonathan Peyton   KA_TRACE(50, ("__kmp_gtid_get_specific: key:%d gtid:%d\n",
17427cc577a4SJonathan Peyton                 __kmp_gtid_threadprivate_key, gtid));
17437cc577a4SJonathan Peyton   return gtid;
17447cc577a4SJonathan Peyton }
17457cc577a4SJonathan Peyton 
__kmp_read_cpu_time(void)17463041982dSJonathan Peyton double __kmp_read_cpu_time(void) {
17477cc577a4SJonathan Peyton   /*clock_t   t;*/
17487cc577a4SJonathan Peyton   struct tms buffer;
17497cc577a4SJonathan Peyton 
17507cc577a4SJonathan Peyton   /*t =*/times(&buffer);
17517cc577a4SJonathan Peyton 
17526b316febSTerry Wilmarth   return (double)(buffer.tms_utime + buffer.tms_cutime) /
17536b316febSTerry Wilmarth          (double)CLOCKS_PER_SEC;
17547cc577a4SJonathan Peyton }
17557cc577a4SJonathan Peyton 
__kmp_read_system_info(struct kmp_sys_info * info)17563041982dSJonathan Peyton int __kmp_read_system_info(struct kmp_sys_info *info) {
17577cc577a4SJonathan Peyton   int status;
17587cc577a4SJonathan Peyton   struct rusage r_usage;
17597cc577a4SJonathan Peyton 
17607cc577a4SJonathan Peyton   memset(info, 0, sizeof(*info));
17617cc577a4SJonathan Peyton 
17627cc577a4SJonathan Peyton   status = getrusage(RUSAGE_SELF, &r_usage);
17637cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("getrusage", status);
17647cc577a4SJonathan Peyton 
17653041982dSJonathan Peyton   // The maximum resident set size utilized (in kilobytes)
17663041982dSJonathan Peyton   info->maxrss = r_usage.ru_maxrss;
17673041982dSJonathan Peyton   // The number of page faults serviced without any I/O
17683041982dSJonathan Peyton   info->minflt = r_usage.ru_minflt;
17693041982dSJonathan Peyton   // The number of page faults serviced that required I/O
17703041982dSJonathan Peyton   info->majflt = r_usage.ru_majflt;
17713041982dSJonathan Peyton   // The number of times a process was "swapped" out of memory
17723041982dSJonathan Peyton   info->nswap = r_usage.ru_nswap;
17733041982dSJonathan Peyton   // The number of times the file system had to perform input
17743041982dSJonathan Peyton   info->inblock = r_usage.ru_inblock;
17753041982dSJonathan Peyton   // The number of times the file system had to perform output
17763041982dSJonathan Peyton   info->oublock = r_usage.ru_oublock;
17773041982dSJonathan Peyton   // The number of times a context switch was voluntarily
17783041982dSJonathan Peyton   info->nvcsw = r_usage.ru_nvcsw;
17793041982dSJonathan Peyton   // The number of times a context switch was forced
17803041982dSJonathan Peyton   info->nivcsw = r_usage.ru_nivcsw;
17817cc577a4SJonathan Peyton 
17827cc577a4SJonathan Peyton   return (status != 0);
17837cc577a4SJonathan Peyton }
17847cc577a4SJonathan Peyton 
__kmp_read_system_time(double * delta)17853041982dSJonathan Peyton void __kmp_read_system_time(double *delta) {
17867cc577a4SJonathan Peyton   double t_ns;
17877cc577a4SJonathan Peyton   struct timeval tval;
17887cc577a4SJonathan Peyton   struct timespec stop;
17897cc577a4SJonathan Peyton   int status;
17907cc577a4SJonathan Peyton 
17917cc577a4SJonathan Peyton   status = gettimeofday(&tval, NULL);
17927cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
17937cc577a4SJonathan Peyton   TIMEVAL_TO_TIMESPEC(&tval, &stop);
17946b316febSTerry Wilmarth   t_ns = (double)(TS2NS(stop) - TS2NS(__kmp_sys_timer_data.start));
17957cc577a4SJonathan Peyton   *delta = (t_ns * 1e-9);
17967cc577a4SJonathan Peyton }
17977cc577a4SJonathan Peyton 
__kmp_clear_system_time(void)17983041982dSJonathan Peyton void __kmp_clear_system_time(void) {
17997cc577a4SJonathan Peyton   struct timeval tval;
18007cc577a4SJonathan Peyton   int status;
18017cc577a4SJonathan Peyton   status = gettimeofday(&tval, NULL);
18027cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
18037cc577a4SJonathan Peyton   TIMEVAL_TO_TIMESPEC(&tval, &__kmp_sys_timer_data.start);
18047cc577a4SJonathan Peyton }
18057cc577a4SJonathan Peyton 
__kmp_get_xproc(void)18063041982dSJonathan Peyton static int __kmp_get_xproc(void) {
18077cc577a4SJonathan Peyton 
18087cc577a4SJonathan Peyton   int r = 0;
18097cc577a4SJonathan Peyton 
18101dd79716SPeyton, Jonathan L #if KMP_OS_LINUX
18111dd79716SPeyton, Jonathan L 
18121dd79716SPeyton, Jonathan L   __kmp_type_convert(sysconf(_SC_NPROCESSORS_CONF), &(r));
18131dd79716SPeyton, Jonathan L 
18141dd79716SPeyton, Jonathan L #elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_OPENBSD || \
18151dd79716SPeyton, Jonathan L     KMP_OS_HURD
18167cc577a4SJonathan Peyton 
18176b316febSTerry Wilmarth   __kmp_type_convert(sysconf(_SC_NPROCESSORS_ONLN), &(r));
18187cc577a4SJonathan Peyton 
18197cc577a4SJonathan Peyton #elif KMP_OS_DARWIN
18207cc577a4SJonathan Peyton 
18217cc577a4SJonathan Peyton   // Bug C77011 High "OpenMP Threads and number of active cores".
18227cc577a4SJonathan Peyton 
18237cc577a4SJonathan Peyton   // Find the number of available CPUs.
18247cc577a4SJonathan Peyton   kern_return_t rc;
18257cc577a4SJonathan Peyton   host_basic_info_data_t info;
18267cc577a4SJonathan Peyton   mach_msg_type_number_t num = HOST_BASIC_INFO_COUNT;
18277cc577a4SJonathan Peyton   rc = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&info, &num);
18287cc577a4SJonathan Peyton   if (rc == 0 && num == HOST_BASIC_INFO_COUNT) {
1829c47afcd9SAndrey Churbanov     // Cannot use KA_TRACE() here because this code works before trace support
1830c47afcd9SAndrey Churbanov     // is initialized.
18317cc577a4SJonathan Peyton     r = info.avail_cpus;
18327cc577a4SJonathan Peyton   } else {
18337cc577a4SJonathan Peyton     KMP_WARNING(CantGetNumAvailCPU);
18347cc577a4SJonathan Peyton     KMP_INFORM(AssumedNumCPU);
1835bd3a7633SJonathan Peyton   }
18367cc577a4SJonathan Peyton 
18377cc577a4SJonathan Peyton #else
18387cc577a4SJonathan Peyton 
18397cc577a4SJonathan Peyton #error "Unknown or unsupported OS."
18407cc577a4SJonathan Peyton 
18417cc577a4SJonathan Peyton #endif
18427cc577a4SJonathan Peyton 
18437cc577a4SJonathan Peyton   return r > 0 ? r : 2; /* guess value of 2 if OS told us 0 */
18447cc577a4SJonathan Peyton 
18457cc577a4SJonathan Peyton } // __kmp_get_xproc
18467cc577a4SJonathan Peyton 
__kmp_read_from_file(char const * path,char const * format,...)18473041982dSJonathan Peyton int __kmp_read_from_file(char const *path, char const *format, ...) {
18487cc577a4SJonathan Peyton   int result;
18497cc577a4SJonathan Peyton   va_list args;
18507cc577a4SJonathan Peyton 
18517cc577a4SJonathan Peyton   va_start(args, format);
18527cc577a4SJonathan Peyton   FILE *f = fopen(path, "rb");
18537cc577a4SJonathan Peyton   if (f == NULL)
18547cc577a4SJonathan Peyton     return 0;
18557cc577a4SJonathan Peyton   result = vfscanf(f, format, args);
18567cc577a4SJonathan Peyton   fclose(f);
18577cc577a4SJonathan Peyton 
18587cc577a4SJonathan Peyton   return result;
18597cc577a4SJonathan Peyton }
18607cc577a4SJonathan Peyton 
__kmp_runtime_initialize(void)18613041982dSJonathan Peyton void __kmp_runtime_initialize(void) {
18627cc577a4SJonathan Peyton   int status;
18637cc577a4SJonathan Peyton   pthread_mutexattr_t mutex_attr;
18647cc577a4SJonathan Peyton   pthread_condattr_t cond_attr;
18657cc577a4SJonathan Peyton 
18667cc577a4SJonathan Peyton   if (__kmp_init_runtime) {
18677cc577a4SJonathan Peyton     return;
1868bd3a7633SJonathan Peyton   }
18697cc577a4SJonathan Peyton 
18707cc577a4SJonathan Peyton #if (KMP_ARCH_X86 || KMP_ARCH_X86_64)
18717cc577a4SJonathan Peyton   if (!__kmp_cpuinfo.initialized) {
18727cc577a4SJonathan Peyton     __kmp_query_cpuid(&__kmp_cpuinfo);
1873bd3a7633SJonathan Peyton   }
18747cc577a4SJonathan Peyton #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
18757cc577a4SJonathan Peyton 
18767cc577a4SJonathan Peyton   __kmp_xproc = __kmp_get_xproc();
18777cc577a4SJonathan Peyton 
1878d47f5488SAndrey Churbanov #if !KMP_32_BIT_ARCH
1879d47f5488SAndrey Churbanov   struct rlimit rlim;
1880d47f5488SAndrey Churbanov   // read stack size of calling thread, save it as default for worker threads;
1881d47f5488SAndrey Churbanov   // this should be done before reading environment variables
1882d47f5488SAndrey Churbanov   status = getrlimit(RLIMIT_STACK, &rlim);
1883d47f5488SAndrey Churbanov   if (status == 0) { // success?
1884d47f5488SAndrey Churbanov     __kmp_stksize = rlim.rlim_cur;
1885d47f5488SAndrey Churbanov     __kmp_check_stksize(&__kmp_stksize); // check value and adjust if needed
1886d47f5488SAndrey Churbanov   }
1887d47f5488SAndrey Churbanov #endif /* KMP_32_BIT_ARCH */
1888d47f5488SAndrey Churbanov 
18897cc577a4SJonathan Peyton   if (sysconf(_SC_THREADS)) {
18907cc577a4SJonathan Peyton 
18917cc577a4SJonathan Peyton     /* Query the maximum number of threads */
18926b316febSTerry Wilmarth     __kmp_type_convert(sysconf(_SC_THREAD_THREADS_MAX), &(__kmp_sys_max_nth));
18937cc577a4SJonathan Peyton     if (__kmp_sys_max_nth == -1) {
18947cc577a4SJonathan Peyton       /* Unlimited threads for NPTL */
18957cc577a4SJonathan Peyton       __kmp_sys_max_nth = INT_MAX;
18963041982dSJonathan Peyton     } else if (__kmp_sys_max_nth <= 1) {
18977cc577a4SJonathan Peyton       /* Can't tell, just use PTHREAD_THREADS_MAX */
18987cc577a4SJonathan Peyton       __kmp_sys_max_nth = KMP_MAX_NTH;
18997cc577a4SJonathan Peyton     }
19007cc577a4SJonathan Peyton 
19017cc577a4SJonathan Peyton     /* Query the minimum stack size */
19027cc577a4SJonathan Peyton     __kmp_sys_min_stksize = sysconf(_SC_THREAD_STACK_MIN);
19037cc577a4SJonathan Peyton     if (__kmp_sys_min_stksize <= 1) {
19047cc577a4SJonathan Peyton       __kmp_sys_min_stksize = KMP_MIN_STKSIZE;
19057cc577a4SJonathan Peyton     }
19067cc577a4SJonathan Peyton   }
19077cc577a4SJonathan Peyton 
19087cc577a4SJonathan Peyton   /* Set up minimum number of threads to switch to TLS gtid */
19097cc577a4SJonathan Peyton   __kmp_tls_gtid_min = KMP_TLS_GTID_MIN;
19107cc577a4SJonathan Peyton 
19113041982dSJonathan Peyton   status = pthread_key_create(&__kmp_gtid_threadprivate_key,
19123041982dSJonathan Peyton                               __kmp_internal_end_dest);
19137cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_key_create", status);
19147cc577a4SJonathan Peyton   status = pthread_mutexattr_init(&mutex_attr);
19157cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutexattr_init", status);
19167cc577a4SJonathan Peyton   status = pthread_mutex_init(&__kmp_wait_mx.m_mutex, &mutex_attr);
19177cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
19181611e547SAndreyChurbanov   status = pthread_mutexattr_destroy(&mutex_attr);
19191611e547SAndreyChurbanov   KMP_CHECK_SYSFAIL("pthread_mutexattr_destroy", status);
19207cc577a4SJonathan Peyton   status = pthread_condattr_init(&cond_attr);
19217cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_condattr_init", status);
19227cc577a4SJonathan Peyton   status = pthread_cond_init(&__kmp_wait_cv.c_cond, &cond_attr);
19237cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
19241611e547SAndreyChurbanov   status = pthread_condattr_destroy(&cond_attr);
19251611e547SAndreyChurbanov   KMP_CHECK_SYSFAIL("pthread_condattr_destroy", status);
19267cc577a4SJonathan Peyton #if USE_ITT_BUILD
19277cc577a4SJonathan Peyton   __kmp_itt_initialize();
19287cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
19297cc577a4SJonathan Peyton 
19307cc577a4SJonathan Peyton   __kmp_init_runtime = TRUE;
19317cc577a4SJonathan Peyton }
19327cc577a4SJonathan Peyton 
__kmp_runtime_destroy(void)19333041982dSJonathan Peyton void __kmp_runtime_destroy(void) {
19347cc577a4SJonathan Peyton   int status;
19357cc577a4SJonathan Peyton 
19367cc577a4SJonathan Peyton   if (!__kmp_init_runtime) {
19377cc577a4SJonathan Peyton     return; // Nothing to do.
1938bd3a7633SJonathan Peyton   }
19397cc577a4SJonathan Peyton 
19407cc577a4SJonathan Peyton #if USE_ITT_BUILD
19417cc577a4SJonathan Peyton   __kmp_itt_destroy();
19427cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
19437cc577a4SJonathan Peyton 
19447cc577a4SJonathan Peyton   status = pthread_key_delete(__kmp_gtid_threadprivate_key);
19457cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_key_delete", status);
19467cc577a4SJonathan Peyton 
19477cc577a4SJonathan Peyton   status = pthread_mutex_destroy(&__kmp_wait_mx.m_mutex);
19487cc577a4SJonathan Peyton   if (status != 0 && status != EBUSY) {
19497cc577a4SJonathan Peyton     KMP_SYSFAIL("pthread_mutex_destroy", status);
19507cc577a4SJonathan Peyton   }
19517cc577a4SJonathan Peyton   status = pthread_cond_destroy(&__kmp_wait_cv.c_cond);
19527cc577a4SJonathan Peyton   if (status != 0 && status != EBUSY) {
19537cc577a4SJonathan Peyton     KMP_SYSFAIL("pthread_cond_destroy", status);
19547cc577a4SJonathan Peyton   }
19557cc577a4SJonathan Peyton #if KMP_AFFINITY_SUPPORTED
19567cc577a4SJonathan Peyton   __kmp_affinity_uninitialize();
19577cc577a4SJonathan Peyton #endif
19587cc577a4SJonathan Peyton 
19597cc577a4SJonathan Peyton   __kmp_init_runtime = FALSE;
19607cc577a4SJonathan Peyton }
19617cc577a4SJonathan Peyton 
19627cc577a4SJonathan Peyton /* Put the thread to sleep for a time period */
19637cc577a4SJonathan Peyton /* NOTE: not currently used anywhere */
__kmp_thread_sleep(int millis)19643041982dSJonathan Peyton void __kmp_thread_sleep(int millis) { sleep((millis + 500) / 1000); }
19657cc577a4SJonathan Peyton 
19667cc577a4SJonathan Peyton /* Calculate the elapsed wall clock time for the user */
__kmp_elapsed(double * t)19673041982dSJonathan Peyton void __kmp_elapsed(double *t) {
19687cc577a4SJonathan Peyton   int status;
19697cc577a4SJonathan Peyton #ifdef FIX_SGI_CLOCK
19707cc577a4SJonathan Peyton   struct timespec ts;
19717cc577a4SJonathan Peyton 
19727cc577a4SJonathan Peyton   status = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
19737cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("clock_gettime", status);
19743041982dSJonathan Peyton   *t =
19753041982dSJonathan Peyton       (double)ts.tv_nsec * (1.0 / (double)KMP_NSEC_PER_SEC) + (double)ts.tv_sec;
19767cc577a4SJonathan Peyton #else
19777cc577a4SJonathan Peyton   struct timeval tv;
19787cc577a4SJonathan Peyton 
19797cc577a4SJonathan Peyton   status = gettimeofday(&tv, NULL);
19807cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
19813041982dSJonathan Peyton   *t =
19823041982dSJonathan Peyton       (double)tv.tv_usec * (1.0 / (double)KMP_USEC_PER_SEC) + (double)tv.tv_sec;
19837cc577a4SJonathan Peyton #endif
19847cc577a4SJonathan Peyton }
19857cc577a4SJonathan Peyton 
19867cc577a4SJonathan Peyton /* Calculate the elapsed wall clock tick for the user */
__kmp_elapsed_tick(double * t)19873041982dSJonathan Peyton void __kmp_elapsed_tick(double *t) { *t = 1 / (double)CLOCKS_PER_SEC; }
19887cc577a4SJonathan Peyton 
19897cc577a4SJonathan Peyton /* Return the current time stamp in nsec */
__kmp_now_nsec()19903041982dSJonathan Peyton kmp_uint64 __kmp_now_nsec() {
19917cc577a4SJonathan Peyton   struct timeval t;
19927cc577a4SJonathan Peyton   gettimeofday(&t, NULL);
1993bdb0a2ffSJonathan Peyton   kmp_uint64 nsec = (kmp_uint64)KMP_NSEC_PER_SEC * (kmp_uint64)t.tv_sec +
1994bdb0a2ffSJonathan Peyton                     (kmp_uint64)1000 * (kmp_uint64)t.tv_usec;
1995bdb0a2ffSJonathan Peyton   return nsec;
19967cc577a4SJonathan Peyton }
19977cc577a4SJonathan Peyton 
19987cc577a4SJonathan Peyton #if KMP_ARCH_X86 || KMP_ARCH_X86_64
199935d75aedSJonathan Peyton /* Measure clock ticks per millisecond */
__kmp_initialize_system_tick()20003041982dSJonathan Peyton void __kmp_initialize_system_tick() {
2001bdb0a2ffSJonathan Peyton   kmp_uint64 now, nsec2, diff;
20027cc577a4SJonathan Peyton   kmp_uint64 delay = 100000; // 50~100 usec on most machines.
20037cc577a4SJonathan Peyton   kmp_uint64 nsec = __kmp_now_nsec();
20047cc577a4SJonathan Peyton   kmp_uint64 goal = __kmp_hardware_timestamp() + delay;
20053041982dSJonathan Peyton   while ((now = __kmp_hardware_timestamp()) < goal)
20063041982dSJonathan Peyton     ;
2007bdb0a2ffSJonathan Peyton   nsec2 = __kmp_now_nsec();
2008bdb0a2ffSJonathan Peyton   diff = nsec2 - nsec;
2009bdb0a2ffSJonathan Peyton   if (diff > 0) {
20106b316febSTerry Wilmarth     kmp_uint64 tpms = ((kmp_uint64)1e6 * (delay + (now - goal)) / diff);
2011bdb0a2ffSJonathan Peyton     if (tpms > 0)
2012bdb0a2ffSJonathan Peyton       __kmp_ticks_per_msec = tpms;
2013bdb0a2ffSJonathan Peyton   }
20147cc577a4SJonathan Peyton }
20157cc577a4SJonathan Peyton #endif
20167cc577a4SJonathan Peyton 
20173041982dSJonathan Peyton /* Determine whether the given address is mapped into the current address
20183041982dSJonathan Peyton    space. */
20197cc577a4SJonathan Peyton 
__kmp_is_address_mapped(void * addr)20203041982dSJonathan Peyton int __kmp_is_address_mapped(void *addr) {
20217cc577a4SJonathan Peyton 
20227cc577a4SJonathan Peyton   int found = 0;
20237cc577a4SJonathan Peyton   int rc;
20247cc577a4SJonathan Peyton 
2025fef62e1aSDavid Carlier #if KMP_OS_LINUX || KMP_OS_HURD
20267cc577a4SJonathan Peyton 
2027309b00a4SShilei Tian   /* On GNUish OSes, read the /proc/<pid>/maps pseudo-file to get all the
2028309b00a4SShilei Tian      address ranges mapped into the address space. */
20297cc577a4SJonathan Peyton 
20307cc577a4SJonathan Peyton   char *name = __kmp_str_format("/proc/%d/maps", getpid());
20317cc577a4SJonathan Peyton   FILE *file = NULL;
20327cc577a4SJonathan Peyton 
20337cc577a4SJonathan Peyton   file = fopen(name, "r");
20347cc577a4SJonathan Peyton   KMP_ASSERT(file != NULL);
20357cc577a4SJonathan Peyton 
20367cc577a4SJonathan Peyton   for (;;) {
20377cc577a4SJonathan Peyton 
20387cc577a4SJonathan Peyton     void *beginning = NULL;
20397cc577a4SJonathan Peyton     void *ending = NULL;
20407cc577a4SJonathan Peyton     char perms[5];
20417cc577a4SJonathan Peyton 
20427cc577a4SJonathan Peyton     rc = fscanf(file, "%p-%p %4s %*[^\n]\n", &beginning, &ending, perms);
20437cc577a4SJonathan Peyton     if (rc == EOF) {
20447cc577a4SJonathan Peyton       break;
2045bd3a7633SJonathan Peyton     }
20463041982dSJonathan Peyton     KMP_ASSERT(rc == 3 &&
20473041982dSJonathan Peyton                KMP_STRLEN(perms) == 4); // Make sure all fields are read.
20487cc577a4SJonathan Peyton 
20497cc577a4SJonathan Peyton     // Ending address is not included in the region, but beginning is.
20507cc577a4SJonathan Peyton     if ((addr >= beginning) && (addr < ending)) {
20517cc577a4SJonathan Peyton       perms[2] = 0; // 3th and 4th character does not matter.
20527cc577a4SJonathan Peyton       if (strcmp(perms, "rw") == 0) {
20537cc577a4SJonathan Peyton         // Memory we are looking for should be readable and writable.
20547cc577a4SJonathan Peyton         found = 1;
2055bd3a7633SJonathan Peyton       }
20567cc577a4SJonathan Peyton       break;
2057bd3a7633SJonathan Peyton     }
2058bd3a7633SJonathan Peyton   }
20597cc577a4SJonathan Peyton 
20607cc577a4SJonathan Peyton   // Free resources.
20617cc577a4SJonathan Peyton   fclose(file);
20627cc577a4SJonathan Peyton   KMP_INTERNAL_FREE(name);
2063fef62e1aSDavid Carlier #elif KMP_OS_FREEBSD
2064fef62e1aSDavid Carlier   char *buf;
2065fef62e1aSDavid Carlier   size_t lstsz;
2066fef62e1aSDavid Carlier   int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()};
2067fef62e1aSDavid Carlier   rc = sysctl(mib, 4, NULL, &lstsz, NULL, 0);
2068fef62e1aSDavid Carlier   if (rc < 0)
2069fef62e1aSDavid Carlier     return 0;
2070fef62e1aSDavid Carlier   // We pass from number of vm entry's semantic
2071fef62e1aSDavid Carlier   // to size of whole entry map list.
2072fef62e1aSDavid Carlier   lstsz = lstsz * 4 / 3;
2073fef62e1aSDavid Carlier   buf = reinterpret_cast<char *>(kmpc_malloc(lstsz));
2074fef62e1aSDavid Carlier   rc = sysctl(mib, 4, buf, &lstsz, NULL, 0);
2075fef62e1aSDavid Carlier   if (rc < 0) {
2076fef62e1aSDavid Carlier     kmpc_free(buf);
2077fef62e1aSDavid Carlier     return 0;
2078fef62e1aSDavid Carlier   }
2079fef62e1aSDavid Carlier 
2080fef62e1aSDavid Carlier   char *lw = buf;
2081fef62e1aSDavid Carlier   char *up = buf + lstsz;
2082fef62e1aSDavid Carlier 
2083fef62e1aSDavid Carlier   while (lw < up) {
2084fef62e1aSDavid Carlier     struct kinfo_vmentry *cur = reinterpret_cast<struct kinfo_vmentry *>(lw);
2085fef62e1aSDavid Carlier     size_t cursz = cur->kve_structsize;
2086fef62e1aSDavid Carlier     if (cursz == 0)
2087fef62e1aSDavid Carlier       break;
2088fef62e1aSDavid Carlier     void *start = reinterpret_cast<void *>(cur->kve_start);
2089fef62e1aSDavid Carlier     void *end = reinterpret_cast<void *>(cur->kve_end);
2090fef62e1aSDavid Carlier     // Readable/Writable addresses within current map entry
2091fef62e1aSDavid Carlier     if ((addr >= start) && (addr < end)) {
2092fef62e1aSDavid Carlier       if ((cur->kve_protection & KVME_PROT_READ) != 0 &&
2093fef62e1aSDavid Carlier           (cur->kve_protection & KVME_PROT_WRITE) != 0) {
2094fef62e1aSDavid Carlier         found = 1;
2095fef62e1aSDavid Carlier         break;
2096fef62e1aSDavid Carlier       }
2097fef62e1aSDavid Carlier     }
2098fef62e1aSDavid Carlier     lw += cursz;
2099fef62e1aSDavid Carlier   }
2100fef62e1aSDavid Carlier   kmpc_free(buf);
21017cc577a4SJonathan Peyton 
21027cc577a4SJonathan Peyton #elif KMP_OS_DARWIN
21037cc577a4SJonathan Peyton 
21043041982dSJonathan Peyton   /* On OS X*, /proc pseudo filesystem is not available. Try to read memory
21053041982dSJonathan Peyton      using vm interface. */
21067cc577a4SJonathan Peyton 
21077cc577a4SJonathan Peyton   int buffer;
21087cc577a4SJonathan Peyton   vm_size_t count;
21093041982dSJonathan Peyton   rc = vm_read_overwrite(
21107cc577a4SJonathan Peyton       mach_task_self(), // Task to read memory of.
21117cc577a4SJonathan Peyton       (vm_address_t)(addr), // Address to read from.
21127cc577a4SJonathan Peyton       1, // Number of bytes to be read.
21137cc577a4SJonathan Peyton       (vm_address_t)(&buffer), // Address of buffer to save read bytes in.
21147cc577a4SJonathan Peyton       &count // Address of var to save number of read bytes in.
21157cc577a4SJonathan Peyton   );
21167cc577a4SJonathan Peyton   if (rc == 0) {
21177cc577a4SJonathan Peyton     // Memory successfully read.
21187cc577a4SJonathan Peyton     found = 1;
2119bd3a7633SJonathan Peyton   }
21207cc577a4SJonathan Peyton 
2121316f4238SKamil Rytarowski #elif KMP_OS_NETBSD
21227cc577a4SJonathan Peyton 
2123316f4238SKamil Rytarowski   int mib[5];
2124316f4238SKamil Rytarowski   mib[0] = CTL_VM;
2125316f4238SKamil Rytarowski   mib[1] = VM_PROC;
2126316f4238SKamil Rytarowski   mib[2] = VM_PROC_MAP;
2127316f4238SKamil Rytarowski   mib[3] = getpid();
2128316f4238SKamil Rytarowski   mib[4] = sizeof(struct kinfo_vmentry);
2129316f4238SKamil Rytarowski 
2130316f4238SKamil Rytarowski   size_t size;
2131316f4238SKamil Rytarowski   rc = sysctl(mib, __arraycount(mib), NULL, &size, NULL, 0);
2132316f4238SKamil Rytarowski   KMP_ASSERT(!rc);
2133316f4238SKamil Rytarowski   KMP_ASSERT(size);
2134316f4238SKamil Rytarowski 
2135316f4238SKamil Rytarowski   size = size * 4 / 3;
2136316f4238SKamil Rytarowski   struct kinfo_vmentry *kiv = (struct kinfo_vmentry *)KMP_INTERNAL_MALLOC(size);
2137316f4238SKamil Rytarowski   KMP_ASSERT(kiv);
2138316f4238SKamil Rytarowski 
2139316f4238SKamil Rytarowski   rc = sysctl(mib, __arraycount(mib), kiv, &size, NULL, 0);
2140316f4238SKamil Rytarowski   KMP_ASSERT(!rc);
2141316f4238SKamil Rytarowski   KMP_ASSERT(size);
2142316f4238SKamil Rytarowski 
2143316f4238SKamil Rytarowski   for (size_t i = 0; i < size; i++) {
2144316f4238SKamil Rytarowski     if (kiv[i].kve_start >= (uint64_t)addr &&
2145316f4238SKamil Rytarowski         kiv[i].kve_end <= (uint64_t)addr) {
2146316f4238SKamil Rytarowski       found = 1;
2147316f4238SKamil Rytarowski       break;
2148316f4238SKamil Rytarowski     }
2149316f4238SKamil Rytarowski   }
2150316f4238SKamil Rytarowski   KMP_INTERNAL_FREE(kiv);
215127f6eedcSAndreyChurbanov #elif KMP_OS_OPENBSD
2152316f4238SKamil Rytarowski 
215327f6eedcSAndreyChurbanov   int mib[3];
215427f6eedcSAndreyChurbanov   mib[0] = CTL_KERN;
215527f6eedcSAndreyChurbanov   mib[1] = KERN_PROC_VMMAP;
215627f6eedcSAndreyChurbanov   mib[2] = getpid();
215727f6eedcSAndreyChurbanov 
215827f6eedcSAndreyChurbanov   size_t size;
215927f6eedcSAndreyChurbanov   uint64_t end;
216027f6eedcSAndreyChurbanov   rc = sysctl(mib, 3, NULL, &size, NULL, 0);
216127f6eedcSAndreyChurbanov   KMP_ASSERT(!rc);
216227f6eedcSAndreyChurbanov   KMP_ASSERT(size);
216327f6eedcSAndreyChurbanov   end = size;
216427f6eedcSAndreyChurbanov 
216527f6eedcSAndreyChurbanov   struct kinfo_vmentry kiv = {.kve_start = 0};
216627f6eedcSAndreyChurbanov 
216727f6eedcSAndreyChurbanov   while ((rc = sysctl(mib, 3, &kiv, &size, NULL, 0)) == 0) {
216827f6eedcSAndreyChurbanov     KMP_ASSERT(size);
216927f6eedcSAndreyChurbanov     if (kiv.kve_end == end)
217027f6eedcSAndreyChurbanov       break;
217127f6eedcSAndreyChurbanov 
217227f6eedcSAndreyChurbanov     if (kiv.kve_start >= (uint64_t)addr && kiv.kve_end <= (uint64_t)addr) {
217327f6eedcSAndreyChurbanov       found = 1;
217427f6eedcSAndreyChurbanov       break;
217527f6eedcSAndreyChurbanov     }
217627f6eedcSAndreyChurbanov     kiv.kve_start += 1;
217727f6eedcSAndreyChurbanov   }
217827f6eedcSAndreyChurbanov #elif KMP_OS_DRAGONFLY
217927f6eedcSAndreyChurbanov 
218027f6eedcSAndreyChurbanov   // FIXME(DragonFly): Implement this
21817cc577a4SJonathan Peyton   found = 1;
21827cc577a4SJonathan Peyton 
21837cc577a4SJonathan Peyton #else
21847cc577a4SJonathan Peyton 
21857cc577a4SJonathan Peyton #error "Unknown or unsupported OS"
21867cc577a4SJonathan Peyton 
21877cc577a4SJonathan Peyton #endif
21887cc577a4SJonathan Peyton 
21897cc577a4SJonathan Peyton   return found;
21907cc577a4SJonathan Peyton 
21917cc577a4SJonathan Peyton } // __kmp_is_address_mapped
21927cc577a4SJonathan Peyton 
21937cc577a4SJonathan Peyton #ifdef USE_LOAD_BALANCE
21947cc577a4SJonathan Peyton 
219570cdd83cSMichal Gorny #if KMP_OS_DARWIN || KMP_OS_NETBSD
21967cc577a4SJonathan Peyton 
21977cc577a4SJonathan Peyton // The function returns the rounded value of the system load average
21987cc577a4SJonathan Peyton // during given time interval which depends on the value of
21997cc577a4SJonathan Peyton // __kmp_load_balance_interval variable (default is 60 sec, other values
22007cc577a4SJonathan Peyton // may be 300 sec or 900 sec).
22017cc577a4SJonathan Peyton // It returns -1 in case of error.
__kmp_get_load_balance(int max)22023041982dSJonathan Peyton int __kmp_get_load_balance(int max) {
22037cc577a4SJonathan Peyton   double averages[3];
22047cc577a4SJonathan Peyton   int ret_avg = 0;
22057cc577a4SJonathan Peyton 
22067cc577a4SJonathan Peyton   int res = getloadavg(averages, 3);
22077cc577a4SJonathan Peyton 
22087cc577a4SJonathan Peyton   // Check __kmp_load_balance_interval to determine which of averages to use.
22097cc577a4SJonathan Peyton   // getloadavg() may return the number of samples less than requested that is
22107cc577a4SJonathan Peyton   // less than 3.
22117cc577a4SJonathan Peyton   if (__kmp_load_balance_interval < 180 && (res >= 1)) {
22126b316febSTerry Wilmarth     ret_avg = (int)averages[0]; // 1 min
22133041982dSJonathan Peyton   } else if ((__kmp_load_balance_interval >= 180 &&
22143041982dSJonathan Peyton               __kmp_load_balance_interval < 600) &&
22153041982dSJonathan Peyton              (res >= 2)) {
22166b316febSTerry Wilmarth     ret_avg = (int)averages[1]; // 5 min
22177cc577a4SJonathan Peyton   } else if ((__kmp_load_balance_interval >= 600) && (res == 3)) {
22186b316febSTerry Wilmarth     ret_avg = (int)averages[2]; // 15 min
22197cc577a4SJonathan Peyton   } else { // Error occurred
22207cc577a4SJonathan Peyton     return -1;
22217cc577a4SJonathan Peyton   }
22227cc577a4SJonathan Peyton 
22237cc577a4SJonathan Peyton   return ret_avg;
22247cc577a4SJonathan Peyton }
22257cc577a4SJonathan Peyton 
22267cc577a4SJonathan Peyton #else // Linux* OS
22277cc577a4SJonathan Peyton 
222842016791SKazuaki Ishizaki // The function returns number of running (not sleeping) threads, or -1 in case
22293041982dSJonathan Peyton // of error. Error could be reported if Linux* OS kernel too old (without
22303041982dSJonathan Peyton // "/proc" support). Counting running threads stops if max running threads
22313041982dSJonathan Peyton // encountered.
__kmp_get_load_balance(int max)22323041982dSJonathan Peyton int __kmp_get_load_balance(int max) {
22337cc577a4SJonathan Peyton   static int permanent_error = 0;
22343041982dSJonathan Peyton   static int glb_running_threads = 0; // Saved count of the running threads for
2235ed5fe645SKelvin Li   // the thread balance algorithm
22367cc577a4SJonathan Peyton   static double glb_call_time = 0; /* Thread balance algorithm call time */
22377cc577a4SJonathan Peyton 
22387cc577a4SJonathan Peyton   int running_threads = 0; // Number of running threads in the system.
22397cc577a4SJonathan Peyton 
22407cc577a4SJonathan Peyton   DIR *proc_dir = NULL; // Handle of "/proc/" directory.
22417cc577a4SJonathan Peyton   struct dirent *proc_entry = NULL;
22427cc577a4SJonathan Peyton 
22437cc577a4SJonathan Peyton   kmp_str_buf_t task_path; // "/proc/<pid>/task/<tid>/" path.
22447cc577a4SJonathan Peyton   DIR *task_dir = NULL; // Handle of "/proc/<pid>/task/<tid>/" directory.
22457cc577a4SJonathan Peyton   struct dirent *task_entry = NULL;
22467cc577a4SJonathan Peyton   int task_path_fixed_len;
22477cc577a4SJonathan Peyton 
22487cc577a4SJonathan Peyton   kmp_str_buf_t stat_path; // "/proc/<pid>/task/<tid>/stat" path.
22497cc577a4SJonathan Peyton   int stat_file = -1;
22507cc577a4SJonathan Peyton   int stat_path_fixed_len;
22517cc577a4SJonathan Peyton 
22527cc577a4SJonathan Peyton   int total_processes = 0; // Total number of processes in system.
22537cc577a4SJonathan Peyton   int total_threads = 0; // Total number of threads in system.
22547cc577a4SJonathan Peyton 
22557cc577a4SJonathan Peyton   double call_time = 0.0;
22567cc577a4SJonathan Peyton 
22577cc577a4SJonathan Peyton   __kmp_str_buf_init(&task_path);
22587cc577a4SJonathan Peyton   __kmp_str_buf_init(&stat_path);
22597cc577a4SJonathan Peyton 
22607cc577a4SJonathan Peyton   __kmp_elapsed(&call_time);
22617cc577a4SJonathan Peyton 
22627cc577a4SJonathan Peyton   if (glb_call_time &&
22637cc577a4SJonathan Peyton       (call_time - glb_call_time < __kmp_load_balance_interval)) {
22647cc577a4SJonathan Peyton     running_threads = glb_running_threads;
22657cc577a4SJonathan Peyton     goto finish;
22667cc577a4SJonathan Peyton   }
22677cc577a4SJonathan Peyton 
22687cc577a4SJonathan Peyton   glb_call_time = call_time;
22697cc577a4SJonathan Peyton 
22707cc577a4SJonathan Peyton   // Do not spend time on scanning "/proc/" if we have a permanent error.
22717cc577a4SJonathan Peyton   if (permanent_error) {
22727cc577a4SJonathan Peyton     running_threads = -1;
22737cc577a4SJonathan Peyton     goto finish;
2274bd3a7633SJonathan Peyton   }
22757cc577a4SJonathan Peyton 
22767cc577a4SJonathan Peyton   if (max <= 0) {
22777cc577a4SJonathan Peyton     max = INT_MAX;
2278bd3a7633SJonathan Peyton   }
22797cc577a4SJonathan Peyton 
22807cc577a4SJonathan Peyton   // Open "/proc/" directory.
22817cc577a4SJonathan Peyton   proc_dir = opendir("/proc");
22827cc577a4SJonathan Peyton   if (proc_dir == NULL) {
22833041982dSJonathan Peyton     // Cannot open "/prroc/". Probably the kernel does not support it. Return an
22843041982dSJonathan Peyton     // error now and in subsequent calls.
22857cc577a4SJonathan Peyton     running_threads = -1;
22867cc577a4SJonathan Peyton     permanent_error = 1;
22877cc577a4SJonathan Peyton     goto finish;
2288bd3a7633SJonathan Peyton   }
22897cc577a4SJonathan Peyton 
22907cc577a4SJonathan Peyton   // Initialize fixed part of task_path. This part will not change.
22917cc577a4SJonathan Peyton   __kmp_str_buf_cat(&task_path, "/proc/", 6);
22927cc577a4SJonathan Peyton   task_path_fixed_len = task_path.used; // Remember number of used characters.
22937cc577a4SJonathan Peyton 
22947cc577a4SJonathan Peyton   proc_entry = readdir(proc_dir);
22957cc577a4SJonathan Peyton   while (proc_entry != NULL) {
22963041982dSJonathan Peyton     // Proc entry is a directory and name starts with a digit. Assume it is a
22973041982dSJonathan Peyton     // process' directory.
22987cc577a4SJonathan Peyton     if (proc_entry->d_type == DT_DIR && isdigit(proc_entry->d_name[0])) {
22997cc577a4SJonathan Peyton 
23007cc577a4SJonathan Peyton       ++total_processes;
23017cc577a4SJonathan Peyton       // Make sure init process is the very first in "/proc", so we can replace
23023041982dSJonathan Peyton       // strcmp( proc_entry->d_name, "1" ) == 0 with simpler total_processes ==
23033041982dSJonathan Peyton       // 1. We are going to check that total_processes == 1 => d_name == "1" is
23043041982dSJonathan Peyton       // true (where "=>" is implication). Since C++ does not have => operator,
23053041982dSJonathan Peyton       // let us replace it with its equivalent: a => b == ! a || b.
23063041982dSJonathan Peyton       KMP_DEBUG_ASSERT(total_processes != 1 ||
23073041982dSJonathan Peyton                        strcmp(proc_entry->d_name, "1") == 0);
23087cc577a4SJonathan Peyton 
23097cc577a4SJonathan Peyton       // Construct task_path.
23107cc577a4SJonathan Peyton       task_path.used = task_path_fixed_len; // Reset task_path to "/proc/".
23113041982dSJonathan Peyton       __kmp_str_buf_cat(&task_path, proc_entry->d_name,
23123041982dSJonathan Peyton                         KMP_STRLEN(proc_entry->d_name));
23137cc577a4SJonathan Peyton       __kmp_str_buf_cat(&task_path, "/task", 5);
23147cc577a4SJonathan Peyton 
23157cc577a4SJonathan Peyton       task_dir = opendir(task_path.str);
23167cc577a4SJonathan Peyton       if (task_dir == NULL) {
23173041982dSJonathan Peyton         // Process can finish between reading "/proc/" directory entry and
23183041982dSJonathan Peyton         // opening process' "task/" directory. So, in general case we should not
23193041982dSJonathan Peyton         // complain, but have to skip this process and read the next one. But on
23203041982dSJonathan Peyton         // systems with no "task/" support we will spend lot of time to scan
23213041982dSJonathan Peyton         // "/proc/" tree again and again without any benefit. "init" process
23223041982dSJonathan Peyton         // (its pid is 1) should exist always, so, if we cannot open
23233041982dSJonathan Peyton         // "/proc/1/task/" directory, it means "task/" is not supported by
23243041982dSJonathan Peyton         // kernel. Report an error now and in the future.
23257cc577a4SJonathan Peyton         if (strcmp(proc_entry->d_name, "1") == 0) {
23267cc577a4SJonathan Peyton           running_threads = -1;
23277cc577a4SJonathan Peyton           permanent_error = 1;
23287cc577a4SJonathan Peyton           goto finish;
2329bd3a7633SJonathan Peyton         }
23307cc577a4SJonathan Peyton       } else {
23317cc577a4SJonathan Peyton         // Construct fixed part of stat file path.
23327cc577a4SJonathan Peyton         __kmp_str_buf_clear(&stat_path);
23337cc577a4SJonathan Peyton         __kmp_str_buf_cat(&stat_path, task_path.str, task_path.used);
23347cc577a4SJonathan Peyton         __kmp_str_buf_cat(&stat_path, "/", 1);
23357cc577a4SJonathan Peyton         stat_path_fixed_len = stat_path.used;
23367cc577a4SJonathan Peyton 
23377cc577a4SJonathan Peyton         task_entry = readdir(task_dir);
23387cc577a4SJonathan Peyton         while (task_entry != NULL) {
23397cc577a4SJonathan Peyton           // It is a directory and name starts with a digit.
23407cc577a4SJonathan Peyton           if (proc_entry->d_type == DT_DIR && isdigit(task_entry->d_name[0])) {
23417cc577a4SJonathan Peyton             ++total_threads;
23427cc577a4SJonathan Peyton 
2343ed5fe645SKelvin Li             // Construct complete stat file path. Easiest way would be:
23443041982dSJonathan Peyton             //  __kmp_str_buf_print( & stat_path, "%s/%s/stat", task_path.str,
23453041982dSJonathan Peyton             //  task_entry->d_name );
23467cc577a4SJonathan Peyton             // but seriae of __kmp_str_buf_cat works a bit faster.
23473041982dSJonathan Peyton             stat_path.used =
23483041982dSJonathan Peyton                 stat_path_fixed_len; // Reset stat path to its fixed part.
23493041982dSJonathan Peyton             __kmp_str_buf_cat(&stat_path, task_entry->d_name,
23503041982dSJonathan Peyton                               KMP_STRLEN(task_entry->d_name));
23517cc577a4SJonathan Peyton             __kmp_str_buf_cat(&stat_path, "/stat", 5);
23527cc577a4SJonathan Peyton 
23537cc577a4SJonathan Peyton             // Note: Low-level API (open/read/close) is used. High-level API
23547cc577a4SJonathan Peyton             // (fopen/fclose)  works ~ 30 % slower.
23557cc577a4SJonathan Peyton             stat_file = open(stat_path.str, O_RDONLY);
23567cc577a4SJonathan Peyton             if (stat_file == -1) {
23573041982dSJonathan Peyton               // We cannot report an error because task (thread) can terminate
23583041982dSJonathan Peyton               // just before reading this file.
23597cc577a4SJonathan Peyton             } else {
23603041982dSJonathan Peyton               /* Content of "stat" file looks like:
23617cc577a4SJonathan Peyton                  24285 (program) S ...
23627cc577a4SJonathan Peyton 
23633041982dSJonathan Peyton                  It is a single line (if program name does not include funny
23643041982dSJonathan Peyton                  symbols). First number is a thread id, then name of executable
23653041982dSJonathan Peyton                  file name in paretheses, then state of the thread. We need just
23663041982dSJonathan Peyton                  thread state.
23677cc577a4SJonathan Peyton 
23687cc577a4SJonathan Peyton                  Good news: Length of program name is 15 characters max. Longer
23697cc577a4SJonathan Peyton                  names are truncated.
23707cc577a4SJonathan Peyton 
23717cc577a4SJonathan Peyton                  Thus, we need rather short buffer: 15 chars for program name +
23727cc577a4SJonathan Peyton                  2 parenthesis, + 3 spaces + ~7 digits of pid = 37.
23737cc577a4SJonathan Peyton 
23747cc577a4SJonathan Peyton                  Bad news: Program name may contain special symbols like space,
23753041982dSJonathan Peyton                  closing parenthesis, or even new line. This makes parsing
23763041982dSJonathan Peyton                  "stat" file not 100 % reliable. In case of fanny program names
23773041982dSJonathan Peyton                  parsing may fail (report incorrect thread state).
23787cc577a4SJonathan Peyton 
23797cc577a4SJonathan Peyton                  Parsing "status" file looks more promissing (due to different
23807cc577a4SJonathan Peyton                  file structure and escaping special symbols) but reading and
23817cc577a4SJonathan Peyton                  parsing of "status" file works slower.
23827cc577a4SJonathan Peyton                   -- ln
23837cc577a4SJonathan Peyton               */
23847cc577a4SJonathan Peyton               char buffer[65];
23856b316febSTerry Wilmarth               ssize_t len;
23867cc577a4SJonathan Peyton               len = read(stat_file, buffer, sizeof(buffer) - 1);
23877cc577a4SJonathan Peyton               if (len >= 0) {
23887cc577a4SJonathan Peyton                 buffer[len] = 0;
23897cc577a4SJonathan Peyton                 // Using scanf:
23907cc577a4SJonathan Peyton                 //     sscanf( buffer, "%*d (%*s) %c ", & state );
23913041982dSJonathan Peyton                 // looks very nice, but searching for a closing parenthesis
23923041982dSJonathan Peyton                 // works a bit faster.
23937cc577a4SJonathan Peyton                 char *close_parent = strstr(buffer, ") ");
23947cc577a4SJonathan Peyton                 if (close_parent != NULL) {
23957cc577a4SJonathan Peyton                   char state = *(close_parent + 2);
23967cc577a4SJonathan Peyton                   if (state == 'R') {
23977cc577a4SJonathan Peyton                     ++running_threads;
23987cc577a4SJonathan Peyton                     if (running_threads >= max) {
23997cc577a4SJonathan Peyton                       goto finish;
2400bd3a7633SJonathan Peyton                     }
2401bd3a7633SJonathan Peyton                   }
2402bd3a7633SJonathan Peyton                 }
2403bd3a7633SJonathan Peyton               }
24047cc577a4SJonathan Peyton               close(stat_file);
24057cc577a4SJonathan Peyton               stat_file = -1;
2406bd3a7633SJonathan Peyton             }
2407bd3a7633SJonathan Peyton           }
24087cc577a4SJonathan Peyton           task_entry = readdir(task_dir);
2409bd3a7633SJonathan Peyton         }
24107cc577a4SJonathan Peyton         closedir(task_dir);
24117cc577a4SJonathan Peyton         task_dir = NULL;
2412bd3a7633SJonathan Peyton       }
2413bd3a7633SJonathan Peyton     }
24147cc577a4SJonathan Peyton     proc_entry = readdir(proc_dir);
2415bd3a7633SJonathan Peyton   }
24167cc577a4SJonathan Peyton 
24177cc577a4SJonathan Peyton   // There _might_ be a timing hole where the thread executing this
24187cc577a4SJonathan Peyton   // code get skipped in the load balance, and running_threads is 0.
24197cc577a4SJonathan Peyton   // Assert in the debug builds only!!!
24207cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(running_threads > 0);
24217cc577a4SJonathan Peyton   if (running_threads <= 0) {
24227cc577a4SJonathan Peyton     running_threads = 1;
24237cc577a4SJonathan Peyton   }
24247cc577a4SJonathan Peyton 
24257cc577a4SJonathan Peyton finish: // Clean up and exit.
24267cc577a4SJonathan Peyton   if (proc_dir != NULL) {
24277cc577a4SJonathan Peyton     closedir(proc_dir);
2428bd3a7633SJonathan Peyton   }
24297cc577a4SJonathan Peyton   __kmp_str_buf_free(&task_path);
24307cc577a4SJonathan Peyton   if (task_dir != NULL) {
24317cc577a4SJonathan Peyton     closedir(task_dir);
2432bd3a7633SJonathan Peyton   }
24337cc577a4SJonathan Peyton   __kmp_str_buf_free(&stat_path);
24347cc577a4SJonathan Peyton   if (stat_file != -1) {
24357cc577a4SJonathan Peyton     close(stat_file);
2436bd3a7633SJonathan Peyton   }
24377cc577a4SJonathan Peyton 
24387cc577a4SJonathan Peyton   glb_running_threads = running_threads;
24397cc577a4SJonathan Peyton 
24407cc577a4SJonathan Peyton   return running_threads;
24417cc577a4SJonathan Peyton 
24427cc577a4SJonathan Peyton } // __kmp_get_load_balance
24437cc577a4SJonathan Peyton 
24447cc577a4SJonathan Peyton #endif // KMP_OS_DARWIN
24457cc577a4SJonathan Peyton 
24467cc577a4SJonathan Peyton #endif // USE_LOAD_BALANCE
24477cc577a4SJonathan Peyton 
2448c47afcd9SAndrey Churbanov #if !(KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_MIC ||                            \
24492488ae9dSJonas Hahnfeld       ((KMP_OS_LINUX || KMP_OS_DARWIN) && KMP_ARCH_AARCH64) ||                 \
24502488ae9dSJonas Hahnfeld       KMP_ARCH_PPC64 || KMP_ARCH_RISCV64)
24517cc577a4SJonathan Peyton 
24527cc577a4SJonathan Peyton // we really only need the case with 1 argument, because CLANG always build
24537cc577a4SJonathan Peyton // a struct of pointers to shared variables referenced in the outlined function
__kmp_invoke_microtask(microtask_t pkfn,int gtid,int tid,int argc,void * p_argv[],void ** exit_frame_ptr)24543041982dSJonathan Peyton int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,
24553041982dSJonathan Peyton                            void *p_argv[]
24567cc577a4SJonathan Peyton #if OMPT_SUPPORT
24573041982dSJonathan Peyton                            ,
24583041982dSJonathan Peyton                            void **exit_frame_ptr
24597cc577a4SJonathan Peyton #endif
24603041982dSJonathan Peyton ) {
24617cc577a4SJonathan Peyton #if OMPT_SUPPORT
246282e94a59SJoachim Protze   *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0);
24637cc577a4SJonathan Peyton #endif
24647cc577a4SJonathan Peyton 
24657cc577a4SJonathan Peyton   switch (argc) {
24667cc577a4SJonathan Peyton   default:
24677cc577a4SJonathan Peyton     fprintf(stderr, "Too many args to microtask: %d!\n", argc);
24687cc577a4SJonathan Peyton     fflush(stderr);
24697cc577a4SJonathan Peyton     exit(-1);
24707cc577a4SJonathan Peyton   case 0:
24717cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid);
24727cc577a4SJonathan Peyton     break;
24737cc577a4SJonathan Peyton   case 1:
24747cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0]);
24757cc577a4SJonathan Peyton     break;
24767cc577a4SJonathan Peyton   case 2:
24777cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1]);
24787cc577a4SJonathan Peyton     break;
24797cc577a4SJonathan Peyton   case 3:
24807cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2]);
24817cc577a4SJonathan Peyton     break;
24827cc577a4SJonathan Peyton   case 4:
24837cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3]);
24847cc577a4SJonathan Peyton     break;
24857cc577a4SJonathan Peyton   case 5:
24867cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4]);
24877cc577a4SJonathan Peyton     break;
24887cc577a4SJonathan Peyton   case 6:
24897cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
24907cc577a4SJonathan Peyton             p_argv[5]);
24917cc577a4SJonathan Peyton     break;
24927cc577a4SJonathan Peyton   case 7:
24937cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
24947cc577a4SJonathan Peyton             p_argv[5], p_argv[6]);
24957cc577a4SJonathan Peyton     break;
24967cc577a4SJonathan Peyton   case 8:
24977cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
24987cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7]);
24997cc577a4SJonathan Peyton     break;
25007cc577a4SJonathan Peyton   case 9:
25017cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25027cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8]);
25037cc577a4SJonathan Peyton     break;
25047cc577a4SJonathan Peyton   case 10:
25057cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25067cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9]);
25077cc577a4SJonathan Peyton     break;
25087cc577a4SJonathan Peyton   case 11:
25097cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25107cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10]);
25117cc577a4SJonathan Peyton     break;
25127cc577a4SJonathan Peyton   case 12:
25137cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25147cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
25157cc577a4SJonathan Peyton             p_argv[11]);
25167cc577a4SJonathan Peyton     break;
25177cc577a4SJonathan Peyton   case 13:
25187cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25197cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
25207cc577a4SJonathan Peyton             p_argv[11], p_argv[12]);
25217cc577a4SJonathan Peyton     break;
25227cc577a4SJonathan Peyton   case 14:
25237cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25247cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
25257cc577a4SJonathan Peyton             p_argv[11], p_argv[12], p_argv[13]);
25267cc577a4SJonathan Peyton     break;
25277cc577a4SJonathan Peyton   case 15:
25287cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25297cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
25307cc577a4SJonathan Peyton             p_argv[11], p_argv[12], p_argv[13], p_argv[14]);
25317cc577a4SJonathan Peyton     break;
25327cc577a4SJonathan Peyton   }
25337cc577a4SJonathan Peyton 
25347cc577a4SJonathan Peyton   return 1;
25357cc577a4SJonathan Peyton }
25367cc577a4SJonathan Peyton 
25377cc577a4SJonathan Peyton #endif
25387cc577a4SJonathan Peyton 
2539f1b9ce27SHansang Bae #if KMP_OS_LINUX
25409d64275aSShilei Tian // Functions for hidden helper task
25419d64275aSShilei Tian namespace {
25429d64275aSShilei Tian // Condition variable for initializing hidden helper team
25439d64275aSShilei Tian pthread_cond_t hidden_helper_threads_initz_cond_var;
25449d64275aSShilei Tian pthread_mutex_t hidden_helper_threads_initz_lock;
25459d64275aSShilei Tian volatile int hidden_helper_initz_signaled = FALSE;
25469d64275aSShilei Tian 
25479d64275aSShilei Tian // Condition variable for deinitializing hidden helper team
25489d64275aSShilei Tian pthread_cond_t hidden_helper_threads_deinitz_cond_var;
25499d64275aSShilei Tian pthread_mutex_t hidden_helper_threads_deinitz_lock;
25509d64275aSShilei Tian volatile int hidden_helper_deinitz_signaled = FALSE;
25519d64275aSShilei Tian 
25529d64275aSShilei Tian // Condition variable for the wrapper function of main thread
25539d64275aSShilei Tian pthread_cond_t hidden_helper_main_thread_cond_var;
25549d64275aSShilei Tian pthread_mutex_t hidden_helper_main_thread_lock;
25559d64275aSShilei Tian volatile int hidden_helper_main_thread_signaled = FALSE;
25569d64275aSShilei Tian 
25579d64275aSShilei Tian // Semaphore for worker threads. We don't use condition variable here in case
25589d64275aSShilei Tian // that when multiple signals are sent at the same time, only one thread might
25599d64275aSShilei Tian // be waken.
25609d64275aSShilei Tian sem_t hidden_helper_task_sem;
25619d64275aSShilei Tian } // namespace
25629d64275aSShilei Tian 
__kmp_hidden_helper_worker_thread_wait()25639d64275aSShilei Tian void __kmp_hidden_helper_worker_thread_wait() {
25649d64275aSShilei Tian   int status = sem_wait(&hidden_helper_task_sem);
25659d64275aSShilei Tian   KMP_CHECK_SYSFAIL("sem_wait", status);
25669d64275aSShilei Tian }
25679d64275aSShilei Tian 
__kmp_do_initialize_hidden_helper_threads()25689d64275aSShilei Tian void __kmp_do_initialize_hidden_helper_threads() {
25699d64275aSShilei Tian   // Initialize condition variable
25709d64275aSShilei Tian   int status =
25719d64275aSShilei Tian       pthread_cond_init(&hidden_helper_threads_initz_cond_var, nullptr);
25729d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
25739d64275aSShilei Tian 
25749d64275aSShilei Tian   status = pthread_cond_init(&hidden_helper_threads_deinitz_cond_var, nullptr);
25759d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
25769d64275aSShilei Tian 
25779d64275aSShilei Tian   status = pthread_cond_init(&hidden_helper_main_thread_cond_var, nullptr);
25789d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
25799d64275aSShilei Tian 
25809d64275aSShilei Tian   status = pthread_mutex_init(&hidden_helper_threads_initz_lock, nullptr);
25819d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
25829d64275aSShilei Tian 
25839d64275aSShilei Tian   status = pthread_mutex_init(&hidden_helper_threads_deinitz_lock, nullptr);
25849d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
25859d64275aSShilei Tian 
25869d64275aSShilei Tian   status = pthread_mutex_init(&hidden_helper_main_thread_lock, nullptr);
25879d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
25889d64275aSShilei Tian 
25899d64275aSShilei Tian   // Initialize the semaphore
25909d64275aSShilei Tian   status = sem_init(&hidden_helper_task_sem, 0, 0);
25919d64275aSShilei Tian   KMP_CHECK_SYSFAIL("sem_init", status);
25929d64275aSShilei Tian 
25939d64275aSShilei Tian   // Create a new thread to finish initialization
25949d64275aSShilei Tian   pthread_t handle;
25959d64275aSShilei Tian   status = pthread_create(
25969d64275aSShilei Tian       &handle, nullptr,
25979d64275aSShilei Tian       [](void *) -> void * {
25989d64275aSShilei Tian         __kmp_hidden_helper_threads_initz_routine();
25999d64275aSShilei Tian         return nullptr;
26009d64275aSShilei Tian       },
26019d64275aSShilei Tian       nullptr);
26029d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_create", status);
26039d64275aSShilei Tian }
26049d64275aSShilei Tian 
__kmp_hidden_helper_threads_initz_wait()26059d64275aSShilei Tian void __kmp_hidden_helper_threads_initz_wait() {
26069d64275aSShilei Tian   // Initial thread waits here for the completion of the initialization. The
26079d64275aSShilei Tian   // condition variable will be notified by main thread of hidden helper teams.
26089d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_threads_initz_lock);
26099d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26109d64275aSShilei Tian 
26119d64275aSShilei Tian   if (!TCR_4(hidden_helper_initz_signaled)) {
26129d64275aSShilei Tian     status = pthread_cond_wait(&hidden_helper_threads_initz_cond_var,
26139d64275aSShilei Tian                                &hidden_helper_threads_initz_lock);
26149d64275aSShilei Tian     KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26159d64275aSShilei Tian   }
26169d64275aSShilei Tian 
26179d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_threads_initz_lock);
26189d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26199d64275aSShilei Tian }
26209d64275aSShilei Tian 
__kmp_hidden_helper_initz_release()26219d64275aSShilei Tian void __kmp_hidden_helper_initz_release() {
26229d64275aSShilei Tian   // After all initialization, reset __kmp_init_hidden_helper_threads to false.
26239d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_threads_initz_lock);
26249d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26259d64275aSShilei Tian 
26269d64275aSShilei Tian   status = pthread_cond_signal(&hidden_helper_threads_initz_cond_var);
26279d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26289d64275aSShilei Tian 
26299d64275aSShilei Tian   TCW_SYNC_4(hidden_helper_initz_signaled, TRUE);
26309d64275aSShilei Tian 
26319d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_threads_initz_lock);
26329d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26339d64275aSShilei Tian }
26349d64275aSShilei Tian 
__kmp_hidden_helper_main_thread_wait()26359d64275aSShilei Tian void __kmp_hidden_helper_main_thread_wait() {
26369d64275aSShilei Tian   // The main thread of hidden helper team will be blocked here. The
26379d64275aSShilei Tian   // condition variable can only be signal in the destructor of RTL.
26389d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_main_thread_lock);
26399d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26409d64275aSShilei Tian 
26419d64275aSShilei Tian   if (!TCR_4(hidden_helper_main_thread_signaled)) {
26429d64275aSShilei Tian     status = pthread_cond_wait(&hidden_helper_main_thread_cond_var,
26439d64275aSShilei Tian                                &hidden_helper_main_thread_lock);
26449d64275aSShilei Tian     KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26459d64275aSShilei Tian   }
26469d64275aSShilei Tian 
26479d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_main_thread_lock);
26489d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26499d64275aSShilei Tian }
26509d64275aSShilei Tian 
__kmp_hidden_helper_main_thread_release()26519d64275aSShilei Tian void __kmp_hidden_helper_main_thread_release() {
26529d64275aSShilei Tian   // The initial thread of OpenMP RTL should call this function to wake up the
26539d64275aSShilei Tian   // main thread of hidden helper team.
26549d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_main_thread_lock);
26559d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26569d64275aSShilei Tian 
26579d64275aSShilei Tian   status = pthread_cond_signal(&hidden_helper_main_thread_cond_var);
26589d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_signal", status);
26599d64275aSShilei Tian 
26609d64275aSShilei Tian   // The hidden helper team is done here
26619d64275aSShilei Tian   TCW_SYNC_4(hidden_helper_main_thread_signaled, TRUE);
26629d64275aSShilei Tian 
26639d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_main_thread_lock);
26649d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26659d64275aSShilei Tian }
26669d64275aSShilei Tian 
__kmp_hidden_helper_worker_thread_signal()26679d64275aSShilei Tian void __kmp_hidden_helper_worker_thread_signal() {
26689d64275aSShilei Tian   int status = sem_post(&hidden_helper_task_sem);
26699d64275aSShilei Tian   KMP_CHECK_SYSFAIL("sem_post", status);
26709d64275aSShilei Tian }
26719d64275aSShilei Tian 
__kmp_hidden_helper_threads_deinitz_wait()26729d64275aSShilei Tian void __kmp_hidden_helper_threads_deinitz_wait() {
26739d64275aSShilei Tian   // Initial thread waits here for the completion of the deinitialization. The
26749d64275aSShilei Tian   // condition variable will be notified by main thread of hidden helper teams.
26759d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_threads_deinitz_lock);
26769d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26779d64275aSShilei Tian 
26789d64275aSShilei Tian   if (!TCR_4(hidden_helper_deinitz_signaled)) {
26799d64275aSShilei Tian     status = pthread_cond_wait(&hidden_helper_threads_deinitz_cond_var,
26809d64275aSShilei Tian                                &hidden_helper_threads_deinitz_lock);
26819d64275aSShilei Tian     KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26829d64275aSShilei Tian   }
26839d64275aSShilei Tian 
26849d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_threads_deinitz_lock);
26859d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26869d64275aSShilei Tian }
26879d64275aSShilei Tian 
__kmp_hidden_helper_threads_deinitz_release()26889d64275aSShilei Tian void __kmp_hidden_helper_threads_deinitz_release() {
26899d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_threads_deinitz_lock);
26909d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26919d64275aSShilei Tian 
26929d64275aSShilei Tian   status = pthread_cond_signal(&hidden_helper_threads_deinitz_cond_var);
26939d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26949d64275aSShilei Tian 
26959d64275aSShilei Tian   TCW_SYNC_4(hidden_helper_deinitz_signaled, TRUE);
26969d64275aSShilei Tian 
26979d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_threads_deinitz_lock);
26989d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26999d64275aSShilei Tian }
2700f1b9ce27SHansang Bae #else // KMP_OS_LINUX
__kmp_hidden_helper_worker_thread_wait()2701f1b9ce27SHansang Bae void __kmp_hidden_helper_worker_thread_wait() {
2702f1b9ce27SHansang Bae   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
2703f1b9ce27SHansang Bae }
2704f1b9ce27SHansang Bae 
__kmp_do_initialize_hidden_helper_threads()2705f1b9ce27SHansang Bae void __kmp_do_initialize_hidden_helper_threads() {
2706f1b9ce27SHansang Bae   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
2707f1b9ce27SHansang Bae }
2708f1b9ce27SHansang Bae 
__kmp_hidden_helper_threads_initz_wait()2709f1b9ce27SHansang Bae void __kmp_hidden_helper_threads_initz_wait() {
2710f1b9ce27SHansang Bae   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
2711f1b9ce27SHansang Bae }
2712f1b9ce27SHansang Bae 
__kmp_hidden_helper_initz_release()2713f1b9ce27SHansang Bae void __kmp_hidden_helper_initz_release() {
2714f1b9ce27SHansang Bae   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
2715f1b9ce27SHansang Bae }
2716f1b9ce27SHansang Bae 
__kmp_hidden_helper_main_thread_wait()2717f1b9ce27SHansang Bae void __kmp_hidden_helper_main_thread_wait() {
2718f1b9ce27SHansang Bae   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
2719f1b9ce27SHansang Bae }
2720f1b9ce27SHansang Bae 
__kmp_hidden_helper_main_thread_release()2721f1b9ce27SHansang Bae void __kmp_hidden_helper_main_thread_release() {
2722f1b9ce27SHansang Bae   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
2723f1b9ce27SHansang Bae }
2724f1b9ce27SHansang Bae 
__kmp_hidden_helper_worker_thread_signal()2725f1b9ce27SHansang Bae void __kmp_hidden_helper_worker_thread_signal() {
2726f1b9ce27SHansang Bae   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
2727f1b9ce27SHansang Bae }
2728f1b9ce27SHansang Bae 
__kmp_hidden_helper_threads_deinitz_wait()2729f1b9ce27SHansang Bae void __kmp_hidden_helper_threads_deinitz_wait() {
2730f1b9ce27SHansang Bae   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
2731f1b9ce27SHansang Bae }
2732f1b9ce27SHansang Bae 
__kmp_hidden_helper_threads_deinitz_release()2733f1b9ce27SHansang Bae void __kmp_hidden_helper_threads_deinitz_release() {
2734f1b9ce27SHansang Bae   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
2735f1b9ce27SHansang Bae }
2736f1b9ce27SHansang Bae #endif // KMP_OS_LINUX
27379d64275aSShilei Tian 
27387cc577a4SJonathan Peyton // end of file //
2739