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);
283*309b00a4SShilei Tian   gCode = pthread_getaffinity_np(pthread_self(), KMP_CPU_SET_SIZE_LIMIT,
284*309b00a4SShilei 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   }
515*309b00a4SShilei Tian #endif /* KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD  \
516*309b00a4SShilei 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   }
1306072ccb72SJonathan Peyton #endif // KMP_AFFINITY_SUPPORTED
1307d330e630SJonathan Peyton 
13087cc577a4SJonathan Peyton #if KMP_USE_MONITOR
13097cc577a4SJonathan Peyton   __kmp_init_monitor = 0;
13107cc577a4SJonathan Peyton #endif
13117cc577a4SJonathan Peyton   __kmp_init_parallel = FALSE;
13127cc577a4SJonathan Peyton   __kmp_init_middle = FALSE;
13137cc577a4SJonathan Peyton   __kmp_init_serial = FALSE;
13147cc577a4SJonathan Peyton   TCW_4(__kmp_init_gtid, FALSE);
13157cc577a4SJonathan Peyton   __kmp_init_common = FALSE;
13167cc577a4SJonathan Peyton 
13177cc577a4SJonathan Peyton   TCW_4(__kmp_init_user_locks, FALSE);
13187cc577a4SJonathan Peyton #if !KMP_USE_DYNAMIC_LOCK
13197cc577a4SJonathan Peyton   __kmp_user_lock_table.used = 1;
13207cc577a4SJonathan Peyton   __kmp_user_lock_table.allocated = 0;
13217cc577a4SJonathan Peyton   __kmp_user_lock_table.table = NULL;
13227cc577a4SJonathan Peyton   __kmp_lock_blocks = NULL;
13237cc577a4SJonathan Peyton #endif
13247cc577a4SJonathan Peyton 
13257cc577a4SJonathan Peyton   __kmp_all_nth = 0;
13267cc577a4SJonathan Peyton   TCW_4(__kmp_nth, 0);
13277cc577a4SJonathan Peyton 
1328eaa9e40cSJonathan Peyton   __kmp_thread_pool = NULL;
1329eaa9e40cSJonathan Peyton   __kmp_thread_pool_insert_pt = NULL;
1330eaa9e40cSJonathan Peyton   __kmp_team_pool = NULL;
1331eaa9e40cSJonathan Peyton 
13323041982dSJonathan Peyton   /* Must actually zero all the *cache arguments passed to __kmpc_threadprivate
13333041982dSJonathan Peyton      here so threadprivate doesn't use stale data */
13347cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_atfork_child: checking cache address list %p\n",
13357cc577a4SJonathan Peyton                 __kmp_threadpriv_cache_list));
13367cc577a4SJonathan Peyton 
13377cc577a4SJonathan Peyton   while (__kmp_threadpriv_cache_list != NULL) {
13387cc577a4SJonathan Peyton 
13397cc577a4SJonathan Peyton     if (*__kmp_threadpriv_cache_list->addr != NULL) {
13407cc577a4SJonathan Peyton       KC_TRACE(50, ("__kmp_atfork_child: zeroing cache at address %p\n",
13417cc577a4SJonathan Peyton                     &(*__kmp_threadpriv_cache_list->addr)));
13427cc577a4SJonathan Peyton 
13437cc577a4SJonathan Peyton       *__kmp_threadpriv_cache_list->addr = NULL;
13447cc577a4SJonathan Peyton     }
13457cc577a4SJonathan Peyton     __kmp_threadpriv_cache_list = __kmp_threadpriv_cache_list->next;
13467cc577a4SJonathan Peyton   }
13477cc577a4SJonathan Peyton 
13487cc577a4SJonathan Peyton   __kmp_init_runtime = FALSE;
13497cc577a4SJonathan Peyton 
13507cc577a4SJonathan Peyton   /* reset statically initialized locks */
13517cc577a4SJonathan Peyton   __kmp_init_bootstrap_lock(&__kmp_initz_lock);
13527cc577a4SJonathan Peyton   __kmp_init_bootstrap_lock(&__kmp_stdio_lock);
13537cc577a4SJonathan Peyton   __kmp_init_bootstrap_lock(&__kmp_console_lock);
1354eaa9e40cSJonathan Peyton   __kmp_init_bootstrap_lock(&__kmp_task_team_lock);
1355eaa9e40cSJonathan Peyton 
13565388acd3SAndrey Churbanov #if USE_ITT_BUILD
1357eaa9e40cSJonathan Peyton   __kmp_itt_reset(); // reset ITT's global state
13585388acd3SAndrey Churbanov #endif /* USE_ITT_BUILD */
13597cc577a4SJonathan Peyton 
1360171ca93cSHansang Bae   __kmp_serial_initialize();
1361171ca93cSHansang Bae 
13627cc577a4SJonathan Peyton   /* This is necessary to make sure no stale data is left around */
13637cc577a4SJonathan Peyton   /* AC: customers complain that we use unsafe routines in the atfork
13647cc577a4SJonathan Peyton      handler. Mathworks: dlsym() is unsafe. We call dlsym and dlopen
13657cc577a4SJonathan Peyton      in dynamic_link when check the presence of shared tbbmalloc library.
13667cc577a4SJonathan Peyton      Suggestion is to make the library initialization lazier, similar
13677cc577a4SJonathan Peyton      to what done for __kmpc_begin(). */
13687cc577a4SJonathan Peyton   // TODO: synchronize all static initializations with regular library
1369de4749b7SJonathan Peyton   //       startup; look at kmp_global.cpp and etc.
13707cc577a4SJonathan Peyton   //__kmp_internal_begin ();
13717cc577a4SJonathan Peyton }
13727cc577a4SJonathan Peyton 
13733041982dSJonathan Peyton void __kmp_register_atfork(void) {
13747cc577a4SJonathan Peyton   if (__kmp_need_register_atfork) {
13753041982dSJonathan Peyton     int status = pthread_atfork(__kmp_atfork_prepare, __kmp_atfork_parent,
13763041982dSJonathan Peyton                                 __kmp_atfork_child);
13777cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_atfork", status);
13787cc577a4SJonathan Peyton     __kmp_need_register_atfork = FALSE;
13797cc577a4SJonathan Peyton   }
13807cc577a4SJonathan Peyton }
13817cc577a4SJonathan Peyton 
13823041982dSJonathan Peyton void __kmp_suspend_initialize(void) {
13837cc577a4SJonathan Peyton   int status;
13847cc577a4SJonathan Peyton   status = pthread_mutexattr_init(&__kmp_suspend_mutex_attr);
13857cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutexattr_init", status);
13867cc577a4SJonathan Peyton   status = pthread_condattr_init(&__kmp_suspend_cond_attr);
13877cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_condattr_init", status);
13887cc577a4SJonathan Peyton }
13897cc577a4SJonathan Peyton 
1390feac33ebSJonathan Peyton void __kmp_suspend_initialize_thread(kmp_info_t *th) {
13917cc577a4SJonathan Peyton   ANNOTATE_HAPPENS_AFTER(&th->th.th_suspend_init_count);
1392f8f788b2SAndrey Churbanov   int old_value = KMP_ATOMIC_LD_RLX(&th->th.th_suspend_init_count);
1393f8f788b2SAndrey Churbanov   int new_value = __kmp_fork_count + 1;
1394f8f788b2SAndrey Churbanov   // Return if already initialized
1395f8f788b2SAndrey Churbanov   if (old_value == new_value)
1396f8f788b2SAndrey Churbanov     return;
1397f8f788b2SAndrey Churbanov   // Wait, then return if being initialized
1398*309b00a4SShilei Tian   if (old_value == -1 || !__kmp_atomic_compare_store(
1399*309b00a4SShilei Tian                              &th->th.th_suspend_init_count, old_value, -1)) {
1400f8f788b2SAndrey Churbanov     while (KMP_ATOMIC_LD_ACQ(&th->th.th_suspend_init_count) != new_value) {
1401f8f788b2SAndrey Churbanov       KMP_CPU_PAUSE();
1402f8f788b2SAndrey Churbanov     }
1403f8f788b2SAndrey Churbanov   } else {
1404f8f788b2SAndrey Churbanov     // Claim to be the initializer and do initializations
14057cc577a4SJonathan Peyton     int status;
14063041982dSJonathan Peyton     status = pthread_cond_init(&th->th.th_suspend_cv.c_cond,
14073041982dSJonathan Peyton                                &__kmp_suspend_cond_attr);
14087cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_cond_init", status);
14093041982dSJonathan Peyton     status = pthread_mutex_init(&th->th.th_suspend_mx.m_mutex,
14103041982dSJonathan Peyton                                 &__kmp_suspend_mutex_attr);
14117cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
1412f8f788b2SAndrey Churbanov     KMP_ATOMIC_ST_REL(&th->th.th_suspend_init_count, new_value);
14137cc577a4SJonathan Peyton     ANNOTATE_HAPPENS_BEFORE(&th->th.th_suspend_init_count);
1414bd3a7633SJonathan Peyton   }
14157cc577a4SJonathan Peyton }
14167cc577a4SJonathan Peyton 
14173041982dSJonathan Peyton void __kmp_suspend_uninitialize_thread(kmp_info_t *th) {
1418f8f788b2SAndrey Churbanov   if (KMP_ATOMIC_LD_ACQ(&th->th.th_suspend_init_count) > __kmp_fork_count) {
14193041982dSJonathan Peyton     /* this means we have initialize the suspension pthread objects for this
14203041982dSJonathan Peyton        thread in this instance of the process */
14217cc577a4SJonathan Peyton     int status;
14227cc577a4SJonathan Peyton 
14237cc577a4SJonathan Peyton     status = pthread_cond_destroy(&th->th.th_suspend_cv.c_cond);
14247cc577a4SJonathan Peyton     if (status != 0 && status != EBUSY) {
14257cc577a4SJonathan Peyton       KMP_SYSFAIL("pthread_cond_destroy", status);
1426bd3a7633SJonathan Peyton     }
14277cc577a4SJonathan Peyton     status = pthread_mutex_destroy(&th->th.th_suspend_mx.m_mutex);
14287cc577a4SJonathan Peyton     if (status != 0 && status != EBUSY) {
14297cc577a4SJonathan Peyton       KMP_SYSFAIL("pthread_mutex_destroy", status);
1430bd3a7633SJonathan Peyton     }
14317cc577a4SJonathan Peyton     --th->th.th_suspend_init_count;
1432f8f788b2SAndrey Churbanov     KMP_DEBUG_ASSERT(KMP_ATOMIC_LD_RLX(&th->th.th_suspend_init_count) ==
1433f8f788b2SAndrey Churbanov                      __kmp_fork_count);
14347cc577a4SJonathan Peyton   }
14357cc577a4SJonathan Peyton }
14367cc577a4SJonathan Peyton 
14379b8bb323SJonathan Peyton // return true if lock obtained, false otherwise
14389b8bb323SJonathan Peyton int __kmp_try_suspend_mx(kmp_info_t *th) {
14399b8bb323SJonathan Peyton   return (pthread_mutex_trylock(&th->th.th_suspend_mx.m_mutex) == 0);
14409b8bb323SJonathan Peyton }
14419b8bb323SJonathan Peyton 
14429b8bb323SJonathan Peyton void __kmp_lock_suspend_mx(kmp_info_t *th) {
14439b8bb323SJonathan Peyton   int status = pthread_mutex_lock(&th->th.th_suspend_mx.m_mutex);
14449b8bb323SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
14459b8bb323SJonathan Peyton }
14469b8bb323SJonathan Peyton 
14479b8bb323SJonathan Peyton void __kmp_unlock_suspend_mx(kmp_info_t *th) {
14489b8bb323SJonathan Peyton   int status = pthread_mutex_unlock(&th->th.th_suspend_mx.m_mutex);
14499b8bb323SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
14509b8bb323SJonathan Peyton }
14519b8bb323SJonathan Peyton 
14527cc577a4SJonathan Peyton /* This routine puts the calling thread to sleep after setting the
14533041982dSJonathan Peyton    sleep bit for the indicated flag variable to true. */
14547cc577a4SJonathan Peyton template <class C>
14553041982dSJonathan Peyton static inline void __kmp_suspend_template(int th_gtid, C *flag) {
14567cc577a4SJonathan Peyton   KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_suspend);
14577cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[th_gtid];
14587cc577a4SJonathan Peyton   int status;
14597cc577a4SJonathan Peyton   typename C::flag_t old_spin;
14607cc577a4SJonathan Peyton 
14613041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_suspend_template: T#%d enter for flag = %p\n", th_gtid,
14623041982dSJonathan Peyton                 flag->get()));
14637cc577a4SJonathan Peyton 
14647cc577a4SJonathan Peyton   __kmp_suspend_initialize_thread(th);
14657cc577a4SJonathan Peyton 
1466e0665a90STerry Wilmarth   __kmp_lock_suspend_mx(th);
14677cc577a4SJonathan Peyton 
14687cc577a4SJonathan Peyton   KF_TRACE(10, ("__kmp_suspend_template: T#%d setting sleep bit for spin(%p)\n",
14697cc577a4SJonathan Peyton                 th_gtid, flag->get()));
14707cc577a4SJonathan Peyton 
14713041982dSJonathan Peyton   /* TODO: shouldn't this use release semantics to ensure that
14723041982dSJonathan Peyton      __kmp_suspend_initialize_thread gets called first? */
14737cc577a4SJonathan Peyton   old_spin = flag->set_sleeping();
14749b8bb323SJonathan Peyton   if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME &&
14759b8bb323SJonathan Peyton       __kmp_pause_status != kmp_soft_paused) {
14769b8bb323SJonathan Peyton     flag->unset_sleeping();
1477e0665a90STerry Wilmarth     __kmp_unlock_suspend_mx(th);
14789b8bb323SJonathan Peyton     return;
14799b8bb323SJonathan Peyton   }
14803041982dSJonathan Peyton   KF_TRACE(5, ("__kmp_suspend_template: T#%d set sleep bit for spin(%p)==%x,"
14813041982dSJonathan Peyton                " was %x\n",
148237e2ef54SJonathan Peyton                th_gtid, flag->get(), flag->load(), old_spin));
14837cc577a4SJonathan Peyton 
14847cc577a4SJonathan Peyton   if (flag->done_check_val(old_spin)) {
14857cc577a4SJonathan Peyton     old_spin = flag->unset_sleeping();
14863041982dSJonathan Peyton     KF_TRACE(5, ("__kmp_suspend_template: T#%d false alarm, reset sleep bit "
14873041982dSJonathan Peyton                  "for spin(%p)\n",
14887cc577a4SJonathan Peyton                  th_gtid, flag->get()));
14897cc577a4SJonathan Peyton   } else {
14907cc577a4SJonathan Peyton     /* Encapsulate in a loop as the documentation states that this may
14913041982dSJonathan Peyton        "with low probability" return when the condition variable has
14923041982dSJonathan Peyton        not been signaled or broadcast */
14937cc577a4SJonathan Peyton     int deactivated = FALSE;
14947cc577a4SJonathan Peyton     TCW_PTR(th->th.th_sleep_loc, (void *)flag);
14953041982dSJonathan Peyton 
14967cc577a4SJonathan Peyton     while (flag->is_sleeping()) {
14977cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND
14987cc577a4SJonathan Peyton       char buffer[128];
14997cc577a4SJonathan Peyton       __kmp_suspend_count++;
15007cc577a4SJonathan Peyton       __kmp_print_cond(buffer, &th->th.th_suspend_cv);
15013041982dSJonathan Peyton       __kmp_printf("__kmp_suspend_template: suspending T#%d: %s\n", th_gtid,
15023041982dSJonathan Peyton                    buffer);
15037cc577a4SJonathan Peyton #endif
15043041982dSJonathan Peyton       // Mark the thread as no longer active (only in the first iteration of the
15053041982dSJonathan Peyton       // loop).
15067cc577a4SJonathan Peyton       if (!deactivated) {
15077cc577a4SJonathan Peyton         th->th.th_active = FALSE;
15087cc577a4SJonathan Peyton         if (th->th.th_active_in_pool) {
15097cc577a4SJonathan Peyton           th->th.th_active_in_pool = FALSE;
151037e2ef54SJonathan Peyton           KMP_ATOMIC_DEC(&__kmp_thread_pool_active_nth);
15117cc577a4SJonathan Peyton           KMP_DEBUG_ASSERT(TCR_4(__kmp_thread_pool_active_nth) >= 0);
15127cc577a4SJonathan Peyton         }
15137cc577a4SJonathan Peyton         deactivated = TRUE;
15147cc577a4SJonathan Peyton       }
15157cc577a4SJonathan Peyton 
15167cc577a4SJonathan Peyton #if USE_SUSPEND_TIMEOUT
15177cc577a4SJonathan Peyton       struct timespec now;
15187cc577a4SJonathan Peyton       struct timeval tval;
15197cc577a4SJonathan Peyton       int msecs;
15207cc577a4SJonathan Peyton 
15217cc577a4SJonathan Peyton       status = gettimeofday(&tval, NULL);
15227cc577a4SJonathan Peyton       KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
15237cc577a4SJonathan Peyton       TIMEVAL_TO_TIMESPEC(&tval, &now);
15247cc577a4SJonathan Peyton 
15257cc577a4SJonathan Peyton       msecs = (4 * __kmp_dflt_blocktime) + 200;
15267cc577a4SJonathan Peyton       now.tv_sec += msecs / 1000;
15277cc577a4SJonathan Peyton       now.tv_nsec += (msecs % 1000) * 1000;
15287cc577a4SJonathan Peyton 
15293041982dSJonathan Peyton       KF_TRACE(15, ("__kmp_suspend_template: T#%d about to perform "
15303041982dSJonathan Peyton                     "pthread_cond_timedwait\n",
15317cc577a4SJonathan Peyton                     th_gtid));
15323041982dSJonathan Peyton       status = pthread_cond_timedwait(&th->th.th_suspend_cv.c_cond,
15333041982dSJonathan Peyton                                       &th->th.th_suspend_mx.m_mutex, &now);
15347cc577a4SJonathan Peyton #else
15353041982dSJonathan Peyton       KF_TRACE(15, ("__kmp_suspend_template: T#%d about to perform"
15363041982dSJonathan Peyton                     " pthread_cond_wait\n",
15377cc577a4SJonathan Peyton                     th_gtid));
15383041982dSJonathan Peyton       status = pthread_cond_wait(&th->th.th_suspend_cv.c_cond,
15393041982dSJonathan Peyton                                  &th->th.th_suspend_mx.m_mutex);
1540e0665a90STerry Wilmarth #endif // USE_SUSPEND_TIMEOUT
15417cc577a4SJonathan Peyton 
15427cc577a4SJonathan Peyton       if ((status != 0) && (status != EINTR) && (status != ETIMEDOUT)) {
15437cc577a4SJonathan Peyton         KMP_SYSFAIL("pthread_cond_wait", status);
15447cc577a4SJonathan Peyton       }
15457cc577a4SJonathan Peyton #ifdef KMP_DEBUG
15467cc577a4SJonathan Peyton       if (status == ETIMEDOUT) {
15477cc577a4SJonathan Peyton         if (flag->is_sleeping()) {
15483041982dSJonathan Peyton           KF_TRACE(100,
15493041982dSJonathan Peyton                    ("__kmp_suspend_template: T#%d timeout wakeup\n", th_gtid));
15507cc577a4SJonathan Peyton         } else {
15513041982dSJonathan Peyton           KF_TRACE(2, ("__kmp_suspend_template: T#%d timeout wakeup, sleep bit "
15523041982dSJonathan Peyton                        "not set!\n",
15537cc577a4SJonathan Peyton                        th_gtid));
15547cc577a4SJonathan Peyton         }
15557cc577a4SJonathan Peyton       } else if (flag->is_sleeping()) {
15563041982dSJonathan Peyton         KF_TRACE(100,
15573041982dSJonathan Peyton                  ("__kmp_suspend_template: T#%d spurious wakeup\n", th_gtid));
15587cc577a4SJonathan Peyton       }
15597cc577a4SJonathan Peyton #endif
15607cc577a4SJonathan Peyton     } // while
15617cc577a4SJonathan Peyton 
15627cc577a4SJonathan Peyton     // Mark the thread as active again (if it was previous marked as inactive)
15637cc577a4SJonathan Peyton     if (deactivated) {
15647cc577a4SJonathan Peyton       th->th.th_active = TRUE;
15657cc577a4SJonathan Peyton       if (TCR_4(th->th.th_in_pool)) {
156637e2ef54SJonathan Peyton         KMP_ATOMIC_INC(&__kmp_thread_pool_active_nth);
15677cc577a4SJonathan Peyton         th->th.th_active_in_pool = TRUE;
15687cc577a4SJonathan Peyton       }
15697cc577a4SJonathan Peyton     }
15707cc577a4SJonathan Peyton   }
15717cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND
15727cc577a4SJonathan Peyton   {
15737cc577a4SJonathan Peyton     char buffer[128];
15747cc577a4SJonathan Peyton     __kmp_print_cond(buffer, &th->th.th_suspend_cv);
15753041982dSJonathan Peyton     __kmp_printf("__kmp_suspend_template: T#%d has awakened: %s\n", th_gtid,
15763041982dSJonathan Peyton                  buffer);
15777cc577a4SJonathan Peyton   }
15787cc577a4SJonathan Peyton #endif
15797cc577a4SJonathan Peyton 
1580e0665a90STerry Wilmarth   __kmp_unlock_suspend_mx(th);
15817cc577a4SJonathan Peyton   KF_TRACE(30, ("__kmp_suspend_template: T#%d exit\n", th_gtid));
15827cc577a4SJonathan Peyton }
15837cc577a4SJonathan Peyton 
1584e0665a90STerry Wilmarth template <bool C, bool S>
1585e0665a90STerry Wilmarth void __kmp_suspend_32(int th_gtid, kmp_flag_32<C, S> *flag) {
15867cc577a4SJonathan Peyton   __kmp_suspend_template(th_gtid, flag);
15877cc577a4SJonathan Peyton }
1588e0665a90STerry Wilmarth template <bool C, bool S>
1589e0665a90STerry Wilmarth void __kmp_suspend_64(int th_gtid, kmp_flag_64<C, S> *flag) {
15907cc577a4SJonathan Peyton   __kmp_suspend_template(th_gtid, flag);
15917cc577a4SJonathan Peyton }
15927cc577a4SJonathan Peyton void __kmp_suspend_oncore(int th_gtid, kmp_flag_oncore *flag) {
15937cc577a4SJonathan Peyton   __kmp_suspend_template(th_gtid, flag);
15947cc577a4SJonathan Peyton }
15957cc577a4SJonathan Peyton 
1596e0665a90STerry Wilmarth template void __kmp_suspend_32<false, false>(int, kmp_flag_32<false, false> *);
1597e0665a90STerry Wilmarth template void __kmp_suspend_64<false, true>(int, kmp_flag_64<false, true> *);
1598e0665a90STerry Wilmarth template void __kmp_suspend_64<true, false>(int, kmp_flag_64<true, false> *);
1599e0665a90STerry Wilmarth 
16007cc577a4SJonathan Peyton /* This routine signals the thread specified by target_gtid to wake up
16013041982dSJonathan Peyton    after setting the sleep bit indicated by the flag argument to FALSE.
16023041982dSJonathan Peyton    The target thread must already have called __kmp_suspend_template() */
16037cc577a4SJonathan Peyton template <class C>
16043041982dSJonathan Peyton static inline void __kmp_resume_template(int target_gtid, C *flag) {
16057cc577a4SJonathan Peyton   KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_resume);
16067cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[target_gtid];
16077cc577a4SJonathan Peyton   int status;
16087cc577a4SJonathan Peyton 
16097cc577a4SJonathan Peyton #ifdef KMP_DEBUG
16107cc577a4SJonathan Peyton   int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
16117cc577a4SJonathan Peyton #endif
16127cc577a4SJonathan Peyton 
16133041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_resume_template: T#%d wants to wakeup T#%d enter\n",
16143041982dSJonathan Peyton                 gtid, target_gtid));
16157cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(gtid != target_gtid);
16167cc577a4SJonathan Peyton 
16177cc577a4SJonathan Peyton   __kmp_suspend_initialize_thread(th);
16185644f734SAndreyChurbanov 
1619e0665a90STerry Wilmarth   __kmp_lock_suspend_mx(th);
16207cc577a4SJonathan Peyton 
16217cc577a4SJonathan Peyton   if (!flag) { // coming from __kmp_null_resume_wrapper
1622c47afcd9SAndrey Churbanov     flag = (C *)CCAST(void *, th->th.th_sleep_loc);
16237cc577a4SJonathan Peyton   }
16247cc577a4SJonathan Peyton 
16253041982dSJonathan Peyton   // First, check if the flag is null or its type has changed. If so, someone
16263041982dSJonathan Peyton   // else woke it up.
16273041982dSJonathan Peyton   if (!flag || flag->get_type() != flag->get_ptr_type()) { // get_ptr_type
1628e0665a90STerry Wilmarth     // simply shows what flag was cast to
16293041982dSJonathan Peyton     KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already "
16303041982dSJonathan Peyton                  "awake: flag(%p)\n",
16317cc577a4SJonathan Peyton                  gtid, target_gtid, NULL));
1632e0665a90STerry Wilmarth     __kmp_unlock_suspend_mx(th);
16337cc577a4SJonathan Peyton     return;
16343041982dSJonathan Peyton   } else { // if multiple threads are sleeping, flag should be internally
16353041982dSJonathan Peyton     // referring to a specific thread here
16367cc577a4SJonathan Peyton     typename C::flag_t old_spin = flag->unset_sleeping();
16377cc577a4SJonathan Peyton     if (!flag->is_sleeping_val(old_spin)) {
16383041982dSJonathan Peyton       KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already "
16393041982dSJonathan Peyton                    "awake: flag(%p): "
16407cc577a4SJonathan Peyton                    "%u => %u\n",
164137e2ef54SJonathan Peyton                    gtid, target_gtid, flag->get(), old_spin, flag->load()));
1642e0665a90STerry Wilmarth       __kmp_unlock_suspend_mx(th);
16437cc577a4SJonathan Peyton       return;
16447cc577a4SJonathan Peyton     }
16453041982dSJonathan Peyton     KF_TRACE(5, ("__kmp_resume_template: T#%d about to wakeup T#%d, reset "
16463041982dSJonathan Peyton                  "sleep bit for flag's loc(%p): "
16477cc577a4SJonathan Peyton                  "%u => %u\n",
164837e2ef54SJonathan Peyton                  gtid, target_gtid, flag->get(), old_spin, flag->load()));
16497cc577a4SJonathan Peyton   }
16507cc577a4SJonathan Peyton   TCW_PTR(th->th.th_sleep_loc, NULL);
16517cc577a4SJonathan Peyton 
16527cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND
16537cc577a4SJonathan Peyton   {
16547cc577a4SJonathan Peyton     char buffer[128];
16557cc577a4SJonathan Peyton     __kmp_print_cond(buffer, &th->th.th_suspend_cv);
16563041982dSJonathan Peyton     __kmp_printf("__kmp_resume_template: T#%d resuming T#%d: %s\n", gtid,
16573041982dSJonathan Peyton                  target_gtid, buffer);
16587cc577a4SJonathan Peyton   }
16597cc577a4SJonathan Peyton #endif
16607cc577a4SJonathan Peyton   status = pthread_cond_signal(&th->th.th_suspend_cv.c_cond);
16617cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_cond_signal", status);
1662e0665a90STerry Wilmarth   __kmp_unlock_suspend_mx(th);
16633041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_resume_template: T#%d exiting after signaling wake up"
16643041982dSJonathan Peyton                 " for T#%d\n",
16657cc577a4SJonathan Peyton                 gtid, target_gtid));
16667cc577a4SJonathan Peyton }
16677cc577a4SJonathan Peyton 
1668e0665a90STerry Wilmarth template <bool C, bool S>
1669e0665a90STerry Wilmarth void __kmp_resume_32(int target_gtid, kmp_flag_32<C, S> *flag) {
16707cc577a4SJonathan Peyton   __kmp_resume_template(target_gtid, flag);
16717cc577a4SJonathan Peyton }
1672e0665a90STerry Wilmarth template <bool C, bool S>
1673e0665a90STerry Wilmarth void __kmp_resume_64(int target_gtid, kmp_flag_64<C, S> *flag) {
16747cc577a4SJonathan Peyton   __kmp_resume_template(target_gtid, flag);
16757cc577a4SJonathan Peyton }
16767cc577a4SJonathan Peyton void __kmp_resume_oncore(int target_gtid, kmp_flag_oncore *flag) {
16777cc577a4SJonathan Peyton   __kmp_resume_template(target_gtid, flag);
16787cc577a4SJonathan Peyton }
16797cc577a4SJonathan Peyton 
1680e0665a90STerry Wilmarth template void __kmp_resume_32<false, true>(int, kmp_flag_32<false, true> *);
1681e0665a90STerry Wilmarth template void __kmp_resume_64<false, true>(int, kmp_flag_64<false, true> *);
1682e0665a90STerry Wilmarth 
16837cc577a4SJonathan Peyton #if KMP_USE_MONITOR
16843041982dSJonathan Peyton void __kmp_resume_monitor() {
16857cc577a4SJonathan Peyton   KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_resume);
16867cc577a4SJonathan Peyton   int status;
16877cc577a4SJonathan Peyton #ifdef KMP_DEBUG
16887cc577a4SJonathan Peyton   int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
16893041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_resume_monitor: T#%d wants to wakeup T#%d enter\n", gtid,
16903041982dSJonathan Peyton                 KMP_GTID_MONITOR));
16917cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(gtid != KMP_GTID_MONITOR);
16927cc577a4SJonathan Peyton #endif
16937cc577a4SJonathan Peyton   status = pthread_mutex_lock(&__kmp_wait_mx.m_mutex);
16947cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
16957cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND
16967cc577a4SJonathan Peyton   {
16977cc577a4SJonathan Peyton     char buffer[128];
16987cc577a4SJonathan Peyton     __kmp_print_cond(buffer, &__kmp_wait_cv.c_cond);
16993041982dSJonathan Peyton     __kmp_printf("__kmp_resume_monitor: T#%d resuming T#%d: %s\n", gtid,
17003041982dSJonathan Peyton                  KMP_GTID_MONITOR, buffer);
17017cc577a4SJonathan Peyton   }
17027cc577a4SJonathan Peyton #endif
17037cc577a4SJonathan Peyton   status = pthread_cond_signal(&__kmp_wait_cv.c_cond);
17047cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_cond_signal", status);
17057cc577a4SJonathan Peyton   status = pthread_mutex_unlock(&__kmp_wait_mx.m_mutex);
17067cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
17073041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_resume_monitor: T#%d exiting after signaling wake up"
17083041982dSJonathan Peyton                 " for T#%d\n",
17097cc577a4SJonathan Peyton                 gtid, KMP_GTID_MONITOR));
17107cc577a4SJonathan Peyton }
17117cc577a4SJonathan Peyton #endif // KMP_USE_MONITOR
17127cc577a4SJonathan Peyton 
1713e47d32f1SJonathan Peyton void __kmp_yield() { sched_yield(); }
17147cc577a4SJonathan Peyton 
17153041982dSJonathan Peyton void __kmp_gtid_set_specific(int gtid) {
17167cc577a4SJonathan Peyton   if (__kmp_init_gtid) {
17177cc577a4SJonathan Peyton     int status;
17183041982dSJonathan Peyton     status = pthread_setspecific(__kmp_gtid_threadprivate_key,
17193041982dSJonathan Peyton                                  (void *)(intptr_t)(gtid + 1));
17207cc577a4SJonathan Peyton     KMP_CHECK_SYSFAIL("pthread_setspecific", status);
17217cc577a4SJonathan Peyton   } else {
17227cc577a4SJonathan Peyton     KA_TRACE(50, ("__kmp_gtid_set_specific: runtime shutdown, returning\n"));
17237cc577a4SJonathan Peyton   }
17247cc577a4SJonathan Peyton }
17257cc577a4SJonathan Peyton 
17263041982dSJonathan Peyton int __kmp_gtid_get_specific() {
17277cc577a4SJonathan Peyton   int gtid;
17287cc577a4SJonathan Peyton   if (!__kmp_init_gtid) {
17293041982dSJonathan Peyton     KA_TRACE(50, ("__kmp_gtid_get_specific: runtime shutdown, returning "
17303041982dSJonathan Peyton                   "KMP_GTID_SHUTDOWN\n"));
17317cc577a4SJonathan Peyton     return KMP_GTID_SHUTDOWN;
17327cc577a4SJonathan Peyton   }
17337cc577a4SJonathan Peyton   gtid = (int)(size_t)pthread_getspecific(__kmp_gtid_threadprivate_key);
17347cc577a4SJonathan Peyton   if (gtid == 0) {
17357cc577a4SJonathan Peyton     gtid = KMP_GTID_DNE;
17363041982dSJonathan Peyton   } else {
17377cc577a4SJonathan Peyton     gtid--;
17387cc577a4SJonathan Peyton   }
17397cc577a4SJonathan Peyton   KA_TRACE(50, ("__kmp_gtid_get_specific: key:%d gtid:%d\n",
17407cc577a4SJonathan Peyton                 __kmp_gtid_threadprivate_key, gtid));
17417cc577a4SJonathan Peyton   return gtid;
17427cc577a4SJonathan Peyton }
17437cc577a4SJonathan Peyton 
17443041982dSJonathan Peyton double __kmp_read_cpu_time(void) {
17457cc577a4SJonathan Peyton   /*clock_t   t;*/
17467cc577a4SJonathan Peyton   struct tms buffer;
17477cc577a4SJonathan Peyton 
17487cc577a4SJonathan Peyton   /*t =*/times(&buffer);
17497cc577a4SJonathan Peyton 
17506b316febSTerry Wilmarth   return (double)(buffer.tms_utime + buffer.tms_cutime) /
17516b316febSTerry Wilmarth          (double)CLOCKS_PER_SEC;
17527cc577a4SJonathan Peyton }
17537cc577a4SJonathan Peyton 
17543041982dSJonathan Peyton int __kmp_read_system_info(struct kmp_sys_info *info) {
17557cc577a4SJonathan Peyton   int status;
17567cc577a4SJonathan Peyton   struct rusage r_usage;
17577cc577a4SJonathan Peyton 
17587cc577a4SJonathan Peyton   memset(info, 0, sizeof(*info));
17597cc577a4SJonathan Peyton 
17607cc577a4SJonathan Peyton   status = getrusage(RUSAGE_SELF, &r_usage);
17617cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("getrusage", status);
17627cc577a4SJonathan Peyton 
17633041982dSJonathan Peyton   // The maximum resident set size utilized (in kilobytes)
17643041982dSJonathan Peyton   info->maxrss = r_usage.ru_maxrss;
17653041982dSJonathan Peyton   // The number of page faults serviced without any I/O
17663041982dSJonathan Peyton   info->minflt = r_usage.ru_minflt;
17673041982dSJonathan Peyton   // The number of page faults serviced that required I/O
17683041982dSJonathan Peyton   info->majflt = r_usage.ru_majflt;
17693041982dSJonathan Peyton   // The number of times a process was "swapped" out of memory
17703041982dSJonathan Peyton   info->nswap = r_usage.ru_nswap;
17713041982dSJonathan Peyton   // The number of times the file system had to perform input
17723041982dSJonathan Peyton   info->inblock = r_usage.ru_inblock;
17733041982dSJonathan Peyton   // The number of times the file system had to perform output
17743041982dSJonathan Peyton   info->oublock = r_usage.ru_oublock;
17753041982dSJonathan Peyton   // The number of times a context switch was voluntarily
17763041982dSJonathan Peyton   info->nvcsw = r_usage.ru_nvcsw;
17773041982dSJonathan Peyton   // The number of times a context switch was forced
17783041982dSJonathan Peyton   info->nivcsw = r_usage.ru_nivcsw;
17797cc577a4SJonathan Peyton 
17807cc577a4SJonathan Peyton   return (status != 0);
17817cc577a4SJonathan Peyton }
17827cc577a4SJonathan Peyton 
17833041982dSJonathan Peyton void __kmp_read_system_time(double *delta) {
17847cc577a4SJonathan Peyton   double t_ns;
17857cc577a4SJonathan Peyton   struct timeval tval;
17867cc577a4SJonathan Peyton   struct timespec stop;
17877cc577a4SJonathan Peyton   int status;
17887cc577a4SJonathan Peyton 
17897cc577a4SJonathan Peyton   status = gettimeofday(&tval, NULL);
17907cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
17917cc577a4SJonathan Peyton   TIMEVAL_TO_TIMESPEC(&tval, &stop);
17926b316febSTerry Wilmarth   t_ns = (double)(TS2NS(stop) - TS2NS(__kmp_sys_timer_data.start));
17937cc577a4SJonathan Peyton   *delta = (t_ns * 1e-9);
17947cc577a4SJonathan Peyton }
17957cc577a4SJonathan Peyton 
17963041982dSJonathan Peyton void __kmp_clear_system_time(void) {
17977cc577a4SJonathan Peyton   struct timeval tval;
17987cc577a4SJonathan Peyton   int status;
17997cc577a4SJonathan Peyton   status = gettimeofday(&tval, NULL);
18007cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
18017cc577a4SJonathan Peyton   TIMEVAL_TO_TIMESPEC(&tval, &__kmp_sys_timer_data.start);
18027cc577a4SJonathan Peyton }
18037cc577a4SJonathan Peyton 
18043041982dSJonathan Peyton static int __kmp_get_xproc(void) {
18057cc577a4SJonathan Peyton 
18067cc577a4SJonathan Peyton   int r = 0;
18077cc577a4SJonathan Peyton 
1808a56ac949SKamil Rytarowski #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
18097e1ea993SKamil Rytarowski     KMP_OS_OPENBSD || KMP_OS_HURD
18107cc577a4SJonathan Peyton 
18116b316febSTerry Wilmarth   __kmp_type_convert(sysconf(_SC_NPROCESSORS_ONLN), &(r));
18127cc577a4SJonathan Peyton 
18137cc577a4SJonathan Peyton #elif KMP_OS_DARWIN
18147cc577a4SJonathan Peyton 
18157cc577a4SJonathan Peyton   // Bug C77011 High "OpenMP Threads and number of active cores".
18167cc577a4SJonathan Peyton 
18177cc577a4SJonathan Peyton   // Find the number of available CPUs.
18187cc577a4SJonathan Peyton   kern_return_t rc;
18197cc577a4SJonathan Peyton   host_basic_info_data_t info;
18207cc577a4SJonathan Peyton   mach_msg_type_number_t num = HOST_BASIC_INFO_COUNT;
18217cc577a4SJonathan Peyton   rc = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&info, &num);
18227cc577a4SJonathan Peyton   if (rc == 0 && num == HOST_BASIC_INFO_COUNT) {
1823c47afcd9SAndrey Churbanov     // Cannot use KA_TRACE() here because this code works before trace support
1824c47afcd9SAndrey Churbanov     // is initialized.
18257cc577a4SJonathan Peyton     r = info.avail_cpus;
18267cc577a4SJonathan Peyton   } else {
18277cc577a4SJonathan Peyton     KMP_WARNING(CantGetNumAvailCPU);
18287cc577a4SJonathan Peyton     KMP_INFORM(AssumedNumCPU);
1829bd3a7633SJonathan Peyton   }
18307cc577a4SJonathan Peyton 
18317cc577a4SJonathan Peyton #else
18327cc577a4SJonathan Peyton 
18337cc577a4SJonathan Peyton #error "Unknown or unsupported OS."
18347cc577a4SJonathan Peyton 
18357cc577a4SJonathan Peyton #endif
18367cc577a4SJonathan Peyton 
18377cc577a4SJonathan Peyton   return r > 0 ? r : 2; /* guess value of 2 if OS told us 0 */
18387cc577a4SJonathan Peyton 
18397cc577a4SJonathan Peyton } // __kmp_get_xproc
18407cc577a4SJonathan Peyton 
18413041982dSJonathan Peyton int __kmp_read_from_file(char const *path, char const *format, ...) {
18427cc577a4SJonathan Peyton   int result;
18437cc577a4SJonathan Peyton   va_list args;
18447cc577a4SJonathan Peyton 
18457cc577a4SJonathan Peyton   va_start(args, format);
18467cc577a4SJonathan Peyton   FILE *f = fopen(path, "rb");
18477cc577a4SJonathan Peyton   if (f == NULL)
18487cc577a4SJonathan Peyton     return 0;
18497cc577a4SJonathan Peyton   result = vfscanf(f, format, args);
18507cc577a4SJonathan Peyton   fclose(f);
18517cc577a4SJonathan Peyton 
18527cc577a4SJonathan Peyton   return result;
18537cc577a4SJonathan Peyton }
18547cc577a4SJonathan Peyton 
18553041982dSJonathan Peyton void __kmp_runtime_initialize(void) {
18567cc577a4SJonathan Peyton   int status;
18577cc577a4SJonathan Peyton   pthread_mutexattr_t mutex_attr;
18587cc577a4SJonathan Peyton   pthread_condattr_t cond_attr;
18597cc577a4SJonathan Peyton 
18607cc577a4SJonathan Peyton   if (__kmp_init_runtime) {
18617cc577a4SJonathan Peyton     return;
1862bd3a7633SJonathan Peyton   }
18637cc577a4SJonathan Peyton 
18647cc577a4SJonathan Peyton #if (KMP_ARCH_X86 || KMP_ARCH_X86_64)
18657cc577a4SJonathan Peyton   if (!__kmp_cpuinfo.initialized) {
18667cc577a4SJonathan Peyton     __kmp_query_cpuid(&__kmp_cpuinfo);
1867bd3a7633SJonathan Peyton   }
18687cc577a4SJonathan Peyton #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
18697cc577a4SJonathan Peyton 
18707cc577a4SJonathan Peyton   __kmp_xproc = __kmp_get_xproc();
18717cc577a4SJonathan Peyton 
1872d47f5488SAndrey Churbanov #if !KMP_32_BIT_ARCH
1873d47f5488SAndrey Churbanov   struct rlimit rlim;
1874d47f5488SAndrey Churbanov   // read stack size of calling thread, save it as default for worker threads;
1875d47f5488SAndrey Churbanov   // this should be done before reading environment variables
1876d47f5488SAndrey Churbanov   status = getrlimit(RLIMIT_STACK, &rlim);
1877d47f5488SAndrey Churbanov   if (status == 0) { // success?
1878d47f5488SAndrey Churbanov     __kmp_stksize = rlim.rlim_cur;
1879d47f5488SAndrey Churbanov     __kmp_check_stksize(&__kmp_stksize); // check value and adjust if needed
1880d47f5488SAndrey Churbanov   }
1881d47f5488SAndrey Churbanov #endif /* KMP_32_BIT_ARCH */
1882d47f5488SAndrey Churbanov 
18837cc577a4SJonathan Peyton   if (sysconf(_SC_THREADS)) {
18847cc577a4SJonathan Peyton 
18857cc577a4SJonathan Peyton     /* Query the maximum number of threads */
18866b316febSTerry Wilmarth     __kmp_type_convert(sysconf(_SC_THREAD_THREADS_MAX), &(__kmp_sys_max_nth));
18877cc577a4SJonathan Peyton     if (__kmp_sys_max_nth == -1) {
18887cc577a4SJonathan Peyton       /* Unlimited threads for NPTL */
18897cc577a4SJonathan Peyton       __kmp_sys_max_nth = INT_MAX;
18903041982dSJonathan Peyton     } else if (__kmp_sys_max_nth <= 1) {
18917cc577a4SJonathan Peyton       /* Can't tell, just use PTHREAD_THREADS_MAX */
18927cc577a4SJonathan Peyton       __kmp_sys_max_nth = KMP_MAX_NTH;
18937cc577a4SJonathan Peyton     }
18947cc577a4SJonathan Peyton 
18957cc577a4SJonathan Peyton     /* Query the minimum stack size */
18967cc577a4SJonathan Peyton     __kmp_sys_min_stksize = sysconf(_SC_THREAD_STACK_MIN);
18977cc577a4SJonathan Peyton     if (__kmp_sys_min_stksize <= 1) {
18987cc577a4SJonathan Peyton       __kmp_sys_min_stksize = KMP_MIN_STKSIZE;
18997cc577a4SJonathan Peyton     }
19007cc577a4SJonathan Peyton   }
19017cc577a4SJonathan Peyton 
19027cc577a4SJonathan Peyton   /* Set up minimum number of threads to switch to TLS gtid */
19037cc577a4SJonathan Peyton   __kmp_tls_gtid_min = KMP_TLS_GTID_MIN;
19047cc577a4SJonathan Peyton 
19053041982dSJonathan Peyton   status = pthread_key_create(&__kmp_gtid_threadprivate_key,
19063041982dSJonathan Peyton                               __kmp_internal_end_dest);
19077cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_key_create", status);
19087cc577a4SJonathan Peyton   status = pthread_mutexattr_init(&mutex_attr);
19097cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutexattr_init", status);
19107cc577a4SJonathan Peyton   status = pthread_mutex_init(&__kmp_wait_mx.m_mutex, &mutex_attr);
19117cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
19127cc577a4SJonathan Peyton   status = pthread_condattr_init(&cond_attr);
19137cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_condattr_init", status);
19147cc577a4SJonathan Peyton   status = pthread_cond_init(&__kmp_wait_cv.c_cond, &cond_attr);
19157cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
19167cc577a4SJonathan Peyton #if USE_ITT_BUILD
19177cc577a4SJonathan Peyton   __kmp_itt_initialize();
19187cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
19197cc577a4SJonathan Peyton 
19207cc577a4SJonathan Peyton   __kmp_init_runtime = TRUE;
19217cc577a4SJonathan Peyton }
19227cc577a4SJonathan Peyton 
19233041982dSJonathan Peyton void __kmp_runtime_destroy(void) {
19247cc577a4SJonathan Peyton   int status;
19257cc577a4SJonathan Peyton 
19267cc577a4SJonathan Peyton   if (!__kmp_init_runtime) {
19277cc577a4SJonathan Peyton     return; // Nothing to do.
1928bd3a7633SJonathan Peyton   }
19297cc577a4SJonathan Peyton 
19307cc577a4SJonathan Peyton #if USE_ITT_BUILD
19317cc577a4SJonathan Peyton   __kmp_itt_destroy();
19327cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
19337cc577a4SJonathan Peyton 
19347cc577a4SJonathan Peyton   status = pthread_key_delete(__kmp_gtid_threadprivate_key);
19357cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL("pthread_key_delete", status);
19367cc577a4SJonathan Peyton 
19377cc577a4SJonathan Peyton   status = pthread_mutex_destroy(&__kmp_wait_mx.m_mutex);
19387cc577a4SJonathan Peyton   if (status != 0 && status != EBUSY) {
19397cc577a4SJonathan Peyton     KMP_SYSFAIL("pthread_mutex_destroy", status);
19407cc577a4SJonathan Peyton   }
19417cc577a4SJonathan Peyton   status = pthread_cond_destroy(&__kmp_wait_cv.c_cond);
19427cc577a4SJonathan Peyton   if (status != 0 && status != EBUSY) {
19437cc577a4SJonathan Peyton     KMP_SYSFAIL("pthread_cond_destroy", status);
19447cc577a4SJonathan Peyton   }
19457cc577a4SJonathan Peyton #if KMP_AFFINITY_SUPPORTED
19467cc577a4SJonathan Peyton   __kmp_affinity_uninitialize();
19477cc577a4SJonathan Peyton #endif
19487cc577a4SJonathan Peyton 
19497cc577a4SJonathan Peyton   __kmp_init_runtime = FALSE;
19507cc577a4SJonathan Peyton }
19517cc577a4SJonathan Peyton 
19527cc577a4SJonathan Peyton /* Put the thread to sleep for a time period */
19537cc577a4SJonathan Peyton /* NOTE: not currently used anywhere */
19543041982dSJonathan Peyton void __kmp_thread_sleep(int millis) { sleep((millis + 500) / 1000); }
19557cc577a4SJonathan Peyton 
19567cc577a4SJonathan Peyton /* Calculate the elapsed wall clock time for the user */
19573041982dSJonathan Peyton void __kmp_elapsed(double *t) {
19587cc577a4SJonathan Peyton   int status;
19597cc577a4SJonathan Peyton #ifdef FIX_SGI_CLOCK
19607cc577a4SJonathan Peyton   struct timespec ts;
19617cc577a4SJonathan Peyton 
19627cc577a4SJonathan Peyton   status = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
19637cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("clock_gettime", status);
19643041982dSJonathan Peyton   *t =
19653041982dSJonathan Peyton       (double)ts.tv_nsec * (1.0 / (double)KMP_NSEC_PER_SEC) + (double)ts.tv_sec;
19667cc577a4SJonathan Peyton #else
19677cc577a4SJonathan Peyton   struct timeval tv;
19687cc577a4SJonathan Peyton 
19697cc577a4SJonathan Peyton   status = gettimeofday(&tv, NULL);
19707cc577a4SJonathan Peyton   KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
19713041982dSJonathan Peyton   *t =
19723041982dSJonathan Peyton       (double)tv.tv_usec * (1.0 / (double)KMP_USEC_PER_SEC) + (double)tv.tv_sec;
19737cc577a4SJonathan Peyton #endif
19747cc577a4SJonathan Peyton }
19757cc577a4SJonathan Peyton 
19767cc577a4SJonathan Peyton /* Calculate the elapsed wall clock tick for the user */
19773041982dSJonathan Peyton void __kmp_elapsed_tick(double *t) { *t = 1 / (double)CLOCKS_PER_SEC; }
19787cc577a4SJonathan Peyton 
19797cc577a4SJonathan Peyton /* Return the current time stamp in nsec */
19803041982dSJonathan Peyton kmp_uint64 __kmp_now_nsec() {
19817cc577a4SJonathan Peyton   struct timeval t;
19827cc577a4SJonathan Peyton   gettimeofday(&t, NULL);
1983bdb0a2ffSJonathan Peyton   kmp_uint64 nsec = (kmp_uint64)KMP_NSEC_PER_SEC * (kmp_uint64)t.tv_sec +
1984bdb0a2ffSJonathan Peyton                     (kmp_uint64)1000 * (kmp_uint64)t.tv_usec;
1985bdb0a2ffSJonathan Peyton   return nsec;
19867cc577a4SJonathan Peyton }
19877cc577a4SJonathan Peyton 
19887cc577a4SJonathan Peyton #if KMP_ARCH_X86 || KMP_ARCH_X86_64
198935d75aedSJonathan Peyton /* Measure clock ticks per millisecond */
19903041982dSJonathan Peyton void __kmp_initialize_system_tick() {
1991bdb0a2ffSJonathan Peyton   kmp_uint64 now, nsec2, diff;
19927cc577a4SJonathan Peyton   kmp_uint64 delay = 100000; // 50~100 usec on most machines.
19937cc577a4SJonathan Peyton   kmp_uint64 nsec = __kmp_now_nsec();
19947cc577a4SJonathan Peyton   kmp_uint64 goal = __kmp_hardware_timestamp() + delay;
19953041982dSJonathan Peyton   while ((now = __kmp_hardware_timestamp()) < goal)
19963041982dSJonathan Peyton     ;
1997bdb0a2ffSJonathan Peyton   nsec2 = __kmp_now_nsec();
1998bdb0a2ffSJonathan Peyton   diff = nsec2 - nsec;
1999bdb0a2ffSJonathan Peyton   if (diff > 0) {
20006b316febSTerry Wilmarth     kmp_uint64 tpms = ((kmp_uint64)1e6 * (delay + (now - goal)) / diff);
2001bdb0a2ffSJonathan Peyton     if (tpms > 0)
2002bdb0a2ffSJonathan Peyton       __kmp_ticks_per_msec = tpms;
2003bdb0a2ffSJonathan Peyton   }
20047cc577a4SJonathan Peyton }
20057cc577a4SJonathan Peyton #endif
20067cc577a4SJonathan Peyton 
20073041982dSJonathan Peyton /* Determine whether the given address is mapped into the current address
20083041982dSJonathan Peyton    space. */
20097cc577a4SJonathan Peyton 
20103041982dSJonathan Peyton int __kmp_is_address_mapped(void *addr) {
20117cc577a4SJonathan Peyton 
20127cc577a4SJonathan Peyton   int found = 0;
20137cc577a4SJonathan Peyton   int rc;
20147cc577a4SJonathan Peyton 
2015fef62e1aSDavid Carlier #if KMP_OS_LINUX || KMP_OS_HURD
20167cc577a4SJonathan Peyton 
2017*309b00a4SShilei Tian   /* On GNUish OSes, read the /proc/<pid>/maps pseudo-file to get all the
2018*309b00a4SShilei Tian      address ranges mapped into the address space. */
20197cc577a4SJonathan Peyton 
20207cc577a4SJonathan Peyton   char *name = __kmp_str_format("/proc/%d/maps", getpid());
20217cc577a4SJonathan Peyton   FILE *file = NULL;
20227cc577a4SJonathan Peyton 
20237cc577a4SJonathan Peyton   file = fopen(name, "r");
20247cc577a4SJonathan Peyton   KMP_ASSERT(file != NULL);
20257cc577a4SJonathan Peyton 
20267cc577a4SJonathan Peyton   for (;;) {
20277cc577a4SJonathan Peyton 
20287cc577a4SJonathan Peyton     void *beginning = NULL;
20297cc577a4SJonathan Peyton     void *ending = NULL;
20307cc577a4SJonathan Peyton     char perms[5];
20317cc577a4SJonathan Peyton 
20327cc577a4SJonathan Peyton     rc = fscanf(file, "%p-%p %4s %*[^\n]\n", &beginning, &ending, perms);
20337cc577a4SJonathan Peyton     if (rc == EOF) {
20347cc577a4SJonathan Peyton       break;
2035bd3a7633SJonathan Peyton     }
20363041982dSJonathan Peyton     KMP_ASSERT(rc == 3 &&
20373041982dSJonathan Peyton                KMP_STRLEN(perms) == 4); // Make sure all fields are read.
20387cc577a4SJonathan Peyton 
20397cc577a4SJonathan Peyton     // Ending address is not included in the region, but beginning is.
20407cc577a4SJonathan Peyton     if ((addr >= beginning) && (addr < ending)) {
20417cc577a4SJonathan Peyton       perms[2] = 0; // 3th and 4th character does not matter.
20427cc577a4SJonathan Peyton       if (strcmp(perms, "rw") == 0) {
20437cc577a4SJonathan Peyton         // Memory we are looking for should be readable and writable.
20447cc577a4SJonathan Peyton         found = 1;
2045bd3a7633SJonathan Peyton       }
20467cc577a4SJonathan Peyton       break;
2047bd3a7633SJonathan Peyton     }
2048bd3a7633SJonathan Peyton   }
20497cc577a4SJonathan Peyton 
20507cc577a4SJonathan Peyton   // Free resources.
20517cc577a4SJonathan Peyton   fclose(file);
20527cc577a4SJonathan Peyton   KMP_INTERNAL_FREE(name);
2053fef62e1aSDavid Carlier #elif KMP_OS_FREEBSD
2054fef62e1aSDavid Carlier   char *buf;
2055fef62e1aSDavid Carlier   size_t lstsz;
2056fef62e1aSDavid Carlier   int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()};
2057fef62e1aSDavid Carlier   rc = sysctl(mib, 4, NULL, &lstsz, NULL, 0);
2058fef62e1aSDavid Carlier   if (rc < 0)
2059fef62e1aSDavid Carlier     return 0;
2060fef62e1aSDavid Carlier   // We pass from number of vm entry's semantic
2061fef62e1aSDavid Carlier   // to size of whole entry map list.
2062fef62e1aSDavid Carlier   lstsz = lstsz * 4 / 3;
2063fef62e1aSDavid Carlier   buf = reinterpret_cast<char *>(kmpc_malloc(lstsz));
2064fef62e1aSDavid Carlier   rc = sysctl(mib, 4, buf, &lstsz, NULL, 0);
2065fef62e1aSDavid Carlier   if (rc < 0) {
2066fef62e1aSDavid Carlier     kmpc_free(buf);
2067fef62e1aSDavid Carlier     return 0;
2068fef62e1aSDavid Carlier   }
2069fef62e1aSDavid Carlier 
2070fef62e1aSDavid Carlier   char *lw = buf;
2071fef62e1aSDavid Carlier   char *up = buf + lstsz;
2072fef62e1aSDavid Carlier 
2073fef62e1aSDavid Carlier   while (lw < up) {
2074fef62e1aSDavid Carlier     struct kinfo_vmentry *cur = reinterpret_cast<struct kinfo_vmentry *>(lw);
2075fef62e1aSDavid Carlier     size_t cursz = cur->kve_structsize;
2076fef62e1aSDavid Carlier     if (cursz == 0)
2077fef62e1aSDavid Carlier       break;
2078fef62e1aSDavid Carlier     void *start = reinterpret_cast<void *>(cur->kve_start);
2079fef62e1aSDavid Carlier     void *end = reinterpret_cast<void *>(cur->kve_end);
2080fef62e1aSDavid Carlier     // Readable/Writable addresses within current map entry
2081fef62e1aSDavid Carlier     if ((addr >= start) && (addr < end)) {
2082fef62e1aSDavid Carlier       if ((cur->kve_protection & KVME_PROT_READ) != 0 &&
2083fef62e1aSDavid Carlier           (cur->kve_protection & KVME_PROT_WRITE) != 0) {
2084fef62e1aSDavid Carlier         found = 1;
2085fef62e1aSDavid Carlier         break;
2086fef62e1aSDavid Carlier       }
2087fef62e1aSDavid Carlier     }
2088fef62e1aSDavid Carlier     lw += cursz;
2089fef62e1aSDavid Carlier   }
2090fef62e1aSDavid Carlier   kmpc_free(buf);
20917cc577a4SJonathan Peyton 
20927cc577a4SJonathan Peyton #elif KMP_OS_DARWIN
20937cc577a4SJonathan Peyton 
20943041982dSJonathan Peyton   /* On OS X*, /proc pseudo filesystem is not available. Try to read memory
20953041982dSJonathan Peyton      using vm interface. */
20967cc577a4SJonathan Peyton 
20977cc577a4SJonathan Peyton   int buffer;
20987cc577a4SJonathan Peyton   vm_size_t count;
20993041982dSJonathan Peyton   rc = vm_read_overwrite(
21007cc577a4SJonathan Peyton       mach_task_self(), // Task to read memory of.
21017cc577a4SJonathan Peyton       (vm_address_t)(addr), // Address to read from.
21027cc577a4SJonathan Peyton       1, // Number of bytes to be read.
21037cc577a4SJonathan Peyton       (vm_address_t)(&buffer), // Address of buffer to save read bytes in.
21047cc577a4SJonathan Peyton       &count // Address of var to save number of read bytes in.
21057cc577a4SJonathan Peyton   );
21067cc577a4SJonathan Peyton   if (rc == 0) {
21077cc577a4SJonathan Peyton     // Memory successfully read.
21087cc577a4SJonathan Peyton     found = 1;
2109bd3a7633SJonathan Peyton   }
21107cc577a4SJonathan Peyton 
2111316f4238SKamil Rytarowski #elif KMP_OS_NETBSD
21127cc577a4SJonathan Peyton 
2113316f4238SKamil Rytarowski   int mib[5];
2114316f4238SKamil Rytarowski   mib[0] = CTL_VM;
2115316f4238SKamil Rytarowski   mib[1] = VM_PROC;
2116316f4238SKamil Rytarowski   mib[2] = VM_PROC_MAP;
2117316f4238SKamil Rytarowski   mib[3] = getpid();
2118316f4238SKamil Rytarowski   mib[4] = sizeof(struct kinfo_vmentry);
2119316f4238SKamil Rytarowski 
2120316f4238SKamil Rytarowski   size_t size;
2121316f4238SKamil Rytarowski   rc = sysctl(mib, __arraycount(mib), NULL, &size, NULL, 0);
2122316f4238SKamil Rytarowski   KMP_ASSERT(!rc);
2123316f4238SKamil Rytarowski   KMP_ASSERT(size);
2124316f4238SKamil Rytarowski 
2125316f4238SKamil Rytarowski   size = size * 4 / 3;
2126316f4238SKamil Rytarowski   struct kinfo_vmentry *kiv = (struct kinfo_vmentry *)KMP_INTERNAL_MALLOC(size);
2127316f4238SKamil Rytarowski   KMP_ASSERT(kiv);
2128316f4238SKamil Rytarowski 
2129316f4238SKamil Rytarowski   rc = sysctl(mib, __arraycount(mib), kiv, &size, NULL, 0);
2130316f4238SKamil Rytarowski   KMP_ASSERT(!rc);
2131316f4238SKamil Rytarowski   KMP_ASSERT(size);
2132316f4238SKamil Rytarowski 
2133316f4238SKamil Rytarowski   for (size_t i = 0; i < size; i++) {
2134316f4238SKamil Rytarowski     if (kiv[i].kve_start >= (uint64_t)addr &&
2135316f4238SKamil Rytarowski         kiv[i].kve_end <= (uint64_t)addr) {
2136316f4238SKamil Rytarowski       found = 1;
2137316f4238SKamil Rytarowski       break;
2138316f4238SKamil Rytarowski     }
2139316f4238SKamil Rytarowski   }
2140316f4238SKamil Rytarowski   KMP_INTERNAL_FREE(kiv);
214127f6eedcSAndreyChurbanov #elif KMP_OS_OPENBSD
2142316f4238SKamil Rytarowski 
214327f6eedcSAndreyChurbanov   int mib[3];
214427f6eedcSAndreyChurbanov   mib[0] = CTL_KERN;
214527f6eedcSAndreyChurbanov   mib[1] = KERN_PROC_VMMAP;
214627f6eedcSAndreyChurbanov   mib[2] = getpid();
214727f6eedcSAndreyChurbanov 
214827f6eedcSAndreyChurbanov   size_t size;
214927f6eedcSAndreyChurbanov   uint64_t end;
215027f6eedcSAndreyChurbanov   rc = sysctl(mib, 3, NULL, &size, NULL, 0);
215127f6eedcSAndreyChurbanov   KMP_ASSERT(!rc);
215227f6eedcSAndreyChurbanov   KMP_ASSERT(size);
215327f6eedcSAndreyChurbanov   end = size;
215427f6eedcSAndreyChurbanov 
215527f6eedcSAndreyChurbanov   struct kinfo_vmentry kiv = {.kve_start = 0};
215627f6eedcSAndreyChurbanov 
215727f6eedcSAndreyChurbanov   while ((rc = sysctl(mib, 3, &kiv, &size, NULL, 0)) == 0) {
215827f6eedcSAndreyChurbanov     KMP_ASSERT(size);
215927f6eedcSAndreyChurbanov     if (kiv.kve_end == end)
216027f6eedcSAndreyChurbanov       break;
216127f6eedcSAndreyChurbanov 
216227f6eedcSAndreyChurbanov     if (kiv.kve_start >= (uint64_t)addr && kiv.kve_end <= (uint64_t)addr) {
216327f6eedcSAndreyChurbanov       found = 1;
216427f6eedcSAndreyChurbanov       break;
216527f6eedcSAndreyChurbanov     }
216627f6eedcSAndreyChurbanov     kiv.kve_start += 1;
216727f6eedcSAndreyChurbanov   }
216827f6eedcSAndreyChurbanov #elif KMP_OS_DRAGONFLY
216927f6eedcSAndreyChurbanov 
217027f6eedcSAndreyChurbanov   // FIXME(DragonFly): Implement this
21717cc577a4SJonathan Peyton   found = 1;
21727cc577a4SJonathan Peyton 
21737cc577a4SJonathan Peyton #else
21747cc577a4SJonathan Peyton 
21757cc577a4SJonathan Peyton #error "Unknown or unsupported OS"
21767cc577a4SJonathan Peyton 
21777cc577a4SJonathan Peyton #endif
21787cc577a4SJonathan Peyton 
21797cc577a4SJonathan Peyton   return found;
21807cc577a4SJonathan Peyton 
21817cc577a4SJonathan Peyton } // __kmp_is_address_mapped
21827cc577a4SJonathan Peyton 
21837cc577a4SJonathan Peyton #ifdef USE_LOAD_BALANCE
21847cc577a4SJonathan Peyton 
218570cdd83cSMichal Gorny #if KMP_OS_DARWIN || KMP_OS_NETBSD
21867cc577a4SJonathan Peyton 
21877cc577a4SJonathan Peyton // The function returns the rounded value of the system load average
21887cc577a4SJonathan Peyton // during given time interval which depends on the value of
21897cc577a4SJonathan Peyton // __kmp_load_balance_interval variable (default is 60 sec, other values
21907cc577a4SJonathan Peyton // may be 300 sec or 900 sec).
21917cc577a4SJonathan Peyton // It returns -1 in case of error.
21923041982dSJonathan Peyton int __kmp_get_load_balance(int max) {
21937cc577a4SJonathan Peyton   double averages[3];
21947cc577a4SJonathan Peyton   int ret_avg = 0;
21957cc577a4SJonathan Peyton 
21967cc577a4SJonathan Peyton   int res = getloadavg(averages, 3);
21977cc577a4SJonathan Peyton 
21987cc577a4SJonathan Peyton   // Check __kmp_load_balance_interval to determine which of averages to use.
21997cc577a4SJonathan Peyton   // getloadavg() may return the number of samples less than requested that is
22007cc577a4SJonathan Peyton   // less than 3.
22017cc577a4SJonathan Peyton   if (__kmp_load_balance_interval < 180 && (res >= 1)) {
22026b316febSTerry Wilmarth     ret_avg = (int)averages[0]; // 1 min
22033041982dSJonathan Peyton   } else if ((__kmp_load_balance_interval >= 180 &&
22043041982dSJonathan Peyton               __kmp_load_balance_interval < 600) &&
22053041982dSJonathan Peyton              (res >= 2)) {
22066b316febSTerry Wilmarth     ret_avg = (int)averages[1]; // 5 min
22077cc577a4SJonathan Peyton   } else if ((__kmp_load_balance_interval >= 600) && (res == 3)) {
22086b316febSTerry Wilmarth     ret_avg = (int)averages[2]; // 15 min
22097cc577a4SJonathan Peyton   } else { // Error occurred
22107cc577a4SJonathan Peyton     return -1;
22117cc577a4SJonathan Peyton   }
22127cc577a4SJonathan Peyton 
22137cc577a4SJonathan Peyton   return ret_avg;
22147cc577a4SJonathan Peyton }
22157cc577a4SJonathan Peyton 
22167cc577a4SJonathan Peyton #else // Linux* OS
22177cc577a4SJonathan Peyton 
221842016791SKazuaki Ishizaki // The function returns number of running (not sleeping) threads, or -1 in case
22193041982dSJonathan Peyton // of error. Error could be reported if Linux* OS kernel too old (without
22203041982dSJonathan Peyton // "/proc" support). Counting running threads stops if max running threads
22213041982dSJonathan Peyton // encountered.
22223041982dSJonathan Peyton int __kmp_get_load_balance(int max) {
22237cc577a4SJonathan Peyton   static int permanent_error = 0;
22243041982dSJonathan Peyton   static int glb_running_threads = 0; // Saved count of the running threads for
2225ed5fe645SKelvin Li   // the thread balance algorithm
22267cc577a4SJonathan Peyton   static double glb_call_time = 0; /* Thread balance algorithm call time */
22277cc577a4SJonathan Peyton 
22287cc577a4SJonathan Peyton   int running_threads = 0; // Number of running threads in the system.
22297cc577a4SJonathan Peyton 
22307cc577a4SJonathan Peyton   DIR *proc_dir = NULL; // Handle of "/proc/" directory.
22317cc577a4SJonathan Peyton   struct dirent *proc_entry = NULL;
22327cc577a4SJonathan Peyton 
22337cc577a4SJonathan Peyton   kmp_str_buf_t task_path; // "/proc/<pid>/task/<tid>/" path.
22347cc577a4SJonathan Peyton   DIR *task_dir = NULL; // Handle of "/proc/<pid>/task/<tid>/" directory.
22357cc577a4SJonathan Peyton   struct dirent *task_entry = NULL;
22367cc577a4SJonathan Peyton   int task_path_fixed_len;
22377cc577a4SJonathan Peyton 
22387cc577a4SJonathan Peyton   kmp_str_buf_t stat_path; // "/proc/<pid>/task/<tid>/stat" path.
22397cc577a4SJonathan Peyton   int stat_file = -1;
22407cc577a4SJonathan Peyton   int stat_path_fixed_len;
22417cc577a4SJonathan Peyton 
22427cc577a4SJonathan Peyton   int total_processes = 0; // Total number of processes in system.
22437cc577a4SJonathan Peyton   int total_threads = 0; // Total number of threads in system.
22447cc577a4SJonathan Peyton 
22457cc577a4SJonathan Peyton   double call_time = 0.0;
22467cc577a4SJonathan Peyton 
22477cc577a4SJonathan Peyton   __kmp_str_buf_init(&task_path);
22487cc577a4SJonathan Peyton   __kmp_str_buf_init(&stat_path);
22497cc577a4SJonathan Peyton 
22507cc577a4SJonathan Peyton   __kmp_elapsed(&call_time);
22517cc577a4SJonathan Peyton 
22527cc577a4SJonathan Peyton   if (glb_call_time &&
22537cc577a4SJonathan Peyton       (call_time - glb_call_time < __kmp_load_balance_interval)) {
22547cc577a4SJonathan Peyton     running_threads = glb_running_threads;
22557cc577a4SJonathan Peyton     goto finish;
22567cc577a4SJonathan Peyton   }
22577cc577a4SJonathan Peyton 
22587cc577a4SJonathan Peyton   glb_call_time = call_time;
22597cc577a4SJonathan Peyton 
22607cc577a4SJonathan Peyton   // Do not spend time on scanning "/proc/" if we have a permanent error.
22617cc577a4SJonathan Peyton   if (permanent_error) {
22627cc577a4SJonathan Peyton     running_threads = -1;
22637cc577a4SJonathan Peyton     goto finish;
2264bd3a7633SJonathan Peyton   }
22657cc577a4SJonathan Peyton 
22667cc577a4SJonathan Peyton   if (max <= 0) {
22677cc577a4SJonathan Peyton     max = INT_MAX;
2268bd3a7633SJonathan Peyton   }
22697cc577a4SJonathan Peyton 
22707cc577a4SJonathan Peyton   // Open "/proc/" directory.
22717cc577a4SJonathan Peyton   proc_dir = opendir("/proc");
22727cc577a4SJonathan Peyton   if (proc_dir == NULL) {
22733041982dSJonathan Peyton     // Cannot open "/prroc/". Probably the kernel does not support it. Return an
22743041982dSJonathan Peyton     // error now and in subsequent calls.
22757cc577a4SJonathan Peyton     running_threads = -1;
22767cc577a4SJonathan Peyton     permanent_error = 1;
22777cc577a4SJonathan Peyton     goto finish;
2278bd3a7633SJonathan Peyton   }
22797cc577a4SJonathan Peyton 
22807cc577a4SJonathan Peyton   // Initialize fixed part of task_path. This part will not change.
22817cc577a4SJonathan Peyton   __kmp_str_buf_cat(&task_path, "/proc/", 6);
22827cc577a4SJonathan Peyton   task_path_fixed_len = task_path.used; // Remember number of used characters.
22837cc577a4SJonathan Peyton 
22847cc577a4SJonathan Peyton   proc_entry = readdir(proc_dir);
22857cc577a4SJonathan Peyton   while (proc_entry != NULL) {
22863041982dSJonathan Peyton     // Proc entry is a directory and name starts with a digit. Assume it is a
22873041982dSJonathan Peyton     // process' directory.
22887cc577a4SJonathan Peyton     if (proc_entry->d_type == DT_DIR && isdigit(proc_entry->d_name[0])) {
22897cc577a4SJonathan Peyton 
22907cc577a4SJonathan Peyton       ++total_processes;
22917cc577a4SJonathan Peyton       // Make sure init process is the very first in "/proc", so we can replace
22923041982dSJonathan Peyton       // strcmp( proc_entry->d_name, "1" ) == 0 with simpler total_processes ==
22933041982dSJonathan Peyton       // 1. We are going to check that total_processes == 1 => d_name == "1" is
22943041982dSJonathan Peyton       // true (where "=>" is implication). Since C++ does not have => operator,
22953041982dSJonathan Peyton       // let us replace it with its equivalent: a => b == ! a || b.
22963041982dSJonathan Peyton       KMP_DEBUG_ASSERT(total_processes != 1 ||
22973041982dSJonathan Peyton                        strcmp(proc_entry->d_name, "1") == 0);
22987cc577a4SJonathan Peyton 
22997cc577a4SJonathan Peyton       // Construct task_path.
23007cc577a4SJonathan Peyton       task_path.used = task_path_fixed_len; // Reset task_path to "/proc/".
23013041982dSJonathan Peyton       __kmp_str_buf_cat(&task_path, proc_entry->d_name,
23023041982dSJonathan Peyton                         KMP_STRLEN(proc_entry->d_name));
23037cc577a4SJonathan Peyton       __kmp_str_buf_cat(&task_path, "/task", 5);
23047cc577a4SJonathan Peyton 
23057cc577a4SJonathan Peyton       task_dir = opendir(task_path.str);
23067cc577a4SJonathan Peyton       if (task_dir == NULL) {
23073041982dSJonathan Peyton         // Process can finish between reading "/proc/" directory entry and
23083041982dSJonathan Peyton         // opening process' "task/" directory. So, in general case we should not
23093041982dSJonathan Peyton         // complain, but have to skip this process and read the next one. But on
23103041982dSJonathan Peyton         // systems with no "task/" support we will spend lot of time to scan
23113041982dSJonathan Peyton         // "/proc/" tree again and again without any benefit. "init" process
23123041982dSJonathan Peyton         // (its pid is 1) should exist always, so, if we cannot open
23133041982dSJonathan Peyton         // "/proc/1/task/" directory, it means "task/" is not supported by
23143041982dSJonathan Peyton         // kernel. Report an error now and in the future.
23157cc577a4SJonathan Peyton         if (strcmp(proc_entry->d_name, "1") == 0) {
23167cc577a4SJonathan Peyton           running_threads = -1;
23177cc577a4SJonathan Peyton           permanent_error = 1;
23187cc577a4SJonathan Peyton           goto finish;
2319bd3a7633SJonathan Peyton         }
23207cc577a4SJonathan Peyton       } else {
23217cc577a4SJonathan Peyton         // Construct fixed part of stat file path.
23227cc577a4SJonathan Peyton         __kmp_str_buf_clear(&stat_path);
23237cc577a4SJonathan Peyton         __kmp_str_buf_cat(&stat_path, task_path.str, task_path.used);
23247cc577a4SJonathan Peyton         __kmp_str_buf_cat(&stat_path, "/", 1);
23257cc577a4SJonathan Peyton         stat_path_fixed_len = stat_path.used;
23267cc577a4SJonathan Peyton 
23277cc577a4SJonathan Peyton         task_entry = readdir(task_dir);
23287cc577a4SJonathan Peyton         while (task_entry != NULL) {
23297cc577a4SJonathan Peyton           // It is a directory and name starts with a digit.
23307cc577a4SJonathan Peyton           if (proc_entry->d_type == DT_DIR && isdigit(task_entry->d_name[0])) {
23317cc577a4SJonathan Peyton             ++total_threads;
23327cc577a4SJonathan Peyton 
2333ed5fe645SKelvin Li             // Construct complete stat file path. Easiest way would be:
23343041982dSJonathan Peyton             //  __kmp_str_buf_print( & stat_path, "%s/%s/stat", task_path.str,
23353041982dSJonathan Peyton             //  task_entry->d_name );
23367cc577a4SJonathan Peyton             // but seriae of __kmp_str_buf_cat works a bit faster.
23373041982dSJonathan Peyton             stat_path.used =
23383041982dSJonathan Peyton                 stat_path_fixed_len; // Reset stat path to its fixed part.
23393041982dSJonathan Peyton             __kmp_str_buf_cat(&stat_path, task_entry->d_name,
23403041982dSJonathan Peyton                               KMP_STRLEN(task_entry->d_name));
23417cc577a4SJonathan Peyton             __kmp_str_buf_cat(&stat_path, "/stat", 5);
23427cc577a4SJonathan Peyton 
23437cc577a4SJonathan Peyton             // Note: Low-level API (open/read/close) is used. High-level API
23447cc577a4SJonathan Peyton             // (fopen/fclose)  works ~ 30 % slower.
23457cc577a4SJonathan Peyton             stat_file = open(stat_path.str, O_RDONLY);
23467cc577a4SJonathan Peyton             if (stat_file == -1) {
23473041982dSJonathan Peyton               // We cannot report an error because task (thread) can terminate
23483041982dSJonathan Peyton               // just before reading this file.
23497cc577a4SJonathan Peyton             } else {
23503041982dSJonathan Peyton               /* Content of "stat" file looks like:
23517cc577a4SJonathan Peyton                  24285 (program) S ...
23527cc577a4SJonathan Peyton 
23533041982dSJonathan Peyton                  It is a single line (if program name does not include funny
23543041982dSJonathan Peyton                  symbols). First number is a thread id, then name of executable
23553041982dSJonathan Peyton                  file name in paretheses, then state of the thread. We need just
23563041982dSJonathan Peyton                  thread state.
23577cc577a4SJonathan Peyton 
23587cc577a4SJonathan Peyton                  Good news: Length of program name is 15 characters max. Longer
23597cc577a4SJonathan Peyton                  names are truncated.
23607cc577a4SJonathan Peyton 
23617cc577a4SJonathan Peyton                  Thus, we need rather short buffer: 15 chars for program name +
23627cc577a4SJonathan Peyton                  2 parenthesis, + 3 spaces + ~7 digits of pid = 37.
23637cc577a4SJonathan Peyton 
23647cc577a4SJonathan Peyton                  Bad news: Program name may contain special symbols like space,
23653041982dSJonathan Peyton                  closing parenthesis, or even new line. This makes parsing
23663041982dSJonathan Peyton                  "stat" file not 100 % reliable. In case of fanny program names
23673041982dSJonathan Peyton                  parsing may fail (report incorrect thread state).
23687cc577a4SJonathan Peyton 
23697cc577a4SJonathan Peyton                  Parsing "status" file looks more promissing (due to different
23707cc577a4SJonathan Peyton                  file structure and escaping special symbols) but reading and
23717cc577a4SJonathan Peyton                  parsing of "status" file works slower.
23727cc577a4SJonathan Peyton                   -- ln
23737cc577a4SJonathan Peyton               */
23747cc577a4SJonathan Peyton               char buffer[65];
23756b316febSTerry Wilmarth               ssize_t len;
23767cc577a4SJonathan Peyton               len = read(stat_file, buffer, sizeof(buffer) - 1);
23777cc577a4SJonathan Peyton               if (len >= 0) {
23787cc577a4SJonathan Peyton                 buffer[len] = 0;
23797cc577a4SJonathan Peyton                 // Using scanf:
23807cc577a4SJonathan Peyton                 //     sscanf( buffer, "%*d (%*s) %c ", & state );
23813041982dSJonathan Peyton                 // looks very nice, but searching for a closing parenthesis
23823041982dSJonathan Peyton                 // works a bit faster.
23837cc577a4SJonathan Peyton                 char *close_parent = strstr(buffer, ") ");
23847cc577a4SJonathan Peyton                 if (close_parent != NULL) {
23857cc577a4SJonathan Peyton                   char state = *(close_parent + 2);
23867cc577a4SJonathan Peyton                   if (state == 'R') {
23877cc577a4SJonathan Peyton                     ++running_threads;
23887cc577a4SJonathan Peyton                     if (running_threads >= max) {
23897cc577a4SJonathan Peyton                       goto finish;
2390bd3a7633SJonathan Peyton                     }
2391bd3a7633SJonathan Peyton                   }
2392bd3a7633SJonathan Peyton                 }
2393bd3a7633SJonathan Peyton               }
23947cc577a4SJonathan Peyton               close(stat_file);
23957cc577a4SJonathan Peyton               stat_file = -1;
2396bd3a7633SJonathan Peyton             }
2397bd3a7633SJonathan Peyton           }
23987cc577a4SJonathan Peyton           task_entry = readdir(task_dir);
2399bd3a7633SJonathan Peyton         }
24007cc577a4SJonathan Peyton         closedir(task_dir);
24017cc577a4SJonathan Peyton         task_dir = NULL;
2402bd3a7633SJonathan Peyton       }
2403bd3a7633SJonathan Peyton     }
24047cc577a4SJonathan Peyton     proc_entry = readdir(proc_dir);
2405bd3a7633SJonathan Peyton   }
24067cc577a4SJonathan Peyton 
24077cc577a4SJonathan Peyton   // There _might_ be a timing hole where the thread executing this
24087cc577a4SJonathan Peyton   // code get skipped in the load balance, and running_threads is 0.
24097cc577a4SJonathan Peyton   // Assert in the debug builds only!!!
24107cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(running_threads > 0);
24117cc577a4SJonathan Peyton   if (running_threads <= 0) {
24127cc577a4SJonathan Peyton     running_threads = 1;
24137cc577a4SJonathan Peyton   }
24147cc577a4SJonathan Peyton 
24157cc577a4SJonathan Peyton finish: // Clean up and exit.
24167cc577a4SJonathan Peyton   if (proc_dir != NULL) {
24177cc577a4SJonathan Peyton     closedir(proc_dir);
2418bd3a7633SJonathan Peyton   }
24197cc577a4SJonathan Peyton   __kmp_str_buf_free(&task_path);
24207cc577a4SJonathan Peyton   if (task_dir != NULL) {
24217cc577a4SJonathan Peyton     closedir(task_dir);
2422bd3a7633SJonathan Peyton   }
24237cc577a4SJonathan Peyton   __kmp_str_buf_free(&stat_path);
24247cc577a4SJonathan Peyton   if (stat_file != -1) {
24257cc577a4SJonathan Peyton     close(stat_file);
2426bd3a7633SJonathan Peyton   }
24277cc577a4SJonathan Peyton 
24287cc577a4SJonathan Peyton   glb_running_threads = running_threads;
24297cc577a4SJonathan Peyton 
24307cc577a4SJonathan Peyton   return running_threads;
24317cc577a4SJonathan Peyton 
24327cc577a4SJonathan Peyton } // __kmp_get_load_balance
24337cc577a4SJonathan Peyton 
24347cc577a4SJonathan Peyton #endif // KMP_OS_DARWIN
24357cc577a4SJonathan Peyton 
24367cc577a4SJonathan Peyton #endif // USE_LOAD_BALANCE
24377cc577a4SJonathan Peyton 
2438c47afcd9SAndrey Churbanov #if !(KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_MIC ||                            \
24392488ae9dSJonas Hahnfeld       ((KMP_OS_LINUX || KMP_OS_DARWIN) && KMP_ARCH_AARCH64) ||                 \
24402488ae9dSJonas Hahnfeld       KMP_ARCH_PPC64 || KMP_ARCH_RISCV64)
24417cc577a4SJonathan Peyton 
24427cc577a4SJonathan Peyton // we really only need the case with 1 argument, because CLANG always build
24437cc577a4SJonathan Peyton // a struct of pointers to shared variables referenced in the outlined function
24443041982dSJonathan Peyton int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,
24453041982dSJonathan Peyton                            void *p_argv[]
24467cc577a4SJonathan Peyton #if OMPT_SUPPORT
24473041982dSJonathan Peyton                            ,
24483041982dSJonathan Peyton                            void **exit_frame_ptr
24497cc577a4SJonathan Peyton #endif
24503041982dSJonathan Peyton ) {
24517cc577a4SJonathan Peyton #if OMPT_SUPPORT
245282e94a59SJoachim Protze   *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0);
24537cc577a4SJonathan Peyton #endif
24547cc577a4SJonathan Peyton 
24557cc577a4SJonathan Peyton   switch (argc) {
24567cc577a4SJonathan Peyton   default:
24577cc577a4SJonathan Peyton     fprintf(stderr, "Too many args to microtask: %d!\n", argc);
24587cc577a4SJonathan Peyton     fflush(stderr);
24597cc577a4SJonathan Peyton     exit(-1);
24607cc577a4SJonathan Peyton   case 0:
24617cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid);
24627cc577a4SJonathan Peyton     break;
24637cc577a4SJonathan Peyton   case 1:
24647cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0]);
24657cc577a4SJonathan Peyton     break;
24667cc577a4SJonathan Peyton   case 2:
24677cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1]);
24687cc577a4SJonathan Peyton     break;
24697cc577a4SJonathan Peyton   case 3:
24707cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2]);
24717cc577a4SJonathan Peyton     break;
24727cc577a4SJonathan Peyton   case 4:
24737cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3]);
24747cc577a4SJonathan Peyton     break;
24757cc577a4SJonathan Peyton   case 5:
24767cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4]);
24777cc577a4SJonathan Peyton     break;
24787cc577a4SJonathan Peyton   case 6:
24797cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
24807cc577a4SJonathan Peyton             p_argv[5]);
24817cc577a4SJonathan Peyton     break;
24827cc577a4SJonathan Peyton   case 7:
24837cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
24847cc577a4SJonathan Peyton             p_argv[5], p_argv[6]);
24857cc577a4SJonathan Peyton     break;
24867cc577a4SJonathan Peyton   case 8:
24877cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
24887cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7]);
24897cc577a4SJonathan Peyton     break;
24907cc577a4SJonathan Peyton   case 9:
24917cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
24927cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8]);
24937cc577a4SJonathan Peyton     break;
24947cc577a4SJonathan Peyton   case 10:
24957cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
24967cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9]);
24977cc577a4SJonathan Peyton     break;
24987cc577a4SJonathan Peyton   case 11:
24997cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25007cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10]);
25017cc577a4SJonathan Peyton     break;
25027cc577a4SJonathan Peyton   case 12:
25037cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25047cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
25057cc577a4SJonathan Peyton             p_argv[11]);
25067cc577a4SJonathan Peyton     break;
25077cc577a4SJonathan Peyton   case 13:
25087cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25097cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
25107cc577a4SJonathan Peyton             p_argv[11], p_argv[12]);
25117cc577a4SJonathan Peyton     break;
25127cc577a4SJonathan Peyton   case 14:
25137cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25147cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
25157cc577a4SJonathan Peyton             p_argv[11], p_argv[12], p_argv[13]);
25167cc577a4SJonathan Peyton     break;
25177cc577a4SJonathan Peyton   case 15:
25187cc577a4SJonathan Peyton     (*pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4],
25197cc577a4SJonathan Peyton             p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10],
25207cc577a4SJonathan Peyton             p_argv[11], p_argv[12], p_argv[13], p_argv[14]);
25217cc577a4SJonathan Peyton     break;
25227cc577a4SJonathan Peyton   }
25237cc577a4SJonathan Peyton 
25247cc577a4SJonathan Peyton   return 1;
25257cc577a4SJonathan Peyton }
25267cc577a4SJonathan Peyton 
25277cc577a4SJonathan Peyton #endif
25287cc577a4SJonathan Peyton 
25299d64275aSShilei Tian // Functions for hidden helper task
25309d64275aSShilei Tian namespace {
25319d64275aSShilei Tian // Condition variable for initializing hidden helper team
25329d64275aSShilei Tian pthread_cond_t hidden_helper_threads_initz_cond_var;
25339d64275aSShilei Tian pthread_mutex_t hidden_helper_threads_initz_lock;
25349d64275aSShilei Tian volatile int hidden_helper_initz_signaled = FALSE;
25359d64275aSShilei Tian 
25369d64275aSShilei Tian // Condition variable for deinitializing hidden helper team
25379d64275aSShilei Tian pthread_cond_t hidden_helper_threads_deinitz_cond_var;
25389d64275aSShilei Tian pthread_mutex_t hidden_helper_threads_deinitz_lock;
25399d64275aSShilei Tian volatile int hidden_helper_deinitz_signaled = FALSE;
25409d64275aSShilei Tian 
25419d64275aSShilei Tian // Condition variable for the wrapper function of main thread
25429d64275aSShilei Tian pthread_cond_t hidden_helper_main_thread_cond_var;
25439d64275aSShilei Tian pthread_mutex_t hidden_helper_main_thread_lock;
25449d64275aSShilei Tian volatile int hidden_helper_main_thread_signaled = FALSE;
25459d64275aSShilei Tian 
25469d64275aSShilei Tian // Semaphore for worker threads. We don't use condition variable here in case
25479d64275aSShilei Tian // that when multiple signals are sent at the same time, only one thread might
25489d64275aSShilei Tian // be waken.
25499d64275aSShilei Tian sem_t hidden_helper_task_sem;
25509d64275aSShilei Tian } // namespace
25519d64275aSShilei Tian 
25529d64275aSShilei Tian void __kmp_hidden_helper_worker_thread_wait() {
25539d64275aSShilei Tian   int status = sem_wait(&hidden_helper_task_sem);
25549d64275aSShilei Tian   KMP_CHECK_SYSFAIL("sem_wait", status);
25559d64275aSShilei Tian }
25569d64275aSShilei Tian 
25579d64275aSShilei Tian void __kmp_do_initialize_hidden_helper_threads() {
25589d64275aSShilei Tian   // Initialize condition variable
25599d64275aSShilei Tian   int status =
25609d64275aSShilei Tian       pthread_cond_init(&hidden_helper_threads_initz_cond_var, nullptr);
25619d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
25629d64275aSShilei Tian 
25639d64275aSShilei Tian   status = pthread_cond_init(&hidden_helper_threads_deinitz_cond_var, nullptr);
25649d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
25659d64275aSShilei Tian 
25669d64275aSShilei Tian   status = pthread_cond_init(&hidden_helper_main_thread_cond_var, nullptr);
25679d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
25689d64275aSShilei Tian 
25699d64275aSShilei Tian   status = pthread_mutex_init(&hidden_helper_threads_initz_lock, nullptr);
25709d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
25719d64275aSShilei Tian 
25729d64275aSShilei Tian   status = pthread_mutex_init(&hidden_helper_threads_deinitz_lock, nullptr);
25739d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
25749d64275aSShilei Tian 
25759d64275aSShilei Tian   status = pthread_mutex_init(&hidden_helper_main_thread_lock, nullptr);
25769d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
25779d64275aSShilei Tian 
25789d64275aSShilei Tian   // Initialize the semaphore
25799d64275aSShilei Tian   status = sem_init(&hidden_helper_task_sem, 0, 0);
25809d64275aSShilei Tian   KMP_CHECK_SYSFAIL("sem_init", status);
25819d64275aSShilei Tian 
25829d64275aSShilei Tian   // Create a new thread to finish initialization
25839d64275aSShilei Tian   pthread_t handle;
25849d64275aSShilei Tian   status = pthread_create(
25859d64275aSShilei Tian       &handle, nullptr,
25869d64275aSShilei Tian       [](void *) -> void * {
25879d64275aSShilei Tian         __kmp_hidden_helper_threads_initz_routine();
25889d64275aSShilei Tian         return nullptr;
25899d64275aSShilei Tian       },
25909d64275aSShilei Tian       nullptr);
25919d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_create", status);
25929d64275aSShilei Tian }
25939d64275aSShilei Tian 
25949d64275aSShilei Tian void __kmp_hidden_helper_threads_initz_wait() {
25959d64275aSShilei Tian   // Initial thread waits here for the completion of the initialization. The
25969d64275aSShilei Tian   // condition variable will be notified by main thread of hidden helper teams.
25979d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_threads_initz_lock);
25989d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
25999d64275aSShilei Tian 
26009d64275aSShilei Tian   if (!TCR_4(hidden_helper_initz_signaled)) {
26019d64275aSShilei Tian     status = pthread_cond_wait(&hidden_helper_threads_initz_cond_var,
26029d64275aSShilei Tian                                &hidden_helper_threads_initz_lock);
26039d64275aSShilei Tian     KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26049d64275aSShilei Tian   }
26059d64275aSShilei Tian 
26069d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_threads_initz_lock);
26079d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26089d64275aSShilei Tian }
26099d64275aSShilei Tian 
26109d64275aSShilei Tian void __kmp_hidden_helper_initz_release() {
26119d64275aSShilei Tian   // After all initialization, reset __kmp_init_hidden_helper_threads to false.
26129d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_threads_initz_lock);
26139d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26149d64275aSShilei Tian 
26159d64275aSShilei Tian   status = pthread_cond_signal(&hidden_helper_threads_initz_cond_var);
26169d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26179d64275aSShilei Tian 
26189d64275aSShilei Tian   TCW_SYNC_4(hidden_helper_initz_signaled, TRUE);
26199d64275aSShilei Tian 
26209d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_threads_initz_lock);
26219d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26229d64275aSShilei Tian }
26239d64275aSShilei Tian 
26249d64275aSShilei Tian void __kmp_hidden_helper_main_thread_wait() {
26259d64275aSShilei Tian   // The main thread of hidden helper team will be blocked here. The
26269d64275aSShilei Tian   // condition variable can only be signal in the destructor of RTL.
26279d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_main_thread_lock);
26289d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26299d64275aSShilei Tian 
26309d64275aSShilei Tian   if (!TCR_4(hidden_helper_main_thread_signaled)) {
26319d64275aSShilei Tian     status = pthread_cond_wait(&hidden_helper_main_thread_cond_var,
26329d64275aSShilei Tian                                &hidden_helper_main_thread_lock);
26339d64275aSShilei Tian     KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26349d64275aSShilei Tian   }
26359d64275aSShilei Tian 
26369d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_main_thread_lock);
26379d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26389d64275aSShilei Tian }
26399d64275aSShilei Tian 
26409d64275aSShilei Tian void __kmp_hidden_helper_main_thread_release() {
26419d64275aSShilei Tian   // The initial thread of OpenMP RTL should call this function to wake up the
26429d64275aSShilei Tian   // main thread of hidden helper team.
26439d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_main_thread_lock);
26449d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26459d64275aSShilei Tian 
26469d64275aSShilei Tian   status = pthread_cond_signal(&hidden_helper_main_thread_cond_var);
26479d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_signal", status);
26489d64275aSShilei Tian 
26499d64275aSShilei Tian   // The hidden helper team is done here
26509d64275aSShilei Tian   TCW_SYNC_4(hidden_helper_main_thread_signaled, TRUE);
26519d64275aSShilei Tian 
26529d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_main_thread_lock);
26539d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26549d64275aSShilei Tian }
26559d64275aSShilei Tian 
26569d64275aSShilei Tian void __kmp_hidden_helper_worker_thread_signal() {
26579d64275aSShilei Tian   int status = sem_post(&hidden_helper_task_sem);
26589d64275aSShilei Tian   KMP_CHECK_SYSFAIL("sem_post", status);
26599d64275aSShilei Tian }
26609d64275aSShilei Tian 
26619d64275aSShilei Tian void __kmp_hidden_helper_threads_deinitz_wait() {
26629d64275aSShilei Tian   // Initial thread waits here for the completion of the deinitialization. The
26639d64275aSShilei Tian   // condition variable will be notified by main thread of hidden helper teams.
26649d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_threads_deinitz_lock);
26659d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26669d64275aSShilei Tian 
26679d64275aSShilei Tian   if (!TCR_4(hidden_helper_deinitz_signaled)) {
26689d64275aSShilei Tian     status = pthread_cond_wait(&hidden_helper_threads_deinitz_cond_var,
26699d64275aSShilei Tian                                &hidden_helper_threads_deinitz_lock);
26709d64275aSShilei Tian     KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26719d64275aSShilei Tian   }
26729d64275aSShilei Tian 
26739d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_threads_deinitz_lock);
26749d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26759d64275aSShilei Tian }
26769d64275aSShilei Tian 
26779d64275aSShilei Tian void __kmp_hidden_helper_threads_deinitz_release() {
26789d64275aSShilei Tian   int status = pthread_mutex_lock(&hidden_helper_threads_deinitz_lock);
26799d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
26809d64275aSShilei Tian 
26819d64275aSShilei Tian   status = pthread_cond_signal(&hidden_helper_threads_deinitz_cond_var);
26829d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
26839d64275aSShilei Tian 
26849d64275aSShilei Tian   TCW_SYNC_4(hidden_helper_deinitz_signaled, TRUE);
26859d64275aSShilei Tian 
26869d64275aSShilei Tian   status = pthread_mutex_unlock(&hidden_helper_threads_deinitz_lock);
26879d64275aSShilei Tian   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
26889d64275aSShilei Tian }
26899d64275aSShilei Tian 
26907cc577a4SJonathan Peyton // end of file //
2691