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