17cc577a4SJonathan Peyton /* 2de4749b7SJonathan Peyton * z_Linux_util.cpp -- platform specific routines. 37cc577a4SJonathan Peyton */ 47cc577a4SJonathan Peyton 57cc577a4SJonathan Peyton //===----------------------------------------------------------------------===// 67cc577a4SJonathan Peyton // 757b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 857b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 957b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 107cc577a4SJonathan Peyton // 117cc577a4SJonathan Peyton //===----------------------------------------------------------------------===// 127cc577a4SJonathan Peyton 137cc577a4SJonathan Peyton #include "kmp.h" 147cc577a4SJonathan Peyton #include "kmp_affinity.h" 153041982dSJonathan Peyton #include "kmp_i18n.h" 163041982dSJonathan Peyton #include "kmp_io.h" 173041982dSJonathan Peyton #include "kmp_itt.h" 183041982dSJonathan Peyton #include "kmp_lock.h" 193041982dSJonathan Peyton #include "kmp_stats.h" 203041982dSJonathan Peyton #include "kmp_str.h" 213041982dSJonathan Peyton #include "kmp_wait_release.h" 223041982dSJonathan Peyton #include "kmp_wrapper_getpid.h" 237cc577a4SJonathan Peyton 247e1ea993SKamil Rytarowski #if !KMP_OS_DRAGONFLY && !KMP_OS_FREEBSD && !KMP_OS_NETBSD && !KMP_OS_OPENBSD 257cc577a4SJonathan Peyton #include <alloca.h> 267cc577a4SJonathan Peyton #endif 277cc577a4SJonathan Peyton #include <math.h> // HUGE_VAL. 289d64275aSShilei Tian #include <semaphore.h> 297cc577a4SJonathan Peyton #include <sys/resource.h> 307cc577a4SJonathan Peyton #include <sys/syscall.h> 313041982dSJonathan Peyton #include <sys/time.h> 323041982dSJonathan Peyton #include <sys/times.h> 333041982dSJonathan Peyton #include <unistd.h> 347cc577a4SJonathan Peyton 35d28f8672SJinsong Ji #if KMP_OS_LINUX 367cc577a4SJonathan Peyton #include <sys/sysinfo.h> 377cc577a4SJonathan Peyton #if KMP_USE_FUTEX 383041982dSJonathan Peyton // We should really include <futex.h>, but that causes compatibility problems on 393041982dSJonathan Peyton // different Linux* OS distributions that either require that you include (or 403041982dSJonathan Peyton // break when you try to include) <pci/types.h>. Since all we need is the two 413041982dSJonathan Peyton // macros below (which are part of the kernel ABI, so can't change) we just 423041982dSJonathan Peyton // define the constants here and don't include <futex.h> 437cc577a4SJonathan Peyton #ifndef FUTEX_WAIT 447cc577a4SJonathan Peyton #define FUTEX_WAIT 0 457cc577a4SJonathan Peyton #endif 467cc577a4SJonathan Peyton #ifndef FUTEX_WAKE 477cc577a4SJonathan Peyton #define FUTEX_WAKE 1 487cc577a4SJonathan Peyton #endif 497cc577a4SJonathan Peyton #endif 507cc577a4SJonathan Peyton #elif KMP_OS_DARWIN 517cc577a4SJonathan Peyton #include <mach/mach.h> 523041982dSJonathan Peyton #include <sys/sysctl.h> 53a56ac949SKamil Rytarowski #elif KMP_OS_DRAGONFLY || KMP_OS_FREEBSD 54fef62e1aSDavid Carlier #include <sys/types.h> 55fef62e1aSDavid Carlier #include <sys/sysctl.h> 56fef62e1aSDavid Carlier #include <sys/user.h> 577cc577a4SJonathan Peyton #include <pthread_np.h> 5827f6eedcSAndreyChurbanov #elif KMP_OS_NETBSD || KMP_OS_OPENBSD 59316f4238SKamil Rytarowski #include <sys/types.h> 60316f4238SKamil Rytarowski #include <sys/sysctl.h> 617cc577a4SJonathan Peyton #endif 627cc577a4SJonathan Peyton 637cc577a4SJonathan Peyton #include <ctype.h> 643041982dSJonathan Peyton #include <dirent.h> 657cc577a4SJonathan Peyton #include <fcntl.h> 667cc577a4SJonathan Peyton 677cc577a4SJonathan Peyton #include "tsan_annotations.h" 687cc577a4SJonathan Peyton 697cc577a4SJonathan Peyton struct kmp_sys_timer { 707cc577a4SJonathan Peyton struct timespec start; 717cc577a4SJonathan Peyton }; 727cc577a4SJonathan Peyton 737cc577a4SJonathan Peyton // Convert timespec to nanoseconds. 746b316febSTerry Wilmarth #define TS2NS(timespec) \ 756b316febSTerry Wilmarth (((timespec).tv_sec * (long int)1e9) + (timespec).tv_nsec) 767cc577a4SJonathan Peyton 777cc577a4SJonathan Peyton static struct kmp_sys_timer __kmp_sys_timer_data; 787cc577a4SJonathan Peyton 797cc577a4SJonathan Peyton #if KMP_HANDLE_SIGNALS 807cc577a4SJonathan Peyton typedef void (*sig_func_t)(int); 817cc577a4SJonathan Peyton STATIC_EFI2_WORKAROUND struct sigaction __kmp_sighldrs[NSIG]; 827cc577a4SJonathan Peyton static sigset_t __kmp_sigset; 837cc577a4SJonathan Peyton #endif 847cc577a4SJonathan Peyton 857cc577a4SJonathan Peyton static int __kmp_init_runtime = FALSE; 867cc577a4SJonathan Peyton 877cc577a4SJonathan Peyton static int __kmp_fork_count = 0; 887cc577a4SJonathan Peyton 897cc577a4SJonathan Peyton static pthread_condattr_t __kmp_suspend_cond_attr; 907cc577a4SJonathan Peyton static pthread_mutexattr_t __kmp_suspend_mutex_attr; 917cc577a4SJonathan Peyton 927cc577a4SJonathan Peyton static kmp_cond_align_t __kmp_wait_cv; 937cc577a4SJonathan Peyton static kmp_mutex_align_t __kmp_wait_mx; 947cc577a4SJonathan Peyton 9535d75aedSJonathan Peyton kmp_uint64 __kmp_ticks_per_msec = 1000000; 967cc577a4SJonathan Peyton 977cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND 983041982dSJonathan Peyton static void __kmp_print_cond(char *buffer, kmp_cond_align_t *cond) { 997cc577a4SJonathan Peyton KMP_SNPRINTF(buffer, 128, "(cond (lock (%ld, %d)), (descr (%p)))", 1007cc577a4SJonathan Peyton cond->c_cond.__c_lock.__status, cond->c_cond.__c_lock.__spinlock, 1017cc577a4SJonathan Peyton cond->c_cond.__c_waiting); 1027cc577a4SJonathan Peyton } 1037cc577a4SJonathan Peyton #endif 1047cc577a4SJonathan Peyton 105f61f13d4SDavid Carlier #if ((KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED) 1067cc577a4SJonathan Peyton 1073041982dSJonathan Peyton /* Affinity support */ 1087cc577a4SJonathan Peyton 1093041982dSJonathan Peyton void __kmp_affinity_bind_thread(int which) { 1107cc577a4SJonathan Peyton KMP_ASSERT2(KMP_AFFINITY_CAPABLE(), 1117cc577a4SJonathan Peyton "Illegal set affinity operation when not capable"); 1127cc577a4SJonathan Peyton 1137cc577a4SJonathan Peyton kmp_affin_mask_t *mask; 1147cc577a4SJonathan Peyton KMP_CPU_ALLOC_ON_STACK(mask); 1157cc577a4SJonathan Peyton KMP_CPU_ZERO(mask); 1167cc577a4SJonathan Peyton KMP_CPU_SET(which, mask); 1177cc577a4SJonathan Peyton __kmp_set_system_affinity(mask, TRUE); 1187cc577a4SJonathan Peyton KMP_CPU_FREE_FROM_STACK(mask); 1197cc577a4SJonathan Peyton } 1207cc577a4SJonathan Peyton 1213041982dSJonathan Peyton /* Determine if we can access affinity functionality on this version of 1227cc577a4SJonathan Peyton * Linux* OS by checking __NR_sched_{get,set}affinity system calls, and set 1233041982dSJonathan Peyton * __kmp_affin_mask_size to the appropriate value (0 means not capable). */ 1243041982dSJonathan Peyton void __kmp_affinity_determine_capable(const char *env_var) { 1257cc577a4SJonathan Peyton // Check and see if the OS supports thread affinity. 1267cc577a4SJonathan Peyton 127f61f13d4SDavid Carlier #if KMP_OS_LINUX 1287cc577a4SJonathan Peyton #define KMP_CPU_SET_SIZE_LIMIT (1024 * 1024) 129f61f13d4SDavid Carlier #elif KMP_OS_FREEBSD 130f61f13d4SDavid Carlier #define KMP_CPU_SET_SIZE_LIMIT (sizeof(cpuset_t)) 131f61f13d4SDavid Carlier #endif 1327cc577a4SJonathan Peyton 133f61f13d4SDavid Carlier #if KMP_OS_LINUX 134f61f13d4SDavid Carlier // If Linux* OS: 135f61f13d4SDavid Carlier // If the syscall fails or returns a suggestion for the size, 136f61f13d4SDavid Carlier // then we don't have to search for an appropriate size. 1376b316febSTerry Wilmarth long gCode; 1386b316febSTerry Wilmarth long sCode; 1397cc577a4SJonathan Peyton unsigned char *buf; 1407cc577a4SJonathan Peyton buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT); 1417cc577a4SJonathan Peyton gCode = syscall(__NR_sched_getaffinity, 0, KMP_CPU_SET_SIZE_LIMIT, buf); 1427cc577a4SJonathan Peyton KA_TRACE(30, ("__kmp_affinity_determine_capable: " 1436b316febSTerry Wilmarth "initial getaffinity call returned %ld errno = %d\n", 1447cc577a4SJonathan Peyton gCode, errno)); 1457cc577a4SJonathan Peyton 1467cc577a4SJonathan Peyton // if ((gCode < 0) && (errno == ENOSYS)) 1477cc577a4SJonathan Peyton if (gCode < 0) { 1487cc577a4SJonathan Peyton // System call not supported 1493041982dSJonathan Peyton if (__kmp_affinity_verbose || 1503041982dSJonathan Peyton (__kmp_affinity_warnings && (__kmp_affinity_type != affinity_none) && 1513041982dSJonathan Peyton (__kmp_affinity_type != affinity_default) && 1523041982dSJonathan Peyton (__kmp_affinity_type != affinity_disabled))) { 1537cc577a4SJonathan Peyton int error = errno; 1547cc577a4SJonathan Peyton kmp_msg_t err_code = KMP_ERR(error); 1553041982dSJonathan Peyton __kmp_msg(kmp_ms_warning, KMP_MSG(GetAffSysCallNotSupported, env_var), 1563041982dSJonathan Peyton err_code, __kmp_msg_null); 1577cc577a4SJonathan Peyton if (__kmp_generate_warnings == kmp_warnings_off) { 1587cc577a4SJonathan Peyton __kmp_str_free(&err_code.str); 1597cc577a4SJonathan Peyton } 1607cc577a4SJonathan Peyton } 1617cc577a4SJonathan Peyton KMP_AFFINITY_DISABLE(); 1627cc577a4SJonathan Peyton KMP_INTERNAL_FREE(buf); 1637cc577a4SJonathan Peyton return; 1647cc577a4SJonathan Peyton } 1657cc577a4SJonathan Peyton if (gCode > 0) { // Linux* OS only 1663041982dSJonathan Peyton // The optimal situation: the OS returns the size of the buffer it expects. 1677cc577a4SJonathan Peyton // 168ea99c099SDavid Carlier // A verification of correct behavior is that setaffinity on a NULL 1697cc577a4SJonathan Peyton // buffer with the same size fails with errno set to EFAULT. 1707cc577a4SJonathan Peyton sCode = syscall(__NR_sched_setaffinity, 0, gCode, NULL); 1717cc577a4SJonathan Peyton KA_TRACE(30, ("__kmp_affinity_determine_capable: " 1726b316febSTerry Wilmarth "setaffinity for mask size %ld returned %ld errno = %d\n", 1737cc577a4SJonathan Peyton gCode, sCode, errno)); 1747cc577a4SJonathan Peyton if (sCode < 0) { 1757cc577a4SJonathan Peyton if (errno == ENOSYS) { 1763041982dSJonathan Peyton if (__kmp_affinity_verbose || 1773041982dSJonathan Peyton (__kmp_affinity_warnings && 1783041982dSJonathan Peyton (__kmp_affinity_type != affinity_none) && 1793041982dSJonathan Peyton (__kmp_affinity_type != affinity_default) && 1803041982dSJonathan Peyton (__kmp_affinity_type != affinity_disabled))) { 1817cc577a4SJonathan Peyton int error = errno; 1827cc577a4SJonathan Peyton kmp_msg_t err_code = KMP_ERR(error); 1833041982dSJonathan Peyton __kmp_msg(kmp_ms_warning, KMP_MSG(SetAffSysCallNotSupported, env_var), 1843041982dSJonathan Peyton err_code, __kmp_msg_null); 1857cc577a4SJonathan Peyton if (__kmp_generate_warnings == kmp_warnings_off) { 1867cc577a4SJonathan Peyton __kmp_str_free(&err_code.str); 1877cc577a4SJonathan Peyton } 1887cc577a4SJonathan Peyton } 1897cc577a4SJonathan Peyton KMP_AFFINITY_DISABLE(); 1907cc577a4SJonathan Peyton KMP_INTERNAL_FREE(buf); 1917cc577a4SJonathan Peyton } 1927cc577a4SJonathan Peyton if (errno == EFAULT) { 1937cc577a4SJonathan Peyton KMP_AFFINITY_ENABLE(gCode); 1947cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_affinity_determine_capable: " 1957cc577a4SJonathan Peyton "affinity supported (mask size %d)\n", 1967cc577a4SJonathan Peyton (int)__kmp_affin_mask_size)); 1977cc577a4SJonathan Peyton KMP_INTERNAL_FREE(buf); 1987cc577a4SJonathan Peyton return; 1997cc577a4SJonathan Peyton } 2007cc577a4SJonathan Peyton } 2017cc577a4SJonathan Peyton } 2027cc577a4SJonathan Peyton 2037cc577a4SJonathan Peyton // Call the getaffinity system call repeatedly with increasing set sizes 2047cc577a4SJonathan Peyton // until we succeed, or reach an upper bound on the search. 2057cc577a4SJonathan Peyton KA_TRACE(30, ("__kmp_affinity_determine_capable: " 2067cc577a4SJonathan Peyton "searching for proper set size\n")); 2077cc577a4SJonathan Peyton int size; 2087cc577a4SJonathan Peyton for (size = 1; size <= KMP_CPU_SET_SIZE_LIMIT; size *= 2) { 2097cc577a4SJonathan Peyton gCode = syscall(__NR_sched_getaffinity, 0, size, buf); 2107cc577a4SJonathan Peyton KA_TRACE(30, ("__kmp_affinity_determine_capable: " 2116b316febSTerry Wilmarth "getaffinity for mask size %ld returned %ld errno = %d\n", 2123041982dSJonathan Peyton size, gCode, errno)); 2137cc577a4SJonathan Peyton 2147cc577a4SJonathan Peyton if (gCode < 0) { 2153041982dSJonathan Peyton if (errno == ENOSYS) { 2167cc577a4SJonathan Peyton // We shouldn't get here 2177cc577a4SJonathan Peyton KA_TRACE(30, ("__kmp_affinity_determine_capable: " 2183041982dSJonathan Peyton "inconsistent OS call behavior: errno == ENOSYS for mask " 2193041982dSJonathan Peyton "size %d\n", 2207cc577a4SJonathan Peyton size)); 2213041982dSJonathan Peyton if (__kmp_affinity_verbose || 2223041982dSJonathan Peyton (__kmp_affinity_warnings && 2233041982dSJonathan Peyton (__kmp_affinity_type != affinity_none) && 2243041982dSJonathan Peyton (__kmp_affinity_type != affinity_default) && 2253041982dSJonathan Peyton (__kmp_affinity_type != affinity_disabled))) { 2267cc577a4SJonathan Peyton int error = errno; 2277cc577a4SJonathan Peyton kmp_msg_t err_code = KMP_ERR(error); 2283041982dSJonathan Peyton __kmp_msg(kmp_ms_warning, KMP_MSG(GetAffSysCallNotSupported, env_var), 2293041982dSJonathan Peyton err_code, __kmp_msg_null); 2307cc577a4SJonathan Peyton if (__kmp_generate_warnings == kmp_warnings_off) { 2317cc577a4SJonathan Peyton __kmp_str_free(&err_code.str); 2327cc577a4SJonathan Peyton } 2337cc577a4SJonathan Peyton } 2347cc577a4SJonathan Peyton KMP_AFFINITY_DISABLE(); 2357cc577a4SJonathan Peyton KMP_INTERNAL_FREE(buf); 2367cc577a4SJonathan Peyton return; 2377cc577a4SJonathan Peyton } 2387cc577a4SJonathan Peyton continue; 2397cc577a4SJonathan Peyton } 2407cc577a4SJonathan Peyton 2417cc577a4SJonathan Peyton sCode = syscall(__NR_sched_setaffinity, 0, gCode, NULL); 2427cc577a4SJonathan Peyton KA_TRACE(30, ("__kmp_affinity_determine_capable: " 2436b316febSTerry Wilmarth "setaffinity for mask size %ld returned %ld errno = %d\n", 2447cc577a4SJonathan Peyton gCode, sCode, errno)); 2457cc577a4SJonathan Peyton if (sCode < 0) { 2467cc577a4SJonathan Peyton if (errno == ENOSYS) { // Linux* OS only 2477cc577a4SJonathan Peyton // We shouldn't get here 2487cc577a4SJonathan Peyton KA_TRACE(30, ("__kmp_affinity_determine_capable: " 2493041982dSJonathan Peyton "inconsistent OS call behavior: errno == ENOSYS for mask " 2503041982dSJonathan Peyton "size %d\n", 2517cc577a4SJonathan Peyton size)); 2523041982dSJonathan Peyton if (__kmp_affinity_verbose || 2533041982dSJonathan Peyton (__kmp_affinity_warnings && 2543041982dSJonathan Peyton (__kmp_affinity_type != affinity_none) && 2553041982dSJonathan Peyton (__kmp_affinity_type != affinity_default) && 2563041982dSJonathan Peyton (__kmp_affinity_type != affinity_disabled))) { 2577cc577a4SJonathan Peyton int error = errno; 2587cc577a4SJonathan Peyton kmp_msg_t err_code = KMP_ERR(error); 2593041982dSJonathan Peyton __kmp_msg(kmp_ms_warning, KMP_MSG(SetAffSysCallNotSupported, env_var), 2603041982dSJonathan Peyton err_code, __kmp_msg_null); 2617cc577a4SJonathan Peyton if (__kmp_generate_warnings == kmp_warnings_off) { 2627cc577a4SJonathan Peyton __kmp_str_free(&err_code.str); 2637cc577a4SJonathan Peyton } 2647cc577a4SJonathan Peyton } 2657cc577a4SJonathan Peyton KMP_AFFINITY_DISABLE(); 2667cc577a4SJonathan Peyton KMP_INTERNAL_FREE(buf); 2677cc577a4SJonathan Peyton return; 2687cc577a4SJonathan Peyton } 2697cc577a4SJonathan Peyton if (errno == EFAULT) { 2707cc577a4SJonathan Peyton KMP_AFFINITY_ENABLE(gCode); 2717cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_affinity_determine_capable: " 2727cc577a4SJonathan Peyton "affinity supported (mask size %d)\n", 2737cc577a4SJonathan Peyton (int)__kmp_affin_mask_size)); 2747cc577a4SJonathan Peyton KMP_INTERNAL_FREE(buf); 2757cc577a4SJonathan Peyton return; 2767cc577a4SJonathan Peyton } 2777cc577a4SJonathan Peyton } 2787cc577a4SJonathan Peyton } 279f61f13d4SDavid Carlier #elif KMP_OS_FREEBSD 2806b316febSTerry Wilmarth long gCode; 281f61f13d4SDavid Carlier unsigned char *buf; 282f61f13d4SDavid Carlier buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT); 283*309b00a4SShilei Tian gCode = pthread_getaffinity_np(pthread_self(), KMP_CPU_SET_SIZE_LIMIT, 284*309b00a4SShilei Tian reinterpret_cast<cpuset_t *>(buf)); 285f61f13d4SDavid Carlier KA_TRACE(30, ("__kmp_affinity_determine_capable: " 286f61f13d4SDavid Carlier "initial getaffinity call returned %d errno = %d\n", 287f61f13d4SDavid Carlier gCode, errno)); 288f61f13d4SDavid Carlier if (gCode == 0) { 289f61f13d4SDavid Carlier KMP_AFFINITY_ENABLE(KMP_CPU_SET_SIZE_LIMIT); 290f61f13d4SDavid Carlier KA_TRACE(10, ("__kmp_affinity_determine_capable: " 291ea99c099SDavid Carlier "affinity supported (mask size %d)\n", 292f61f13d4SDavid Carlier (int)__kmp_affin_mask_size)); 293f61f13d4SDavid Carlier KMP_INTERNAL_FREE(buf); 294f61f13d4SDavid Carlier return; 295f61f13d4SDavid Carlier } 296f61f13d4SDavid Carlier #endif 2973041982dSJonathan Peyton // save uncaught error code 2983041982dSJonathan Peyton // int error = errno; 2997cc577a4SJonathan Peyton KMP_INTERNAL_FREE(buf); 3003041982dSJonathan Peyton // restore uncaught error code, will be printed at the next KMP_WARNING below 3013041982dSJonathan Peyton // errno = error; 3027cc577a4SJonathan Peyton 3037cc577a4SJonathan Peyton // Affinity is not supported 3047cc577a4SJonathan Peyton KMP_AFFINITY_DISABLE(); 3057cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_affinity_determine_capable: " 3067cc577a4SJonathan Peyton "cannot determine mask size - affinity not supported\n")); 3073041982dSJonathan Peyton if (__kmp_affinity_verbose || 3083041982dSJonathan Peyton (__kmp_affinity_warnings && (__kmp_affinity_type != affinity_none) && 3093041982dSJonathan Peyton (__kmp_affinity_type != affinity_default) && 3103041982dSJonathan Peyton (__kmp_affinity_type != affinity_disabled))) { 3117cc577a4SJonathan Peyton KMP_WARNING(AffCantGetMaskSize, env_var); 3127cc577a4SJonathan Peyton } 3137cc577a4SJonathan Peyton } 3147cc577a4SJonathan Peyton 3157cc577a4SJonathan Peyton #endif // KMP_OS_LINUX && KMP_AFFINITY_SUPPORTED 3167cc577a4SJonathan Peyton 3177cc577a4SJonathan Peyton #if KMP_USE_FUTEX 3187cc577a4SJonathan Peyton 3193041982dSJonathan Peyton int __kmp_futex_determine_capable() { 3207cc577a4SJonathan Peyton int loc = 0; 3216b316febSTerry Wilmarth long rc = syscall(__NR_futex, &loc, FUTEX_WAKE, 1, NULL, NULL, 0); 3227cc577a4SJonathan Peyton int retval = (rc == 0) || (errno != ENOSYS); 3237cc577a4SJonathan Peyton 3243041982dSJonathan Peyton KA_TRACE(10, 3253041982dSJonathan Peyton ("__kmp_futex_determine_capable: rc = %d errno = %d\n", rc, errno)); 3267cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_futex_determine_capable: futex syscall%s supported\n", 3277cc577a4SJonathan Peyton retval ? "" : " not")); 3287cc577a4SJonathan Peyton 3297cc577a4SJonathan Peyton return retval; 3307cc577a4SJonathan Peyton } 3317cc577a4SJonathan Peyton 3327cc577a4SJonathan Peyton #endif // KMP_USE_FUTEX 3337cc577a4SJonathan Peyton 3347cc577a4SJonathan Peyton #if (KMP_ARCH_X86 || KMP_ARCH_X86_64) && (!KMP_ASM_INTRINS) 3353041982dSJonathan Peyton /* Only 32-bit "add-exchange" instruction on IA-32 architecture causes us to 3363041982dSJonathan Peyton use compare_and_store for these routines */ 3377cc577a4SJonathan Peyton 3383041982dSJonathan Peyton kmp_int8 __kmp_test_then_or8(volatile kmp_int8 *p, kmp_int8 d) { 3397cc577a4SJonathan Peyton kmp_int8 old_value, new_value; 3407cc577a4SJonathan Peyton 3417cc577a4SJonathan Peyton old_value = TCR_1(*p); 3427cc577a4SJonathan Peyton new_value = old_value | d; 3437cc577a4SJonathan Peyton 3443041982dSJonathan Peyton while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) { 3457cc577a4SJonathan Peyton KMP_CPU_PAUSE(); 3467cc577a4SJonathan Peyton old_value = TCR_1(*p); 3477cc577a4SJonathan Peyton new_value = old_value | d; 3487cc577a4SJonathan Peyton } 3497cc577a4SJonathan Peyton return old_value; 3507cc577a4SJonathan Peyton } 3517cc577a4SJonathan Peyton 3523041982dSJonathan Peyton kmp_int8 __kmp_test_then_and8(volatile kmp_int8 *p, kmp_int8 d) { 3537cc577a4SJonathan Peyton kmp_int8 old_value, new_value; 3547cc577a4SJonathan Peyton 3557cc577a4SJonathan Peyton old_value = TCR_1(*p); 3567cc577a4SJonathan Peyton new_value = old_value & d; 3577cc577a4SJonathan Peyton 3583041982dSJonathan Peyton while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) { 3597cc577a4SJonathan Peyton KMP_CPU_PAUSE(); 3607cc577a4SJonathan Peyton old_value = TCR_1(*p); 3617cc577a4SJonathan Peyton new_value = old_value & d; 3627cc577a4SJonathan Peyton } 3637cc577a4SJonathan Peyton return old_value; 3647cc577a4SJonathan Peyton } 3657cc577a4SJonathan Peyton 3665ba90c79SAndrey Churbanov kmp_uint32 __kmp_test_then_or32(volatile kmp_uint32 *p, kmp_uint32 d) { 3675ba90c79SAndrey Churbanov kmp_uint32 old_value, new_value; 3687cc577a4SJonathan Peyton 3697cc577a4SJonathan Peyton old_value = TCR_4(*p); 3707cc577a4SJonathan Peyton new_value = old_value | d; 3717cc577a4SJonathan Peyton 3723041982dSJonathan Peyton while (!KMP_COMPARE_AND_STORE_REL32(p, old_value, new_value)) { 3737cc577a4SJonathan Peyton KMP_CPU_PAUSE(); 3747cc577a4SJonathan Peyton old_value = TCR_4(*p); 3757cc577a4SJonathan Peyton new_value = old_value | d; 3767cc577a4SJonathan Peyton } 3777cc577a4SJonathan Peyton return old_value; 3787cc577a4SJonathan Peyton } 3797cc577a4SJonathan Peyton 3805ba90c79SAndrey Churbanov kmp_uint32 __kmp_test_then_and32(volatile kmp_uint32 *p, kmp_uint32 d) { 3815ba90c79SAndrey Churbanov kmp_uint32 old_value, new_value; 3827cc577a4SJonathan Peyton 3837cc577a4SJonathan Peyton old_value = TCR_4(*p); 3847cc577a4SJonathan Peyton new_value = old_value & d; 3857cc577a4SJonathan Peyton 3863041982dSJonathan Peyton while (!KMP_COMPARE_AND_STORE_REL32(p, old_value, new_value)) { 3877cc577a4SJonathan Peyton KMP_CPU_PAUSE(); 3887cc577a4SJonathan Peyton old_value = TCR_4(*p); 3897cc577a4SJonathan Peyton new_value = old_value & d; 3907cc577a4SJonathan Peyton } 3917cc577a4SJonathan Peyton return old_value; 3927cc577a4SJonathan Peyton } 3937cc577a4SJonathan Peyton 394928b8ea2SJonathan Peyton #if KMP_ARCH_X86 3953041982dSJonathan Peyton kmp_int8 __kmp_test_then_add8(volatile kmp_int8 *p, kmp_int8 d) { 3967cc577a4SJonathan Peyton kmp_int8 old_value, new_value; 3977cc577a4SJonathan Peyton 3987cc577a4SJonathan Peyton old_value = TCR_1(*p); 3997cc577a4SJonathan Peyton new_value = old_value + d; 4007cc577a4SJonathan Peyton 4013041982dSJonathan Peyton while (!KMP_COMPARE_AND_STORE_REL8(p, old_value, new_value)) { 4027cc577a4SJonathan Peyton KMP_CPU_PAUSE(); 4037cc577a4SJonathan Peyton old_value = TCR_1(*p); 4047cc577a4SJonathan Peyton new_value = old_value + d; 4057cc577a4SJonathan Peyton } 4067cc577a4SJonathan Peyton return old_value; 4077cc577a4SJonathan Peyton } 4087cc577a4SJonathan Peyton 4093041982dSJonathan Peyton kmp_int64 __kmp_test_then_add64(volatile kmp_int64 *p, kmp_int64 d) { 4107cc577a4SJonathan Peyton kmp_int64 old_value, new_value; 4117cc577a4SJonathan Peyton 4127cc577a4SJonathan Peyton old_value = TCR_8(*p); 4137cc577a4SJonathan Peyton new_value = old_value + d; 4147cc577a4SJonathan Peyton 4153041982dSJonathan Peyton while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) { 4167cc577a4SJonathan Peyton KMP_CPU_PAUSE(); 4177cc577a4SJonathan Peyton old_value = TCR_8(*p); 4187cc577a4SJonathan Peyton new_value = old_value + d; 4197cc577a4SJonathan Peyton } 4207cc577a4SJonathan Peyton return old_value; 4217cc577a4SJonathan Peyton } 422928b8ea2SJonathan Peyton #endif /* KMP_ARCH_X86 */ 4237cc577a4SJonathan Peyton 4245ba90c79SAndrey Churbanov kmp_uint64 __kmp_test_then_or64(volatile kmp_uint64 *p, kmp_uint64 d) { 4255ba90c79SAndrey Churbanov kmp_uint64 old_value, new_value; 4267cc577a4SJonathan Peyton 4277cc577a4SJonathan Peyton old_value = TCR_8(*p); 4287cc577a4SJonathan Peyton new_value = old_value | d; 4293041982dSJonathan Peyton while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) { 4307cc577a4SJonathan Peyton KMP_CPU_PAUSE(); 4317cc577a4SJonathan Peyton old_value = TCR_8(*p); 4327cc577a4SJonathan Peyton new_value = old_value | d; 4337cc577a4SJonathan Peyton } 4347cc577a4SJonathan Peyton return old_value; 4357cc577a4SJonathan Peyton } 4367cc577a4SJonathan Peyton 4375ba90c79SAndrey Churbanov kmp_uint64 __kmp_test_then_and64(volatile kmp_uint64 *p, kmp_uint64 d) { 4385ba90c79SAndrey Churbanov kmp_uint64 old_value, new_value; 4397cc577a4SJonathan Peyton 4407cc577a4SJonathan Peyton old_value = TCR_8(*p); 4417cc577a4SJonathan Peyton new_value = old_value & d; 4423041982dSJonathan Peyton while (!KMP_COMPARE_AND_STORE_REL64(p, old_value, new_value)) { 4437cc577a4SJonathan Peyton KMP_CPU_PAUSE(); 4447cc577a4SJonathan Peyton old_value = TCR_8(*p); 4457cc577a4SJonathan Peyton new_value = old_value & d; 4467cc577a4SJonathan Peyton } 4477cc577a4SJonathan Peyton return old_value; 4487cc577a4SJonathan Peyton } 4497cc577a4SJonathan Peyton 4507cc577a4SJonathan Peyton #endif /* (KMP_ARCH_X86 || KMP_ARCH_X86_64) && (! KMP_ASM_INTRINS) */ 4517cc577a4SJonathan Peyton 4523041982dSJonathan Peyton void __kmp_terminate_thread(int gtid) { 4537cc577a4SJonathan Peyton int status; 4547cc577a4SJonathan Peyton kmp_info_t *th = __kmp_threads[gtid]; 4557cc577a4SJonathan Peyton 4563041982dSJonathan Peyton if (!th) 4573041982dSJonathan Peyton return; 4587cc577a4SJonathan Peyton 4597cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS 4607cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_terminate_thread: kill (%d)\n", gtid)); 4617cc577a4SJonathan Peyton status = pthread_cancel(th->th.th_info.ds.ds_thread); 4627cc577a4SJonathan Peyton if (status != 0 && status != ESRCH) { 4636a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(CantTerminateWorkerThread), KMP_ERR(status), 4643041982dSJonathan Peyton __kmp_msg_null); 465bd3a7633SJonathan Peyton } 4667cc577a4SJonathan Peyton #endif 467e47d32f1SJonathan Peyton KMP_YIELD(TRUE); 4687cc577a4SJonathan Peyton } // 4697cc577a4SJonathan Peyton 4703041982dSJonathan Peyton /* Set thread stack info according to values returned by pthread_getattr_np(). 4713041982dSJonathan Peyton If values are unreasonable, assume call failed and use incremental stack 4723041982dSJonathan Peyton refinement method instead. Returns TRUE if the stack parameters could be 4733041982dSJonathan Peyton determined exactly, FALSE if incremental refinement is necessary. */ 4743041982dSJonathan Peyton static kmp_int32 __kmp_set_stack_info(int gtid, kmp_info_t *th) { 4757cc577a4SJonathan Peyton int stack_data; 476a56ac949SKamil Rytarowski #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \ 477a56ac949SKamil Rytarowski KMP_OS_HURD 4787cc577a4SJonathan Peyton pthread_attr_t attr; 4797cc577a4SJonathan Peyton int status; 4807cc577a4SJonathan Peyton size_t size = 0; 4817cc577a4SJonathan Peyton void *addr = 0; 4827cc577a4SJonathan Peyton 4833041982dSJonathan Peyton /* Always do incremental stack refinement for ubermaster threads since the 4843041982dSJonathan Peyton initial thread stack range can be reduced by sibling thread creation so 4853041982dSJonathan Peyton pthread_attr_getstack may cause thread gtid aliasing */ 4867cc577a4SJonathan Peyton if (!KMP_UBER_GTID(gtid)) { 4877cc577a4SJonathan Peyton 4887cc577a4SJonathan Peyton /* Fetch the real thread attributes */ 4897cc577a4SJonathan Peyton status = pthread_attr_init(&attr); 4907cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_attr_init", status); 491a56ac949SKamil Rytarowski #if KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD 4927cc577a4SJonathan Peyton status = pthread_attr_get_np(pthread_self(), &attr); 4937cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_attr_get_np", status); 4947cc577a4SJonathan Peyton #else 4957cc577a4SJonathan Peyton status = pthread_getattr_np(pthread_self(), &attr); 4967cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_getattr_np", status); 4977cc577a4SJonathan Peyton #endif 4987cc577a4SJonathan Peyton status = pthread_attr_getstack(&attr, &addr, &size); 4997cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_attr_getstack", status); 5003041982dSJonathan Peyton KA_TRACE(60, 5013041982dSJonathan Peyton ("__kmp_set_stack_info: T#%d pthread_attr_getstack returned size:" 5023041982dSJonathan Peyton " %lu, low addr: %p\n", 5037cc577a4SJonathan Peyton gtid, size, addr)); 5047cc577a4SJonathan Peyton status = pthread_attr_destroy(&attr); 5057cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_attr_destroy", status); 5067cc577a4SJonathan Peyton } 5077cc577a4SJonathan Peyton 5083041982dSJonathan Peyton if (size != 0 && addr != 0) { // was stack parameter determination successful? 5097cc577a4SJonathan Peyton /* Store the correct base and size */ 5107cc577a4SJonathan Peyton TCW_PTR(th->th.th_info.ds.ds_stackbase, (((char *)addr) + size)); 5117cc577a4SJonathan Peyton TCW_PTR(th->th.th_info.ds.ds_stacksize, size); 5127cc577a4SJonathan Peyton TCW_4(th->th.th_info.ds.ds_stackgrow, FALSE); 5137cc577a4SJonathan Peyton return TRUE; 5147cc577a4SJonathan Peyton } 515*309b00a4SShilei Tian #endif /* KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD \ 516*309b00a4SShilei Tian || KMP_OS_HURD */ 5177cc577a4SJonathan Peyton /* Use incremental refinement starting from initial conservative estimate */ 5187cc577a4SJonathan Peyton TCW_PTR(th->th.th_info.ds.ds_stacksize, 0); 5197cc577a4SJonathan Peyton TCW_PTR(th->th.th_info.ds.ds_stackbase, &stack_data); 5207cc577a4SJonathan Peyton TCW_4(th->th.th_info.ds.ds_stackgrow, TRUE); 5217cc577a4SJonathan Peyton return FALSE; 5227cc577a4SJonathan Peyton } 5237cc577a4SJonathan Peyton 5243041982dSJonathan Peyton static void *__kmp_launch_worker(void *thr) { 5257cc577a4SJonathan Peyton int status, old_type, old_state; 5267cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS 5277cc577a4SJonathan Peyton sigset_t new_set, old_set; 5287cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */ 5297cc577a4SJonathan Peyton void *exit_val; 530a56ac949SKamil Rytarowski #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \ 5317e1ea993SKamil Rytarowski KMP_OS_OPENBSD || KMP_OS_HURD 5327cc577a4SJonathan Peyton void *volatile padding = 0; 5337cc577a4SJonathan Peyton #endif 5347cc577a4SJonathan Peyton int gtid; 5357cc577a4SJonathan Peyton 5367cc577a4SJonathan Peyton gtid = ((kmp_info_t *)thr)->th.th_info.ds.ds_gtid; 5377cc577a4SJonathan Peyton __kmp_gtid_set_specific(gtid); 5387cc577a4SJonathan Peyton #ifdef KMP_TDATA_GTID 5397cc577a4SJonathan Peyton __kmp_gtid = gtid; 5407cc577a4SJonathan Peyton #endif 5417cc577a4SJonathan Peyton #if KMP_STATS_ENABLED 54240039ac9SJonathan Peyton // set thread local index to point to thread-specific stats 5437cc577a4SJonathan Peyton __kmp_stats_thread_ptr = ((kmp_info_t *)thr)->th.th_stats; 544f0682ac4SJonathan Peyton __kmp_stats_thread_ptr->startLife(); 5457cc577a4SJonathan Peyton KMP_SET_THREAD_STATE(IDLE); 5467cc577a4SJonathan Peyton KMP_INIT_PARTITIONED_TIMERS(OMP_idle); 5477cc577a4SJonathan Peyton #endif 5487cc577a4SJonathan Peyton 5497cc577a4SJonathan Peyton #if USE_ITT_BUILD 5507cc577a4SJonathan Peyton __kmp_itt_thread_name(gtid); 5517cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */ 5527cc577a4SJonathan Peyton 5537cc577a4SJonathan Peyton #if KMP_AFFINITY_SUPPORTED 5547cc577a4SJonathan Peyton __kmp_affinity_set_init_mask(gtid, FALSE); 5557cc577a4SJonathan Peyton #endif 5567cc577a4SJonathan Peyton 5577cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS 5587cc577a4SJonathan Peyton status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_type); 5597cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_setcanceltype", status); 5603041982dSJonathan Peyton // josh todo: isn't PTHREAD_CANCEL_ENABLE default for newly-created threads? 5617cc577a4SJonathan Peyton status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state); 5627cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_setcancelstate", status); 5637cc577a4SJonathan Peyton #endif 5647cc577a4SJonathan Peyton 5657cc577a4SJonathan Peyton #if KMP_ARCH_X86 || KMP_ARCH_X86_64 5663041982dSJonathan Peyton // Set FP control regs to be a copy of the parallel initialization thread's. 5677cc577a4SJonathan Peyton __kmp_clear_x87_fpu_status_word(); 5687cc577a4SJonathan Peyton __kmp_load_x87_fpu_control_word(&__kmp_init_x87_fpu_control_word); 5697cc577a4SJonathan Peyton __kmp_load_mxcsr(&__kmp_init_mxcsr); 5707cc577a4SJonathan Peyton #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ 5717cc577a4SJonathan Peyton 5727cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS 5737cc577a4SJonathan Peyton status = sigfillset(&new_set); 5747cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL_ERRNO("sigfillset", status); 5757cc577a4SJonathan Peyton status = pthread_sigmask(SIG_BLOCK, &new_set, &old_set); 5767cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_sigmask", status); 5777cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */ 5787cc577a4SJonathan Peyton 5797e1ea993SKamil Rytarowski #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \ 5807e1ea993SKamil Rytarowski KMP_OS_OPENBSD 5817cc577a4SJonathan Peyton if (__kmp_stkoffset > 0 && gtid > 0) { 5827cc577a4SJonathan Peyton padding = KMP_ALLOCA(gtid * __kmp_stkoffset); 5837cc577a4SJonathan Peyton } 5847cc577a4SJonathan Peyton #endif 5857cc577a4SJonathan Peyton 5867cc577a4SJonathan Peyton KMP_MB(); 5877cc577a4SJonathan Peyton __kmp_set_stack_info(gtid, (kmp_info_t *)thr); 5887cc577a4SJonathan Peyton 5897cc577a4SJonathan Peyton __kmp_check_stack_overlap((kmp_info_t *)thr); 5907cc577a4SJonathan Peyton 5917cc577a4SJonathan Peyton exit_val = __kmp_launch_thread((kmp_info_t *)thr); 5927cc577a4SJonathan Peyton 5937cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS 5947cc577a4SJonathan Peyton status = pthread_sigmask(SIG_SETMASK, &old_set, NULL); 5957cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_sigmask", status); 5967cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */ 5977cc577a4SJonathan Peyton 5987cc577a4SJonathan Peyton return exit_val; 5997cc577a4SJonathan Peyton } 6007cc577a4SJonathan Peyton 6017cc577a4SJonathan Peyton #if KMP_USE_MONITOR 6027cc577a4SJonathan Peyton /* The monitor thread controls all of the threads in the complex */ 6037cc577a4SJonathan Peyton 6043041982dSJonathan Peyton static void *__kmp_launch_monitor(void *thr) { 6057cc577a4SJonathan Peyton int status, old_type, old_state; 6067cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS 6077cc577a4SJonathan Peyton sigset_t new_set; 6087cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */ 6097cc577a4SJonathan Peyton struct timespec interval; 6107cc577a4SJonathan Peyton 6117cc577a4SJonathan Peyton KMP_MB(); /* Flush all pending memory write invalidates. */ 6127cc577a4SJonathan Peyton 6137cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_launch_monitor: #1 launched\n")); 6147cc577a4SJonathan Peyton 6157cc577a4SJonathan Peyton /* register us as the monitor thread */ 6167cc577a4SJonathan Peyton __kmp_gtid_set_specific(KMP_GTID_MONITOR); 6177cc577a4SJonathan Peyton #ifdef KMP_TDATA_GTID 6187cc577a4SJonathan Peyton __kmp_gtid = KMP_GTID_MONITOR; 6197cc577a4SJonathan Peyton #endif 6207cc577a4SJonathan Peyton 6217cc577a4SJonathan Peyton KMP_MB(); 6227cc577a4SJonathan Peyton 6237cc577a4SJonathan Peyton #if USE_ITT_BUILD 6243041982dSJonathan Peyton // Instruct Intel(R) Threading Tools to ignore monitor thread. 6253041982dSJonathan Peyton __kmp_itt_thread_ignore(); 6267cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */ 6277cc577a4SJonathan Peyton 6283041982dSJonathan Peyton __kmp_set_stack_info(((kmp_info_t *)thr)->th.th_info.ds.ds_gtid, 6293041982dSJonathan Peyton (kmp_info_t *)thr); 6307cc577a4SJonathan Peyton 6317cc577a4SJonathan Peyton __kmp_check_stack_overlap((kmp_info_t *)thr); 6327cc577a4SJonathan Peyton 6337cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS 6347cc577a4SJonathan Peyton status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_type); 6357cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_setcanceltype", status); 6363041982dSJonathan Peyton // josh todo: isn't PTHREAD_CANCEL_ENABLE default for newly-created threads? 6377cc577a4SJonathan Peyton status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state); 6387cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_setcancelstate", status); 6397cc577a4SJonathan Peyton #endif 6407cc577a4SJonathan Peyton 6417cc577a4SJonathan Peyton #if KMP_REAL_TIME_FIX 6423041982dSJonathan Peyton // This is a potential fix which allows application with real-time scheduling 6433041982dSJonathan Peyton // policy work. However, decision about the fix is not made yet, so it is 6443041982dSJonathan Peyton // disabled by default. 6457cc577a4SJonathan Peyton { // Are program started with real-time scheduling policy? 6467cc577a4SJonathan Peyton int sched = sched_getscheduler(0); 6477cc577a4SJonathan Peyton if (sched == SCHED_FIFO || sched == SCHED_RR) { 6483041982dSJonathan Peyton // Yes, we are a part of real-time application. Try to increase the 6493041982dSJonathan Peyton // priority of the monitor. 6507cc577a4SJonathan Peyton struct sched_param param; 6517cc577a4SJonathan Peyton int max_priority = sched_get_priority_max(sched); 6527cc577a4SJonathan Peyton int rc; 6537cc577a4SJonathan Peyton KMP_WARNING(RealTimeSchedNotSupported); 6547cc577a4SJonathan Peyton sched_getparam(0, ¶m); 6557cc577a4SJonathan Peyton if (param.sched_priority < max_priority) { 6567cc577a4SJonathan Peyton param.sched_priority += 1; 6577cc577a4SJonathan Peyton rc = sched_setscheduler(0, sched, ¶m); 6587cc577a4SJonathan Peyton if (rc != 0) { 6597cc577a4SJonathan Peyton int error = errno; 6607cc577a4SJonathan Peyton kmp_msg_t err_code = KMP_ERR(error); 6613041982dSJonathan Peyton __kmp_msg(kmp_ms_warning, KMP_MSG(CantChangeMonitorPriority), 6623041982dSJonathan Peyton err_code, KMP_MSG(MonitorWillStarve), __kmp_msg_null); 6637cc577a4SJonathan Peyton if (__kmp_generate_warnings == kmp_warnings_off) { 6647cc577a4SJonathan Peyton __kmp_str_free(&err_code.str); 6657cc577a4SJonathan Peyton } 666bd3a7633SJonathan Peyton } 6677cc577a4SJonathan Peyton } else { 6683041982dSJonathan Peyton // We cannot abort here, because number of CPUs may be enough for all 6693041982dSJonathan Peyton // the threads, including the monitor thread, so application could 6703041982dSJonathan Peyton // potentially work... 6713041982dSJonathan Peyton __kmp_msg(kmp_ms_warning, KMP_MSG(RunningAtMaxPriority), 6723041982dSJonathan Peyton KMP_MSG(MonitorWillStarve), KMP_HNT(RunningAtMaxPriority), 6733041982dSJonathan Peyton __kmp_msg_null); 674bd3a7633SJonathan Peyton } 675bd3a7633SJonathan Peyton } 6763041982dSJonathan Peyton // AC: free thread that waits for monitor started 6773041982dSJonathan Peyton TCW_4(__kmp_global.g.g_time.dt.t_value, 0); 6787cc577a4SJonathan Peyton } 6797cc577a4SJonathan Peyton #endif // KMP_REAL_TIME_FIX 6807cc577a4SJonathan Peyton 6817cc577a4SJonathan Peyton KMP_MB(); /* Flush all pending memory write invalidates. */ 6827cc577a4SJonathan Peyton 6837cc577a4SJonathan Peyton if (__kmp_monitor_wakeups == 1) { 6847cc577a4SJonathan Peyton interval.tv_sec = 1; 6857cc577a4SJonathan Peyton interval.tv_nsec = 0; 6867cc577a4SJonathan Peyton } else { 6877cc577a4SJonathan Peyton interval.tv_sec = 0; 6887cc577a4SJonathan Peyton interval.tv_nsec = (KMP_NSEC_PER_SEC / __kmp_monitor_wakeups); 6897cc577a4SJonathan Peyton } 6907cc577a4SJonathan Peyton 6917cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_launch_monitor: #2 monitor\n")); 6927cc577a4SJonathan Peyton 6937cc577a4SJonathan Peyton while (!TCR_4(__kmp_global.g.g_done)) { 6947cc577a4SJonathan Peyton struct timespec now; 6957cc577a4SJonathan Peyton struct timeval tval; 6967cc577a4SJonathan Peyton 6977cc577a4SJonathan Peyton /* This thread monitors the state of the system */ 6987cc577a4SJonathan Peyton 6997cc577a4SJonathan Peyton KA_TRACE(15, ("__kmp_launch_monitor: update\n")); 7007cc577a4SJonathan Peyton 7017cc577a4SJonathan Peyton status = gettimeofday(&tval, NULL); 7027cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status); 7037cc577a4SJonathan Peyton TIMEVAL_TO_TIMESPEC(&tval, &now); 7047cc577a4SJonathan Peyton 7057cc577a4SJonathan Peyton now.tv_sec += interval.tv_sec; 7067cc577a4SJonathan Peyton now.tv_nsec += interval.tv_nsec; 7077cc577a4SJonathan Peyton 7087cc577a4SJonathan Peyton if (now.tv_nsec >= KMP_NSEC_PER_SEC) { 7097cc577a4SJonathan Peyton now.tv_sec += 1; 7107cc577a4SJonathan Peyton now.tv_nsec -= KMP_NSEC_PER_SEC; 7117cc577a4SJonathan Peyton } 7127cc577a4SJonathan Peyton 7137cc577a4SJonathan Peyton status = pthread_mutex_lock(&__kmp_wait_mx.m_mutex); 7147cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_mutex_lock", status); 7157cc577a4SJonathan Peyton // AC: the monitor should not fall asleep if g_done has been set 7167cc577a4SJonathan Peyton if (!TCR_4(__kmp_global.g.g_done)) { // check once more under mutex 7173041982dSJonathan Peyton status = pthread_cond_timedwait(&__kmp_wait_cv.c_cond, 7183041982dSJonathan Peyton &__kmp_wait_mx.m_mutex, &now); 7197cc577a4SJonathan Peyton if (status != 0) { 7207cc577a4SJonathan Peyton if (status != ETIMEDOUT && status != EINTR) { 7217cc577a4SJonathan Peyton KMP_SYSFAIL("pthread_cond_timedwait", status); 722bd3a7633SJonathan Peyton } 723bd3a7633SJonathan Peyton } 724bd3a7633SJonathan Peyton } 7257cc577a4SJonathan Peyton status = pthread_mutex_unlock(&__kmp_wait_mx.m_mutex); 7267cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status); 7277cc577a4SJonathan Peyton 7287cc577a4SJonathan Peyton TCW_4(__kmp_global.g.g_time.dt.t_value, 7297cc577a4SJonathan Peyton TCR_4(__kmp_global.g.g_time.dt.t_value) + 1); 7307cc577a4SJonathan Peyton 7317cc577a4SJonathan Peyton KMP_MB(); /* Flush all pending memory write invalidates. */ 7327cc577a4SJonathan Peyton } 7337cc577a4SJonathan Peyton 7347cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_launch_monitor: #3 cleanup\n")); 7357cc577a4SJonathan Peyton 7367cc577a4SJonathan Peyton #ifdef KMP_BLOCK_SIGNALS 7377cc577a4SJonathan Peyton status = sigfillset(&new_set); 7387cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL_ERRNO("sigfillset", status); 7397cc577a4SJonathan Peyton status = pthread_sigmask(SIG_UNBLOCK, &new_set, NULL); 7407cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_sigmask", status); 7417cc577a4SJonathan Peyton #endif /* KMP_BLOCK_SIGNALS */ 7427cc577a4SJonathan Peyton 7437cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_launch_monitor: #4 finished\n")); 7447cc577a4SJonathan Peyton 7457cc577a4SJonathan Peyton if (__kmp_global.g.g_abort != 0) { 7467cc577a4SJonathan Peyton /* now we need to terminate the worker threads */ 7477cc577a4SJonathan Peyton /* the value of t_abort is the signal we caught */ 7487cc577a4SJonathan Peyton 7497cc577a4SJonathan Peyton int gtid; 7507cc577a4SJonathan Peyton 7513041982dSJonathan Peyton KA_TRACE(10, ("__kmp_launch_monitor: #5 terminate sig=%d\n", 7523041982dSJonathan Peyton __kmp_global.g.g_abort)); 7537cc577a4SJonathan Peyton 7547cc577a4SJonathan Peyton /* terminate the OpenMP worker threads */ 7557cc577a4SJonathan Peyton /* TODO this is not valid for sibling threads!! 7567cc577a4SJonathan Peyton * the uber master might not be 0 anymore.. */ 7577cc577a4SJonathan Peyton for (gtid = 1; gtid < __kmp_threads_capacity; ++gtid) 7587cc577a4SJonathan Peyton __kmp_terminate_thread(gtid); 7597cc577a4SJonathan Peyton 7607cc577a4SJonathan Peyton __kmp_cleanup(); 7617cc577a4SJonathan Peyton 7623041982dSJonathan Peyton KA_TRACE(10, ("__kmp_launch_monitor: #6 raise sig=%d\n", 7633041982dSJonathan Peyton __kmp_global.g.g_abort)); 7647cc577a4SJonathan Peyton 7657cc577a4SJonathan Peyton if (__kmp_global.g.g_abort > 0) 7667cc577a4SJonathan Peyton raise(__kmp_global.g.g_abort); 7677cc577a4SJonathan Peyton } 7687cc577a4SJonathan Peyton 7697cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_launch_monitor: #7 exit\n")); 7707cc577a4SJonathan Peyton 7717cc577a4SJonathan Peyton return thr; 7727cc577a4SJonathan Peyton } 7737cc577a4SJonathan Peyton #endif // KMP_USE_MONITOR 7747cc577a4SJonathan Peyton 7753041982dSJonathan Peyton void __kmp_create_worker(int gtid, kmp_info_t *th, size_t stack_size) { 7767cc577a4SJonathan Peyton pthread_t handle; 7777cc577a4SJonathan Peyton pthread_attr_t thread_attr; 7787cc577a4SJonathan Peyton int status; 7797cc577a4SJonathan Peyton 7807cc577a4SJonathan Peyton th->th.th_info.ds.ds_gtid = gtid; 7817cc577a4SJonathan Peyton 7827cc577a4SJonathan Peyton #if KMP_STATS_ENABLED 7837cc577a4SJonathan Peyton // sets up worker thread stats 7847cc577a4SJonathan Peyton __kmp_acquire_tas_lock(&__kmp_stats_lock, gtid); 7857cc577a4SJonathan Peyton 7863041982dSJonathan Peyton // th->th.th_stats is used to transfer thread-specific stats-pointer to 7873041982dSJonathan Peyton // __kmp_launch_worker. So when thread is created (goes into 78840039ac9SJonathan Peyton // __kmp_launch_worker) it will set its thread local pointer to 7893041982dSJonathan Peyton // th->th.th_stats 7907cc577a4SJonathan Peyton if (!KMP_UBER_GTID(gtid)) { 7917cc577a4SJonathan Peyton th->th.th_stats = __kmp_stats_list->push_back(gtid); 7927cc577a4SJonathan Peyton } else { 7933041982dSJonathan Peyton // For root threads, __kmp_stats_thread_ptr is set in __kmp_register_root(), 7943041982dSJonathan Peyton // so set the th->th.th_stats field to it. 7957cc577a4SJonathan Peyton th->th.th_stats = __kmp_stats_thread_ptr; 7967cc577a4SJonathan Peyton } 7977cc577a4SJonathan Peyton __kmp_release_tas_lock(&__kmp_stats_lock, gtid); 7987cc577a4SJonathan Peyton 7997cc577a4SJonathan Peyton #endif // KMP_STATS_ENABLED 8007cc577a4SJonathan Peyton 8017cc577a4SJonathan Peyton if (KMP_UBER_GTID(gtid)) { 8027cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_create_worker: uber thread (%d)\n", gtid)); 8037cc577a4SJonathan Peyton th->th.th_info.ds.ds_thread = pthread_self(); 8047cc577a4SJonathan Peyton __kmp_set_stack_info(gtid, th); 8057cc577a4SJonathan Peyton __kmp_check_stack_overlap(th); 8067cc577a4SJonathan Peyton return; 807bd3a7633SJonathan Peyton } 8087cc577a4SJonathan Peyton 8097cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_create_worker: try to create thread (%d)\n", gtid)); 8107cc577a4SJonathan Peyton 8117cc577a4SJonathan Peyton KMP_MB(); /* Flush all pending memory write invalidates. */ 8127cc577a4SJonathan Peyton 8137cc577a4SJonathan Peyton #ifdef KMP_THREAD_ATTR 8147cc577a4SJonathan Peyton status = pthread_attr_init(&thread_attr); 8157cc577a4SJonathan Peyton if (status != 0) { 8166a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(CantInitThreadAttrs), KMP_ERR(status), __kmp_msg_null); 817bd3a7633SJonathan Peyton } 8187cc577a4SJonathan Peyton status = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); 8197cc577a4SJonathan Peyton if (status != 0) { 8206a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(CantSetWorkerState), KMP_ERR(status), __kmp_msg_null); 821bd3a7633SJonathan Peyton } 8227cc577a4SJonathan Peyton 8237cc577a4SJonathan Peyton /* Set stack size for this thread now. 8243041982dSJonathan Peyton The multiple of 2 is there because on some machines, requesting an unusual 8253041982dSJonathan Peyton stacksize causes the thread to have an offset before the dummy alloca() 8263041982dSJonathan Peyton takes place to create the offset. Since we want the user to have a 8273041982dSJonathan Peyton sufficient stacksize AND support a stack offset, we alloca() twice the 8283041982dSJonathan Peyton offset so that the upcoming alloca() does not eliminate any premade offset, 8293041982dSJonathan Peyton and also gives the user the stack space they requested for all threads */ 8307cc577a4SJonathan Peyton stack_size += gtid * __kmp_stkoffset * 2; 8317cc577a4SJonathan Peyton 8323d21a3afSYi Kong #if defined(__ANDROID__) && __ANDROID_API__ < 19 8333d21a3afSYi Kong // Round the stack size to a multiple of the page size. Older versions of 8343d21a3afSYi Kong // Android (until KitKat) would fail pthread_attr_setstacksize with EINVAL 8353d21a3afSYi Kong // if the stack size was not a multiple of the page size. 8363d21a3afSYi Kong stack_size = (stack_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); 8373d21a3afSYi Kong #endif 8383d21a3afSYi Kong 8397cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_create_worker: T#%d, default stacksize = %lu bytes, " 8407cc577a4SJonathan Peyton "__kmp_stksize = %lu bytes, final stacksize = %lu bytes\n", 8417cc577a4SJonathan Peyton gtid, KMP_DEFAULT_STKSIZE, __kmp_stksize, stack_size)); 8427cc577a4SJonathan Peyton 8437cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE 8447cc577a4SJonathan Peyton status = pthread_attr_setstacksize(&thread_attr, stack_size); 8457cc577a4SJonathan Peyton #ifdef KMP_BACKUP_STKSIZE 8467cc577a4SJonathan Peyton if (status != 0) { 8477cc577a4SJonathan Peyton if (!__kmp_env_stksize) { 8487cc577a4SJonathan Peyton stack_size = KMP_BACKUP_STKSIZE + gtid * __kmp_stkoffset; 8497cc577a4SJonathan Peyton __kmp_stksize = KMP_BACKUP_STKSIZE; 8507cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_create_worker: T#%d, default stacksize = %lu bytes, " 8517cc577a4SJonathan Peyton "__kmp_stksize = %lu bytes, (backup) final stacksize = %lu " 8527cc577a4SJonathan Peyton "bytes\n", 8533041982dSJonathan Peyton gtid, KMP_DEFAULT_STKSIZE, __kmp_stksize, stack_size)); 8547cc577a4SJonathan Peyton status = pthread_attr_setstacksize(&thread_attr, stack_size); 855bd3a7633SJonathan Peyton } 856bd3a7633SJonathan Peyton } 8577cc577a4SJonathan Peyton #endif /* KMP_BACKUP_STKSIZE */ 8587cc577a4SJonathan Peyton if (status != 0) { 8596a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(CantSetWorkerStackSize, stack_size), KMP_ERR(status), 8606a393f75SJonathan Peyton KMP_HNT(ChangeWorkerStackSize), __kmp_msg_null); 861bd3a7633SJonathan Peyton } 8627cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */ 8637cc577a4SJonathan Peyton 8647cc577a4SJonathan Peyton #endif /* KMP_THREAD_ATTR */ 8657cc577a4SJonathan Peyton 8663041982dSJonathan Peyton status = 8673041982dSJonathan Peyton pthread_create(&handle, &thread_attr, __kmp_launch_worker, (void *)th); 8687cc577a4SJonathan Peyton if (status != 0 || !handle) { // ??? Why do we check handle?? 8697cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE 8707cc577a4SJonathan Peyton if (status == EINVAL) { 8716a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(CantSetWorkerStackSize, stack_size), KMP_ERR(status), 8726a393f75SJonathan Peyton KMP_HNT(IncreaseWorkerStackSize), __kmp_msg_null); 873bd3a7633SJonathan Peyton } 8747cc577a4SJonathan Peyton if (status == ENOMEM) { 8756a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(CantSetWorkerStackSize, stack_size), KMP_ERR(status), 8766a393f75SJonathan Peyton KMP_HNT(DecreaseWorkerStackSize), __kmp_msg_null); 877bd3a7633SJonathan Peyton } 8787cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */ 8797cc577a4SJonathan Peyton if (status == EAGAIN) { 8806a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(NoResourcesForWorkerThread), KMP_ERR(status), 8816a393f75SJonathan Peyton KMP_HNT(Decrease_NUM_THREADS), __kmp_msg_null); 882bd3a7633SJonathan Peyton } 8837cc577a4SJonathan Peyton KMP_SYSFAIL("pthread_create", status); 884bd3a7633SJonathan Peyton } 8857cc577a4SJonathan Peyton 8867cc577a4SJonathan Peyton th->th.th_info.ds.ds_thread = handle; 8877cc577a4SJonathan Peyton 8887cc577a4SJonathan Peyton #ifdef KMP_THREAD_ATTR 8897cc577a4SJonathan Peyton status = pthread_attr_destroy(&thread_attr); 8907cc577a4SJonathan Peyton if (status) { 8917cc577a4SJonathan Peyton kmp_msg_t err_code = KMP_ERR(status); 8923041982dSJonathan Peyton __kmp_msg(kmp_ms_warning, KMP_MSG(CantDestroyThreadAttrs), err_code, 8933041982dSJonathan Peyton __kmp_msg_null); 8947cc577a4SJonathan Peyton if (__kmp_generate_warnings == kmp_warnings_off) { 8957cc577a4SJonathan Peyton __kmp_str_free(&err_code.str); 8967cc577a4SJonathan Peyton } 897bd3a7633SJonathan Peyton } 8987cc577a4SJonathan Peyton #endif /* KMP_THREAD_ATTR */ 8997cc577a4SJonathan Peyton 9007cc577a4SJonathan Peyton KMP_MB(); /* Flush all pending memory write invalidates. */ 9017cc577a4SJonathan Peyton 9027cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_create_worker: done creating thread (%d)\n", gtid)); 9037cc577a4SJonathan Peyton 9047cc577a4SJonathan Peyton } // __kmp_create_worker 9057cc577a4SJonathan Peyton 9067cc577a4SJonathan Peyton #if KMP_USE_MONITOR 9073041982dSJonathan Peyton void __kmp_create_monitor(kmp_info_t *th) { 9087cc577a4SJonathan Peyton pthread_t handle; 9097cc577a4SJonathan Peyton pthread_attr_t thread_attr; 9107cc577a4SJonathan Peyton size_t size; 9117cc577a4SJonathan Peyton int status; 9127cc577a4SJonathan Peyton int auto_adj_size = FALSE; 9137cc577a4SJonathan Peyton 9147cc577a4SJonathan Peyton if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME) { 9157cc577a4SJonathan Peyton // We don't need monitor thread in case of MAX_BLOCKTIME 9163041982dSJonathan Peyton KA_TRACE(10, ("__kmp_create_monitor: skipping monitor thread because of " 9173041982dSJonathan Peyton "MAX blocktime\n")); 9187cc577a4SJonathan Peyton th->th.th_info.ds.ds_tid = 0; // this makes reap_monitor no-op 9197cc577a4SJonathan Peyton th->th.th_info.ds.ds_gtid = 0; 9207cc577a4SJonathan Peyton return; 9217cc577a4SJonathan Peyton } 9227cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_create_monitor: try to create monitor\n")); 9237cc577a4SJonathan Peyton 9247cc577a4SJonathan Peyton KMP_MB(); /* Flush all pending memory write invalidates. */ 9257cc577a4SJonathan Peyton 9267cc577a4SJonathan Peyton th->th.th_info.ds.ds_tid = KMP_GTID_MONITOR; 9277cc577a4SJonathan Peyton th->th.th_info.ds.ds_gtid = KMP_GTID_MONITOR; 9287cc577a4SJonathan Peyton #if KMP_REAL_TIME_FIX 9293041982dSJonathan Peyton TCW_4(__kmp_global.g.g_time.dt.t_value, 9303041982dSJonathan Peyton -1); // Will use it for synchronization a bit later. 9317cc577a4SJonathan Peyton #else 9327cc577a4SJonathan Peyton TCW_4(__kmp_global.g.g_time.dt.t_value, 0); 9337cc577a4SJonathan Peyton #endif // KMP_REAL_TIME_FIX 9347cc577a4SJonathan Peyton 9357cc577a4SJonathan Peyton #ifdef KMP_THREAD_ATTR 9367cc577a4SJonathan Peyton if (__kmp_monitor_stksize == 0) { 9377cc577a4SJonathan Peyton __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE; 9387cc577a4SJonathan Peyton auto_adj_size = TRUE; 9397cc577a4SJonathan Peyton } 9407cc577a4SJonathan Peyton status = pthread_attr_init(&thread_attr); 9417cc577a4SJonathan Peyton if (status != 0) { 9426a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(CantInitThreadAttrs), KMP_ERR(status), __kmp_msg_null); 943bd3a7633SJonathan Peyton } 9447cc577a4SJonathan Peyton status = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); 9457cc577a4SJonathan Peyton if (status != 0) { 9466a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(CantSetMonitorState), KMP_ERR(status), __kmp_msg_null); 947bd3a7633SJonathan Peyton } 9487cc577a4SJonathan Peyton 9497cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE 9507cc577a4SJonathan Peyton status = pthread_attr_getstacksize(&thread_attr, &size); 9517cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_attr_getstacksize", status); 9527cc577a4SJonathan Peyton #else 9537cc577a4SJonathan Peyton size = __kmp_sys_min_stksize; 9547cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */ 9557cc577a4SJonathan Peyton #endif /* KMP_THREAD_ATTR */ 9567cc577a4SJonathan Peyton 9577cc577a4SJonathan Peyton if (__kmp_monitor_stksize == 0) { 9587cc577a4SJonathan Peyton __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE; 9597cc577a4SJonathan Peyton } 9607cc577a4SJonathan Peyton if (__kmp_monitor_stksize < __kmp_sys_min_stksize) { 9617cc577a4SJonathan Peyton __kmp_monitor_stksize = __kmp_sys_min_stksize; 9627cc577a4SJonathan Peyton } 9637cc577a4SJonathan Peyton 9647cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_create_monitor: default stacksize = %lu bytes," 9657cc577a4SJonathan Peyton "requested stacksize = %lu bytes\n", 9667cc577a4SJonathan Peyton size, __kmp_monitor_stksize)); 9677cc577a4SJonathan Peyton 9687cc577a4SJonathan Peyton retry: 9697cc577a4SJonathan Peyton 9707cc577a4SJonathan Peyton /* Set stack size for this thread now. */ 9717cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE 9727cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_create_monitor: setting stacksize = %lu bytes,", 9737cc577a4SJonathan Peyton __kmp_monitor_stksize)); 9747cc577a4SJonathan Peyton status = pthread_attr_setstacksize(&thread_attr, __kmp_monitor_stksize); 9757cc577a4SJonathan Peyton if (status != 0) { 9767cc577a4SJonathan Peyton if (auto_adj_size) { 9777cc577a4SJonathan Peyton __kmp_monitor_stksize *= 2; 9787cc577a4SJonathan Peyton goto retry; 9797cc577a4SJonathan Peyton } 9807cc577a4SJonathan Peyton kmp_msg_t err_code = KMP_ERR(status); 9813041982dSJonathan Peyton __kmp_msg(kmp_ms_warning, // should this be fatal? BB 9827cc577a4SJonathan Peyton KMP_MSG(CantSetMonitorStackSize, (long int)__kmp_monitor_stksize), 9833041982dSJonathan Peyton err_code, KMP_HNT(ChangeMonitorStackSize), __kmp_msg_null); 9847cc577a4SJonathan Peyton if (__kmp_generate_warnings == kmp_warnings_off) { 9857cc577a4SJonathan Peyton __kmp_str_free(&err_code.str); 9867cc577a4SJonathan Peyton } 987bd3a7633SJonathan Peyton } 9887cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */ 9897cc577a4SJonathan Peyton 9903041982dSJonathan Peyton status = 9913041982dSJonathan Peyton pthread_create(&handle, &thread_attr, __kmp_launch_monitor, (void *)th); 9927cc577a4SJonathan Peyton 9937cc577a4SJonathan Peyton if (status != 0) { 9947cc577a4SJonathan Peyton #ifdef _POSIX_THREAD_ATTR_STACKSIZE 9957cc577a4SJonathan Peyton if (status == EINVAL) { 9967cc577a4SJonathan Peyton if (auto_adj_size && (__kmp_monitor_stksize < (size_t)0x40000000)) { 9977cc577a4SJonathan Peyton __kmp_monitor_stksize *= 2; 9987cc577a4SJonathan Peyton goto retry; 9997cc577a4SJonathan Peyton } 10006a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(CantSetMonitorStackSize, __kmp_monitor_stksize), 10016a393f75SJonathan Peyton KMP_ERR(status), KMP_HNT(IncreaseMonitorStackSize), 10026a393f75SJonathan Peyton __kmp_msg_null); 1003bd3a7633SJonathan Peyton } 10047cc577a4SJonathan Peyton if (status == ENOMEM) { 10056a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(CantSetMonitorStackSize, __kmp_monitor_stksize), 10066a393f75SJonathan Peyton KMP_ERR(status), KMP_HNT(DecreaseMonitorStackSize), 10076a393f75SJonathan Peyton __kmp_msg_null); 1008bd3a7633SJonathan Peyton } 10097cc577a4SJonathan Peyton #endif /* _POSIX_THREAD_ATTR_STACKSIZE */ 10107cc577a4SJonathan Peyton if (status == EAGAIN) { 10116a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(NoResourcesForMonitorThread), KMP_ERR(status), 10126a393f75SJonathan Peyton KMP_HNT(DecreaseNumberOfThreadsInUse), __kmp_msg_null); 1013bd3a7633SJonathan Peyton } 10147cc577a4SJonathan Peyton KMP_SYSFAIL("pthread_create", status); 1015bd3a7633SJonathan Peyton } 10167cc577a4SJonathan Peyton 10177cc577a4SJonathan Peyton th->th.th_info.ds.ds_thread = handle; 10187cc577a4SJonathan Peyton 10197cc577a4SJonathan Peyton #if KMP_REAL_TIME_FIX 10207cc577a4SJonathan Peyton // Wait for the monitor thread is really started and set its *priority*. 10213041982dSJonathan Peyton KMP_DEBUG_ASSERT(sizeof(kmp_uint32) == 10223041982dSJonathan Peyton sizeof(__kmp_global.g.g_time.dt.t_value)); 1023e47d32f1SJonathan Peyton __kmp_wait_4((kmp_uint32 volatile *)&__kmp_global.g.g_time.dt.t_value, -1, 1024e47d32f1SJonathan Peyton &__kmp_neq_4, NULL); 10257cc577a4SJonathan Peyton #endif // KMP_REAL_TIME_FIX 10267cc577a4SJonathan Peyton 10277cc577a4SJonathan Peyton #ifdef KMP_THREAD_ATTR 10287cc577a4SJonathan Peyton status = pthread_attr_destroy(&thread_attr); 10297cc577a4SJonathan Peyton if (status != 0) { 10307cc577a4SJonathan Peyton kmp_msg_t err_code = KMP_ERR(status); 10313041982dSJonathan Peyton __kmp_msg(kmp_ms_warning, KMP_MSG(CantDestroyThreadAttrs), err_code, 10323041982dSJonathan Peyton __kmp_msg_null); 10337cc577a4SJonathan Peyton if (__kmp_generate_warnings == kmp_warnings_off) { 10347cc577a4SJonathan Peyton __kmp_str_free(&err_code.str); 10357cc577a4SJonathan Peyton } 1036bd3a7633SJonathan Peyton } 10377cc577a4SJonathan Peyton #endif 10387cc577a4SJonathan Peyton 10397cc577a4SJonathan Peyton KMP_MB(); /* Flush all pending memory write invalidates. */ 10407cc577a4SJonathan Peyton 10413041982dSJonathan Peyton KA_TRACE(10, ("__kmp_create_monitor: monitor created %#.8lx\n", 10423041982dSJonathan Peyton th->th.th_info.ds.ds_thread)); 10437cc577a4SJonathan Peyton 10447cc577a4SJonathan Peyton } // __kmp_create_monitor 10457cc577a4SJonathan Peyton #endif // KMP_USE_MONITOR 10467cc577a4SJonathan Peyton 10473041982dSJonathan Peyton void __kmp_exit_thread(int exit_status) { 10487cc577a4SJonathan Peyton pthread_exit((void *)(intptr_t)exit_status); 10497cc577a4SJonathan Peyton } // __kmp_exit_thread 10507cc577a4SJonathan Peyton 10517cc577a4SJonathan Peyton #if KMP_USE_MONITOR 10527cc577a4SJonathan Peyton void __kmp_resume_monitor(); 10537cc577a4SJonathan Peyton 10543041982dSJonathan Peyton void __kmp_reap_monitor(kmp_info_t *th) { 10557cc577a4SJonathan Peyton int status; 10567cc577a4SJonathan Peyton void *exit_val; 10577cc577a4SJonathan Peyton 10583041982dSJonathan Peyton KA_TRACE(10, ("__kmp_reap_monitor: try to reap monitor thread with handle" 10593041982dSJonathan Peyton " %#.8lx\n", 10607cc577a4SJonathan Peyton th->th.th_info.ds.ds_thread)); 10617cc577a4SJonathan Peyton 10627cc577a4SJonathan Peyton // If monitor has been created, its tid and gtid should be KMP_GTID_MONITOR. 10637cc577a4SJonathan Peyton // If both tid and gtid are 0, it means the monitor did not ever start. 10647cc577a4SJonathan Peyton // If both tid and gtid are KMP_GTID_DNE, the monitor has been shut down. 10657cc577a4SJonathan Peyton KMP_DEBUG_ASSERT(th->th.th_info.ds.ds_tid == th->th.th_info.ds.ds_gtid); 10667cc577a4SJonathan Peyton if (th->th.th_info.ds.ds_gtid != KMP_GTID_MONITOR) { 10677cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_reap_monitor: monitor did not start, returning\n")); 10687cc577a4SJonathan Peyton return; 1069bd3a7633SJonathan Peyton } 10707cc577a4SJonathan Peyton 10717cc577a4SJonathan Peyton KMP_MB(); /* Flush all pending memory write invalidates. */ 10727cc577a4SJonathan Peyton 10733041982dSJonathan Peyton /* First, check to see whether the monitor thread exists to wake it up. This 10743041982dSJonathan Peyton is to avoid performance problem when the monitor sleeps during 10753041982dSJonathan Peyton blocktime-size interval */ 10767cc577a4SJonathan Peyton 10777cc577a4SJonathan Peyton status = pthread_kill(th->th.th_info.ds.ds_thread, 0); 10787cc577a4SJonathan Peyton if (status != ESRCH) { 10797cc577a4SJonathan Peyton __kmp_resume_monitor(); // Wake up the monitor thread 10807cc577a4SJonathan Peyton } 10817cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_reap_monitor: try to join with monitor\n")); 10827cc577a4SJonathan Peyton status = pthread_join(th->th.th_info.ds.ds_thread, &exit_val); 10837cc577a4SJonathan Peyton if (exit_val != th) { 10846a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(ReapMonitorError), KMP_ERR(status), __kmp_msg_null); 10857cc577a4SJonathan Peyton } 10867cc577a4SJonathan Peyton 10877cc577a4SJonathan Peyton th->th.th_info.ds.ds_tid = KMP_GTID_DNE; 10887cc577a4SJonathan Peyton th->th.th_info.ds.ds_gtid = KMP_GTID_DNE; 10897cc577a4SJonathan Peyton 10903041982dSJonathan Peyton KA_TRACE(10, ("__kmp_reap_monitor: done reaping monitor thread with handle" 10913041982dSJonathan Peyton " %#.8lx\n", 10927cc577a4SJonathan Peyton th->th.th_info.ds.ds_thread)); 10937cc577a4SJonathan Peyton 10947cc577a4SJonathan Peyton KMP_MB(); /* Flush all pending memory write invalidates. */ 10957cc577a4SJonathan Peyton } 10967cc577a4SJonathan Peyton #endif // KMP_USE_MONITOR 10977cc577a4SJonathan Peyton 10983041982dSJonathan Peyton void __kmp_reap_worker(kmp_info_t *th) { 10997cc577a4SJonathan Peyton int status; 11007cc577a4SJonathan Peyton void *exit_val; 11017cc577a4SJonathan Peyton 11027cc577a4SJonathan Peyton KMP_MB(); /* Flush all pending memory write invalidates. */ 11037cc577a4SJonathan Peyton 11043041982dSJonathan Peyton KA_TRACE( 11053041982dSJonathan Peyton 10, ("__kmp_reap_worker: try to reap T#%d\n", th->th.th_info.ds.ds_gtid)); 11067cc577a4SJonathan Peyton 11077cc577a4SJonathan Peyton status = pthread_join(th->th.th_info.ds.ds_thread, &exit_val); 11087cc577a4SJonathan Peyton #ifdef KMP_DEBUG 11097cc577a4SJonathan Peyton /* Don't expose these to the user until we understand when they trigger */ 11107cc577a4SJonathan Peyton if (status != 0) { 11116a393f75SJonathan Peyton __kmp_fatal(KMP_MSG(ReapWorkerError), KMP_ERR(status), __kmp_msg_null); 11127cc577a4SJonathan Peyton } 11137cc577a4SJonathan Peyton if (exit_val != th) { 11143041982dSJonathan Peyton KA_TRACE(10, ("__kmp_reap_worker: worker T#%d did not reap properly, " 11153041982dSJonathan Peyton "exit_val = %p\n", 11167cc577a4SJonathan Peyton th->th.th_info.ds.ds_gtid, exit_val)); 11177cc577a4SJonathan Peyton } 11187cc577a4SJonathan Peyton #endif /* KMP_DEBUG */ 11197cc577a4SJonathan Peyton 11203041982dSJonathan Peyton KA_TRACE(10, ("__kmp_reap_worker: done reaping T#%d\n", 11213041982dSJonathan Peyton th->th.th_info.ds.ds_gtid)); 11227cc577a4SJonathan Peyton 11237cc577a4SJonathan Peyton KMP_MB(); /* Flush all pending memory write invalidates. */ 11247cc577a4SJonathan Peyton } 11257cc577a4SJonathan Peyton 11267cc577a4SJonathan Peyton #if KMP_HANDLE_SIGNALS 11277cc577a4SJonathan Peyton 11283041982dSJonathan Peyton static void __kmp_null_handler(int signo) { 11297cc577a4SJonathan Peyton // Do nothing, for doing SIG_IGN-type actions. 11307cc577a4SJonathan Peyton } // __kmp_null_handler 11317cc577a4SJonathan Peyton 11323041982dSJonathan Peyton static void __kmp_team_handler(int signo) { 11337cc577a4SJonathan Peyton if (__kmp_global.g.g_abort == 0) { 11347cc577a4SJonathan Peyton /* Stage 1 signal handler, let's shut down all of the threads */ 11357cc577a4SJonathan Peyton #ifdef KMP_DEBUG 11367cc577a4SJonathan Peyton __kmp_debug_printf("__kmp_team_handler: caught signal = %d\n", signo); 11377cc577a4SJonathan Peyton #endif 11387cc577a4SJonathan Peyton switch (signo) { 11397cc577a4SJonathan Peyton case SIGHUP: 11407cc577a4SJonathan Peyton case SIGINT: 11417cc577a4SJonathan Peyton case SIGQUIT: 11427cc577a4SJonathan Peyton case SIGILL: 11437cc577a4SJonathan Peyton case SIGABRT: 11447cc577a4SJonathan Peyton case SIGFPE: 11457cc577a4SJonathan Peyton case SIGBUS: 11467cc577a4SJonathan Peyton case SIGSEGV: 11477cc577a4SJonathan Peyton #ifdef SIGSYS 11487cc577a4SJonathan Peyton case SIGSYS: 11497cc577a4SJonathan Peyton #endif 11507cc577a4SJonathan Peyton case SIGTERM: 11517cc577a4SJonathan Peyton if (__kmp_debug_buf) { 11527cc577a4SJonathan Peyton __kmp_dump_debug_buffer(); 1153bd3a7633SJonathan Peyton } 11549615890dSTodd Erdner __kmp_unregister_library(); // cleanup shared memory 11557cc577a4SJonathan Peyton KMP_MB(); // Flush all pending memory write invalidates. 11567cc577a4SJonathan Peyton TCW_4(__kmp_global.g.g_abort, signo); 11577cc577a4SJonathan Peyton KMP_MB(); // Flush all pending memory write invalidates. 11587cc577a4SJonathan Peyton TCW_4(__kmp_global.g.g_done, TRUE); 11597cc577a4SJonathan Peyton KMP_MB(); // Flush all pending memory write invalidates. 11607cc577a4SJonathan Peyton break; 11617cc577a4SJonathan Peyton default: 11627cc577a4SJonathan Peyton #ifdef KMP_DEBUG 11637cc577a4SJonathan Peyton __kmp_debug_printf("__kmp_team_handler: unknown signal type"); 11647cc577a4SJonathan Peyton #endif 11657cc577a4SJonathan Peyton break; 1166bd3a7633SJonathan Peyton } 1167bd3a7633SJonathan Peyton } 11687cc577a4SJonathan Peyton } // __kmp_team_handler 11697cc577a4SJonathan Peyton 11703041982dSJonathan Peyton static void __kmp_sigaction(int signum, const struct sigaction *act, 11713041982dSJonathan Peyton struct sigaction *oldact) { 11727cc577a4SJonathan Peyton int rc = sigaction(signum, act, oldact); 11737cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL_ERRNO("sigaction", rc); 11747cc577a4SJonathan Peyton } 11757cc577a4SJonathan Peyton 11763041982dSJonathan Peyton static void __kmp_install_one_handler(int sig, sig_func_t handler_func, 11773041982dSJonathan Peyton int parallel_init) { 11787cc577a4SJonathan Peyton KMP_MB(); // Flush all pending memory write invalidates. 11793041982dSJonathan Peyton KB_TRACE(60, 11803041982dSJonathan Peyton ("__kmp_install_one_handler( %d, ..., %d )\n", sig, parallel_init)); 11817cc577a4SJonathan Peyton if (parallel_init) { 11827cc577a4SJonathan Peyton struct sigaction new_action; 11837cc577a4SJonathan Peyton struct sigaction old_action; 11847cc577a4SJonathan Peyton new_action.sa_handler = handler_func; 11857cc577a4SJonathan Peyton new_action.sa_flags = 0; 11867cc577a4SJonathan Peyton sigfillset(&new_action.sa_mask); 11877cc577a4SJonathan Peyton __kmp_sigaction(sig, &new_action, &old_action); 11887cc577a4SJonathan Peyton if (old_action.sa_handler == __kmp_sighldrs[sig].sa_handler) { 11897cc577a4SJonathan Peyton sigaddset(&__kmp_sigset, sig); 11907cc577a4SJonathan Peyton } else { 11917cc577a4SJonathan Peyton // Restore/keep user's handler if one previously installed. 11927cc577a4SJonathan Peyton __kmp_sigaction(sig, &old_action, NULL); 1193bd3a7633SJonathan Peyton } 11947cc577a4SJonathan Peyton } else { 11957cc577a4SJonathan Peyton // Save initial/system signal handlers to see if user handlers installed. 11967cc577a4SJonathan Peyton __kmp_sigaction(sig, NULL, &__kmp_sighldrs[sig]); 1197bd3a7633SJonathan Peyton } 11987cc577a4SJonathan Peyton KMP_MB(); // Flush all pending memory write invalidates. 11997cc577a4SJonathan Peyton } // __kmp_install_one_handler 12007cc577a4SJonathan Peyton 12013041982dSJonathan Peyton static void __kmp_remove_one_handler(int sig) { 12027cc577a4SJonathan Peyton KB_TRACE(60, ("__kmp_remove_one_handler( %d )\n", sig)); 12037cc577a4SJonathan Peyton if (sigismember(&__kmp_sigset, sig)) { 12047cc577a4SJonathan Peyton struct sigaction old; 12057cc577a4SJonathan Peyton KMP_MB(); // Flush all pending memory write invalidates. 12067cc577a4SJonathan Peyton __kmp_sigaction(sig, &__kmp_sighldrs[sig], &old); 12073041982dSJonathan Peyton if ((old.sa_handler != __kmp_team_handler) && 12083041982dSJonathan Peyton (old.sa_handler != __kmp_null_handler)) { 12097cc577a4SJonathan Peyton // Restore the users signal handler. 12103041982dSJonathan Peyton KB_TRACE(10, ("__kmp_remove_one_handler: oops, not our handler, " 12113041982dSJonathan Peyton "restoring: sig=%d\n", 12123041982dSJonathan Peyton sig)); 12137cc577a4SJonathan Peyton __kmp_sigaction(sig, &old, NULL); 1214bd3a7633SJonathan Peyton } 12157cc577a4SJonathan Peyton sigdelset(&__kmp_sigset, sig); 12167cc577a4SJonathan Peyton KMP_MB(); // Flush all pending memory write invalidates. 1217bd3a7633SJonathan Peyton } 12187cc577a4SJonathan Peyton } // __kmp_remove_one_handler 12197cc577a4SJonathan Peyton 12203041982dSJonathan Peyton void __kmp_install_signals(int parallel_init) { 12217cc577a4SJonathan Peyton KB_TRACE(10, ("__kmp_install_signals( %d )\n", parallel_init)); 12227cc577a4SJonathan Peyton if (__kmp_handle_signals || !parallel_init) { 12233041982dSJonathan Peyton // If ! parallel_init, we do not install handlers, just save original 12243041982dSJonathan Peyton // handlers. Let us do it even __handle_signals is 0. 12257cc577a4SJonathan Peyton sigemptyset(&__kmp_sigset); 12267cc577a4SJonathan Peyton __kmp_install_one_handler(SIGHUP, __kmp_team_handler, parallel_init); 12277cc577a4SJonathan Peyton __kmp_install_one_handler(SIGINT, __kmp_team_handler, parallel_init); 12287cc577a4SJonathan Peyton __kmp_install_one_handler(SIGQUIT, __kmp_team_handler, parallel_init); 12297cc577a4SJonathan Peyton __kmp_install_one_handler(SIGILL, __kmp_team_handler, parallel_init); 12307cc577a4SJonathan Peyton __kmp_install_one_handler(SIGABRT, __kmp_team_handler, parallel_init); 12317cc577a4SJonathan Peyton __kmp_install_one_handler(SIGFPE, __kmp_team_handler, parallel_init); 12327cc577a4SJonathan Peyton __kmp_install_one_handler(SIGBUS, __kmp_team_handler, parallel_init); 12337cc577a4SJonathan Peyton __kmp_install_one_handler(SIGSEGV, __kmp_team_handler, parallel_init); 12347cc577a4SJonathan Peyton #ifdef SIGSYS 12357cc577a4SJonathan Peyton __kmp_install_one_handler(SIGSYS, __kmp_team_handler, parallel_init); 12367cc577a4SJonathan Peyton #endif // SIGSYS 12377cc577a4SJonathan Peyton __kmp_install_one_handler(SIGTERM, __kmp_team_handler, parallel_init); 12387cc577a4SJonathan Peyton #ifdef SIGPIPE 12397cc577a4SJonathan Peyton __kmp_install_one_handler(SIGPIPE, __kmp_team_handler, parallel_init); 12407cc577a4SJonathan Peyton #endif // SIGPIPE 1241bd3a7633SJonathan Peyton } 12427cc577a4SJonathan Peyton } // __kmp_install_signals 12437cc577a4SJonathan Peyton 12443041982dSJonathan Peyton void __kmp_remove_signals(void) { 12457cc577a4SJonathan Peyton int sig; 12467cc577a4SJonathan Peyton KB_TRACE(10, ("__kmp_remove_signals()\n")); 12477cc577a4SJonathan Peyton for (sig = 1; sig < NSIG; ++sig) { 12487cc577a4SJonathan Peyton __kmp_remove_one_handler(sig); 1249bd3a7633SJonathan Peyton } 12507cc577a4SJonathan Peyton } // __kmp_remove_signals 12517cc577a4SJonathan Peyton 12527cc577a4SJonathan Peyton #endif // KMP_HANDLE_SIGNALS 12537cc577a4SJonathan Peyton 12543041982dSJonathan Peyton void __kmp_enable(int new_state) { 12557cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS 12567cc577a4SJonathan Peyton int status, old_state; 12577cc577a4SJonathan Peyton status = pthread_setcancelstate(new_state, &old_state); 12587cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_setcancelstate", status); 12597cc577a4SJonathan Peyton KMP_DEBUG_ASSERT(old_state == PTHREAD_CANCEL_DISABLE); 12607cc577a4SJonathan Peyton #endif 12617cc577a4SJonathan Peyton } 12627cc577a4SJonathan Peyton 12633041982dSJonathan Peyton void __kmp_disable(int *old_state) { 12647cc577a4SJonathan Peyton #ifdef KMP_CANCEL_THREADS 12657cc577a4SJonathan Peyton int status; 12667cc577a4SJonathan Peyton status = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, old_state); 12677cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_setcancelstate", status); 12687cc577a4SJonathan Peyton #endif 12697cc577a4SJonathan Peyton } 12707cc577a4SJonathan Peyton 1271eaa9e40cSJonathan Peyton static void __kmp_atfork_prepare(void) { 1272eaa9e40cSJonathan Peyton __kmp_acquire_bootstrap_lock(&__kmp_initz_lock); 1273eaa9e40cSJonathan Peyton __kmp_acquire_bootstrap_lock(&__kmp_forkjoin_lock); 12747cc577a4SJonathan Peyton } 12757cc577a4SJonathan Peyton 1276eaa9e40cSJonathan Peyton static void __kmp_atfork_parent(void) { 1277eaa9e40cSJonathan Peyton __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock); 1278171ca93cSHansang Bae __kmp_release_bootstrap_lock(&__kmp_initz_lock); 12797cc577a4SJonathan Peyton } 12807cc577a4SJonathan Peyton 12813041982dSJonathan Peyton /* Reset the library so execution in the child starts "all over again" with 12827cc577a4SJonathan Peyton clean data structures in initial states. Don't worry about freeing memory 12833041982dSJonathan Peyton allocated by parent, just abandon it to be safe. */ 12843041982dSJonathan Peyton static void __kmp_atfork_child(void) { 1285eaa9e40cSJonathan Peyton __kmp_release_bootstrap_lock(&__kmp_forkjoin_lock); 1286171ca93cSHansang Bae __kmp_release_bootstrap_lock(&__kmp_initz_lock); 12877cc577a4SJonathan Peyton /* TODO make sure this is done right for nested/sibling */ 12887cc577a4SJonathan Peyton // ATT: Memory leaks are here? TODO: Check it and fix. 12897cc577a4SJonathan Peyton /* KMP_ASSERT( 0 ); */ 12907cc577a4SJonathan Peyton 12917cc577a4SJonathan Peyton ++__kmp_fork_count; 12927cc577a4SJonathan Peyton 1293072ccb72SJonathan Peyton #if KMP_AFFINITY_SUPPORTED 129450699284SDavid Carlier #if KMP_OS_LINUX || KMP_OS_FREEBSD 1295d330e630SJonathan Peyton // reset the affinity in the child to the initial thread 1296d330e630SJonathan Peyton // affinity in the parent 1297d330e630SJonathan Peyton kmp_set_thread_affinity_mask_initial(); 1298d330e630SJonathan Peyton #endif 1299072ccb72SJonathan Peyton // Set default not to bind threads tightly in the child (we’re expecting 1300072ccb72SJonathan Peyton // over-subscription after the fork and this can improve things for 1301072ccb72SJonathan Peyton // scripting languages that use OpenMP inside process-parallel code). 1302072ccb72SJonathan Peyton __kmp_affinity_type = affinity_none; 1303072ccb72SJonathan Peyton if (__kmp_nested_proc_bind.bind_types != NULL) { 1304072ccb72SJonathan Peyton __kmp_nested_proc_bind.bind_types[0] = proc_bind_false; 1305072ccb72SJonathan Peyton } 1306072ccb72SJonathan Peyton #endif // KMP_AFFINITY_SUPPORTED 1307d330e630SJonathan Peyton 13087cc577a4SJonathan Peyton #if KMP_USE_MONITOR 13097cc577a4SJonathan Peyton __kmp_init_monitor = 0; 13107cc577a4SJonathan Peyton #endif 13117cc577a4SJonathan Peyton __kmp_init_parallel = FALSE; 13127cc577a4SJonathan Peyton __kmp_init_middle = FALSE; 13137cc577a4SJonathan Peyton __kmp_init_serial = FALSE; 13147cc577a4SJonathan Peyton TCW_4(__kmp_init_gtid, FALSE); 13157cc577a4SJonathan Peyton __kmp_init_common = FALSE; 13167cc577a4SJonathan Peyton 13177cc577a4SJonathan Peyton TCW_4(__kmp_init_user_locks, FALSE); 13187cc577a4SJonathan Peyton #if !KMP_USE_DYNAMIC_LOCK 13197cc577a4SJonathan Peyton __kmp_user_lock_table.used = 1; 13207cc577a4SJonathan Peyton __kmp_user_lock_table.allocated = 0; 13217cc577a4SJonathan Peyton __kmp_user_lock_table.table = NULL; 13227cc577a4SJonathan Peyton __kmp_lock_blocks = NULL; 13237cc577a4SJonathan Peyton #endif 13247cc577a4SJonathan Peyton 13257cc577a4SJonathan Peyton __kmp_all_nth = 0; 13267cc577a4SJonathan Peyton TCW_4(__kmp_nth, 0); 13277cc577a4SJonathan Peyton 1328eaa9e40cSJonathan Peyton __kmp_thread_pool = NULL; 1329eaa9e40cSJonathan Peyton __kmp_thread_pool_insert_pt = NULL; 1330eaa9e40cSJonathan Peyton __kmp_team_pool = NULL; 1331eaa9e40cSJonathan Peyton 13323041982dSJonathan Peyton /* Must actually zero all the *cache arguments passed to __kmpc_threadprivate 13333041982dSJonathan Peyton here so threadprivate doesn't use stale data */ 13347cc577a4SJonathan Peyton KA_TRACE(10, ("__kmp_atfork_child: checking cache address list %p\n", 13357cc577a4SJonathan Peyton __kmp_threadpriv_cache_list)); 13367cc577a4SJonathan Peyton 13377cc577a4SJonathan Peyton while (__kmp_threadpriv_cache_list != NULL) { 13387cc577a4SJonathan Peyton 13397cc577a4SJonathan Peyton if (*__kmp_threadpriv_cache_list->addr != NULL) { 13407cc577a4SJonathan Peyton KC_TRACE(50, ("__kmp_atfork_child: zeroing cache at address %p\n", 13417cc577a4SJonathan Peyton &(*__kmp_threadpriv_cache_list->addr))); 13427cc577a4SJonathan Peyton 13437cc577a4SJonathan Peyton *__kmp_threadpriv_cache_list->addr = NULL; 13447cc577a4SJonathan Peyton } 13457cc577a4SJonathan Peyton __kmp_threadpriv_cache_list = __kmp_threadpriv_cache_list->next; 13467cc577a4SJonathan Peyton } 13477cc577a4SJonathan Peyton 13487cc577a4SJonathan Peyton __kmp_init_runtime = FALSE; 13497cc577a4SJonathan Peyton 13507cc577a4SJonathan Peyton /* reset statically initialized locks */ 13517cc577a4SJonathan Peyton __kmp_init_bootstrap_lock(&__kmp_initz_lock); 13527cc577a4SJonathan Peyton __kmp_init_bootstrap_lock(&__kmp_stdio_lock); 13537cc577a4SJonathan Peyton __kmp_init_bootstrap_lock(&__kmp_console_lock); 1354eaa9e40cSJonathan Peyton __kmp_init_bootstrap_lock(&__kmp_task_team_lock); 1355eaa9e40cSJonathan Peyton 13565388acd3SAndrey Churbanov #if USE_ITT_BUILD 1357eaa9e40cSJonathan Peyton __kmp_itt_reset(); // reset ITT's global state 13585388acd3SAndrey Churbanov #endif /* USE_ITT_BUILD */ 13597cc577a4SJonathan Peyton 1360171ca93cSHansang Bae __kmp_serial_initialize(); 1361171ca93cSHansang Bae 13627cc577a4SJonathan Peyton /* This is necessary to make sure no stale data is left around */ 13637cc577a4SJonathan Peyton /* AC: customers complain that we use unsafe routines in the atfork 13647cc577a4SJonathan Peyton handler. Mathworks: dlsym() is unsafe. We call dlsym and dlopen 13657cc577a4SJonathan Peyton in dynamic_link when check the presence of shared tbbmalloc library. 13667cc577a4SJonathan Peyton Suggestion is to make the library initialization lazier, similar 13677cc577a4SJonathan Peyton to what done for __kmpc_begin(). */ 13687cc577a4SJonathan Peyton // TODO: synchronize all static initializations with regular library 1369de4749b7SJonathan Peyton // startup; look at kmp_global.cpp and etc. 13707cc577a4SJonathan Peyton //__kmp_internal_begin (); 13717cc577a4SJonathan Peyton } 13727cc577a4SJonathan Peyton 13733041982dSJonathan Peyton void __kmp_register_atfork(void) { 13747cc577a4SJonathan Peyton if (__kmp_need_register_atfork) { 13753041982dSJonathan Peyton int status = pthread_atfork(__kmp_atfork_prepare, __kmp_atfork_parent, 13763041982dSJonathan Peyton __kmp_atfork_child); 13777cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_atfork", status); 13787cc577a4SJonathan Peyton __kmp_need_register_atfork = FALSE; 13797cc577a4SJonathan Peyton } 13807cc577a4SJonathan Peyton } 13817cc577a4SJonathan Peyton 13823041982dSJonathan Peyton void __kmp_suspend_initialize(void) { 13837cc577a4SJonathan Peyton int status; 13847cc577a4SJonathan Peyton status = pthread_mutexattr_init(&__kmp_suspend_mutex_attr); 13857cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_mutexattr_init", status); 13867cc577a4SJonathan Peyton status = pthread_condattr_init(&__kmp_suspend_cond_attr); 13877cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_condattr_init", status); 13887cc577a4SJonathan Peyton } 13897cc577a4SJonathan Peyton 1390feac33ebSJonathan Peyton void __kmp_suspend_initialize_thread(kmp_info_t *th) { 13917cc577a4SJonathan Peyton ANNOTATE_HAPPENS_AFTER(&th->th.th_suspend_init_count); 1392f8f788b2SAndrey Churbanov int old_value = KMP_ATOMIC_LD_RLX(&th->th.th_suspend_init_count); 1393f8f788b2SAndrey Churbanov int new_value = __kmp_fork_count + 1; 1394f8f788b2SAndrey Churbanov // Return if already initialized 1395f8f788b2SAndrey Churbanov if (old_value == new_value) 1396f8f788b2SAndrey Churbanov return; 1397f8f788b2SAndrey Churbanov // Wait, then return if being initialized 1398*309b00a4SShilei Tian if (old_value == -1 || !__kmp_atomic_compare_store( 1399*309b00a4SShilei Tian &th->th.th_suspend_init_count, old_value, -1)) { 1400f8f788b2SAndrey Churbanov while (KMP_ATOMIC_LD_ACQ(&th->th.th_suspend_init_count) != new_value) { 1401f8f788b2SAndrey Churbanov KMP_CPU_PAUSE(); 1402f8f788b2SAndrey Churbanov } 1403f8f788b2SAndrey Churbanov } else { 1404f8f788b2SAndrey Churbanov // Claim to be the initializer and do initializations 14057cc577a4SJonathan Peyton int status; 14063041982dSJonathan Peyton status = pthread_cond_init(&th->th.th_suspend_cv.c_cond, 14073041982dSJonathan Peyton &__kmp_suspend_cond_attr); 14087cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_cond_init", status); 14093041982dSJonathan Peyton status = pthread_mutex_init(&th->th.th_suspend_mx.m_mutex, 14103041982dSJonathan Peyton &__kmp_suspend_mutex_attr); 14117cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_mutex_init", status); 1412f8f788b2SAndrey Churbanov KMP_ATOMIC_ST_REL(&th->th.th_suspend_init_count, new_value); 14137cc577a4SJonathan Peyton ANNOTATE_HAPPENS_BEFORE(&th->th.th_suspend_init_count); 1414bd3a7633SJonathan Peyton } 14157cc577a4SJonathan Peyton } 14167cc577a4SJonathan Peyton 14173041982dSJonathan Peyton void __kmp_suspend_uninitialize_thread(kmp_info_t *th) { 1418f8f788b2SAndrey Churbanov if (KMP_ATOMIC_LD_ACQ(&th->th.th_suspend_init_count) > __kmp_fork_count) { 14193041982dSJonathan Peyton /* this means we have initialize the suspension pthread objects for this 14203041982dSJonathan Peyton thread in this instance of the process */ 14217cc577a4SJonathan Peyton int status; 14227cc577a4SJonathan Peyton 14237cc577a4SJonathan Peyton status = pthread_cond_destroy(&th->th.th_suspend_cv.c_cond); 14247cc577a4SJonathan Peyton if (status != 0 && status != EBUSY) { 14257cc577a4SJonathan Peyton KMP_SYSFAIL("pthread_cond_destroy", status); 1426bd3a7633SJonathan Peyton } 14277cc577a4SJonathan Peyton status = pthread_mutex_destroy(&th->th.th_suspend_mx.m_mutex); 14287cc577a4SJonathan Peyton if (status != 0 && status != EBUSY) { 14297cc577a4SJonathan Peyton KMP_SYSFAIL("pthread_mutex_destroy", status); 1430bd3a7633SJonathan Peyton } 14317cc577a4SJonathan Peyton --th->th.th_suspend_init_count; 1432f8f788b2SAndrey Churbanov KMP_DEBUG_ASSERT(KMP_ATOMIC_LD_RLX(&th->th.th_suspend_init_count) == 1433f8f788b2SAndrey Churbanov __kmp_fork_count); 14347cc577a4SJonathan Peyton } 14357cc577a4SJonathan Peyton } 14367cc577a4SJonathan Peyton 14379b8bb323SJonathan Peyton // return true if lock obtained, false otherwise 14389b8bb323SJonathan Peyton int __kmp_try_suspend_mx(kmp_info_t *th) { 14399b8bb323SJonathan Peyton return (pthread_mutex_trylock(&th->th.th_suspend_mx.m_mutex) == 0); 14409b8bb323SJonathan Peyton } 14419b8bb323SJonathan Peyton 14429b8bb323SJonathan Peyton void __kmp_lock_suspend_mx(kmp_info_t *th) { 14439b8bb323SJonathan Peyton int status = pthread_mutex_lock(&th->th.th_suspend_mx.m_mutex); 14449b8bb323SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_mutex_lock", status); 14459b8bb323SJonathan Peyton } 14469b8bb323SJonathan Peyton 14479b8bb323SJonathan Peyton void __kmp_unlock_suspend_mx(kmp_info_t *th) { 14489b8bb323SJonathan Peyton int status = pthread_mutex_unlock(&th->th.th_suspend_mx.m_mutex); 14499b8bb323SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status); 14509b8bb323SJonathan Peyton } 14519b8bb323SJonathan Peyton 14527cc577a4SJonathan Peyton /* This routine puts the calling thread to sleep after setting the 14533041982dSJonathan Peyton sleep bit for the indicated flag variable to true. */ 14547cc577a4SJonathan Peyton template <class C> 14553041982dSJonathan Peyton static inline void __kmp_suspend_template(int th_gtid, C *flag) { 14567cc577a4SJonathan Peyton KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_suspend); 14577cc577a4SJonathan Peyton kmp_info_t *th = __kmp_threads[th_gtid]; 14587cc577a4SJonathan Peyton int status; 14597cc577a4SJonathan Peyton typename C::flag_t old_spin; 14607cc577a4SJonathan Peyton 14613041982dSJonathan Peyton KF_TRACE(30, ("__kmp_suspend_template: T#%d enter for flag = %p\n", th_gtid, 14623041982dSJonathan Peyton flag->get())); 14637cc577a4SJonathan Peyton 14647cc577a4SJonathan Peyton __kmp_suspend_initialize_thread(th); 14657cc577a4SJonathan Peyton 1466e0665a90STerry Wilmarth __kmp_lock_suspend_mx(th); 14677cc577a4SJonathan Peyton 14687cc577a4SJonathan Peyton KF_TRACE(10, ("__kmp_suspend_template: T#%d setting sleep bit for spin(%p)\n", 14697cc577a4SJonathan Peyton th_gtid, flag->get())); 14707cc577a4SJonathan Peyton 14713041982dSJonathan Peyton /* TODO: shouldn't this use release semantics to ensure that 14723041982dSJonathan Peyton __kmp_suspend_initialize_thread gets called first? */ 14737cc577a4SJonathan Peyton old_spin = flag->set_sleeping(); 14749b8bb323SJonathan Peyton if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME && 14759b8bb323SJonathan Peyton __kmp_pause_status != kmp_soft_paused) { 14769b8bb323SJonathan Peyton flag->unset_sleeping(); 1477e0665a90STerry Wilmarth __kmp_unlock_suspend_mx(th); 14789b8bb323SJonathan Peyton return; 14799b8bb323SJonathan Peyton } 14803041982dSJonathan Peyton KF_TRACE(5, ("__kmp_suspend_template: T#%d set sleep bit for spin(%p)==%x," 14813041982dSJonathan Peyton " was %x\n", 148237e2ef54SJonathan Peyton th_gtid, flag->get(), flag->load(), old_spin)); 14837cc577a4SJonathan Peyton 14847cc577a4SJonathan Peyton if (flag->done_check_val(old_spin)) { 14857cc577a4SJonathan Peyton old_spin = flag->unset_sleeping(); 14863041982dSJonathan Peyton KF_TRACE(5, ("__kmp_suspend_template: T#%d false alarm, reset sleep bit " 14873041982dSJonathan Peyton "for spin(%p)\n", 14887cc577a4SJonathan Peyton th_gtid, flag->get())); 14897cc577a4SJonathan Peyton } else { 14907cc577a4SJonathan Peyton /* Encapsulate in a loop as the documentation states that this may 14913041982dSJonathan Peyton "with low probability" return when the condition variable has 14923041982dSJonathan Peyton not been signaled or broadcast */ 14937cc577a4SJonathan Peyton int deactivated = FALSE; 14947cc577a4SJonathan Peyton TCW_PTR(th->th.th_sleep_loc, (void *)flag); 14953041982dSJonathan Peyton 14967cc577a4SJonathan Peyton while (flag->is_sleeping()) { 14977cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND 14987cc577a4SJonathan Peyton char buffer[128]; 14997cc577a4SJonathan Peyton __kmp_suspend_count++; 15007cc577a4SJonathan Peyton __kmp_print_cond(buffer, &th->th.th_suspend_cv); 15013041982dSJonathan Peyton __kmp_printf("__kmp_suspend_template: suspending T#%d: %s\n", th_gtid, 15023041982dSJonathan Peyton buffer); 15037cc577a4SJonathan Peyton #endif 15043041982dSJonathan Peyton // Mark the thread as no longer active (only in the first iteration of the 15053041982dSJonathan Peyton // loop). 15067cc577a4SJonathan Peyton if (!deactivated) { 15077cc577a4SJonathan Peyton th->th.th_active = FALSE; 15087cc577a4SJonathan Peyton if (th->th.th_active_in_pool) { 15097cc577a4SJonathan Peyton th->th.th_active_in_pool = FALSE; 151037e2ef54SJonathan Peyton KMP_ATOMIC_DEC(&__kmp_thread_pool_active_nth); 15117cc577a4SJonathan Peyton KMP_DEBUG_ASSERT(TCR_4(__kmp_thread_pool_active_nth) >= 0); 15127cc577a4SJonathan Peyton } 15137cc577a4SJonathan Peyton deactivated = TRUE; 15147cc577a4SJonathan Peyton } 15157cc577a4SJonathan Peyton 15167cc577a4SJonathan Peyton #if USE_SUSPEND_TIMEOUT 15177cc577a4SJonathan Peyton struct timespec now; 15187cc577a4SJonathan Peyton struct timeval tval; 15197cc577a4SJonathan Peyton int msecs; 15207cc577a4SJonathan Peyton 15217cc577a4SJonathan Peyton status = gettimeofday(&tval, NULL); 15227cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status); 15237cc577a4SJonathan Peyton TIMEVAL_TO_TIMESPEC(&tval, &now); 15247cc577a4SJonathan Peyton 15257cc577a4SJonathan Peyton msecs = (4 * __kmp_dflt_blocktime) + 200; 15267cc577a4SJonathan Peyton now.tv_sec += msecs / 1000; 15277cc577a4SJonathan Peyton now.tv_nsec += (msecs % 1000) * 1000; 15287cc577a4SJonathan Peyton 15293041982dSJonathan Peyton KF_TRACE(15, ("__kmp_suspend_template: T#%d about to perform " 15303041982dSJonathan Peyton "pthread_cond_timedwait\n", 15317cc577a4SJonathan Peyton th_gtid)); 15323041982dSJonathan Peyton status = pthread_cond_timedwait(&th->th.th_suspend_cv.c_cond, 15333041982dSJonathan Peyton &th->th.th_suspend_mx.m_mutex, &now); 15347cc577a4SJonathan Peyton #else 15353041982dSJonathan Peyton KF_TRACE(15, ("__kmp_suspend_template: T#%d about to perform" 15363041982dSJonathan Peyton " pthread_cond_wait\n", 15377cc577a4SJonathan Peyton th_gtid)); 15383041982dSJonathan Peyton status = pthread_cond_wait(&th->th.th_suspend_cv.c_cond, 15393041982dSJonathan Peyton &th->th.th_suspend_mx.m_mutex); 1540e0665a90STerry Wilmarth #endif // USE_SUSPEND_TIMEOUT 15417cc577a4SJonathan Peyton 15427cc577a4SJonathan Peyton if ((status != 0) && (status != EINTR) && (status != ETIMEDOUT)) { 15437cc577a4SJonathan Peyton KMP_SYSFAIL("pthread_cond_wait", status); 15447cc577a4SJonathan Peyton } 15457cc577a4SJonathan Peyton #ifdef KMP_DEBUG 15467cc577a4SJonathan Peyton if (status == ETIMEDOUT) { 15477cc577a4SJonathan Peyton if (flag->is_sleeping()) { 15483041982dSJonathan Peyton KF_TRACE(100, 15493041982dSJonathan Peyton ("__kmp_suspend_template: T#%d timeout wakeup\n", th_gtid)); 15507cc577a4SJonathan Peyton } else { 15513041982dSJonathan Peyton KF_TRACE(2, ("__kmp_suspend_template: T#%d timeout wakeup, sleep bit " 15523041982dSJonathan Peyton "not set!\n", 15537cc577a4SJonathan Peyton th_gtid)); 15547cc577a4SJonathan Peyton } 15557cc577a4SJonathan Peyton } else if (flag->is_sleeping()) { 15563041982dSJonathan Peyton KF_TRACE(100, 15573041982dSJonathan Peyton ("__kmp_suspend_template: T#%d spurious wakeup\n", th_gtid)); 15587cc577a4SJonathan Peyton } 15597cc577a4SJonathan Peyton #endif 15607cc577a4SJonathan Peyton } // while 15617cc577a4SJonathan Peyton 15627cc577a4SJonathan Peyton // Mark the thread as active again (if it was previous marked as inactive) 15637cc577a4SJonathan Peyton if (deactivated) { 15647cc577a4SJonathan Peyton th->th.th_active = TRUE; 15657cc577a4SJonathan Peyton if (TCR_4(th->th.th_in_pool)) { 156637e2ef54SJonathan Peyton KMP_ATOMIC_INC(&__kmp_thread_pool_active_nth); 15677cc577a4SJonathan Peyton th->th.th_active_in_pool = TRUE; 15687cc577a4SJonathan Peyton } 15697cc577a4SJonathan Peyton } 15707cc577a4SJonathan Peyton } 15717cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND 15727cc577a4SJonathan Peyton { 15737cc577a4SJonathan Peyton char buffer[128]; 15747cc577a4SJonathan Peyton __kmp_print_cond(buffer, &th->th.th_suspend_cv); 15753041982dSJonathan Peyton __kmp_printf("__kmp_suspend_template: T#%d has awakened: %s\n", th_gtid, 15763041982dSJonathan Peyton buffer); 15777cc577a4SJonathan Peyton } 15787cc577a4SJonathan Peyton #endif 15797cc577a4SJonathan Peyton 1580e0665a90STerry Wilmarth __kmp_unlock_suspend_mx(th); 15817cc577a4SJonathan Peyton KF_TRACE(30, ("__kmp_suspend_template: T#%d exit\n", th_gtid)); 15827cc577a4SJonathan Peyton } 15837cc577a4SJonathan Peyton 1584e0665a90STerry Wilmarth template <bool C, bool S> 1585e0665a90STerry Wilmarth void __kmp_suspend_32(int th_gtid, kmp_flag_32<C, S> *flag) { 15867cc577a4SJonathan Peyton __kmp_suspend_template(th_gtid, flag); 15877cc577a4SJonathan Peyton } 1588e0665a90STerry Wilmarth template <bool C, bool S> 1589e0665a90STerry Wilmarth void __kmp_suspend_64(int th_gtid, kmp_flag_64<C, S> *flag) { 15907cc577a4SJonathan Peyton __kmp_suspend_template(th_gtid, flag); 15917cc577a4SJonathan Peyton } 15927cc577a4SJonathan Peyton void __kmp_suspend_oncore(int th_gtid, kmp_flag_oncore *flag) { 15937cc577a4SJonathan Peyton __kmp_suspend_template(th_gtid, flag); 15947cc577a4SJonathan Peyton } 15957cc577a4SJonathan Peyton 1596e0665a90STerry Wilmarth template void __kmp_suspend_32<false, false>(int, kmp_flag_32<false, false> *); 1597e0665a90STerry Wilmarth template void __kmp_suspend_64<false, true>(int, kmp_flag_64<false, true> *); 1598e0665a90STerry Wilmarth template void __kmp_suspend_64<true, false>(int, kmp_flag_64<true, false> *); 1599e0665a90STerry Wilmarth 16007cc577a4SJonathan Peyton /* This routine signals the thread specified by target_gtid to wake up 16013041982dSJonathan Peyton after setting the sleep bit indicated by the flag argument to FALSE. 16023041982dSJonathan Peyton The target thread must already have called __kmp_suspend_template() */ 16037cc577a4SJonathan Peyton template <class C> 16043041982dSJonathan Peyton static inline void __kmp_resume_template(int target_gtid, C *flag) { 16057cc577a4SJonathan Peyton KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_resume); 16067cc577a4SJonathan Peyton kmp_info_t *th = __kmp_threads[target_gtid]; 16077cc577a4SJonathan Peyton int status; 16087cc577a4SJonathan Peyton 16097cc577a4SJonathan Peyton #ifdef KMP_DEBUG 16107cc577a4SJonathan Peyton int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1; 16117cc577a4SJonathan Peyton #endif 16127cc577a4SJonathan Peyton 16133041982dSJonathan Peyton KF_TRACE(30, ("__kmp_resume_template: T#%d wants to wakeup T#%d enter\n", 16143041982dSJonathan Peyton gtid, target_gtid)); 16157cc577a4SJonathan Peyton KMP_DEBUG_ASSERT(gtid != target_gtid); 16167cc577a4SJonathan Peyton 16177cc577a4SJonathan Peyton __kmp_suspend_initialize_thread(th); 16185644f734SAndreyChurbanov 1619e0665a90STerry Wilmarth __kmp_lock_suspend_mx(th); 16207cc577a4SJonathan Peyton 16217cc577a4SJonathan Peyton if (!flag) { // coming from __kmp_null_resume_wrapper 1622c47afcd9SAndrey Churbanov flag = (C *)CCAST(void *, th->th.th_sleep_loc); 16237cc577a4SJonathan Peyton } 16247cc577a4SJonathan Peyton 16253041982dSJonathan Peyton // First, check if the flag is null or its type has changed. If so, someone 16263041982dSJonathan Peyton // else woke it up. 16273041982dSJonathan Peyton if (!flag || flag->get_type() != flag->get_ptr_type()) { // get_ptr_type 1628e0665a90STerry Wilmarth // simply shows what flag was cast to 16293041982dSJonathan Peyton KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already " 16303041982dSJonathan Peyton "awake: flag(%p)\n", 16317cc577a4SJonathan Peyton gtid, target_gtid, NULL)); 1632e0665a90STerry Wilmarth __kmp_unlock_suspend_mx(th); 16337cc577a4SJonathan Peyton return; 16343041982dSJonathan Peyton } else { // if multiple threads are sleeping, flag should be internally 16353041982dSJonathan Peyton // referring to a specific thread here 16367cc577a4SJonathan Peyton typename C::flag_t old_spin = flag->unset_sleeping(); 16377cc577a4SJonathan Peyton if (!flag->is_sleeping_val(old_spin)) { 16383041982dSJonathan Peyton KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already " 16393041982dSJonathan Peyton "awake: flag(%p): " 16407cc577a4SJonathan Peyton "%u => %u\n", 164137e2ef54SJonathan Peyton gtid, target_gtid, flag->get(), old_spin, flag->load())); 1642e0665a90STerry Wilmarth __kmp_unlock_suspend_mx(th); 16437cc577a4SJonathan Peyton return; 16447cc577a4SJonathan Peyton } 16453041982dSJonathan Peyton KF_TRACE(5, ("__kmp_resume_template: T#%d about to wakeup T#%d, reset " 16463041982dSJonathan Peyton "sleep bit for flag's loc(%p): " 16477cc577a4SJonathan Peyton "%u => %u\n", 164837e2ef54SJonathan Peyton gtid, target_gtid, flag->get(), old_spin, flag->load())); 16497cc577a4SJonathan Peyton } 16507cc577a4SJonathan Peyton TCW_PTR(th->th.th_sleep_loc, NULL); 16517cc577a4SJonathan Peyton 16527cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND 16537cc577a4SJonathan Peyton { 16547cc577a4SJonathan Peyton char buffer[128]; 16557cc577a4SJonathan Peyton __kmp_print_cond(buffer, &th->th.th_suspend_cv); 16563041982dSJonathan Peyton __kmp_printf("__kmp_resume_template: T#%d resuming T#%d: %s\n", gtid, 16573041982dSJonathan Peyton target_gtid, buffer); 16587cc577a4SJonathan Peyton } 16597cc577a4SJonathan Peyton #endif 16607cc577a4SJonathan Peyton status = pthread_cond_signal(&th->th.th_suspend_cv.c_cond); 16617cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_cond_signal", status); 1662e0665a90STerry Wilmarth __kmp_unlock_suspend_mx(th); 16633041982dSJonathan Peyton KF_TRACE(30, ("__kmp_resume_template: T#%d exiting after signaling wake up" 16643041982dSJonathan Peyton " for T#%d\n", 16657cc577a4SJonathan Peyton gtid, target_gtid)); 16667cc577a4SJonathan Peyton } 16677cc577a4SJonathan Peyton 1668e0665a90STerry Wilmarth template <bool C, bool S> 1669e0665a90STerry Wilmarth void __kmp_resume_32(int target_gtid, kmp_flag_32<C, S> *flag) { 16707cc577a4SJonathan Peyton __kmp_resume_template(target_gtid, flag); 16717cc577a4SJonathan Peyton } 1672e0665a90STerry Wilmarth template <bool C, bool S> 1673e0665a90STerry Wilmarth void __kmp_resume_64(int target_gtid, kmp_flag_64<C, S> *flag) { 16747cc577a4SJonathan Peyton __kmp_resume_template(target_gtid, flag); 16757cc577a4SJonathan Peyton } 16767cc577a4SJonathan Peyton void __kmp_resume_oncore(int target_gtid, kmp_flag_oncore *flag) { 16777cc577a4SJonathan Peyton __kmp_resume_template(target_gtid, flag); 16787cc577a4SJonathan Peyton } 16797cc577a4SJonathan Peyton 1680e0665a90STerry Wilmarth template void __kmp_resume_32<false, true>(int, kmp_flag_32<false, true> *); 1681e0665a90STerry Wilmarth template void __kmp_resume_64<false, true>(int, kmp_flag_64<false, true> *); 1682e0665a90STerry Wilmarth 16837cc577a4SJonathan Peyton #if KMP_USE_MONITOR 16843041982dSJonathan Peyton void __kmp_resume_monitor() { 16857cc577a4SJonathan Peyton KMP_TIME_DEVELOPER_PARTITIONED_BLOCK(USER_resume); 16867cc577a4SJonathan Peyton int status; 16877cc577a4SJonathan Peyton #ifdef KMP_DEBUG 16887cc577a4SJonathan Peyton int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1; 16893041982dSJonathan Peyton KF_TRACE(30, ("__kmp_resume_monitor: T#%d wants to wakeup T#%d enter\n", gtid, 16903041982dSJonathan Peyton KMP_GTID_MONITOR)); 16917cc577a4SJonathan Peyton KMP_DEBUG_ASSERT(gtid != KMP_GTID_MONITOR); 16927cc577a4SJonathan Peyton #endif 16937cc577a4SJonathan Peyton status = pthread_mutex_lock(&__kmp_wait_mx.m_mutex); 16947cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_mutex_lock", status); 16957cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND 16967cc577a4SJonathan Peyton { 16977cc577a4SJonathan Peyton char buffer[128]; 16987cc577a4SJonathan Peyton __kmp_print_cond(buffer, &__kmp_wait_cv.c_cond); 16993041982dSJonathan Peyton __kmp_printf("__kmp_resume_monitor: T#%d resuming T#%d: %s\n", gtid, 17003041982dSJonathan Peyton KMP_GTID_MONITOR, buffer); 17017cc577a4SJonathan Peyton } 17027cc577a4SJonathan Peyton #endif 17037cc577a4SJonathan Peyton status = pthread_cond_signal(&__kmp_wait_cv.c_cond); 17047cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_cond_signal", status); 17057cc577a4SJonathan Peyton status = pthread_mutex_unlock(&__kmp_wait_mx.m_mutex); 17067cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status); 17073041982dSJonathan Peyton KF_TRACE(30, ("__kmp_resume_monitor: T#%d exiting after signaling wake up" 17083041982dSJonathan Peyton " for T#%d\n", 17097cc577a4SJonathan Peyton gtid, KMP_GTID_MONITOR)); 17107cc577a4SJonathan Peyton } 17117cc577a4SJonathan Peyton #endif // KMP_USE_MONITOR 17127cc577a4SJonathan Peyton 1713e47d32f1SJonathan Peyton void __kmp_yield() { sched_yield(); } 17147cc577a4SJonathan Peyton 17153041982dSJonathan Peyton void __kmp_gtid_set_specific(int gtid) { 17167cc577a4SJonathan Peyton if (__kmp_init_gtid) { 17177cc577a4SJonathan Peyton int status; 17183041982dSJonathan Peyton status = pthread_setspecific(__kmp_gtid_threadprivate_key, 17193041982dSJonathan Peyton (void *)(intptr_t)(gtid + 1)); 17207cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_setspecific", status); 17217cc577a4SJonathan Peyton } else { 17227cc577a4SJonathan Peyton KA_TRACE(50, ("__kmp_gtid_set_specific: runtime shutdown, returning\n")); 17237cc577a4SJonathan Peyton } 17247cc577a4SJonathan Peyton } 17257cc577a4SJonathan Peyton 17263041982dSJonathan Peyton int __kmp_gtid_get_specific() { 17277cc577a4SJonathan Peyton int gtid; 17287cc577a4SJonathan Peyton if (!__kmp_init_gtid) { 17293041982dSJonathan Peyton KA_TRACE(50, ("__kmp_gtid_get_specific: runtime shutdown, returning " 17303041982dSJonathan Peyton "KMP_GTID_SHUTDOWN\n")); 17317cc577a4SJonathan Peyton return KMP_GTID_SHUTDOWN; 17327cc577a4SJonathan Peyton } 17337cc577a4SJonathan Peyton gtid = (int)(size_t)pthread_getspecific(__kmp_gtid_threadprivate_key); 17347cc577a4SJonathan Peyton if (gtid == 0) { 17357cc577a4SJonathan Peyton gtid = KMP_GTID_DNE; 17363041982dSJonathan Peyton } else { 17377cc577a4SJonathan Peyton gtid--; 17387cc577a4SJonathan Peyton } 17397cc577a4SJonathan Peyton KA_TRACE(50, ("__kmp_gtid_get_specific: key:%d gtid:%d\n", 17407cc577a4SJonathan Peyton __kmp_gtid_threadprivate_key, gtid)); 17417cc577a4SJonathan Peyton return gtid; 17427cc577a4SJonathan Peyton } 17437cc577a4SJonathan Peyton 17443041982dSJonathan Peyton double __kmp_read_cpu_time(void) { 17457cc577a4SJonathan Peyton /*clock_t t;*/ 17467cc577a4SJonathan Peyton struct tms buffer; 17477cc577a4SJonathan Peyton 17487cc577a4SJonathan Peyton /*t =*/times(&buffer); 17497cc577a4SJonathan Peyton 17506b316febSTerry Wilmarth return (double)(buffer.tms_utime + buffer.tms_cutime) / 17516b316febSTerry Wilmarth (double)CLOCKS_PER_SEC; 17527cc577a4SJonathan Peyton } 17537cc577a4SJonathan Peyton 17543041982dSJonathan Peyton int __kmp_read_system_info(struct kmp_sys_info *info) { 17557cc577a4SJonathan Peyton int status; 17567cc577a4SJonathan Peyton struct rusage r_usage; 17577cc577a4SJonathan Peyton 17587cc577a4SJonathan Peyton memset(info, 0, sizeof(*info)); 17597cc577a4SJonathan Peyton 17607cc577a4SJonathan Peyton status = getrusage(RUSAGE_SELF, &r_usage); 17617cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL_ERRNO("getrusage", status); 17627cc577a4SJonathan Peyton 17633041982dSJonathan Peyton // The maximum resident set size utilized (in kilobytes) 17643041982dSJonathan Peyton info->maxrss = r_usage.ru_maxrss; 17653041982dSJonathan Peyton // The number of page faults serviced without any I/O 17663041982dSJonathan Peyton info->minflt = r_usage.ru_minflt; 17673041982dSJonathan Peyton // The number of page faults serviced that required I/O 17683041982dSJonathan Peyton info->majflt = r_usage.ru_majflt; 17693041982dSJonathan Peyton // The number of times a process was "swapped" out of memory 17703041982dSJonathan Peyton info->nswap = r_usage.ru_nswap; 17713041982dSJonathan Peyton // The number of times the file system had to perform input 17723041982dSJonathan Peyton info->inblock = r_usage.ru_inblock; 17733041982dSJonathan Peyton // The number of times the file system had to perform output 17743041982dSJonathan Peyton info->oublock = r_usage.ru_oublock; 17753041982dSJonathan Peyton // The number of times a context switch was voluntarily 17763041982dSJonathan Peyton info->nvcsw = r_usage.ru_nvcsw; 17773041982dSJonathan Peyton // The number of times a context switch was forced 17783041982dSJonathan Peyton info->nivcsw = r_usage.ru_nivcsw; 17797cc577a4SJonathan Peyton 17807cc577a4SJonathan Peyton return (status != 0); 17817cc577a4SJonathan Peyton } 17827cc577a4SJonathan Peyton 17833041982dSJonathan Peyton void __kmp_read_system_time(double *delta) { 17847cc577a4SJonathan Peyton double t_ns; 17857cc577a4SJonathan Peyton struct timeval tval; 17867cc577a4SJonathan Peyton struct timespec stop; 17877cc577a4SJonathan Peyton int status; 17887cc577a4SJonathan Peyton 17897cc577a4SJonathan Peyton status = gettimeofday(&tval, NULL); 17907cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status); 17917cc577a4SJonathan Peyton TIMEVAL_TO_TIMESPEC(&tval, &stop); 17926b316febSTerry Wilmarth t_ns = (double)(TS2NS(stop) - TS2NS(__kmp_sys_timer_data.start)); 17937cc577a4SJonathan Peyton *delta = (t_ns * 1e-9); 17947cc577a4SJonathan Peyton } 17957cc577a4SJonathan Peyton 17963041982dSJonathan Peyton void __kmp_clear_system_time(void) { 17977cc577a4SJonathan Peyton struct timeval tval; 17987cc577a4SJonathan Peyton int status; 17997cc577a4SJonathan Peyton status = gettimeofday(&tval, NULL); 18007cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status); 18017cc577a4SJonathan Peyton TIMEVAL_TO_TIMESPEC(&tval, &__kmp_sys_timer_data.start); 18027cc577a4SJonathan Peyton } 18037cc577a4SJonathan Peyton 18043041982dSJonathan Peyton static int __kmp_get_xproc(void) { 18057cc577a4SJonathan Peyton 18067cc577a4SJonathan Peyton int r = 0; 18077cc577a4SJonathan Peyton 1808a56ac949SKamil Rytarowski #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \ 18097e1ea993SKamil Rytarowski KMP_OS_OPENBSD || KMP_OS_HURD 18107cc577a4SJonathan Peyton 18116b316febSTerry Wilmarth __kmp_type_convert(sysconf(_SC_NPROCESSORS_ONLN), &(r)); 18127cc577a4SJonathan Peyton 18137cc577a4SJonathan Peyton #elif KMP_OS_DARWIN 18147cc577a4SJonathan Peyton 18157cc577a4SJonathan Peyton // Bug C77011 High "OpenMP Threads and number of active cores". 18167cc577a4SJonathan Peyton 18177cc577a4SJonathan Peyton // Find the number of available CPUs. 18187cc577a4SJonathan Peyton kern_return_t rc; 18197cc577a4SJonathan Peyton host_basic_info_data_t info; 18207cc577a4SJonathan Peyton mach_msg_type_number_t num = HOST_BASIC_INFO_COUNT; 18217cc577a4SJonathan Peyton rc = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&info, &num); 18227cc577a4SJonathan Peyton if (rc == 0 && num == HOST_BASIC_INFO_COUNT) { 1823c47afcd9SAndrey Churbanov // Cannot use KA_TRACE() here because this code works before trace support 1824c47afcd9SAndrey Churbanov // is initialized. 18257cc577a4SJonathan Peyton r = info.avail_cpus; 18267cc577a4SJonathan Peyton } else { 18277cc577a4SJonathan Peyton KMP_WARNING(CantGetNumAvailCPU); 18287cc577a4SJonathan Peyton KMP_INFORM(AssumedNumCPU); 1829bd3a7633SJonathan Peyton } 18307cc577a4SJonathan Peyton 18317cc577a4SJonathan Peyton #else 18327cc577a4SJonathan Peyton 18337cc577a4SJonathan Peyton #error "Unknown or unsupported OS." 18347cc577a4SJonathan Peyton 18357cc577a4SJonathan Peyton #endif 18367cc577a4SJonathan Peyton 18377cc577a4SJonathan Peyton return r > 0 ? r : 2; /* guess value of 2 if OS told us 0 */ 18387cc577a4SJonathan Peyton 18397cc577a4SJonathan Peyton } // __kmp_get_xproc 18407cc577a4SJonathan Peyton 18413041982dSJonathan Peyton int __kmp_read_from_file(char const *path, char const *format, ...) { 18427cc577a4SJonathan Peyton int result; 18437cc577a4SJonathan Peyton va_list args; 18447cc577a4SJonathan Peyton 18457cc577a4SJonathan Peyton va_start(args, format); 18467cc577a4SJonathan Peyton FILE *f = fopen(path, "rb"); 18477cc577a4SJonathan Peyton if (f == NULL) 18487cc577a4SJonathan Peyton return 0; 18497cc577a4SJonathan Peyton result = vfscanf(f, format, args); 18507cc577a4SJonathan Peyton fclose(f); 18517cc577a4SJonathan Peyton 18527cc577a4SJonathan Peyton return result; 18537cc577a4SJonathan Peyton } 18547cc577a4SJonathan Peyton 18553041982dSJonathan Peyton void __kmp_runtime_initialize(void) { 18567cc577a4SJonathan Peyton int status; 18577cc577a4SJonathan Peyton pthread_mutexattr_t mutex_attr; 18587cc577a4SJonathan Peyton pthread_condattr_t cond_attr; 18597cc577a4SJonathan Peyton 18607cc577a4SJonathan Peyton if (__kmp_init_runtime) { 18617cc577a4SJonathan Peyton return; 1862bd3a7633SJonathan Peyton } 18637cc577a4SJonathan Peyton 18647cc577a4SJonathan Peyton #if (KMP_ARCH_X86 || KMP_ARCH_X86_64) 18657cc577a4SJonathan Peyton if (!__kmp_cpuinfo.initialized) { 18667cc577a4SJonathan Peyton __kmp_query_cpuid(&__kmp_cpuinfo); 1867bd3a7633SJonathan Peyton } 18687cc577a4SJonathan Peyton #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ 18697cc577a4SJonathan Peyton 18707cc577a4SJonathan Peyton __kmp_xproc = __kmp_get_xproc(); 18717cc577a4SJonathan Peyton 1872d47f5488SAndrey Churbanov #if !KMP_32_BIT_ARCH 1873d47f5488SAndrey Churbanov struct rlimit rlim; 1874d47f5488SAndrey Churbanov // read stack size of calling thread, save it as default for worker threads; 1875d47f5488SAndrey Churbanov // this should be done before reading environment variables 1876d47f5488SAndrey Churbanov status = getrlimit(RLIMIT_STACK, &rlim); 1877d47f5488SAndrey Churbanov if (status == 0) { // success? 1878d47f5488SAndrey Churbanov __kmp_stksize = rlim.rlim_cur; 1879d47f5488SAndrey Churbanov __kmp_check_stksize(&__kmp_stksize); // check value and adjust if needed 1880d47f5488SAndrey Churbanov } 1881d47f5488SAndrey Churbanov #endif /* KMP_32_BIT_ARCH */ 1882d47f5488SAndrey Churbanov 18837cc577a4SJonathan Peyton if (sysconf(_SC_THREADS)) { 18847cc577a4SJonathan Peyton 18857cc577a4SJonathan Peyton /* Query the maximum number of threads */ 18866b316febSTerry Wilmarth __kmp_type_convert(sysconf(_SC_THREAD_THREADS_MAX), &(__kmp_sys_max_nth)); 18877cc577a4SJonathan Peyton if (__kmp_sys_max_nth == -1) { 18887cc577a4SJonathan Peyton /* Unlimited threads for NPTL */ 18897cc577a4SJonathan Peyton __kmp_sys_max_nth = INT_MAX; 18903041982dSJonathan Peyton } else if (__kmp_sys_max_nth <= 1) { 18917cc577a4SJonathan Peyton /* Can't tell, just use PTHREAD_THREADS_MAX */ 18927cc577a4SJonathan Peyton __kmp_sys_max_nth = KMP_MAX_NTH; 18937cc577a4SJonathan Peyton } 18947cc577a4SJonathan Peyton 18957cc577a4SJonathan Peyton /* Query the minimum stack size */ 18967cc577a4SJonathan Peyton __kmp_sys_min_stksize = sysconf(_SC_THREAD_STACK_MIN); 18977cc577a4SJonathan Peyton if (__kmp_sys_min_stksize <= 1) { 18987cc577a4SJonathan Peyton __kmp_sys_min_stksize = KMP_MIN_STKSIZE; 18997cc577a4SJonathan Peyton } 19007cc577a4SJonathan Peyton } 19017cc577a4SJonathan Peyton 19027cc577a4SJonathan Peyton /* Set up minimum number of threads to switch to TLS gtid */ 19037cc577a4SJonathan Peyton __kmp_tls_gtid_min = KMP_TLS_GTID_MIN; 19047cc577a4SJonathan Peyton 19053041982dSJonathan Peyton status = pthread_key_create(&__kmp_gtid_threadprivate_key, 19063041982dSJonathan Peyton __kmp_internal_end_dest); 19077cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_key_create", status); 19087cc577a4SJonathan Peyton status = pthread_mutexattr_init(&mutex_attr); 19097cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_mutexattr_init", status); 19107cc577a4SJonathan Peyton status = pthread_mutex_init(&__kmp_wait_mx.m_mutex, &mutex_attr); 19117cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_mutex_init", status); 19127cc577a4SJonathan Peyton status = pthread_condattr_init(&cond_attr); 19137cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_condattr_init", status); 19147cc577a4SJonathan Peyton status = pthread_cond_init(&__kmp_wait_cv.c_cond, &cond_attr); 19157cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_cond_init", status); 19167cc577a4SJonathan Peyton #if USE_ITT_BUILD 19177cc577a4SJonathan Peyton __kmp_itt_initialize(); 19187cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */ 19197cc577a4SJonathan Peyton 19207cc577a4SJonathan Peyton __kmp_init_runtime = TRUE; 19217cc577a4SJonathan Peyton } 19227cc577a4SJonathan Peyton 19233041982dSJonathan Peyton void __kmp_runtime_destroy(void) { 19247cc577a4SJonathan Peyton int status; 19257cc577a4SJonathan Peyton 19267cc577a4SJonathan Peyton if (!__kmp_init_runtime) { 19277cc577a4SJonathan Peyton return; // Nothing to do. 1928bd3a7633SJonathan Peyton } 19297cc577a4SJonathan Peyton 19307cc577a4SJonathan Peyton #if USE_ITT_BUILD 19317cc577a4SJonathan Peyton __kmp_itt_destroy(); 19327cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */ 19337cc577a4SJonathan Peyton 19347cc577a4SJonathan Peyton status = pthread_key_delete(__kmp_gtid_threadprivate_key); 19357cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL("pthread_key_delete", status); 19367cc577a4SJonathan Peyton 19377cc577a4SJonathan Peyton status = pthread_mutex_destroy(&__kmp_wait_mx.m_mutex); 19387cc577a4SJonathan Peyton if (status != 0 && status != EBUSY) { 19397cc577a4SJonathan Peyton KMP_SYSFAIL("pthread_mutex_destroy", status); 19407cc577a4SJonathan Peyton } 19417cc577a4SJonathan Peyton status = pthread_cond_destroy(&__kmp_wait_cv.c_cond); 19427cc577a4SJonathan Peyton if (status != 0 && status != EBUSY) { 19437cc577a4SJonathan Peyton KMP_SYSFAIL("pthread_cond_destroy", status); 19447cc577a4SJonathan Peyton } 19457cc577a4SJonathan Peyton #if KMP_AFFINITY_SUPPORTED 19467cc577a4SJonathan Peyton __kmp_affinity_uninitialize(); 19477cc577a4SJonathan Peyton #endif 19487cc577a4SJonathan Peyton 19497cc577a4SJonathan Peyton __kmp_init_runtime = FALSE; 19507cc577a4SJonathan Peyton } 19517cc577a4SJonathan Peyton 19527cc577a4SJonathan Peyton /* Put the thread to sleep for a time period */ 19537cc577a4SJonathan Peyton /* NOTE: not currently used anywhere */ 19543041982dSJonathan Peyton void __kmp_thread_sleep(int millis) { sleep((millis + 500) / 1000); } 19557cc577a4SJonathan Peyton 19567cc577a4SJonathan Peyton /* Calculate the elapsed wall clock time for the user */ 19573041982dSJonathan Peyton void __kmp_elapsed(double *t) { 19587cc577a4SJonathan Peyton int status; 19597cc577a4SJonathan Peyton #ifdef FIX_SGI_CLOCK 19607cc577a4SJonathan Peyton struct timespec ts; 19617cc577a4SJonathan Peyton 19627cc577a4SJonathan Peyton status = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); 19637cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL_ERRNO("clock_gettime", status); 19643041982dSJonathan Peyton *t = 19653041982dSJonathan Peyton (double)ts.tv_nsec * (1.0 / (double)KMP_NSEC_PER_SEC) + (double)ts.tv_sec; 19667cc577a4SJonathan Peyton #else 19677cc577a4SJonathan Peyton struct timeval tv; 19687cc577a4SJonathan Peyton 19697cc577a4SJonathan Peyton status = gettimeofday(&tv, NULL); 19707cc577a4SJonathan Peyton KMP_CHECK_SYSFAIL_ERRNO("gettimeofday", status); 19713041982dSJonathan Peyton *t = 19723041982dSJonathan Peyton (double)tv.tv_usec * (1.0 / (double)KMP_USEC_PER_SEC) + (double)tv.tv_sec; 19737cc577a4SJonathan Peyton #endif 19747cc577a4SJonathan Peyton } 19757cc577a4SJonathan Peyton 19767cc577a4SJonathan Peyton /* Calculate the elapsed wall clock tick for the user */ 19773041982dSJonathan Peyton void __kmp_elapsed_tick(double *t) { *t = 1 / (double)CLOCKS_PER_SEC; } 19787cc577a4SJonathan Peyton 19797cc577a4SJonathan Peyton /* Return the current time stamp in nsec */ 19803041982dSJonathan Peyton kmp_uint64 __kmp_now_nsec() { 19817cc577a4SJonathan Peyton struct timeval t; 19827cc577a4SJonathan Peyton gettimeofday(&t, NULL); 1983bdb0a2ffSJonathan Peyton kmp_uint64 nsec = (kmp_uint64)KMP_NSEC_PER_SEC * (kmp_uint64)t.tv_sec + 1984bdb0a2ffSJonathan Peyton (kmp_uint64)1000 * (kmp_uint64)t.tv_usec; 1985bdb0a2ffSJonathan Peyton return nsec; 19867cc577a4SJonathan Peyton } 19877cc577a4SJonathan Peyton 19887cc577a4SJonathan Peyton #if KMP_ARCH_X86 || KMP_ARCH_X86_64 198935d75aedSJonathan Peyton /* Measure clock ticks per millisecond */ 19903041982dSJonathan Peyton void __kmp_initialize_system_tick() { 1991bdb0a2ffSJonathan Peyton kmp_uint64 now, nsec2, diff; 19927cc577a4SJonathan Peyton kmp_uint64 delay = 100000; // 50~100 usec on most machines. 19937cc577a4SJonathan Peyton kmp_uint64 nsec = __kmp_now_nsec(); 19947cc577a4SJonathan Peyton kmp_uint64 goal = __kmp_hardware_timestamp() + delay; 19953041982dSJonathan Peyton while ((now = __kmp_hardware_timestamp()) < goal) 19963041982dSJonathan Peyton ; 1997bdb0a2ffSJonathan Peyton nsec2 = __kmp_now_nsec(); 1998bdb0a2ffSJonathan Peyton diff = nsec2 - nsec; 1999bdb0a2ffSJonathan Peyton if (diff > 0) { 20006b316febSTerry Wilmarth kmp_uint64 tpms = ((kmp_uint64)1e6 * (delay + (now - goal)) / diff); 2001bdb0a2ffSJonathan Peyton if (tpms > 0) 2002bdb0a2ffSJonathan Peyton __kmp_ticks_per_msec = tpms; 2003bdb0a2ffSJonathan Peyton } 20047cc577a4SJonathan Peyton } 20057cc577a4SJonathan Peyton #endif 20067cc577a4SJonathan Peyton 20073041982dSJonathan Peyton /* Determine whether the given address is mapped into the current address 20083041982dSJonathan Peyton space. */ 20097cc577a4SJonathan Peyton 20103041982dSJonathan Peyton int __kmp_is_address_mapped(void *addr) { 20117cc577a4SJonathan Peyton 20127cc577a4SJonathan Peyton int found = 0; 20137cc577a4SJonathan Peyton int rc; 20147cc577a4SJonathan Peyton 2015fef62e1aSDavid Carlier #if KMP_OS_LINUX || KMP_OS_HURD 20167cc577a4SJonathan Peyton 2017*309b00a4SShilei Tian /* On GNUish OSes, read the /proc/<pid>/maps pseudo-file to get all the 2018*309b00a4SShilei Tian address ranges mapped into the address space. */ 20197cc577a4SJonathan Peyton 20207cc577a4SJonathan Peyton char *name = __kmp_str_format("/proc/%d/maps", getpid()); 20217cc577a4SJonathan Peyton FILE *file = NULL; 20227cc577a4SJonathan Peyton 20237cc577a4SJonathan Peyton file = fopen(name, "r"); 20247cc577a4SJonathan Peyton KMP_ASSERT(file != NULL); 20257cc577a4SJonathan Peyton 20267cc577a4SJonathan Peyton for (;;) { 20277cc577a4SJonathan Peyton 20287cc577a4SJonathan Peyton void *beginning = NULL; 20297cc577a4SJonathan Peyton void *ending = NULL; 20307cc577a4SJonathan Peyton char perms[5]; 20317cc577a4SJonathan Peyton 20327cc577a4SJonathan Peyton rc = fscanf(file, "%p-%p %4s %*[^\n]\n", &beginning, &ending, perms); 20337cc577a4SJonathan Peyton if (rc == EOF) { 20347cc577a4SJonathan Peyton break; 2035bd3a7633SJonathan Peyton } 20363041982dSJonathan Peyton KMP_ASSERT(rc == 3 && 20373041982dSJonathan Peyton KMP_STRLEN(perms) == 4); // Make sure all fields are read. 20387cc577a4SJonathan Peyton 20397cc577a4SJonathan Peyton // Ending address is not included in the region, but beginning is. 20407cc577a4SJonathan Peyton if ((addr >= beginning) && (addr < ending)) { 20417cc577a4SJonathan Peyton perms[2] = 0; // 3th and 4th character does not matter. 20427cc577a4SJonathan Peyton if (strcmp(perms, "rw") == 0) { 20437cc577a4SJonathan Peyton // Memory we are looking for should be readable and writable. 20447cc577a4SJonathan Peyton found = 1; 2045bd3a7633SJonathan Peyton } 20467cc577a4SJonathan Peyton break; 2047bd3a7633SJonathan Peyton } 2048bd3a7633SJonathan Peyton } 20497cc577a4SJonathan Peyton 20507cc577a4SJonathan Peyton // Free resources. 20517cc577a4SJonathan Peyton fclose(file); 20527cc577a4SJonathan Peyton KMP_INTERNAL_FREE(name); 2053fef62e1aSDavid Carlier #elif KMP_OS_FREEBSD 2054fef62e1aSDavid Carlier char *buf; 2055fef62e1aSDavid Carlier size_t lstsz; 2056fef62e1aSDavid Carlier int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()}; 2057fef62e1aSDavid Carlier rc = sysctl(mib, 4, NULL, &lstsz, NULL, 0); 2058fef62e1aSDavid Carlier if (rc < 0) 2059fef62e1aSDavid Carlier return 0; 2060fef62e1aSDavid Carlier // We pass from number of vm entry's semantic 2061fef62e1aSDavid Carlier // to size of whole entry map list. 2062fef62e1aSDavid Carlier lstsz = lstsz * 4 / 3; 2063fef62e1aSDavid Carlier buf = reinterpret_cast<char *>(kmpc_malloc(lstsz)); 2064fef62e1aSDavid Carlier rc = sysctl(mib, 4, buf, &lstsz, NULL, 0); 2065fef62e1aSDavid Carlier if (rc < 0) { 2066fef62e1aSDavid Carlier kmpc_free(buf); 2067fef62e1aSDavid Carlier return 0; 2068fef62e1aSDavid Carlier } 2069fef62e1aSDavid Carlier 2070fef62e1aSDavid Carlier char *lw = buf; 2071fef62e1aSDavid Carlier char *up = buf + lstsz; 2072fef62e1aSDavid Carlier 2073fef62e1aSDavid Carlier while (lw < up) { 2074fef62e1aSDavid Carlier struct kinfo_vmentry *cur = reinterpret_cast<struct kinfo_vmentry *>(lw); 2075fef62e1aSDavid Carlier size_t cursz = cur->kve_structsize; 2076fef62e1aSDavid Carlier if (cursz == 0) 2077fef62e1aSDavid Carlier break; 2078fef62e1aSDavid Carlier void *start = reinterpret_cast<void *>(cur->kve_start); 2079fef62e1aSDavid Carlier void *end = reinterpret_cast<void *>(cur->kve_end); 2080fef62e1aSDavid Carlier // Readable/Writable addresses within current map entry 2081fef62e1aSDavid Carlier if ((addr >= start) && (addr < end)) { 2082fef62e1aSDavid Carlier if ((cur->kve_protection & KVME_PROT_READ) != 0 && 2083fef62e1aSDavid Carlier (cur->kve_protection & KVME_PROT_WRITE) != 0) { 2084fef62e1aSDavid Carlier found = 1; 2085fef62e1aSDavid Carlier break; 2086fef62e1aSDavid Carlier } 2087fef62e1aSDavid Carlier } 2088fef62e1aSDavid Carlier lw += cursz; 2089fef62e1aSDavid Carlier } 2090fef62e1aSDavid Carlier kmpc_free(buf); 20917cc577a4SJonathan Peyton 20927cc577a4SJonathan Peyton #elif KMP_OS_DARWIN 20937cc577a4SJonathan Peyton 20943041982dSJonathan Peyton /* On OS X*, /proc pseudo filesystem is not available. Try to read memory 20953041982dSJonathan Peyton using vm interface. */ 20967cc577a4SJonathan Peyton 20977cc577a4SJonathan Peyton int buffer; 20987cc577a4SJonathan Peyton vm_size_t count; 20993041982dSJonathan Peyton rc = vm_read_overwrite( 21007cc577a4SJonathan Peyton mach_task_self(), // Task to read memory of. 21017cc577a4SJonathan Peyton (vm_address_t)(addr), // Address to read from. 21027cc577a4SJonathan Peyton 1, // Number of bytes to be read. 21037cc577a4SJonathan Peyton (vm_address_t)(&buffer), // Address of buffer to save read bytes in. 21047cc577a4SJonathan Peyton &count // Address of var to save number of read bytes in. 21057cc577a4SJonathan Peyton ); 21067cc577a4SJonathan Peyton if (rc == 0) { 21077cc577a4SJonathan Peyton // Memory successfully read. 21087cc577a4SJonathan Peyton found = 1; 2109bd3a7633SJonathan Peyton } 21107cc577a4SJonathan Peyton 2111316f4238SKamil Rytarowski #elif KMP_OS_NETBSD 21127cc577a4SJonathan Peyton 2113316f4238SKamil Rytarowski int mib[5]; 2114316f4238SKamil Rytarowski mib[0] = CTL_VM; 2115316f4238SKamil Rytarowski mib[1] = VM_PROC; 2116316f4238SKamil Rytarowski mib[2] = VM_PROC_MAP; 2117316f4238SKamil Rytarowski mib[3] = getpid(); 2118316f4238SKamil Rytarowski mib[4] = sizeof(struct kinfo_vmentry); 2119316f4238SKamil Rytarowski 2120316f4238SKamil Rytarowski size_t size; 2121316f4238SKamil Rytarowski rc = sysctl(mib, __arraycount(mib), NULL, &size, NULL, 0); 2122316f4238SKamil Rytarowski KMP_ASSERT(!rc); 2123316f4238SKamil Rytarowski KMP_ASSERT(size); 2124316f4238SKamil Rytarowski 2125316f4238SKamil Rytarowski size = size * 4 / 3; 2126316f4238SKamil Rytarowski struct kinfo_vmentry *kiv = (struct kinfo_vmentry *)KMP_INTERNAL_MALLOC(size); 2127316f4238SKamil Rytarowski KMP_ASSERT(kiv); 2128316f4238SKamil Rytarowski 2129316f4238SKamil Rytarowski rc = sysctl(mib, __arraycount(mib), kiv, &size, NULL, 0); 2130316f4238SKamil Rytarowski KMP_ASSERT(!rc); 2131316f4238SKamil Rytarowski KMP_ASSERT(size); 2132316f4238SKamil Rytarowski 2133316f4238SKamil Rytarowski for (size_t i = 0; i < size; i++) { 2134316f4238SKamil Rytarowski if (kiv[i].kve_start >= (uint64_t)addr && 2135316f4238SKamil Rytarowski kiv[i].kve_end <= (uint64_t)addr) { 2136316f4238SKamil Rytarowski found = 1; 2137316f4238SKamil Rytarowski break; 2138316f4238SKamil Rytarowski } 2139316f4238SKamil Rytarowski } 2140316f4238SKamil Rytarowski KMP_INTERNAL_FREE(kiv); 214127f6eedcSAndreyChurbanov #elif KMP_OS_OPENBSD 2142316f4238SKamil Rytarowski 214327f6eedcSAndreyChurbanov int mib[3]; 214427f6eedcSAndreyChurbanov mib[0] = CTL_KERN; 214527f6eedcSAndreyChurbanov mib[1] = KERN_PROC_VMMAP; 214627f6eedcSAndreyChurbanov mib[2] = getpid(); 214727f6eedcSAndreyChurbanov 214827f6eedcSAndreyChurbanov size_t size; 214927f6eedcSAndreyChurbanov uint64_t end; 215027f6eedcSAndreyChurbanov rc = sysctl(mib, 3, NULL, &size, NULL, 0); 215127f6eedcSAndreyChurbanov KMP_ASSERT(!rc); 215227f6eedcSAndreyChurbanov KMP_ASSERT(size); 215327f6eedcSAndreyChurbanov end = size; 215427f6eedcSAndreyChurbanov 215527f6eedcSAndreyChurbanov struct kinfo_vmentry kiv = {.kve_start = 0}; 215627f6eedcSAndreyChurbanov 215727f6eedcSAndreyChurbanov while ((rc = sysctl(mib, 3, &kiv, &size, NULL, 0)) == 0) { 215827f6eedcSAndreyChurbanov KMP_ASSERT(size); 215927f6eedcSAndreyChurbanov if (kiv.kve_end == end) 216027f6eedcSAndreyChurbanov break; 216127f6eedcSAndreyChurbanov 216227f6eedcSAndreyChurbanov if (kiv.kve_start >= (uint64_t)addr && kiv.kve_end <= (uint64_t)addr) { 216327f6eedcSAndreyChurbanov found = 1; 216427f6eedcSAndreyChurbanov break; 216527f6eedcSAndreyChurbanov } 216627f6eedcSAndreyChurbanov kiv.kve_start += 1; 216727f6eedcSAndreyChurbanov } 216827f6eedcSAndreyChurbanov #elif KMP_OS_DRAGONFLY 216927f6eedcSAndreyChurbanov 217027f6eedcSAndreyChurbanov // FIXME(DragonFly): Implement this 21717cc577a4SJonathan Peyton found = 1; 21727cc577a4SJonathan Peyton 21737cc577a4SJonathan Peyton #else 21747cc577a4SJonathan Peyton 21757cc577a4SJonathan Peyton #error "Unknown or unsupported OS" 21767cc577a4SJonathan Peyton 21777cc577a4SJonathan Peyton #endif 21787cc577a4SJonathan Peyton 21797cc577a4SJonathan Peyton return found; 21807cc577a4SJonathan Peyton 21817cc577a4SJonathan Peyton } // __kmp_is_address_mapped 21827cc577a4SJonathan Peyton 21837cc577a4SJonathan Peyton #ifdef USE_LOAD_BALANCE 21847cc577a4SJonathan Peyton 218570cdd83cSMichal Gorny #if KMP_OS_DARWIN || KMP_OS_NETBSD 21867cc577a4SJonathan Peyton 21877cc577a4SJonathan Peyton // The function returns the rounded value of the system load average 21887cc577a4SJonathan Peyton // during given time interval which depends on the value of 21897cc577a4SJonathan Peyton // __kmp_load_balance_interval variable (default is 60 sec, other values 21907cc577a4SJonathan Peyton // may be 300 sec or 900 sec). 21917cc577a4SJonathan Peyton // It returns -1 in case of error. 21923041982dSJonathan Peyton int __kmp_get_load_balance(int max) { 21937cc577a4SJonathan Peyton double averages[3]; 21947cc577a4SJonathan Peyton int ret_avg = 0; 21957cc577a4SJonathan Peyton 21967cc577a4SJonathan Peyton int res = getloadavg(averages, 3); 21977cc577a4SJonathan Peyton 21987cc577a4SJonathan Peyton // Check __kmp_load_balance_interval to determine which of averages to use. 21997cc577a4SJonathan Peyton // getloadavg() may return the number of samples less than requested that is 22007cc577a4SJonathan Peyton // less than 3. 22017cc577a4SJonathan Peyton if (__kmp_load_balance_interval < 180 && (res >= 1)) { 22026b316febSTerry Wilmarth ret_avg = (int)averages[0]; // 1 min 22033041982dSJonathan Peyton } else if ((__kmp_load_balance_interval >= 180 && 22043041982dSJonathan Peyton __kmp_load_balance_interval < 600) && 22053041982dSJonathan Peyton (res >= 2)) { 22066b316febSTerry Wilmarth ret_avg = (int)averages[1]; // 5 min 22077cc577a4SJonathan Peyton } else if ((__kmp_load_balance_interval >= 600) && (res == 3)) { 22086b316febSTerry Wilmarth ret_avg = (int)averages[2]; // 15 min 22097cc577a4SJonathan Peyton } else { // Error occurred 22107cc577a4SJonathan Peyton return -1; 22117cc577a4SJonathan Peyton } 22127cc577a4SJonathan Peyton 22137cc577a4SJonathan Peyton return ret_avg; 22147cc577a4SJonathan Peyton } 22157cc577a4SJonathan Peyton 22167cc577a4SJonathan Peyton #else // Linux* OS 22177cc577a4SJonathan Peyton 221842016791SKazuaki Ishizaki // The function returns number of running (not sleeping) threads, or -1 in case 22193041982dSJonathan Peyton // of error. Error could be reported if Linux* OS kernel too old (without 22203041982dSJonathan Peyton // "/proc" support). Counting running threads stops if max running threads 22213041982dSJonathan Peyton // encountered. 22223041982dSJonathan Peyton int __kmp_get_load_balance(int max) { 22237cc577a4SJonathan Peyton static int permanent_error = 0; 22243041982dSJonathan Peyton static int glb_running_threads = 0; // Saved count of the running threads for 2225ed5fe645SKelvin Li // the thread balance algorithm 22267cc577a4SJonathan Peyton static double glb_call_time = 0; /* Thread balance algorithm call time */ 22277cc577a4SJonathan Peyton 22287cc577a4SJonathan Peyton int running_threads = 0; // Number of running threads in the system. 22297cc577a4SJonathan Peyton 22307cc577a4SJonathan Peyton DIR *proc_dir = NULL; // Handle of "/proc/" directory. 22317cc577a4SJonathan Peyton struct dirent *proc_entry = NULL; 22327cc577a4SJonathan Peyton 22337cc577a4SJonathan Peyton kmp_str_buf_t task_path; // "/proc/<pid>/task/<tid>/" path. 22347cc577a4SJonathan Peyton DIR *task_dir = NULL; // Handle of "/proc/<pid>/task/<tid>/" directory. 22357cc577a4SJonathan Peyton struct dirent *task_entry = NULL; 22367cc577a4SJonathan Peyton int task_path_fixed_len; 22377cc577a4SJonathan Peyton 22387cc577a4SJonathan Peyton kmp_str_buf_t stat_path; // "/proc/<pid>/task/<tid>/stat" path. 22397cc577a4SJonathan Peyton int stat_file = -1; 22407cc577a4SJonathan Peyton int stat_path_fixed_len; 22417cc577a4SJonathan Peyton 22427cc577a4SJonathan Peyton int total_processes = 0; // Total number of processes in system. 22437cc577a4SJonathan Peyton int total_threads = 0; // Total number of threads in system. 22447cc577a4SJonathan Peyton 22457cc577a4SJonathan Peyton double call_time = 0.0; 22467cc577a4SJonathan Peyton 22477cc577a4SJonathan Peyton __kmp_str_buf_init(&task_path); 22487cc577a4SJonathan Peyton __kmp_str_buf_init(&stat_path); 22497cc577a4SJonathan Peyton 22507cc577a4SJonathan Peyton __kmp_elapsed(&call_time); 22517cc577a4SJonathan Peyton 22527cc577a4SJonathan Peyton if (glb_call_time && 22537cc577a4SJonathan Peyton (call_time - glb_call_time < __kmp_load_balance_interval)) { 22547cc577a4SJonathan Peyton running_threads = glb_running_threads; 22557cc577a4SJonathan Peyton goto finish; 22567cc577a4SJonathan Peyton } 22577cc577a4SJonathan Peyton 22587cc577a4SJonathan Peyton glb_call_time = call_time; 22597cc577a4SJonathan Peyton 22607cc577a4SJonathan Peyton // Do not spend time on scanning "/proc/" if we have a permanent error. 22617cc577a4SJonathan Peyton if (permanent_error) { 22627cc577a4SJonathan Peyton running_threads = -1; 22637cc577a4SJonathan Peyton goto finish; 2264bd3a7633SJonathan Peyton } 22657cc577a4SJonathan Peyton 22667cc577a4SJonathan Peyton if (max <= 0) { 22677cc577a4SJonathan Peyton max = INT_MAX; 2268bd3a7633SJonathan Peyton } 22697cc577a4SJonathan Peyton 22707cc577a4SJonathan Peyton // Open "/proc/" directory. 22717cc577a4SJonathan Peyton proc_dir = opendir("/proc"); 22727cc577a4SJonathan Peyton if (proc_dir == NULL) { 22733041982dSJonathan Peyton // Cannot open "/prroc/". Probably the kernel does not support it. Return an 22743041982dSJonathan Peyton // error now and in subsequent calls. 22757cc577a4SJonathan Peyton running_threads = -1; 22767cc577a4SJonathan Peyton permanent_error = 1; 22777cc577a4SJonathan Peyton goto finish; 2278bd3a7633SJonathan Peyton } 22797cc577a4SJonathan Peyton 22807cc577a4SJonathan Peyton // Initialize fixed part of task_path. This part will not change. 22817cc577a4SJonathan Peyton __kmp_str_buf_cat(&task_path, "/proc/", 6); 22827cc577a4SJonathan Peyton task_path_fixed_len = task_path.used; // Remember number of used characters. 22837cc577a4SJonathan Peyton 22847cc577a4SJonathan Peyton proc_entry = readdir(proc_dir); 22857cc577a4SJonathan Peyton while (proc_entry != NULL) { 22863041982dSJonathan Peyton // Proc entry is a directory and name starts with a digit. Assume it is a 22873041982dSJonathan Peyton // process' directory. 22887cc577a4SJonathan Peyton if (proc_entry->d_type == DT_DIR && isdigit(proc_entry->d_name[0])) { 22897cc577a4SJonathan Peyton 22907cc577a4SJonathan Peyton ++total_processes; 22917cc577a4SJonathan Peyton // Make sure init process is the very first in "/proc", so we can replace 22923041982dSJonathan Peyton // strcmp( proc_entry->d_name, "1" ) == 0 with simpler total_processes == 22933041982dSJonathan Peyton // 1. We are going to check that total_processes == 1 => d_name == "1" is 22943041982dSJonathan Peyton // true (where "=>" is implication). Since C++ does not have => operator, 22953041982dSJonathan Peyton // let us replace it with its equivalent: a => b == ! a || b. 22963041982dSJonathan Peyton KMP_DEBUG_ASSERT(total_processes != 1 || 22973041982dSJonathan Peyton strcmp(proc_entry->d_name, "1") == 0); 22987cc577a4SJonathan Peyton 22997cc577a4SJonathan Peyton // Construct task_path. 23007cc577a4SJonathan Peyton task_path.used = task_path_fixed_len; // Reset task_path to "/proc/". 23013041982dSJonathan Peyton __kmp_str_buf_cat(&task_path, proc_entry->d_name, 23023041982dSJonathan Peyton KMP_STRLEN(proc_entry->d_name)); 23037cc577a4SJonathan Peyton __kmp_str_buf_cat(&task_path, "/task", 5); 23047cc577a4SJonathan Peyton 23057cc577a4SJonathan Peyton task_dir = opendir(task_path.str); 23067cc577a4SJonathan Peyton if (task_dir == NULL) { 23073041982dSJonathan Peyton // Process can finish between reading "/proc/" directory entry and 23083041982dSJonathan Peyton // opening process' "task/" directory. So, in general case we should not 23093041982dSJonathan Peyton // complain, but have to skip this process and read the next one. But on 23103041982dSJonathan Peyton // systems with no "task/" support we will spend lot of time to scan 23113041982dSJonathan Peyton // "/proc/" tree again and again without any benefit. "init" process 23123041982dSJonathan Peyton // (its pid is 1) should exist always, so, if we cannot open 23133041982dSJonathan Peyton // "/proc/1/task/" directory, it means "task/" is not supported by 23143041982dSJonathan Peyton // kernel. Report an error now and in the future. 23157cc577a4SJonathan Peyton if (strcmp(proc_entry->d_name, "1") == 0) { 23167cc577a4SJonathan Peyton running_threads = -1; 23177cc577a4SJonathan Peyton permanent_error = 1; 23187cc577a4SJonathan Peyton goto finish; 2319bd3a7633SJonathan Peyton } 23207cc577a4SJonathan Peyton } else { 23217cc577a4SJonathan Peyton // Construct fixed part of stat file path. 23227cc577a4SJonathan Peyton __kmp_str_buf_clear(&stat_path); 23237cc577a4SJonathan Peyton __kmp_str_buf_cat(&stat_path, task_path.str, task_path.used); 23247cc577a4SJonathan Peyton __kmp_str_buf_cat(&stat_path, "/", 1); 23257cc577a4SJonathan Peyton stat_path_fixed_len = stat_path.used; 23267cc577a4SJonathan Peyton 23277cc577a4SJonathan Peyton task_entry = readdir(task_dir); 23287cc577a4SJonathan Peyton while (task_entry != NULL) { 23297cc577a4SJonathan Peyton // It is a directory and name starts with a digit. 23307cc577a4SJonathan Peyton if (proc_entry->d_type == DT_DIR && isdigit(task_entry->d_name[0])) { 23317cc577a4SJonathan Peyton ++total_threads; 23327cc577a4SJonathan Peyton 2333ed5fe645SKelvin Li // Construct complete stat file path. Easiest way would be: 23343041982dSJonathan Peyton // __kmp_str_buf_print( & stat_path, "%s/%s/stat", task_path.str, 23353041982dSJonathan Peyton // task_entry->d_name ); 23367cc577a4SJonathan Peyton // but seriae of __kmp_str_buf_cat works a bit faster. 23373041982dSJonathan Peyton stat_path.used = 23383041982dSJonathan Peyton stat_path_fixed_len; // Reset stat path to its fixed part. 23393041982dSJonathan Peyton __kmp_str_buf_cat(&stat_path, task_entry->d_name, 23403041982dSJonathan Peyton KMP_STRLEN(task_entry->d_name)); 23417cc577a4SJonathan Peyton __kmp_str_buf_cat(&stat_path, "/stat", 5); 23427cc577a4SJonathan Peyton 23437cc577a4SJonathan Peyton // Note: Low-level API (open/read/close) is used. High-level API 23447cc577a4SJonathan Peyton // (fopen/fclose) works ~ 30 % slower. 23457cc577a4SJonathan Peyton stat_file = open(stat_path.str, O_RDONLY); 23467cc577a4SJonathan Peyton if (stat_file == -1) { 23473041982dSJonathan Peyton // We cannot report an error because task (thread) can terminate 23483041982dSJonathan Peyton // just before reading this file. 23497cc577a4SJonathan Peyton } else { 23503041982dSJonathan Peyton /* Content of "stat" file looks like: 23517cc577a4SJonathan Peyton 24285 (program) S ... 23527cc577a4SJonathan Peyton 23533041982dSJonathan Peyton It is a single line (if program name does not include funny 23543041982dSJonathan Peyton symbols). First number is a thread id, then name of executable 23553041982dSJonathan Peyton file name in paretheses, then state of the thread. We need just 23563041982dSJonathan Peyton thread state. 23577cc577a4SJonathan Peyton 23587cc577a4SJonathan Peyton Good news: Length of program name is 15 characters max. Longer 23597cc577a4SJonathan Peyton names are truncated. 23607cc577a4SJonathan Peyton 23617cc577a4SJonathan Peyton Thus, we need rather short buffer: 15 chars for program name + 23627cc577a4SJonathan Peyton 2 parenthesis, + 3 spaces + ~7 digits of pid = 37. 23637cc577a4SJonathan Peyton 23647cc577a4SJonathan Peyton Bad news: Program name may contain special symbols like space, 23653041982dSJonathan Peyton closing parenthesis, or even new line. This makes parsing 23663041982dSJonathan Peyton "stat" file not 100 % reliable. In case of fanny program names 23673041982dSJonathan Peyton parsing may fail (report incorrect thread state). 23687cc577a4SJonathan Peyton 23697cc577a4SJonathan Peyton Parsing "status" file looks more promissing (due to different 23707cc577a4SJonathan Peyton file structure and escaping special symbols) but reading and 23717cc577a4SJonathan Peyton parsing of "status" file works slower. 23727cc577a4SJonathan Peyton -- ln 23737cc577a4SJonathan Peyton */ 23747cc577a4SJonathan Peyton char buffer[65]; 23756b316febSTerry Wilmarth ssize_t len; 23767cc577a4SJonathan Peyton len = read(stat_file, buffer, sizeof(buffer) - 1); 23777cc577a4SJonathan Peyton if (len >= 0) { 23787cc577a4SJonathan Peyton buffer[len] = 0; 23797cc577a4SJonathan Peyton // Using scanf: 23807cc577a4SJonathan Peyton // sscanf( buffer, "%*d (%*s) %c ", & state ); 23813041982dSJonathan Peyton // looks very nice, but searching for a closing parenthesis 23823041982dSJonathan Peyton // works a bit faster. 23837cc577a4SJonathan Peyton char *close_parent = strstr(buffer, ") "); 23847cc577a4SJonathan Peyton if (close_parent != NULL) { 23857cc577a4SJonathan Peyton char state = *(close_parent + 2); 23867cc577a4SJonathan Peyton if (state == 'R') { 23877cc577a4SJonathan Peyton ++running_threads; 23887cc577a4SJonathan Peyton if (running_threads >= max) { 23897cc577a4SJonathan Peyton goto finish; 2390bd3a7633SJonathan Peyton } 2391bd3a7633SJonathan Peyton } 2392bd3a7633SJonathan Peyton } 2393bd3a7633SJonathan Peyton } 23947cc577a4SJonathan Peyton close(stat_file); 23957cc577a4SJonathan Peyton stat_file = -1; 2396bd3a7633SJonathan Peyton } 2397bd3a7633SJonathan Peyton } 23987cc577a4SJonathan Peyton task_entry = readdir(task_dir); 2399bd3a7633SJonathan Peyton } 24007cc577a4SJonathan Peyton closedir(task_dir); 24017cc577a4SJonathan Peyton task_dir = NULL; 2402bd3a7633SJonathan Peyton } 2403bd3a7633SJonathan Peyton } 24047cc577a4SJonathan Peyton proc_entry = readdir(proc_dir); 2405bd3a7633SJonathan Peyton } 24067cc577a4SJonathan Peyton 24077cc577a4SJonathan Peyton // There _might_ be a timing hole where the thread executing this 24087cc577a4SJonathan Peyton // code get skipped in the load balance, and running_threads is 0. 24097cc577a4SJonathan Peyton // Assert in the debug builds only!!! 24107cc577a4SJonathan Peyton KMP_DEBUG_ASSERT(running_threads > 0); 24117cc577a4SJonathan Peyton if (running_threads <= 0) { 24127cc577a4SJonathan Peyton running_threads = 1; 24137cc577a4SJonathan Peyton } 24147cc577a4SJonathan Peyton 24157cc577a4SJonathan Peyton finish: // Clean up and exit. 24167cc577a4SJonathan Peyton if (proc_dir != NULL) { 24177cc577a4SJonathan Peyton closedir(proc_dir); 2418bd3a7633SJonathan Peyton } 24197cc577a4SJonathan Peyton __kmp_str_buf_free(&task_path); 24207cc577a4SJonathan Peyton if (task_dir != NULL) { 24217cc577a4SJonathan Peyton closedir(task_dir); 2422bd3a7633SJonathan Peyton } 24237cc577a4SJonathan Peyton __kmp_str_buf_free(&stat_path); 24247cc577a4SJonathan Peyton if (stat_file != -1) { 24257cc577a4SJonathan Peyton close(stat_file); 2426bd3a7633SJonathan Peyton } 24277cc577a4SJonathan Peyton 24287cc577a4SJonathan Peyton glb_running_threads = running_threads; 24297cc577a4SJonathan Peyton 24307cc577a4SJonathan Peyton return running_threads; 24317cc577a4SJonathan Peyton 24327cc577a4SJonathan Peyton } // __kmp_get_load_balance 24337cc577a4SJonathan Peyton 24347cc577a4SJonathan Peyton #endif // KMP_OS_DARWIN 24357cc577a4SJonathan Peyton 24367cc577a4SJonathan Peyton #endif // USE_LOAD_BALANCE 24377cc577a4SJonathan Peyton 2438c47afcd9SAndrey Churbanov #if !(KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_MIC || \ 24392488ae9dSJonas Hahnfeld ((KMP_OS_LINUX || KMP_OS_DARWIN) && KMP_ARCH_AARCH64) || \ 24402488ae9dSJonas Hahnfeld KMP_ARCH_PPC64 || KMP_ARCH_RISCV64) 24417cc577a4SJonathan Peyton 24427cc577a4SJonathan Peyton // we really only need the case with 1 argument, because CLANG always build 24437cc577a4SJonathan Peyton // a struct of pointers to shared variables referenced in the outlined function 24443041982dSJonathan Peyton int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc, 24453041982dSJonathan Peyton void *p_argv[] 24467cc577a4SJonathan Peyton #if OMPT_SUPPORT 24473041982dSJonathan Peyton , 24483041982dSJonathan Peyton void **exit_frame_ptr 24497cc577a4SJonathan Peyton #endif 24503041982dSJonathan Peyton ) { 24517cc577a4SJonathan Peyton #if OMPT_SUPPORT 245282e94a59SJoachim Protze *exit_frame_ptr = OMPT_GET_FRAME_ADDRESS(0); 24537cc577a4SJonathan Peyton #endif 24547cc577a4SJonathan Peyton 24557cc577a4SJonathan Peyton switch (argc) { 24567cc577a4SJonathan Peyton default: 24577cc577a4SJonathan Peyton fprintf(stderr, "Too many args to microtask: %d!\n", argc); 24587cc577a4SJonathan Peyton fflush(stderr); 24597cc577a4SJonathan Peyton exit(-1); 24607cc577a4SJonathan Peyton case 0: 24617cc577a4SJonathan Peyton (*pkfn)(>id, &tid); 24627cc577a4SJonathan Peyton break; 24637cc577a4SJonathan Peyton case 1: 24647cc577a4SJonathan Peyton (*pkfn)(>id, &tid, p_argv[0]); 24657cc577a4SJonathan Peyton break; 24667cc577a4SJonathan Peyton case 2: 24677cc577a4SJonathan Peyton (*pkfn)(>id, &tid, p_argv[0], p_argv[1]); 24687cc577a4SJonathan Peyton break; 24697cc577a4SJonathan Peyton case 3: 24707cc577a4SJonathan Peyton (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2]); 24717cc577a4SJonathan Peyton break; 24727cc577a4SJonathan Peyton case 4: 24737cc577a4SJonathan Peyton (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3]); 24747cc577a4SJonathan Peyton break; 24757cc577a4SJonathan Peyton case 5: 24767cc577a4SJonathan Peyton (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4]); 24777cc577a4SJonathan Peyton break; 24787cc577a4SJonathan Peyton case 6: 24797cc577a4SJonathan Peyton (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], 24807cc577a4SJonathan Peyton p_argv[5]); 24817cc577a4SJonathan Peyton break; 24827cc577a4SJonathan Peyton case 7: 24837cc577a4SJonathan Peyton (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], 24847cc577a4SJonathan Peyton p_argv[5], p_argv[6]); 24857cc577a4SJonathan Peyton break; 24867cc577a4SJonathan Peyton case 8: 24877cc577a4SJonathan Peyton (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], 24887cc577a4SJonathan Peyton p_argv[5], p_argv[6], p_argv[7]); 24897cc577a4SJonathan Peyton break; 24907cc577a4SJonathan Peyton case 9: 24917cc577a4SJonathan Peyton (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], 24927cc577a4SJonathan Peyton p_argv[5], p_argv[6], p_argv[7], p_argv[8]); 24937cc577a4SJonathan Peyton break; 24947cc577a4SJonathan Peyton case 10: 24957cc577a4SJonathan Peyton (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], 24967cc577a4SJonathan Peyton p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9]); 24977cc577a4SJonathan Peyton break; 24987cc577a4SJonathan Peyton case 11: 24997cc577a4SJonathan Peyton (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], 25007cc577a4SJonathan Peyton p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10]); 25017cc577a4SJonathan Peyton break; 25027cc577a4SJonathan Peyton case 12: 25037cc577a4SJonathan Peyton (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], 25047cc577a4SJonathan Peyton p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10], 25057cc577a4SJonathan Peyton p_argv[11]); 25067cc577a4SJonathan Peyton break; 25077cc577a4SJonathan Peyton case 13: 25087cc577a4SJonathan Peyton (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], 25097cc577a4SJonathan Peyton p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10], 25107cc577a4SJonathan Peyton p_argv[11], p_argv[12]); 25117cc577a4SJonathan Peyton break; 25127cc577a4SJonathan Peyton case 14: 25137cc577a4SJonathan Peyton (*pkfn)(>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], p_argv[12], p_argv[13]); 25167cc577a4SJonathan Peyton break; 25177cc577a4SJonathan Peyton case 15: 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], p_argv[13], p_argv[14]); 25217cc577a4SJonathan Peyton break; 25227cc577a4SJonathan Peyton } 25237cc577a4SJonathan Peyton 25247cc577a4SJonathan Peyton return 1; 25257cc577a4SJonathan Peyton } 25267cc577a4SJonathan Peyton 25277cc577a4SJonathan Peyton #endif 25287cc577a4SJonathan Peyton 25299d64275aSShilei Tian // Functions for hidden helper task 25309d64275aSShilei Tian namespace { 25319d64275aSShilei Tian // Condition variable for initializing hidden helper team 25329d64275aSShilei Tian pthread_cond_t hidden_helper_threads_initz_cond_var; 25339d64275aSShilei Tian pthread_mutex_t hidden_helper_threads_initz_lock; 25349d64275aSShilei Tian volatile int hidden_helper_initz_signaled = FALSE; 25359d64275aSShilei Tian 25369d64275aSShilei Tian // Condition variable for deinitializing hidden helper team 25379d64275aSShilei Tian pthread_cond_t hidden_helper_threads_deinitz_cond_var; 25389d64275aSShilei Tian pthread_mutex_t hidden_helper_threads_deinitz_lock; 25399d64275aSShilei Tian volatile int hidden_helper_deinitz_signaled = FALSE; 25409d64275aSShilei Tian 25419d64275aSShilei Tian // Condition variable for the wrapper function of main thread 25429d64275aSShilei Tian pthread_cond_t hidden_helper_main_thread_cond_var; 25439d64275aSShilei Tian pthread_mutex_t hidden_helper_main_thread_lock; 25449d64275aSShilei Tian volatile int hidden_helper_main_thread_signaled = FALSE; 25459d64275aSShilei Tian 25469d64275aSShilei Tian // Semaphore for worker threads. We don't use condition variable here in case 25479d64275aSShilei Tian // that when multiple signals are sent at the same time, only one thread might 25489d64275aSShilei Tian // be waken. 25499d64275aSShilei Tian sem_t hidden_helper_task_sem; 25509d64275aSShilei Tian } // namespace 25519d64275aSShilei Tian 25529d64275aSShilei Tian void __kmp_hidden_helper_worker_thread_wait() { 25539d64275aSShilei Tian int status = sem_wait(&hidden_helper_task_sem); 25549d64275aSShilei Tian KMP_CHECK_SYSFAIL("sem_wait", status); 25559d64275aSShilei Tian } 25569d64275aSShilei Tian 25579d64275aSShilei Tian void __kmp_do_initialize_hidden_helper_threads() { 25589d64275aSShilei Tian // Initialize condition variable 25599d64275aSShilei Tian int status = 25609d64275aSShilei Tian pthread_cond_init(&hidden_helper_threads_initz_cond_var, nullptr); 25619d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_cond_init", status); 25629d64275aSShilei Tian 25639d64275aSShilei Tian status = pthread_cond_init(&hidden_helper_threads_deinitz_cond_var, nullptr); 25649d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_cond_init", status); 25659d64275aSShilei Tian 25669d64275aSShilei Tian status = pthread_cond_init(&hidden_helper_main_thread_cond_var, nullptr); 25679d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_cond_init", status); 25689d64275aSShilei Tian 25699d64275aSShilei Tian status = pthread_mutex_init(&hidden_helper_threads_initz_lock, nullptr); 25709d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_init", status); 25719d64275aSShilei Tian 25729d64275aSShilei Tian status = pthread_mutex_init(&hidden_helper_threads_deinitz_lock, nullptr); 25739d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_init", status); 25749d64275aSShilei Tian 25759d64275aSShilei Tian status = pthread_mutex_init(&hidden_helper_main_thread_lock, nullptr); 25769d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_init", status); 25779d64275aSShilei Tian 25789d64275aSShilei Tian // Initialize the semaphore 25799d64275aSShilei Tian status = sem_init(&hidden_helper_task_sem, 0, 0); 25809d64275aSShilei Tian KMP_CHECK_SYSFAIL("sem_init", status); 25819d64275aSShilei Tian 25829d64275aSShilei Tian // Create a new thread to finish initialization 25839d64275aSShilei Tian pthread_t handle; 25849d64275aSShilei Tian status = pthread_create( 25859d64275aSShilei Tian &handle, nullptr, 25869d64275aSShilei Tian [](void *) -> void * { 25879d64275aSShilei Tian __kmp_hidden_helper_threads_initz_routine(); 25889d64275aSShilei Tian return nullptr; 25899d64275aSShilei Tian }, 25909d64275aSShilei Tian nullptr); 25919d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_create", status); 25929d64275aSShilei Tian } 25939d64275aSShilei Tian 25949d64275aSShilei Tian void __kmp_hidden_helper_threads_initz_wait() { 25959d64275aSShilei Tian // Initial thread waits here for the completion of the initialization. The 25969d64275aSShilei Tian // condition variable will be notified by main thread of hidden helper teams. 25979d64275aSShilei Tian int status = pthread_mutex_lock(&hidden_helper_threads_initz_lock); 25989d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_lock", status); 25999d64275aSShilei Tian 26009d64275aSShilei Tian if (!TCR_4(hidden_helper_initz_signaled)) { 26019d64275aSShilei Tian status = pthread_cond_wait(&hidden_helper_threads_initz_cond_var, 26029d64275aSShilei Tian &hidden_helper_threads_initz_lock); 26039d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_cond_wait", status); 26049d64275aSShilei Tian } 26059d64275aSShilei Tian 26069d64275aSShilei Tian status = pthread_mutex_unlock(&hidden_helper_threads_initz_lock); 26079d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status); 26089d64275aSShilei Tian } 26099d64275aSShilei Tian 26109d64275aSShilei Tian void __kmp_hidden_helper_initz_release() { 26119d64275aSShilei Tian // After all initialization, reset __kmp_init_hidden_helper_threads to false. 26129d64275aSShilei Tian int status = pthread_mutex_lock(&hidden_helper_threads_initz_lock); 26139d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_lock", status); 26149d64275aSShilei Tian 26159d64275aSShilei Tian status = pthread_cond_signal(&hidden_helper_threads_initz_cond_var); 26169d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_cond_wait", status); 26179d64275aSShilei Tian 26189d64275aSShilei Tian TCW_SYNC_4(hidden_helper_initz_signaled, TRUE); 26199d64275aSShilei Tian 26209d64275aSShilei Tian status = pthread_mutex_unlock(&hidden_helper_threads_initz_lock); 26219d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status); 26229d64275aSShilei Tian } 26239d64275aSShilei Tian 26249d64275aSShilei Tian void __kmp_hidden_helper_main_thread_wait() { 26259d64275aSShilei Tian // The main thread of hidden helper team will be blocked here. The 26269d64275aSShilei Tian // condition variable can only be signal in the destructor of RTL. 26279d64275aSShilei Tian int status = pthread_mutex_lock(&hidden_helper_main_thread_lock); 26289d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_lock", status); 26299d64275aSShilei Tian 26309d64275aSShilei Tian if (!TCR_4(hidden_helper_main_thread_signaled)) { 26319d64275aSShilei Tian status = pthread_cond_wait(&hidden_helper_main_thread_cond_var, 26329d64275aSShilei Tian &hidden_helper_main_thread_lock); 26339d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_cond_wait", status); 26349d64275aSShilei Tian } 26359d64275aSShilei Tian 26369d64275aSShilei Tian status = pthread_mutex_unlock(&hidden_helper_main_thread_lock); 26379d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status); 26389d64275aSShilei Tian } 26399d64275aSShilei Tian 26409d64275aSShilei Tian void __kmp_hidden_helper_main_thread_release() { 26419d64275aSShilei Tian // The initial thread of OpenMP RTL should call this function to wake up the 26429d64275aSShilei Tian // main thread of hidden helper team. 26439d64275aSShilei Tian int status = pthread_mutex_lock(&hidden_helper_main_thread_lock); 26449d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_lock", status); 26459d64275aSShilei Tian 26469d64275aSShilei Tian status = pthread_cond_signal(&hidden_helper_main_thread_cond_var); 26479d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_cond_signal", status); 26489d64275aSShilei Tian 26499d64275aSShilei Tian // The hidden helper team is done here 26509d64275aSShilei Tian TCW_SYNC_4(hidden_helper_main_thread_signaled, TRUE); 26519d64275aSShilei Tian 26529d64275aSShilei Tian status = pthread_mutex_unlock(&hidden_helper_main_thread_lock); 26539d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status); 26549d64275aSShilei Tian } 26559d64275aSShilei Tian 26569d64275aSShilei Tian void __kmp_hidden_helper_worker_thread_signal() { 26579d64275aSShilei Tian int status = sem_post(&hidden_helper_task_sem); 26589d64275aSShilei Tian KMP_CHECK_SYSFAIL("sem_post", status); 26599d64275aSShilei Tian } 26609d64275aSShilei Tian 26619d64275aSShilei Tian void __kmp_hidden_helper_threads_deinitz_wait() { 26629d64275aSShilei Tian // Initial thread waits here for the completion of the deinitialization. The 26639d64275aSShilei Tian // condition variable will be notified by main thread of hidden helper teams. 26649d64275aSShilei Tian int status = pthread_mutex_lock(&hidden_helper_threads_deinitz_lock); 26659d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_lock", status); 26669d64275aSShilei Tian 26679d64275aSShilei Tian if (!TCR_4(hidden_helper_deinitz_signaled)) { 26689d64275aSShilei Tian status = pthread_cond_wait(&hidden_helper_threads_deinitz_cond_var, 26699d64275aSShilei Tian &hidden_helper_threads_deinitz_lock); 26709d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_cond_wait", status); 26719d64275aSShilei Tian } 26729d64275aSShilei Tian 26739d64275aSShilei Tian status = pthread_mutex_unlock(&hidden_helper_threads_deinitz_lock); 26749d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status); 26759d64275aSShilei Tian } 26769d64275aSShilei Tian 26779d64275aSShilei Tian void __kmp_hidden_helper_threads_deinitz_release() { 26789d64275aSShilei Tian int status = pthread_mutex_lock(&hidden_helper_threads_deinitz_lock); 26799d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_lock", status); 26809d64275aSShilei Tian 26819d64275aSShilei Tian status = pthread_cond_signal(&hidden_helper_threads_deinitz_cond_var); 26829d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_cond_wait", status); 26839d64275aSShilei Tian 26849d64275aSShilei Tian TCW_SYNC_4(hidden_helper_deinitz_signaled, TRUE); 26859d64275aSShilei Tian 26869d64275aSShilei Tian status = pthread_mutex_unlock(&hidden_helper_threads_deinitz_lock); 26879d64275aSShilei Tian KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status); 26889d64275aSShilei Tian } 26899d64275aSShilei Tian 26907cc577a4SJonathan Peyton // end of file // 2691