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.
289d64275aSShilei Tian #include <semaphore.h>
297cc577a4SJonathan Peyton #include <sys/resource.h>
307cc577a4SJonathan Peyton #include <sys/syscall.h>
313041982dSJonathan Peyton #include <sys/time.h>
323041982dSJonathan Peyton #include <sys/times.h>
333041982dSJonathan Peyton #include <unistd.h>
347cc577a4SJonathan Peyton 
35d28f8672SJinsong Ji #if KMP_OS_LINUX
367cc577a4SJonathan Peyton #include <sys/sysinfo.h>
377cc577a4SJonathan Peyton #if KMP_USE_FUTEX
383041982dSJonathan Peyton // We should really include <futex.h>, but that causes compatibility problems on
393041982dSJonathan Peyton // different Linux* OS distributions that either require that you include (or
403041982dSJonathan Peyton // break when you try to include) <pci/types.h>. Since all we need is the two
413041982dSJonathan Peyton // macros below (which are part of the kernel ABI, so can't change) we just
423041982dSJonathan Peyton // define the constants here and don't include <futex.h>
437cc577a4SJonathan Peyton #ifndef FUTEX_WAIT
447cc577a4SJonathan Peyton #define FUTEX_WAIT 0
457cc577a4SJonathan Peyton #endif
467cc577a4SJonathan Peyton #ifndef FUTEX_WAKE
477cc577a4SJonathan Peyton #define FUTEX_WAKE 1
487cc577a4SJonathan Peyton #endif
497cc577a4SJonathan Peyton #endif
507cc577a4SJonathan Peyton #elif KMP_OS_DARWIN
517cc577a4SJonathan Peyton #include <mach/mach.h>
523041982dSJonathan Peyton #include <sys/sysctl.h>
53a56ac949SKamil Rytarowski #elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD
54fef62e1aSDavid Carlier #include <sys/types.h>
55fef62e1aSDavid Carlier #include <sys/sysctl.h>
56fef62e1aSDavid Carlier #include <sys/user.h>
577cc577a4SJonathan Peyton #include <pthread_np.h>
5827f6eedcSAndreyChurbanov #elif KMP_OS_NETBSD || KMP_OS_OPENBSD
59316f4238SKamil Rytarowski #include <sys/types.h>
60316f4238SKamil Rytarowski #include <sys/sysctl.h>
617cc577a4SJonathan Peyton #endif
627cc577a4SJonathan Peyton 
637cc577a4SJonathan Peyton #include <ctype.h>
643041982dSJonathan Peyton #include <dirent.h>
657cc577a4SJonathan Peyton #include <fcntl.h>
667cc577a4SJonathan Peyton 
677cc577a4SJonathan Peyton #include "tsan_annotations.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
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 
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). */
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)
129f61f13d4SDavid Carlier #elif KMP_OS_FREEBSD
130f61f13d4SDavid Carlier #define KMP_CPU_SET_SIZE_LIMIT (sizeof(cpuset_t))
131f61f13d4SDavid Carlier #endif
1327cc577a4SJonathan Peyton 
133f61f13d4SDavid Carlier #if KMP_OS_LINUX
134f61f13d4SDavid Carlier   // If Linux* OS:
135f61f13d4SDavid Carlier   // If the syscall fails or returns a suggestion for the size,
136f61f13d4SDavid Carlier   // then we don't have to search for an appropriate size.
1376b316febSTerry Wilmarth   long gCode;
1386b316febSTerry Wilmarth   long sCode;
1397cc577a4SJonathan Peyton   unsigned char *buf;
1407cc577a4SJonathan Peyton   buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT);
1417cc577a4SJonathan Peyton   gCode = syscall(__NR_sched_getaffinity, 0, KMP_CPU_SET_SIZE_LIMIT, 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 
1467cc577a4SJonathan Peyton   // if ((gCode < 0) && (errno == ENOSYS))
1477cc577a4SJonathan Peyton   if (gCode < 0) {
1487cc577a4SJonathan Peyton     // System call not supported
1493041982dSJonathan Peyton     if (__kmp_affinity_verbose ||
1503041982dSJonathan Peyton         (__kmp_affinity_warnings && (__kmp_affinity_type != affinity_none) &&
1513041982dSJonathan Peyton          (__kmp_affinity_type != affinity_default) &&
1523041982dSJonathan Peyton          (__kmp_affinity_type != affinity_disabled))) {
1537cc577a4SJonathan Peyton       int error = errno;
1547cc577a4SJonathan Peyton       kmp_msg_t err_code = KMP_ERR(error);
1553041982dSJonathan Peyton       __kmp_msg(kmp_ms_warning, KMP_MSG(GetAffSysCallNotSupported, env_var),
1563041982dSJonathan Peyton                 err_code, __kmp_msg_null);
1577cc577a4SJonathan Peyton       if (__kmp_generate_warnings == kmp_warnings_off) {
1587cc577a4SJonathan Peyton         __kmp_str_free(&err_code.str);
1597cc577a4SJonathan Peyton       }
1607cc577a4SJonathan Peyton     }
1617cc577a4SJonathan Peyton     KMP_AFFINITY_DISABLE();
1627cc577a4SJonathan Peyton     KMP_INTERNAL_FREE(buf);
1637cc577a4SJonathan Peyton     return;
1647cc577a4SJonathan Peyton   }
1657cc577a4SJonathan Peyton   if (gCode > 0) { // Linux* OS only
1663041982dSJonathan Peyton     // The optimal situation: the OS returns the size of the buffer it expects.
1677cc577a4SJonathan Peyton     //
168ea99c099SDavid Carlier     // A verification of correct behavior is that setaffinity on a NULL
1697cc577a4SJonathan Peyton     // buffer with the same size fails with errno set to EFAULT.
1707cc577a4SJonathan Peyton     sCode = syscall(__NR_sched_setaffinity, 0, gCode, NULL);
1717cc577a4SJonathan Peyton     KA_TRACE(30, ("__kmp_affinity_determine_capable: "
1726b316febSTerry Wilmarth                   "setaffinity for mask size %ld returned %ld errno = %d\n",
1737cc577a4SJonathan Peyton                   gCode, sCode, errno));
1747cc577a4SJonathan Peyton     if (sCode < 0) {
1757cc577a4SJonathan Peyton       if (errno == ENOSYS) {
1763041982dSJonathan Peyton         if (__kmp_affinity_verbose ||
1773041982dSJonathan Peyton             (__kmp_affinity_warnings &&
1783041982dSJonathan Peyton              (__kmp_affinity_type != affinity_none) &&
1793041982dSJonathan Peyton              (__kmp_affinity_type != affinity_default) &&
1803041982dSJonathan Peyton              (__kmp_affinity_type != affinity_disabled))) {
1817cc577a4SJonathan Peyton           int error = errno;
1827cc577a4SJonathan Peyton           kmp_msg_t err_code = KMP_ERR(error);
1833041982dSJonathan Peyton           __kmp_msg(kmp_ms_warning, KMP_MSG(SetAffSysCallNotSupported, env_var),
1843041982dSJonathan Peyton                     err_code, __kmp_msg_null);
1857cc577a4SJonathan Peyton           if (__kmp_generate_warnings == kmp_warnings_off) {
1867cc577a4SJonathan Peyton             __kmp_str_free(&err_code.str);
1877cc577a4SJonathan Peyton           }
1887cc577a4SJonathan Peyton         }
1897cc577a4SJonathan Peyton         KMP_AFFINITY_DISABLE();
1907cc577a4SJonathan Peyton         KMP_INTERNAL_FREE(buf);
1917cc577a4SJonathan Peyton       }
1927cc577a4SJonathan Peyton       if (errno == EFAULT) {
1937cc577a4SJonathan Peyton         KMP_AFFINITY_ENABLE(gCode);
1947cc577a4SJonathan Peyton         KA_TRACE(10, ("__kmp_affinity_determine_capable: "
1957cc577a4SJonathan Peyton                       "affinity supported (mask size %d)\n",
1967cc577a4SJonathan Peyton                       (int)__kmp_affin_mask_size));
1977cc577a4SJonathan Peyton         KMP_INTERNAL_FREE(buf);
1987cc577a4SJonathan Peyton         return;
1997cc577a4SJonathan Peyton       }
2007cc577a4SJonathan Peyton     }
2017cc577a4SJonathan Peyton   }
2027cc577a4SJonathan Peyton 
2037cc577a4SJonathan Peyton   // Call the getaffinity system call repeatedly with increasing set sizes
2047cc577a4SJonathan Peyton   // until we succeed, or reach an upper bound on the search.
2057cc577a4SJonathan Peyton   KA_TRACE(30, ("__kmp_affinity_determine_capable: "
2067cc577a4SJonathan Peyton                 "searching for proper set size\n"));
2077cc577a4SJonathan Peyton   int size;
2087cc577a4SJonathan Peyton   for (size = 1; size <= KMP_CPU_SET_SIZE_LIMIT; size *= 2) {
2097cc577a4SJonathan Peyton     gCode = syscall(__NR_sched_getaffinity, 0, size, buf);
2107cc577a4SJonathan Peyton     KA_TRACE(30, ("__kmp_affinity_determine_capable: "
2116b316febSTerry Wilmarth                   "getaffinity for mask size %ld returned %ld errno = %d\n",
2123041982dSJonathan Peyton                   size, gCode, errno));
2137cc577a4SJonathan Peyton 
2147cc577a4SJonathan Peyton     if (gCode < 0) {
2153041982dSJonathan Peyton       if (errno == ENOSYS) {
2167cc577a4SJonathan Peyton         // We shouldn't get here
2177cc577a4SJonathan Peyton         KA_TRACE(30, ("__kmp_affinity_determine_capable: "
2183041982dSJonathan Peyton                       "inconsistent OS call behavior: errno == ENOSYS for mask "
2193041982dSJonathan Peyton                       "size %d\n",
2207cc577a4SJonathan Peyton                       size));
2213041982dSJonathan Peyton         if (__kmp_affinity_verbose ||
2223041982dSJonathan Peyton             (__kmp_affinity_warnings &&
2233041982dSJonathan Peyton              (__kmp_affinity_type != affinity_none) &&
2243041982dSJonathan Peyton              (__kmp_affinity_type != affinity_default) &&
2253041982dSJonathan Peyton              (__kmp_affinity_type != affinity_disabled))) {
2267cc577a4SJonathan Peyton           int error = errno;
2277cc577a4SJonathan Peyton           kmp_msg_t err_code = KMP_ERR(error);
2283041982dSJonathan Peyton           __kmp_msg(kmp_ms_warning, KMP_MSG(GetAffSysCallNotSupported, env_var),
2293041982dSJonathan Peyton                     err_code, __kmp_msg_null);
2307cc577a4SJonathan Peyton           if (__kmp_generate_warnings == kmp_warnings_off) {
2317cc577a4SJonathan Peyton             __kmp_str_free(&err_code.str);
2327cc577a4SJonathan Peyton           }
2337cc577a4SJonathan Peyton         }
2347cc577a4SJonathan Peyton         KMP_AFFINITY_DISABLE();
2357cc577a4SJonathan Peyton         KMP_INTERNAL_FREE(buf);
2367cc577a4SJonathan Peyton         return;
2377cc577a4SJonathan Peyton       }
2387cc577a4SJonathan Peyton       continue;
2397cc577a4SJonathan Peyton     }
2407cc577a4SJonathan Peyton 
2417cc577a4SJonathan Peyton     sCode = syscall(__NR_sched_setaffinity, 0, gCode, NULL);
2427cc577a4SJonathan Peyton     KA_TRACE(30, ("__kmp_affinity_determine_capable: "
2436b316febSTerry Wilmarth                   "setaffinity for mask size %ld returned %ld errno = %d\n",
2447cc577a4SJonathan Peyton                   gCode, sCode, errno));
2457cc577a4SJonathan Peyton     if (sCode < 0) {
2467cc577a4SJonathan Peyton       if (errno == ENOSYS) { // Linux* OS only
2477cc577a4SJonathan Peyton         // We shouldn't get here
2487cc577a4SJonathan Peyton         KA_TRACE(30, ("__kmp_affinity_determine_capable: "
2493041982dSJonathan Peyton                       "inconsistent OS call behavior: errno == ENOSYS for mask "
2503041982dSJonathan Peyton                       "size %d\n",
2517cc577a4SJonathan Peyton                       size));
2523041982dSJonathan Peyton         if (__kmp_affinity_verbose ||
2533041982dSJonathan Peyton             (__kmp_affinity_warnings &&
2543041982dSJonathan Peyton              (__kmp_affinity_type != affinity_none) &&
2553041982dSJonathan Peyton              (__kmp_affinity_type != affinity_default) &&
2563041982dSJonathan Peyton              (__kmp_affinity_type != affinity_disabled))) {
2577cc577a4SJonathan Peyton           int error = errno;
2587cc577a4SJonathan Peyton           kmp_msg_t err_code = KMP_ERR(error);
2593041982dSJonathan Peyton           __kmp_msg(kmp_ms_warning, KMP_MSG(SetAffSysCallNotSupported, env_var),
2603041982dSJonathan Peyton                     err_code, __kmp_msg_null);
2617cc577a4SJonathan Peyton           if (__kmp_generate_warnings == kmp_warnings_off) {
2627cc577a4SJonathan Peyton             __kmp_str_free(&err_code.str);
2637cc577a4SJonathan Peyton           }
2647cc577a4SJonathan Peyton         }
2657cc577a4SJonathan Peyton         KMP_AFFINITY_DISABLE();
2667cc577a4SJonathan Peyton         KMP_INTERNAL_FREE(buf);
2677cc577a4SJonathan Peyton         return;
2687cc577a4SJonathan Peyton       }
2697cc577a4SJonathan Peyton       if (errno == EFAULT) {
2707cc577a4SJonathan Peyton         KMP_AFFINITY_ENABLE(gCode);
2717cc577a4SJonathan Peyton         KA_TRACE(10, ("__kmp_affinity_determine_capable: "
2727cc577a4SJonathan Peyton                       "affinity supported (mask size %d)\n",
2737cc577a4SJonathan Peyton                       (int)__kmp_affin_mask_size));
2747cc577a4SJonathan Peyton         KMP_INTERNAL_FREE(buf);
2757cc577a4SJonathan Peyton         return;
2767cc577a4SJonathan Peyton       }
2777cc577a4SJonathan Peyton     }
2787cc577a4SJonathan Peyton   }
279f61f13d4SDavid Carlier #elif KMP_OS_FREEBSD
2806b316febSTerry Wilmarth   long gCode;
281f61f13d4SDavid Carlier   unsigned char *buf;
282f61f13d4SDavid Carlier   buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT);
283309b00a4SShilei Tian   gCode = pthread_getaffinity_np(pthread_self(), KMP_CPU_SET_SIZE_LIMIT,
284309b00a4SShilei Tian                                  reinterpret_cast<cpuset_t *>(buf));
285f61f13d4SDavid Carlier   KA_TRACE(30, ("__kmp_affinity_determine_capable: "
286f61f13d4SDavid Carlier                 "initial getaffinity call returned %d errno = %d\n",
287f61f13d4SDavid Carlier                 gCode, errno));
288f61f13d4SDavid Carlier   if (gCode == 0) {
289f61f13d4SDavid Carlier     KMP_AFFINITY_ENABLE(KMP_CPU_SET_SIZE_LIMIT);
290f61f13d4SDavid Carlier     KA_TRACE(10, ("__kmp_affinity_determine_capable: "
291ea99c099SDavid Carlier                   "affinity supported (mask size %d)\n",
292f61f13d4SDavid Carlier                   (int)__kmp_affin_mask_size));
293f61f13d4SDavid Carlier     KMP_INTERNAL_FREE(buf);
294f61f13d4SDavid Carlier     return;
295f61f13d4SDavid Carlier   }
296f61f13d4SDavid Carlier #endif
2973041982dSJonathan Peyton   // save uncaught error code
2983041982dSJonathan Peyton   // int error = errno;
2997cc577a4SJonathan Peyton   KMP_INTERNAL_FREE(buf);
3003041982dSJonathan Peyton   // restore uncaught error code, will be printed at the next KMP_WARNING below
3013041982dSJonathan Peyton   // errno = error;
3027cc577a4SJonathan Peyton 
3037cc577a4SJonathan Peyton   // Affinity is not supported
3047cc577a4SJonathan Peyton   KMP_AFFINITY_DISABLE();
3057cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_affinity_determine_capable: "
3067cc577a4SJonathan Peyton                 "cannot determine mask size - affinity not supported\n"));
3073041982dSJonathan Peyton   if (__kmp_affinity_verbose ||
3083041982dSJonathan Peyton       (__kmp_affinity_warnings && (__kmp_affinity_type != affinity_none) &&
3093041982dSJonathan Peyton        (__kmp_affinity_type != affinity_default) &&
3103041982dSJonathan Peyton        (__kmp_affinity_type != affinity_disabled))) {
3117cc577a4SJonathan Peyton     KMP_WARNING(AffCantGetMaskSize, env_var);
3127cc577a4SJonathan Peyton   }
3137cc577a4SJonathan Peyton }
3147cc577a4SJonathan Peyton 
3157cc577a4SJonathan Peyton #endif // KMP_OS_LINUX && KMP_AFFINITY_SUPPORTED
3167cc577a4SJonathan Peyton 
3177cc577a4SJonathan Peyton #if KMP_USE_FUTEX
3187cc577a4SJonathan Peyton 
3193041982dSJonathan Peyton int __kmp_futex_determine_capable() {
3207cc577a4SJonathan Peyton   int loc = 0;
3216b316febSTerry Wilmarth   long rc = syscall(__NR_futex, &loc, FUTEX_WAKE, 1, NULL, NULL, 0);
3227cc577a4SJonathan Peyton   int retval = (rc == 0) || (errno != ENOSYS);
3237cc577a4SJonathan Peyton 
3243041982dSJonathan Peyton   KA_TRACE(10,
3253041982dSJonathan Peyton            ("__kmp_futex_determine_capable: rc = %d errno = %d\n", rc, errno));
3267cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_futex_determine_capable: futex syscall%s supported\n",
3277cc577a4SJonathan Peyton                 retval ? "" : " not"));
3287cc577a4SJonathan Peyton 
3297cc577a4SJonathan Peyton   return retval;
3307cc577a4SJonathan Peyton }
3317cc577a4SJonathan Peyton 
3327cc577a4SJonathan Peyton #endif // KMP_USE_FUTEX
3337cc577a4SJonathan Peyton 
3347cc577a4SJonathan Peyton #if (KMP_ARCH_X86 || KMP_ARCH_X86_64) && (!KMP_ASM_INTRINS)
3353041982dSJonathan Peyton /* Only 32-bit "add-exchange" instruction on IA-32 architecture causes us to
3363041982dSJonathan Peyton    use compare_and_store for these routines */
3377cc577a4SJonathan Peyton 
3383041982dSJonathan Peyton kmp_int8 __kmp_test_then_or8(volatile kmp_int8 *p, kmp_int8 d) {
3397cc577a4SJonathan Peyton   kmp_int8 old_value, new_value;
3407cc577a4SJonathan Peyton 
3417cc577a4SJonathan Peyton   old_value = TCR_1(*p);
3427cc577a4SJonathan Peyton   new_value = old_value | d;
3437cc577a4SJonathan Peyton 
3443041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
3457cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
3467cc577a4SJonathan Peyton     old_value = TCR_1(*p);
3477cc577a4SJonathan Peyton     new_value = old_value | d;
3487cc577a4SJonathan Peyton   }
3497cc577a4SJonathan Peyton   return old_value;
3507cc577a4SJonathan Peyton }
3517cc577a4SJonathan Peyton 
3523041982dSJonathan Peyton kmp_int8 __kmp_test_then_and8(volatile kmp_int8 *p, kmp_int8 d) {
3537cc577a4SJonathan Peyton   kmp_int8 old_value, new_value;
3547cc577a4SJonathan Peyton 
3557cc577a4SJonathan Peyton   old_value = TCR_1(*p);
3567cc577a4SJonathan Peyton   new_value = old_value & d;
3577cc577a4SJonathan Peyton 
3583041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
3597cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
3607cc577a4SJonathan Peyton     old_value = TCR_1(*p);
3617cc577a4SJonathan Peyton     new_value = old_value & d;
3627cc577a4SJonathan Peyton   }
3637cc577a4SJonathan Peyton   return old_value;
3647cc577a4SJonathan Peyton }
3657cc577a4SJonathan Peyton 
3665ba90c79SAndrey Churbanov kmp_uint32 __kmp_test_then_or32(volatile kmp_uint32 *p, kmp_uint32 d) {
3675ba90c79SAndrey Churbanov   kmp_uint32 old_value, new_value;
3687cc577a4SJonathan Peyton 
3697cc577a4SJonathan Peyton   old_value = TCR_4(*p);
3707cc577a4SJonathan Peyton   new_value = old_value | d;
3717cc577a4SJonathan Peyton 
3723041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL32(p, old_value, new_value)) {
3737cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
3747cc577a4SJonathan Peyton     old_value = TCR_4(*p);
3757cc577a4SJonathan Peyton     new_value = old_value | d;
3767cc577a4SJonathan Peyton   }
3777cc577a4SJonathan Peyton   return old_value;
3787cc577a4SJonathan Peyton }
3797cc577a4SJonathan Peyton 
3805ba90c79SAndrey Churbanov kmp_uint32 __kmp_test_then_and32(volatile kmp_uint32 *p, kmp_uint32 d) {
3815ba90c79SAndrey Churbanov   kmp_uint32 old_value, new_value;
3827cc577a4SJonathan Peyton 
3837cc577a4SJonathan Peyton   old_value = TCR_4(*p);
3847cc577a4SJonathan Peyton   new_value = old_value & d;
3857cc577a4SJonathan Peyton 
3863041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL32(p, old_value, new_value)) {
3877cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
3887cc577a4SJonathan Peyton     old_value = TCR_4(*p);
3897cc577a4SJonathan Peyton     new_value = old_value & d;
3907cc577a4SJonathan Peyton   }
3917cc577a4SJonathan Peyton   return old_value;
3927cc577a4SJonathan Peyton }
3937cc577a4SJonathan Peyton 
394928b8ea2SJonathan Peyton #if KMP_ARCH_X86
3953041982dSJonathan Peyton kmp_int8 __kmp_test_then_add8(volatile kmp_int8 *p, kmp_int8 d) {
3967cc577a4SJonathan Peyton   kmp_int8 old_value, new_value;
3977cc577a4SJonathan Peyton 
3987cc577a4SJonathan Peyton   old_value = TCR_1(*p);
3997cc577a4SJonathan Peyton   new_value = old_value + d;
4007cc577a4SJonathan Peyton 
4013041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
4027cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
4037cc577a4SJonathan Peyton     old_value = TCR_1(*p);
4047cc577a4SJonathan Peyton     new_value = old_value + d;
4057cc577a4SJonathan Peyton   }
4067cc577a4SJonathan Peyton   return old_value;
4077cc577a4SJonathan Peyton }
4087cc577a4SJonathan Peyton 
4093041982dSJonathan Peyton kmp_int64 __kmp_test_then_add64(volatile kmp_int64 *p, kmp_int64 d) {
4107cc577a4SJonathan Peyton   kmp_int64 old_value, new_value;
4117cc577a4SJonathan Peyton 
4127cc577a4SJonathan Peyton   old_value = TCR_8(*p);
4137cc577a4SJonathan Peyton   new_value = old_value + d;
4147cc577a4SJonathan Peyton 
4153041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
4167cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
4177cc577a4SJonathan Peyton     old_value = TCR_8(*p);
4187cc577a4SJonathan Peyton     new_value = old_value + d;
4197cc577a4SJonathan Peyton   }
4207cc577a4SJonathan Peyton   return old_value;
4217cc577a4SJonathan Peyton }
422928b8ea2SJonathan Peyton #endif /* KMP_ARCH_X86 */
4237cc577a4SJonathan Peyton 
4245ba90c79SAndrey Churbanov kmp_uint64 __kmp_test_then_or64(volatile kmp_uint64 *p, kmp_uint64 d) {
4255ba90c79SAndrey Churbanov   kmp_uint64 old_value, new_value;
4267cc577a4SJonathan Peyton 
4277cc577a4SJonathan Peyton   old_value = TCR_8(*p);
4287cc577a4SJonathan Peyton   new_value = old_value | d;
4293041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
4307cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
4317cc577a4SJonathan Peyton     old_value = TCR_8(*p);
4327cc577a4SJonathan Peyton     new_value = old_value | d;
4337cc577a4SJonathan Peyton   }
4347cc577a4SJonathan Peyton   return old_value;
4357cc577a4SJonathan Peyton }
4367cc577a4SJonathan Peyton 
4375ba90c79SAndrey Churbanov kmp_uint64 __kmp_test_then_and64(volatile kmp_uint64 *p, kmp_uint64 d) {
4385ba90c79SAndrey Churbanov   kmp_uint64 old_value, new_value;
4397cc577a4SJonathan Peyton 
4407cc577a4SJonathan Peyton   old_value = TCR_8(*p);
4417cc577a4SJonathan Peyton   new_value = old_value & d;
4423041982dSJonathan Peyton   while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
4437cc577a4SJonathan Peyton     KMP_CPU_PAUSE();
4447cc577a4SJonathan Peyton     old_value = TCR_8(*p);
4457cc577a4SJonathan Peyton     new_value = old_value & d;
4467cc577a4SJonathan Peyton   }
4477cc577a4SJonathan Peyton   return old_value;
4487cc577a4SJonathan Peyton }
4497cc577a4SJonathan Peyton 
4507cc577a4SJonathan Peyton #endif /* (KMP_ARCH_X86 || KMP_ARCH_X86_64) && (! KMP_ASM_INTRINS) */
4517cc577a4SJonathan Peyton 
4523041982dSJonathan Peyton void __kmp_terminate_thread(int gtid) {
4537cc577a4SJonathan Peyton   int status;
4547cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[gtid];
4557cc577a4SJonathan Peyton 
4563041982dSJonathan Peyton   if (!th)
4573041982dSJonathan Peyton     return;
4587cc577a4SJonathan Peyton 
4597cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS
4607cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_terminate_thread: kill (%d)\n", gtid));
4617cc577a4SJonathan Peyton   status = pthread_cancel(th->th.th_info.ds.ds_thread);
4627cc577a4SJonathan Peyton   if (status != 0 && status != ESRCH) {
4636a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantTerminateWorkerThread), KMP_ERR(status),
4643041982dSJonathan Peyton                 __kmp_msg_null);
465bd3a7633SJonathan Peyton   }
4667cc577a4SJonathan Peyton #endif
467e47d32f1SJonathan Peyton   KMP_YIELD(TRUE);
4687cc577a4SJonathan Peyton } //
4697cc577a4SJonathan Peyton 
4703041982dSJonathan Peyton /* Set thread stack info according to values returned by pthread_getattr_np().
4713041982dSJonathan Peyton    If values are unreasonable, assume call failed and use incremental stack
4723041982dSJonathan Peyton    refinement method instead. Returns TRUE if the stack parameters could be
4733041982dSJonathan Peyton    determined exactly, FALSE if incremental refinement is necessary. */
4743041982dSJonathan Peyton static kmp_int32 __kmp_set_stack_info(int gtid, kmp_info_t *th) {
4757cc577a4SJonathan Peyton   int stack_data;
476a56ac949SKamil Rytarowski #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
477a56ac949SKamil Rytarowski     KMP_OS_HURD
4787cc577a4SJonathan Peyton   pthread_attr_t attr;
4797cc577a4SJonathan Peyton   int status;
4807cc577a4SJonathan Peyton   size_t size = 0;
4817cc577a4SJonathan Peyton   void *addr = 0;
4827cc577a4SJonathan Peyton 
4833041982dSJonathan Peyton   /* Always do incremental stack refinement for ubermaster threads since the
4843041982dSJonathan Peyton      initial thread stack range can be reduced by sibling thread creation so
4853041982dSJonathan Peyton      pthread_attr_getstack may cause thread gtid aliasing */
4867cc577a4SJonathan Peyton   if (!KMP_UBER_GTID(gtid)) {
4877cc577a4SJonathan Peyton 
4887cc577a4SJonathan Peyton     /* Fetch the real thread attributes */
4897cc577a4SJonathan Peyton     status = pthread_attr_init(&attr);
4907cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_attr_init", status);
491a56ac949SKamil Rytarowski #if KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD
4927cc577a4SJonathan Peyton     status = pthread_attr_get_np(pthread_self(), &attr);
4937cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_attr_get_np", status);
4947cc577a4SJonathan Peyton #else
4957cc577a4SJonathan Peyton     status = pthread_getattr_np(pthread_self(), &attr);
4967cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_getattr_np", status);
4977cc577a4SJonathan Peyton #endif
4987cc577a4SJonathan Peyton     status = pthread_attr_getstack(&attr, &addr, &size);
4997cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_attr_getstack", status);
5003041982dSJonathan Peyton     KA_TRACE(60,
5013041982dSJonathan Peyton              ("__kmp_set_stack_info: T#%d pthread_attr_getstack returned size:"
5023041982dSJonathan Peyton               " %lu, low addr: %p\n",
5037cc577a4SJonathan Peyton               gtid, size, addr));
5047cc577a4SJonathan Peyton     status = pthread_attr_destroy(&attr);
5057cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_attr_destroy", status);
5067cc577a4SJonathan Peyton   }
5077cc577a4SJonathan Peyton 
5083041982dSJonathan Peyton   if (size != 0 && addr != 0) { // was stack parameter determination successful?
5097cc577a4SJonathan Peyton     /* Store the correct base and size */
5107cc577a4SJonathan Peyton     TCW_PTR(th->th.th_info.ds.ds_stackbase, (((char *)addr) + size));
5117cc577a4SJonathan Peyton     TCW_PTR(th->th.th_info.ds.ds_stacksize, size);
5127cc577a4SJonathan Peyton     TCW_4(th->th.th_info.ds.ds_stackgrow, FALSE);
5137cc577a4SJonathan Peyton     return TRUE;
5147cc577a4SJonathan Peyton   }
515309b00a4SShilei Tian #endif /* KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD  \
516309b00a4SShilei Tian           || KMP_OS_HURD */
5177cc577a4SJonathan Peyton   /* Use incremental refinement starting from initial conservative estimate */
5187cc577a4SJonathan Peyton   TCW_PTR(th->th.th_info.ds.ds_stacksize, 0);
5197cc577a4SJonathan Peyton   TCW_PTR(th->th.th_info.ds.ds_stackbase, &stack_data);
5207cc577a4SJonathan Peyton   TCW_4(th->th.th_info.ds.ds_stackgrow, TRUE);
5217cc577a4SJonathan Peyton   return FALSE;
5227cc577a4SJonathan Peyton }
5237cc577a4SJonathan Peyton 
5243041982dSJonathan Peyton static void *__kmp_launch_worker(void *thr) {
5257cc577a4SJonathan Peyton   int status, old_type, old_state;
5267cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS
5277cc577a4SJonathan Peyton   sigset_t new_set, old_set;
5287cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */
5297cc577a4SJonathan Peyton   void *exit_val;
530a56ac949SKamil Rytarowski #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
5317e1ea993SKamil Rytarowski     KMP_OS_OPENBSD || KMP_OS_HURD
5327cc577a4SJonathan Peyton   void *volatile padding = 0;
5337cc577a4SJonathan Peyton #endif
5347cc577a4SJonathan Peyton   int gtid;
5357cc577a4SJonathan Peyton 
5367cc577a4SJonathan Peyton   gtid = ((kmp_info_t *)thr)->th.th_info.ds.ds_gtid;
5377cc577a4SJonathan Peyton   __kmp_gtid_set_specific(gtid);
5387cc577a4SJonathan Peyton #ifdef KMP_TDATA_GTID
5397cc577a4SJonathan Peyton   __kmp_gtid = gtid;
5407cc577a4SJonathan Peyton #endif
5417cc577a4SJonathan Peyton #if KMP_STATS_ENABLED
54240039ac9SJonathan Peyton   // set thread local index to point to thread-specific stats
5437cc577a4SJonathan Peyton   __kmp_stats_thread_ptr = ((kmp_info_t *)thr)->th.th_stats;
544f0682ac4SJonathan Peyton   __kmp_stats_thread_ptr->startLife();
5457cc577a4SJonathan Peyton   KMP_SET_THREAD_STATE(IDLE);
5467cc577a4SJonathan Peyton   KMP_INIT_PARTITIONED_TIMERS(OMP_idle);
5477cc577a4SJonathan Peyton #endif
5487cc577a4SJonathan Peyton 
5497cc577a4SJonathan Peyton #if USE_ITT_BUILD
5507cc577a4SJonathan Peyton   __kmp_itt_thread_name(gtid);
5517cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
5527cc577a4SJonathan Peyton 
5537cc577a4SJonathan Peyton #if KMP_AFFINITY_SUPPORTED
5547cc577a4SJonathan Peyton   __kmp_affinity_set_init_mask(gtid, FALSE);
5557cc577a4SJonathan Peyton #endif
5567cc577a4SJonathan Peyton 
5577cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS
5587cc577a4SJonathan Peyton   status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_type);
5597cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_setcanceltype", status);
5603041982dSJonathan Peyton   // josh todo: isn't PTHREAD_CANCEL_ENABLE default for newly-created threads?
5617cc577a4SJonathan Peyton   status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state);
5627cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_setcancelstate", status);
5637cc577a4SJonathan Peyton #endif
5647cc577a4SJonathan Peyton 
5657cc577a4SJonathan Peyton #if KMP_ARCH_X86 || KMP_ARCH_X86_64
5663041982dSJonathan Peyton   // Set FP control regs to be a copy of the parallel initialization thread's.
5677cc577a4SJonathan Peyton   __kmp_clear_x87_fpu_status_word();
5687cc577a4SJonathan Peyton   __kmp_load_x87_fpu_control_word(&__kmp_init_x87_fpu_control_word);
5697cc577a4SJonathan Peyton   __kmp_load_mxcsr(&__kmp_init_mxcsr);
5707cc577a4SJonathan Peyton #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
5717cc577a4SJonathan Peyton 
5727cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS
5737cc577a4SJonathan Peyton   status = sigfillset(&new_set);
5747cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("sigfillset", status);
5757cc577a4SJonathan Peyton   status = pthread_sigmask(SIG_BLOCK, &new_set, &old_set);
5767cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_sigmask", status);
5777cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */
5787cc577a4SJonathan Peyton 
5797e1ea993SKamil Rytarowski #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
5807e1ea993SKamil Rytarowski     KMP_OS_OPENBSD
5817cc577a4SJonathan Peyton   if (__kmp_stkoffset > 0 && gtid > 0) {
5827cc577a4SJonathan Peyton     padding = KMP_ALLOCA(gtid * __kmp_stkoffset);
5837cc577a4SJonathan Peyton   }
5847cc577a4SJonathan Peyton #endif
5857cc577a4SJonathan Peyton 
5867cc577a4SJonathan Peyton   KMP_MB();
5877cc577a4SJonathan Peyton   __kmp_set_stack_info(gtid, (kmp_info_t *)thr);
5887cc577a4SJonathan Peyton 
5897cc577a4SJonathan Peyton   __kmp_check_stack_overlap((kmp_info_t *)thr);
5907cc577a4SJonathan Peyton 
5917cc577a4SJonathan Peyton   exit_val = __kmp_launch_thread((kmp_info_t *)thr);
5927cc577a4SJonathan Peyton 
5937cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS
5947cc577a4SJonathan Peyton   status = pthread_sigmask(SIG_SETMASK, &old_set, NULL);
5957cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_sigmask", status);
5967cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */
5977cc577a4SJonathan Peyton 
5987cc577a4SJonathan Peyton   return exit_val;
5997cc577a4SJonathan Peyton }
6007cc577a4SJonathan Peyton 
6017cc577a4SJonathan Peyton #if KMP_USE_MONITOR
6027cc577a4SJonathan Peyton /* The monitor thread controls all of the threads in the complex */
6037cc577a4SJonathan Peyton 
6043041982dSJonathan Peyton static void *__kmp_launch_monitor(void *thr) {
6057cc577a4SJonathan Peyton   int status, old_type, old_state;
6067cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS
6077cc577a4SJonathan Peyton   sigset_t new_set;
6087cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */
6097cc577a4SJonathan Peyton   struct timespec interval;
6107cc577a4SJonathan Peyton 
6117cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
6127cc577a4SJonathan Peyton 
6137cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_launch_monitor: #1 launched\n"));
6147cc577a4SJonathan Peyton 
6157cc577a4SJonathan Peyton   /* register us as the monitor thread */
6167cc577a4SJonathan Peyton   __kmp_gtid_set_specific(KMP_GTID_MONITOR);
6177cc577a4SJonathan Peyton #ifdef KMP_TDATA_GTID
6187cc577a4SJonathan Peyton   __kmp_gtid = KMP_GTID_MONITOR;
6197cc577a4SJonathan Peyton #endif
6207cc577a4SJonathan Peyton 
6217cc577a4SJonathan Peyton   KMP_MB();
6227cc577a4SJonathan Peyton 
6237cc577a4SJonathan Peyton #if USE_ITT_BUILD
6243041982dSJonathan Peyton   // Instruct Intel(R) Threading Tools to ignore monitor thread.
6253041982dSJonathan Peyton   __kmp_itt_thread_ignore();
6267cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
6277cc577a4SJonathan Peyton 
6283041982dSJonathan Peyton   __kmp_set_stack_info(((kmp_info_t *)thr)->th.th_info.ds.ds_gtid,
6293041982dSJonathan Peyton                        (kmp_info_t *)thr);
6307cc577a4SJonathan Peyton 
6317cc577a4SJonathan Peyton   __kmp_check_stack_overlap((kmp_info_t *)thr);
6327cc577a4SJonathan Peyton 
6337cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS
6347cc577a4SJonathan Peyton   status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_type);
6357cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_setcanceltype", status);
6363041982dSJonathan Peyton   // josh todo: isn't PTHREAD_CANCEL_ENABLE default for newly-created threads?
6377cc577a4SJonathan Peyton   status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state);
6387cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_setcancelstate", status);
6397cc577a4SJonathan Peyton #endif
6407cc577a4SJonathan Peyton 
6417cc577a4SJonathan Peyton #if KMP_REAL_TIME_FIX
6423041982dSJonathan Peyton   // This is a potential fix which allows application with real-time scheduling
6433041982dSJonathan Peyton   // policy work. However, decision about the fix is not made yet, so it is
6443041982dSJonathan Peyton   // disabled by default.
6457cc577a4SJonathan Peyton   { // Are program started with real-time scheduling policy?
6467cc577a4SJonathan Peyton     int sched = sched_getscheduler(0);
6477cc577a4SJonathan Peyton     if (sched == SCHED_FIFO || sched == SCHED_RR) {
6483041982dSJonathan Peyton       // Yes, we are a part of real-time application. Try to increase the
6493041982dSJonathan Peyton       // priority of the monitor.
6507cc577a4SJonathan Peyton       struct sched_param param;
6517cc577a4SJonathan Peyton       int max_priority = sched_get_priority_max(sched);
6527cc577a4SJonathan Peyton       int rc;
6537cc577a4SJonathan Peyton       KMP_WARNING(RealTimeSchedNotSupported);
6547cc577a4SJonathan Peyton       sched_getparam(0, &param);
6557cc577a4SJonathan Peyton       if (param.sched_priority < max_priority) {
6567cc577a4SJonathan Peyton         param.sched_priority += 1;
6577cc577a4SJonathan Peyton         rc = sched_setscheduler(0, sched, &param);
6587cc577a4SJonathan Peyton         if (rc != 0) {
6597cc577a4SJonathan Peyton           int error = errno;
6607cc577a4SJonathan Peyton           kmp_msg_t err_code = KMP_ERR(error);
6613041982dSJonathan Peyton           __kmp_msg(kmp_ms_warning, KMP_MSG(CantChangeMonitorPriority),
6623041982dSJonathan Peyton                     err_code, KMP_MSG(MonitorWillStarve), __kmp_msg_null);
6637cc577a4SJonathan Peyton           if (__kmp_generate_warnings == kmp_warnings_off) {
6647cc577a4SJonathan Peyton             __kmp_str_free(&err_code.str);
6657cc577a4SJonathan Peyton           }
666bd3a7633SJonathan Peyton         }
6677cc577a4SJonathan Peyton       } else {
6683041982dSJonathan Peyton         // We cannot abort here, because number of CPUs may be enough for all
6693041982dSJonathan Peyton         // the threads, including the monitor thread, so application could
6703041982dSJonathan Peyton         // potentially work...
6713041982dSJonathan Peyton         __kmp_msg(kmp_ms_warning, KMP_MSG(RunningAtMaxPriority),
6723041982dSJonathan Peyton                   KMP_MSG(MonitorWillStarve), KMP_HNT(RunningAtMaxPriority),
6733041982dSJonathan Peyton                   __kmp_msg_null);
674bd3a7633SJonathan Peyton       }
675bd3a7633SJonathan Peyton     }
6763041982dSJonathan Peyton     // AC: free thread that waits for monitor started
6773041982dSJonathan Peyton     TCW_4(__kmp_global.g.g_time.dt.t_value, 0);
6787cc577a4SJonathan Peyton   }
6797cc577a4SJonathan Peyton #endif // KMP_REAL_TIME_FIX
6807cc577a4SJonathan Peyton 
6817cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
6827cc577a4SJonathan Peyton 
6837cc577a4SJonathan Peyton   if (__kmp_monitor_wakeups == 1) {
6847cc577a4SJonathan Peyton     interval.tv_sec = 1;
6857cc577a4SJonathan Peyton     interval.tv_nsec = 0;
6867cc577a4SJonathan Peyton   } else {
6877cc577a4SJonathan Peyton     interval.tv_sec = 0;
6887cc577a4SJonathan Peyton     interval.tv_nsec = (KMP_NSEC_PER_SEC / __kmp_monitor_wakeups);
6897cc577a4SJonathan Peyton   }
6907cc577a4SJonathan Peyton 
6917cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_launch_monitor: #2 monitor\n"));
6927cc577a4SJonathan Peyton 
6937cc577a4SJonathan Peyton   while (!TCR_4(__kmp_global.g.g_done)) {
6947cc577a4SJonathan Peyton     struct timespec now;
6957cc577a4SJonathan Peyton     struct timeval tval;
6967cc577a4SJonathan Peyton 
6977cc577a4SJonathan Peyton     /*  This thread monitors the state of the system */
6987cc577a4SJonathan Peyton 
6997cc577a4SJonathan Peyton     KA_TRACE(15, ("__kmp_launch_monitor: update\n"));
7007cc577a4SJonathan Peyton 
7017cc577a4SJonathan Peyton     status = gettimeofday(&tval, NULL);
7027cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
7037cc577a4SJonathan Peyton     TIMEVAL_TO_TIMESPEC(&tval, &now);
7047cc577a4SJonathan Peyton 
7057cc577a4SJonathan Peyton     now.tv_sec += interval.tv_sec;
7067cc577a4SJonathan Peyton     now.tv_nsec += interval.tv_nsec;
7077cc577a4SJonathan Peyton 
7087cc577a4SJonathan Peyton     if (now.tv_nsec >= KMP_NSEC_PER_SEC) {
7097cc577a4SJonathan Peyton       now.tv_sec += 1;
7107cc577a4SJonathan Peyton       now.tv_nsec -= KMP_NSEC_PER_SEC;
7117cc577a4SJonathan Peyton     }
7127cc577a4SJonathan Peyton 
7137cc577a4SJonathan Peyton     status = pthread_mutex_lock(&__kmp_wait_mx.m_mutex);
7147cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
7157cc577a4SJonathan Peyton     // AC: the monitor should not fall asleep if g_done has been set
7167cc577a4SJonathan Peyton     if (!TCR_4(__kmp_global.g.g_done)) { // check once more under mutex
7173041982dSJonathan Peyton       status = pthread_cond_timedwait(&__kmp_wait_cv.c_cond,
7183041982dSJonathan Peyton                                       &__kmp_wait_mx.m_mutex, &now);
7197cc577a4SJonathan Peyton       if (status != 0) {
7207cc577a4SJonathan Peyton         if (status != ETIMEDOUT && status != EINTR) {
7217cc577a4SJonathan Peyton           KMP_SYSFAIL("pthread_cond_timedwait", status);
722bd3a7633SJonathan Peyton         }
723bd3a7633SJonathan Peyton       }
724bd3a7633SJonathan Peyton     }
7257cc577a4SJonathan Peyton     status = pthread_mutex_unlock(&__kmp_wait_mx.m_mutex);
7267cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
7277cc577a4SJonathan Peyton 
7287cc577a4SJonathan Peyton     TCW_4(__kmp_global.g.g_time.dt.t_value,
7297cc577a4SJonathan Peyton           TCR_4(__kmp_global.g.g_time.dt.t_value) + 1);
7307cc577a4SJonathan Peyton 
7317cc577a4SJonathan Peyton     KMP_MB(); /* Flush all pending memory write invalidates.  */
7327cc577a4SJonathan Peyton   }
7337cc577a4SJonathan Peyton 
7347cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_launch_monitor: #3 cleanup\n"));
7357cc577a4SJonathan Peyton 
7367cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS
7377cc577a4SJonathan Peyton   status = sigfillset(&new_set);
7387cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("sigfillset", status);
7397cc577a4SJonathan Peyton   status = pthread_sigmask(SIG_UNBLOCK, &new_set, NULL);
7407cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_sigmask", status);
7417cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */
7427cc577a4SJonathan Peyton 
7437cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_launch_monitor: #4 finished\n"));
7447cc577a4SJonathan Peyton 
7457cc577a4SJonathan Peyton   if (__kmp_global.g.g_abort != 0) {
7467cc577a4SJonathan Peyton     /* now we need to terminate the worker threads  */
7477cc577a4SJonathan Peyton     /* the value of t_abort is the signal we caught */
7487cc577a4SJonathan Peyton 
7497cc577a4SJonathan Peyton     int gtid;
7507cc577a4SJonathan Peyton 
7513041982dSJonathan Peyton     KA_TRACE(10, ("__kmp_launch_monitor: #5 terminate sig=%d\n",
7523041982dSJonathan Peyton                   __kmp_global.g.g_abort));
7537cc577a4SJonathan Peyton 
7547cc577a4SJonathan Peyton     /* terminate the OpenMP worker threads */
7557cc577a4SJonathan Peyton     /* TODO this is not valid for sibling threads!!
7567cc577a4SJonathan Peyton      * the uber master might not be 0 anymore.. */
7577cc577a4SJonathan Peyton     for (gtid = 1; gtid < __kmp_threads_capacity; ++gtid)
7587cc577a4SJonathan Peyton       __kmp_terminate_thread(gtid);
7597cc577a4SJonathan Peyton 
7607cc577a4SJonathan Peyton     __kmp_cleanup();
7617cc577a4SJonathan Peyton 
7623041982dSJonathan Peyton     KA_TRACE(10, ("__kmp_launch_monitor: #6 raise sig=%d\n",
7633041982dSJonathan Peyton                   __kmp_global.g.g_abort));
7647cc577a4SJonathan Peyton 
7657cc577a4SJonathan Peyton     if (__kmp_global.g.g_abort > 0)
7667cc577a4SJonathan Peyton       raise(__kmp_global.g.g_abort);
7677cc577a4SJonathan Peyton   }
7687cc577a4SJonathan Peyton 
7697cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_launch_monitor: #7 exit\n"));
7707cc577a4SJonathan Peyton 
7717cc577a4SJonathan Peyton   return thr;
7727cc577a4SJonathan Peyton }
7737cc577a4SJonathan Peyton #endif // KMP_USE_MONITOR
7747cc577a4SJonathan Peyton 
7753041982dSJonathan Peyton void __kmp_create_worker(int gtid, kmp_info_t *th, size_t stack_size) {
7767cc577a4SJonathan Peyton   pthread_t handle;
7777cc577a4SJonathan Peyton   pthread_attr_t thread_attr;
7787cc577a4SJonathan Peyton   int status;
7797cc577a4SJonathan Peyton 
7807cc577a4SJonathan Peyton   th->th.th_info.ds.ds_gtid = gtid;
7817cc577a4SJonathan Peyton 
7827cc577a4SJonathan Peyton #if KMP_STATS_ENABLED
7837cc577a4SJonathan Peyton   // sets up worker thread stats
7847cc577a4SJonathan Peyton   __kmp_acquire_tas_lock(&__kmp_stats_lock, gtid);
7857cc577a4SJonathan Peyton 
7863041982dSJonathan Peyton   // th->th.th_stats is used to transfer thread-specific stats-pointer to
7873041982dSJonathan Peyton   // __kmp_launch_worker. So when thread is created (goes into
78840039ac9SJonathan Peyton   // __kmp_launch_worker) it will set its thread local pointer to
7893041982dSJonathan Peyton   // th->th.th_stats
7907cc577a4SJonathan Peyton   if (!KMP_UBER_GTID(gtid)) {
7917cc577a4SJonathan Peyton     th->th.th_stats = __kmp_stats_list->push_back(gtid);
7927cc577a4SJonathan Peyton   } else {
7933041982dSJonathan Peyton     // For root threads, __kmp_stats_thread_ptr is set in __kmp_register_root(),
7943041982dSJonathan Peyton     // so set the th->th.th_stats field to it.
7957cc577a4SJonathan Peyton     th->th.th_stats = __kmp_stats_thread_ptr;
7967cc577a4SJonathan Peyton   }
7977cc577a4SJonathan Peyton   __kmp_release_tas_lock(&__kmp_stats_lock, gtid);
7987cc577a4SJonathan Peyton 
7997cc577a4SJonathan Peyton #endif // KMP_STATS_ENABLED
8007cc577a4SJonathan Peyton 
8017cc577a4SJonathan Peyton   if (KMP_UBER_GTID(gtid)) {
8027cc577a4SJonathan Peyton     KA_TRACE(10, ("__kmp_create_worker: uber thread (%d)\n", gtid));
8037cc577a4SJonathan Peyton     th->th.th_info.ds.ds_thread = pthread_self();
8047cc577a4SJonathan Peyton     __kmp_set_stack_info(gtid, th);
8057cc577a4SJonathan Peyton     __kmp_check_stack_overlap(th);
8067cc577a4SJonathan Peyton     return;
807bd3a7633SJonathan Peyton   }
8087cc577a4SJonathan Peyton 
8097cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_worker: try to create thread (%d)\n", gtid));
8107cc577a4SJonathan Peyton 
8117cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
8127cc577a4SJonathan Peyton 
8137cc577a4SJonathan Peyton #ifdef KMP_THREAD_ATTR
8147cc577a4SJonathan Peyton   status = pthread_attr_init(&thread_attr);
8157cc577a4SJonathan Peyton   if (status != 0) {
8166a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantInitThreadAttrs), KMP_ERR(status), __kmp_msg_null);
817bd3a7633SJonathan Peyton   }
8187cc577a4SJonathan Peyton   status = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
8197cc577a4SJonathan Peyton   if (status != 0) {
8206a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantSetWorkerState), KMP_ERR(status), __kmp_msg_null);
821bd3a7633SJonathan Peyton   }
8227cc577a4SJonathan Peyton 
8237cc577a4SJonathan Peyton   /* Set stack size for this thread now.
8243041982dSJonathan Peyton      The multiple of 2 is there because on some machines, requesting an unusual
8253041982dSJonathan Peyton      stacksize causes the thread to have an offset before the dummy alloca()
8263041982dSJonathan Peyton      takes place to create the offset.  Since we want the user to have a
8273041982dSJonathan Peyton      sufficient stacksize AND support a stack offset, we alloca() twice the
8283041982dSJonathan Peyton      offset so that the upcoming alloca() does not eliminate any premade offset,
8293041982dSJonathan Peyton      and also gives the user the stack space they requested for all threads */
8307cc577a4SJonathan Peyton   stack_size += gtid * __kmp_stkoffset * 2;
8317cc577a4SJonathan Peyton 
8323d21a3afSYi Kong #if defined(__ANDROID__) && __ANDROID_API__ < 19
8333d21a3afSYi Kong   // Round the stack size to a multiple of the page size. Older versions of
8343d21a3afSYi Kong   // Android (until KitKat) would fail pthread_attr_setstacksize with EINVAL
8353d21a3afSYi Kong   // if the stack size was not a multiple of the page size.
8363d21a3afSYi Kong   stack_size = (stack_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
8373d21a3afSYi Kong #endif
8383d21a3afSYi Kong 
8397cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_worker: T#%d, default stacksize = %lu bytes, "
8407cc577a4SJonathan Peyton                 "__kmp_stksize = %lu bytes, final stacksize = %lu bytes\n",
8417cc577a4SJonathan Peyton                 gtid, KMP_DEFAULT_STKSIZE, __kmp_stksize, stack_size));
8427cc577a4SJonathan Peyton 
8437cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE
8447cc577a4SJonathan Peyton   status = pthread_attr_setstacksize(&thread_attr, stack_size);
8457cc577a4SJonathan Peyton #ifdef KMP_BACKUP_STKSIZE
8467cc577a4SJonathan Peyton   if (status != 0) {
8477cc577a4SJonathan Peyton     if (!__kmp_env_stksize) {
8487cc577a4SJonathan Peyton       stack_size = KMP_BACKUP_STKSIZE + gtid * __kmp_stkoffset;
8497cc577a4SJonathan Peyton       __kmp_stksize = KMP_BACKUP_STKSIZE;
8507cc577a4SJonathan Peyton       KA_TRACE(10, ("__kmp_create_worker: T#%d, default stacksize = %lu bytes, "
8517cc577a4SJonathan Peyton                     "__kmp_stksize = %lu bytes, (backup) final stacksize = %lu "
8527cc577a4SJonathan Peyton                     "bytes\n",
8533041982dSJonathan Peyton                     gtid, KMP_DEFAULT_STKSIZE, __kmp_stksize, stack_size));
8547cc577a4SJonathan Peyton       status = pthread_attr_setstacksize(&thread_attr, stack_size);
855bd3a7633SJonathan Peyton     }
856bd3a7633SJonathan Peyton   }
8577cc577a4SJonathan Peyton #endif /* KMP_BACKUP_STKSIZE */
8587cc577a4SJonathan Peyton   if (status != 0) {
8596a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantSetWorkerStackSize, stack_size), KMP_ERR(status),
8606a393f75SJonathan Peyton                 KMP_HNT(ChangeWorkerStackSize), __kmp_msg_null);
861bd3a7633SJonathan Peyton   }
8627cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
8637cc577a4SJonathan Peyton 
8647cc577a4SJonathan Peyton #endif /* KMP_THREAD_ATTR */
8657cc577a4SJonathan Peyton 
8663041982dSJonathan Peyton   status =
8673041982dSJonathan Peyton       pthread_create(&handle, &thread_attr, __kmp_launch_worker, (void *)th);
8687cc577a4SJonathan Peyton   if (status != 0 || !handle) { // ??? Why do we check handle??
8697cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE
8707cc577a4SJonathan Peyton     if (status == EINVAL) {
8716a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(CantSetWorkerStackSize, stack_size), KMP_ERR(status),
8726a393f75SJonathan Peyton                   KMP_HNT(IncreaseWorkerStackSize), __kmp_msg_null);
873bd3a7633SJonathan Peyton     }
8747cc577a4SJonathan Peyton     if (status == ENOMEM) {
8756a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(CantSetWorkerStackSize, stack_size), KMP_ERR(status),
8766a393f75SJonathan Peyton                   KMP_HNT(DecreaseWorkerStackSize), __kmp_msg_null);
877bd3a7633SJonathan Peyton     }
8787cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
8797cc577a4SJonathan Peyton     if (status == EAGAIN) {
8806a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(NoResourcesForWorkerThread), KMP_ERR(status),
8816a393f75SJonathan Peyton                   KMP_HNT(Decrease_NUM_THREADS), __kmp_msg_null);
882bd3a7633SJonathan Peyton     }
8837cc577a4SJonathan Peyton     KMP_SYSFAIL("pthread_create", status);
884bd3a7633SJonathan Peyton   }
8857cc577a4SJonathan Peyton 
8867cc577a4SJonathan Peyton   th->th.th_info.ds.ds_thread = handle;
8877cc577a4SJonathan Peyton 
8887cc577a4SJonathan Peyton #ifdef KMP_THREAD_ATTR
8897cc577a4SJonathan Peyton   status = pthread_attr_destroy(&thread_attr);
8907cc577a4SJonathan Peyton   if (status) {
8917cc577a4SJonathan Peyton     kmp_msg_t err_code = KMP_ERR(status);
8923041982dSJonathan Peyton     __kmp_msg(kmp_ms_warning, KMP_MSG(CantDestroyThreadAttrs), err_code,
8933041982dSJonathan Peyton               __kmp_msg_null);
8947cc577a4SJonathan Peyton     if (__kmp_generate_warnings == kmp_warnings_off) {
8957cc577a4SJonathan Peyton       __kmp_str_free(&err_code.str);
8967cc577a4SJonathan Peyton     }
897bd3a7633SJonathan Peyton   }
8987cc577a4SJonathan Peyton #endif /* KMP_THREAD_ATTR */
8997cc577a4SJonathan Peyton 
9007cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
9017cc577a4SJonathan Peyton 
9027cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_worker: done creating thread (%d)\n", gtid));
9037cc577a4SJonathan Peyton 
9047cc577a4SJonathan Peyton } // __kmp_create_worker
9057cc577a4SJonathan Peyton 
9067cc577a4SJonathan Peyton #if KMP_USE_MONITOR
9073041982dSJonathan Peyton void __kmp_create_monitor(kmp_info_t *th) {
9087cc577a4SJonathan Peyton   pthread_t handle;
9097cc577a4SJonathan Peyton   pthread_attr_t thread_attr;
9107cc577a4SJonathan Peyton   size_t size;
9117cc577a4SJonathan Peyton   int status;
9127cc577a4SJonathan Peyton   int auto_adj_size = FALSE;
9137cc577a4SJonathan Peyton 
9147cc577a4SJonathan Peyton   if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME) {
9157cc577a4SJonathan Peyton     // We don't need monitor thread in case of MAX_BLOCKTIME
9163041982dSJonathan Peyton     KA_TRACE(10, ("__kmp_create_monitor: skipping monitor thread because of "
9173041982dSJonathan Peyton                   "MAX blocktime\n"));
9187cc577a4SJonathan Peyton     th->th.th_info.ds.ds_tid = 0; // this makes reap_monitor no-op
9197cc577a4SJonathan Peyton     th->th.th_info.ds.ds_gtid = 0;
9207cc577a4SJonathan Peyton     return;
9217cc577a4SJonathan Peyton   }
9227cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_monitor: try to create monitor\n"));
9237cc577a4SJonathan Peyton 
9247cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
9257cc577a4SJonathan Peyton 
9267cc577a4SJonathan Peyton   th->th.th_info.ds.ds_tid = KMP_GTID_MONITOR;
9277cc577a4SJonathan Peyton   th->th.th_info.ds.ds_gtid = KMP_GTID_MONITOR;
9287cc577a4SJonathan Peyton #if KMP_REAL_TIME_FIX
9293041982dSJonathan Peyton   TCW_4(__kmp_global.g.g_time.dt.t_value,
9303041982dSJonathan Peyton         -1); // Will use it for synchronization a bit later.
9317cc577a4SJonathan Peyton #else
9327cc577a4SJonathan Peyton   TCW_4(__kmp_global.g.g_time.dt.t_value, 0);
9337cc577a4SJonathan Peyton #endif // KMP_REAL_TIME_FIX
9347cc577a4SJonathan Peyton 
9357cc577a4SJonathan Peyton #ifdef KMP_THREAD_ATTR
9367cc577a4SJonathan Peyton   if (__kmp_monitor_stksize == 0) {
9377cc577a4SJonathan Peyton     __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE;
9387cc577a4SJonathan Peyton     auto_adj_size = TRUE;
9397cc577a4SJonathan Peyton   }
9407cc577a4SJonathan Peyton   status = pthread_attr_init(&thread_attr);
9417cc577a4SJonathan Peyton   if (status != 0) {
9426a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantInitThreadAttrs), KMP_ERR(status), __kmp_msg_null);
943bd3a7633SJonathan Peyton   }
9447cc577a4SJonathan Peyton   status = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
9457cc577a4SJonathan Peyton   if (status != 0) {
9466a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantSetMonitorState), KMP_ERR(status), __kmp_msg_null);
947bd3a7633SJonathan Peyton   }
9487cc577a4SJonathan Peyton 
9497cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE
9507cc577a4SJonathan Peyton   status = pthread_attr_getstacksize(&thread_attr, &size);
9517cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_attr_getstacksize", status);
9527cc577a4SJonathan Peyton #else
9537cc577a4SJonathan Peyton   size = __kmp_sys_min_stksize;
9547cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
9557cc577a4SJonathan Peyton #endif /* KMP_THREAD_ATTR */
9567cc577a4SJonathan Peyton 
9577cc577a4SJonathan Peyton   if (__kmp_monitor_stksize == 0) {
9587cc577a4SJonathan Peyton     __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE;
9597cc577a4SJonathan Peyton   }
9607cc577a4SJonathan Peyton   if (__kmp_monitor_stksize < __kmp_sys_min_stksize) {
9617cc577a4SJonathan Peyton     __kmp_monitor_stksize = __kmp_sys_min_stksize;
9627cc577a4SJonathan Peyton   }
9637cc577a4SJonathan Peyton 
9647cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_monitor: default stacksize = %lu bytes,"
9657cc577a4SJonathan Peyton                 "requested stacksize = %lu bytes\n",
9667cc577a4SJonathan Peyton                 size, __kmp_monitor_stksize));
9677cc577a4SJonathan Peyton 
9687cc577a4SJonathan Peyton retry:
9697cc577a4SJonathan Peyton 
9707cc577a4SJonathan Peyton /* Set stack size for this thread now. */
9717cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE
9727cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_monitor: setting stacksize = %lu bytes,",
9737cc577a4SJonathan Peyton                 __kmp_monitor_stksize));
9747cc577a4SJonathan Peyton   status = pthread_attr_setstacksize(&thread_attr, __kmp_monitor_stksize);
9757cc577a4SJonathan Peyton   if (status != 0) {
9767cc577a4SJonathan Peyton     if (auto_adj_size) {
9777cc577a4SJonathan Peyton       __kmp_monitor_stksize *= 2;
9787cc577a4SJonathan Peyton       goto retry;
9797cc577a4SJonathan Peyton     }
9807cc577a4SJonathan Peyton     kmp_msg_t err_code = KMP_ERR(status);
9813041982dSJonathan Peyton     __kmp_msg(kmp_ms_warning, // should this be fatal?  BB
9827cc577a4SJonathan Peyton               KMP_MSG(CantSetMonitorStackSize, (long int)__kmp_monitor_stksize),
9833041982dSJonathan Peyton               err_code, KMP_HNT(ChangeMonitorStackSize), __kmp_msg_null);
9847cc577a4SJonathan Peyton     if (__kmp_generate_warnings == kmp_warnings_off) {
9857cc577a4SJonathan Peyton       __kmp_str_free(&err_code.str);
9867cc577a4SJonathan Peyton     }
987bd3a7633SJonathan Peyton   }
9887cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
9897cc577a4SJonathan Peyton 
9903041982dSJonathan Peyton   status =
9913041982dSJonathan Peyton       pthread_create(&handle, &thread_attr, __kmp_launch_monitor, (void *)th);
9927cc577a4SJonathan Peyton 
9937cc577a4SJonathan Peyton   if (status != 0) {
9947cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE
9957cc577a4SJonathan Peyton     if (status == EINVAL) {
9967cc577a4SJonathan Peyton       if (auto_adj_size && (__kmp_monitor_stksize < (size_t)0x40000000)) {
9977cc577a4SJonathan Peyton         __kmp_monitor_stksize *= 2;
9987cc577a4SJonathan Peyton         goto retry;
9997cc577a4SJonathan Peyton       }
10006a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(CantSetMonitorStackSize, __kmp_monitor_stksize),
10016a393f75SJonathan Peyton                   KMP_ERR(status), KMP_HNT(IncreaseMonitorStackSize),
10026a393f75SJonathan Peyton                   __kmp_msg_null);
1003bd3a7633SJonathan Peyton     }
10047cc577a4SJonathan Peyton     if (status == ENOMEM) {
10056a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(CantSetMonitorStackSize, __kmp_monitor_stksize),
10066a393f75SJonathan Peyton                   KMP_ERR(status), KMP_HNT(DecreaseMonitorStackSize),
10076a393f75SJonathan Peyton                   __kmp_msg_null);
1008bd3a7633SJonathan Peyton     }
10097cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
10107cc577a4SJonathan Peyton     if (status == EAGAIN) {
10116a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(NoResourcesForMonitorThread), KMP_ERR(status),
10126a393f75SJonathan Peyton                   KMP_HNT(DecreaseNumberOfThreadsInUse), __kmp_msg_null);
1013bd3a7633SJonathan Peyton     }
10147cc577a4SJonathan Peyton     KMP_SYSFAIL("pthread_create", status);
1015bd3a7633SJonathan Peyton   }
10167cc577a4SJonathan Peyton 
10177cc577a4SJonathan Peyton   th->th.th_info.ds.ds_thread = handle;
10187cc577a4SJonathan Peyton 
10197cc577a4SJonathan Peyton #if KMP_REAL_TIME_FIX
10207cc577a4SJonathan Peyton   // Wait for the monitor thread is really started and set its *priority*.
10213041982dSJonathan Peyton   KMP_DEBUG_ASSERT(sizeof(kmp_uint32) ==
10223041982dSJonathan Peyton                    sizeof(__kmp_global.g.g_time.dt.t_value));
1023e47d32f1SJonathan Peyton   __kmp_wait_4((kmp_uint32 volatile *)&__kmp_global.g.g_time.dt.t_value, -1,
1024e47d32f1SJonathan Peyton                &__kmp_neq_4, NULL);
10257cc577a4SJonathan Peyton #endif // KMP_REAL_TIME_FIX
10267cc577a4SJonathan Peyton 
10277cc577a4SJonathan Peyton #ifdef KMP_THREAD_ATTR
10287cc577a4SJonathan Peyton   status = pthread_attr_destroy(&thread_attr);
10297cc577a4SJonathan Peyton   if (status != 0) {
10307cc577a4SJonathan Peyton     kmp_msg_t err_code = KMP_ERR(status);
10313041982dSJonathan Peyton     __kmp_msg(kmp_ms_warning, KMP_MSG(CantDestroyThreadAttrs), err_code,
10323041982dSJonathan Peyton               __kmp_msg_null);
10337cc577a4SJonathan Peyton     if (__kmp_generate_warnings == kmp_warnings_off) {
10347cc577a4SJonathan Peyton       __kmp_str_free(&err_code.str);
10357cc577a4SJonathan Peyton     }
1036bd3a7633SJonathan Peyton   }
10377cc577a4SJonathan Peyton #endif
10387cc577a4SJonathan Peyton 
10397cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
10407cc577a4SJonathan Peyton 
10413041982dSJonathan Peyton   KA_TRACE(10, ("__kmp_create_monitor: monitor created %#.8lx\n",
10423041982dSJonathan Peyton                 th->th.th_info.ds.ds_thread));
10437cc577a4SJonathan Peyton 
10447cc577a4SJonathan Peyton } // __kmp_create_monitor
10457cc577a4SJonathan Peyton #endif // KMP_USE_MONITOR
10467cc577a4SJonathan Peyton 
10473041982dSJonathan Peyton void __kmp_exit_thread(int exit_status) {
10487cc577a4SJonathan Peyton   pthread_exit((void *)(intptr_t)exit_status);
10497cc577a4SJonathan Peyton } // __kmp_exit_thread
10507cc577a4SJonathan Peyton 
10517cc577a4SJonathan Peyton #if KMP_USE_MONITOR
10527cc577a4SJonathan Peyton void __kmp_resume_monitor();
10537cc577a4SJonathan Peyton 
10543041982dSJonathan Peyton void __kmp_reap_monitor(kmp_info_t *th) {
10557cc577a4SJonathan Peyton   int status;
10567cc577a4SJonathan Peyton   void *exit_val;
10577cc577a4SJonathan Peyton 
10583041982dSJonathan Peyton   KA_TRACE(10, ("__kmp_reap_monitor: try to reap monitor thread with handle"
10593041982dSJonathan Peyton                 " %#.8lx\n",
10607cc577a4SJonathan Peyton                 th->th.th_info.ds.ds_thread));
10617cc577a4SJonathan Peyton 
10627cc577a4SJonathan Peyton   // If monitor has been created, its tid and gtid should be KMP_GTID_MONITOR.
10637cc577a4SJonathan Peyton   // If both tid and gtid are 0, it means the monitor did not ever start.
10647cc577a4SJonathan Peyton   // If both tid and gtid are KMP_GTID_DNE, the monitor has been shut down.
10657cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(th->th.th_info.ds.ds_tid == th->th.th_info.ds.ds_gtid);
10667cc577a4SJonathan Peyton   if (th->th.th_info.ds.ds_gtid != KMP_GTID_MONITOR) {
10677cc577a4SJonathan Peyton     KA_TRACE(10, ("__kmp_reap_monitor: monitor did not start, returning\n"));
10687cc577a4SJonathan Peyton     return;
1069bd3a7633SJonathan Peyton   }
10707cc577a4SJonathan Peyton 
10717cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
10727cc577a4SJonathan Peyton 
10733041982dSJonathan Peyton   /* First, check to see whether the monitor thread exists to wake it up. This
10743041982dSJonathan Peyton      is to avoid performance problem when the monitor sleeps during
10753041982dSJonathan Peyton      blocktime-size interval */
10767cc577a4SJonathan Peyton 
10777cc577a4SJonathan Peyton   status = pthread_kill(th->th.th_info.ds.ds_thread, 0);
10787cc577a4SJonathan Peyton   if (status != ESRCH) {
10797cc577a4SJonathan Peyton     __kmp_resume_monitor(); // Wake up the monitor thread
10807cc577a4SJonathan Peyton   }
10817cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_reap_monitor: try to join with monitor\n"));
10827cc577a4SJonathan Peyton   status = pthread_join(th->th.th_info.ds.ds_thread, &exit_val);
10837cc577a4SJonathan Peyton   if (exit_val != th) {
10846a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(ReapMonitorError), KMP_ERR(status), __kmp_msg_null);
10857cc577a4SJonathan Peyton   }
10867cc577a4SJonathan Peyton 
10877cc577a4SJonathan Peyton   th->th.th_info.ds.ds_tid = KMP_GTID_DNE;
10887cc577a4SJonathan Peyton   th->th.th_info.ds.ds_gtid = KMP_GTID_DNE;
10897cc577a4SJonathan Peyton 
10903041982dSJonathan Peyton   KA_TRACE(10, ("__kmp_reap_monitor: done reaping monitor thread with handle"
10913041982dSJonathan Peyton                 " %#.8lx\n",
10927cc577a4SJonathan Peyton                 th->th.th_info.ds.ds_thread));
10937cc577a4SJonathan Peyton 
10947cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
10957cc577a4SJonathan Peyton }
10967cc577a4SJonathan Peyton #endif // KMP_USE_MONITOR
10977cc577a4SJonathan Peyton 
10983041982dSJonathan Peyton void __kmp_reap_worker(kmp_info_t *th) {
10997cc577a4SJonathan Peyton   int status;
11007cc577a4SJonathan Peyton   void *exit_val;
11017cc577a4SJonathan Peyton 
11027cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
11037cc577a4SJonathan Peyton 
11043041982dSJonathan Peyton   KA_TRACE(
11053041982dSJonathan Peyton       10, ("__kmp_reap_worker: try to reap T#%d\n", th->th.th_info.ds.ds_gtid));
11067cc577a4SJonathan Peyton 
11077cc577a4SJonathan Peyton   status = pthread_join(th->th.th_info.ds.ds_thread, &exit_val);
11087cc577a4SJonathan Peyton #ifdef KMP_DEBUG
11097cc577a4SJonathan Peyton   /* Don't expose these to the user until we understand when they trigger */
11107cc577a4SJonathan Peyton   if (status != 0) {
11116a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(ReapWorkerError), KMP_ERR(status), __kmp_msg_null);
11127cc577a4SJonathan Peyton   }
11137cc577a4SJonathan Peyton   if (exit_val != th) {
11143041982dSJonathan Peyton     KA_TRACE(10, ("__kmp_reap_worker: worker T#%d did not reap properly, "
11153041982dSJonathan Peyton                   "exit_val = %p\n",
11167cc577a4SJonathan Peyton                   th->th.th_info.ds.ds_gtid, exit_val));
11177cc577a4SJonathan Peyton   }
11187cc577a4SJonathan Peyton #endif /* KMP_DEBUG */
11197cc577a4SJonathan Peyton 
11203041982dSJonathan Peyton   KA_TRACE(10, ("__kmp_reap_worker: done reaping T#%d\n",
11213041982dSJonathan Peyton                 th->th.th_info.ds.ds_gtid));
11227cc577a4SJonathan Peyton 
11237cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
11247cc577a4SJonathan Peyton }
11257cc577a4SJonathan Peyton 
11267cc577a4SJonathan Peyton #if KMP_HANDLE_SIGNALS
11277cc577a4SJonathan Peyton 
11283041982dSJonathan Peyton static void __kmp_null_handler(int signo) {
11297cc577a4SJonathan Peyton   //  Do nothing, for doing SIG_IGN-type actions.
11307cc577a4SJonathan Peyton } // __kmp_null_handler
11317cc577a4SJonathan Peyton 
11323041982dSJonathan Peyton static void __kmp_team_handler(int signo) {
11337cc577a4SJonathan Peyton   if (__kmp_global.g.g_abort == 0) {
11347cc577a4SJonathan Peyton /* Stage 1 signal handler, let's shut down all of the threads */
11357cc577a4SJonathan Peyton #ifdef KMP_DEBUG
11367cc577a4SJonathan Peyton     __kmp_debug_printf("__kmp_team_handler: caught signal = %d\n", signo);
11377cc577a4SJonathan Peyton #endif
11387cc577a4SJonathan Peyton     switch (signo) {
11397cc577a4SJonathan Peyton     case SIGHUP:
11407cc577a4SJonathan Peyton     case SIGINT:
11417cc577a4SJonathan Peyton     case SIGQUIT:
11427cc577a4SJonathan Peyton     case SIGILL:
11437cc577a4SJonathan Peyton     case SIGABRT:
11447cc577a4SJonathan Peyton     case SIGFPE:
11457cc577a4SJonathan Peyton     case SIGBUS:
11467cc577a4SJonathan Peyton     case SIGSEGV:
11477cc577a4SJonathan Peyton #ifdef SIGSYS
11487cc577a4SJonathan Peyton     case SIGSYS:
11497cc577a4SJonathan Peyton #endif
11507cc577a4SJonathan Peyton     case SIGTERM:
11517cc577a4SJonathan Peyton       if (__kmp_debug_buf) {
11527cc577a4SJonathan Peyton         __kmp_dump_debug_buffer();
1153bd3a7633SJonathan Peyton       }
11549615890dSTodd Erdner       __kmp_unregister_library(); // cleanup shared memory
11557cc577a4SJonathan Peyton       KMP_MB(); // Flush all pending memory write invalidates.
11567cc577a4SJonathan Peyton       TCW_4(__kmp_global.g.g_abort, signo);
11577cc577a4SJonathan Peyton       KMP_MB(); // Flush all pending memory write invalidates.
11587cc577a4SJonathan Peyton       TCW_4(__kmp_global.g.g_done, TRUE);
11597cc577a4SJonathan Peyton       KMP_MB(); // Flush all pending memory write invalidates.
11607cc577a4SJonathan Peyton       break;
11617cc577a4SJonathan Peyton     default:
11627cc577a4SJonathan Peyton #ifdef KMP_DEBUG
11637cc577a4SJonathan Peyton       __kmp_debug_printf("__kmp_team_handler: unknown signal type");
11647cc577a4SJonathan Peyton #endif
11657cc577a4SJonathan Peyton       break;
1166bd3a7633SJonathan Peyton     }
1167bd3a7633SJonathan Peyton   }
11687cc577a4SJonathan Peyton } // __kmp_team_handler
11697cc577a4SJonathan Peyton 
11703041982dSJonathan Peyton static void __kmp_sigaction(int signum, const struct sigaction *act,
11713041982dSJonathan Peyton                             struct sigaction *oldact) {
11727cc577a4SJonathan Peyton   int rc = sigaction(signum, act, oldact);
11737cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("sigaction", rc);
11747cc577a4SJonathan Peyton }
11757cc577a4SJonathan Peyton 
11763041982dSJonathan Peyton static void __kmp_install_one_handler(int sig, sig_func_t handler_func,
11773041982dSJonathan Peyton                                       int parallel_init) {
11787cc577a4SJonathan Peyton   KMP_MB(); // Flush all pending memory write invalidates.
11793041982dSJonathan Peyton   KB_TRACE(60,
11803041982dSJonathan Peyton            ("__kmp_install_one_handler( %d, ..., %d )\n", sig, parallel_init));
11817cc577a4SJonathan Peyton   if (parallel_init) {
11827cc577a4SJonathan Peyton     struct sigaction new_action;
11837cc577a4SJonathan Peyton     struct sigaction old_action;
11847cc577a4SJonathan Peyton     new_action.sa_handler = handler_func;
11857cc577a4SJonathan Peyton     new_action.sa_flags = 0;
11867cc577a4SJonathan Peyton     sigfillset(&new_action.sa_mask);
11877cc577a4SJonathan Peyton     __kmp_sigaction(sig, &new_action, &old_action);
11887cc577a4SJonathan Peyton     if (old_action.sa_handler == __kmp_sighldrs[sig].sa_handler) {
11897cc577a4SJonathan Peyton       sigaddset(&__kmp_sigset, sig);
11907cc577a4SJonathan Peyton     } else {
11917cc577a4SJonathan Peyton       // Restore/keep user's handler if one previously installed.
11927cc577a4SJonathan Peyton       __kmp_sigaction(sig, &old_action, NULL);
1193bd3a7633SJonathan Peyton     }
11947cc577a4SJonathan Peyton   } else {
11957cc577a4SJonathan Peyton     // Save initial/system signal handlers to see if user handlers installed.
11967cc577a4SJonathan Peyton     __kmp_sigaction(sig, NULL, &__kmp_sighldrs[sig]);
1197bd3a7633SJonathan Peyton   }
11987cc577a4SJonathan Peyton   KMP_MB(); // Flush all pending memory write invalidates.
11997cc577a4SJonathan Peyton } // __kmp_install_one_handler
12007cc577a4SJonathan Peyton 
12013041982dSJonathan Peyton static void __kmp_remove_one_handler(int sig) {
12027cc577a4SJonathan Peyton   KB_TRACE(60, ("__kmp_remove_one_handler( %d )\n", sig));
12037cc577a4SJonathan Peyton   if (sigismember(&__kmp_sigset, sig)) {
12047cc577a4SJonathan Peyton     struct sigaction old;
12057cc577a4SJonathan Peyton     KMP_MB(); // Flush all pending memory write invalidates.
12067cc577a4SJonathan Peyton     __kmp_sigaction(sig, &__kmp_sighldrs[sig], &old);
12073041982dSJonathan Peyton     if ((old.sa_handler != __kmp_team_handler) &&
12083041982dSJonathan Peyton         (old.sa_handler != __kmp_null_handler)) {
12097cc577a4SJonathan Peyton       // Restore the users signal handler.
12103041982dSJonathan Peyton       KB_TRACE(10, ("__kmp_remove_one_handler: oops, not our handler, "
12113041982dSJonathan Peyton                     "restoring: sig=%d\n",
12123041982dSJonathan Peyton                     sig));
12137cc577a4SJonathan Peyton       __kmp_sigaction(sig, &old, NULL);
1214bd3a7633SJonathan Peyton     }
12157cc577a4SJonathan Peyton     sigdelset(&__kmp_sigset, sig);
12167cc577a4SJonathan Peyton     KMP_MB(); // Flush all pending memory write invalidates.
1217bd3a7633SJonathan Peyton   }
12187cc577a4SJonathan Peyton } // __kmp_remove_one_handler
12197cc577a4SJonathan Peyton 
12203041982dSJonathan Peyton void __kmp_install_signals(int parallel_init) {
12217cc577a4SJonathan Peyton   KB_TRACE(10, ("__kmp_install_signals( %d )\n", parallel_init));
12227cc577a4SJonathan Peyton   if (__kmp_handle_signals || !parallel_init) {
12233041982dSJonathan Peyton     // If ! parallel_init, we do not install handlers, just save original
12243041982dSJonathan Peyton     // handlers. Let us do it even __handle_signals is 0.
12257cc577a4SJonathan Peyton     sigemptyset(&__kmp_sigset);
12267cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGHUP, __kmp_team_handler, parallel_init);
12277cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGINT, __kmp_team_handler, parallel_init);
12287cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGQUIT, __kmp_team_handler, parallel_init);
12297cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGILL, __kmp_team_handler, parallel_init);
12307cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGABRT, __kmp_team_handler, parallel_init);
12317cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGFPE, __kmp_team_handler, parallel_init);
12327cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGBUS, __kmp_team_handler, parallel_init);
12337cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGSEGV, __kmp_team_handler, parallel_init);
12347cc577a4SJonathan Peyton #ifdef SIGSYS
12357cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGSYS, __kmp_team_handler, parallel_init);
12367cc577a4SJonathan Peyton #endif // SIGSYS
12377cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGTERM, __kmp_team_handler, parallel_init);
12387cc577a4SJonathan Peyton #ifdef SIGPIPE
12397cc577a4SJonathan Peyton     __kmp_install_one_handler(SIGPIPE, __kmp_team_handler, parallel_init);
12407cc577a4SJonathan Peyton #endif // SIGPIPE
1241bd3a7633SJonathan Peyton   }
12427cc577a4SJonathan Peyton } // __kmp_install_signals
12437cc577a4SJonathan Peyton 
12443041982dSJonathan Peyton void __kmp_remove_signals(void) {
12457cc577a4SJonathan Peyton   int sig;
12467cc577a4SJonathan Peyton   KB_TRACE(10, ("__kmp_remove_signals()\n"));
12477cc577a4SJonathan Peyton   for (sig = 1; sig < NSIG; ++sig) {
12487cc577a4SJonathan Peyton     __kmp_remove_one_handler(sig);
1249bd3a7633SJonathan Peyton   }
12507cc577a4SJonathan Peyton } // __kmp_remove_signals
12517cc577a4SJonathan Peyton 
12527cc577a4SJonathan Peyton #endif // KMP_HANDLE_SIGNALS
12537cc577a4SJonathan Peyton 
12543041982dSJonathan Peyton void __kmp_enable(int new_state) {
12557cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS
12567cc577a4SJonathan Peyton   int status, old_state;
12577cc577a4SJonathan Peyton   status = pthread_setcancelstate(new_state, &old_state);
12587cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_setcancelstate", status);
12597cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(old_state == PTHREAD_CANCEL_DISABLE);
12607cc577a4SJonathan Peyton #endif
12617cc577a4SJonathan Peyton }
12627cc577a4SJonathan Peyton 
12633041982dSJonathan Peyton void __kmp_disable(int *old_state) {
12647cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS
12657cc577a4SJonathan Peyton   int status;
12667cc577a4SJonathan Peyton   status = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, old_state);
12677cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_setcancelstate", status);
12687cc577a4SJonathan Peyton #endif
12697cc577a4SJonathan Peyton }
12707cc577a4SJonathan Peyton 
1271eaa9e40cSJonathan Peyton static void __kmp_atfork_prepare(void) {
1272eaa9e40cSJonathan Peyton   __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
1273eaa9e40cSJonathan Peyton   __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
12747cc577a4SJonathan Peyton }
12757cc577a4SJonathan Peyton 
1276eaa9e40cSJonathan Peyton static void __kmp_atfork_parent(void) {
1277eaa9e40cSJonathan Peyton   __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
1278171ca93cSHansang Bae   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
12797cc577a4SJonathan Peyton }
12807cc577a4SJonathan Peyton 
12813041982dSJonathan Peyton /* Reset the library so execution in the child starts "all over again" with
12827cc577a4SJonathan Peyton    clean data structures in initial states.  Don't worry about freeing memory
12833041982dSJonathan Peyton    allocated by parent, just abandon it to be safe. */
12843041982dSJonathan Peyton static void __kmp_atfork_child(void) {
1285eaa9e40cSJonathan Peyton   __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
1286171ca93cSHansang Bae   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
12877cc577a4SJonathan Peyton   /* TODO make sure this is done right for nested/sibling */
12887cc577a4SJonathan Peyton   // ATT:  Memory leaks are here? TODO: Check it and fix.
12897cc577a4SJonathan Peyton   /* KMP_ASSERT( 0 ); */
12907cc577a4SJonathan Peyton 
12917cc577a4SJonathan Peyton   ++__kmp_fork_count;
12927cc577a4SJonathan Peyton 
1293072ccb72SJonathan Peyton #if KMP_AFFINITY_SUPPORTED
129450699284SDavid Carlier #if KMP_OS_LINUX || KMP_OS_FREEBSD
1295d330e630SJonathan Peyton   // reset the affinity in the child to the initial thread
1296d330e630SJonathan Peyton   // affinity in the parent
1297d330e630SJonathan Peyton   kmp_set_thread_affinity_mask_initial();
1298d330e630SJonathan Peyton #endif
1299072ccb72SJonathan Peyton   // Set default not to bind threads tightly in the child (we’re expecting
1300072ccb72SJonathan Peyton   // over-subscription after the fork and this can improve things for
1301072ccb72SJonathan Peyton   // scripting languages that use OpenMP inside process-parallel code).
1302072ccb72SJonathan Peyton   __kmp_affinity_type = affinity_none;
1303072ccb72SJonathan Peyton   if (__kmp_nested_proc_bind.bind_types != NULL) {
1304072ccb72SJonathan Peyton     __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
1305072ccb72SJonathan Peyton   }
1306*5ebbb366SPeyton, Jonathan L   __kmp_affinity_masks = NULL;
1307*5ebbb366SPeyton, Jonathan L   __kmp_affinity_num_masks = 0;
1308072ccb72SJonathan Peyton #endif // KMP_AFFINITY_SUPPORTED
1309d330e630SJonathan Peyton 
13107cc577a4SJonathan Peyton #if KMP_USE_MONITOR
13117cc577a4SJonathan Peyton   __kmp_init_monitor = 0;
13127cc577a4SJonathan Peyton #endif
13137cc577a4SJonathan Peyton   __kmp_init_parallel = FALSE;
13147cc577a4SJonathan Peyton   __kmp_init_middle = FALSE;
13157cc577a4SJonathan Peyton   __kmp_init_serial = FALSE;
13167cc577a4SJonathan Peyton   TCW_4(__kmp_init_gtid, FALSE);
13177cc577a4SJonathan Peyton   __kmp_init_common = FALSE;
13187cc577a4SJonathan Peyton 
13197cc577a4SJonathan Peyton   TCW_4(__kmp_init_user_locks, FALSE);
13207cc577a4SJonathan Peyton #if !KMP_USE_DYNAMIC_LOCK
13217cc577a4SJonathan Peyton   __kmp_user_lock_table.used = 1;
13227cc577a4SJonathan Peyton   __kmp_user_lock_table.allocated = 0;
13237cc577a4SJonathan Peyton   __kmp_user_lock_table.table = NULL;
13247cc577a4SJonathan Peyton   __kmp_lock_blocks = NULL;
13257cc577a4SJonathan Peyton #endif
13267cc577a4SJonathan Peyton 
13277cc577a4SJonathan Peyton   __kmp_all_nth = 0;
13287cc577a4SJonathan Peyton   TCW_4(__kmp_nth, 0);
13297cc577a4SJonathan Peyton 
1330eaa9e40cSJonathan Peyton   __kmp_thread_pool = NULL;
1331eaa9e40cSJonathan Peyton   __kmp_thread_pool_insert_pt = NULL;
1332eaa9e40cSJonathan Peyton   __kmp_team_pool = NULL;
1333eaa9e40cSJonathan Peyton 
13343041982dSJonathan Peyton   /* Must actually zero all the *cache arguments passed to __kmpc_threadprivate
13353041982dSJonathan Peyton      here so threadprivate doesn't use stale data */
13367cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_atfork_child: checking cache address list %p\n",
13377cc577a4SJonathan Peyton                 __kmp_threadpriv_cache_list));
13387cc577a4SJonathan Peyton 
13397cc577a4SJonathan Peyton   while (__kmp_threadpriv_cache_list != NULL) {
13407cc577a4SJonathan Peyton 
13417cc577a4SJonathan Peyton     if (*__kmp_threadpriv_cache_list->addr != NULL) {
13427cc577a4SJonathan Peyton       KC_TRACE(50, ("__kmp_atfork_child: zeroing cache at address %p\n",
13437cc577a4SJonathan Peyton                     &(*__kmp_threadpriv_cache_list->addr)));
13447cc577a4SJonathan Peyton 
13457cc577a4SJonathan Peyton       *__kmp_threadpriv_cache_list->addr = NULL;
13467cc577a4SJonathan Peyton     }
13477cc577a4SJonathan Peyton     __kmp_threadpriv_cache_list = __kmp_threadpriv_cache_list->next;
13487cc577a4SJonathan Peyton   }
13497cc577a4SJonathan Peyton 
13507cc577a4SJonathan Peyton   __kmp_init_runtime = FALSE;
13517cc577a4SJonathan Peyton 
13527cc577a4SJonathan Peyton   /* reset statically initialized locks */
13537cc577a4SJonathan Peyton   __kmp_init_bootstrap_lock(&__kmp_initz_lock);
13547cc577a4SJonathan Peyton   __kmp_init_bootstrap_lock(&__kmp_stdio_lock);
13557cc577a4SJonathan Peyton   __kmp_init_bootstrap_lock(&__kmp_console_lock);
1356eaa9e40cSJonathan Peyton   __kmp_init_bootstrap_lock(&__kmp_task_team_lock);
1357eaa9e40cSJonathan Peyton 
13585388acd3SAndrey Churbanov #if USE_ITT_BUILD
1359eaa9e40cSJonathan Peyton   __kmp_itt_reset(); // reset ITT's global state
13605388acd3SAndrey Churbanov #endif /* USE_ITT_BUILD */
13617cc577a4SJonathan Peyton 
1362171ca93cSHansang Bae   __kmp_serial_initialize();
1363171ca93cSHansang Bae 
13647cc577a4SJonathan Peyton   /* This is necessary to make sure no stale data is left around */
13657cc577a4SJonathan Peyton   /* AC: customers complain that we use unsafe routines in the atfork
13667cc577a4SJonathan Peyton      handler. Mathworks: dlsym() is unsafe. We call dlsym and dlopen
13677cc577a4SJonathan Peyton      in dynamic_link when check the presence of shared tbbmalloc library.
13687cc577a4SJonathan Peyton      Suggestion is to make the library initialization lazier, similar
13697cc577a4SJonathan Peyton      to what done for __kmpc_begin(). */
13707cc577a4SJonathan Peyton   // TODO: synchronize all static initializations with regular library
1371de4749b7SJonathan Peyton   //       startup; look at kmp_global.cpp and etc.
13727cc577a4SJonathan Peyton   //__kmp_internal_begin ();
13737cc577a4SJonathan Peyton }
13747cc577a4SJonathan Peyton 
13753041982dSJonathan Peyton void __kmp_register_atfork(void) {
13767cc577a4SJonathan Peyton   if (__kmp_need_register_atfork) {
13773041982dSJonathan Peyton     int status = pthread_atfork(__kmp_atfork_prepare, __kmp_atfork_parent,
13783041982dSJonathan Peyton                                 __kmp_atfork_child);
13797cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_atfork", status);
13807cc577a4SJonathan Peyton     __kmp_need_register_atfork = FALSE;
13817cc577a4SJonathan Peyton   }
13827cc577a4SJonathan Peyton }
13837cc577a4SJonathan Peyton 
13843041982dSJonathan Peyton void __kmp_suspend_initialize(void) {
13857cc577a4SJonathan Peyton   int status;
13867cc577a4SJonathan Peyton   status = pthread_mutexattr_init(&__kmp_suspend_mutex_attr);
13877cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutexattr_init", status);
13887cc577a4SJonathan Peyton   status = pthread_condattr_init(&__kmp_suspend_cond_attr);
13897cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_condattr_init", status);
13907cc577a4SJonathan Peyton }
13917cc577a4SJonathan Peyton 
1392feac33ebSJonathan Peyton void __kmp_suspend_initialize_thread(kmp_info_t *th) {
13937cc577a4SJonathan Peyton   ANNOTATE_HAPPENS_AFTER(&th->th.th_suspend_init_count);
1394f8f788b2SAndrey Churbanov   int old_value = KMP_ATOMIC_LD_RLX(&th->th.th_suspend_init_count);
1395f8f788b2SAndrey Churbanov   int new_value = __kmp_fork_count + 1;
1396f8f788b2SAndrey Churbanov   // Return if already initialized
1397f8f788b2SAndrey Churbanov   if (old_value == new_value)
1398f8f788b2SAndrey Churbanov     return;
1399f8f788b2SAndrey Churbanov   // Wait, then return if being initialized
1400309b00a4SShilei Tian   if (old_value == -1 || !__kmp_atomic_compare_store(
1401309b00a4SShilei Tian                              &th->th.th_suspend_init_count, old_value, -1)) {
1402f8f788b2SAndrey Churbanov     while (KMP_ATOMIC_LD_ACQ(&th->th.th_suspend_init_count) != new_value) {
1403f8f788b2SAndrey Churbanov       KMP_CPU_PAUSE();
1404f8f788b2SAndrey Churbanov     }
1405f8f788b2SAndrey Churbanov   } else {
1406f8f788b2SAndrey Churbanov     // Claim to be the initializer and do initializations
14077cc577a4SJonathan Peyton     int status;
14083041982dSJonathan Peyton     status = pthread_cond_init(&th->th.th_suspend_cv.c_cond,
14093041982dSJonathan Peyton                                &__kmp_suspend_cond_attr);
14107cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_cond_init", status);
14113041982dSJonathan Peyton     status = pthread_mutex_init(&th->th.th_suspend_mx.m_mutex,
14123041982dSJonathan Peyton                                 &__kmp_suspend_mutex_attr);
14137cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
1414f8f788b2SAndrey Churbanov     KMP_ATOMIC_ST_REL(&th->th.th_suspend_init_count, new_value);
14157cc577a4SJonathan Peyton     ANNOTATE_HAPPENS_BEFORE(&th->th.th_suspend_init_count);
1416bd3a7633SJonathan Peyton   }
14177cc577a4SJonathan Peyton }
14187cc577a4SJonathan Peyton 
14193041982dSJonathan Peyton void __kmp_suspend_uninitialize_thread(kmp_info_t *th) {
1420f8f788b2SAndrey Churbanov   if (KMP_ATOMIC_LD_ACQ(&th->th.th_suspend_init_count) > __kmp_fork_count) {
14213041982dSJonathan Peyton     /* this means we have initialize the suspension pthread objects for this
14223041982dSJonathan Peyton        thread in this instance of the process */
14237cc577a4SJonathan Peyton     int status;
14247cc577a4SJonathan Peyton 
14257cc577a4SJonathan Peyton     status = pthread_cond_destroy(&th->th.th_suspend_cv.c_cond);
14267cc577a4SJonathan Peyton     if (status != 0 && status != EBUSY) {
14277cc577a4SJonathan Peyton       KMP_SYSFAIL("pthread_cond_destroy", status);
1428bd3a7633SJonathan Peyton     }
14297cc577a4SJonathan Peyton     status = pthread_mutex_destroy(&th->th.th_suspend_mx.m_mutex);
14307cc577a4SJonathan Peyton     if (status != 0 && status != EBUSY) {
14317cc577a4SJonathan Peyton       KMP_SYSFAIL("pthread_mutex_destroy", status);
1432bd3a7633SJonathan Peyton     }
14337cc577a4SJonathan Peyton     --th->th.th_suspend_init_count;
1434f8f788b2SAndrey Churbanov     KMP_DEBUG_ASSERT(KMP_ATOMIC_LD_RLX(&th->th.th_suspend_init_count) ==
1435f8f788b2SAndrey Churbanov                      __kmp_fork_count);
14367cc577a4SJonathan Peyton   }
14377cc577a4SJonathan Peyton }
14387cc577a4SJonathan Peyton 
14399b8bb323SJonathan Peyton // return true if lock obtained, false otherwise
14409b8bb323SJonathan Peyton int __kmp_try_suspend_mx(kmp_info_t *th) {
14419b8bb323SJonathan Peyton   return (pthread_mutex_trylock(&th->th.th_suspend_mx.m_mutex) == 0);
14429b8bb323SJonathan Peyton }
14439b8bb323SJonathan Peyton 
14449b8bb323SJonathan Peyton void __kmp_lock_suspend_mx(kmp_info_t *th) {
14459b8bb323SJonathan Peyton   int status = pthread_mutex_lock(&th->th.th_suspend_mx.m_mutex);
14469b8bb323SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
14479b8bb323SJonathan Peyton }
14489b8bb323SJonathan Peyton 
14499b8bb323SJonathan Peyton void __kmp_unlock_suspend_mx(kmp_info_t *th) {
14509b8bb323SJonathan Peyton   int status = pthread_mutex_unlock(&th->th.th_suspend_mx.m_mutex);
14519b8bb323SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
14529b8bb323SJonathan Peyton }
14539b8bb323SJonathan Peyton 
14547cc577a4SJonathan Peyton /* This routine puts the calling thread to sleep after setting the
14553041982dSJonathan Peyton    sleep bit for the indicated flag variable to true. */
14567cc577a4SJonathan Peyton template <class C>
14573041982dSJonathan Peyton static inline void __kmp_suspend_template(int th_gtid, C *flag) {
14587cc577a4SJonathan Peyton   KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_suspend);
14597cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[th_gtid];
14607cc577a4SJonathan Peyton   int status;
14617cc577a4SJonathan Peyton   typename C::flag_t old_spin;
14627cc577a4SJonathan Peyton 
14633041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_suspend_template: T#%d enter for flag = %p\n", th_gtid,
14643041982dSJonathan Peyton                 flag->get()));
14657cc577a4SJonathan Peyton 
14667cc577a4SJonathan Peyton   __kmp_suspend_initialize_thread(th);
14677cc577a4SJonathan Peyton 
1468e0665a90STerry Wilmarth   __kmp_lock_suspend_mx(th);
14697cc577a4SJonathan Peyton 
14707cc577a4SJonathan Peyton   KF_TRACE(10, ("__kmp_suspend_template: T#%d setting sleep bit for spin(%p)\n",
14717cc577a4SJonathan Peyton                 th_gtid, flag->get()));
14727cc577a4SJonathan Peyton 
14733041982dSJonathan Peyton   /* TODO: shouldn't this use release semantics to ensure that
14743041982dSJonathan Peyton      __kmp_suspend_initialize_thread gets called first? */
14757cc577a4SJonathan Peyton   old_spin = flag->set_sleeping();
14769b8bb323SJonathan Peyton   if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME &&
14779b8bb323SJonathan Peyton       __kmp_pause_status != kmp_soft_paused) {
14789b8bb323SJonathan Peyton     flag->unset_sleeping();
1479e0665a90STerry Wilmarth     __kmp_unlock_suspend_mx(th);
14809b8bb323SJonathan Peyton     return;
14819b8bb323SJonathan Peyton   }
14823041982dSJonathan Peyton   KF_TRACE(5, ("__kmp_suspend_template: T#%d set sleep bit for spin(%p)==%x,"
14833041982dSJonathan Peyton                " was %x\n",
148437e2ef54SJonathan Peyton                th_gtid, flag->get(), flag->load(), old_spin));
14857cc577a4SJonathan Peyton 
14867cc577a4SJonathan Peyton   if (flag->done_check_val(old_spin)) {
14877cc577a4SJonathan Peyton     old_spin = flag->unset_sleeping();
14883041982dSJonathan Peyton     KF_TRACE(5, ("__kmp_suspend_template: T#%d false alarm, reset sleep bit "
14893041982dSJonathan Peyton                  "for spin(%p)\n",
14907cc577a4SJonathan Peyton                  th_gtid, flag->get()));
14917cc577a4SJonathan Peyton   } else {
14927cc577a4SJonathan Peyton     /* Encapsulate in a loop as the documentation states that this may
14933041982dSJonathan Peyton        "with low probability" return when the condition variable has
14943041982dSJonathan Peyton        not been signaled or broadcast */
14957cc577a4SJonathan Peyton     int deactivated = FALSE;
14967cc577a4SJonathan Peyton     TCW_PTR(th->th.th_sleep_loc, (void *)flag);
14973041982dSJonathan Peyton 
14987cc577a4SJonathan Peyton     while (flag->is_sleeping()) {
14997cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND
15007cc577a4SJonathan Peyton       char buffer[128];
15017cc577a4SJonathan Peyton       __kmp_suspend_count++;
15027cc577a4SJonathan Peyton       __kmp_print_cond(buffer, &th->th.th_suspend_cv);
15033041982dSJonathan Peyton       __kmp_printf("__kmp_suspend_template: suspending T#%d: %s\n", th_gtid,
15043041982dSJonathan Peyton                    buffer);
15057cc577a4SJonathan Peyton #endif
15063041982dSJonathan Peyton       // Mark the thread as no longer active (only in the first iteration of the
15073041982dSJonathan Peyton       // loop).
15087cc577a4SJonathan Peyton       if (!deactivated) {
15097cc577a4SJonathan Peyton         th->th.th_active = FALSE;
15107cc577a4SJonathan Peyton         if (th->th.th_active_in_pool) {
15117cc577a4SJonathan Peyton           th->th.th_active_in_pool = FALSE;
151237e2ef54SJonathan Peyton           KMP_ATOMIC_DEC(&__kmp_thread_pool_active_nth);
15137cc577a4SJonathan Peyton           KMP_DEBUG_ASSERT(TCR_4(__kmp_thread_pool_active_nth) >= 0);
15147cc577a4SJonathan Peyton         }
15157cc577a4SJonathan Peyton         deactivated = TRUE;
15167cc577a4SJonathan Peyton       }
15177cc577a4SJonathan Peyton 
15187cc577a4SJonathan Peyton #if USE_SUSPEND_TIMEOUT
15197cc577a4SJonathan Peyton       struct timespec now;
15207cc577a4SJonathan Peyton       struct timeval tval;
15217cc577a4SJonathan Peyton       int msecs;
15227cc577a4SJonathan Peyton 
15237cc577a4SJonathan Peyton       status = gettimeofday(&tval, NULL);
15247cc577a4SJonathan Peyton       KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
15257cc577a4SJonathan Peyton       TIMEVAL_TO_TIMESPEC(&tval, &now);
15267cc577a4SJonathan Peyton 
15277cc577a4SJonathan Peyton       msecs = (4 * __kmp_dflt_blocktime) + 200;
15287cc577a4SJonathan Peyton       now.tv_sec += msecs / 1000;
15297cc577a4SJonathan Peyton       now.tv_nsec += (msecs % 1000) * 1000;
15307cc577a4SJonathan Peyton 
15313041982dSJonathan Peyton       KF_TRACE(15, ("__kmp_suspend_template: T#%d about to perform "
15323041982dSJonathan Peyton                     "pthread_cond_timedwait\n",
15337cc577a4SJonathan Peyton                     th_gtid));
15343041982dSJonathan Peyton       status = pthread_cond_timedwait(&th->th.th_suspend_cv.c_cond,
15353041982dSJonathan Peyton                                       &th->th.th_suspend_mx.m_mutex, &now);
15367cc577a4SJonathan Peyton #else
15373041982dSJonathan Peyton       KF_TRACE(15, ("__kmp_suspend_template: T#%d about to perform"
15383041982dSJonathan Peyton                     " pthread_cond_wait\n",
15397cc577a4SJonathan Peyton                     th_gtid));
15403041982dSJonathan Peyton       status = pthread_cond_wait(&th->th.th_suspend_cv.c_cond,
15413041982dSJonathan Peyton                                  &th->th.th_suspend_mx.m_mutex);
1542e0665a90STerry Wilmarth #endif // USE_SUSPEND_TIMEOUT
15437cc577a4SJonathan Peyton 
15447cc577a4SJonathan Peyton       if ((status != 0) && (status != EINTR) && (status != ETIMEDOUT)) {
15457cc577a4SJonathan Peyton         KMP_SYSFAIL("pthread_cond_wait", status);
15467cc577a4SJonathan Peyton       }
15477cc577a4SJonathan Peyton #ifdef KMP_DEBUG
15487cc577a4SJonathan Peyton       if (status == ETIMEDOUT) {
15497cc577a4SJonathan Peyton         if (flag->is_sleeping()) {
15503041982dSJonathan Peyton           KF_TRACE(100,
15513041982dSJonathan Peyton                    ("__kmp_suspend_template: T#%d timeout wakeup\n", th_gtid));
15527cc577a4SJonathan Peyton         } else {
15533041982dSJonathan Peyton           KF_TRACE(2, ("__kmp_suspend_template: T#%d timeout wakeup, sleep bit "
15543041982dSJonathan Peyton                        "not set!\n",
15557cc577a4SJonathan Peyton                        th_gtid));
15567cc577a4SJonathan Peyton         }
15577cc577a4SJonathan Peyton       } else if (flag->is_sleeping()) {
15583041982dSJonathan Peyton         KF_TRACE(100,
15593041982dSJonathan Peyton                  ("__kmp_suspend_template: T#%d spurious wakeup\n", th_gtid));
15607cc577a4SJonathan Peyton       }
15617cc577a4SJonathan Peyton #endif
15627cc577a4SJonathan Peyton     } // while
15637cc577a4SJonathan Peyton 
15647cc577a4SJonathan Peyton     // Mark the thread as active again (if it was previous marked as inactive)
15657cc577a4SJonathan Peyton     if (deactivated) {
15667cc577a4SJonathan Peyton       th->th.th_active = TRUE;
15677cc577a4SJonathan Peyton       if (TCR_4(th->th.th_in_pool)) {
156837e2ef54SJonathan Peyton         KMP_ATOMIC_INC(&__kmp_thread_pool_active_nth);
15697cc577a4SJonathan Peyton         th->th.th_active_in_pool = TRUE;
15707cc577a4SJonathan Peyton       }
15717cc577a4SJonathan Peyton     }
15727cc577a4SJonathan Peyton   }
15737cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND
15747cc577a4SJonathan Peyton   {
15757cc577a4SJonathan Peyton     char buffer[128];
15767cc577a4SJonathan Peyton     __kmp_print_cond(buffer, &th->th.th_suspend_cv);
15773041982dSJonathan Peyton     __kmp_printf("__kmp_suspend_template: T#%d has awakened: %s\n", th_gtid,
15783041982dSJonathan Peyton                  buffer);
15797cc577a4SJonathan Peyton   }
15807cc577a4SJonathan Peyton #endif
15817cc577a4SJonathan Peyton 
1582e0665a90STerry Wilmarth   __kmp_unlock_suspend_mx(th);
15837cc577a4SJonathan Peyton   KF_TRACE(30, ("__kmp_suspend_template: T#%d exit\n", th_gtid));
15847cc577a4SJonathan Peyton }
15857cc577a4SJonathan Peyton 
1586e0665a90STerry Wilmarth template <bool C, bool S>
1587e0665a90STerry Wilmarth void __kmp_suspend_32(int th_gtid, kmp_flag_32<C, S> *flag) {
15887cc577a4SJonathan Peyton   __kmp_suspend_template(th_gtid, flag);
15897cc577a4SJonathan Peyton }
1590e0665a90STerry Wilmarth template <bool C, bool S>
1591e0665a90STerry Wilmarth void __kmp_suspend_64(int th_gtid, kmp_flag_64<C, S> *flag) {
15927cc577a4SJonathan Peyton   __kmp_suspend_template(th_gtid, flag);
15937cc577a4SJonathan Peyton }
15947cc577a4SJonathan Peyton void __kmp_suspend_oncore(int th_gtid, kmp_flag_oncore *flag) {
15957cc577a4SJonathan Peyton   __kmp_suspend_template(th_gtid, flag);
15967cc577a4SJonathan Peyton }
15977cc577a4SJonathan Peyton 
1598e0665a90STerry Wilmarth template void __kmp_suspend_32<false, false>(int, kmp_flag_32<false, false> *);
1599e0665a90STerry Wilmarth template void __kmp_suspend_64<false, true>(int, kmp_flag_64<false, true> *);
1600e0665a90STerry Wilmarth template void __kmp_suspend_64<true, false>(int, kmp_flag_64<true, false> *);
1601e0665a90STerry Wilmarth 
16027cc577a4SJonathan Peyton /* This routine signals the thread specified by target_gtid to wake up
16033041982dSJonathan Peyton    after setting the sleep bit indicated by the flag argument to FALSE.
16043041982dSJonathan Peyton    The target thread must already have called __kmp_suspend_template() */
16057cc577a4SJonathan Peyton template <class C>
16063041982dSJonathan Peyton static inline void __kmp_resume_template(int target_gtid, C *flag) {
16077cc577a4SJonathan Peyton   KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_resume);
16087cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[target_gtid];
16097cc577a4SJonathan Peyton   int status;
16107cc577a4SJonathan Peyton 
16117cc577a4SJonathan Peyton #ifdef KMP_DEBUG
16127cc577a4SJonathan Peyton   int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
16137cc577a4SJonathan Peyton #endif
16147cc577a4SJonathan Peyton 
16153041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_resume_template: T#%d wants to wakeup T#%d enter\n",
16163041982dSJonathan Peyton                 gtid, target_gtid));
16177cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(gtid != target_gtid);
16187cc577a4SJonathan Peyton 
16197cc577a4SJonathan Peyton   __kmp_suspend_initialize_thread(th);
16205644f734SAndreyChurbanov 
1621e0665a90STerry Wilmarth   __kmp_lock_suspend_mx(th);
16227cc577a4SJonathan Peyton 
16237cc577a4SJonathan Peyton   if (!flag) { // coming from __kmp_null_resume_wrapper
1624c47afcd9SAndrey Churbanov     flag = (C *)CCAST(void *, th->th.th_sleep_loc);
16257cc577a4SJonathan Peyton   }
16267cc577a4SJonathan Peyton 
16273041982dSJonathan Peyton   // First, check if the flag is null or its type has changed. If so, someone
16283041982dSJonathan Peyton   // else woke it up.
16293041982dSJonathan Peyton   if (!flag || flag->get_type() != flag->get_ptr_type()) { // get_ptr_type
1630e0665a90STerry Wilmarth     // simply shows what flag was cast to
16313041982dSJonathan Peyton     KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already "
16323041982dSJonathan Peyton                  "awake: flag(%p)\n",
16337cc577a4SJonathan Peyton                  gtid, target_gtid, NULL));
1634e0665a90STerry Wilmarth     __kmp_unlock_suspend_mx(th);
16357cc577a4SJonathan Peyton     return;
16363041982dSJonathan Peyton   } else { // if multiple threads are sleeping, flag should be internally
16373041982dSJonathan Peyton     // referring to a specific thread here
16387cc577a4SJonathan Peyton     typename C::flag_t old_spin = flag->unset_sleeping();
16397cc577a4SJonathan Peyton     if (!flag->is_sleeping_val(old_spin)) {
16403041982dSJonathan Peyton       KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already "
16413041982dSJonathan Peyton                    "awake: flag(%p): "
16427cc577a4SJonathan Peyton                    "%u => %u\n",
164337e2ef54SJonathan Peyton                    gtid, target_gtid, flag->get(), old_spin, flag->load()));
1644e0665a90STerry Wilmarth       __kmp_unlock_suspend_mx(th);
16457cc577a4SJonathan Peyton       return;
16467cc577a4SJonathan Peyton     }
16473041982dSJonathan Peyton     KF_TRACE(5, ("__kmp_resume_template: T#%d about to wakeup T#%d, reset "
16483041982dSJonathan Peyton                  "sleep bit for flag's loc(%p): "
16497cc577a4SJonathan Peyton                  "%u => %u\n",
165037e2ef54SJonathan Peyton                  gtid, target_gtid, flag->get(), old_spin, flag->load()));
16517cc577a4SJonathan Peyton   }
16527cc577a4SJonathan Peyton   TCW_PTR(th->th.th_sleep_loc, NULL);
16537cc577a4SJonathan Peyton 
16547cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND
16557cc577a4SJonathan Peyton   {
16567cc577a4SJonathan Peyton     char buffer[128];
16577cc577a4SJonathan Peyton     __kmp_print_cond(buffer, &th->th.th_suspend_cv);
16583041982dSJonathan Peyton     __kmp_printf("__kmp_resume_template: T#%d resuming T#%d: %s\n", gtid,
16593041982dSJonathan Peyton                  target_gtid, buffer);
16607cc577a4SJonathan Peyton   }
16617cc577a4SJonathan Peyton #endif
16627cc577a4SJonathan Peyton   status = pthread_cond_signal(&th->th.th_suspend_cv.c_cond);
16637cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_cond_signal", status);
1664e0665a90STerry Wilmarth   __kmp_unlock_suspend_mx(th);
16653041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_resume_template: T#%d exiting after signaling wake up"
16663041982dSJonathan Peyton                 " for T#%d\n",
16677cc577a4SJonathan Peyton                 gtid, target_gtid));
16687cc577a4SJonathan Peyton }
16697cc577a4SJonathan Peyton 
1670e0665a90STerry Wilmarth template <bool C, bool S>
1671e0665a90STerry Wilmarth void __kmp_resume_32(int target_gtid, kmp_flag_32<C, S> *flag) {
16727cc577a4SJonathan Peyton   __kmp_resume_template(target_gtid, flag);
16737cc577a4SJonathan Peyton }
1674e0665a90STerry Wilmarth template <bool C, bool S>
1675e0665a90STerry Wilmarth void __kmp_resume_64(int target_gtid, kmp_flag_64<C, S> *flag) {
16767cc577a4SJonathan Peyton   __kmp_resume_template(target_gtid, flag);
16777cc577a4SJonathan Peyton }
16787cc577a4SJonathan Peyton void __kmp_resume_oncore(int target_gtid, kmp_flag_oncore *flag) {
16797cc577a4SJonathan Peyton   __kmp_resume_template(target_gtid, flag);
16807cc577a4SJonathan Peyton }
16817cc577a4SJonathan Peyton 
1682e0665a90STerry Wilmarth template void __kmp_resume_32<false, true>(int, kmp_flag_32<false, true> *);
1683e0665a90STerry Wilmarth template void __kmp_resume_64<false, true>(int, kmp_flag_64<false, true> *);
1684e0665a90STerry Wilmarth 
16857cc577a4SJonathan Peyton #if KMP_USE_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 
1715e47d32f1SJonathan Peyton void __kmp_yield() { sched_yield(); }
17167cc577a4SJonathan Peyton 
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 
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 
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 
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 
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 
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 
18063041982dSJonathan Peyton static int __kmp_get_xproc(void) {
18077cc577a4SJonathan Peyton 
18087cc577a4SJonathan Peyton   int r = 0;
18097cc577a4SJonathan Peyton 
1810a56ac949SKamil Rytarowski #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
18117e1ea993SKamil Rytarowski     KMP_OS_OPENBSD || KMP_OS_HURD
18127cc577a4SJonathan Peyton 
18136b316febSTerry Wilmarth   __kmp_type_convert(sysconf(_SC_NPROCESSORS_ONLN), &(r));
18147cc577a4SJonathan Peyton 
18157cc577a4SJonathan Peyton #elif KMP_OS_DARWIN
18167cc577a4SJonathan Peyton 
18177cc577a4SJonathan Peyton   // Bug C77011 High "OpenMP Threads and number of active cores".
18187cc577a4SJonathan Peyton 
18197cc577a4SJonathan Peyton   // Find the number of available CPUs.
18207cc577a4SJonathan Peyton   kern_return_t rc;
18217cc577a4SJonathan Peyton   host_basic_info_data_t info;
18227cc577a4SJonathan Peyton   mach_msg_type_number_t num = HOST_BASIC_INFO_COUNT;
18237cc577a4SJonathan Peyton   rc = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&info, &num);
18247cc577a4SJonathan Peyton   if (rc == 0 && num == HOST_BASIC_INFO_COUNT) {
1825c47afcd9SAndrey Churbanov     // Cannot use KA_TRACE() here because this code works before trace support
1826c47afcd9SAndrey Churbanov     // is initialized.
18277cc577a4SJonathan Peyton     r = info.avail_cpus;
18287cc577a4SJonathan Peyton   } else {
18297cc577a4SJonathan Peyton     KMP_WARNING(CantGetNumAvailCPU);
18307cc577a4SJonathan Peyton     KMP_INFORM(AssumedNumCPU);
1831bd3a7633SJonathan Peyton   }
18327cc577a4SJonathan Peyton 
18337cc577a4SJonathan Peyton #else
18347cc577a4SJonathan Peyton 
18357cc577a4SJonathan Peyton #error "Unknown or unsupported OS."
18367cc577a4SJonathan Peyton 
18377cc577a4SJonathan Peyton #endif
18387cc577a4SJonathan Peyton 
18397cc577a4SJonathan Peyton   return r > 0 ? r : 2; /* guess value of 2 if OS told us 0 */
18407cc577a4SJonathan Peyton 
18417cc577a4SJonathan Peyton } // __kmp_get_xproc
18427cc577a4SJonathan Peyton 
18433041982dSJonathan Peyton int __kmp_read_from_file(char const *path, char const *format, ...) {
18447cc577a4SJonathan Peyton   int result;
18457cc577a4SJonathan Peyton   va_list args;
18467cc577a4SJonathan Peyton 
18477cc577a4SJonathan Peyton   va_start(args, format);
18487cc577a4SJonathan Peyton   FILE *f = fopen(path, "rb");
18497cc577a4SJonathan Peyton   if (f == NULL)
18507cc577a4SJonathan Peyton     return 0;
18517cc577a4SJonathan Peyton   result = vfscanf(f, format, args);
18527cc577a4SJonathan Peyton   fclose(f);
18537cc577a4SJonathan Peyton 
18547cc577a4SJonathan Peyton   return result;
18557cc577a4SJonathan Peyton }
18567cc577a4SJonathan Peyton 
18573041982dSJonathan Peyton void __kmp_runtime_initialize(void) {
18587cc577a4SJonathan Peyton   int status;
18597cc577a4SJonathan Peyton   pthread_mutexattr_t mutex_attr;
18607cc577a4SJonathan Peyton   pthread_condattr_t cond_attr;
18617cc577a4SJonathan Peyton 
18627cc577a4SJonathan Peyton   if (__kmp_init_runtime) {
18637cc577a4SJonathan Peyton     return;
1864bd3a7633SJonathan Peyton   }
18657cc577a4SJonathan Peyton 
18667cc577a4SJonathan Peyton #if (KMP_ARCH_X86 || KMP_ARCH_X86_64)
18677cc577a4SJonathan Peyton   if (!__kmp_cpuinfo.initialized) {
18687cc577a4SJonathan Peyton     __kmp_query_cpuid(&__kmp_cpuinfo);
1869bd3a7633SJonathan Peyton   }
18707cc577a4SJonathan Peyton #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
18717cc577a4SJonathan Peyton 
18727cc577a4SJonathan Peyton   __kmp_xproc = __kmp_get_xproc();
18737cc577a4SJonathan Peyton 
1874d47f5488SAndrey Churbanov #if !KMP_32_BIT_ARCH
1875d47f5488SAndrey Churbanov   struct rlimit rlim;
1876d47f5488SAndrey Churbanov   // read stack size of calling thread, save it as default for worker threads;
1877d47f5488SAndrey Churbanov   // this should be done before reading environment variables
1878d47f5488SAndrey Churbanov   status = getrlimit(RLIMIT_STACK, &rlim);
1879d47f5488SAndrey Churbanov   if (status == 0) { // success?
1880d47f5488SAndrey Churbanov     __kmp_stksize = rlim.rlim_cur;
1881d47f5488SAndrey Churbanov     __kmp_check_stksize(&__kmp_stksize); // check value and adjust if needed
1882d47f5488SAndrey Churbanov   }
1883d47f5488SAndrey Churbanov #endif /* KMP_32_BIT_ARCH */
1884d47f5488SAndrey Churbanov 
18857cc577a4SJonathan Peyton   if (sysconf(_SC_THREADS)) {
18867cc577a4SJonathan Peyton 
18877cc577a4SJonathan Peyton     /* Query the maximum number of threads */
18886b316febSTerry Wilmarth     __kmp_type_convert(sysconf(_SC_THREAD_THREADS_MAX), &(__kmp_sys_max_nth));
18897cc577a4SJonathan Peyton     if (__kmp_sys_max_nth == -1) {
18907cc577a4SJonathan Peyton       /* Unlimited threads for NPTL */
18917cc577a4SJonathan Peyton       __kmp_sys_max_nth = INT_MAX;
18923041982dSJonathan Peyton     } else if (__kmp_sys_max_nth <= 1) {
18937cc577a4SJonathan Peyton       /* Can't tell, just use PTHREAD_THREADS_MAX */
18947cc577a4SJonathan Peyton       __kmp_sys_max_nth = KMP_MAX_NTH;
18957cc577a4SJonathan Peyton     }
18967cc577a4SJonathan Peyton 
18977cc577a4SJonathan Peyton     /* Query the minimum stack size */
18987cc577a4SJonathan Peyton     __kmp_sys_min_stksize = sysconf(_SC_THREAD_STACK_MIN);
18997cc577a4SJonathan Peyton     if (__kmp_sys_min_stksize <= 1) {
19007cc577a4SJonathan Peyton       __kmp_sys_min_stksize = KMP_MIN_STKSIZE;
19017cc577a4SJonathan Peyton     }
19027cc577a4SJonathan Peyton   }
19037cc577a4SJonathan Peyton 
19047cc577a4SJonathan Peyton   /* Set up minimum number of threads to switch to TLS gtid */
19057cc577a4SJonathan Peyton   __kmp_tls_gtid_min = KMP_TLS_GTID_MIN;
19067cc577a4SJonathan Peyton 
19073041982dSJonathan Peyton   status = pthread_key_create(&__kmp_gtid_threadprivate_key,
19083041982dSJonathan Peyton                               __kmp_internal_end_dest);
19097cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_key_create", status);
19107cc577a4SJonathan Peyton   status = pthread_mutexattr_init(&mutex_attr);
19117cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutexattr_init", status);
19127cc577a4SJonathan Peyton   status = pthread_mutex_init(&__kmp_wait_mx.m_mutex, &mutex_attr);
19137cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
19141611e547SAndreyChurbanov   status = pthread_mutexattr_destroy(&mutex_attr);
19151611e547SAndreyChurbanov   KMP_CHECK_SYSFAIL("pthread_mutexattr_destroy", status);
19167cc577a4SJonathan Peyton   status = pthread_condattr_init(&cond_attr);
19177cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_condattr_init", status);
19187cc577a4SJonathan Peyton   status = pthread_cond_init(&__kmp_wait_cv.c_cond, &cond_attr);
19197cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
19201611e547SAndreyChurbanov   status = pthread_condattr_destroy(&cond_attr);
19211611e547SAndreyChurbanov   KMP_CHECK_SYSFAIL("pthread_condattr_destroy", status);
19227cc577a4SJonathan Peyton #if USE_ITT_BUILD
19237cc577a4SJonathan Peyton   __kmp_itt_initialize();
19247cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
19257cc577a4SJonathan Peyton 
19267cc577a4SJonathan Peyton   __kmp_init_runtime = TRUE;
19277cc577a4SJonathan Peyton }
19287cc577a4SJonathan Peyton 
19293041982dSJonathan Peyton void __kmp_runtime_destroy(void) {
19307cc577a4SJonathan Peyton   int status;
19317cc577a4SJonathan Peyton 
19327cc577a4SJonathan Peyton   if (!__kmp_init_runtime) {
19337cc577a4SJonathan Peyton     return; // Nothing to do.
1934bd3a7633SJonathan Peyton   }
19357cc577a4SJonathan Peyton 
19367cc577a4SJonathan Peyton #if USE_ITT_BUILD
19377cc577a4SJonathan Peyton   __kmp_itt_destroy();
19387cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
19397cc577a4SJonathan Peyton 
19407cc577a4SJonathan Peyton   status = pthread_key_delete(__kmp_gtid_threadprivate_key);
19417cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_key_delete", status);
19427cc577a4SJonathan Peyton 
19437cc577a4SJonathan Peyton   status = pthread_mutex_destroy(&__kmp_wait_mx.m_mutex);
19447cc577a4SJonathan Peyton   if (status != 0 && status != EBUSY) {
19457cc577a4SJonathan Peyton     KMP_SYSFAIL("pthread_mutex_destroy", status);
19467cc577a4SJonathan Peyton   }
19477cc577a4SJonathan Peyton   status = pthread_cond_destroy(&__kmp_wait_cv.c_cond);
19487cc577a4SJonathan Peyton   if (status != 0 && status != EBUSY) {
19497cc577a4SJonathan Peyton     KMP_SYSFAIL("pthread_cond_destroy", status);
19507cc577a4SJonathan Peyton   }
19517cc577a4SJonathan Peyton #if KMP_AFFINITY_SUPPORTED
19527cc577a4SJonathan Peyton   __kmp_affinity_uninitialize();
19537cc577a4SJonathan Peyton #endif
19547cc577a4SJonathan Peyton 
19557cc577a4SJonathan Peyton   __kmp_init_runtime = FALSE;
19567cc577a4SJonathan Peyton }
19577cc577a4SJonathan Peyton 
19587cc577a4SJonathan Peyton /* Put the thread to sleep for a time period */
19597cc577a4SJonathan Peyton /* NOTE: not currently used anywhere */
19603041982dSJonathan Peyton void __kmp_thread_sleep(int millis) { sleep((millis + 500) / 1000); }
19617cc577a4SJonathan Peyton 
19627cc577a4SJonathan Peyton /* Calculate the elapsed wall clock time for the user */
19633041982dSJonathan Peyton void __kmp_elapsed(double *t) {
19647cc577a4SJonathan Peyton   int status;
19657cc577a4SJonathan Peyton #ifdef FIX_SGI_CLOCK
19667cc577a4SJonathan Peyton   struct timespec ts;
19677cc577a4SJonathan Peyton 
19687cc577a4SJonathan Peyton   status = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
19697cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("clock_gettime", status);
19703041982dSJonathan Peyton   *t =
19713041982dSJonathan Peyton       (double)ts.tv_nsec * (1.0 / (double)KMP_NSEC_PER_SEC) + (double)ts.tv_sec;
19727cc577a4SJonathan Peyton #else
19737cc577a4SJonathan Peyton   struct timeval tv;
19747cc577a4SJonathan Peyton 
19757cc577a4SJonathan Peyton   status = gettimeofday(&tv, NULL);
19767cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
19773041982dSJonathan Peyton   *t =
19783041982dSJonathan Peyton       (double)tv.tv_usec * (1.0 / (double)KMP_USEC_PER_SEC) + (double)tv.tv_sec;
19797cc577a4SJonathan Peyton #endif
19807cc577a4SJonathan Peyton }
19817cc577a4SJonathan Peyton 
19827cc577a4SJonathan Peyton /* Calculate the elapsed wall clock tick for the user */
19833041982dSJonathan Peyton void __kmp_elapsed_tick(double *t) { *t = 1 / (double)CLOCKS_PER_SEC; }
19847cc577a4SJonathan Peyton 
19857cc577a4SJonathan Peyton /* Return the current time stamp in nsec */
19863041982dSJonathan Peyton kmp_uint64 __kmp_now_nsec() {
19877cc577a4SJonathan Peyton   struct timeval t;
19887cc577a4SJonathan Peyton   gettimeofday(&t, NULL);
1989bdb0a2ffSJonathan Peyton   kmp_uint64 nsec = (kmp_uint64)KMP_NSEC_PER_SEC * (kmp_uint64)t.tv_sec +
1990bdb0a2ffSJonathan Peyton                     (kmp_uint64)1000 * (kmp_uint64)t.tv_usec;
1991bdb0a2ffSJonathan Peyton   return nsec;
19927cc577a4SJonathan Peyton }
19937cc577a4SJonathan Peyton 
19947cc577a4SJonathan Peyton #if KMP_ARCH_X86 || KMP_ARCH_X86_64
199535d75aedSJonathan Peyton /* Measure clock ticks per millisecond */
19963041982dSJonathan Peyton void __kmp_initialize_system_tick() {
1997bdb0a2ffSJonathan Peyton   kmp_uint64 now, nsec2, diff;
19987cc577a4SJonathan Peyton   kmp_uint64 delay = 100000; // 50~100 usec on most machines.
19997cc577a4SJonathan Peyton   kmp_uint64 nsec = __kmp_now_nsec();
20007cc577a4SJonathan Peyton   kmp_uint64 goal = __kmp_hardware_timestamp() + delay;
20013041982dSJonathan Peyton   while ((now = __kmp_hardware_timestamp()) < goal)
20023041982dSJonathan Peyton     ;
2003bdb0a2ffSJonathan Peyton   nsec2 = __kmp_now_nsec();
2004bdb0a2ffSJonathan Peyton   diff = nsec2 - nsec;
2005bdb0a2ffSJonathan Peyton   if (diff > 0) {
20066b316febSTerry Wilmarth     kmp_uint64 tpms = ((kmp_uint64)1e6 * (delay + (now - goal)) / diff);
2007bdb0a2ffSJonathan Peyton     if (tpms > 0)
2008bdb0a2ffSJonathan Peyton       __kmp_ticks_per_msec = tpms;
2009bdb0a2ffSJonathan Peyton   }
20107cc577a4SJonathan Peyton }
20117cc577a4SJonathan Peyton #endif
20127cc577a4SJonathan Peyton 
20133041982dSJonathan Peyton /* Determine whether the given address is mapped into the current address
20143041982dSJonathan Peyton    space. */
20157cc577a4SJonathan Peyton 
20163041982dSJonathan Peyton int __kmp_is_address_mapped(void *addr) {
20177cc577a4SJonathan Peyton 
20187cc577a4SJonathan Peyton   int found = 0;
20197cc577a4SJonathan Peyton   int rc;
20207cc577a4SJonathan Peyton 
2021fef62e1aSDavid Carlier #if KMP_OS_LINUX || KMP_OS_HURD
20227cc577a4SJonathan Peyton 
2023309b00a4SShilei Tian   /* On GNUish OSes, read the /proc/<pid>/maps pseudo-file to get all the
2024309b00a4SShilei Tian      address ranges mapped into the address space. */
20257cc577a4SJonathan Peyton 
20267cc577a4SJonathan Peyton   char *name = __kmp_str_format("/proc/%d/maps", getpid());
20277cc577a4SJonathan Peyton   FILE *file = NULL;
20287cc577a4SJonathan Peyton 
20297cc577a4SJonathan Peyton   file = fopen(name, "r");
20307cc577a4SJonathan Peyton   KMP_ASSERT(file != NULL);
20317cc577a4SJonathan Peyton 
20327cc577a4SJonathan Peyton   for (;;) {
20337cc577a4SJonathan Peyton 
20347cc577a4SJonathan Peyton     void *beginning = NULL;
20357cc577a4SJonathan Peyton     void *ending = NULL;
20367cc577a4SJonathan Peyton     char perms[5];
20377cc577a4SJonathan Peyton 
20387cc577a4SJonathan Peyton     rc = fscanf(file, "%p-%p %4s %*[^\n]\n", &beginning, &ending, perms);
20397cc577a4SJonathan Peyton     if (rc == EOF) {
20407cc577a4SJonathan Peyton       break;
2041bd3a7633SJonathan Peyton     }
20423041982dSJonathan Peyton     KMP_ASSERT(rc == 3 &&
20433041982dSJonathan Peyton                KMP_STRLEN(perms) == 4); // Make sure all fields are read.
20447cc577a4SJonathan Peyton 
20457cc577a4SJonathan Peyton     // Ending address is not included in the region, but beginning is.
20467cc577a4SJonathan Peyton     if ((addr >= beginning) && (addr < ending)) {
20477cc577a4SJonathan Peyton       perms[2] = 0; // 3th and 4th character does not matter.
20487cc577a4SJonathan Peyton       if (strcmp(perms, "rw") == 0) {
20497cc577a4SJonathan Peyton         // Memory we are looking for should be readable and writable.
20507cc577a4SJonathan Peyton         found = 1;
2051bd3a7633SJonathan Peyton       }
20527cc577a4SJonathan Peyton       break;
2053bd3a7633SJonathan Peyton     }
2054bd3a7633SJonathan Peyton   }
20557cc577a4SJonathan Peyton 
20567cc577a4SJonathan Peyton   // Free resources.
20577cc577a4SJonathan Peyton   fclose(file);
20587cc577a4SJonathan Peyton   KMP_INTERNAL_FREE(name);
2059fef62e1aSDavid Carlier #elif KMP_OS_FREEBSD
2060fef62e1aSDavid Carlier   char *buf;
2061fef62e1aSDavid Carlier   size_t lstsz;
2062fef62e1aSDavid Carlier   int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()};
2063fef62e1aSDavid Carlier   rc = sysctl(mib, 4, NULL, &lstsz, NULL, 0);
2064fef62e1aSDavid Carlier   if (rc < 0)
2065fef62e1aSDavid Carlier     return 0;
2066fef62e1aSDavid Carlier   // We pass from number of vm entry's semantic
2067fef62e1aSDavid Carlier   // to size of whole entry map list.
2068fef62e1aSDavid Carlier   lstsz = lstsz * 4 / 3;
2069fef62e1aSDavid Carlier   buf = reinterpret_cast<char *>(kmpc_malloc(lstsz));
2070fef62e1aSDavid Carlier   rc = sysctl(mib, 4, buf, &lstsz, NULL, 0);
2071fef62e1aSDavid Carlier   if (rc < 0) {
2072fef62e1aSDavid Carlier     kmpc_free(buf);
2073fef62e1aSDavid Carlier     return 0;
2074fef62e1aSDavid Carlier   }
2075fef62e1aSDavid Carlier 
2076fef62e1aSDavid Carlier   char *lw = buf;
2077fef62e1aSDavid Carlier   char *up = buf + lstsz;
2078fef62e1aSDavid Carlier 
2079fef62e1aSDavid Carlier   while (lw < up) {
2080fef62e1aSDavid Carlier     struct kinfo_vmentry *cur = reinterpret_cast<struct kinfo_vmentry *>(lw);
2081fef62e1aSDavid Carlier     size_t cursz = cur->kve_structsize;
2082fef62e1aSDavid Carlier     if (cursz == 0)
2083fef62e1aSDavid Carlier       break;
2084fef62e1aSDavid Carlier     void *start = reinterpret_cast<void *>(cur->kve_start);
2085fef62e1aSDavid Carlier     void *end = reinterpret_cast<void *>(cur->kve_end);
2086fef62e1aSDavid Carlier     // Readable/Writable addresses within current map entry
2087fef62e1aSDavid Carlier     if ((addr >= start) && (addr < end)) {
2088fef62e1aSDavid Carlier       if ((cur->kve_protection & KVME_PROT_READ) != 0 &&
2089fef62e1aSDavid Carlier           (cur->kve_protection & KVME_PROT_WRITE) != 0) {
2090fef62e1aSDavid Carlier         found = 1;
2091fef62e1aSDavid Carlier         break;
2092fef62e1aSDavid Carlier       }
2093fef62e1aSDavid Carlier     }
2094fef62e1aSDavid Carlier     lw += cursz;
2095fef62e1aSDavid Carlier   }
2096fef62e1aSDavid Carlier   kmpc_free(buf);
20977cc577a4SJonathan Peyton 
20987cc577a4SJonathan Peyton #elif KMP_OS_DARWIN
20997cc577a4SJonathan Peyton 
21003041982dSJonathan Peyton   /* On OS X*, /proc pseudo filesystem is not available. Try to read memory
21013041982dSJonathan Peyton      using vm interface. */
21027cc577a4SJonathan Peyton 
21037cc577a4SJonathan Peyton   int buffer;
21047cc577a4SJonathan Peyton   vm_size_t count;
21053041982dSJonathan Peyton   rc = vm_read_overwrite(
21067cc577a4SJonathan Peyton       mach_task_self(), // Task to read memory of.
21077cc577a4SJonathan Peyton       (vm_address_t)(addr), // Address to read from.
21087cc577a4SJonathan Peyton       1, // Number of bytes to be read.
21097cc577a4SJonathan Peyton       (vm_address_t)(&buffer), // Address of buffer to save read bytes in.
21107cc577a4SJonathan Peyton       &count // Address of var to save number of read bytes in.
21117cc577a4SJonathan Peyton   );
21127cc577a4SJonathan Peyton   if (rc == 0) {
21137cc577a4SJonathan Peyton     // Memory successfully read.
21147cc577a4SJonathan Peyton     found = 1;
2115bd3a7633SJonathan Peyton   }
21167cc577a4SJonathan Peyton 
2117316f4238SKamil Rytarowski #elif KMP_OS_NETBSD
21187cc577a4SJonathan Peyton 
2119316f4238SKamil Rytarowski   int mib[5];
2120316f4238SKamil Rytarowski   mib[0] = CTL_VM;
2121316f4238SKamil Rytarowski   mib[1] = VM_PROC;
2122316f4238SKamil Rytarowski   mib[2] = VM_PROC_MAP;
2123316f4238SKamil Rytarowski   mib[3] = getpid();
2124316f4238SKamil Rytarowski   mib[4] = sizeof(struct kinfo_vmentry);
2125316f4238SKamil Rytarowski 
2126316f4238SKamil Rytarowski   size_t size;
2127316f4238SKamil Rytarowski   rc = sysctl(mib, __arraycount(mib), NULL, &size, NULL, 0);
2128316f4238SKamil Rytarowski   KMP_ASSERT(!rc);
2129316f4238SKamil Rytarowski   KMP_ASSERT(size);
2130316f4238SKamil Rytarowski 
2131316f4238SKamil Rytarowski   size = size * 4 / 3;
2132316f4238SKamil Rytarowski   struct kinfo_vmentry *kiv = (struct kinfo_vmentry *)KMP_INTERNAL_MALLOC(size);
2133316f4238SKamil Rytarowski   KMP_ASSERT(kiv);
2134316f4238SKamil Rytarowski 
2135316f4238SKamil Rytarowski   rc = sysctl(mib, __arraycount(mib), kiv, &size, NULL, 0);
2136316f4238SKamil Rytarowski   KMP_ASSERT(!rc);
2137316f4238SKamil Rytarowski   KMP_ASSERT(size);
2138316f4238SKamil Rytarowski 
2139316f4238SKamil Rytarowski   for (size_t i = 0; i < size; i++) {
2140316f4238SKamil Rytarowski     if (kiv[i].kve_start >= (uint64_t)addr &&
2141316f4238SKamil Rytarowski         kiv[i].kve_end <= (uint64_t)addr) {
2142316f4238SKamil Rytarowski       found = 1;
2143316f4238SKamil Rytarowski       break;
2144316f4238SKamil Rytarowski     }
2145316f4238SKamil Rytarowski   }
2146316f4238SKamil Rytarowski   KMP_INTERNAL_FREE(kiv);
214727f6eedcSAndreyChurbanov #elif KMP_OS_OPENBSD
2148316f4238SKamil Rytarowski 
214927f6eedcSAndreyChurbanov   int mib[3];
215027f6eedcSAndreyChurbanov   mib[0] = CTL_KERN;
215127f6eedcSAndreyChurbanov   mib[1] = KERN_PROC_VMMAP;
215227f6eedcSAndreyChurbanov   mib[2] = getpid();
215327f6eedcSAndreyChurbanov 
215427f6eedcSAndreyChurbanov   size_t size;
215527f6eedcSAndreyChurbanov   uint64_t end;
215627f6eedcSAndreyChurbanov   rc = sysctl(mib, 3, NULL, &size, NULL, 0);
215727f6eedcSAndreyChurbanov   KMP_ASSERT(!rc);
215827f6eedcSAndreyChurbanov   KMP_ASSERT(size);
215927f6eedcSAndreyChurbanov   end = size;
216027f6eedcSAndreyChurbanov 
216127f6eedcSAndreyChurbanov   struct kinfo_vmentry kiv = {.kve_start = 0};
216227f6eedcSAndreyChurbanov 
216327f6eedcSAndreyChurbanov   while ((rc = sysctl(mib, 3, &kiv, &size, NULL, 0)) == 0) {
216427f6eedcSAndreyChurbanov     KMP_ASSERT(size);
216527f6eedcSAndreyChurbanov     if (kiv.kve_end == end)
216627f6eedcSAndreyChurbanov       break;
216727f6eedcSAndreyChurbanov 
216827f6eedcSAndreyChurbanov     if (kiv.kve_start >= (uint64_t)addr && kiv.kve_end <= (uint64_t)addr) {
216927f6eedcSAndreyChurbanov       found = 1;
217027f6eedcSAndreyChurbanov       break;
217127f6eedcSAndreyChurbanov     }
217227f6eedcSAndreyChurbanov     kiv.kve_start += 1;
217327f6eedcSAndreyChurbanov   }
217427f6eedcSAndreyChurbanov #elif KMP_OS_DRAGONFLY
217527f6eedcSAndreyChurbanov 
217627f6eedcSAndreyChurbanov   // FIXME(DragonFly): Implement this
21777cc577a4SJonathan Peyton   found = 1;
21787cc577a4SJonathan Peyton 
21797cc577a4SJonathan Peyton #else
21807cc577a4SJonathan Peyton 
21817cc577a4SJonathan Peyton #error "Unknown or unsupported OS"
21827cc577a4SJonathan Peyton 
21837cc577a4SJonathan Peyton #endif
21847cc577a4SJonathan Peyton 
21857cc577a4SJonathan Peyton   return found;
21867cc577a4SJonathan Peyton 
21877cc577a4SJonathan Peyton } // __kmp_is_address_mapped
21887cc577a4SJonathan Peyton 
21897cc577a4SJonathan Peyton #ifdef USE_LOAD_BALANCE
21907cc577a4SJonathan Peyton 
219170cdd83cSMichal Gorny #if KMP_OS_DARWIN || KMP_OS_NETBSD
21927cc577a4SJonathan Peyton 
21937cc577a4SJonathan Peyton // The function returns the rounded value of the system load average
21947cc577a4SJonathan Peyton // during given time interval which depends on the value of
21957cc577a4SJonathan Peyton // __kmp_load_balance_interval variable (default is 60 sec, other values
21967cc577a4SJonathan Peyton // may be 300 sec or 900 sec).
21977cc577a4SJonathan Peyton // It returns -1 in case of error.
21983041982dSJonathan Peyton int __kmp_get_load_balance(int max) {
21997cc577a4SJonathan Peyton   double averages[3];
22007cc577a4SJonathan Peyton   int ret_avg = 0;
22017cc577a4SJonathan Peyton 
22027cc577a4SJonathan Peyton   int res = getloadavg(averages, 3);
22037cc577a4SJonathan Peyton 
22047cc577a4SJonathan Peyton   // Check __kmp_load_balance_interval to determine which of averages to use.
22057cc577a4SJonathan Peyton   // getloadavg() may return the number of samples less than requested that is
22067cc577a4SJonathan Peyton   // less than 3.
22077cc577a4SJonathan Peyton   if (__kmp_load_balance_interval < 180 && (res >= 1)) {
22086b316febSTerry Wilmarth     ret_avg = (int)averages[0]; // 1 min
22093041982dSJonathan Peyton   } else if ((__kmp_load_balance_interval >= 180 &&
22103041982dSJonathan Peyton               __kmp_load_balance_interval < 600) &&
22113041982dSJonathan Peyton              (res >= 2)) {
22126b316febSTerry Wilmarth     ret_avg = (int)averages[1]; // 5 min
22137cc577a4SJonathan Peyton   } else if ((__kmp_load_balance_interval >= 600) && (res == 3)) {
22146b316febSTerry Wilmarth     ret_avg = (int)averages[2]; // 15 min
22157cc577a4SJonathan Peyton   } else { // Error occurred
22167cc577a4SJonathan Peyton     return -1;
22177cc577a4SJonathan Peyton   }
22187cc577a4SJonathan Peyton 
22197cc577a4SJonathan Peyton   return ret_avg;
22207cc577a4SJonathan Peyton }
22217cc577a4SJonathan Peyton 
22227cc577a4SJonathan Peyton #else // Linux* OS
22237cc577a4SJonathan Peyton 
222442016791SKazuaki Ishizaki // The function returns number of running (not sleeping) threads, or -1 in case
22253041982dSJonathan Peyton // of error. Error could be reported if Linux* OS kernel too old (without
22263041982dSJonathan Peyton // "/proc" support). Counting running threads stops if max running threads
22273041982dSJonathan Peyton // encountered.
22283041982dSJonathan Peyton int __kmp_get_load_balance(int max) {
22297cc577a4SJonathan Peyton   static int permanent_error = 0;
22303041982dSJonathan Peyton   static int glb_running_threads = 0; // Saved count of the running threads for
2231ed5fe645SKelvin Li   // the thread balance algorithm
22327cc577a4SJonathan Peyton   static double glb_call_time = 0; /* Thread balance algorithm call time */
22337cc577a4SJonathan Peyton 
22347cc577a4SJonathan Peyton   int running_threads = 0; // Number of running threads in the system.
22357cc577a4SJonathan Peyton 
22367cc577a4SJonathan Peyton   DIR *proc_dir = NULL; // Handle of "/proc/" directory.
22377cc577a4SJonathan Peyton   struct dirent *proc_entry = NULL;
22387cc577a4SJonathan Peyton 
22397cc577a4SJonathan Peyton   kmp_str_buf_t task_path; // "/proc/<pid>/task/<tid>/" path.
22407cc577a4SJonathan Peyton   DIR *task_dir = NULL; // Handle of "/proc/<pid>/task/<tid>/" directory.
22417cc577a4SJonathan Peyton   struct dirent *task_entry = NULL;
22427cc577a4SJonathan Peyton   int task_path_fixed_len;
22437cc577a4SJonathan Peyton 
22447cc577a4SJonathan Peyton   kmp_str_buf_t stat_path; // "/proc/<pid>/task/<tid>/stat" path.
22457cc577a4SJonathan Peyton   int stat_file = -1;
22467cc577a4SJonathan Peyton   int stat_path_fixed_len;
22477cc577a4SJonathan Peyton 
22487cc577a4SJonathan Peyton   int total_processes = 0; // Total number of processes in system.
22497cc577a4SJonathan Peyton   int total_threads = 0; // Total number of threads in system.
22507cc577a4SJonathan Peyton 
22517cc577a4SJonathan Peyton   double call_time = 0.0;
22527cc577a4SJonathan Peyton 
22537cc577a4SJonathan Peyton   __kmp_str_buf_init(&task_path);
22547cc577a4SJonathan Peyton   __kmp_str_buf_init(&stat_path);
22557cc577a4SJonathan Peyton 
22567cc577a4SJonathan Peyton   __kmp_elapsed(&call_time);
22577cc577a4SJonathan Peyton 
22587cc577a4SJonathan Peyton   if (glb_call_time &&
22597cc577a4SJonathan Peyton       (call_time - glb_call_time < __kmp_load_balance_interval)) {
22607cc577a4SJonathan Peyton     running_threads = glb_running_threads;
22617cc577a4SJonathan Peyton     goto finish;
22627cc577a4SJonathan Peyton   }
22637cc577a4SJonathan Peyton 
22647cc577a4SJonathan Peyton   glb_call_time = call_time;
22657cc577a4SJonathan Peyton 
22667cc577a4SJonathan Peyton   // Do not spend time on scanning "/proc/" if we have a permanent error.
22677cc577a4SJonathan Peyton   if (permanent_error) {
22687cc577a4SJonathan Peyton     running_threads = -1;
22697cc577a4SJonathan Peyton     goto finish;
2270bd3a7633SJonathan Peyton   }
22717cc577a4SJonathan Peyton 
22727cc577a4SJonathan Peyton   if (max <= 0) {
22737cc577a4SJonathan Peyton     max = INT_MAX;
2274bd3a7633SJonathan Peyton   }
22757cc577a4SJonathan Peyton 
22767cc577a4SJonathan Peyton   // Open "/proc/" directory.
22777cc577a4SJonathan Peyton   proc_dir = opendir("/proc");
22787cc577a4SJonathan Peyton   if (proc_dir == NULL) {
22793041982dSJonathan Peyton     // Cannot open "/prroc/". Probably the kernel does not support it. Return an
22803041982dSJonathan Peyton     // error now and in subsequent calls.
22817cc577a4SJonathan Peyton     running_threads = -1;
22827cc577a4SJonathan Peyton     permanent_error = 1;
22837cc577a4SJonathan Peyton     goto finish;
2284bd3a7633SJonathan Peyton   }
22857cc577a4SJonathan Peyton 
22867cc577a4SJonathan Peyton   // Initialize fixed part of task_path. This part will not change.
22877cc577a4SJonathan Peyton   __kmp_str_buf_cat(&task_path, "/proc/", 6);
22887cc577a4SJonathan Peyton   task_path_fixed_len = task_path.used; // Remember number of used characters.
22897cc577a4SJonathan Peyton 
22907cc577a4SJonathan Peyton   proc_entry = readdir(proc_dir);
22917cc577a4SJonathan Peyton   while (proc_entry != NULL) {
22923041982dSJonathan Peyton     // Proc entry is a directory and name starts with a digit. Assume it is a
22933041982dSJonathan Peyton     // process' directory.
22947cc577a4SJonathan Peyton     if (proc_entry->d_type == DT_DIR && isdigit(proc_entry->d_name[0])) {
22957cc577a4SJonathan Peyton 
22967cc577a4SJonathan Peyton       ++total_processes;
22977cc577a4SJonathan Peyton       // Make sure init process is the very first in "/proc", so we can replace
22983041982dSJonathan Peyton       // strcmp( proc_entry->d_name, "1" ) == 0 with simpler total_processes ==
22993041982dSJonathan Peyton       // 1. We are going to check that total_processes == 1 => d_name == "1" is
23003041982dSJonathan Peyton       // true (where "=>" is implication). Since C++ does not have => operator,
23013041982dSJonathan Peyton       // let us replace it with its equivalent: a => b == ! a || b.
23023041982dSJonathan Peyton       KMP_DEBUG_ASSERT(total_processes != 1 ||
23033041982dSJonathan Peyton                        strcmp(proc_entry->d_name, "1") == 0);
23047cc577a4SJonathan Peyton 
23057cc577a4SJonathan Peyton       // Construct task_path.
23067cc577a4SJonathan Peyton       task_path.used = task_path_fixed_len; // Reset task_path to "/proc/".
23073041982dSJonathan Peyton       __kmp_str_buf_cat(&task_path, proc_entry->d_name,
23083041982dSJonathan Peyton                         KMP_STRLEN(proc_entry->d_name));
23097cc577a4SJonathan Peyton       __kmp_str_buf_cat(&task_path, "/task", 5);
23107cc577a4SJonathan Peyton 
23117cc577a4SJonathan Peyton       task_dir = opendir(task_path.str);
23127cc577a4SJonathan Peyton       if (task_dir == NULL) {
23133041982dSJonathan Peyton         // Process can finish between reading "/proc/" directory entry and
23143041982dSJonathan Peyton         // opening process' "task/" directory. So, in general case we should not
23153041982dSJonathan Peyton         // complain, but have to skip this process and read the next one. But on
23163041982dSJonathan Peyton         // systems with no "task/" support we will spend lot of time to scan
23173041982dSJonathan Peyton         // "/proc/" tree again and again without any benefit. "init" process
23183041982dSJonathan Peyton         // (its pid is 1) should exist always, so, if we cannot open
23193041982dSJonathan Peyton         // "/proc/1/task/" directory, it means "task/" is not supported by
23203041982dSJonathan Peyton         // kernel. Report an error now and in the future.
23217cc577a4SJonathan Peyton         if (strcmp(proc_entry->d_name, "1") == 0) {
23227cc577a4SJonathan Peyton           running_threads = -1;
23237cc577a4SJonathan Peyton           permanent_error = 1;
23247cc577a4SJonathan Peyton           goto finish;
2325bd3a7633SJonathan Peyton         }
23267cc577a4SJonathan Peyton       } else {
23277cc577a4SJonathan Peyton         // Construct fixed part of stat file path.
23287cc577a4SJonathan Peyton         __kmp_str_buf_clear(&stat_path);
23297cc577a4SJonathan Peyton         __kmp_str_buf_cat(&stat_path, task_path.str, task_path.used);
23307cc577a4SJonathan Peyton         __kmp_str_buf_cat(&stat_path, "/", 1);
23317cc577a4SJonathan Peyton         stat_path_fixed_len = stat_path.used;
23327cc577a4SJonathan Peyton 
23337cc577a4SJonathan Peyton         task_entry = readdir(task_dir);
23347cc577a4SJonathan Peyton         while (task_entry != NULL) {
23357cc577a4SJonathan Peyton           // It is a directory and name starts with a digit.
23367cc577a4SJonathan Peyton           if (proc_entry->d_type == DT_DIR && isdigit(task_entry->d_name[0])) {
23377cc577a4SJonathan Peyton             ++total_threads;
23387cc577a4SJonathan Peyton 
2339ed5fe645SKelvin Li             // Construct complete stat file path. Easiest way would be:
23403041982dSJonathan Peyton             //  __kmp_str_buf_print( & stat_path, "%s/%s/stat", task_path.str,
23413041982dSJonathan Peyton             //  task_entry->d_name );
23427cc577a4SJonathan Peyton             // but seriae of __kmp_str_buf_cat works a bit faster.
23433041982dSJonathan Peyton             stat_path.used =
23443041982dSJonathan Peyton                 stat_path_fixed_len; // Reset stat path to its fixed part.
23453041982dSJonathan Peyton             __kmp_str_buf_cat(&stat_path, task_entry->d_name,
23463041982dSJonathan Peyton                               KMP_STRLEN(task_entry->d_name));
23477cc577a4SJonathan Peyton             __kmp_str_buf_cat(&stat_path, "/stat", 5);
23487cc577a4SJonathan Peyton 
23497cc577a4SJonathan Peyton             // Note: Low-level API (open/read/close) is used. High-level API
23507cc577a4SJonathan Peyton             // (fopen/fclose)  works ~ 30 % slower.
23517cc577a4SJonathan Peyton             stat_file = open(stat_path.str, O_RDONLY);
23527cc577a4SJonathan Peyton             if (stat_file == -1) {
23533041982dSJonathan Peyton               // We cannot report an error because task (thread) can terminate
23543041982dSJonathan Peyton               // just before reading this file.
23557cc577a4SJonathan Peyton             } else {
23563041982dSJonathan Peyton               /* Content of "stat" file looks like:
23577cc577a4SJonathan Peyton                  24285 (program) S ...
23587cc577a4SJonathan Peyton 
23593041982dSJonathan Peyton                  It is a single line (if program name does not include funny
23603041982dSJonathan Peyton                  symbols). First number is a thread id, then name of executable
23613041982dSJonathan Peyton                  file name in paretheses, then state of the thread. We need just
23623041982dSJonathan Peyton                  thread state.
23637cc577a4SJonathan Peyton 
23647cc577a4SJonathan Peyton                  Good news: Length of program name is 15 characters max. Longer
23657cc577a4SJonathan Peyton                  names are truncated.
23667cc577a4SJonathan Peyton 
23677cc577a4SJonathan Peyton                  Thus, we need rather short buffer: 15 chars for program name +
23687cc577a4SJonathan Peyton                  2 parenthesis, + 3 spaces + ~7 digits of pid = 37.
23697cc577a4SJonathan Peyton 
23707cc577a4SJonathan Peyton                  Bad news: Program name may contain special symbols like space,
23713041982dSJonathan Peyton                  closing parenthesis, or even new line. This makes parsing
23723041982dSJonathan Peyton                  "stat" file not 100 % reliable. In case of fanny program names
23733041982dSJonathan Peyton                  parsing may fail (report incorrect thread state).
23747cc577a4SJonathan Peyton 
23757cc577a4SJonathan Peyton                  Parsing "status" file looks more promissing (due to different
23767cc577a4SJonathan Peyton                  file structure and escaping special symbols) but reading and
23777cc577a4SJonathan Peyton                  parsing of "status" file works slower.
23787cc577a4SJonathan Peyton                   -- ln
23797cc577a4SJonathan Peyton               */
23807cc577a4SJonathan Peyton               char buffer[65];
23816b316febSTerry Wilmarth               ssize_t len;
23827cc577a4SJonathan Peyton               len = read(stat_file, buffer, sizeof(buffer) - 1);
23837cc577a4SJonathan Peyton               if (len >= 0) {
23847cc577a4SJonathan Peyton                 buffer[len] = 0;
23857cc577a4SJonathan Peyton                 // Using scanf:
23867cc577a4SJonathan Peyton                 //     sscanf( buffer, "%*d (%*s) %c ", & state );
23873041982dSJonathan Peyton                 // looks very nice, but searching for a closing parenthesis
23883041982dSJonathan Peyton                 // works a bit faster.
23897cc577a4SJonathan Peyton                 char *close_parent = strstr(buffer, ") ");
23907cc577a4SJonathan Peyton                 if (close_parent != NULL) {
23917cc577a4SJonathan Peyton                   char state = *(close_parent + 2);
23927cc577a4SJonathan Peyton                   if (state == 'R') {
23937cc577a4SJonathan Peyton                     ++running_threads;
23947cc577a4SJonathan Peyton                     if (running_threads >= max) {
23957cc577a4SJonathan Peyton                       goto finish;
2396bd3a7633SJonathan Peyton                     }
2397bd3a7633SJonathan Peyton                   }
2398bd3a7633SJonathan Peyton                 }
2399bd3a7633SJonathan Peyton               }
24007cc577a4SJonathan Peyton               close(stat_file);
24017cc577a4SJonathan Peyton               stat_file = -1;
2402bd3a7633SJonathan Peyton             }
2403bd3a7633SJonathan Peyton           }
24047cc577a4SJonathan Peyton           task_entry = readdir(task_dir);
2405bd3a7633SJonathan Peyton         }
24067cc577a4SJonathan Peyton         closedir(task_dir);
24077cc577a4SJonathan Peyton         task_dir = NULL;
2408bd3a7633SJonathan Peyton       }
2409bd3a7633SJonathan Peyton     }
24107cc577a4SJonathan Peyton     proc_entry = readdir(proc_dir);
2411bd3a7633SJonathan Peyton   }
24127cc577a4SJonathan Peyton 
24137cc577a4SJonathan Peyton   // There _might_ be a timing hole where the thread executing this
24147cc577a4SJonathan Peyton   // code get skipped in the load balance, and running_threads is 0.
24157cc577a4SJonathan Peyton   // Assert in the debug builds only!!!
24167cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(running_threads > 0);
24177cc577a4SJonathan Peyton   if (running_threads <= 0) {
24187cc577a4SJonathan Peyton     running_threads = 1;
24197cc577a4SJonathan Peyton   }
24207cc577a4SJonathan Peyton 
24217cc577a4SJonathan Peyton finish: // Clean up and exit.
24227cc577a4SJonathan Peyton   if (proc_dir != NULL) {
24237cc577a4SJonathan Peyton     closedir(proc_dir);
2424bd3a7633SJonathan Peyton   }
24257cc577a4SJonathan Peyton   __kmp_str_buf_free(&task_path);
24267cc577a4SJonathan Peyton   if (task_dir != NULL) {
24277cc577a4SJonathan Peyton     closedir(task_dir);
2428bd3a7633SJonathan Peyton   }
24297cc577a4SJonathan Peyton   __kmp_str_buf_free(&stat_path);
24307cc577a4SJonathan Peyton   if (stat_file != -1) {
24317cc577a4SJonathan Peyton     close(stat_file);
2432bd3a7633SJonathan Peyton   }
24337cc577a4SJonathan Peyton 
24347cc577a4SJonathan Peyton   glb_running_threads = running_threads;
24357cc577a4SJonathan Peyton 
24367cc577a4SJonathan Peyton   return running_threads;
24377cc577a4SJonathan Peyton 
24387cc577a4SJonathan Peyton } // __kmp_get_load_balance
24397cc577a4SJonathan Peyton 
24407cc577a4SJonathan Peyton #endif // KMP_OS_DARWIN
24417cc577a4SJonathan Peyton 
24427cc577a4SJonathan Peyton #endif // USE_LOAD_BALANCE
24437cc577a4SJonathan Peyton 
2444c47afcd9SAndrey Churbanov #if !(KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_MIC ||                            \
24452488ae9dSJonas Hahnfeld       ((KMP_OS_LINUX || KMP_OS_DARWIN) && KMP_ARCH_AARCH64) ||                 \
24462488ae9dSJonas Hahnfeld       KMP_ARCH_PPC64 || KMP_ARCH_RISCV64)
24477cc577a4SJonathan Peyton 
24487cc577a4SJonathan Peyton // we really only need the case with 1 argument, because CLANG always build
24497cc577a4SJonathan Peyton // a struct of pointers to shared variables referenced in the outlined function
24503041982dSJonathan Peyton int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,
24513041982dSJonathan Peyton                            void *p_argv[]
24527cc577a4SJonathan Peyton #if OMPT_SUPPORT
24533041982dSJonathan Peyton                            ,
24543041982dSJonathan Peyton                            void **exit_frame_ptr
24557cc577a4SJonathan Peyton #endif
24563041982dSJonathan Peyton ) {
24577cc577a4SJonathan Peyton #if OMPT_SUPPORT
245882e94a59SJoachim Protze   *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0);
24597cc577a4SJonathan Peyton #endif
24607cc577a4SJonathan Peyton 
24617cc577a4SJonathan Peyton   switch (argc) {
24627cc577a4SJonathan Peyton   default:
24637cc577a4SJonathan Peyton     fprintf(stderr, "Too many args to microtask: %d!\n", argc);
24647cc577a4SJonathan Peyton     fflush(stderr);
24657cc577a4SJonathan Peyton     exit(-1);
24667cc577a4SJonathan Peyton   case 0:
24677cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid);
24687cc577a4SJonathan Peyton     break;
24697cc577a4SJonathan Peyton   case 1:
24707cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0]);
24717cc577a4SJonathan Peyton     break;
24727cc577a4SJonathan Peyton   case 2:
24737cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1]);
24747cc577a4SJonathan Peyton     break;
24757cc577a4SJonathan Peyton   case 3:
24767cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2]);
24777cc577a4SJonathan Peyton     break;
24787cc577a4SJonathan Peyton   case 4:
24797cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3]);
24807cc577a4SJonathan Peyton     break;
24817cc577a4SJonathan Peyton   case 5:
24827cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4]);
24837cc577a4SJonathan Peyton     break;
24847cc577a4SJonathan Peyton   case 6:
24857cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
24867cc577a4SJonathan Peyton             p_argv[5]);
24877cc577a4SJonathan Peyton     break;
24887cc577a4SJonathan Peyton   case 7:
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], p_argv[6]);
24917cc577a4SJonathan Peyton     break;
24927cc577a4SJonathan Peyton   case 8:
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], p_argv[7]);
24957cc577a4SJonathan Peyton     break;
24967cc577a4SJonathan Peyton   case 9:
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], p_argv[8]);
24997cc577a4SJonathan Peyton     break;
25007cc577a4SJonathan Peyton   case 10:
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], p_argv[9]);
25037cc577a4SJonathan Peyton     break;
25047cc577a4SJonathan Peyton   case 11:
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], p_argv[10]);
25077cc577a4SJonathan Peyton     break;
25087cc577a4SJonathan Peyton   case 12:
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             p_argv[11]);
25127cc577a4SJonathan Peyton     break;
25137cc577a4SJonathan Peyton   case 13:
25147cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25157cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
25167cc577a4SJonathan Peyton             p_argv[11], p_argv[12]);
25177cc577a4SJonathan Peyton     break;
25187cc577a4SJonathan Peyton   case 14:
25197cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25207cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
25217cc577a4SJonathan Peyton             p_argv[11], p_argv[12], p_argv[13]);
25227cc577a4SJonathan Peyton     break;
25237cc577a4SJonathan Peyton   case 15:
25247cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25257cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
25267cc577a4SJonathan Peyton             p_argv[11], p_argv[12], p_argv[13], p_argv[14]);
25277cc577a4SJonathan Peyton     break;
25287cc577a4SJonathan Peyton   }
25297cc577a4SJonathan Peyton 
25307cc577a4SJonathan Peyton   return 1;
25317cc577a4SJonathan Peyton }
25327cc577a4SJonathan Peyton 
25337cc577a4SJonathan Peyton #endif
25347cc577a4SJonathan Peyton 
25359d64275aSShilei Tian // Functions for hidden helper task
25369d64275aSShilei Tian namespace {
25379d64275aSShilei Tian // Condition variable for initializing hidden helper team
25389d64275aSShilei Tian pthread_cond_t hidden_helper_threads_initz_cond_var;
25399d64275aSShilei Tian pthread_mutex_t hidden_helper_threads_initz_lock;
25409d64275aSShilei Tian volatile int hidden_helper_initz_signaled = FALSE;
25419d64275aSShilei Tian 
25429d64275aSShilei Tian // Condition variable for deinitializing hidden helper team
25439d64275aSShilei Tian pthread_cond_t hidden_helper_threads_deinitz_cond_var;
25449d64275aSShilei Tian pthread_mutex_t hidden_helper_threads_deinitz_lock;
25459d64275aSShilei Tian volatile int hidden_helper_deinitz_signaled = FALSE;
25469d64275aSShilei Tian 
25479d64275aSShilei Tian // Condition variable for the wrapper function of main thread
25489d64275aSShilei Tian pthread_cond_t hidden_helper_main_thread_cond_var;
25499d64275aSShilei Tian pthread_mutex_t hidden_helper_main_thread_lock;
25509d64275aSShilei Tian volatile int hidden_helper_main_thread_signaled = FALSE;
25519d64275aSShilei Tian 
25529d64275aSShilei Tian // Semaphore for worker threads. We don't use condition variable here in case
25539d64275aSShilei Tian // that when multiple signals are sent at the same time, only one thread might
25549d64275aSShilei Tian // be waken.
25559d64275aSShilei Tian sem_t hidden_helper_task_sem;
25569d64275aSShilei Tian } // namespace
25579d64275aSShilei Tian 
25589d64275aSShilei Tian void __kmp_hidden_helper_worker_thread_wait() {
25599d64275aSShilei Tian   int status = sem_wait(&hidden_helper_task_sem);
25609d64275aSShilei Tian   KMP_CHECK_SYSFAIL("sem_wait", status);
25619d64275aSShilei Tian }
25629d64275aSShilei Tian 
25639d64275aSShilei Tian void __kmp_do_initialize_hidden_helper_threads() {
25649d64275aSShilei Tian   // Initialize condition variable
25659d64275aSShilei Tian   int status =
25669d64275aSShilei Tian       pthread_cond_init(&hidden_helper_threads_initz_cond_var, nullptr);
25679d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
25689d64275aSShilei Tian 
25699d64275aSShilei Tian   status = pthread_cond_init(&hidden_helper_threads_deinitz_cond_var, nullptr);
25709d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
25719d64275aSShilei Tian 
25729d64275aSShilei Tian   status = pthread_cond_init(&hidden_helper_main_thread_cond_var, nullptr);
25739d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
25749d64275aSShilei Tian 
25759d64275aSShilei Tian   status = pthread_mutex_init(&hidden_helper_threads_initz_lock, nullptr);
25769d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
25779d64275aSShilei Tian 
25789d64275aSShilei Tian   status = pthread_mutex_init(&hidden_helper_threads_deinitz_lock, nullptr);
25799d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
25809d64275aSShilei Tian 
25819d64275aSShilei Tian   status = pthread_mutex_init(&hidden_helper_main_thread_lock, nullptr);
25829d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
25839d64275aSShilei Tian 
25849d64275aSShilei Tian   // Initialize the semaphore
25859d64275aSShilei Tian   status = sem_init(&hidden_helper_task_sem, 0, 0);
25869d64275aSShilei Tian   KMP_CHECK_SYSFAIL("sem_init", status);
25879d64275aSShilei Tian 
25889d64275aSShilei Tian   // Create a new thread to finish initialization
25899d64275aSShilei Tian   pthread_t handle;
25909d64275aSShilei Tian   status = pthread_create(
25919d64275aSShilei Tian       &handle, nullptr,
25929d64275aSShilei Tian       [](void *) -> void * {
25939d64275aSShilei Tian         __kmp_hidden_helper_threads_initz_routine();
25949d64275aSShilei Tian         return nullptr;
25959d64275aSShilei Tian       },
25969d64275aSShilei Tian       nullptr);
25979d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_create", status);
25989d64275aSShilei Tian }
25999d64275aSShilei Tian 
26009d64275aSShilei Tian void __kmp_hidden_helper_threads_initz_wait() {
26019d64275aSShilei Tian   // Initial thread waits here for the completion of the initialization. The
26029d64275aSShilei Tian   // condition variable will be notified by main thread of hidden helper teams.
26039d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_threads_initz_lock);
26049d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26059d64275aSShilei Tian 
26069d64275aSShilei Tian   if (!TCR_4(hidden_helper_initz_signaled)) {
26079d64275aSShilei Tian     status = pthread_cond_wait(&hidden_helper_threads_initz_cond_var,
26089d64275aSShilei Tian                                &hidden_helper_threads_initz_lock);
26099d64275aSShilei Tian     KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26109d64275aSShilei Tian   }
26119d64275aSShilei Tian 
26129d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_threads_initz_lock);
26139d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26149d64275aSShilei Tian }
26159d64275aSShilei Tian 
26169d64275aSShilei Tian void __kmp_hidden_helper_initz_release() {
26179d64275aSShilei Tian   // After all initialization, reset __kmp_init_hidden_helper_threads to false.
26189d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_threads_initz_lock);
26199d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26209d64275aSShilei Tian 
26219d64275aSShilei Tian   status = pthread_cond_signal(&hidden_helper_threads_initz_cond_var);
26229d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26239d64275aSShilei Tian 
26249d64275aSShilei Tian   TCW_SYNC_4(hidden_helper_initz_signaled, TRUE);
26259d64275aSShilei Tian 
26269d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_threads_initz_lock);
26279d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26289d64275aSShilei Tian }
26299d64275aSShilei Tian 
26309d64275aSShilei Tian void __kmp_hidden_helper_main_thread_wait() {
26319d64275aSShilei Tian   // The main thread of hidden helper team will be blocked here. The
26329d64275aSShilei Tian   // condition variable can only be signal in the destructor of RTL.
26339d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_main_thread_lock);
26349d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26359d64275aSShilei Tian 
26369d64275aSShilei Tian   if (!TCR_4(hidden_helper_main_thread_signaled)) {
26379d64275aSShilei Tian     status = pthread_cond_wait(&hidden_helper_main_thread_cond_var,
26389d64275aSShilei Tian                                &hidden_helper_main_thread_lock);
26399d64275aSShilei Tian     KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26409d64275aSShilei Tian   }
26419d64275aSShilei Tian 
26429d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_main_thread_lock);
26439d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26449d64275aSShilei Tian }
26459d64275aSShilei Tian 
26469d64275aSShilei Tian void __kmp_hidden_helper_main_thread_release() {
26479d64275aSShilei Tian   // The initial thread of OpenMP RTL should call this function to wake up the
26489d64275aSShilei Tian   // main thread of hidden helper team.
26499d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_main_thread_lock);
26509d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26519d64275aSShilei Tian 
26529d64275aSShilei Tian   status = pthread_cond_signal(&hidden_helper_main_thread_cond_var);
26539d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_signal", status);
26549d64275aSShilei Tian 
26559d64275aSShilei Tian   // The hidden helper team is done here
26569d64275aSShilei Tian   TCW_SYNC_4(hidden_helper_main_thread_signaled, TRUE);
26579d64275aSShilei Tian 
26589d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_main_thread_lock);
26599d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26609d64275aSShilei Tian }
26619d64275aSShilei Tian 
26629d64275aSShilei Tian void __kmp_hidden_helper_worker_thread_signal() {
26639d64275aSShilei Tian   int status = sem_post(&hidden_helper_task_sem);
26649d64275aSShilei Tian   KMP_CHECK_SYSFAIL("sem_post", status);
26659d64275aSShilei Tian }
26669d64275aSShilei Tian 
26679d64275aSShilei Tian void __kmp_hidden_helper_threads_deinitz_wait() {
26689d64275aSShilei Tian   // Initial thread waits here for the completion of the deinitialization. The
26699d64275aSShilei Tian   // condition variable will be notified by main thread of hidden helper teams.
26709d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_threads_deinitz_lock);
26719d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26729d64275aSShilei Tian 
26739d64275aSShilei Tian   if (!TCR_4(hidden_helper_deinitz_signaled)) {
26749d64275aSShilei Tian     status = pthread_cond_wait(&hidden_helper_threads_deinitz_cond_var,
26759d64275aSShilei Tian                                &hidden_helper_threads_deinitz_lock);
26769d64275aSShilei Tian     KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26779d64275aSShilei Tian   }
26789d64275aSShilei Tian 
26799d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_threads_deinitz_lock);
26809d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26819d64275aSShilei Tian }
26829d64275aSShilei Tian 
26839d64275aSShilei Tian void __kmp_hidden_helper_threads_deinitz_release() {
26849d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_threads_deinitz_lock);
26859d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26869d64275aSShilei Tian 
26879d64275aSShilei Tian   status = pthread_cond_signal(&hidden_helper_threads_deinitz_cond_var);
26889d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26899d64275aSShilei Tian 
26909d64275aSShilei Tian   TCW_SYNC_4(hidden_helper_deinitz_signaled, TRUE);
26919d64275aSShilei Tian 
26929d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_threads_deinitz_lock);
26939d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26949d64275aSShilei Tian }
26959d64275aSShilei Tian 
26967cc577a4SJonathan Peyton // end of file //
2697