xref: /freebsd/contrib/llvm-project/openmp/runtime/src/z_Linux_util.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric /*
20b57cec5SDimitry Andric  * z_Linux_util.cpp -- platform specific routines.
30b57cec5SDimitry Andric  */
40b57cec5SDimitry Andric 
50b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
80b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
90b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "kmp.h"
140b57cec5SDimitry Andric #include "kmp_affinity.h"
150b57cec5SDimitry Andric #include "kmp_i18n.h"
160b57cec5SDimitry Andric #include "kmp_io.h"
170b57cec5SDimitry Andric #include "kmp_itt.h"
180b57cec5SDimitry Andric #include "kmp_lock.h"
190b57cec5SDimitry Andric #include "kmp_stats.h"
200b57cec5SDimitry Andric #include "kmp_str.h"
210b57cec5SDimitry Andric #include "kmp_wait_release.h"
220b57cec5SDimitry Andric #include "kmp_wrapper_getpid.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric #if !KMP_OS_DRAGONFLY && !KMP_OS_FREEBSD && !KMP_OS_NETBSD && !KMP_OS_OPENBSD
250b57cec5SDimitry Andric #include <alloca.h>
260b57cec5SDimitry Andric #endif
270b57cec5SDimitry Andric #include <math.h> // HUGE_VAL.
28fe6060f1SDimitry Andric #if KMP_OS_LINUX
29e8d8bef9SDimitry Andric #include <semaphore.h>
30fe6060f1SDimitry Andric #endif // KMP_OS_LINUX
310b57cec5SDimitry Andric #include <sys/resource.h>
32*0fca6ea1SDimitry Andric #if KMP_OS_AIX
33*0fca6ea1SDimitry Andric #include <sys/ldr.h>
34*0fca6ea1SDimitry Andric #include <libperfstat.h>
35*0fca6ea1SDimitry Andric #else
360b57cec5SDimitry Andric #include <sys/syscall.h>
371db9f3b2SDimitry Andric #endif
380b57cec5SDimitry Andric #include <sys/time.h>
390b57cec5SDimitry Andric #include <sys/times.h>
400b57cec5SDimitry Andric #include <unistd.h>
410b57cec5SDimitry Andric 
42e8d8bef9SDimitry Andric #if KMP_OS_LINUX
430b57cec5SDimitry Andric #include <sys/sysinfo.h>
440b57cec5SDimitry Andric #if KMP_USE_FUTEX
450b57cec5SDimitry Andric // We should really include <futex.h>, but that causes compatibility problems on
460b57cec5SDimitry Andric // different Linux* OS distributions that either require that you include (or
470b57cec5SDimitry Andric // break when you try to include) <pci/types.h>. Since all we need is the two
480b57cec5SDimitry Andric // macros below (which are part of the kernel ABI, so can't change) we just
490b57cec5SDimitry Andric // define the constants here and don't include <futex.h>
500b57cec5SDimitry Andric #ifndef FUTEX_WAIT
510b57cec5SDimitry Andric #define FUTEX_WAIT 0
520b57cec5SDimitry Andric #endif
530b57cec5SDimitry Andric #ifndef FUTEX_WAKE
540b57cec5SDimitry Andric #define FUTEX_WAKE 1
550b57cec5SDimitry Andric #endif
560b57cec5SDimitry Andric #endif
570b57cec5SDimitry Andric #elif KMP_OS_DARWIN
580b57cec5SDimitry Andric #include <mach/mach.h>
590b57cec5SDimitry Andric #include <sys/sysctl.h>
600b57cec5SDimitry Andric #elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD
61489b1cf2SDimitry Andric #include <sys/types.h>
62489b1cf2SDimitry Andric #include <sys/sysctl.h>
63489b1cf2SDimitry Andric #include <sys/user.h>
640b57cec5SDimitry Andric #include <pthread_np.h>
65*0fca6ea1SDimitry Andric #if KMP_OS_DRAGONFLY
66*0fca6ea1SDimitry Andric #include <kvm.h>
67*0fca6ea1SDimitry Andric #endif
68480093f4SDimitry Andric #elif KMP_OS_NETBSD || KMP_OS_OPENBSD
690b57cec5SDimitry Andric #include <sys/types.h>
700b57cec5SDimitry Andric #include <sys/sysctl.h>
71*0fca6ea1SDimitry Andric #if KMP_OS_NETBSD
72*0fca6ea1SDimitry Andric #include <sched.h>
73*0fca6ea1SDimitry Andric #endif
745f757f3fSDimitry Andric #elif KMP_OS_SOLARIS
75*0fca6ea1SDimitry Andric #include <libproc.h>
76*0fca6ea1SDimitry Andric #include <procfs.h>
77*0fca6ea1SDimitry Andric #include <thread.h>
785f757f3fSDimitry Andric #include <sys/loadavg.h>
790b57cec5SDimitry Andric #endif
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric #include <ctype.h>
820b57cec5SDimitry Andric #include <dirent.h>
830b57cec5SDimitry Andric #include <fcntl.h>
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric struct kmp_sys_timer {
860b57cec5SDimitry Andric   struct timespec start;
870b57cec5SDimitry Andric };
880b57cec5SDimitry Andric 
895f757f3fSDimitry Andric #ifndef TIMEVAL_TO_TIMESPEC
905f757f3fSDimitry Andric // Convert timeval to timespec.
915f757f3fSDimitry Andric #define TIMEVAL_TO_TIMESPEC(tv, ts)                                            \
925f757f3fSDimitry Andric   do {                                                                         \
935f757f3fSDimitry Andric     (ts)->tv_sec = (tv)->tv_sec;                                               \
945f757f3fSDimitry Andric     (ts)->tv_nsec = (tv)->tv_usec * 1000;                                      \
955f757f3fSDimitry Andric   } while (0)
965f757f3fSDimitry Andric #endif
975f757f3fSDimitry Andric 
980b57cec5SDimitry Andric // Convert timespec to nanoseconds.
99e8d8bef9SDimitry Andric #define TS2NS(timespec)                                                        \
100e8d8bef9SDimitry Andric   (((timespec).tv_sec * (long int)1e9) + (timespec).tv_nsec)
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric static struct kmp_sys_timer __kmp_sys_timer_data;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric #if KMP_HANDLE_SIGNALS
1050b57cec5SDimitry Andric typedef void (*sig_func_t)(int);
1060b57cec5SDimitry Andric STATIC_EFI2_WORKAROUND struct sigaction __kmp_sighldrs[NSIG];
1070b57cec5SDimitry Andric static sigset_t __kmp_sigset;
1080b57cec5SDimitry Andric #endif
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric static int __kmp_init_runtime = FALSE;
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric static int __kmp_fork_count = 0;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric static pthread_condattr_t __kmp_suspend_cond_attr;
1150b57cec5SDimitry Andric static pthread_mutexattr_t __kmp_suspend_mutex_attr;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric static kmp_cond_align_t __kmp_wait_cv;
1180b57cec5SDimitry Andric static kmp_mutex_align_t __kmp_wait_mx;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric kmp_uint64 __kmp_ticks_per_msec = 1000000;
1215f757f3fSDimitry Andric kmp_uint64 __kmp_ticks_per_usec = 1000;
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric #ifdef DEBUG_SUSPEND
__kmp_print_cond(char * buffer,kmp_cond_align_t * cond)1240b57cec5SDimitry Andric static void __kmp_print_cond(char *buffer, kmp_cond_align_t *cond) {
1250b57cec5SDimitry Andric   KMP_SNPRINTF(buffer, 128, "(cond (lock (%ld, %d)), (descr (%p)))",
1260b57cec5SDimitry Andric                cond->c_cond.__c_lock.__status, cond->c_cond.__c_lock.__spinlock,
1270b57cec5SDimitry Andric                cond->c_cond.__c_waiting);
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric #endif
1300b57cec5SDimitry Andric 
131*0fca6ea1SDimitry Andric #if ((KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY ||   \
132*0fca6ea1SDimitry Andric       KMP_OS_AIX) &&                                                           \
133*0fca6ea1SDimitry Andric      KMP_AFFINITY_SUPPORTED)
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric /* Affinity support */
1360b57cec5SDimitry Andric 
__kmp_affinity_bind_thread(int which)1370b57cec5SDimitry Andric void __kmp_affinity_bind_thread(int which) {
1380b57cec5SDimitry Andric   KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
1390b57cec5SDimitry Andric               "Illegal set affinity operation when not capable");
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   kmp_affin_mask_t *mask;
1420b57cec5SDimitry Andric   KMP_CPU_ALLOC_ON_STACK(mask);
1430b57cec5SDimitry Andric   KMP_CPU_ZERO(mask);
1440b57cec5SDimitry Andric   KMP_CPU_SET(which, mask);
1450b57cec5SDimitry Andric   __kmp_set_system_affinity(mask, TRUE);
1460b57cec5SDimitry Andric   KMP_CPU_FREE_FROM_STACK(mask);
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric 
149439352acSDimitry Andric #if KMP_OS_AIX
__kmp_affinity_determine_capable(const char * env_var)150439352acSDimitry Andric void __kmp_affinity_determine_capable(const char *env_var) {
151439352acSDimitry Andric   // All versions of AIX support bindprocessor().
152439352acSDimitry Andric 
153439352acSDimitry Andric   size_t mask_size = __kmp_xproc / CHAR_BIT;
154439352acSDimitry Andric   // Round up to byte boundary.
155439352acSDimitry Andric   if (__kmp_xproc % CHAR_BIT)
156439352acSDimitry Andric     ++mask_size;
157439352acSDimitry Andric 
158439352acSDimitry Andric   // Round up to the mask_size_type boundary.
159439352acSDimitry Andric   if (mask_size % sizeof(__kmp_affin_mask_size))
160439352acSDimitry Andric     mask_size += sizeof(__kmp_affin_mask_size) -
161439352acSDimitry Andric                  mask_size % sizeof(__kmp_affin_mask_size);
162439352acSDimitry Andric   KMP_AFFINITY_ENABLE(mask_size);
163439352acSDimitry Andric   KA_TRACE(10,
164439352acSDimitry Andric            ("__kmp_affinity_determine_capable: "
165439352acSDimitry Andric             "AIX OS affinity interface bindprocessor functional (mask size = "
166439352acSDimitry Andric             "%" KMP_SIZE_T_SPEC ").\n",
167439352acSDimitry Andric             __kmp_affin_mask_size));
168439352acSDimitry Andric }
169439352acSDimitry Andric 
170439352acSDimitry Andric #else // !KMP_OS_AIX
171439352acSDimitry Andric 
1720b57cec5SDimitry Andric /* Determine if we can access affinity functionality on this version of
1730b57cec5SDimitry Andric  * Linux* OS by checking __NR_sched_{get,set}affinity system calls, and set
1740b57cec5SDimitry Andric  * __kmp_affin_mask_size to the appropriate value (0 means not capable). */
__kmp_affinity_determine_capable(const char * env_var)1750b57cec5SDimitry Andric void __kmp_affinity_determine_capable(const char *env_var) {
1760b57cec5SDimitry Andric   // Check and see if the OS supports thread affinity.
1770b57cec5SDimitry Andric 
178489b1cf2SDimitry Andric #if KMP_OS_LINUX
1790b57cec5SDimitry Andric #define KMP_CPU_SET_SIZE_LIMIT (1024 * 1024)
180fe6060f1SDimitry Andric #define KMP_CPU_SET_TRY_SIZE CACHE_LINE
181*0fca6ea1SDimitry Andric #elif KMP_OS_FREEBSD || KMP_OS_DRAGONFLY
182489b1cf2SDimitry Andric #define KMP_CPU_SET_SIZE_LIMIT (sizeof(cpuset_t))
183*0fca6ea1SDimitry Andric #elif KMP_OS_NETBSD
184*0fca6ea1SDimitry Andric #define KMP_CPU_SET_SIZE_LIMIT (256)
185489b1cf2SDimitry Andric #endif
1860b57cec5SDimitry Andric 
187bdd1243dSDimitry Andric   int verbose = __kmp_affinity.flags.verbose;
188bdd1243dSDimitry Andric   int warnings = __kmp_affinity.flags.warnings;
189bdd1243dSDimitry Andric   enum affinity_type type = __kmp_affinity.type;
190bdd1243dSDimitry Andric 
191489b1cf2SDimitry Andric #if KMP_OS_LINUX
192e8d8bef9SDimitry Andric   long gCode;
1930b57cec5SDimitry Andric   unsigned char *buf;
1940b57cec5SDimitry Andric   buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT);
195fe6060f1SDimitry Andric 
196fe6060f1SDimitry Andric   // If the syscall returns a suggestion for the size,
197fe6060f1SDimitry Andric   // then we don't have to search for an appropriate size.
198fe6060f1SDimitry Andric   gCode = syscall(__NR_sched_getaffinity, 0, KMP_CPU_SET_TRY_SIZE, buf);
1990b57cec5SDimitry Andric   KA_TRACE(30, ("__kmp_affinity_determine_capable: "
200e8d8bef9SDimitry Andric                 "initial getaffinity call returned %ld errno = %d\n",
2010b57cec5SDimitry Andric                 gCode, errno));
2020b57cec5SDimitry Andric 
203fe6060f1SDimitry Andric   if (gCode < 0 && errno != EINVAL) {
2040b57cec5SDimitry Andric     // System call not supported
205bdd1243dSDimitry Andric     if (verbose ||
206bdd1243dSDimitry Andric         (warnings && (type != affinity_none) && (type != affinity_default) &&
207bdd1243dSDimitry Andric          (type != affinity_disabled))) {
2080b57cec5SDimitry Andric       int error = errno;
2090b57cec5SDimitry Andric       kmp_msg_t err_code = KMP_ERR(error);
2100b57cec5SDimitry Andric       __kmp_msg(kmp_ms_warning, KMP_MSG(GetAffSysCallNotSupported, env_var),
2110b57cec5SDimitry Andric                 err_code, __kmp_msg_null);
2120b57cec5SDimitry Andric       if (__kmp_generate_warnings == kmp_warnings_off) {
2130b57cec5SDimitry Andric         __kmp_str_free(&err_code.str);
2140b57cec5SDimitry Andric       }
2150b57cec5SDimitry Andric     }
2160b57cec5SDimitry Andric     KMP_AFFINITY_DISABLE();
2170b57cec5SDimitry Andric     KMP_INTERNAL_FREE(buf);
2180b57cec5SDimitry Andric     return;
219fe6060f1SDimitry Andric   } else if (gCode > 0) {
2200b57cec5SDimitry Andric     // The optimal situation: the OS returns the size of the buffer it expects.
2210b57cec5SDimitry Andric     KMP_AFFINITY_ENABLE(gCode);
2220b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_affinity_determine_capable: "
2230b57cec5SDimitry Andric                   "affinity supported (mask size %d)\n",
2240b57cec5SDimitry Andric                   (int)__kmp_affin_mask_size));
2250b57cec5SDimitry Andric     KMP_INTERNAL_FREE(buf);
2260b57cec5SDimitry Andric     return;
2270b57cec5SDimitry Andric   }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   // Call the getaffinity system call repeatedly with increasing set sizes
2300b57cec5SDimitry Andric   // until we succeed, or reach an upper bound on the search.
2310b57cec5SDimitry Andric   KA_TRACE(30, ("__kmp_affinity_determine_capable: "
2320b57cec5SDimitry Andric                 "searching for proper set size\n"));
2330b57cec5SDimitry Andric   int size;
2340b57cec5SDimitry Andric   for (size = 1; size <= KMP_CPU_SET_SIZE_LIMIT; size *= 2) {
2350b57cec5SDimitry Andric     gCode = syscall(__NR_sched_getaffinity, 0, size, buf);
2360b57cec5SDimitry Andric     KA_TRACE(30, ("__kmp_affinity_determine_capable: "
237e8d8bef9SDimitry Andric                   "getaffinity for mask size %ld returned %ld errno = %d\n",
2380b57cec5SDimitry Andric                   size, gCode, errno));
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric     if (gCode < 0) {
2410b57cec5SDimitry Andric       if (errno == ENOSYS) {
2420b57cec5SDimitry Andric         // We shouldn't get here
2430b57cec5SDimitry Andric         KA_TRACE(30, ("__kmp_affinity_determine_capable: "
2440b57cec5SDimitry Andric                       "inconsistent OS call behavior: errno == ENOSYS for mask "
2450b57cec5SDimitry Andric                       "size %d\n",
2460b57cec5SDimitry Andric                       size));
247bdd1243dSDimitry Andric         if (verbose ||
248bdd1243dSDimitry Andric             (warnings && (type != affinity_none) &&
249bdd1243dSDimitry Andric              (type != affinity_default) && (type != affinity_disabled))) {
2500b57cec5SDimitry Andric           int error = errno;
2510b57cec5SDimitry Andric           kmp_msg_t err_code = KMP_ERR(error);
2520b57cec5SDimitry Andric           __kmp_msg(kmp_ms_warning, KMP_MSG(GetAffSysCallNotSupported, env_var),
2530b57cec5SDimitry Andric                     err_code, __kmp_msg_null);
2540b57cec5SDimitry Andric           if (__kmp_generate_warnings == kmp_warnings_off) {
2550b57cec5SDimitry Andric             __kmp_str_free(&err_code.str);
2560b57cec5SDimitry Andric           }
2570b57cec5SDimitry Andric         }
2580b57cec5SDimitry Andric         KMP_AFFINITY_DISABLE();
2590b57cec5SDimitry Andric         KMP_INTERNAL_FREE(buf);
2600b57cec5SDimitry Andric         return;
2610b57cec5SDimitry Andric       }
2620b57cec5SDimitry Andric       continue;
2630b57cec5SDimitry Andric     }
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric     KMP_AFFINITY_ENABLE(gCode);
2660b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_affinity_determine_capable: "
2670b57cec5SDimitry Andric                   "affinity supported (mask size %d)\n",
2680b57cec5SDimitry Andric                   (int)__kmp_affin_mask_size));
2690b57cec5SDimitry Andric     KMP_INTERNAL_FREE(buf);
2700b57cec5SDimitry Andric     return;
2710b57cec5SDimitry Andric   }
272*0fca6ea1SDimitry Andric #elif KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY
273e8d8bef9SDimitry Andric   long gCode;
274489b1cf2SDimitry Andric   unsigned char *buf;
275489b1cf2SDimitry Andric   buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT);
276fe6060f1SDimitry Andric   gCode = pthread_getaffinity_np(pthread_self(), KMP_CPU_SET_SIZE_LIMIT,
277fe6060f1SDimitry Andric                                  reinterpret_cast<cpuset_t *>(buf));
278489b1cf2SDimitry Andric   KA_TRACE(30, ("__kmp_affinity_determine_capable: "
279489b1cf2SDimitry Andric                 "initial getaffinity call returned %d errno = %d\n",
280489b1cf2SDimitry Andric                 gCode, errno));
281489b1cf2SDimitry Andric   if (gCode == 0) {
282489b1cf2SDimitry Andric     KMP_AFFINITY_ENABLE(KMP_CPU_SET_SIZE_LIMIT);
283489b1cf2SDimitry Andric     KA_TRACE(10, ("__kmp_affinity_determine_capable: "
2845ffd83dbSDimitry Andric                   "affinity supported (mask size %d)\n",
285489b1cf2SDimitry Andric                   (int)__kmp_affin_mask_size));
286489b1cf2SDimitry Andric     KMP_INTERNAL_FREE(buf);
287489b1cf2SDimitry Andric     return;
288489b1cf2SDimitry Andric   }
289489b1cf2SDimitry Andric #endif
2900b57cec5SDimitry Andric   KMP_INTERNAL_FREE(buf);
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   // Affinity is not supported
2930b57cec5SDimitry Andric   KMP_AFFINITY_DISABLE();
2940b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_affinity_determine_capable: "
2950b57cec5SDimitry Andric                 "cannot determine mask size - affinity not supported\n"));
296bdd1243dSDimitry Andric   if (verbose || (warnings && (type != affinity_none) &&
297bdd1243dSDimitry Andric                   (type != affinity_default) && (type != affinity_disabled))) {
2980b57cec5SDimitry Andric     KMP_WARNING(AffCantGetMaskSize, env_var);
2990b57cec5SDimitry Andric   }
3000b57cec5SDimitry Andric }
301439352acSDimitry Andric #endif // KMP_OS_AIX
302*0fca6ea1SDimitry Andric #endif // (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD ||                  \
303*0fca6ea1SDimitry Andric            KMP_OS_DRAGONFLY || KMP_OS_AIX) && KMP_AFFINITY_SUPPORTED
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric #if KMP_USE_FUTEX
3060b57cec5SDimitry Andric 
__kmp_futex_determine_capable()3070b57cec5SDimitry Andric int __kmp_futex_determine_capable() {
3080b57cec5SDimitry Andric   int loc = 0;
309e8d8bef9SDimitry Andric   long rc = syscall(__NR_futex, &loc, FUTEX_WAKE, 1, NULL, NULL, 0);
3100b57cec5SDimitry Andric   int retval = (rc == 0) || (errno != ENOSYS);
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   KA_TRACE(10,
3130b57cec5SDimitry Andric            ("__kmp_futex_determine_capable: rc = %d errno = %d\n", rc, errno));
3140b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_futex_determine_capable: futex syscall%s supported\n",
3150b57cec5SDimitry Andric                 retval ? "" : " not"));
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric   return retval;
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric #endif // KMP_USE_FUTEX
3210b57cec5SDimitry Andric 
3225f757f3fSDimitry Andric #if (KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_WASM) && (!KMP_ASM_INTRINS)
3230b57cec5SDimitry Andric /* Only 32-bit "add-exchange" instruction on IA-32 architecture causes us to
3240b57cec5SDimitry Andric    use compare_and_store for these routines */
3250b57cec5SDimitry Andric 
__kmp_test_then_or8(volatile kmp_int8 * p,kmp_int8 d)3260b57cec5SDimitry Andric kmp_int8 __kmp_test_then_or8(volatile kmp_int8 *p, kmp_int8 d) {
3270b57cec5SDimitry Andric   kmp_int8 old_value, new_value;
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric   old_value = TCR_1(*p);
3300b57cec5SDimitry Andric   new_value = old_value | d;
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric   while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
3330b57cec5SDimitry Andric     KMP_CPU_PAUSE();
3340b57cec5SDimitry Andric     old_value = TCR_1(*p);
3350b57cec5SDimitry Andric     new_value = old_value | d;
3360b57cec5SDimitry Andric   }
3370b57cec5SDimitry Andric   return old_value;
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric 
__kmp_test_then_and8(volatile kmp_int8 * p,kmp_int8 d)3400b57cec5SDimitry Andric kmp_int8 __kmp_test_then_and8(volatile kmp_int8 *p, kmp_int8 d) {
3410b57cec5SDimitry Andric   kmp_int8 old_value, new_value;
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   old_value = TCR_1(*p);
3440b57cec5SDimitry Andric   new_value = old_value & d;
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
3470b57cec5SDimitry Andric     KMP_CPU_PAUSE();
3480b57cec5SDimitry Andric     old_value = TCR_1(*p);
3490b57cec5SDimitry Andric     new_value = old_value & d;
3500b57cec5SDimitry Andric   }
3510b57cec5SDimitry Andric   return old_value;
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric 
__kmp_test_then_or32(volatile kmp_uint32 * p,kmp_uint32 d)3540b57cec5SDimitry Andric kmp_uint32 __kmp_test_then_or32(volatile kmp_uint32 *p, kmp_uint32 d) {
3550b57cec5SDimitry Andric   kmp_uint32 old_value, new_value;
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   old_value = TCR_4(*p);
3580b57cec5SDimitry Andric   new_value = old_value | d;
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   while (!KMP_COMPARE_AND_STORE_REL32(p, old_value, new_value)) {
3610b57cec5SDimitry Andric     KMP_CPU_PAUSE();
3620b57cec5SDimitry Andric     old_value = TCR_4(*p);
3630b57cec5SDimitry Andric     new_value = old_value | d;
3640b57cec5SDimitry Andric   }
3650b57cec5SDimitry Andric   return old_value;
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric 
__kmp_test_then_and32(volatile kmp_uint32 * p,kmp_uint32 d)3680b57cec5SDimitry Andric kmp_uint32 __kmp_test_then_and32(volatile kmp_uint32 *p, kmp_uint32 d) {
3690b57cec5SDimitry Andric   kmp_uint32 old_value, new_value;
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric   old_value = TCR_4(*p);
3720b57cec5SDimitry Andric   new_value = old_value & d;
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   while (!KMP_COMPARE_AND_STORE_REL32(p, old_value, new_value)) {
3750b57cec5SDimitry Andric     KMP_CPU_PAUSE();
3760b57cec5SDimitry Andric     old_value = TCR_4(*p);
3770b57cec5SDimitry Andric     new_value = old_value & d;
3780b57cec5SDimitry Andric   }
3790b57cec5SDimitry Andric   return old_value;
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric 
3825f757f3fSDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_WASM
__kmp_test_then_add8(volatile kmp_int8 * p,kmp_int8 d)3830b57cec5SDimitry Andric kmp_int8 __kmp_test_then_add8(volatile kmp_int8 *p, kmp_int8 d) {
3840b57cec5SDimitry Andric   kmp_int8 old_value, new_value;
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   old_value = TCR_1(*p);
3870b57cec5SDimitry Andric   new_value = old_value + d;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) {
3900b57cec5SDimitry Andric     KMP_CPU_PAUSE();
3910b57cec5SDimitry Andric     old_value = TCR_1(*p);
3920b57cec5SDimitry Andric     new_value = old_value + d;
3930b57cec5SDimitry Andric   }
3940b57cec5SDimitry Andric   return old_value;
3950b57cec5SDimitry Andric }
3960b57cec5SDimitry Andric 
__kmp_test_then_add64(volatile kmp_int64 * p,kmp_int64 d)3970b57cec5SDimitry Andric kmp_int64 __kmp_test_then_add64(volatile kmp_int64 *p, kmp_int64 d) {
3980b57cec5SDimitry Andric   kmp_int64 old_value, new_value;
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   old_value = TCR_8(*p);
4010b57cec5SDimitry Andric   new_value = old_value + d;
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
4040b57cec5SDimitry Andric     KMP_CPU_PAUSE();
4050b57cec5SDimitry Andric     old_value = TCR_8(*p);
4060b57cec5SDimitry Andric     new_value = old_value + d;
4070b57cec5SDimitry Andric   }
4080b57cec5SDimitry Andric   return old_value;
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 */
4110b57cec5SDimitry Andric 
__kmp_test_then_or64(volatile kmp_uint64 * p,kmp_uint64 d)4120b57cec5SDimitry Andric kmp_uint64 __kmp_test_then_or64(volatile kmp_uint64 *p, kmp_uint64 d) {
4130b57cec5SDimitry Andric   kmp_uint64 old_value, new_value;
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric   old_value = TCR_8(*p);
4160b57cec5SDimitry Andric   new_value = old_value | d;
4170b57cec5SDimitry Andric   while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
4180b57cec5SDimitry Andric     KMP_CPU_PAUSE();
4190b57cec5SDimitry Andric     old_value = TCR_8(*p);
4200b57cec5SDimitry Andric     new_value = old_value | d;
4210b57cec5SDimitry Andric   }
4220b57cec5SDimitry Andric   return old_value;
4230b57cec5SDimitry Andric }
4240b57cec5SDimitry Andric 
__kmp_test_then_and64(volatile kmp_uint64 * p,kmp_uint64 d)4250b57cec5SDimitry Andric kmp_uint64 __kmp_test_then_and64(volatile kmp_uint64 *p, kmp_uint64 d) {
4260b57cec5SDimitry Andric   kmp_uint64 old_value, new_value;
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric   old_value = TCR_8(*p);
4290b57cec5SDimitry Andric   new_value = old_value & d;
4300b57cec5SDimitry Andric   while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) {
4310b57cec5SDimitry Andric     KMP_CPU_PAUSE();
4320b57cec5SDimitry Andric     old_value = TCR_8(*p);
4330b57cec5SDimitry Andric     new_value = old_value & d;
4340b57cec5SDimitry Andric   }
4350b57cec5SDimitry Andric   return old_value;
4360b57cec5SDimitry Andric }
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric #endif /* (KMP_ARCH_X86 || KMP_ARCH_X86_64) && (! KMP_ASM_INTRINS) */
4390b57cec5SDimitry Andric 
__kmp_terminate_thread(int gtid)4400b57cec5SDimitry Andric void __kmp_terminate_thread(int gtid) {
4410b57cec5SDimitry Andric   int status;
4420b57cec5SDimitry Andric   kmp_info_t *th = __kmp_threads[gtid];
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric   if (!th)
4450b57cec5SDimitry Andric     return;
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric #ifdef KMP_CANCEL_THREADS
4480b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_terminate_thread: kill (%d)\n", gtid));
4490b57cec5SDimitry Andric   status = pthread_cancel(th->th.th_info.ds.ds_thread);
4500b57cec5SDimitry Andric   if (status != 0 && status != ESRCH) {
4510b57cec5SDimitry Andric     __kmp_fatal(KMP_MSG(CantTerminateWorkerThread), KMP_ERR(status),
4520b57cec5SDimitry Andric                 __kmp_msg_null);
4530b57cec5SDimitry Andric   }
4540b57cec5SDimitry Andric #endif
4550b57cec5SDimitry Andric   KMP_YIELD(TRUE);
4560b57cec5SDimitry Andric } //
4570b57cec5SDimitry Andric 
458*0fca6ea1SDimitry Andric /* Set thread stack info.
4590b57cec5SDimitry Andric    If values are unreasonable, assume call failed and use incremental stack
4600b57cec5SDimitry Andric    refinement method instead. Returns TRUE if the stack parameters could be
4610b57cec5SDimitry Andric    determined exactly, FALSE if incremental refinement is necessary. */
__kmp_set_stack_info(int gtid,kmp_info_t * th)4620b57cec5SDimitry Andric static kmp_int32 __kmp_set_stack_info(int gtid, kmp_info_t *th) {
4630b57cec5SDimitry Andric   int stack_data;
4640b57cec5SDimitry Andric #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
465297eecfbSDimitry Andric     KMP_OS_HURD || KMP_OS_SOLARIS || KMP_OS_AIX
4660b57cec5SDimitry Andric   int status;
4670b57cec5SDimitry Andric   size_t size = 0;
4680b57cec5SDimitry Andric   void *addr = 0;
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric   /* Always do incremental stack refinement for ubermaster threads since the
4710b57cec5SDimitry Andric      initial thread stack range can be reduced by sibling thread creation so
4720b57cec5SDimitry Andric      pthread_attr_getstack may cause thread gtid aliasing */
4730b57cec5SDimitry Andric   if (!KMP_UBER_GTID(gtid)) {
4740b57cec5SDimitry Andric 
475*0fca6ea1SDimitry Andric #if KMP_OS_SOLARIS
476*0fca6ea1SDimitry Andric     stack_t s;
477*0fca6ea1SDimitry Andric     if ((status = thr_stksegment(&s)) < 0) {
478*0fca6ea1SDimitry Andric       KMP_CHECK_SYSFAIL("thr_stksegment", status);
479*0fca6ea1SDimitry Andric     }
480*0fca6ea1SDimitry Andric 
481*0fca6ea1SDimitry Andric     addr = s.ss_sp;
482*0fca6ea1SDimitry Andric     size = s.ss_size;
483*0fca6ea1SDimitry Andric     KA_TRACE(60, ("__kmp_set_stack_info: T#%d thr_stksegment returned size:"
484*0fca6ea1SDimitry Andric                   " %lu, low addr: %p\n",
485*0fca6ea1SDimitry Andric                   gtid, size, addr));
486*0fca6ea1SDimitry Andric #else
487*0fca6ea1SDimitry Andric     pthread_attr_t attr;
4880b57cec5SDimitry Andric     /* Fetch the real thread attributes */
4890b57cec5SDimitry Andric     status = pthread_attr_init(&attr);
4900b57cec5SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_attr_init", status);
4910b57cec5SDimitry Andric #if KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD
4920b57cec5SDimitry Andric     status = pthread_attr_get_np(pthread_self(), &attr);
4930b57cec5SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_attr_get_np", status);
4940b57cec5SDimitry Andric #else
4950b57cec5SDimitry Andric     status = pthread_getattr_np(pthread_self(), &attr);
4960b57cec5SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_getattr_np", status);
4970b57cec5SDimitry Andric #endif
4980b57cec5SDimitry Andric     status = pthread_attr_getstack(&attr, &addr, &size);
4990b57cec5SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_attr_getstack", status);
5000b57cec5SDimitry Andric     KA_TRACE(60,
5010b57cec5SDimitry Andric              ("__kmp_set_stack_info: T#%d pthread_attr_getstack returned size:"
5020b57cec5SDimitry Andric               " %lu, low addr: %p\n",
5030b57cec5SDimitry Andric               gtid, size, addr));
5040b57cec5SDimitry Andric     status = pthread_attr_destroy(&attr);
5050b57cec5SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_attr_destroy", status);
506*0fca6ea1SDimitry Andric #endif
5070b57cec5SDimitry Andric   }
5080b57cec5SDimitry Andric 
5090b57cec5SDimitry Andric   if (size != 0 && addr != 0) { // was stack parameter determination successful?
5100b57cec5SDimitry Andric     /* Store the correct base and size */
5110b57cec5SDimitry Andric     TCW_PTR(th->th.th_info.ds.ds_stackbase, (((char *)addr) + size));
5120b57cec5SDimitry Andric     TCW_PTR(th->th.th_info.ds.ds_stacksize, size);
5130b57cec5SDimitry Andric     TCW_4(th->th.th_info.ds.ds_stackgrow, FALSE);
5140b57cec5SDimitry Andric     return TRUE;
5150b57cec5SDimitry Andric   }
516fe6060f1SDimitry Andric #endif /* KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD  \
5175f757f3fSDimitry Andric           || KMP_OS_HURD || KMP_OS_SOLARIS */
5180b57cec5SDimitry Andric   /* Use incremental refinement starting from initial conservative estimate */
5190b57cec5SDimitry Andric   TCW_PTR(th->th.th_info.ds.ds_stacksize, 0);
5200b57cec5SDimitry Andric   TCW_PTR(th->th.th_info.ds.ds_stackbase, &stack_data);
5210b57cec5SDimitry Andric   TCW_4(th->th.th_info.ds.ds_stackgrow, TRUE);
5220b57cec5SDimitry Andric   return FALSE;
5230b57cec5SDimitry Andric }
5240b57cec5SDimitry Andric 
__kmp_launch_worker(void * thr)5250b57cec5SDimitry Andric static void *__kmp_launch_worker(void *thr) {
5260b57cec5SDimitry Andric   int status, old_type, old_state;
5270b57cec5SDimitry Andric #ifdef KMP_BLOCK_SIGNALS
5280b57cec5SDimitry Andric   sigset_t new_set, old_set;
5290b57cec5SDimitry Andric #endif /* KMP_BLOCK_SIGNALS */
5300b57cec5SDimitry Andric   void *exit_val;
5310b57cec5SDimitry Andric #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
532439352acSDimitry Andric     KMP_OS_OPENBSD || KMP_OS_HURD || KMP_OS_SOLARIS || KMP_OS_AIX
5330b57cec5SDimitry Andric   void *volatile padding = 0;
5340b57cec5SDimitry Andric #endif
5350b57cec5SDimitry Andric   int gtid;
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   gtid = ((kmp_info_t *)thr)->th.th_info.ds.ds_gtid;
5380b57cec5SDimitry Andric   __kmp_gtid_set_specific(gtid);
5390b57cec5SDimitry Andric #ifdef KMP_TDATA_GTID
5400b57cec5SDimitry Andric   __kmp_gtid = gtid;
5410b57cec5SDimitry Andric #endif
5420b57cec5SDimitry Andric #if KMP_STATS_ENABLED
5430b57cec5SDimitry Andric   // set thread local index to point to thread-specific stats
5440b57cec5SDimitry Andric   __kmp_stats_thread_ptr = ((kmp_info_t *)thr)->th.th_stats;
5450b57cec5SDimitry Andric   __kmp_stats_thread_ptr->startLife();
5460b57cec5SDimitry Andric   KMP_SET_THREAD_STATE(IDLE);
5470b57cec5SDimitry Andric   KMP_INIT_PARTITIONED_TIMERS(OMP_idle);
5480b57cec5SDimitry Andric #endif
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric #if USE_ITT_BUILD
5510b57cec5SDimitry Andric   __kmp_itt_thread_name(gtid);
5520b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
5555f757f3fSDimitry Andric   __kmp_affinity_bind_init_mask(gtid);
5560b57cec5SDimitry Andric #endif
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric #ifdef KMP_CANCEL_THREADS
5590b57cec5SDimitry Andric   status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_type);
5600b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_setcanceltype", status);
5610b57cec5SDimitry Andric   // josh todo: isn't PTHREAD_CANCEL_ENABLE default for newly-created threads?
5620b57cec5SDimitry Andric   status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state);
5630b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_setcancelstate", status);
5640b57cec5SDimitry Andric #endif
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
5670b57cec5SDimitry Andric   // Set FP control regs to be a copy of the parallel initialization thread's.
5680b57cec5SDimitry Andric   __kmp_clear_x87_fpu_status_word();
5690b57cec5SDimitry Andric   __kmp_load_x87_fpu_control_word(&__kmp_init_x87_fpu_control_word);
5700b57cec5SDimitry Andric   __kmp_load_mxcsr(&__kmp_init_mxcsr);
5710b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric #ifdef KMP_BLOCK_SIGNALS
5740b57cec5SDimitry Andric   status = sigfillset(&new_set);
5750b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL_ERRNO("sigfillset", status);
5760b57cec5SDimitry Andric   status = pthread_sigmask(SIG_BLOCK, &new_set, &old_set);
5770b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_sigmask", status);
5780b57cec5SDimitry Andric #endif /* KMP_BLOCK_SIGNALS */
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||     \
581439352acSDimitry Andric     KMP_OS_OPENBSD || KMP_OS_HURD || KMP_OS_SOLARIS || KMP_OS_AIX
5820b57cec5SDimitry Andric   if (__kmp_stkoffset > 0 && gtid > 0) {
5830b57cec5SDimitry Andric     padding = KMP_ALLOCA(gtid * __kmp_stkoffset);
584fe6060f1SDimitry Andric     (void)padding;
5850b57cec5SDimitry Andric   }
5860b57cec5SDimitry Andric #endif
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric   KMP_MB();
5890b57cec5SDimitry Andric   __kmp_set_stack_info(gtid, (kmp_info_t *)thr);
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric   __kmp_check_stack_overlap((kmp_info_t *)thr);
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric   exit_val = __kmp_launch_thread((kmp_info_t *)thr);
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric #ifdef KMP_BLOCK_SIGNALS
5960b57cec5SDimitry Andric   status = pthread_sigmask(SIG_SETMASK, &old_set, NULL);
5970b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_sigmask", status);
5980b57cec5SDimitry Andric #endif /* KMP_BLOCK_SIGNALS */
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric   return exit_val;
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric #if KMP_USE_MONITOR
6040b57cec5SDimitry Andric /* The monitor thread controls all of the threads in the complex */
6050b57cec5SDimitry Andric 
__kmp_launch_monitor(void * thr)6060b57cec5SDimitry Andric static void *__kmp_launch_monitor(void *thr) {
6070b57cec5SDimitry Andric   int status, old_type, old_state;
6080b57cec5SDimitry Andric #ifdef KMP_BLOCK_SIGNALS
6090b57cec5SDimitry Andric   sigset_t new_set;
6100b57cec5SDimitry Andric #endif /* KMP_BLOCK_SIGNALS */
6110b57cec5SDimitry Andric   struct timespec interval;
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_launch_monitor: #1 launched\n"));
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   /* register us as the monitor thread */
6180b57cec5SDimitry Andric   __kmp_gtid_set_specific(KMP_GTID_MONITOR);
6190b57cec5SDimitry Andric #ifdef KMP_TDATA_GTID
6200b57cec5SDimitry Andric   __kmp_gtid = KMP_GTID_MONITOR;
6210b57cec5SDimitry Andric #endif
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric   KMP_MB();
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric #if USE_ITT_BUILD
6260b57cec5SDimitry Andric   // Instruct Intel(R) Threading Tools to ignore monitor thread.
6270b57cec5SDimitry Andric   __kmp_itt_thread_ignore();
6280b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric   __kmp_set_stack_info(((kmp_info_t *)thr)->th.th_info.ds.ds_gtid,
6310b57cec5SDimitry Andric                        (kmp_info_t *)thr);
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric   __kmp_check_stack_overlap((kmp_info_t *)thr);
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric #ifdef KMP_CANCEL_THREADS
6360b57cec5SDimitry Andric   status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_type);
6370b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_setcanceltype", status);
6380b57cec5SDimitry Andric   // josh todo: isn't PTHREAD_CANCEL_ENABLE default for newly-created threads?
6390b57cec5SDimitry Andric   status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state);
6400b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_setcancelstate", status);
6410b57cec5SDimitry Andric #endif
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric #if KMP_REAL_TIME_FIX
6440b57cec5SDimitry Andric   // This is a potential fix which allows application with real-time scheduling
6450b57cec5SDimitry Andric   // policy work. However, decision about the fix is not made yet, so it is
6460b57cec5SDimitry Andric   // disabled by default.
6470b57cec5SDimitry Andric   { // Are program started with real-time scheduling policy?
6480b57cec5SDimitry Andric     int sched = sched_getscheduler(0);
6490b57cec5SDimitry Andric     if (sched == SCHED_FIFO || sched == SCHED_RR) {
6500b57cec5SDimitry Andric       // Yes, we are a part of real-time application. Try to increase the
6510b57cec5SDimitry Andric       // priority of the monitor.
6520b57cec5SDimitry Andric       struct sched_param param;
6530b57cec5SDimitry Andric       int max_priority = sched_get_priority_max(sched);
6540b57cec5SDimitry Andric       int rc;
6550b57cec5SDimitry Andric       KMP_WARNING(RealTimeSchedNotSupported);
6560b57cec5SDimitry Andric       sched_getparam(0, &param);
6570b57cec5SDimitry Andric       if (param.sched_priority < max_priority) {
6580b57cec5SDimitry Andric         param.sched_priority += 1;
6590b57cec5SDimitry Andric         rc = sched_setscheduler(0, sched, &param);
6600b57cec5SDimitry Andric         if (rc != 0) {
6610b57cec5SDimitry Andric           int error = errno;
6620b57cec5SDimitry Andric           kmp_msg_t err_code = KMP_ERR(error);
6630b57cec5SDimitry Andric           __kmp_msg(kmp_ms_warning, KMP_MSG(CantChangeMonitorPriority),
6640b57cec5SDimitry Andric                     err_code, KMP_MSG(MonitorWillStarve), __kmp_msg_null);
6650b57cec5SDimitry Andric           if (__kmp_generate_warnings == kmp_warnings_off) {
6660b57cec5SDimitry Andric             __kmp_str_free(&err_code.str);
6670b57cec5SDimitry Andric           }
6680b57cec5SDimitry Andric         }
6690b57cec5SDimitry Andric       } else {
6700b57cec5SDimitry Andric         // We cannot abort here, because number of CPUs may be enough for all
6710b57cec5SDimitry Andric         // the threads, including the monitor thread, so application could
6720b57cec5SDimitry Andric         // potentially work...
6730b57cec5SDimitry Andric         __kmp_msg(kmp_ms_warning, KMP_MSG(RunningAtMaxPriority),
6740b57cec5SDimitry Andric                   KMP_MSG(MonitorWillStarve), KMP_HNT(RunningAtMaxPriority),
6750b57cec5SDimitry Andric                   __kmp_msg_null);
6760b57cec5SDimitry Andric       }
6770b57cec5SDimitry Andric     }
6780b57cec5SDimitry Andric     // AC: free thread that waits for monitor started
6790b57cec5SDimitry Andric     TCW_4(__kmp_global.g.g_time.dt.t_value, 0);
6800b57cec5SDimitry Andric   }
6810b57cec5SDimitry Andric #endif // KMP_REAL_TIME_FIX
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
6840b57cec5SDimitry Andric 
6850b57cec5SDimitry Andric   if (__kmp_monitor_wakeups == 1) {
6860b57cec5SDimitry Andric     interval.tv_sec = 1;
6870b57cec5SDimitry Andric     interval.tv_nsec = 0;
6880b57cec5SDimitry Andric   } else {
6890b57cec5SDimitry Andric     interval.tv_sec = 0;
6900b57cec5SDimitry Andric     interval.tv_nsec = (KMP_NSEC_PER_SEC / __kmp_monitor_wakeups);
6910b57cec5SDimitry Andric   }
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_launch_monitor: #2 monitor\n"));
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric   while (!TCR_4(__kmp_global.g.g_done)) {
6960b57cec5SDimitry Andric     struct timespec now;
6970b57cec5SDimitry Andric     struct timeval tval;
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric     /*  This thread monitors the state of the system */
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric     KA_TRACE(15, ("__kmp_launch_monitor: update\n"));
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric     status = gettimeofday(&tval, NULL);
7040b57cec5SDimitry Andric     KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
7050b57cec5SDimitry Andric     TIMEVAL_TO_TIMESPEC(&tval, &now);
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric     now.tv_sec += interval.tv_sec;
7080b57cec5SDimitry Andric     now.tv_nsec += interval.tv_nsec;
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric     if (now.tv_nsec >= KMP_NSEC_PER_SEC) {
7110b57cec5SDimitry Andric       now.tv_sec += 1;
7120b57cec5SDimitry Andric       now.tv_nsec -= KMP_NSEC_PER_SEC;
7130b57cec5SDimitry Andric     }
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric     status = pthread_mutex_lock(&__kmp_wait_mx.m_mutex);
7160b57cec5SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
7170b57cec5SDimitry Andric     // AC: the monitor should not fall asleep if g_done has been set
7180b57cec5SDimitry Andric     if (!TCR_4(__kmp_global.g.g_done)) { // check once more under mutex
7190b57cec5SDimitry Andric       status = pthread_cond_timedwait(&__kmp_wait_cv.c_cond,
7200b57cec5SDimitry Andric                                       &__kmp_wait_mx.m_mutex, &now);
7210b57cec5SDimitry Andric       if (status != 0) {
7220b57cec5SDimitry Andric         if (status != ETIMEDOUT && status != EINTR) {
7230b57cec5SDimitry Andric           KMP_SYSFAIL("pthread_cond_timedwait", status);
7240b57cec5SDimitry Andric         }
7250b57cec5SDimitry Andric       }
7260b57cec5SDimitry Andric     }
7270b57cec5SDimitry Andric     status = pthread_mutex_unlock(&__kmp_wait_mx.m_mutex);
7280b57cec5SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric     TCW_4(__kmp_global.g.g_time.dt.t_value,
7310b57cec5SDimitry Andric           TCR_4(__kmp_global.g.g_time.dt.t_value) + 1);
7320b57cec5SDimitry Andric 
7330b57cec5SDimitry Andric     KMP_MB(); /* Flush all pending memory write invalidates.  */
7340b57cec5SDimitry Andric   }
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_launch_monitor: #3 cleanup\n"));
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric #ifdef KMP_BLOCK_SIGNALS
7390b57cec5SDimitry Andric   status = sigfillset(&new_set);
7400b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL_ERRNO("sigfillset", status);
7410b57cec5SDimitry Andric   status = pthread_sigmask(SIG_UNBLOCK, &new_set, NULL);
7420b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_sigmask", status);
7430b57cec5SDimitry Andric #endif /* KMP_BLOCK_SIGNALS */
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_launch_monitor: #4 finished\n"));
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric   if (__kmp_global.g.g_abort != 0) {
7480b57cec5SDimitry Andric     /* now we need to terminate the worker threads  */
7490b57cec5SDimitry Andric     /* the value of t_abort is the signal we caught */
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric     int gtid;
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_launch_monitor: #5 terminate sig=%d\n",
7540b57cec5SDimitry Andric                   __kmp_global.g.g_abort));
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric     /* terminate the OpenMP worker threads */
7570b57cec5SDimitry Andric     /* TODO this is not valid for sibling threads!!
7580b57cec5SDimitry Andric      * the uber master might not be 0 anymore.. */
7590b57cec5SDimitry Andric     for (gtid = 1; gtid < __kmp_threads_capacity; ++gtid)
7600b57cec5SDimitry Andric       __kmp_terminate_thread(gtid);
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric     __kmp_cleanup();
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_launch_monitor: #6 raise sig=%d\n",
7650b57cec5SDimitry Andric                   __kmp_global.g.g_abort));
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric     if (__kmp_global.g.g_abort > 0)
7680b57cec5SDimitry Andric       raise(__kmp_global.g.g_abort);
7690b57cec5SDimitry Andric   }
7700b57cec5SDimitry Andric 
7710b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_launch_monitor: #7 exit\n"));
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric   return thr;
7740b57cec5SDimitry Andric }
7750b57cec5SDimitry Andric #endif // KMP_USE_MONITOR
7760b57cec5SDimitry Andric 
__kmp_create_worker(int gtid,kmp_info_t * th,size_t stack_size)7770b57cec5SDimitry Andric void __kmp_create_worker(int gtid, kmp_info_t *th, size_t stack_size) {
7780b57cec5SDimitry Andric   pthread_t handle;
7790b57cec5SDimitry Andric   pthread_attr_t thread_attr;
7800b57cec5SDimitry Andric   int status;
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric   th->th.th_info.ds.ds_gtid = gtid;
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric #if KMP_STATS_ENABLED
7850b57cec5SDimitry Andric   // sets up worker thread stats
7860b57cec5SDimitry Andric   __kmp_acquire_tas_lock(&__kmp_stats_lock, gtid);
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   // th->th.th_stats is used to transfer thread-specific stats-pointer to
7890b57cec5SDimitry Andric   // __kmp_launch_worker. So when thread is created (goes into
7900b57cec5SDimitry Andric   // __kmp_launch_worker) it will set its thread local pointer to
7910b57cec5SDimitry Andric   // th->th.th_stats
7920b57cec5SDimitry Andric   if (!KMP_UBER_GTID(gtid)) {
7930b57cec5SDimitry Andric     th->th.th_stats = __kmp_stats_list->push_back(gtid);
7940b57cec5SDimitry Andric   } else {
7950b57cec5SDimitry Andric     // For root threads, __kmp_stats_thread_ptr is set in __kmp_register_root(),
7960b57cec5SDimitry Andric     // so set the th->th.th_stats field to it.
7970b57cec5SDimitry Andric     th->th.th_stats = __kmp_stats_thread_ptr;
7980b57cec5SDimitry Andric   }
7990b57cec5SDimitry Andric   __kmp_release_tas_lock(&__kmp_stats_lock, gtid);
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric #endif // KMP_STATS_ENABLED
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric   if (KMP_UBER_GTID(gtid)) {
8040b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_create_worker: uber thread (%d)\n", gtid));
8050b57cec5SDimitry Andric     th->th.th_info.ds.ds_thread = pthread_self();
8060b57cec5SDimitry Andric     __kmp_set_stack_info(gtid, th);
8070b57cec5SDimitry Andric     __kmp_check_stack_overlap(th);
8080b57cec5SDimitry Andric     return;
8090b57cec5SDimitry Andric   }
8100b57cec5SDimitry Andric 
8110b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_create_worker: try to create thread (%d)\n", gtid));
8120b57cec5SDimitry Andric 
8130b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
8140b57cec5SDimitry Andric 
8150b57cec5SDimitry Andric #ifdef KMP_THREAD_ATTR
8160b57cec5SDimitry Andric   status = pthread_attr_init(&thread_attr);
8170b57cec5SDimitry Andric   if (status != 0) {
8180b57cec5SDimitry Andric     __kmp_fatal(KMP_MSG(CantInitThreadAttrs), KMP_ERR(status), __kmp_msg_null);
8190b57cec5SDimitry Andric   }
8200b57cec5SDimitry Andric   status = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
8210b57cec5SDimitry Andric   if (status != 0) {
8220b57cec5SDimitry Andric     __kmp_fatal(KMP_MSG(CantSetWorkerState), KMP_ERR(status), __kmp_msg_null);
8230b57cec5SDimitry Andric   }
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric   /* Set stack size for this thread now.
8260b57cec5SDimitry Andric      The multiple of 2 is there because on some machines, requesting an unusual
8270b57cec5SDimitry Andric      stacksize causes the thread to have an offset before the dummy alloca()
8280b57cec5SDimitry Andric      takes place to create the offset.  Since we want the user to have a
8290b57cec5SDimitry Andric      sufficient stacksize AND support a stack offset, we alloca() twice the
8300b57cec5SDimitry Andric      offset so that the upcoming alloca() does not eliminate any premade offset,
8310b57cec5SDimitry Andric      and also gives the user the stack space they requested for all threads */
8320b57cec5SDimitry Andric   stack_size += gtid * __kmp_stkoffset * 2;
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_create_worker: T#%d, default stacksize = %lu bytes, "
8350b57cec5SDimitry Andric                 "__kmp_stksize = %lu bytes, final stacksize = %lu bytes\n",
8360b57cec5SDimitry Andric                 gtid, KMP_DEFAULT_STKSIZE, __kmp_stksize, stack_size));
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric #ifdef _POSIX_THREAD_ATTR_STACKSIZE
8390b57cec5SDimitry Andric   status = pthread_attr_setstacksize(&thread_attr, stack_size);
8400b57cec5SDimitry Andric #ifdef KMP_BACKUP_STKSIZE
8410b57cec5SDimitry Andric   if (status != 0) {
8420b57cec5SDimitry Andric     if (!__kmp_env_stksize) {
8430b57cec5SDimitry Andric       stack_size = KMP_BACKUP_STKSIZE + gtid * __kmp_stkoffset;
8440b57cec5SDimitry Andric       __kmp_stksize = KMP_BACKUP_STKSIZE;
8450b57cec5SDimitry Andric       KA_TRACE(10, ("__kmp_create_worker: T#%d, default stacksize = %lu bytes, "
8460b57cec5SDimitry Andric                     "__kmp_stksize = %lu bytes, (backup) final stacksize = %lu "
8470b57cec5SDimitry Andric                     "bytes\n",
8480b57cec5SDimitry Andric                     gtid, KMP_DEFAULT_STKSIZE, __kmp_stksize, stack_size));
8490b57cec5SDimitry Andric       status = pthread_attr_setstacksize(&thread_attr, stack_size);
8500b57cec5SDimitry Andric     }
8510b57cec5SDimitry Andric   }
8520b57cec5SDimitry Andric #endif /* KMP_BACKUP_STKSIZE */
8530b57cec5SDimitry Andric   if (status != 0) {
8540b57cec5SDimitry Andric     __kmp_fatal(KMP_MSG(CantSetWorkerStackSize, stack_size), KMP_ERR(status),
8550b57cec5SDimitry Andric                 KMP_HNT(ChangeWorkerStackSize), __kmp_msg_null);
8560b57cec5SDimitry Andric   }
8570b57cec5SDimitry Andric #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric #endif /* KMP_THREAD_ATTR */
8600b57cec5SDimitry Andric 
8610b57cec5SDimitry Andric   status =
8620b57cec5SDimitry Andric       pthread_create(&handle, &thread_attr, __kmp_launch_worker, (void *)th);
8630b57cec5SDimitry Andric   if (status != 0 || !handle) { // ??? Why do we check handle??
8640b57cec5SDimitry Andric #ifdef _POSIX_THREAD_ATTR_STACKSIZE
8650b57cec5SDimitry Andric     if (status == EINVAL) {
8660b57cec5SDimitry Andric       __kmp_fatal(KMP_MSG(CantSetWorkerStackSize, stack_size), KMP_ERR(status),
8670b57cec5SDimitry Andric                   KMP_HNT(IncreaseWorkerStackSize), __kmp_msg_null);
8680b57cec5SDimitry Andric     }
8690b57cec5SDimitry Andric     if (status == ENOMEM) {
8700b57cec5SDimitry Andric       __kmp_fatal(KMP_MSG(CantSetWorkerStackSize, stack_size), KMP_ERR(status),
8710b57cec5SDimitry Andric                   KMP_HNT(DecreaseWorkerStackSize), __kmp_msg_null);
8720b57cec5SDimitry Andric     }
8730b57cec5SDimitry Andric #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
8740b57cec5SDimitry Andric     if (status == EAGAIN) {
8750b57cec5SDimitry Andric       __kmp_fatal(KMP_MSG(NoResourcesForWorkerThread), KMP_ERR(status),
8760b57cec5SDimitry Andric                   KMP_HNT(Decrease_NUM_THREADS), __kmp_msg_null);
8770b57cec5SDimitry Andric     }
8780b57cec5SDimitry Andric     KMP_SYSFAIL("pthread_create", status);
8790b57cec5SDimitry Andric   }
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric   th->th.th_info.ds.ds_thread = handle;
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric #ifdef KMP_THREAD_ATTR
8840b57cec5SDimitry Andric   status = pthread_attr_destroy(&thread_attr);
8850b57cec5SDimitry Andric   if (status) {
8860b57cec5SDimitry Andric     kmp_msg_t err_code = KMP_ERR(status);
8870b57cec5SDimitry Andric     __kmp_msg(kmp_ms_warning, KMP_MSG(CantDestroyThreadAttrs), err_code,
8880b57cec5SDimitry Andric               __kmp_msg_null);
8890b57cec5SDimitry Andric     if (__kmp_generate_warnings == kmp_warnings_off) {
8900b57cec5SDimitry Andric       __kmp_str_free(&err_code.str);
8910b57cec5SDimitry Andric     }
8920b57cec5SDimitry Andric   }
8930b57cec5SDimitry Andric #endif /* KMP_THREAD_ATTR */
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
8960b57cec5SDimitry Andric 
8970b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_create_worker: done creating thread (%d)\n", gtid));
8980b57cec5SDimitry Andric 
8990b57cec5SDimitry Andric } // __kmp_create_worker
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric #if KMP_USE_MONITOR
__kmp_create_monitor(kmp_info_t * th)9020b57cec5SDimitry Andric void __kmp_create_monitor(kmp_info_t *th) {
9030b57cec5SDimitry Andric   pthread_t handle;
9040b57cec5SDimitry Andric   pthread_attr_t thread_attr;
9050b57cec5SDimitry Andric   size_t size;
9060b57cec5SDimitry Andric   int status;
9070b57cec5SDimitry Andric   int auto_adj_size = FALSE;
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric   if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME) {
9100b57cec5SDimitry Andric     // We don't need monitor thread in case of MAX_BLOCKTIME
9110b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_create_monitor: skipping monitor thread because of "
9120b57cec5SDimitry Andric                   "MAX blocktime\n"));
9130b57cec5SDimitry Andric     th->th.th_info.ds.ds_tid = 0; // this makes reap_monitor no-op
9140b57cec5SDimitry Andric     th->th.th_info.ds.ds_gtid = 0;
9150b57cec5SDimitry Andric     return;
9160b57cec5SDimitry Andric   }
9170b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_create_monitor: try to create monitor\n"));
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
9200b57cec5SDimitry Andric 
9210b57cec5SDimitry Andric   th->th.th_info.ds.ds_tid = KMP_GTID_MONITOR;
9220b57cec5SDimitry Andric   th->th.th_info.ds.ds_gtid = KMP_GTID_MONITOR;
9230b57cec5SDimitry Andric #if KMP_REAL_TIME_FIX
9240b57cec5SDimitry Andric   TCW_4(__kmp_global.g.g_time.dt.t_value,
9250b57cec5SDimitry Andric         -1); // Will use it for synchronization a bit later.
9260b57cec5SDimitry Andric #else
9270b57cec5SDimitry Andric   TCW_4(__kmp_global.g.g_time.dt.t_value, 0);
9280b57cec5SDimitry Andric #endif // KMP_REAL_TIME_FIX
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric #ifdef KMP_THREAD_ATTR
9310b57cec5SDimitry Andric   if (__kmp_monitor_stksize == 0) {
9320b57cec5SDimitry Andric     __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE;
9330b57cec5SDimitry Andric     auto_adj_size = TRUE;
9340b57cec5SDimitry Andric   }
9350b57cec5SDimitry Andric   status = pthread_attr_init(&thread_attr);
9360b57cec5SDimitry Andric   if (status != 0) {
9370b57cec5SDimitry Andric     __kmp_fatal(KMP_MSG(CantInitThreadAttrs), KMP_ERR(status), __kmp_msg_null);
9380b57cec5SDimitry Andric   }
9390b57cec5SDimitry Andric   status = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
9400b57cec5SDimitry Andric   if (status != 0) {
9410b57cec5SDimitry Andric     __kmp_fatal(KMP_MSG(CantSetMonitorState), KMP_ERR(status), __kmp_msg_null);
9420b57cec5SDimitry Andric   }
9430b57cec5SDimitry Andric 
9440b57cec5SDimitry Andric #ifdef _POSIX_THREAD_ATTR_STACKSIZE
9450b57cec5SDimitry Andric   status = pthread_attr_getstacksize(&thread_attr, &size);
9460b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_attr_getstacksize", status);
9470b57cec5SDimitry Andric #else
9480b57cec5SDimitry Andric   size = __kmp_sys_min_stksize;
9490b57cec5SDimitry Andric #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
9500b57cec5SDimitry Andric #endif /* KMP_THREAD_ATTR */
9510b57cec5SDimitry Andric 
9520b57cec5SDimitry Andric   if (__kmp_monitor_stksize == 0) {
9530b57cec5SDimitry Andric     __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE;
9540b57cec5SDimitry Andric   }
9550b57cec5SDimitry Andric   if (__kmp_monitor_stksize < __kmp_sys_min_stksize) {
9560b57cec5SDimitry Andric     __kmp_monitor_stksize = __kmp_sys_min_stksize;
9570b57cec5SDimitry Andric   }
9580b57cec5SDimitry Andric 
9590b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_create_monitor: default stacksize = %lu bytes,"
9600b57cec5SDimitry Andric                 "requested stacksize = %lu bytes\n",
9610b57cec5SDimitry Andric                 size, __kmp_monitor_stksize));
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric retry:
9640b57cec5SDimitry Andric 
9650b57cec5SDimitry Andric /* Set stack size for this thread now. */
9660b57cec5SDimitry Andric #ifdef _POSIX_THREAD_ATTR_STACKSIZE
9670b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_create_monitor: setting stacksize = %lu bytes,",
9680b57cec5SDimitry Andric                 __kmp_monitor_stksize));
9690b57cec5SDimitry Andric   status = pthread_attr_setstacksize(&thread_attr, __kmp_monitor_stksize);
9700b57cec5SDimitry Andric   if (status != 0) {
9710b57cec5SDimitry Andric     if (auto_adj_size) {
9720b57cec5SDimitry Andric       __kmp_monitor_stksize *= 2;
9730b57cec5SDimitry Andric       goto retry;
9740b57cec5SDimitry Andric     }
9750b57cec5SDimitry Andric     kmp_msg_t err_code = KMP_ERR(status);
9760b57cec5SDimitry Andric     __kmp_msg(kmp_ms_warning, // should this be fatal?  BB
9770b57cec5SDimitry Andric               KMP_MSG(CantSetMonitorStackSize, (long int)__kmp_monitor_stksize),
9780b57cec5SDimitry Andric               err_code, KMP_HNT(ChangeMonitorStackSize), __kmp_msg_null);
9790b57cec5SDimitry Andric     if (__kmp_generate_warnings == kmp_warnings_off) {
9800b57cec5SDimitry Andric       __kmp_str_free(&err_code.str);
9810b57cec5SDimitry Andric     }
9820b57cec5SDimitry Andric   }
9830b57cec5SDimitry Andric #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric   status =
9860b57cec5SDimitry Andric       pthread_create(&handle, &thread_attr, __kmp_launch_monitor, (void *)th);
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric   if (status != 0) {
9890b57cec5SDimitry Andric #ifdef _POSIX_THREAD_ATTR_STACKSIZE
9900b57cec5SDimitry Andric     if (status == EINVAL) {
9910b57cec5SDimitry Andric       if (auto_adj_size && (__kmp_monitor_stksize < (size_t)0x40000000)) {
9920b57cec5SDimitry Andric         __kmp_monitor_stksize *= 2;
9930b57cec5SDimitry Andric         goto retry;
9940b57cec5SDimitry Andric       }
9950b57cec5SDimitry Andric       __kmp_fatal(KMP_MSG(CantSetMonitorStackSize, __kmp_monitor_stksize),
9960b57cec5SDimitry Andric                   KMP_ERR(status), KMP_HNT(IncreaseMonitorStackSize),
9970b57cec5SDimitry Andric                   __kmp_msg_null);
9980b57cec5SDimitry Andric     }
9990b57cec5SDimitry Andric     if (status == ENOMEM) {
10000b57cec5SDimitry Andric       __kmp_fatal(KMP_MSG(CantSetMonitorStackSize, __kmp_monitor_stksize),
10010b57cec5SDimitry Andric                   KMP_ERR(status), KMP_HNT(DecreaseMonitorStackSize),
10020b57cec5SDimitry Andric                   __kmp_msg_null);
10030b57cec5SDimitry Andric     }
10040b57cec5SDimitry Andric #endif /* _POSIX_THREAD_ATTR_STACKSIZE */
10050b57cec5SDimitry Andric     if (status == EAGAIN) {
10060b57cec5SDimitry Andric       __kmp_fatal(KMP_MSG(NoResourcesForMonitorThread), KMP_ERR(status),
10070b57cec5SDimitry Andric                   KMP_HNT(DecreaseNumberOfThreadsInUse), __kmp_msg_null);
10080b57cec5SDimitry Andric     }
10090b57cec5SDimitry Andric     KMP_SYSFAIL("pthread_create", status);
10100b57cec5SDimitry Andric   }
10110b57cec5SDimitry Andric 
10120b57cec5SDimitry Andric   th->th.th_info.ds.ds_thread = handle;
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric #if KMP_REAL_TIME_FIX
10150b57cec5SDimitry Andric   // Wait for the monitor thread is really started and set its *priority*.
10160b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(sizeof(kmp_uint32) ==
10170b57cec5SDimitry Andric                    sizeof(__kmp_global.g.g_time.dt.t_value));
10180b57cec5SDimitry Andric   __kmp_wait_4((kmp_uint32 volatile *)&__kmp_global.g.g_time.dt.t_value, -1,
10190b57cec5SDimitry Andric                &__kmp_neq_4, NULL);
10200b57cec5SDimitry Andric #endif // KMP_REAL_TIME_FIX
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric #ifdef KMP_THREAD_ATTR
10230b57cec5SDimitry Andric   status = pthread_attr_destroy(&thread_attr);
10240b57cec5SDimitry Andric   if (status != 0) {
10250b57cec5SDimitry Andric     kmp_msg_t err_code = KMP_ERR(status);
10260b57cec5SDimitry Andric     __kmp_msg(kmp_ms_warning, KMP_MSG(CantDestroyThreadAttrs), err_code,
10270b57cec5SDimitry Andric               __kmp_msg_null);
10280b57cec5SDimitry Andric     if (__kmp_generate_warnings == kmp_warnings_off) {
10290b57cec5SDimitry Andric       __kmp_str_free(&err_code.str);
10300b57cec5SDimitry Andric     }
10310b57cec5SDimitry Andric   }
10320b57cec5SDimitry Andric #endif
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
10350b57cec5SDimitry Andric 
10360b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_create_monitor: monitor created %#.8lx\n",
10370b57cec5SDimitry Andric                 th->th.th_info.ds.ds_thread));
10380b57cec5SDimitry Andric 
10390b57cec5SDimitry Andric } // __kmp_create_monitor
10400b57cec5SDimitry Andric #endif // KMP_USE_MONITOR
10410b57cec5SDimitry Andric 
__kmp_exit_thread(int exit_status)10420b57cec5SDimitry Andric void __kmp_exit_thread(int exit_status) {
10435f757f3fSDimitry Andric #if KMP_OS_WASI
10445f757f3fSDimitry Andric // TODO: the wasm32-wasi-threads target does not yet support pthread_exit.
10455f757f3fSDimitry Andric #else
10460b57cec5SDimitry Andric   pthread_exit((void *)(intptr_t)exit_status);
10475f757f3fSDimitry Andric #endif
10480b57cec5SDimitry Andric } // __kmp_exit_thread
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric #if KMP_USE_MONITOR
10510b57cec5SDimitry Andric void __kmp_resume_monitor();
10520b57cec5SDimitry Andric 
__kmp_reap_monitor(kmp_info_t * th)1053bdd1243dSDimitry Andric extern "C" void __kmp_reap_monitor(kmp_info_t *th) {
10540b57cec5SDimitry Andric   int status;
10550b57cec5SDimitry Andric   void *exit_val;
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_reap_monitor: try to reap monitor thread with handle"
10580b57cec5SDimitry Andric                 " %#.8lx\n",
10590b57cec5SDimitry Andric                 th->th.th_info.ds.ds_thread));
10600b57cec5SDimitry Andric 
10610b57cec5SDimitry Andric   // If monitor has been created, its tid and gtid should be KMP_GTID_MONITOR.
10620b57cec5SDimitry Andric   // If both tid and gtid are 0, it means the monitor did not ever start.
10630b57cec5SDimitry Andric   // If both tid and gtid are KMP_GTID_DNE, the monitor has been shut down.
10640b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(th->th.th_info.ds.ds_tid == th->th.th_info.ds.ds_gtid);
10650b57cec5SDimitry Andric   if (th->th.th_info.ds.ds_gtid != KMP_GTID_MONITOR) {
10660b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_reap_monitor: monitor did not start, returning\n"));
10670b57cec5SDimitry Andric     return;
10680b57cec5SDimitry Andric   }
10690b57cec5SDimitry Andric 
10700b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
10710b57cec5SDimitry Andric 
10720b57cec5SDimitry Andric   /* First, check to see whether the monitor thread exists to wake it up. This
10730b57cec5SDimitry Andric      is to avoid performance problem when the monitor sleeps during
10740b57cec5SDimitry Andric      blocktime-size interval */
10750b57cec5SDimitry Andric 
10760b57cec5SDimitry Andric   status = pthread_kill(th->th.th_info.ds.ds_thread, 0);
10770b57cec5SDimitry Andric   if (status != ESRCH) {
10780b57cec5SDimitry Andric     __kmp_resume_monitor(); // Wake up the monitor thread
10790b57cec5SDimitry Andric   }
10800b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_reap_monitor: try to join with monitor\n"));
10810b57cec5SDimitry Andric   status = pthread_join(th->th.th_info.ds.ds_thread, &exit_val);
10820b57cec5SDimitry Andric   if (exit_val != th) {
10830b57cec5SDimitry Andric     __kmp_fatal(KMP_MSG(ReapMonitorError), KMP_ERR(status), __kmp_msg_null);
10840b57cec5SDimitry Andric   }
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric   th->th.th_info.ds.ds_tid = KMP_GTID_DNE;
10870b57cec5SDimitry Andric   th->th.th_info.ds.ds_gtid = KMP_GTID_DNE;
10880b57cec5SDimitry Andric 
10890b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_reap_monitor: done reaping monitor thread with handle"
10900b57cec5SDimitry Andric                 " %#.8lx\n",
10910b57cec5SDimitry Andric                 th->th.th_info.ds.ds_thread));
10920b57cec5SDimitry Andric 
10930b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
10940b57cec5SDimitry Andric }
1095bdd1243dSDimitry Andric #else
1096bdd1243dSDimitry Andric // Empty symbol to export (see exports_so.txt) when
1097bdd1243dSDimitry Andric // monitor thread feature is disabled
__kmp_reap_monitor(kmp_info_t * th)1098*0fca6ea1SDimitry Andric extern "C" void __kmp_reap_monitor(kmp_info_t *th) { (void)th; }
10990b57cec5SDimitry Andric #endif // KMP_USE_MONITOR
11000b57cec5SDimitry Andric 
__kmp_reap_worker(kmp_info_t * th)11010b57cec5SDimitry Andric void __kmp_reap_worker(kmp_info_t *th) {
11020b57cec5SDimitry Andric   int status;
11030b57cec5SDimitry Andric   void *exit_val;
11040b57cec5SDimitry Andric 
11050b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   KA_TRACE(
11080b57cec5SDimitry Andric       10, ("__kmp_reap_worker: try to reap T#%d\n", th->th.th_info.ds.ds_gtid));
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric   status = pthread_join(th->th.th_info.ds.ds_thread, &exit_val);
11110b57cec5SDimitry Andric #ifdef KMP_DEBUG
11120b57cec5SDimitry Andric   /* Don't expose these to the user until we understand when they trigger */
11130b57cec5SDimitry Andric   if (status != 0) {
11140b57cec5SDimitry Andric     __kmp_fatal(KMP_MSG(ReapWorkerError), KMP_ERR(status), __kmp_msg_null);
11150b57cec5SDimitry Andric   }
11160b57cec5SDimitry Andric   if (exit_val != th) {
11170b57cec5SDimitry Andric     KA_TRACE(10, ("__kmp_reap_worker: worker T#%d did not reap properly, "
11180b57cec5SDimitry Andric                   "exit_val = %p\n",
11190b57cec5SDimitry Andric                   th->th.th_info.ds.ds_gtid, exit_val));
11200b57cec5SDimitry Andric   }
1121349cc55cSDimitry Andric #else
1122349cc55cSDimitry Andric   (void)status; // unused variable
11230b57cec5SDimitry Andric #endif /* KMP_DEBUG */
11240b57cec5SDimitry Andric 
11250b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_reap_worker: done reaping T#%d\n",
11260b57cec5SDimitry Andric                 th->th.th_info.ds.ds_gtid));
11270b57cec5SDimitry Andric 
11280b57cec5SDimitry Andric   KMP_MB(); /* Flush all pending memory write invalidates.  */
11290b57cec5SDimitry Andric }
11300b57cec5SDimitry Andric 
11310b57cec5SDimitry Andric #if KMP_HANDLE_SIGNALS
11320b57cec5SDimitry Andric 
__kmp_null_handler(int signo)11330b57cec5SDimitry Andric static void __kmp_null_handler(int signo) {
11340b57cec5SDimitry Andric   //  Do nothing, for doing SIG_IGN-type actions.
11350b57cec5SDimitry Andric } // __kmp_null_handler
11360b57cec5SDimitry Andric 
__kmp_team_handler(int signo)11370b57cec5SDimitry Andric static void __kmp_team_handler(int signo) {
11380b57cec5SDimitry Andric   if (__kmp_global.g.g_abort == 0) {
11390b57cec5SDimitry Andric /* Stage 1 signal handler, let's shut down all of the threads */
11400b57cec5SDimitry Andric #ifdef KMP_DEBUG
11410b57cec5SDimitry Andric     __kmp_debug_printf("__kmp_team_handler: caught signal = %d\n", signo);
11420b57cec5SDimitry Andric #endif
11430b57cec5SDimitry Andric     switch (signo) {
11440b57cec5SDimitry Andric     case SIGHUP:
11450b57cec5SDimitry Andric     case SIGINT:
11460b57cec5SDimitry Andric     case SIGQUIT:
11470b57cec5SDimitry Andric     case SIGILL:
11480b57cec5SDimitry Andric     case SIGABRT:
11490b57cec5SDimitry Andric     case SIGFPE:
11500b57cec5SDimitry Andric     case SIGBUS:
11510b57cec5SDimitry Andric     case SIGSEGV:
11520b57cec5SDimitry Andric #ifdef SIGSYS
11530b57cec5SDimitry Andric     case SIGSYS:
11540b57cec5SDimitry Andric #endif
11550b57cec5SDimitry Andric     case SIGTERM:
11560b57cec5SDimitry Andric       if (__kmp_debug_buf) {
11570b57cec5SDimitry Andric         __kmp_dump_debug_buffer();
11580b57cec5SDimitry Andric       }
1159e8d8bef9SDimitry Andric       __kmp_unregister_library(); // cleanup shared memory
11600b57cec5SDimitry Andric       KMP_MB(); // Flush all pending memory write invalidates.
11610b57cec5SDimitry Andric       TCW_4(__kmp_global.g.g_abort, signo);
11620b57cec5SDimitry Andric       KMP_MB(); // Flush all pending memory write invalidates.
11630b57cec5SDimitry Andric       TCW_4(__kmp_global.g.g_done, TRUE);
11640b57cec5SDimitry Andric       KMP_MB(); // Flush all pending memory write invalidates.
11650b57cec5SDimitry Andric       break;
11660b57cec5SDimitry Andric     default:
11670b57cec5SDimitry Andric #ifdef KMP_DEBUG
11680b57cec5SDimitry Andric       __kmp_debug_printf("__kmp_team_handler: unknown signal type");
11690b57cec5SDimitry Andric #endif
11700b57cec5SDimitry Andric       break;
11710b57cec5SDimitry Andric     }
11720b57cec5SDimitry Andric   }
11730b57cec5SDimitry Andric } // __kmp_team_handler
11740b57cec5SDimitry Andric 
__kmp_sigaction(int signum,const struct sigaction * act,struct sigaction * oldact)11750b57cec5SDimitry Andric static void __kmp_sigaction(int signum, const struct sigaction *act,
11760b57cec5SDimitry Andric                             struct sigaction *oldact) {
11770b57cec5SDimitry Andric   int rc = sigaction(signum, act, oldact);
11780b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL_ERRNO("sigaction", rc);
11790b57cec5SDimitry Andric }
11800b57cec5SDimitry Andric 
__kmp_install_one_handler(int sig,sig_func_t handler_func,int parallel_init)11810b57cec5SDimitry Andric static void __kmp_install_one_handler(int sig, sig_func_t handler_func,
11820b57cec5SDimitry Andric                                       int parallel_init) {
11830b57cec5SDimitry Andric   KMP_MB(); // Flush all pending memory write invalidates.
11840b57cec5SDimitry Andric   KB_TRACE(60,
11850b57cec5SDimitry Andric            ("__kmp_install_one_handler( %d, ..., %d )\n", sig, parallel_init));
11860b57cec5SDimitry Andric   if (parallel_init) {
11870b57cec5SDimitry Andric     struct sigaction new_action;
11880b57cec5SDimitry Andric     struct sigaction old_action;
11890b57cec5SDimitry Andric     new_action.sa_handler = handler_func;
11900b57cec5SDimitry Andric     new_action.sa_flags = 0;
11910b57cec5SDimitry Andric     sigfillset(&new_action.sa_mask);
11920b57cec5SDimitry Andric     __kmp_sigaction(sig, &new_action, &old_action);
11930b57cec5SDimitry Andric     if (old_action.sa_handler == __kmp_sighldrs[sig].sa_handler) {
11940b57cec5SDimitry Andric       sigaddset(&__kmp_sigset, sig);
11950b57cec5SDimitry Andric     } else {
11960b57cec5SDimitry Andric       // Restore/keep user's handler if one previously installed.
11970b57cec5SDimitry Andric       __kmp_sigaction(sig, &old_action, NULL);
11980b57cec5SDimitry Andric     }
11990b57cec5SDimitry Andric   } else {
12000b57cec5SDimitry Andric     // Save initial/system signal handlers to see if user handlers installed.
12010b57cec5SDimitry Andric     __kmp_sigaction(sig, NULL, &__kmp_sighldrs[sig]);
12020b57cec5SDimitry Andric   }
12030b57cec5SDimitry Andric   KMP_MB(); // Flush all pending memory write invalidates.
12040b57cec5SDimitry Andric } // __kmp_install_one_handler
12050b57cec5SDimitry Andric 
__kmp_remove_one_handler(int sig)12060b57cec5SDimitry Andric static void __kmp_remove_one_handler(int sig) {
12070b57cec5SDimitry Andric   KB_TRACE(60, ("__kmp_remove_one_handler( %d )\n", sig));
12080b57cec5SDimitry Andric   if (sigismember(&__kmp_sigset, sig)) {
12090b57cec5SDimitry Andric     struct sigaction old;
12100b57cec5SDimitry Andric     KMP_MB(); // Flush all pending memory write invalidates.
12110b57cec5SDimitry Andric     __kmp_sigaction(sig, &__kmp_sighldrs[sig], &old);
12120b57cec5SDimitry Andric     if ((old.sa_handler != __kmp_team_handler) &&
12130b57cec5SDimitry Andric         (old.sa_handler != __kmp_null_handler)) {
12140b57cec5SDimitry Andric       // Restore the users signal handler.
12150b57cec5SDimitry Andric       KB_TRACE(10, ("__kmp_remove_one_handler: oops, not our handler, "
12160b57cec5SDimitry Andric                     "restoring: sig=%d\n",
12170b57cec5SDimitry Andric                     sig));
12180b57cec5SDimitry Andric       __kmp_sigaction(sig, &old, NULL);
12190b57cec5SDimitry Andric     }
12200b57cec5SDimitry Andric     sigdelset(&__kmp_sigset, sig);
12210b57cec5SDimitry Andric     KMP_MB(); // Flush all pending memory write invalidates.
12220b57cec5SDimitry Andric   }
12230b57cec5SDimitry Andric } // __kmp_remove_one_handler
12240b57cec5SDimitry Andric 
__kmp_install_signals(int parallel_init)12250b57cec5SDimitry Andric void __kmp_install_signals(int parallel_init) {
12260b57cec5SDimitry Andric   KB_TRACE(10, ("__kmp_install_signals( %d )\n", parallel_init));
12270b57cec5SDimitry Andric   if (__kmp_handle_signals || !parallel_init) {
12280b57cec5SDimitry Andric     // If ! parallel_init, we do not install handlers, just save original
12290b57cec5SDimitry Andric     // handlers. Let us do it even __handle_signals is 0.
12300b57cec5SDimitry Andric     sigemptyset(&__kmp_sigset);
12310b57cec5SDimitry Andric     __kmp_install_one_handler(SIGHUP, __kmp_team_handler, parallel_init);
12320b57cec5SDimitry Andric     __kmp_install_one_handler(SIGINT, __kmp_team_handler, parallel_init);
12330b57cec5SDimitry Andric     __kmp_install_one_handler(SIGQUIT, __kmp_team_handler, parallel_init);
12340b57cec5SDimitry Andric     __kmp_install_one_handler(SIGILL, __kmp_team_handler, parallel_init);
12350b57cec5SDimitry Andric     __kmp_install_one_handler(SIGABRT, __kmp_team_handler, parallel_init);
12360b57cec5SDimitry Andric     __kmp_install_one_handler(SIGFPE, __kmp_team_handler, parallel_init);
12370b57cec5SDimitry Andric     __kmp_install_one_handler(SIGBUS, __kmp_team_handler, parallel_init);
12380b57cec5SDimitry Andric     __kmp_install_one_handler(SIGSEGV, __kmp_team_handler, parallel_init);
12390b57cec5SDimitry Andric #ifdef SIGSYS
12400b57cec5SDimitry Andric     __kmp_install_one_handler(SIGSYS, __kmp_team_handler, parallel_init);
12410b57cec5SDimitry Andric #endif // SIGSYS
12420b57cec5SDimitry Andric     __kmp_install_one_handler(SIGTERM, __kmp_team_handler, parallel_init);
12430b57cec5SDimitry Andric #ifdef SIGPIPE
12440b57cec5SDimitry Andric     __kmp_install_one_handler(SIGPIPE, __kmp_team_handler, parallel_init);
12450b57cec5SDimitry Andric #endif // SIGPIPE
12460b57cec5SDimitry Andric   }
12470b57cec5SDimitry Andric } // __kmp_install_signals
12480b57cec5SDimitry Andric 
__kmp_remove_signals(void)12490b57cec5SDimitry Andric void __kmp_remove_signals(void) {
12500b57cec5SDimitry Andric   int sig;
12510b57cec5SDimitry Andric   KB_TRACE(10, ("__kmp_remove_signals()\n"));
12520b57cec5SDimitry Andric   for (sig = 1; sig < NSIG; ++sig) {
12530b57cec5SDimitry Andric     __kmp_remove_one_handler(sig);
12540b57cec5SDimitry Andric   }
12550b57cec5SDimitry Andric } // __kmp_remove_signals
12560b57cec5SDimitry Andric 
12570b57cec5SDimitry Andric #endif // KMP_HANDLE_SIGNALS
12580b57cec5SDimitry Andric 
__kmp_enable(int new_state)12590b57cec5SDimitry Andric void __kmp_enable(int new_state) {
12600b57cec5SDimitry Andric #ifdef KMP_CANCEL_THREADS
12610b57cec5SDimitry Andric   int status, old_state;
12620b57cec5SDimitry Andric   status = pthread_setcancelstate(new_state, &old_state);
12630b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_setcancelstate", status);
12640b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(old_state == PTHREAD_CANCEL_DISABLE);
12650b57cec5SDimitry Andric #endif
12660b57cec5SDimitry Andric }
12670b57cec5SDimitry Andric 
__kmp_disable(int * old_state)12680b57cec5SDimitry Andric void __kmp_disable(int *old_state) {
12690b57cec5SDimitry Andric #ifdef KMP_CANCEL_THREADS
12700b57cec5SDimitry Andric   int status;
12710b57cec5SDimitry Andric   status = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, old_state);
12720b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_setcancelstate", status);
12730b57cec5SDimitry Andric #endif
12740b57cec5SDimitry Andric }
12750b57cec5SDimitry Andric 
__kmp_atfork_prepare(void)12760b57cec5SDimitry Andric static void __kmp_atfork_prepare(void) {
12770b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_initz_lock);
12780b57cec5SDimitry Andric   __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock);
12790b57cec5SDimitry Andric }
12800b57cec5SDimitry Andric 
__kmp_atfork_parent(void)12810b57cec5SDimitry Andric static void __kmp_atfork_parent(void) {
12820b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
1283e8d8bef9SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
12840b57cec5SDimitry Andric }
12850b57cec5SDimitry Andric 
12860b57cec5SDimitry Andric /* Reset the library so execution in the child starts "all over again" with
12870b57cec5SDimitry Andric    clean data structures in initial states.  Don't worry about freeing memory
12880b57cec5SDimitry Andric    allocated by parent, just abandon it to be safe. */
__kmp_atfork_child(void)12890b57cec5SDimitry Andric static void __kmp_atfork_child(void) {
12900b57cec5SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock);
1291e8d8bef9SDimitry Andric   __kmp_release_bootstrap_lock(&__kmp_initz_lock);
12920b57cec5SDimitry Andric   /* TODO make sure this is done right for nested/sibling */
12930b57cec5SDimitry Andric   // ATT:  Memory leaks are here? TODO: Check it and fix.
12940b57cec5SDimitry Andric   /* KMP_ASSERT( 0 ); */
12950b57cec5SDimitry Andric 
12960b57cec5SDimitry Andric   ++__kmp_fork_count;
12970b57cec5SDimitry Andric 
12980b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
1299*0fca6ea1SDimitry Andric #if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY ||     \
1300*0fca6ea1SDimitry Andric     KMP_OS_AIX
13010b57cec5SDimitry Andric   // reset the affinity in the child to the initial thread
13020b57cec5SDimitry Andric   // affinity in the parent
13030b57cec5SDimitry Andric   kmp_set_thread_affinity_mask_initial();
13040b57cec5SDimitry Andric #endif
1305349cc55cSDimitry Andric   // Set default not to bind threads tightly in the child (we're expecting
13060b57cec5SDimitry Andric   // over-subscription after the fork and this can improve things for
13070b57cec5SDimitry Andric   // scripting languages that use OpenMP inside process-parallel code).
13080b57cec5SDimitry Andric   if (__kmp_nested_proc_bind.bind_types != NULL) {
13090b57cec5SDimitry Andric     __kmp_nested_proc_bind.bind_types[0] = proc_bind_false;
13100b57cec5SDimitry Andric   }
1311bdd1243dSDimitry Andric   for (kmp_affinity_t *affinity : __kmp_affinities)
1312bdd1243dSDimitry Andric     *affinity = KMP_AFFINITY_INIT(affinity->env_var);
1313bdd1243dSDimitry Andric   __kmp_affin_fullMask = nullptr;
1314bdd1243dSDimitry Andric   __kmp_affin_origMask = nullptr;
13155f757f3fSDimitry Andric   __kmp_topology = nullptr;
13160b57cec5SDimitry Andric #endif // KMP_AFFINITY_SUPPORTED
13170b57cec5SDimitry Andric 
13180b57cec5SDimitry Andric #if KMP_USE_MONITOR
13190b57cec5SDimitry Andric   __kmp_init_monitor = 0;
13200b57cec5SDimitry Andric #endif
13210b57cec5SDimitry Andric   __kmp_init_parallel = FALSE;
13220b57cec5SDimitry Andric   __kmp_init_middle = FALSE;
13230b57cec5SDimitry Andric   __kmp_init_serial = FALSE;
13240b57cec5SDimitry Andric   TCW_4(__kmp_init_gtid, FALSE);
13250b57cec5SDimitry Andric   __kmp_init_common = FALSE;
13260b57cec5SDimitry Andric 
13270b57cec5SDimitry Andric   TCW_4(__kmp_init_user_locks, FALSE);
13280b57cec5SDimitry Andric #if !KMP_USE_DYNAMIC_LOCK
13290b57cec5SDimitry Andric   __kmp_user_lock_table.used = 1;
13300b57cec5SDimitry Andric   __kmp_user_lock_table.allocated = 0;
13310b57cec5SDimitry Andric   __kmp_user_lock_table.table = NULL;
13320b57cec5SDimitry Andric   __kmp_lock_blocks = NULL;
13330b57cec5SDimitry Andric #endif
13340b57cec5SDimitry Andric 
13350b57cec5SDimitry Andric   __kmp_all_nth = 0;
13360b57cec5SDimitry Andric   TCW_4(__kmp_nth, 0);
13370b57cec5SDimitry Andric 
13380b57cec5SDimitry Andric   __kmp_thread_pool = NULL;
13390b57cec5SDimitry Andric   __kmp_thread_pool_insert_pt = NULL;
13400b57cec5SDimitry Andric   __kmp_team_pool = NULL;
13410b57cec5SDimitry Andric 
13420b57cec5SDimitry Andric   /* Must actually zero all the *cache arguments passed to __kmpc_threadprivate
13430b57cec5SDimitry Andric      here so threadprivate doesn't use stale data */
13440b57cec5SDimitry Andric   KA_TRACE(10, ("__kmp_atfork_child: checking cache address list %p\n",
13450b57cec5SDimitry Andric                 __kmp_threadpriv_cache_list));
13460b57cec5SDimitry Andric 
13470b57cec5SDimitry Andric   while (__kmp_threadpriv_cache_list != NULL) {
13480b57cec5SDimitry Andric 
13490b57cec5SDimitry Andric     if (*__kmp_threadpriv_cache_list->addr != NULL) {
13500b57cec5SDimitry Andric       KC_TRACE(50, ("__kmp_atfork_child: zeroing cache at address %p\n",
13510b57cec5SDimitry Andric                     &(*__kmp_threadpriv_cache_list->addr)));
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric       *__kmp_threadpriv_cache_list->addr = NULL;
13540b57cec5SDimitry Andric     }
13550b57cec5SDimitry Andric     __kmp_threadpriv_cache_list = __kmp_threadpriv_cache_list->next;
13560b57cec5SDimitry Andric   }
13570b57cec5SDimitry Andric 
13580b57cec5SDimitry Andric   __kmp_init_runtime = FALSE;
13590b57cec5SDimitry Andric 
13600b57cec5SDimitry Andric   /* reset statically initialized locks */
13610b57cec5SDimitry Andric   __kmp_init_bootstrap_lock(&__kmp_initz_lock);
13620b57cec5SDimitry Andric   __kmp_init_bootstrap_lock(&__kmp_stdio_lock);
13630b57cec5SDimitry Andric   __kmp_init_bootstrap_lock(&__kmp_console_lock);
13640b57cec5SDimitry Andric   __kmp_init_bootstrap_lock(&__kmp_task_team_lock);
13650b57cec5SDimitry Andric 
13660b57cec5SDimitry Andric #if USE_ITT_BUILD
13670b57cec5SDimitry Andric   __kmp_itt_reset(); // reset ITT's global state
13680b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
13690b57cec5SDimitry Andric 
1370fcaf7f86SDimitry Andric   {
1371fcaf7f86SDimitry Andric     // Child process often get terminated without any use of OpenMP. That might
1372fcaf7f86SDimitry Andric     // cause mapped shared memory file to be left unattended. Thus we postpone
1373fcaf7f86SDimitry Andric     // library registration till middle initialization in the child process.
1374fcaf7f86SDimitry Andric     __kmp_need_register_serial = FALSE;
1375e8d8bef9SDimitry Andric     __kmp_serial_initialize();
1376fcaf7f86SDimitry Andric   }
1377e8d8bef9SDimitry Andric 
13780b57cec5SDimitry Andric   /* This is necessary to make sure no stale data is left around */
13790b57cec5SDimitry Andric   /* AC: customers complain that we use unsafe routines in the atfork
13800b57cec5SDimitry Andric      handler. Mathworks: dlsym() is unsafe. We call dlsym and dlopen
13810b57cec5SDimitry Andric      in dynamic_link when check the presence of shared tbbmalloc library.
13820b57cec5SDimitry Andric      Suggestion is to make the library initialization lazier, similar
13830b57cec5SDimitry Andric      to what done for __kmpc_begin(). */
13840b57cec5SDimitry Andric   // TODO: synchronize all static initializations with regular library
13850b57cec5SDimitry Andric   //       startup; look at kmp_global.cpp and etc.
13860b57cec5SDimitry Andric   //__kmp_internal_begin ();
13870b57cec5SDimitry Andric }
13880b57cec5SDimitry Andric 
__kmp_register_atfork(void)13890b57cec5SDimitry Andric void __kmp_register_atfork(void) {
13900b57cec5SDimitry Andric   if (__kmp_need_register_atfork) {
13915f757f3fSDimitry Andric #if !KMP_OS_WASI
13920b57cec5SDimitry Andric     int status = pthread_atfork(__kmp_atfork_prepare, __kmp_atfork_parent,
13930b57cec5SDimitry Andric                                 __kmp_atfork_child);
13940b57cec5SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_atfork", status);
13955f757f3fSDimitry Andric #endif
13960b57cec5SDimitry Andric     __kmp_need_register_atfork = FALSE;
13970b57cec5SDimitry Andric   }
13980b57cec5SDimitry Andric }
13990b57cec5SDimitry Andric 
__kmp_suspend_initialize(void)14000b57cec5SDimitry Andric void __kmp_suspend_initialize(void) {
14010b57cec5SDimitry Andric   int status;
14020b57cec5SDimitry Andric   status = pthread_mutexattr_init(&__kmp_suspend_mutex_attr);
14030b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutexattr_init", status);
14040b57cec5SDimitry Andric   status = pthread_condattr_init(&__kmp_suspend_cond_attr);
14050b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_condattr_init", status);
14060b57cec5SDimitry Andric }
14070b57cec5SDimitry Andric 
__kmp_suspend_initialize_thread(kmp_info_t * th)14080b57cec5SDimitry Andric void __kmp_suspend_initialize_thread(kmp_info_t *th) {
14090b57cec5SDimitry Andric   int old_value = KMP_ATOMIC_LD_RLX(&th->th.th_suspend_init_count);
14100b57cec5SDimitry Andric   int new_value = __kmp_fork_count + 1;
14110b57cec5SDimitry Andric   // Return if already initialized
14120b57cec5SDimitry Andric   if (old_value == new_value)
14130b57cec5SDimitry Andric     return;
14140b57cec5SDimitry Andric   // Wait, then return if being initialized
1415fe6060f1SDimitry Andric   if (old_value == -1 || !__kmp_atomic_compare_store(
1416fe6060f1SDimitry Andric                              &th->th.th_suspend_init_count, old_value, -1)) {
14170b57cec5SDimitry Andric     while (KMP_ATOMIC_LD_ACQ(&th->th.th_suspend_init_count) != new_value) {
14180b57cec5SDimitry Andric       KMP_CPU_PAUSE();
14190b57cec5SDimitry Andric     }
14200b57cec5SDimitry Andric   } else {
14210b57cec5SDimitry Andric     // Claim to be the initializer and do initializations
14220b57cec5SDimitry Andric     int status;
14230b57cec5SDimitry Andric     status = pthread_cond_init(&th->th.th_suspend_cv.c_cond,
14240b57cec5SDimitry Andric                                &__kmp_suspend_cond_attr);
14250b57cec5SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_cond_init", status);
14260b57cec5SDimitry Andric     status = pthread_mutex_init(&th->th.th_suspend_mx.m_mutex,
14270b57cec5SDimitry Andric                                 &__kmp_suspend_mutex_attr);
14280b57cec5SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
14290b57cec5SDimitry Andric     KMP_ATOMIC_ST_REL(&th->th.th_suspend_init_count, new_value);
14300b57cec5SDimitry Andric   }
14310b57cec5SDimitry Andric }
14320b57cec5SDimitry Andric 
__kmp_suspend_uninitialize_thread(kmp_info_t * th)14330b57cec5SDimitry Andric void __kmp_suspend_uninitialize_thread(kmp_info_t *th) {
14340b57cec5SDimitry Andric   if (KMP_ATOMIC_LD_ACQ(&th->th.th_suspend_init_count) > __kmp_fork_count) {
14350b57cec5SDimitry Andric     /* this means we have initialize the suspension pthread objects for this
14360b57cec5SDimitry Andric        thread in this instance of the process */
14370b57cec5SDimitry Andric     int status;
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric     status = pthread_cond_destroy(&th->th.th_suspend_cv.c_cond);
14400b57cec5SDimitry Andric     if (status != 0 && status != EBUSY) {
14410b57cec5SDimitry Andric       KMP_SYSFAIL("pthread_cond_destroy", status);
14420b57cec5SDimitry Andric     }
14430b57cec5SDimitry Andric     status = pthread_mutex_destroy(&th->th.th_suspend_mx.m_mutex);
14440b57cec5SDimitry Andric     if (status != 0 && status != EBUSY) {
14450b57cec5SDimitry Andric       KMP_SYSFAIL("pthread_mutex_destroy", status);
14460b57cec5SDimitry Andric     }
14470b57cec5SDimitry Andric     --th->th.th_suspend_init_count;
14480b57cec5SDimitry Andric     KMP_DEBUG_ASSERT(KMP_ATOMIC_LD_RLX(&th->th.th_suspend_init_count) ==
14490b57cec5SDimitry Andric                      __kmp_fork_count);
14500b57cec5SDimitry Andric   }
14510b57cec5SDimitry Andric }
14520b57cec5SDimitry Andric 
14530b57cec5SDimitry Andric // return true if lock obtained, false otherwise
__kmp_try_suspend_mx(kmp_info_t * th)14540b57cec5SDimitry Andric int __kmp_try_suspend_mx(kmp_info_t *th) {
14550b57cec5SDimitry Andric   return (pthread_mutex_trylock(&th->th.th_suspend_mx.m_mutex) == 0);
14560b57cec5SDimitry Andric }
14570b57cec5SDimitry Andric 
__kmp_lock_suspend_mx(kmp_info_t * th)14580b57cec5SDimitry Andric void __kmp_lock_suspend_mx(kmp_info_t *th) {
14590b57cec5SDimitry Andric   int status = pthread_mutex_lock(&th->th.th_suspend_mx.m_mutex);
14600b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
14610b57cec5SDimitry Andric }
14620b57cec5SDimitry Andric 
__kmp_unlock_suspend_mx(kmp_info_t * th)14630b57cec5SDimitry Andric void __kmp_unlock_suspend_mx(kmp_info_t *th) {
14640b57cec5SDimitry Andric   int status = pthread_mutex_unlock(&th->th.th_suspend_mx.m_mutex);
14650b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
14660b57cec5SDimitry Andric }
14670b57cec5SDimitry Andric 
14680b57cec5SDimitry Andric /* This routine puts the calling thread to sleep after setting the
14690b57cec5SDimitry Andric    sleep bit for the indicated flag variable to true. */
14700b57cec5SDimitry Andric template <class C>
__kmp_suspend_template(int th_gtid,C * flag)14710b57cec5SDimitry Andric static inline void __kmp_suspend_template(int th_gtid, C *flag) {
14720b57cec5SDimitry Andric   KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_suspend);
14730b57cec5SDimitry Andric   kmp_info_t *th = __kmp_threads[th_gtid];
14740b57cec5SDimitry Andric   int status;
14750b57cec5SDimitry Andric   typename C::flag_t old_spin;
14760b57cec5SDimitry Andric 
14770b57cec5SDimitry Andric   KF_TRACE(30, ("__kmp_suspend_template: T#%d enter for flag = %p\n", th_gtid,
14780b57cec5SDimitry Andric                 flag->get()));
14790b57cec5SDimitry Andric 
14800b57cec5SDimitry Andric   __kmp_suspend_initialize_thread(th);
14810b57cec5SDimitry Andric 
1482e8d8bef9SDimitry Andric   __kmp_lock_suspend_mx(th);
14830b57cec5SDimitry Andric 
14840b57cec5SDimitry Andric   KF_TRACE(10, ("__kmp_suspend_template: T#%d setting sleep bit for spin(%p)\n",
14850b57cec5SDimitry Andric                 th_gtid, flag->get()));
14860b57cec5SDimitry Andric 
14870b57cec5SDimitry Andric   /* TODO: shouldn't this use release semantics to ensure that
14880b57cec5SDimitry Andric      __kmp_suspend_initialize_thread gets called first? */
14890b57cec5SDimitry Andric   old_spin = flag->set_sleeping();
1490349cc55cSDimitry Andric   TCW_PTR(th->th.th_sleep_loc, (void *)flag);
1491349cc55cSDimitry Andric   th->th.th_sleep_loc_type = flag->get_type();
14920b57cec5SDimitry Andric   if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME &&
14930b57cec5SDimitry Andric       __kmp_pause_status != kmp_soft_paused) {
14940b57cec5SDimitry Andric     flag->unset_sleeping();
1495349cc55cSDimitry Andric     TCW_PTR(th->th.th_sleep_loc, NULL);
1496349cc55cSDimitry Andric     th->th.th_sleep_loc_type = flag_unset;
1497e8d8bef9SDimitry Andric     __kmp_unlock_suspend_mx(th);
14980b57cec5SDimitry Andric     return;
14990b57cec5SDimitry Andric   }
15000b57cec5SDimitry Andric   KF_TRACE(5, ("__kmp_suspend_template: T#%d set sleep bit for spin(%p)==%x,"
15010b57cec5SDimitry Andric                " was %x\n",
15020b57cec5SDimitry Andric                th_gtid, flag->get(), flag->load(), old_spin));
15030b57cec5SDimitry Andric 
1504349cc55cSDimitry Andric   if (flag->done_check_val(old_spin) || flag->done_check()) {
1505349cc55cSDimitry Andric     flag->unset_sleeping();
1506349cc55cSDimitry Andric     TCW_PTR(th->th.th_sleep_loc, NULL);
1507349cc55cSDimitry Andric     th->th.th_sleep_loc_type = flag_unset;
15080b57cec5SDimitry Andric     KF_TRACE(5, ("__kmp_suspend_template: T#%d false alarm, reset sleep bit "
15090b57cec5SDimitry Andric                  "for spin(%p)\n",
15100b57cec5SDimitry Andric                  th_gtid, flag->get()));
15110b57cec5SDimitry Andric   } else {
15120b57cec5SDimitry Andric     /* Encapsulate in a loop as the documentation states that this may
15130b57cec5SDimitry Andric        "with low probability" return when the condition variable has
15140b57cec5SDimitry Andric        not been signaled or broadcast */
15150b57cec5SDimitry Andric     int deactivated = FALSE;
15160b57cec5SDimitry Andric 
15170b57cec5SDimitry Andric     while (flag->is_sleeping()) {
15180b57cec5SDimitry Andric #ifdef DEBUG_SUSPEND
15190b57cec5SDimitry Andric       char buffer[128];
15200b57cec5SDimitry Andric       __kmp_suspend_count++;
15210b57cec5SDimitry Andric       __kmp_print_cond(buffer, &th->th.th_suspend_cv);
15220b57cec5SDimitry Andric       __kmp_printf("__kmp_suspend_template: suspending T#%d: %s\n", th_gtid,
15230b57cec5SDimitry Andric                    buffer);
15240b57cec5SDimitry Andric #endif
15250b57cec5SDimitry Andric       // Mark the thread as no longer active (only in the first iteration of the
15260b57cec5SDimitry Andric       // loop).
15270b57cec5SDimitry Andric       if (!deactivated) {
15280b57cec5SDimitry Andric         th->th.th_active = FALSE;
15290b57cec5SDimitry Andric         if (th->th.th_active_in_pool) {
15300b57cec5SDimitry Andric           th->th.th_active_in_pool = FALSE;
15310b57cec5SDimitry Andric           KMP_ATOMIC_DEC(&__kmp_thread_pool_active_nth);
15320b57cec5SDimitry Andric           KMP_DEBUG_ASSERT(TCR_4(__kmp_thread_pool_active_nth) >= 0);
15330b57cec5SDimitry Andric         }
15340b57cec5SDimitry Andric         deactivated = TRUE;
15350b57cec5SDimitry Andric       }
15360b57cec5SDimitry Andric 
1537349cc55cSDimitry Andric       KMP_DEBUG_ASSERT(th->th.th_sleep_loc);
1538349cc55cSDimitry Andric       KMP_DEBUG_ASSERT(flag->get_type() == th->th.th_sleep_loc_type);
1539349cc55cSDimitry Andric 
15400b57cec5SDimitry Andric #if USE_SUSPEND_TIMEOUT
15410b57cec5SDimitry Andric       struct timespec now;
15420b57cec5SDimitry Andric       struct timeval tval;
15430b57cec5SDimitry Andric       int msecs;
15440b57cec5SDimitry Andric 
15450b57cec5SDimitry Andric       status = gettimeofday(&tval, NULL);
15460b57cec5SDimitry Andric       KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
15470b57cec5SDimitry Andric       TIMEVAL_TO_TIMESPEC(&tval, &now);
15480b57cec5SDimitry Andric 
15490b57cec5SDimitry Andric       msecs = (4 * __kmp_dflt_blocktime) + 200;
15500b57cec5SDimitry Andric       now.tv_sec += msecs / 1000;
15510b57cec5SDimitry Andric       now.tv_nsec += (msecs % 1000) * 1000;
15520b57cec5SDimitry Andric 
15530b57cec5SDimitry Andric       KF_TRACE(15, ("__kmp_suspend_template: T#%d about to perform "
15540b57cec5SDimitry Andric                     "pthread_cond_timedwait\n",
15550b57cec5SDimitry Andric                     th_gtid));
15560b57cec5SDimitry Andric       status = pthread_cond_timedwait(&th->th.th_suspend_cv.c_cond,
15570b57cec5SDimitry Andric                                       &th->th.th_suspend_mx.m_mutex, &now);
15580b57cec5SDimitry Andric #else
15590b57cec5SDimitry Andric       KF_TRACE(15, ("__kmp_suspend_template: T#%d about to perform"
15600b57cec5SDimitry Andric                     " pthread_cond_wait\n",
15610b57cec5SDimitry Andric                     th_gtid));
15620b57cec5SDimitry Andric       status = pthread_cond_wait(&th->th.th_suspend_cv.c_cond,
15630b57cec5SDimitry Andric                                  &th->th.th_suspend_mx.m_mutex);
1564e8d8bef9SDimitry Andric #endif // USE_SUSPEND_TIMEOUT
15650b57cec5SDimitry Andric 
15660b57cec5SDimitry Andric       if ((status != 0) && (status != EINTR) && (status != ETIMEDOUT)) {
15670b57cec5SDimitry Andric         KMP_SYSFAIL("pthread_cond_wait", status);
15680b57cec5SDimitry Andric       }
1569349cc55cSDimitry Andric 
1570349cc55cSDimitry Andric       KMP_DEBUG_ASSERT(flag->get_type() == flag->get_ptr_type());
1571349cc55cSDimitry Andric 
1572349cc55cSDimitry Andric       if (!flag->is_sleeping() &&
1573349cc55cSDimitry Andric           ((status == EINTR) || (status == ETIMEDOUT))) {
1574349cc55cSDimitry Andric         // if interrupt or timeout, and thread is no longer sleeping, we need to
1575349cc55cSDimitry Andric         // make sure sleep_loc gets reset; however, this shouldn't be needed if
1576349cc55cSDimitry Andric         // we woke up with resume
1577349cc55cSDimitry Andric         flag->unset_sleeping();
1578349cc55cSDimitry Andric         TCW_PTR(th->th.th_sleep_loc, NULL);
1579349cc55cSDimitry Andric         th->th.th_sleep_loc_type = flag_unset;
1580349cc55cSDimitry Andric       }
15810b57cec5SDimitry Andric #ifdef KMP_DEBUG
15820b57cec5SDimitry Andric       if (status == ETIMEDOUT) {
15830b57cec5SDimitry Andric         if (flag->is_sleeping()) {
15840b57cec5SDimitry Andric           KF_TRACE(100,
15850b57cec5SDimitry Andric                    ("__kmp_suspend_template: T#%d timeout wakeup\n", th_gtid));
15860b57cec5SDimitry Andric         } else {
15870b57cec5SDimitry Andric           KF_TRACE(2, ("__kmp_suspend_template: T#%d timeout wakeup, sleep bit "
15880b57cec5SDimitry Andric                        "not set!\n",
15890b57cec5SDimitry Andric                        th_gtid));
1590349cc55cSDimitry Andric           TCW_PTR(th->th.th_sleep_loc, NULL);
1591349cc55cSDimitry Andric           th->th.th_sleep_loc_type = flag_unset;
15920b57cec5SDimitry Andric         }
15930b57cec5SDimitry Andric       } else if (flag->is_sleeping()) {
15940b57cec5SDimitry Andric         KF_TRACE(100,
15950b57cec5SDimitry Andric                  ("__kmp_suspend_template: T#%d spurious wakeup\n", th_gtid));
15960b57cec5SDimitry Andric       }
15970b57cec5SDimitry Andric #endif
15980b57cec5SDimitry Andric     } // while
15990b57cec5SDimitry Andric 
16000b57cec5SDimitry Andric     // Mark the thread as active again (if it was previous marked as inactive)
16010b57cec5SDimitry Andric     if (deactivated) {
16020b57cec5SDimitry Andric       th->th.th_active = TRUE;
16030b57cec5SDimitry Andric       if (TCR_4(th->th.th_in_pool)) {
16040b57cec5SDimitry Andric         KMP_ATOMIC_INC(&__kmp_thread_pool_active_nth);
16050b57cec5SDimitry Andric         th->th.th_active_in_pool = TRUE;
16060b57cec5SDimitry Andric       }
16070b57cec5SDimitry Andric     }
16080b57cec5SDimitry Andric   }
1609349cc55cSDimitry Andric   // We may have had the loop variable set before entering the loop body;
1610349cc55cSDimitry Andric   // so we need to reset sleep_loc.
1611349cc55cSDimitry Andric   TCW_PTR(th->th.th_sleep_loc, NULL);
1612349cc55cSDimitry Andric   th->th.th_sleep_loc_type = flag_unset;
1613349cc55cSDimitry Andric 
1614349cc55cSDimitry Andric   KMP_DEBUG_ASSERT(!flag->is_sleeping());
1615349cc55cSDimitry Andric   KMP_DEBUG_ASSERT(!th->th.th_sleep_loc);
16160b57cec5SDimitry Andric #ifdef DEBUG_SUSPEND
16170b57cec5SDimitry Andric   {
16180b57cec5SDimitry Andric     char buffer[128];
16190b57cec5SDimitry Andric     __kmp_print_cond(buffer, &th->th.th_suspend_cv);
16200b57cec5SDimitry Andric     __kmp_printf("__kmp_suspend_template: T#%d has awakened: %s\n", th_gtid,
16210b57cec5SDimitry Andric                  buffer);
16220b57cec5SDimitry Andric   }
16230b57cec5SDimitry Andric #endif
16240b57cec5SDimitry Andric 
1625e8d8bef9SDimitry Andric   __kmp_unlock_suspend_mx(th);
16260b57cec5SDimitry Andric   KF_TRACE(30, ("__kmp_suspend_template: T#%d exit\n", th_gtid));
16270b57cec5SDimitry Andric }
16280b57cec5SDimitry Andric 
1629e8d8bef9SDimitry Andric template <bool C, bool S>
__kmp_suspend_32(int th_gtid,kmp_flag_32<C,S> * flag)1630e8d8bef9SDimitry Andric void __kmp_suspend_32(int th_gtid, kmp_flag_32<C, S> *flag) {
16310b57cec5SDimitry Andric   __kmp_suspend_template(th_gtid, flag);
16320b57cec5SDimitry Andric }
1633e8d8bef9SDimitry Andric template <bool C, bool S>
__kmp_suspend_64(int th_gtid,kmp_flag_64<C,S> * flag)1634e8d8bef9SDimitry Andric void __kmp_suspend_64(int th_gtid, kmp_flag_64<C, S> *flag) {
16350b57cec5SDimitry Andric   __kmp_suspend_template(th_gtid, flag);
16360b57cec5SDimitry Andric }
1637349cc55cSDimitry Andric template <bool C, bool S>
__kmp_atomic_suspend_64(int th_gtid,kmp_atomic_flag_64<C,S> * flag)1638349cc55cSDimitry Andric void __kmp_atomic_suspend_64(int th_gtid, kmp_atomic_flag_64<C, S> *flag) {
1639349cc55cSDimitry Andric   __kmp_suspend_template(th_gtid, flag);
1640349cc55cSDimitry Andric }
__kmp_suspend_oncore(int th_gtid,kmp_flag_oncore * flag)16410b57cec5SDimitry Andric void __kmp_suspend_oncore(int th_gtid, kmp_flag_oncore *flag) {
16420b57cec5SDimitry Andric   __kmp_suspend_template(th_gtid, flag);
16430b57cec5SDimitry Andric }
16440b57cec5SDimitry Andric 
1645e8d8bef9SDimitry Andric template void __kmp_suspend_32<false, false>(int, kmp_flag_32<false, false> *);
1646e8d8bef9SDimitry Andric template void __kmp_suspend_64<false, true>(int, kmp_flag_64<false, true> *);
1647e8d8bef9SDimitry Andric template void __kmp_suspend_64<true, false>(int, kmp_flag_64<true, false> *);
1648349cc55cSDimitry Andric template void
1649349cc55cSDimitry Andric __kmp_atomic_suspend_64<false, true>(int, kmp_atomic_flag_64<false, true> *);
1650349cc55cSDimitry Andric template void
1651349cc55cSDimitry Andric __kmp_atomic_suspend_64<true, false>(int, kmp_atomic_flag_64<true, false> *);
1652e8d8bef9SDimitry Andric 
16530b57cec5SDimitry Andric /* This routine signals the thread specified by target_gtid to wake up
16540b57cec5SDimitry Andric    after setting the sleep bit indicated by the flag argument to FALSE.
16550b57cec5SDimitry Andric    The target thread must already have called __kmp_suspend_template() */
16560b57cec5SDimitry Andric template <class C>
__kmp_resume_template(int target_gtid,C * flag)16570b57cec5SDimitry Andric static inline void __kmp_resume_template(int target_gtid, C *flag) {
16580b57cec5SDimitry Andric   KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_resume);
16590b57cec5SDimitry Andric   kmp_info_t *th = __kmp_threads[target_gtid];
16600b57cec5SDimitry Andric   int status;
16610b57cec5SDimitry Andric 
16620b57cec5SDimitry Andric #ifdef KMP_DEBUG
16630b57cec5SDimitry Andric   int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
16640b57cec5SDimitry Andric #endif
16650b57cec5SDimitry Andric 
16660b57cec5SDimitry Andric   KF_TRACE(30, ("__kmp_resume_template: T#%d wants to wakeup T#%d enter\n",
16670b57cec5SDimitry Andric                 gtid, target_gtid));
16680b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(gtid != target_gtid);
16690b57cec5SDimitry Andric 
16700b57cec5SDimitry Andric   __kmp_suspend_initialize_thread(th);
16710b57cec5SDimitry Andric 
1672e8d8bef9SDimitry Andric   __kmp_lock_suspend_mx(th);
16730b57cec5SDimitry Andric 
1674349cc55cSDimitry Andric   if (!flag || flag != th->th.th_sleep_loc) {
1675349cc55cSDimitry Andric     // coming from __kmp_null_resume_wrapper, or thread is now sleeping on a
1676349cc55cSDimitry Andric     // different location; wake up at new location
16770b57cec5SDimitry Andric     flag = (C *)CCAST(void *, th->th.th_sleep_loc);
16780b57cec5SDimitry Andric   }
16790b57cec5SDimitry Andric 
16800b57cec5SDimitry Andric   // First, check if the flag is null or its type has changed. If so, someone
16810b57cec5SDimitry Andric   // else woke it up.
1682349cc55cSDimitry Andric   if (!flag) { // Thread doesn't appear to be sleeping on anything
16830b57cec5SDimitry Andric     KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already "
16840b57cec5SDimitry Andric                  "awake: flag(%p)\n",
1685349cc55cSDimitry Andric                  gtid, target_gtid, (void *)NULL));
1686e8d8bef9SDimitry Andric     __kmp_unlock_suspend_mx(th);
16870b57cec5SDimitry Andric     return;
1688349cc55cSDimitry Andric   } else if (flag->get_type() != th->th.th_sleep_loc_type) {
1689349cc55cSDimitry Andric     // Flag type does not appear to match this function template; possibly the
1690349cc55cSDimitry Andric     // thread is sleeping on something else. Try null resume again.
1691349cc55cSDimitry Andric     KF_TRACE(
1692349cc55cSDimitry Andric         5,
1693349cc55cSDimitry Andric         ("__kmp_resume_template: T#%d retrying, thread T#%d Mismatch flag(%p), "
1694349cc55cSDimitry Andric          "spin(%p) type=%d ptr_type=%d\n",
1695349cc55cSDimitry Andric          gtid, target_gtid, flag, flag->get(), flag->get_type(),
1696349cc55cSDimitry Andric          th->th.th_sleep_loc_type));
1697349cc55cSDimitry Andric     __kmp_unlock_suspend_mx(th);
1698349cc55cSDimitry Andric     __kmp_null_resume_wrapper(th);
1699349cc55cSDimitry Andric     return;
17000b57cec5SDimitry Andric   } else { // if multiple threads are sleeping, flag should be internally
17010b57cec5SDimitry Andric     // referring to a specific thread here
1702349cc55cSDimitry Andric     if (!flag->is_sleeping()) {
17030b57cec5SDimitry Andric       KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already "
1704349cc55cSDimitry Andric                    "awake: flag(%p): %u\n",
1705349cc55cSDimitry Andric                    gtid, target_gtid, flag->get(), (unsigned int)flag->load()));
1706e8d8bef9SDimitry Andric       __kmp_unlock_suspend_mx(th);
17070b57cec5SDimitry Andric       return;
17080b57cec5SDimitry Andric     }
17090b57cec5SDimitry Andric   }
1710349cc55cSDimitry Andric   KMP_DEBUG_ASSERT(flag);
1711349cc55cSDimitry Andric   flag->unset_sleeping();
17120b57cec5SDimitry Andric   TCW_PTR(th->th.th_sleep_loc, NULL);
1713349cc55cSDimitry Andric   th->th.th_sleep_loc_type = flag_unset;
1714349cc55cSDimitry Andric 
1715349cc55cSDimitry Andric   KF_TRACE(5, ("__kmp_resume_template: T#%d about to wakeup T#%d, reset "
1716349cc55cSDimitry Andric                "sleep bit for flag's loc(%p): %u\n",
1717349cc55cSDimitry Andric                gtid, target_gtid, flag->get(), (unsigned int)flag->load()));
17180b57cec5SDimitry Andric 
17190b57cec5SDimitry Andric #ifdef DEBUG_SUSPEND
17200b57cec5SDimitry Andric   {
17210b57cec5SDimitry Andric     char buffer[128];
17220b57cec5SDimitry Andric     __kmp_print_cond(buffer, &th->th.th_suspend_cv);
17230b57cec5SDimitry Andric     __kmp_printf("__kmp_resume_template: T#%d resuming T#%d: %s\n", gtid,
17240b57cec5SDimitry Andric                  target_gtid, buffer);
17250b57cec5SDimitry Andric   }
17260b57cec5SDimitry Andric #endif
17270b57cec5SDimitry Andric   status = pthread_cond_signal(&th->th.th_suspend_cv.c_cond);
17280b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_cond_signal", status);
1729e8d8bef9SDimitry Andric   __kmp_unlock_suspend_mx(th);
17300b57cec5SDimitry Andric   KF_TRACE(30, ("__kmp_resume_template: T#%d exiting after signaling wake up"
17310b57cec5SDimitry Andric                 " for T#%d\n",
17320b57cec5SDimitry Andric                 gtid, target_gtid));
17330b57cec5SDimitry Andric }
17340b57cec5SDimitry Andric 
1735e8d8bef9SDimitry Andric template <bool C, bool S>
__kmp_resume_32(int target_gtid,kmp_flag_32<C,S> * flag)1736e8d8bef9SDimitry Andric void __kmp_resume_32(int target_gtid, kmp_flag_32<C, S> *flag) {
17370b57cec5SDimitry Andric   __kmp_resume_template(target_gtid, flag);
17380b57cec5SDimitry Andric }
1739e8d8bef9SDimitry Andric template <bool C, bool S>
__kmp_resume_64(int target_gtid,kmp_flag_64<C,S> * flag)1740e8d8bef9SDimitry Andric void __kmp_resume_64(int target_gtid, kmp_flag_64<C, S> *flag) {
17410b57cec5SDimitry Andric   __kmp_resume_template(target_gtid, flag);
17420b57cec5SDimitry Andric }
1743349cc55cSDimitry Andric template <bool C, bool S>
__kmp_atomic_resume_64(int target_gtid,kmp_atomic_flag_64<C,S> * flag)1744349cc55cSDimitry Andric void __kmp_atomic_resume_64(int target_gtid, kmp_atomic_flag_64<C, S> *flag) {
1745349cc55cSDimitry Andric   __kmp_resume_template(target_gtid, flag);
1746349cc55cSDimitry Andric }
__kmp_resume_oncore(int target_gtid,kmp_flag_oncore * flag)17470b57cec5SDimitry Andric void __kmp_resume_oncore(int target_gtid, kmp_flag_oncore *flag) {
17480b57cec5SDimitry Andric   __kmp_resume_template(target_gtid, flag);
17490b57cec5SDimitry Andric }
17500b57cec5SDimitry Andric 
1751e8d8bef9SDimitry Andric template void __kmp_resume_32<false, true>(int, kmp_flag_32<false, true> *);
1752349cc55cSDimitry Andric template void __kmp_resume_32<false, false>(int, kmp_flag_32<false, false> *);
1753e8d8bef9SDimitry Andric template void __kmp_resume_64<false, true>(int, kmp_flag_64<false, true> *);
1754349cc55cSDimitry Andric template void
1755349cc55cSDimitry Andric __kmp_atomic_resume_64<false, true>(int, kmp_atomic_flag_64<false, true> *);
1756e8d8bef9SDimitry Andric 
17570b57cec5SDimitry Andric #if KMP_USE_MONITOR
__kmp_resume_monitor()17580b57cec5SDimitry Andric void __kmp_resume_monitor() {
17590b57cec5SDimitry Andric   KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_resume);
17600b57cec5SDimitry Andric   int status;
17610b57cec5SDimitry Andric #ifdef KMP_DEBUG
17620b57cec5SDimitry Andric   int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
17630b57cec5SDimitry Andric   KF_TRACE(30, ("__kmp_resume_monitor: T#%d wants to wakeup T#%d enter\n", gtid,
17640b57cec5SDimitry Andric                 KMP_GTID_MONITOR));
17650b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(gtid != KMP_GTID_MONITOR);
17660b57cec5SDimitry Andric #endif
17670b57cec5SDimitry Andric   status = pthread_mutex_lock(&__kmp_wait_mx.m_mutex);
17680b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
17690b57cec5SDimitry Andric #ifdef DEBUG_SUSPEND
17700b57cec5SDimitry Andric   {
17710b57cec5SDimitry Andric     char buffer[128];
17720b57cec5SDimitry Andric     __kmp_print_cond(buffer, &__kmp_wait_cv.c_cond);
17730b57cec5SDimitry Andric     __kmp_printf("__kmp_resume_monitor: T#%d resuming T#%d: %s\n", gtid,
17740b57cec5SDimitry Andric                  KMP_GTID_MONITOR, buffer);
17750b57cec5SDimitry Andric   }
17760b57cec5SDimitry Andric #endif
17770b57cec5SDimitry Andric   status = pthread_cond_signal(&__kmp_wait_cv.c_cond);
17780b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_cond_signal", status);
17790b57cec5SDimitry Andric   status = pthread_mutex_unlock(&__kmp_wait_mx.m_mutex);
17800b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
17810b57cec5SDimitry Andric   KF_TRACE(30, ("__kmp_resume_monitor: T#%d exiting after signaling wake up"
17820b57cec5SDimitry Andric                 " for T#%d\n",
17830b57cec5SDimitry Andric                 gtid, KMP_GTID_MONITOR));
17840b57cec5SDimitry Andric }
17850b57cec5SDimitry Andric #endif // KMP_USE_MONITOR
17860b57cec5SDimitry Andric 
__kmp_yield()17870b57cec5SDimitry Andric void __kmp_yield() { sched_yield(); }
17880b57cec5SDimitry Andric 
__kmp_gtid_set_specific(int gtid)17890b57cec5SDimitry Andric void __kmp_gtid_set_specific(int gtid) {
17900b57cec5SDimitry Andric   if (__kmp_init_gtid) {
17910b57cec5SDimitry Andric     int status;
17920b57cec5SDimitry Andric     status = pthread_setspecific(__kmp_gtid_threadprivate_key,
17930b57cec5SDimitry Andric                                  (void *)(intptr_t)(gtid + 1));
17940b57cec5SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_setspecific", status);
17950b57cec5SDimitry Andric   } else {
17960b57cec5SDimitry Andric     KA_TRACE(50, ("__kmp_gtid_set_specific: runtime shutdown, returning\n"));
17970b57cec5SDimitry Andric   }
17980b57cec5SDimitry Andric }
17990b57cec5SDimitry Andric 
__kmp_gtid_get_specific()18000b57cec5SDimitry Andric int __kmp_gtid_get_specific() {
18010b57cec5SDimitry Andric   int gtid;
18020b57cec5SDimitry Andric   if (!__kmp_init_gtid) {
18030b57cec5SDimitry Andric     KA_TRACE(50, ("__kmp_gtid_get_specific: runtime shutdown, returning "
18040b57cec5SDimitry Andric                   "KMP_GTID_SHUTDOWN\n"));
18050b57cec5SDimitry Andric     return KMP_GTID_SHUTDOWN;
18060b57cec5SDimitry Andric   }
18070b57cec5SDimitry Andric   gtid = (int)(size_t)pthread_getspecific(__kmp_gtid_threadprivate_key);
18080b57cec5SDimitry Andric   if (gtid == 0) {
18090b57cec5SDimitry Andric     gtid = KMP_GTID_DNE;
18100b57cec5SDimitry Andric   } else {
18110b57cec5SDimitry Andric     gtid--;
18120b57cec5SDimitry Andric   }
18130b57cec5SDimitry Andric   KA_TRACE(50, ("__kmp_gtid_get_specific: key:%d gtid:%d\n",
18140b57cec5SDimitry Andric                 __kmp_gtid_threadprivate_key, gtid));
18150b57cec5SDimitry Andric   return gtid;
18160b57cec5SDimitry Andric }
18170b57cec5SDimitry Andric 
__kmp_read_cpu_time(void)18180b57cec5SDimitry Andric double __kmp_read_cpu_time(void) {
18190b57cec5SDimitry Andric   /*clock_t   t;*/
18200b57cec5SDimitry Andric   struct tms buffer;
18210b57cec5SDimitry Andric 
18220b57cec5SDimitry Andric   /*t =*/times(&buffer);
18230b57cec5SDimitry Andric 
1824e8d8bef9SDimitry Andric   return (double)(buffer.tms_utime + buffer.tms_cutime) /
1825e8d8bef9SDimitry Andric          (double)CLOCKS_PER_SEC;
18260b57cec5SDimitry Andric }
18270b57cec5SDimitry Andric 
__kmp_read_system_info(struct kmp_sys_info * info)18280b57cec5SDimitry Andric int __kmp_read_system_info(struct kmp_sys_info *info) {
18290b57cec5SDimitry Andric   int status;
18300b57cec5SDimitry Andric   struct rusage r_usage;
18310b57cec5SDimitry Andric 
18320b57cec5SDimitry Andric   memset(info, 0, sizeof(*info));
18330b57cec5SDimitry Andric 
18340b57cec5SDimitry Andric   status = getrusage(RUSAGE_SELF, &r_usage);
18350b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL_ERRNO("getrusage", status);
18360b57cec5SDimitry Andric 
18375f757f3fSDimitry Andric #if !KMP_OS_WASI
18380b57cec5SDimitry Andric   // The maximum resident set size utilized (in kilobytes)
18390b57cec5SDimitry Andric   info->maxrss = r_usage.ru_maxrss;
18400b57cec5SDimitry Andric   // The number of page faults serviced without any I/O
18410b57cec5SDimitry Andric   info->minflt = r_usage.ru_minflt;
18420b57cec5SDimitry Andric   // The number of page faults serviced that required I/O
18430b57cec5SDimitry Andric   info->majflt = r_usage.ru_majflt;
18440b57cec5SDimitry Andric   // The number of times a process was "swapped" out of memory
18450b57cec5SDimitry Andric   info->nswap = r_usage.ru_nswap;
18460b57cec5SDimitry Andric   // The number of times the file system had to perform input
18470b57cec5SDimitry Andric   info->inblock = r_usage.ru_inblock;
18480b57cec5SDimitry Andric   // The number of times the file system had to perform output
18490b57cec5SDimitry Andric   info->oublock = r_usage.ru_oublock;
18500b57cec5SDimitry Andric   // The number of times a context switch was voluntarily
18510b57cec5SDimitry Andric   info->nvcsw = r_usage.ru_nvcsw;
18520b57cec5SDimitry Andric   // The number of times a context switch was forced
18530b57cec5SDimitry Andric   info->nivcsw = r_usage.ru_nivcsw;
18545f757f3fSDimitry Andric #endif
18550b57cec5SDimitry Andric 
18560b57cec5SDimitry Andric   return (status != 0);
18570b57cec5SDimitry Andric }
18580b57cec5SDimitry Andric 
__kmp_read_system_time(double * delta)18590b57cec5SDimitry Andric void __kmp_read_system_time(double *delta) {
18600b57cec5SDimitry Andric   double t_ns;
18610b57cec5SDimitry Andric   struct timeval tval;
18620b57cec5SDimitry Andric   struct timespec stop;
18630b57cec5SDimitry Andric   int status;
18640b57cec5SDimitry Andric 
18650b57cec5SDimitry Andric   status = gettimeofday(&tval, NULL);
18660b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
18670b57cec5SDimitry Andric   TIMEVAL_TO_TIMESPEC(&tval, &stop);
1868e8d8bef9SDimitry Andric   t_ns = (double)(TS2NS(stop) - TS2NS(__kmp_sys_timer_data.start));
18690b57cec5SDimitry Andric   *delta = (t_ns * 1e-9);
18700b57cec5SDimitry Andric }
18710b57cec5SDimitry Andric 
__kmp_clear_system_time(void)18720b57cec5SDimitry Andric void __kmp_clear_system_time(void) {
18730b57cec5SDimitry Andric   struct timeval tval;
18740b57cec5SDimitry Andric   int status;
18750b57cec5SDimitry Andric   status = gettimeofday(&tval, NULL);
18760b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
18770b57cec5SDimitry Andric   TIMEVAL_TO_TIMESPEC(&tval, &__kmp_sys_timer_data.start);
18780b57cec5SDimitry Andric }
18790b57cec5SDimitry Andric 
__kmp_get_xproc(void)18800b57cec5SDimitry Andric static int __kmp_get_xproc(void) {
18810b57cec5SDimitry Andric 
18820b57cec5SDimitry Andric   int r = 0;
18830b57cec5SDimitry Andric 
1884349cc55cSDimitry Andric #if KMP_OS_LINUX
1885349cc55cSDimitry Andric 
1886349cc55cSDimitry Andric   __kmp_type_convert(sysconf(_SC_NPROCESSORS_CONF), &(r));
1887349cc55cSDimitry Andric 
1888349cc55cSDimitry Andric #elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_OPENBSD || \
18891db9f3b2SDimitry Andric     KMP_OS_HURD || KMP_OS_SOLARIS || KMP_OS_WASI || KMP_OS_AIX
18900b57cec5SDimitry Andric 
1891e8d8bef9SDimitry Andric   __kmp_type_convert(sysconf(_SC_NPROCESSORS_ONLN), &(r));
18920b57cec5SDimitry Andric 
18930b57cec5SDimitry Andric #elif KMP_OS_DARWIN
18940b57cec5SDimitry Andric 
1895*0fca6ea1SDimitry Andric   size_t len = sizeof(r);
1896*0fca6ea1SDimitry Andric   sysctlbyname("hw.logicalcpu", &r, &len, NULL, 0);
18970b57cec5SDimitry Andric 
18980b57cec5SDimitry Andric #else
18990b57cec5SDimitry Andric 
19000b57cec5SDimitry Andric #error "Unknown or unsupported OS."
19010b57cec5SDimitry Andric 
19020b57cec5SDimitry Andric #endif
19030b57cec5SDimitry Andric 
19040b57cec5SDimitry Andric   return r > 0 ? r : 2; /* guess value of 2 if OS told us 0 */
19050b57cec5SDimitry Andric 
19060b57cec5SDimitry Andric } // __kmp_get_xproc
19070b57cec5SDimitry Andric 
__kmp_read_from_file(char const * path,char const * format,...)19080b57cec5SDimitry Andric int __kmp_read_from_file(char const *path, char const *format, ...) {
19090b57cec5SDimitry Andric   int result;
19100b57cec5SDimitry Andric   va_list args;
19110b57cec5SDimitry Andric 
19120b57cec5SDimitry Andric   va_start(args, format);
19130b57cec5SDimitry Andric   FILE *f = fopen(path, "rb");
191406c3fb27SDimitry Andric   if (f == NULL) {
191506c3fb27SDimitry Andric     va_end(args);
19160b57cec5SDimitry Andric     return 0;
191706c3fb27SDimitry Andric   }
19180b57cec5SDimitry Andric   result = vfscanf(f, format, args);
19190b57cec5SDimitry Andric   fclose(f);
192006c3fb27SDimitry Andric   va_end(args);
19210b57cec5SDimitry Andric 
19220b57cec5SDimitry Andric   return result;
19230b57cec5SDimitry Andric }
19240b57cec5SDimitry Andric 
__kmp_runtime_initialize(void)19250b57cec5SDimitry Andric void __kmp_runtime_initialize(void) {
19260b57cec5SDimitry Andric   int status;
19270b57cec5SDimitry Andric   pthread_mutexattr_t mutex_attr;
19280b57cec5SDimitry Andric   pthread_condattr_t cond_attr;
19290b57cec5SDimitry Andric 
19300b57cec5SDimitry Andric   if (__kmp_init_runtime) {
19310b57cec5SDimitry Andric     return;
19320b57cec5SDimitry Andric   }
19330b57cec5SDimitry Andric 
19340b57cec5SDimitry Andric #if (KMP_ARCH_X86 || KMP_ARCH_X86_64)
19350b57cec5SDimitry Andric   if (!__kmp_cpuinfo.initialized) {
19360b57cec5SDimitry Andric     __kmp_query_cpuid(&__kmp_cpuinfo);
19370b57cec5SDimitry Andric   }
19380b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
19390b57cec5SDimitry Andric 
19400b57cec5SDimitry Andric   __kmp_xproc = __kmp_get_xproc();
19410b57cec5SDimitry Andric 
19420b57cec5SDimitry Andric #if !KMP_32_BIT_ARCH
19430b57cec5SDimitry Andric   struct rlimit rlim;
19440b57cec5SDimitry Andric   // read stack size of calling thread, save it as default for worker threads;
19450b57cec5SDimitry Andric   // this should be done before reading environment variables
19460b57cec5SDimitry Andric   status = getrlimit(RLIMIT_STACK, &rlim);
19470b57cec5SDimitry Andric   if (status == 0) { // success?
19480b57cec5SDimitry Andric     __kmp_stksize = rlim.rlim_cur;
19490b57cec5SDimitry Andric     __kmp_check_stksize(&__kmp_stksize); // check value and adjust if needed
19500b57cec5SDimitry Andric   }
19510b57cec5SDimitry Andric #endif /* KMP_32_BIT_ARCH */
19520b57cec5SDimitry Andric 
19530b57cec5SDimitry Andric   if (sysconf(_SC_THREADS)) {
19540b57cec5SDimitry Andric 
19550b57cec5SDimitry Andric     /* Query the maximum number of threads */
1956e8d8bef9SDimitry Andric     __kmp_type_convert(sysconf(_SC_THREAD_THREADS_MAX), &(__kmp_sys_max_nth));
19575f757f3fSDimitry Andric #ifdef __ve__
19585f757f3fSDimitry Andric     if (__kmp_sys_max_nth == -1) {
19595f757f3fSDimitry Andric       // VE's pthread supports only up to 64 threads per a VE process.
19605f757f3fSDimitry Andric       // So we use that KMP_MAX_NTH (predefined as 64) here.
19615f757f3fSDimitry Andric       __kmp_sys_max_nth = KMP_MAX_NTH;
19625f757f3fSDimitry Andric     }
19635f757f3fSDimitry Andric #else
19640b57cec5SDimitry Andric     if (__kmp_sys_max_nth == -1) {
19650b57cec5SDimitry Andric       /* Unlimited threads for NPTL */
19660b57cec5SDimitry Andric       __kmp_sys_max_nth = INT_MAX;
19670b57cec5SDimitry Andric     } else if (__kmp_sys_max_nth <= 1) {
19680b57cec5SDimitry Andric       /* Can't tell, just use PTHREAD_THREADS_MAX */
19690b57cec5SDimitry Andric       __kmp_sys_max_nth = KMP_MAX_NTH;
19700b57cec5SDimitry Andric     }
19715f757f3fSDimitry Andric #endif
19720b57cec5SDimitry Andric 
19730b57cec5SDimitry Andric     /* Query the minimum stack size */
19740b57cec5SDimitry Andric     __kmp_sys_min_stksize = sysconf(_SC_THREAD_STACK_MIN);
19750b57cec5SDimitry Andric     if (__kmp_sys_min_stksize <= 1) {
19760b57cec5SDimitry Andric       __kmp_sys_min_stksize = KMP_MIN_STKSIZE;
19770b57cec5SDimitry Andric     }
19780b57cec5SDimitry Andric   }
19790b57cec5SDimitry Andric 
19800b57cec5SDimitry Andric   /* Set up minimum number of threads to switch to TLS gtid */
19810b57cec5SDimitry Andric   __kmp_tls_gtid_min = KMP_TLS_GTID_MIN;
19820b57cec5SDimitry Andric 
19830b57cec5SDimitry Andric   status = pthread_key_create(&__kmp_gtid_threadprivate_key,
19840b57cec5SDimitry Andric                               __kmp_internal_end_dest);
19850b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_key_create", status);
19860b57cec5SDimitry Andric   status = pthread_mutexattr_init(&mutex_attr);
19870b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutexattr_init", status);
19880b57cec5SDimitry Andric   status = pthread_mutex_init(&__kmp_wait_mx.m_mutex, &mutex_attr);
19890b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
1990fe6060f1SDimitry Andric   status = pthread_mutexattr_destroy(&mutex_attr);
1991fe6060f1SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutexattr_destroy", status);
19920b57cec5SDimitry Andric   status = pthread_condattr_init(&cond_attr);
19930b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_condattr_init", status);
19940b57cec5SDimitry Andric   status = pthread_cond_init(&__kmp_wait_cv.c_cond, &cond_attr);
19950b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
1996fe6060f1SDimitry Andric   status = pthread_condattr_destroy(&cond_attr);
1997fe6060f1SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_condattr_destroy", status);
19980b57cec5SDimitry Andric #if USE_ITT_BUILD
19990b57cec5SDimitry Andric   __kmp_itt_initialize();
20000b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
20010b57cec5SDimitry Andric 
20020b57cec5SDimitry Andric   __kmp_init_runtime = TRUE;
20030b57cec5SDimitry Andric }
20040b57cec5SDimitry Andric 
__kmp_runtime_destroy(void)20050b57cec5SDimitry Andric void __kmp_runtime_destroy(void) {
20060b57cec5SDimitry Andric   int status;
20070b57cec5SDimitry Andric 
20080b57cec5SDimitry Andric   if (!__kmp_init_runtime) {
20090b57cec5SDimitry Andric     return; // Nothing to do.
20100b57cec5SDimitry Andric   }
20110b57cec5SDimitry Andric 
20120b57cec5SDimitry Andric #if USE_ITT_BUILD
20130b57cec5SDimitry Andric   __kmp_itt_destroy();
20140b57cec5SDimitry Andric #endif /* USE_ITT_BUILD */
20150b57cec5SDimitry Andric 
20160b57cec5SDimitry Andric   status = pthread_key_delete(__kmp_gtid_threadprivate_key);
20170b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_key_delete", status);
20180b57cec5SDimitry Andric 
20190b57cec5SDimitry Andric   status = pthread_mutex_destroy(&__kmp_wait_mx.m_mutex);
20200b57cec5SDimitry Andric   if (status != 0 && status != EBUSY) {
20210b57cec5SDimitry Andric     KMP_SYSFAIL("pthread_mutex_destroy", status);
20220b57cec5SDimitry Andric   }
20230b57cec5SDimitry Andric   status = pthread_cond_destroy(&__kmp_wait_cv.c_cond);
20240b57cec5SDimitry Andric   if (status != 0 && status != EBUSY) {
20250b57cec5SDimitry Andric     KMP_SYSFAIL("pthread_cond_destroy", status);
20260b57cec5SDimitry Andric   }
20270b57cec5SDimitry Andric #if KMP_AFFINITY_SUPPORTED
20280b57cec5SDimitry Andric   __kmp_affinity_uninitialize();
20290b57cec5SDimitry Andric #endif
20300b57cec5SDimitry Andric 
20310b57cec5SDimitry Andric   __kmp_init_runtime = FALSE;
20320b57cec5SDimitry Andric }
20330b57cec5SDimitry Andric 
20340b57cec5SDimitry Andric /* Put the thread to sleep for a time period */
20350b57cec5SDimitry Andric /* NOTE: not currently used anywhere */
__kmp_thread_sleep(int millis)20360b57cec5SDimitry Andric void __kmp_thread_sleep(int millis) { sleep((millis + 500) / 1000); }
20370b57cec5SDimitry Andric 
20380b57cec5SDimitry Andric /* Calculate the elapsed wall clock time for the user */
__kmp_elapsed(double * t)20390b57cec5SDimitry Andric void __kmp_elapsed(double *t) {
20400b57cec5SDimitry Andric   int status;
20410b57cec5SDimitry Andric #ifdef FIX_SGI_CLOCK
20420b57cec5SDimitry Andric   struct timespec ts;
20430b57cec5SDimitry Andric 
20440b57cec5SDimitry Andric   status = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
20450b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL_ERRNO("clock_gettime", status);
20460b57cec5SDimitry Andric   *t =
20470b57cec5SDimitry Andric       (double)ts.tv_nsec * (1.0 / (double)KMP_NSEC_PER_SEC) + (double)ts.tv_sec;
20480b57cec5SDimitry Andric #else
20490b57cec5SDimitry Andric   struct timeval tv;
20500b57cec5SDimitry Andric 
20510b57cec5SDimitry Andric   status = gettimeofday(&tv, NULL);
20520b57cec5SDimitry Andric   KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status);
20530b57cec5SDimitry Andric   *t =
20540b57cec5SDimitry Andric       (double)tv.tv_usec * (1.0 / (double)KMP_USEC_PER_SEC) + (double)tv.tv_sec;
20550b57cec5SDimitry Andric #endif
20560b57cec5SDimitry Andric }
20570b57cec5SDimitry Andric 
20580b57cec5SDimitry Andric /* Calculate the elapsed wall clock tick for the user */
__kmp_elapsed_tick(double * t)20590b57cec5SDimitry Andric void __kmp_elapsed_tick(double *t) { *t = 1 / (double)CLOCKS_PER_SEC; }
20600b57cec5SDimitry Andric 
20610b57cec5SDimitry Andric /* Return the current time stamp in nsec */
__kmp_now_nsec()20620b57cec5SDimitry Andric kmp_uint64 __kmp_now_nsec() {
20630b57cec5SDimitry Andric   struct timeval t;
20640b57cec5SDimitry Andric   gettimeofday(&t, NULL);
20650b57cec5SDimitry Andric   kmp_uint64 nsec = (kmp_uint64)KMP_NSEC_PER_SEC * (kmp_uint64)t.tv_sec +
20660b57cec5SDimitry Andric                     (kmp_uint64)1000 * (kmp_uint64)t.tv_usec;
20670b57cec5SDimitry Andric   return nsec;
20680b57cec5SDimitry Andric }
20690b57cec5SDimitry Andric 
20700b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
20710b57cec5SDimitry Andric /* Measure clock ticks per millisecond */
__kmp_initialize_system_tick()20720b57cec5SDimitry Andric void __kmp_initialize_system_tick() {
20730b57cec5SDimitry Andric   kmp_uint64 now, nsec2, diff;
20745f757f3fSDimitry Andric   kmp_uint64 delay = 1000000; // ~450 usec on most machines.
20750b57cec5SDimitry Andric   kmp_uint64 nsec = __kmp_now_nsec();
20760b57cec5SDimitry Andric   kmp_uint64 goal = __kmp_hardware_timestamp() + delay;
20770b57cec5SDimitry Andric   while ((now = __kmp_hardware_timestamp()) < goal)
20780b57cec5SDimitry Andric     ;
20790b57cec5SDimitry Andric   nsec2 = __kmp_now_nsec();
20800b57cec5SDimitry Andric   diff = nsec2 - nsec;
20810b57cec5SDimitry Andric   if (diff > 0) {
20825f757f3fSDimitry Andric     double tpus = 1000.0 * (double)(delay + (now - goal)) / (double)diff;
20835f757f3fSDimitry Andric     if (tpus > 0.0) {
20845f757f3fSDimitry Andric       __kmp_ticks_per_msec = (kmp_uint64)(tpus * 1000.0);
20855f757f3fSDimitry Andric       __kmp_ticks_per_usec = (kmp_uint64)tpus;
20865f757f3fSDimitry Andric     }
20870b57cec5SDimitry Andric   }
20880b57cec5SDimitry Andric }
20890b57cec5SDimitry Andric #endif
20900b57cec5SDimitry Andric 
20910b57cec5SDimitry Andric /* Determine whether the given address is mapped into the current address
20920b57cec5SDimitry Andric    space. */
20930b57cec5SDimitry Andric 
__kmp_is_address_mapped(void * addr)20940b57cec5SDimitry Andric int __kmp_is_address_mapped(void *addr) {
20950b57cec5SDimitry Andric 
20960b57cec5SDimitry Andric   int found = 0;
20970b57cec5SDimitry Andric   int rc;
20980b57cec5SDimitry Andric 
2099489b1cf2SDimitry Andric #if KMP_OS_LINUX || KMP_OS_HURD
21000b57cec5SDimitry Andric 
2101fe6060f1SDimitry Andric   /* On GNUish OSes, read the /proc/<pid>/maps pseudo-file to get all the
2102fe6060f1SDimitry Andric      address ranges mapped into the address space. */
21030b57cec5SDimitry Andric 
21040b57cec5SDimitry Andric   char *name = __kmp_str_format("/proc/%d/maps", getpid());
21050b57cec5SDimitry Andric   FILE *file = NULL;
21060b57cec5SDimitry Andric 
21070b57cec5SDimitry Andric   file = fopen(name, "r");
21080b57cec5SDimitry Andric   KMP_ASSERT(file != NULL);
21090b57cec5SDimitry Andric 
21100b57cec5SDimitry Andric   for (;;) {
21110b57cec5SDimitry Andric 
21120b57cec5SDimitry Andric     void *beginning = NULL;
21130b57cec5SDimitry Andric     void *ending = NULL;
21140b57cec5SDimitry Andric     char perms[5];
21150b57cec5SDimitry Andric 
21160b57cec5SDimitry Andric     rc = fscanf(file, "%p-%p %4s %*[^\n]\n", &beginning, &ending, perms);
21170b57cec5SDimitry Andric     if (rc == EOF) {
21180b57cec5SDimitry Andric       break;
21190b57cec5SDimitry Andric     }
21200b57cec5SDimitry Andric     KMP_ASSERT(rc == 3 &&
21210b57cec5SDimitry Andric                KMP_STRLEN(perms) == 4); // Make sure all fields are read.
21220b57cec5SDimitry Andric 
21230b57cec5SDimitry Andric     // Ending address is not included in the region, but beginning is.
21240b57cec5SDimitry Andric     if ((addr >= beginning) && (addr < ending)) {
21250b57cec5SDimitry Andric       perms[2] = 0; // 3th and 4th character does not matter.
21260b57cec5SDimitry Andric       if (strcmp(perms, "rw") == 0) {
21270b57cec5SDimitry Andric         // Memory we are looking for should be readable and writable.
21280b57cec5SDimitry Andric         found = 1;
21290b57cec5SDimitry Andric       }
21300b57cec5SDimitry Andric       break;
21310b57cec5SDimitry Andric     }
21320b57cec5SDimitry Andric   }
21330b57cec5SDimitry Andric 
21340b57cec5SDimitry Andric   // Free resources.
21350b57cec5SDimitry Andric   fclose(file);
21360b57cec5SDimitry Andric   KMP_INTERNAL_FREE(name);
2137489b1cf2SDimitry Andric #elif KMP_OS_FREEBSD
2138489b1cf2SDimitry Andric   char *buf;
2139489b1cf2SDimitry Andric   size_t lstsz;
2140489b1cf2SDimitry Andric   int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()};
2141489b1cf2SDimitry Andric   rc = sysctl(mib, 4, NULL, &lstsz, NULL, 0);
2142489b1cf2SDimitry Andric   if (rc < 0)
2143489b1cf2SDimitry Andric     return 0;
2144489b1cf2SDimitry Andric   // We pass from number of vm entry's semantic
2145489b1cf2SDimitry Andric   // to size of whole entry map list.
2146489b1cf2SDimitry Andric   lstsz = lstsz * 4 / 3;
2147da15ed2eSDimitry Andric   buf = reinterpret_cast<char *>(KMP_INTERNAL_MALLOC(lstsz));
2148489b1cf2SDimitry Andric   rc = sysctl(mib, 4, buf, &lstsz, NULL, 0);
2149489b1cf2SDimitry Andric   if (rc < 0) {
2150da15ed2eSDimitry Andric     KMP_INTERNAL_FREE(buf);
2151489b1cf2SDimitry Andric     return 0;
2152489b1cf2SDimitry Andric   }
2153489b1cf2SDimitry Andric 
2154489b1cf2SDimitry Andric   char *lw = buf;
2155489b1cf2SDimitry Andric   char *up = buf + lstsz;
2156489b1cf2SDimitry Andric 
2157489b1cf2SDimitry Andric   while (lw < up) {
2158489b1cf2SDimitry Andric     struct kinfo_vmentry *cur = reinterpret_cast<struct kinfo_vmentry *>(lw);
2159489b1cf2SDimitry Andric     size_t cursz = cur->kve_structsize;
2160489b1cf2SDimitry Andric     if (cursz == 0)
2161489b1cf2SDimitry Andric       break;
2162489b1cf2SDimitry Andric     void *start = reinterpret_cast<void *>(cur->kve_start);
2163489b1cf2SDimitry Andric     void *end = reinterpret_cast<void *>(cur->kve_end);
2164489b1cf2SDimitry Andric     // Readable/Writable addresses within current map entry
2165489b1cf2SDimitry Andric     if ((addr >= start) && (addr < end)) {
2166489b1cf2SDimitry Andric       if ((cur->kve_protection & KVME_PROT_READ) != 0 &&
2167489b1cf2SDimitry Andric           (cur->kve_protection & KVME_PROT_WRITE) != 0) {
2168489b1cf2SDimitry Andric         found = 1;
2169489b1cf2SDimitry Andric         break;
2170489b1cf2SDimitry Andric       }
2171489b1cf2SDimitry Andric     }
2172489b1cf2SDimitry Andric     lw += cursz;
2173489b1cf2SDimitry Andric   }
2174da15ed2eSDimitry Andric   KMP_INTERNAL_FREE(buf);
2175*0fca6ea1SDimitry Andric #elif KMP_OS_DRAGONFLY
2176*0fca6ea1SDimitry Andric   char err[_POSIX2_LINE_MAX];
2177*0fca6ea1SDimitry Andric   kinfo_proc *proc;
2178*0fca6ea1SDimitry Andric   vmspace sp;
2179*0fca6ea1SDimitry Andric   vm_map *cur;
2180*0fca6ea1SDimitry Andric   vm_map_entry entry, *c;
2181*0fca6ea1SDimitry Andric   struct proc p;
2182*0fca6ea1SDimitry Andric   kvm_t *fd;
2183*0fca6ea1SDimitry Andric   uintptr_t uaddr;
2184*0fca6ea1SDimitry Andric   int num;
21850b57cec5SDimitry Andric 
2186*0fca6ea1SDimitry Andric   fd = kvm_openfiles(nullptr, nullptr, nullptr, O_RDONLY, err);
2187*0fca6ea1SDimitry Andric   if (!fd) {
2188*0fca6ea1SDimitry Andric     return 0;
2189*0fca6ea1SDimitry Andric   }
2190*0fca6ea1SDimitry Andric 
2191*0fca6ea1SDimitry Andric   proc = kvm_getprocs(fd, KERN_PROC_PID, getpid(), &num);
2192*0fca6ea1SDimitry Andric 
2193*0fca6ea1SDimitry Andric   if (kvm_read(fd, static_cast<uintptr_t>(proc->kp_paddr), &p, sizeof(p)) !=
2194*0fca6ea1SDimitry Andric           sizeof(p) ||
2195*0fca6ea1SDimitry Andric       kvm_read(fd, reinterpret_cast<uintptr_t>(p.p_vmspace), &sp, sizeof(sp)) !=
2196*0fca6ea1SDimitry Andric           sizeof(sp)) {
2197*0fca6ea1SDimitry Andric     kvm_close(fd);
2198*0fca6ea1SDimitry Andric     return 0;
2199*0fca6ea1SDimitry Andric   }
2200*0fca6ea1SDimitry Andric 
2201*0fca6ea1SDimitry Andric   (void)rc;
2202*0fca6ea1SDimitry Andric   cur = &sp.vm_map;
2203*0fca6ea1SDimitry Andric   uaddr = reinterpret_cast<uintptr_t>(addr);
2204*0fca6ea1SDimitry Andric   for (c = kvm_vm_map_entry_first(fd, cur, &entry); c;
2205*0fca6ea1SDimitry Andric        c = kvm_vm_map_entry_next(fd, c, &entry)) {
2206*0fca6ea1SDimitry Andric     if ((uaddr >= entry.ba.start) && (uaddr <= entry.ba.end)) {
2207*0fca6ea1SDimitry Andric       if ((entry.protection & VM_PROT_READ) != 0 &&
2208*0fca6ea1SDimitry Andric           (entry.protection & VM_PROT_WRITE) != 0) {
2209*0fca6ea1SDimitry Andric         found = 1;
2210*0fca6ea1SDimitry Andric         break;
2211*0fca6ea1SDimitry Andric       }
2212*0fca6ea1SDimitry Andric     }
2213*0fca6ea1SDimitry Andric   }
2214*0fca6ea1SDimitry Andric 
2215*0fca6ea1SDimitry Andric   kvm_close(fd);
2216*0fca6ea1SDimitry Andric #elif KMP_OS_SOLARIS
2217*0fca6ea1SDimitry Andric   prmap_t *cur, *map;
2218*0fca6ea1SDimitry Andric   void *buf;
2219*0fca6ea1SDimitry Andric   uintptr_t uaddr;
2220*0fca6ea1SDimitry Andric   ssize_t rd;
2221*0fca6ea1SDimitry Andric   int err;
2222*0fca6ea1SDimitry Andric   int file;
2223*0fca6ea1SDimitry Andric 
2224*0fca6ea1SDimitry Andric   pid_t pid = getpid();
2225*0fca6ea1SDimitry Andric   struct ps_prochandle *fd = Pgrab(pid, PGRAB_RDONLY, &err);
2226*0fca6ea1SDimitry Andric   ;
2227*0fca6ea1SDimitry Andric 
2228*0fca6ea1SDimitry Andric   if (!fd) {
2229*0fca6ea1SDimitry Andric     return 0;
2230*0fca6ea1SDimitry Andric   }
2231*0fca6ea1SDimitry Andric 
2232*0fca6ea1SDimitry Andric   char *name = __kmp_str_format("/proc/%d/map", pid);
2233*0fca6ea1SDimitry Andric   size_t sz = (1 << 20);
2234*0fca6ea1SDimitry Andric   file = open(name, O_RDONLY);
2235*0fca6ea1SDimitry Andric   if (file == -1) {
2236*0fca6ea1SDimitry Andric     KMP_INTERNAL_FREE(name);
2237*0fca6ea1SDimitry Andric     return 0;
2238*0fca6ea1SDimitry Andric   }
2239*0fca6ea1SDimitry Andric 
2240*0fca6ea1SDimitry Andric   buf = KMP_INTERNAL_MALLOC(sz);
2241*0fca6ea1SDimitry Andric 
2242*0fca6ea1SDimitry Andric   while (sz > 0 && (rd = pread(file, buf, sz, 0)) == sz) {
2243*0fca6ea1SDimitry Andric     void *newbuf;
2244*0fca6ea1SDimitry Andric     sz <<= 1;
2245*0fca6ea1SDimitry Andric     newbuf = KMP_INTERNAL_REALLOC(buf, sz);
2246*0fca6ea1SDimitry Andric     buf = newbuf;
2247*0fca6ea1SDimitry Andric   }
2248*0fca6ea1SDimitry Andric 
2249*0fca6ea1SDimitry Andric   map = reinterpret_cast<prmap_t *>(buf);
2250*0fca6ea1SDimitry Andric   uaddr = reinterpret_cast<uintptr_t>(addr);
2251*0fca6ea1SDimitry Andric 
2252*0fca6ea1SDimitry Andric   for (cur = map; rd > 0; cur++, rd = -sizeof(*map)) {
2253*0fca6ea1SDimitry Andric     if ((uaddr >= cur->pr_vaddr) && (uaddr < cur->pr_vaddr)) {
2254*0fca6ea1SDimitry Andric       if ((cur->pr_mflags & MA_READ) != 0 && (cur->pr_mflags & MA_WRITE) != 0) {
2255*0fca6ea1SDimitry Andric         found = 1;
2256*0fca6ea1SDimitry Andric         break;
2257*0fca6ea1SDimitry Andric       }
2258*0fca6ea1SDimitry Andric     }
2259*0fca6ea1SDimitry Andric   }
2260*0fca6ea1SDimitry Andric 
2261*0fca6ea1SDimitry Andric   KMP_INTERNAL_FREE(map);
2262*0fca6ea1SDimitry Andric   close(file);
2263*0fca6ea1SDimitry Andric   KMP_INTERNAL_FREE(name);
22640b57cec5SDimitry Andric #elif KMP_OS_DARWIN
22650b57cec5SDimitry Andric 
22660b57cec5SDimitry Andric   /* On OS X*, /proc pseudo filesystem is not available. Try to read memory
22670b57cec5SDimitry Andric      using vm interface. */
22680b57cec5SDimitry Andric 
22690b57cec5SDimitry Andric   int buffer;
22700b57cec5SDimitry Andric   vm_size_t count;
22710b57cec5SDimitry Andric   rc = vm_read_overwrite(
22720b57cec5SDimitry Andric       mach_task_self(), // Task to read memory of.
22730b57cec5SDimitry Andric       (vm_address_t)(addr), // Address to read from.
22740b57cec5SDimitry Andric       1, // Number of bytes to be read.
22750b57cec5SDimitry Andric       (vm_address_t)(&buffer), // Address of buffer to save read bytes in.
22760b57cec5SDimitry Andric       &count // Address of var to save number of read bytes in.
22770b57cec5SDimitry Andric   );
22780b57cec5SDimitry Andric   if (rc == 0) {
22790b57cec5SDimitry Andric     // Memory successfully read.
22800b57cec5SDimitry Andric     found = 1;
22810b57cec5SDimitry Andric   }
22820b57cec5SDimitry Andric 
22830b57cec5SDimitry Andric #elif KMP_OS_NETBSD
22840b57cec5SDimitry Andric 
22850b57cec5SDimitry Andric   int mib[5];
22860b57cec5SDimitry Andric   mib[0] = CTL_VM;
22870b57cec5SDimitry Andric   mib[1] = VM_PROC;
22880b57cec5SDimitry Andric   mib[2] = VM_PROC_MAP;
22890b57cec5SDimitry Andric   mib[3] = getpid();
22900b57cec5SDimitry Andric   mib[4] = sizeof(struct kinfo_vmentry);
22910b57cec5SDimitry Andric 
22920b57cec5SDimitry Andric   size_t size;
22930b57cec5SDimitry Andric   rc = sysctl(mib, __arraycount(mib), NULL, &size, NULL, 0);
22940b57cec5SDimitry Andric   KMP_ASSERT(!rc);
22950b57cec5SDimitry Andric   KMP_ASSERT(size);
22960b57cec5SDimitry Andric 
22970b57cec5SDimitry Andric   size = size * 4 / 3;
22980b57cec5SDimitry Andric   struct kinfo_vmentry *kiv = (struct kinfo_vmentry *)KMP_INTERNAL_MALLOC(size);
22990b57cec5SDimitry Andric   KMP_ASSERT(kiv);
23000b57cec5SDimitry Andric 
23010b57cec5SDimitry Andric   rc = sysctl(mib, __arraycount(mib), kiv, &size, NULL, 0);
23020b57cec5SDimitry Andric   KMP_ASSERT(!rc);
23030b57cec5SDimitry Andric   KMP_ASSERT(size);
23040b57cec5SDimitry Andric 
23050b57cec5SDimitry Andric   for (size_t i = 0; i < size; i++) {
23060b57cec5SDimitry Andric     if (kiv[i].kve_start >= (uint64_t)addr &&
23070b57cec5SDimitry Andric         kiv[i].kve_end <= (uint64_t)addr) {
23080b57cec5SDimitry Andric       found = 1;
23090b57cec5SDimitry Andric       break;
23100b57cec5SDimitry Andric     }
23110b57cec5SDimitry Andric   }
23120b57cec5SDimitry Andric   KMP_INTERNAL_FREE(kiv);
2313480093f4SDimitry Andric #elif KMP_OS_OPENBSD
23140b57cec5SDimitry Andric 
2315480093f4SDimitry Andric   int mib[3];
2316480093f4SDimitry Andric   mib[0] = CTL_KERN;
2317480093f4SDimitry Andric   mib[1] = KERN_PROC_VMMAP;
2318480093f4SDimitry Andric   mib[2] = getpid();
2319480093f4SDimitry Andric 
2320480093f4SDimitry Andric   size_t size;
2321480093f4SDimitry Andric   uint64_t end;
2322480093f4SDimitry Andric   rc = sysctl(mib, 3, NULL, &size, NULL, 0);
2323480093f4SDimitry Andric   KMP_ASSERT(!rc);
2324480093f4SDimitry Andric   KMP_ASSERT(size);
2325480093f4SDimitry Andric   end = size;
2326480093f4SDimitry Andric 
2327480093f4SDimitry Andric   struct kinfo_vmentry kiv = {.kve_start = 0};
2328480093f4SDimitry Andric 
2329480093f4SDimitry Andric   while ((rc = sysctl(mib, 3, &kiv, &size, NULL, 0)) == 0) {
2330480093f4SDimitry Andric     KMP_ASSERT(size);
2331480093f4SDimitry Andric     if (kiv.kve_end == end)
2332480093f4SDimitry Andric       break;
2333480093f4SDimitry Andric 
2334480093f4SDimitry Andric     if (kiv.kve_start >= (uint64_t)addr && kiv.kve_end <= (uint64_t)addr) {
2335480093f4SDimitry Andric       found = 1;
2336480093f4SDimitry Andric       break;
2337480093f4SDimitry Andric     }
2338480093f4SDimitry Andric     kiv.kve_start += 1;
2339480093f4SDimitry Andric   }
23405f757f3fSDimitry Andric #elif KMP_OS_WASI
23415f757f3fSDimitry Andric   found = (int)addr < (__builtin_wasm_memory_size(0) * PAGESIZE);
2342*0fca6ea1SDimitry Andric #elif KMP_OS_AIX
2343480093f4SDimitry Andric 
2344*0fca6ea1SDimitry Andric   uint32_t loadQueryBufSize = 4096u; // Default loadquery buffer size.
2345*0fca6ea1SDimitry Andric   char *loadQueryBuf;
2346*0fca6ea1SDimitry Andric 
2347*0fca6ea1SDimitry Andric   for (;;) {
2348*0fca6ea1SDimitry Andric     loadQueryBuf = (char *)KMP_INTERNAL_MALLOC(loadQueryBufSize);
2349*0fca6ea1SDimitry Andric     if (loadQueryBuf == NULL) {
2350*0fca6ea1SDimitry Andric       return 0;
2351*0fca6ea1SDimitry Andric     }
2352*0fca6ea1SDimitry Andric 
2353*0fca6ea1SDimitry Andric     rc = loadquery(L_GETXINFO | L_IGNOREUNLOAD, loadQueryBuf, loadQueryBufSize);
2354*0fca6ea1SDimitry Andric     if (rc < 0) {
2355*0fca6ea1SDimitry Andric       KMP_INTERNAL_FREE(loadQueryBuf);
2356*0fca6ea1SDimitry Andric       if (errno != ENOMEM) {
2357*0fca6ea1SDimitry Andric         return 0;
2358*0fca6ea1SDimitry Andric       }
2359*0fca6ea1SDimitry Andric       // errno == ENOMEM; double the size.
2360*0fca6ea1SDimitry Andric       loadQueryBufSize <<= 1;
2361*0fca6ea1SDimitry Andric       continue;
2362*0fca6ea1SDimitry Andric     }
2363*0fca6ea1SDimitry Andric     // Obtained the load info successfully.
2364*0fca6ea1SDimitry Andric     break;
2365*0fca6ea1SDimitry Andric   }
2366*0fca6ea1SDimitry Andric 
2367*0fca6ea1SDimitry Andric   struct ld_xinfo *curLdInfo = (struct ld_xinfo *)loadQueryBuf;
2368*0fca6ea1SDimitry Andric 
2369*0fca6ea1SDimitry Andric   // Loop through the load info to find if there is a match.
2370*0fca6ea1SDimitry Andric   for (;;) {
2371*0fca6ea1SDimitry Andric     uintptr_t curDataStart = (uintptr_t)curLdInfo->ldinfo_dataorg;
2372*0fca6ea1SDimitry Andric     uintptr_t curDataEnd = curDataStart + curLdInfo->ldinfo_datasize;
2373*0fca6ea1SDimitry Andric 
2374*0fca6ea1SDimitry Andric     // The data segment is readable and writable.
2375*0fca6ea1SDimitry Andric     if (curDataStart <= (uintptr_t)addr && (uintptr_t)addr < curDataEnd) {
23760b57cec5SDimitry Andric       found = 1;
2377*0fca6ea1SDimitry Andric       break;
2378*0fca6ea1SDimitry Andric     }
2379*0fca6ea1SDimitry Andric     if (curLdInfo->ldinfo_next == 0u) {
2380*0fca6ea1SDimitry Andric       // Reached the end of load info.
2381*0fca6ea1SDimitry Andric       break;
2382*0fca6ea1SDimitry Andric     }
2383*0fca6ea1SDimitry Andric     curLdInfo = (struct ld_xinfo *)((char *)curLdInfo + curLdInfo->ldinfo_next);
2384*0fca6ea1SDimitry Andric   }
2385*0fca6ea1SDimitry Andric   KMP_INTERNAL_FREE(loadQueryBuf);
23860b57cec5SDimitry Andric 
23870b57cec5SDimitry Andric #else
23880b57cec5SDimitry Andric 
23890b57cec5SDimitry Andric #error "Unknown or unsupported OS"
23900b57cec5SDimitry Andric 
23910b57cec5SDimitry Andric #endif
23920b57cec5SDimitry Andric 
23930b57cec5SDimitry Andric   return found;
23940b57cec5SDimitry Andric 
23950b57cec5SDimitry Andric } // __kmp_is_address_mapped
23960b57cec5SDimitry Andric 
23970b57cec5SDimitry Andric #ifdef USE_LOAD_BALANCE
23980b57cec5SDimitry Andric 
23995f757f3fSDimitry Andric #if KMP_OS_DARWIN || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD ||    \
24005f757f3fSDimitry Andric     KMP_OS_OPENBSD || KMP_OS_SOLARIS
24010b57cec5SDimitry Andric 
24020b57cec5SDimitry Andric // The function returns the rounded value of the system load average
24030b57cec5SDimitry Andric // during given time interval which depends on the value of
24040b57cec5SDimitry Andric // __kmp_load_balance_interval variable (default is 60 sec, other values
24050b57cec5SDimitry Andric // may be 300 sec or 900 sec).
24060b57cec5SDimitry Andric // It returns -1 in case of error.
__kmp_get_load_balance(int max)24070b57cec5SDimitry Andric int __kmp_get_load_balance(int max) {
24080b57cec5SDimitry Andric   double averages[3];
24090b57cec5SDimitry Andric   int ret_avg = 0;
24100b57cec5SDimitry Andric 
24110b57cec5SDimitry Andric   int res = getloadavg(averages, 3);
24120b57cec5SDimitry Andric 
24130b57cec5SDimitry Andric   // Check __kmp_load_balance_interval to determine which of averages to use.
24140b57cec5SDimitry Andric   // getloadavg() may return the number of samples less than requested that is
24150b57cec5SDimitry Andric   // less than 3.
24160b57cec5SDimitry Andric   if (__kmp_load_balance_interval < 180 && (res >= 1)) {
2417e8d8bef9SDimitry Andric     ret_avg = (int)averages[0]; // 1 min
24180b57cec5SDimitry Andric   } else if ((__kmp_load_balance_interval >= 180 &&
24190b57cec5SDimitry Andric               __kmp_load_balance_interval < 600) &&
24200b57cec5SDimitry Andric              (res >= 2)) {
2421e8d8bef9SDimitry Andric     ret_avg = (int)averages[1]; // 5 min
24220b57cec5SDimitry Andric   } else if ((__kmp_load_balance_interval >= 600) && (res == 3)) {
2423e8d8bef9SDimitry Andric     ret_avg = (int)averages[2]; // 15 min
24240b57cec5SDimitry Andric   } else { // Error occurred
24250b57cec5SDimitry Andric     return -1;
24260b57cec5SDimitry Andric   }
24270b57cec5SDimitry Andric 
24280b57cec5SDimitry Andric   return ret_avg;
24290b57cec5SDimitry Andric }
24300b57cec5SDimitry Andric 
2431*0fca6ea1SDimitry Andric #elif KMP_OS_AIX
2432*0fca6ea1SDimitry Andric 
2433*0fca6ea1SDimitry Andric // The function returns number of running (not sleeping) threads, or -1 in case
2434*0fca6ea1SDimitry Andric // of error.
__kmp_get_load_balance(int max)2435*0fca6ea1SDimitry Andric int __kmp_get_load_balance(int max) {
2436*0fca6ea1SDimitry Andric 
2437*0fca6ea1SDimitry Andric   static int glb_running_threads = 0; // Saved count of the running threads for
2438*0fca6ea1SDimitry Andric                                       // the thread balance algorithm.
2439*0fca6ea1SDimitry Andric   static double glb_call_time = 0; // Thread balance algorithm call time.
2440*0fca6ea1SDimitry Andric   int running_threads = 0; // Number of running threads in the system.
2441*0fca6ea1SDimitry Andric 
2442*0fca6ea1SDimitry Andric   double call_time = 0.0;
2443*0fca6ea1SDimitry Andric 
2444*0fca6ea1SDimitry Andric   __kmp_elapsed(&call_time);
2445*0fca6ea1SDimitry Andric 
2446*0fca6ea1SDimitry Andric   if (glb_call_time &&
2447*0fca6ea1SDimitry Andric       (call_time - glb_call_time < __kmp_load_balance_interval))
2448*0fca6ea1SDimitry Andric     return glb_running_threads;
2449*0fca6ea1SDimitry Andric 
2450*0fca6ea1SDimitry Andric   glb_call_time = call_time;
2451*0fca6ea1SDimitry Andric 
2452*0fca6ea1SDimitry Andric   if (max <= 0) {
2453*0fca6ea1SDimitry Andric     max = INT_MAX;
2454*0fca6ea1SDimitry Andric   }
2455*0fca6ea1SDimitry Andric 
2456*0fca6ea1SDimitry Andric   // Check how many perfstat_cpu_t structures are available.
2457*0fca6ea1SDimitry Andric   int logical_cpus = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);
2458*0fca6ea1SDimitry Andric   if (logical_cpus <= 0) {
2459*0fca6ea1SDimitry Andric     glb_call_time = -1;
2460*0fca6ea1SDimitry Andric     return -1;
2461*0fca6ea1SDimitry Andric   }
2462*0fca6ea1SDimitry Andric 
2463*0fca6ea1SDimitry Andric   perfstat_cpu_t *cpu_stat = (perfstat_cpu_t *)KMP_INTERNAL_MALLOC(
2464*0fca6ea1SDimitry Andric       logical_cpus * sizeof(perfstat_cpu_t));
2465*0fca6ea1SDimitry Andric   if (cpu_stat == NULL) {
2466*0fca6ea1SDimitry Andric     glb_call_time = -1;
2467*0fca6ea1SDimitry Andric     return -1;
2468*0fca6ea1SDimitry Andric   }
2469*0fca6ea1SDimitry Andric 
2470*0fca6ea1SDimitry Andric   // Set first CPU as the name of the first logical CPU for which the info is
2471*0fca6ea1SDimitry Andric   // desired.
2472*0fca6ea1SDimitry Andric   perfstat_id_t first_cpu_name;
2473*0fca6ea1SDimitry Andric   strcpy(first_cpu_name.name, FIRST_CPU);
2474*0fca6ea1SDimitry Andric 
2475*0fca6ea1SDimitry Andric   // Get the stat info of logical CPUs.
2476*0fca6ea1SDimitry Andric   int rc = perfstat_cpu(&first_cpu_name, cpu_stat, sizeof(perfstat_cpu_t),
2477*0fca6ea1SDimitry Andric                         logical_cpus);
2478*0fca6ea1SDimitry Andric   KMP_DEBUG_ASSERT(rc == logical_cpus);
2479*0fca6ea1SDimitry Andric   if (rc <= 0) {
2480*0fca6ea1SDimitry Andric     KMP_INTERNAL_FREE(cpu_stat);
2481*0fca6ea1SDimitry Andric     glb_call_time = -1;
2482*0fca6ea1SDimitry Andric     return -1;
2483*0fca6ea1SDimitry Andric   }
2484*0fca6ea1SDimitry Andric   for (int i = 0; i < logical_cpus; ++i) {
2485*0fca6ea1SDimitry Andric     running_threads += cpu_stat[i].runque;
2486*0fca6ea1SDimitry Andric     if (running_threads >= max)
2487*0fca6ea1SDimitry Andric       break;
2488*0fca6ea1SDimitry Andric   }
2489*0fca6ea1SDimitry Andric 
2490*0fca6ea1SDimitry Andric   // There _might_ be a timing hole where the thread executing this
2491*0fca6ea1SDimitry Andric   // code gets skipped in the load balance, and running_threads is 0.
2492*0fca6ea1SDimitry Andric   // Assert in the debug builds only!!!
2493*0fca6ea1SDimitry Andric   KMP_DEBUG_ASSERT(running_threads > 0);
2494*0fca6ea1SDimitry Andric   if (running_threads <= 0)
2495*0fca6ea1SDimitry Andric     running_threads = 1;
2496*0fca6ea1SDimitry Andric 
2497*0fca6ea1SDimitry Andric   KMP_INTERNAL_FREE(cpu_stat);
2498*0fca6ea1SDimitry Andric 
2499*0fca6ea1SDimitry Andric   glb_running_threads = running_threads;
2500*0fca6ea1SDimitry Andric 
2501*0fca6ea1SDimitry Andric   return running_threads;
2502*0fca6ea1SDimitry Andric }
2503*0fca6ea1SDimitry Andric 
25040b57cec5SDimitry Andric #else // Linux* OS
25050b57cec5SDimitry Andric 
25065ffd83dbSDimitry Andric // The function returns number of running (not sleeping) threads, or -1 in case
25070b57cec5SDimitry Andric // of error. Error could be reported if Linux* OS kernel too old (without
25080b57cec5SDimitry Andric // "/proc" support). Counting running threads stops if max running threads
25090b57cec5SDimitry Andric // encountered.
__kmp_get_load_balance(int max)25100b57cec5SDimitry Andric int __kmp_get_load_balance(int max) {
25110b57cec5SDimitry Andric   static int permanent_error = 0;
25120b57cec5SDimitry Andric   static int glb_running_threads = 0; // Saved count of the running threads for
2513480093f4SDimitry Andric   // the thread balance algorithm
25140b57cec5SDimitry Andric   static double glb_call_time = 0; /* Thread balance algorithm call time */
25150b57cec5SDimitry Andric 
25160b57cec5SDimitry Andric   int running_threads = 0; // Number of running threads in the system.
25170b57cec5SDimitry Andric 
25180b57cec5SDimitry Andric   DIR *proc_dir = NULL; // Handle of "/proc/" directory.
25190b57cec5SDimitry Andric   struct dirent *proc_entry = NULL;
25200b57cec5SDimitry Andric 
25210b57cec5SDimitry Andric   kmp_str_buf_t task_path; // "/proc/<pid>/task/<tid>/" path.
25220b57cec5SDimitry Andric   DIR *task_dir = NULL; // Handle of "/proc/<pid>/task/<tid>/" directory.
25230b57cec5SDimitry Andric   struct dirent *task_entry = NULL;
25240b57cec5SDimitry Andric   int task_path_fixed_len;
25250b57cec5SDimitry Andric 
25260b57cec5SDimitry Andric   kmp_str_buf_t stat_path; // "/proc/<pid>/task/<tid>/stat" path.
25270b57cec5SDimitry Andric   int stat_file = -1;
25280b57cec5SDimitry Andric   int stat_path_fixed_len;
25290b57cec5SDimitry Andric 
2530bdd1243dSDimitry Andric #ifdef KMP_DEBUG
25310b57cec5SDimitry Andric   int total_processes = 0; // Total number of processes in system.
2532bdd1243dSDimitry Andric #endif
25330b57cec5SDimitry Andric 
25340b57cec5SDimitry Andric   double call_time = 0.0;
25350b57cec5SDimitry Andric 
25360b57cec5SDimitry Andric   __kmp_str_buf_init(&task_path);
25370b57cec5SDimitry Andric   __kmp_str_buf_init(&stat_path);
25380b57cec5SDimitry Andric 
25390b57cec5SDimitry Andric   __kmp_elapsed(&call_time);
25400b57cec5SDimitry Andric 
25410b57cec5SDimitry Andric   if (glb_call_time &&
25420b57cec5SDimitry Andric       (call_time - glb_call_time < __kmp_load_balance_interval)) {
25430b57cec5SDimitry Andric     running_threads = glb_running_threads;
25440b57cec5SDimitry Andric     goto finish;
25450b57cec5SDimitry Andric   }
25460b57cec5SDimitry Andric 
25470b57cec5SDimitry Andric   glb_call_time = call_time;
25480b57cec5SDimitry Andric 
25490b57cec5SDimitry Andric   // Do not spend time on scanning "/proc/" if we have a permanent error.
25500b57cec5SDimitry Andric   if (permanent_error) {
25510b57cec5SDimitry Andric     running_threads = -1;
25520b57cec5SDimitry Andric     goto finish;
25530b57cec5SDimitry Andric   }
25540b57cec5SDimitry Andric 
25550b57cec5SDimitry Andric   if (max <= 0) {
25560b57cec5SDimitry Andric     max = INT_MAX;
25570b57cec5SDimitry Andric   }
25580b57cec5SDimitry Andric 
25590b57cec5SDimitry Andric   // Open "/proc/" directory.
25600b57cec5SDimitry Andric   proc_dir = opendir("/proc");
25610b57cec5SDimitry Andric   if (proc_dir == NULL) {
25621db9f3b2SDimitry Andric     // Cannot open "/proc/". Probably the kernel does not support it. Return an
25630b57cec5SDimitry Andric     // error now and in subsequent calls.
25640b57cec5SDimitry Andric     running_threads = -1;
25650b57cec5SDimitry Andric     permanent_error = 1;
25660b57cec5SDimitry Andric     goto finish;
25670b57cec5SDimitry Andric   }
25680b57cec5SDimitry Andric 
25690b57cec5SDimitry Andric   // Initialize fixed part of task_path. This part will not change.
25700b57cec5SDimitry Andric   __kmp_str_buf_cat(&task_path, "/proc/", 6);
25710b57cec5SDimitry Andric   task_path_fixed_len = task_path.used; // Remember number of used characters.
25720b57cec5SDimitry Andric 
25730b57cec5SDimitry Andric   proc_entry = readdir(proc_dir);
25740b57cec5SDimitry Andric   while (proc_entry != NULL) {
25750b57cec5SDimitry Andric     // Proc entry is a directory and name starts with a digit. Assume it is a
25760b57cec5SDimitry Andric     // process' directory.
25770b57cec5SDimitry Andric     if (proc_entry->d_type == DT_DIR && isdigit(proc_entry->d_name[0])) {
25780b57cec5SDimitry Andric 
2579bdd1243dSDimitry Andric #ifdef KMP_DEBUG
25800b57cec5SDimitry Andric       ++total_processes;
2581bdd1243dSDimitry Andric #endif
25820b57cec5SDimitry Andric       // Make sure init process is the very first in "/proc", so we can replace
25830b57cec5SDimitry Andric       // strcmp( proc_entry->d_name, "1" ) == 0 with simpler total_processes ==
25840b57cec5SDimitry Andric       // 1. We are going to check that total_processes == 1 => d_name == "1" is
25850b57cec5SDimitry Andric       // true (where "=>" is implication). Since C++ does not have => operator,
25860b57cec5SDimitry Andric       // let us replace it with its equivalent: a => b == ! a || b.
25870b57cec5SDimitry Andric       KMP_DEBUG_ASSERT(total_processes != 1 ||
25880b57cec5SDimitry Andric                        strcmp(proc_entry->d_name, "1") == 0);
25890b57cec5SDimitry Andric 
25900b57cec5SDimitry Andric       // Construct task_path.
25910b57cec5SDimitry Andric       task_path.used = task_path_fixed_len; // Reset task_path to "/proc/".
25920b57cec5SDimitry Andric       __kmp_str_buf_cat(&task_path, proc_entry->d_name,
25930b57cec5SDimitry Andric                         KMP_STRLEN(proc_entry->d_name));
25940b57cec5SDimitry Andric       __kmp_str_buf_cat(&task_path, "/task", 5);
25950b57cec5SDimitry Andric 
25960b57cec5SDimitry Andric       task_dir = opendir(task_path.str);
25970b57cec5SDimitry Andric       if (task_dir == NULL) {
25980b57cec5SDimitry Andric         // Process can finish between reading "/proc/" directory entry and
25990b57cec5SDimitry Andric         // opening process' "task/" directory. So, in general case we should not
26000b57cec5SDimitry Andric         // complain, but have to skip this process and read the next one. But on
26010b57cec5SDimitry Andric         // systems with no "task/" support we will spend lot of time to scan
26020b57cec5SDimitry Andric         // "/proc/" tree again and again without any benefit. "init" process
26030b57cec5SDimitry Andric         // (its pid is 1) should exist always, so, if we cannot open
26040b57cec5SDimitry Andric         // "/proc/1/task/" directory, it means "task/" is not supported by
26050b57cec5SDimitry Andric         // kernel. Report an error now and in the future.
26060b57cec5SDimitry Andric         if (strcmp(proc_entry->d_name, "1") == 0) {
26070b57cec5SDimitry Andric           running_threads = -1;
26080b57cec5SDimitry Andric           permanent_error = 1;
26090b57cec5SDimitry Andric           goto finish;
26100b57cec5SDimitry Andric         }
26110b57cec5SDimitry Andric       } else {
26120b57cec5SDimitry Andric         // Construct fixed part of stat file path.
26130b57cec5SDimitry Andric         __kmp_str_buf_clear(&stat_path);
26140b57cec5SDimitry Andric         __kmp_str_buf_cat(&stat_path, task_path.str, task_path.used);
26150b57cec5SDimitry Andric         __kmp_str_buf_cat(&stat_path, "/", 1);
26160b57cec5SDimitry Andric         stat_path_fixed_len = stat_path.used;
26170b57cec5SDimitry Andric 
26180b57cec5SDimitry Andric         task_entry = readdir(task_dir);
26190b57cec5SDimitry Andric         while (task_entry != NULL) {
26200b57cec5SDimitry Andric           // It is a directory and name starts with a digit.
26210b57cec5SDimitry Andric           if (proc_entry->d_type == DT_DIR && isdigit(task_entry->d_name[0])) {
26220b57cec5SDimitry Andric 
2623480093f4SDimitry Andric             // Construct complete stat file path. Easiest way would be:
26240b57cec5SDimitry Andric             //  __kmp_str_buf_print( & stat_path, "%s/%s/stat", task_path.str,
26250b57cec5SDimitry Andric             //  task_entry->d_name );
26260b57cec5SDimitry Andric             // but seriae of __kmp_str_buf_cat works a bit faster.
26270b57cec5SDimitry Andric             stat_path.used =
26280b57cec5SDimitry Andric                 stat_path_fixed_len; // Reset stat path to its fixed part.
26290b57cec5SDimitry Andric             __kmp_str_buf_cat(&stat_path, task_entry->d_name,
26300b57cec5SDimitry Andric                               KMP_STRLEN(task_entry->d_name));
26310b57cec5SDimitry Andric             __kmp_str_buf_cat(&stat_path, "/stat", 5);
26320b57cec5SDimitry Andric 
26330b57cec5SDimitry Andric             // Note: Low-level API (open/read/close) is used. High-level API
26340b57cec5SDimitry Andric             // (fopen/fclose)  works ~ 30 % slower.
26350b57cec5SDimitry Andric             stat_file = open(stat_path.str, O_RDONLY);
26360b57cec5SDimitry Andric             if (stat_file == -1) {
26370b57cec5SDimitry Andric               // We cannot report an error because task (thread) can terminate
26380b57cec5SDimitry Andric               // just before reading this file.
26390b57cec5SDimitry Andric             } else {
26400b57cec5SDimitry Andric               /* Content of "stat" file looks like:
26410b57cec5SDimitry Andric                  24285 (program) S ...
26420b57cec5SDimitry Andric 
26430b57cec5SDimitry Andric                  It is a single line (if program name does not include funny
26440b57cec5SDimitry Andric                  symbols). First number is a thread id, then name of executable
26450b57cec5SDimitry Andric                  file name in paretheses, then state of the thread. We need just
26460b57cec5SDimitry Andric                  thread state.
26470b57cec5SDimitry Andric 
26480b57cec5SDimitry Andric                  Good news: Length of program name is 15 characters max. Longer
26490b57cec5SDimitry Andric                  names are truncated.
26500b57cec5SDimitry Andric 
26510b57cec5SDimitry Andric                  Thus, we need rather short buffer: 15 chars for program name +
26520b57cec5SDimitry Andric                  2 parenthesis, + 3 spaces + ~7 digits of pid = 37.
26530b57cec5SDimitry Andric 
26540b57cec5SDimitry Andric                  Bad news: Program name may contain special symbols like space,
26550b57cec5SDimitry Andric                  closing parenthesis, or even new line. This makes parsing
26560b57cec5SDimitry Andric                  "stat" file not 100 % reliable. In case of fanny program names
26570b57cec5SDimitry Andric                  parsing may fail (report incorrect thread state).
26580b57cec5SDimitry Andric 
26590b57cec5SDimitry Andric                  Parsing "status" file looks more promissing (due to different
26600b57cec5SDimitry Andric                  file structure and escaping special symbols) but reading and
26610b57cec5SDimitry Andric                  parsing of "status" file works slower.
26620b57cec5SDimitry Andric                   -- ln
26630b57cec5SDimitry Andric               */
26640b57cec5SDimitry Andric               char buffer[65];
2665e8d8bef9SDimitry Andric               ssize_t len;
26660b57cec5SDimitry Andric               len = read(stat_file, buffer, sizeof(buffer) - 1);
26670b57cec5SDimitry Andric               if (len >= 0) {
26680b57cec5SDimitry Andric                 buffer[len] = 0;
26690b57cec5SDimitry Andric                 // Using scanf:
26700b57cec5SDimitry Andric                 //     sscanf( buffer, "%*d (%*s) %c ", & state );
26710b57cec5SDimitry Andric                 // looks very nice, but searching for a closing parenthesis
26720b57cec5SDimitry Andric                 // works a bit faster.
26730b57cec5SDimitry Andric                 char *close_parent = strstr(buffer, ") ");
26740b57cec5SDimitry Andric                 if (close_parent != NULL) {
26750b57cec5SDimitry Andric                   char state = *(close_parent + 2);
26760b57cec5SDimitry Andric                   if (state == 'R') {
26770b57cec5SDimitry Andric                     ++running_threads;
26780b57cec5SDimitry Andric                     if (running_threads >= max) {
26790b57cec5SDimitry Andric                       goto finish;
26800b57cec5SDimitry Andric                     }
26810b57cec5SDimitry Andric                   }
26820b57cec5SDimitry Andric                 }
26830b57cec5SDimitry Andric               }
26840b57cec5SDimitry Andric               close(stat_file);
26850b57cec5SDimitry Andric               stat_file = -1;
26860b57cec5SDimitry Andric             }
26870b57cec5SDimitry Andric           }
26880b57cec5SDimitry Andric           task_entry = readdir(task_dir);
26890b57cec5SDimitry Andric         }
26900b57cec5SDimitry Andric         closedir(task_dir);
26910b57cec5SDimitry Andric         task_dir = NULL;
26920b57cec5SDimitry Andric       }
26930b57cec5SDimitry Andric     }
26940b57cec5SDimitry Andric     proc_entry = readdir(proc_dir);
26950b57cec5SDimitry Andric   }
26960b57cec5SDimitry Andric 
26970b57cec5SDimitry Andric   // There _might_ be a timing hole where the thread executing this
26980b57cec5SDimitry Andric   // code get skipped in the load balance, and running_threads is 0.
26990b57cec5SDimitry Andric   // Assert in the debug builds only!!!
27000b57cec5SDimitry Andric   KMP_DEBUG_ASSERT(running_threads > 0);
27010b57cec5SDimitry Andric   if (running_threads <= 0) {
27020b57cec5SDimitry Andric     running_threads = 1;
27030b57cec5SDimitry Andric   }
27040b57cec5SDimitry Andric 
27050b57cec5SDimitry Andric finish: // Clean up and exit.
27060b57cec5SDimitry Andric   if (proc_dir != NULL) {
27070b57cec5SDimitry Andric     closedir(proc_dir);
27080b57cec5SDimitry Andric   }
27090b57cec5SDimitry Andric   __kmp_str_buf_free(&task_path);
27100b57cec5SDimitry Andric   if (task_dir != NULL) {
27110b57cec5SDimitry Andric     closedir(task_dir);
27120b57cec5SDimitry Andric   }
27130b57cec5SDimitry Andric   __kmp_str_buf_free(&stat_path);
27140b57cec5SDimitry Andric   if (stat_file != -1) {
27150b57cec5SDimitry Andric     close(stat_file);
27160b57cec5SDimitry Andric   }
27170b57cec5SDimitry Andric 
27180b57cec5SDimitry Andric   glb_running_threads = running_threads;
27190b57cec5SDimitry Andric 
27200b57cec5SDimitry Andric   return running_threads;
27210b57cec5SDimitry Andric 
27220b57cec5SDimitry Andric } // __kmp_get_load_balance
27230b57cec5SDimitry Andric 
27240b57cec5SDimitry Andric #endif // KMP_OS_DARWIN
27250b57cec5SDimitry Andric 
27260b57cec5SDimitry Andric #endif // USE_LOAD_BALANCE
27270b57cec5SDimitry Andric 
27280b57cec5SDimitry Andric #if !(KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_MIC ||                            \
2729489b1cf2SDimitry Andric       ((KMP_OS_LINUX || KMP_OS_DARWIN) && KMP_ARCH_AARCH64) ||                 \
2730bdd1243dSDimitry Andric       KMP_ARCH_PPC64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 ||            \
2731*0fca6ea1SDimitry Andric       KMP_ARCH_ARM || KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_PPC_XCOFF ||   \
2732*0fca6ea1SDimitry Andric       KMP_ARCH_AARCH64_32)
2733*0fca6ea1SDimitry Andric 
2734*0fca6ea1SDimitry Andric // Because WebAssembly will use `call_indirect` to invoke the microtask and
2735*0fca6ea1SDimitry Andric // WebAssembly indirect calls check that the called signature is a precise
2736*0fca6ea1SDimitry Andric // match, we need to cast each microtask function pointer back from `void *` to
2737*0fca6ea1SDimitry Andric // its original type.
2738*0fca6ea1SDimitry Andric typedef void (*microtask_t0)(int *, int *);
2739*0fca6ea1SDimitry Andric typedef void (*microtask_t1)(int *, int *, void *);
2740*0fca6ea1SDimitry Andric typedef void (*microtask_t2)(int *, int *, void *, void *);
2741*0fca6ea1SDimitry Andric typedef void (*microtask_t3)(int *, int *, void *, void *, void *);
2742*0fca6ea1SDimitry Andric typedef void (*microtask_t4)(int *, int *, void *, void *, void *, void *);
2743*0fca6ea1SDimitry Andric typedef void (*microtask_t5)(int *, int *, void *, void *, void *, void *,
2744*0fca6ea1SDimitry Andric                              void *);
2745*0fca6ea1SDimitry Andric typedef void (*microtask_t6)(int *, int *, void *, void *, void *, void *,
2746*0fca6ea1SDimitry Andric                              void *, void *);
2747*0fca6ea1SDimitry Andric typedef void (*microtask_t7)(int *, int *, void *, void *, void *, void *,
2748*0fca6ea1SDimitry Andric                              void *, void *, void *);
2749*0fca6ea1SDimitry Andric typedef void (*microtask_t8)(int *, int *, void *, void *, void *, void *,
2750*0fca6ea1SDimitry Andric                              void *, void *, void *, void *);
2751*0fca6ea1SDimitry Andric typedef void (*microtask_t9)(int *, int *, void *, void *, void *, void *,
2752*0fca6ea1SDimitry Andric                              void *, void *, void *, void *, void *);
2753*0fca6ea1SDimitry Andric typedef void (*microtask_t10)(int *, int *, void *, void *, void *, void *,
2754*0fca6ea1SDimitry Andric                               void *, void *, void *, void *, void *, void *);
2755*0fca6ea1SDimitry Andric typedef void (*microtask_t11)(int *, int *, void *, void *, void *, void *,
2756*0fca6ea1SDimitry Andric                               void *, void *, void *, void *, void *, void *,
2757*0fca6ea1SDimitry Andric                               void *);
2758*0fca6ea1SDimitry Andric typedef void (*microtask_t12)(int *, int *, void *, void *, void *, void *,
2759*0fca6ea1SDimitry Andric                               void *, void *, void *, void *, void *, void *,
2760*0fca6ea1SDimitry Andric                               void *, void *);
2761*0fca6ea1SDimitry Andric typedef void (*microtask_t13)(int *, int *, void *, void *, void *, void *,
2762*0fca6ea1SDimitry Andric                               void *, void *, void *, void *, void *, void *,
2763*0fca6ea1SDimitry Andric                               void *, void *, void *);
2764*0fca6ea1SDimitry Andric typedef void (*microtask_t14)(int *, int *, void *, void *, void *, void *,
2765*0fca6ea1SDimitry Andric                               void *, void *, void *, void *, void *, void *,
2766*0fca6ea1SDimitry Andric                               void *, void *, void *, void *);
2767*0fca6ea1SDimitry Andric typedef void (*microtask_t15)(int *, int *, void *, void *, void *, void *,
2768*0fca6ea1SDimitry Andric                               void *, void *, void *, void *, void *, void *,
2769*0fca6ea1SDimitry Andric                               void *, void *, void *, void *, void *);
27700b57cec5SDimitry Andric 
27710b57cec5SDimitry Andric // we really only need the case with 1 argument, because CLANG always build
27720b57cec5SDimitry Andric // a struct of pointers to shared variables referenced in the outlined function
__kmp_invoke_microtask(microtask_t pkfn,int gtid,int tid,int argc,void * p_argv[],void ** exit_frame_ptr)27730b57cec5SDimitry Andric int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,
27740b57cec5SDimitry Andric                            void *p_argv[]
27750b57cec5SDimitry Andric #if OMPT_SUPPORT
27760b57cec5SDimitry Andric                            ,
27770b57cec5SDimitry Andric                            void **exit_frame_ptr
27780b57cec5SDimitry Andric #endif
27790b57cec5SDimitry Andric ) {
27800b57cec5SDimitry Andric #if OMPT_SUPPORT
27810b57cec5SDimitry Andric   *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0);
27820b57cec5SDimitry Andric #endif
27830b57cec5SDimitry Andric 
27840b57cec5SDimitry Andric   switch (argc) {
27850b57cec5SDimitry Andric   default:
27860b57cec5SDimitry Andric     fprintf(stderr, "Too many args to microtask: %d!\n", argc);
27870b57cec5SDimitry Andric     fflush(stderr);
27880b57cec5SDimitry Andric     exit(-1);
27890b57cec5SDimitry Andric   case 0:
2790*0fca6ea1SDimitry Andric     (*(microtask_t0)pkfn)(&gtid, &tid);
27910b57cec5SDimitry Andric     break;
27920b57cec5SDimitry Andric   case 1:
2793*0fca6ea1SDimitry Andric     (*(microtask_t1)pkfn)(&gtid, &tid, p_argv[0]);
27940b57cec5SDimitry Andric     break;
27950b57cec5SDimitry Andric   case 2:
2796*0fca6ea1SDimitry Andric     (*(microtask_t2)pkfn)(&gtid, &tid, p_argv[0], p_argv[1]);
27970b57cec5SDimitry Andric     break;
27980b57cec5SDimitry Andric   case 3:
2799*0fca6ea1SDimitry Andric     (*(microtask_t3)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2]);
28000b57cec5SDimitry Andric     break;
28010b57cec5SDimitry Andric   case 4:
2802*0fca6ea1SDimitry Andric     (*(microtask_t4)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
2803*0fca6ea1SDimitry Andric                           p_argv[3]);
28040b57cec5SDimitry Andric     break;
28050b57cec5SDimitry Andric   case 5:
2806*0fca6ea1SDimitry Andric     (*(microtask_t5)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
2807*0fca6ea1SDimitry Andric                           p_argv[3], p_argv[4]);
28080b57cec5SDimitry Andric     break;
28090b57cec5SDimitry Andric   case 6:
2810*0fca6ea1SDimitry Andric     (*(microtask_t6)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
2811*0fca6ea1SDimitry Andric                           p_argv[3], p_argv[4], p_argv[5]);
28120b57cec5SDimitry Andric     break;
28130b57cec5SDimitry Andric   case 7:
2814*0fca6ea1SDimitry Andric     (*(microtask_t7)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
2815*0fca6ea1SDimitry Andric                           p_argv[3], p_argv[4], p_argv[5], p_argv[6]);
28160b57cec5SDimitry Andric     break;
28170b57cec5SDimitry Andric   case 8:
2818*0fca6ea1SDimitry Andric     (*(microtask_t8)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
2819*0fca6ea1SDimitry Andric                           p_argv[3], p_argv[4], p_argv[5], p_argv[6],
2820*0fca6ea1SDimitry Andric                           p_argv[7]);
28210b57cec5SDimitry Andric     break;
28220b57cec5SDimitry Andric   case 9:
2823*0fca6ea1SDimitry Andric     (*(microtask_t9)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
2824*0fca6ea1SDimitry Andric                           p_argv[3], p_argv[4], p_argv[5], p_argv[6], p_argv[7],
2825*0fca6ea1SDimitry Andric                           p_argv[8]);
28260b57cec5SDimitry Andric     break;
28270b57cec5SDimitry Andric   case 10:
2828*0fca6ea1SDimitry Andric     (*(microtask_t10)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
2829*0fca6ea1SDimitry Andric                            p_argv[3], p_argv[4], p_argv[5], p_argv[6],
2830*0fca6ea1SDimitry Andric                            p_argv[7], p_argv[8], p_argv[9]);
28310b57cec5SDimitry Andric     break;
28320b57cec5SDimitry Andric   case 11:
2833*0fca6ea1SDimitry Andric     (*(microtask_t11)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
2834*0fca6ea1SDimitry Andric                            p_argv[3], p_argv[4], p_argv[5], p_argv[6],
2835*0fca6ea1SDimitry Andric                            p_argv[7], p_argv[8], p_argv[9], p_argv[10]);
28360b57cec5SDimitry Andric     break;
28370b57cec5SDimitry Andric   case 12:
2838*0fca6ea1SDimitry Andric     (*(microtask_t12)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
2839*0fca6ea1SDimitry Andric                            p_argv[3], p_argv[4], p_argv[5], p_argv[6],
2840*0fca6ea1SDimitry Andric                            p_argv[7], p_argv[8], p_argv[9], p_argv[10],
28410b57cec5SDimitry Andric                            p_argv[11]);
28420b57cec5SDimitry Andric     break;
28430b57cec5SDimitry Andric   case 13:
2844*0fca6ea1SDimitry Andric     (*(microtask_t13)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
2845*0fca6ea1SDimitry Andric                            p_argv[3], p_argv[4], p_argv[5], p_argv[6],
2846*0fca6ea1SDimitry Andric                            p_argv[7], p_argv[8], p_argv[9], p_argv[10],
28470b57cec5SDimitry Andric                            p_argv[11], p_argv[12]);
28480b57cec5SDimitry Andric     break;
28490b57cec5SDimitry Andric   case 14:
2850*0fca6ea1SDimitry Andric     (*(microtask_t14)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
2851*0fca6ea1SDimitry Andric                            p_argv[3], p_argv[4], p_argv[5], p_argv[6],
2852*0fca6ea1SDimitry Andric                            p_argv[7], p_argv[8], p_argv[9], p_argv[10],
28530b57cec5SDimitry Andric                            p_argv[11], p_argv[12], p_argv[13]);
28540b57cec5SDimitry Andric     break;
28550b57cec5SDimitry Andric   case 15:
2856*0fca6ea1SDimitry Andric     (*(microtask_t15)pkfn)(&gtid, &tid, p_argv[0], p_argv[1], p_argv[2],
2857*0fca6ea1SDimitry Andric                            p_argv[3], p_argv[4], p_argv[5], p_argv[6],
2858*0fca6ea1SDimitry Andric                            p_argv[7], p_argv[8], p_argv[9], p_argv[10],
28590b57cec5SDimitry Andric                            p_argv[11], p_argv[12], p_argv[13], p_argv[14]);
28600b57cec5SDimitry Andric     break;
28610b57cec5SDimitry Andric   }
28620b57cec5SDimitry Andric 
28630b57cec5SDimitry Andric   return 1;
28640b57cec5SDimitry Andric }
28650b57cec5SDimitry Andric 
28660b57cec5SDimitry Andric #endif
28670b57cec5SDimitry Andric 
2868fe6060f1SDimitry Andric #if KMP_OS_LINUX
2869e8d8bef9SDimitry Andric // Functions for hidden helper task
2870e8d8bef9SDimitry Andric namespace {
2871e8d8bef9SDimitry Andric // Condition variable for initializing hidden helper team
2872e8d8bef9SDimitry Andric pthread_cond_t hidden_helper_threads_initz_cond_var;
2873e8d8bef9SDimitry Andric pthread_mutex_t hidden_helper_threads_initz_lock;
2874e8d8bef9SDimitry Andric volatile int hidden_helper_initz_signaled = FALSE;
2875e8d8bef9SDimitry Andric 
2876e8d8bef9SDimitry Andric // Condition variable for deinitializing hidden helper team
2877e8d8bef9SDimitry Andric pthread_cond_t hidden_helper_threads_deinitz_cond_var;
2878e8d8bef9SDimitry Andric pthread_mutex_t hidden_helper_threads_deinitz_lock;
2879e8d8bef9SDimitry Andric volatile int hidden_helper_deinitz_signaled = FALSE;
2880e8d8bef9SDimitry Andric 
2881e8d8bef9SDimitry Andric // Condition variable for the wrapper function of main thread
2882e8d8bef9SDimitry Andric pthread_cond_t hidden_helper_main_thread_cond_var;
2883e8d8bef9SDimitry Andric pthread_mutex_t hidden_helper_main_thread_lock;
2884e8d8bef9SDimitry Andric volatile int hidden_helper_main_thread_signaled = FALSE;
2885e8d8bef9SDimitry Andric 
2886e8d8bef9SDimitry Andric // Semaphore for worker threads. We don't use condition variable here in case
2887e8d8bef9SDimitry Andric // that when multiple signals are sent at the same time, only one thread might
2888e8d8bef9SDimitry Andric // be waken.
2889e8d8bef9SDimitry Andric sem_t hidden_helper_task_sem;
2890e8d8bef9SDimitry Andric } // namespace
2891e8d8bef9SDimitry Andric 
__kmp_hidden_helper_worker_thread_wait()2892e8d8bef9SDimitry Andric void __kmp_hidden_helper_worker_thread_wait() {
2893e8d8bef9SDimitry Andric   int status = sem_wait(&hidden_helper_task_sem);
2894e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("sem_wait", status);
2895e8d8bef9SDimitry Andric }
2896e8d8bef9SDimitry Andric 
__kmp_do_initialize_hidden_helper_threads()2897e8d8bef9SDimitry Andric void __kmp_do_initialize_hidden_helper_threads() {
2898e8d8bef9SDimitry Andric   // Initialize condition variable
2899e8d8bef9SDimitry Andric   int status =
2900e8d8bef9SDimitry Andric       pthread_cond_init(&hidden_helper_threads_initz_cond_var, nullptr);
2901e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
2902e8d8bef9SDimitry Andric 
2903e8d8bef9SDimitry Andric   status = pthread_cond_init(&hidden_helper_threads_deinitz_cond_var, nullptr);
2904e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
2905e8d8bef9SDimitry Andric 
2906e8d8bef9SDimitry Andric   status = pthread_cond_init(&hidden_helper_main_thread_cond_var, nullptr);
2907e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_cond_init", status);
2908e8d8bef9SDimitry Andric 
2909e8d8bef9SDimitry Andric   status = pthread_mutex_init(&hidden_helper_threads_initz_lock, nullptr);
2910e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
2911e8d8bef9SDimitry Andric 
2912e8d8bef9SDimitry Andric   status = pthread_mutex_init(&hidden_helper_threads_deinitz_lock, nullptr);
2913e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
2914e8d8bef9SDimitry Andric 
2915e8d8bef9SDimitry Andric   status = pthread_mutex_init(&hidden_helper_main_thread_lock, nullptr);
2916e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_init", status);
2917e8d8bef9SDimitry Andric 
2918e8d8bef9SDimitry Andric   // Initialize the semaphore
2919e8d8bef9SDimitry Andric   status = sem_init(&hidden_helper_task_sem, 0, 0);
2920e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("sem_init", status);
2921e8d8bef9SDimitry Andric 
2922e8d8bef9SDimitry Andric   // Create a new thread to finish initialization
2923e8d8bef9SDimitry Andric   pthread_t handle;
2924e8d8bef9SDimitry Andric   status = pthread_create(
2925e8d8bef9SDimitry Andric       &handle, nullptr,
2926e8d8bef9SDimitry Andric       [](void *) -> void * {
2927e8d8bef9SDimitry Andric         __kmp_hidden_helper_threads_initz_routine();
2928e8d8bef9SDimitry Andric         return nullptr;
2929e8d8bef9SDimitry Andric       },
2930e8d8bef9SDimitry Andric       nullptr);
2931e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_create", status);
2932e8d8bef9SDimitry Andric }
2933e8d8bef9SDimitry Andric 
__kmp_hidden_helper_threads_initz_wait()2934e8d8bef9SDimitry Andric void __kmp_hidden_helper_threads_initz_wait() {
2935e8d8bef9SDimitry Andric   // Initial thread waits here for the completion of the initialization. The
2936e8d8bef9SDimitry Andric   // condition variable will be notified by main thread of hidden helper teams.
2937e8d8bef9SDimitry Andric   int status = pthread_mutex_lock(&hidden_helper_threads_initz_lock);
2938e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
2939e8d8bef9SDimitry Andric 
2940e8d8bef9SDimitry Andric   if (!TCR_4(hidden_helper_initz_signaled)) {
2941e8d8bef9SDimitry Andric     status = pthread_cond_wait(&hidden_helper_threads_initz_cond_var,
2942e8d8bef9SDimitry Andric                                &hidden_helper_threads_initz_lock);
2943e8d8bef9SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
2944e8d8bef9SDimitry Andric   }
2945e8d8bef9SDimitry Andric 
2946e8d8bef9SDimitry Andric   status = pthread_mutex_unlock(&hidden_helper_threads_initz_lock);
2947e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
2948e8d8bef9SDimitry Andric }
2949e8d8bef9SDimitry Andric 
__kmp_hidden_helper_initz_release()2950e8d8bef9SDimitry Andric void __kmp_hidden_helper_initz_release() {
2951e8d8bef9SDimitry Andric   // After all initialization, reset __kmp_init_hidden_helper_threads to false.
2952e8d8bef9SDimitry Andric   int status = pthread_mutex_lock(&hidden_helper_threads_initz_lock);
2953e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
2954e8d8bef9SDimitry Andric 
2955e8d8bef9SDimitry Andric   status = pthread_cond_signal(&hidden_helper_threads_initz_cond_var);
2956e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
2957e8d8bef9SDimitry Andric 
2958e8d8bef9SDimitry Andric   TCW_SYNC_4(hidden_helper_initz_signaled, TRUE);
2959e8d8bef9SDimitry Andric 
2960e8d8bef9SDimitry Andric   status = pthread_mutex_unlock(&hidden_helper_threads_initz_lock);
2961e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
2962e8d8bef9SDimitry Andric }
2963e8d8bef9SDimitry Andric 
__kmp_hidden_helper_main_thread_wait()2964e8d8bef9SDimitry Andric void __kmp_hidden_helper_main_thread_wait() {
2965e8d8bef9SDimitry Andric   // The main thread of hidden helper team will be blocked here. The
2966e8d8bef9SDimitry Andric   // condition variable can only be signal in the destructor of RTL.
2967e8d8bef9SDimitry Andric   int status = pthread_mutex_lock(&hidden_helper_main_thread_lock);
2968e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
2969e8d8bef9SDimitry Andric 
2970e8d8bef9SDimitry Andric   if (!TCR_4(hidden_helper_main_thread_signaled)) {
2971e8d8bef9SDimitry Andric     status = pthread_cond_wait(&hidden_helper_main_thread_cond_var,
2972e8d8bef9SDimitry Andric                                &hidden_helper_main_thread_lock);
2973e8d8bef9SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
2974e8d8bef9SDimitry Andric   }
2975e8d8bef9SDimitry Andric 
2976e8d8bef9SDimitry Andric   status = pthread_mutex_unlock(&hidden_helper_main_thread_lock);
2977e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
2978e8d8bef9SDimitry Andric }
2979e8d8bef9SDimitry Andric 
__kmp_hidden_helper_main_thread_release()2980e8d8bef9SDimitry Andric void __kmp_hidden_helper_main_thread_release() {
2981e8d8bef9SDimitry Andric   // The initial thread of OpenMP RTL should call this function to wake up the
2982e8d8bef9SDimitry Andric   // main thread of hidden helper team.
2983e8d8bef9SDimitry Andric   int status = pthread_mutex_lock(&hidden_helper_main_thread_lock);
2984e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
2985e8d8bef9SDimitry Andric 
2986e8d8bef9SDimitry Andric   status = pthread_cond_signal(&hidden_helper_main_thread_cond_var);
2987e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_cond_signal", status);
2988e8d8bef9SDimitry Andric 
2989e8d8bef9SDimitry Andric   // The hidden helper team is done here
2990e8d8bef9SDimitry Andric   TCW_SYNC_4(hidden_helper_main_thread_signaled, TRUE);
2991e8d8bef9SDimitry Andric 
2992e8d8bef9SDimitry Andric   status = pthread_mutex_unlock(&hidden_helper_main_thread_lock);
2993e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
2994e8d8bef9SDimitry Andric }
2995e8d8bef9SDimitry Andric 
__kmp_hidden_helper_worker_thread_signal()2996e8d8bef9SDimitry Andric void __kmp_hidden_helper_worker_thread_signal() {
2997e8d8bef9SDimitry Andric   int status = sem_post(&hidden_helper_task_sem);
2998e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("sem_post", status);
2999e8d8bef9SDimitry Andric }
3000e8d8bef9SDimitry Andric 
__kmp_hidden_helper_threads_deinitz_wait()3001e8d8bef9SDimitry Andric void __kmp_hidden_helper_threads_deinitz_wait() {
3002e8d8bef9SDimitry Andric   // Initial thread waits here for the completion of the deinitialization. The
3003e8d8bef9SDimitry Andric   // condition variable will be notified by main thread of hidden helper teams.
3004e8d8bef9SDimitry Andric   int status = pthread_mutex_lock(&hidden_helper_threads_deinitz_lock);
3005e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
3006e8d8bef9SDimitry Andric 
3007e8d8bef9SDimitry Andric   if (!TCR_4(hidden_helper_deinitz_signaled)) {
3008e8d8bef9SDimitry Andric     status = pthread_cond_wait(&hidden_helper_threads_deinitz_cond_var,
3009e8d8bef9SDimitry Andric                                &hidden_helper_threads_deinitz_lock);
3010e8d8bef9SDimitry Andric     KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
3011e8d8bef9SDimitry Andric   }
3012e8d8bef9SDimitry Andric 
3013e8d8bef9SDimitry Andric   status = pthread_mutex_unlock(&hidden_helper_threads_deinitz_lock);
3014e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
3015e8d8bef9SDimitry Andric }
3016e8d8bef9SDimitry Andric 
__kmp_hidden_helper_threads_deinitz_release()3017e8d8bef9SDimitry Andric void __kmp_hidden_helper_threads_deinitz_release() {
3018e8d8bef9SDimitry Andric   int status = pthread_mutex_lock(&hidden_helper_threads_deinitz_lock);
3019e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_lock", status);
3020e8d8bef9SDimitry Andric 
3021e8d8bef9SDimitry Andric   status = pthread_cond_signal(&hidden_helper_threads_deinitz_cond_var);
3022e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_cond_wait", status);
3023e8d8bef9SDimitry Andric 
3024e8d8bef9SDimitry Andric   TCW_SYNC_4(hidden_helper_deinitz_signaled, TRUE);
3025e8d8bef9SDimitry Andric 
3026e8d8bef9SDimitry Andric   status = pthread_mutex_unlock(&hidden_helper_threads_deinitz_lock);
3027e8d8bef9SDimitry Andric   KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
3028e8d8bef9SDimitry Andric }
3029fe6060f1SDimitry Andric #else // KMP_OS_LINUX
__kmp_hidden_helper_worker_thread_wait()3030fe6060f1SDimitry Andric void __kmp_hidden_helper_worker_thread_wait() {
3031fe6060f1SDimitry Andric   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
3032fe6060f1SDimitry Andric }
3033fe6060f1SDimitry Andric 
__kmp_do_initialize_hidden_helper_threads()3034fe6060f1SDimitry Andric void __kmp_do_initialize_hidden_helper_threads() {
3035fe6060f1SDimitry Andric   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
3036fe6060f1SDimitry Andric }
3037fe6060f1SDimitry Andric 
__kmp_hidden_helper_threads_initz_wait()3038fe6060f1SDimitry Andric void __kmp_hidden_helper_threads_initz_wait() {
3039fe6060f1SDimitry Andric   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
3040fe6060f1SDimitry Andric }
3041fe6060f1SDimitry Andric 
__kmp_hidden_helper_initz_release()3042fe6060f1SDimitry Andric void __kmp_hidden_helper_initz_release() {
3043fe6060f1SDimitry Andric   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
3044fe6060f1SDimitry Andric }
3045fe6060f1SDimitry Andric 
__kmp_hidden_helper_main_thread_wait()3046fe6060f1SDimitry Andric void __kmp_hidden_helper_main_thread_wait() {
3047fe6060f1SDimitry Andric   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
3048fe6060f1SDimitry Andric }
3049fe6060f1SDimitry Andric 
__kmp_hidden_helper_main_thread_release()3050fe6060f1SDimitry Andric void __kmp_hidden_helper_main_thread_release() {
3051fe6060f1SDimitry Andric   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
3052fe6060f1SDimitry Andric }
3053fe6060f1SDimitry Andric 
__kmp_hidden_helper_worker_thread_signal()3054fe6060f1SDimitry Andric void __kmp_hidden_helper_worker_thread_signal() {
3055fe6060f1SDimitry Andric   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
3056fe6060f1SDimitry Andric }
3057fe6060f1SDimitry Andric 
__kmp_hidden_helper_threads_deinitz_wait()3058fe6060f1SDimitry Andric void __kmp_hidden_helper_threads_deinitz_wait() {
3059fe6060f1SDimitry Andric   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
3060fe6060f1SDimitry Andric }
3061fe6060f1SDimitry Andric 
__kmp_hidden_helper_threads_deinitz_release()3062fe6060f1SDimitry Andric void __kmp_hidden_helper_threads_deinitz_release() {
3063fe6060f1SDimitry Andric   KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
3064fe6060f1SDimitry Andric }
3065fe6060f1SDimitry Andric #endif // KMP_OS_LINUX
3066e8d8bef9SDimitry Andric 
__kmp_detect_shm()30675f757f3fSDimitry Andric bool __kmp_detect_shm() {
30685f757f3fSDimitry Andric   DIR *dir = opendir("/dev/shm");
30695f757f3fSDimitry Andric   if (dir) { // /dev/shm exists
30705f757f3fSDimitry Andric     closedir(dir);
30715f757f3fSDimitry Andric     return true;
30725f757f3fSDimitry Andric   } else if (ENOENT == errno) { // /dev/shm does not exist
30735f757f3fSDimitry Andric     return false;
30745f757f3fSDimitry Andric   } else { // opendir() failed
30755f757f3fSDimitry Andric     return false;
30765f757f3fSDimitry Andric   }
30775f757f3fSDimitry Andric }
30785f757f3fSDimitry Andric 
__kmp_detect_tmp()30795f757f3fSDimitry Andric bool __kmp_detect_tmp() {
30805f757f3fSDimitry Andric   DIR *dir = opendir("/tmp");
30815f757f3fSDimitry Andric   if (dir) { // /tmp exists
30825f757f3fSDimitry Andric     closedir(dir);
30835f757f3fSDimitry Andric     return true;
30845f757f3fSDimitry Andric   } else if (ENOENT == errno) { // /tmp does not exist
30855f757f3fSDimitry Andric     return false;
30865f757f3fSDimitry Andric   } else { // opendir() failed
30875f757f3fSDimitry Andric     return false;
30885f757f3fSDimitry Andric   }
30895f757f3fSDimitry Andric }
30905f757f3fSDimitry Andric 
30910b57cec5SDimitry Andric // end of file //
3092