17cc577a4SJonathan Peyton /*
2de4749b7SJonathan Peyton  * z_Windows_NT_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"
143041982dSJonathan Peyton #include "kmp_affinity.h"
157cc577a4SJonathan Peyton #include "kmp_i18n.h"
167cc577a4SJonathan Peyton #include "kmp_io.h"
173041982dSJonathan Peyton #include "kmp_itt.h"
187cc577a4SJonathan Peyton #include "kmp_wait_release.h"
197cc577a4SJonathan Peyton 
207cc577a4SJonathan Peyton /* This code is related to NtQuerySystemInformation() function. This function
217cc577a4SJonathan Peyton    is used in the Load balance algorithm for OMP_DYNAMIC=true to find the
227cc577a4SJonathan Peyton    number of running threads in the system. */
237cc577a4SJonathan Peyton 
247cc577a4SJonathan Peyton #include <ntsecapi.h> // UNICODE_STRING
253041982dSJonathan Peyton #include <ntstatus.h>
26ffb21e7fSHansang Bae #include <psapi.h>
273f9519b7SMartin Storsjö #ifdef _MSC_VER
28ffb21e7fSHansang Bae #pragma comment(lib, "psapi.lib")
293f9519b7SMartin Storsjö #endif
307cc577a4SJonathan Peyton 
317cc577a4SJonathan Peyton enum SYSTEM_INFORMATION_CLASS {
327cc577a4SJonathan Peyton   SystemProcessInformation = 5
337cc577a4SJonathan Peyton }; // SYSTEM_INFORMATION_CLASS
347cc577a4SJonathan Peyton 
357cc577a4SJonathan Peyton struct CLIENT_ID {
367cc577a4SJonathan Peyton   HANDLE UniqueProcess;
377cc577a4SJonathan Peyton   HANDLE UniqueThread;
387cc577a4SJonathan Peyton }; // struct CLIENT_ID
397cc577a4SJonathan Peyton 
407cc577a4SJonathan Peyton enum THREAD_STATE {
417cc577a4SJonathan Peyton   StateInitialized,
427cc577a4SJonathan Peyton   StateReady,
437cc577a4SJonathan Peyton   StateRunning,
447cc577a4SJonathan Peyton   StateStandby,
457cc577a4SJonathan Peyton   StateTerminated,
467cc577a4SJonathan Peyton   StateWait,
477cc577a4SJonathan Peyton   StateTransition,
487cc577a4SJonathan Peyton   StateUnknown
497cc577a4SJonathan Peyton }; // enum THREAD_STATE
507cc577a4SJonathan Peyton 
517cc577a4SJonathan Peyton struct VM_COUNTERS {
527cc577a4SJonathan Peyton   SIZE_T PeakVirtualSize;
537cc577a4SJonathan Peyton   SIZE_T VirtualSize;
547cc577a4SJonathan Peyton   ULONG PageFaultCount;
557cc577a4SJonathan Peyton   SIZE_T PeakWorkingSetSize;
567cc577a4SJonathan Peyton   SIZE_T WorkingSetSize;
577cc577a4SJonathan Peyton   SIZE_T QuotaPeakPagedPoolUsage;
587cc577a4SJonathan Peyton   SIZE_T QuotaPagedPoolUsage;
597cc577a4SJonathan Peyton   SIZE_T QuotaPeakNonPagedPoolUsage;
607cc577a4SJonathan Peyton   SIZE_T QuotaNonPagedPoolUsage;
617cc577a4SJonathan Peyton   SIZE_T PagefileUsage;
627cc577a4SJonathan Peyton   SIZE_T PeakPagefileUsage;
637cc577a4SJonathan Peyton   SIZE_T PrivatePageCount;
647cc577a4SJonathan Peyton }; // struct VM_COUNTERS
657cc577a4SJonathan Peyton 
667cc577a4SJonathan Peyton struct SYSTEM_THREAD {
677cc577a4SJonathan Peyton   LARGE_INTEGER KernelTime;
687cc577a4SJonathan Peyton   LARGE_INTEGER UserTime;
697cc577a4SJonathan Peyton   LARGE_INTEGER CreateTime;
707cc577a4SJonathan Peyton   ULONG WaitTime;
717cc577a4SJonathan Peyton   LPVOID StartAddress;
727cc577a4SJonathan Peyton   CLIENT_ID ClientId;
737cc577a4SJonathan Peyton   DWORD Priority;
747cc577a4SJonathan Peyton   LONG BasePriority;
757cc577a4SJonathan Peyton   ULONG ContextSwitchCount;
767cc577a4SJonathan Peyton   THREAD_STATE State;
777cc577a4SJonathan Peyton   ULONG WaitReason;
787cc577a4SJonathan Peyton }; // SYSTEM_THREAD
797cc577a4SJonathan Peyton 
807cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_THREAD, KernelTime) == 0);
817cc577a4SJonathan Peyton #if KMP_ARCH_X86
827cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_THREAD, StartAddress) == 28);
837cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_THREAD, State) == 52);
847cc577a4SJonathan Peyton #else
857cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_THREAD, StartAddress) == 32);
867cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_THREAD, State) == 68);
877cc577a4SJonathan Peyton #endif
887cc577a4SJonathan Peyton 
897cc577a4SJonathan Peyton struct SYSTEM_PROCESS_INFORMATION {
907cc577a4SJonathan Peyton   ULONG NextEntryOffset;
917cc577a4SJonathan Peyton   ULONG NumberOfThreads;
927cc577a4SJonathan Peyton   LARGE_INTEGER Reserved[3];
937cc577a4SJonathan Peyton   LARGE_INTEGER CreateTime;
947cc577a4SJonathan Peyton   LARGE_INTEGER UserTime;
957cc577a4SJonathan Peyton   LARGE_INTEGER KernelTime;
967cc577a4SJonathan Peyton   UNICODE_STRING ImageName;
977cc577a4SJonathan Peyton   DWORD BasePriority;
987cc577a4SJonathan Peyton   HANDLE ProcessId;
997cc577a4SJonathan Peyton   HANDLE ParentProcessId;
1007cc577a4SJonathan Peyton   ULONG HandleCount;
1017cc577a4SJonathan Peyton   ULONG Reserved2[2];
1027cc577a4SJonathan Peyton   VM_COUNTERS VMCounters;
1037cc577a4SJonathan Peyton   IO_COUNTERS IOCounters;
1047cc577a4SJonathan Peyton   SYSTEM_THREAD Threads[1];
1057cc577a4SJonathan Peyton }; // SYSTEM_PROCESS_INFORMATION
1067cc577a4SJonathan Peyton typedef SYSTEM_PROCESS_INFORMATION *PSYSTEM_PROCESS_INFORMATION;
1077cc577a4SJonathan Peyton 
1087cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, NextEntryOffset) == 0);
1097cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, CreateTime) == 32);
1107cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, ImageName) == 56);
1117cc577a4SJonathan Peyton #if KMP_ARCH_X86
1127cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, ProcessId) == 68);
1137cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, HandleCount) == 76);
1147cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, VMCounters) == 88);
1157cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, IOCounters) == 136);
1167cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, Threads) == 184);
1177cc577a4SJonathan Peyton #else
1187cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, ProcessId) == 80);
1197cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, HandleCount) == 96);
1207cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, VMCounters) == 112);
1217cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, IOCounters) == 208);
1227cc577a4SJonathan Peyton KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, Threads) == 256);
1237cc577a4SJonathan Peyton #endif
1247cc577a4SJonathan Peyton 
1253041982dSJonathan Peyton typedef NTSTATUS(NTAPI *NtQuerySystemInformation_t)(SYSTEM_INFORMATION_CLASS,
1263041982dSJonathan Peyton                                                     PVOID, ULONG, PULONG);
1277cc577a4SJonathan Peyton NtQuerySystemInformation_t NtQuerySystemInformation = NULL;
1287cc577a4SJonathan Peyton 
1297cc577a4SJonathan Peyton HMODULE ntdll = NULL;
1307cc577a4SJonathan Peyton 
1317cc577a4SJonathan Peyton /* End of NtQuerySystemInformation()-related code */
1327cc577a4SJonathan Peyton 
1337cc577a4SJonathan Peyton static HMODULE kernel32 = NULL;
1347cc577a4SJonathan Peyton 
1357cc577a4SJonathan Peyton #if KMP_HANDLE_SIGNALS
1367cc577a4SJonathan Peyton typedef void (*sig_func_t)(int);
1377cc577a4SJonathan Peyton static sig_func_t __kmp_sighldrs[NSIG];
1387cc577a4SJonathan Peyton static int __kmp_siginstalled[NSIG];
1397cc577a4SJonathan Peyton #endif
1407cc577a4SJonathan Peyton 
1417cc577a4SJonathan Peyton #if KMP_USE_MONITOR
1427cc577a4SJonathan Peyton static HANDLE __kmp_monitor_ev;
1437cc577a4SJonathan Peyton #endif
1447cc577a4SJonathan Peyton static kmp_int64 __kmp_win32_time;
1457cc577a4SJonathan Peyton double __kmp_win32_tick;
1467cc577a4SJonathan Peyton 
1477cc577a4SJonathan Peyton int __kmp_init_runtime = FALSE;
1487cc577a4SJonathan Peyton CRITICAL_SECTION __kmp_win32_section;
1497cc577a4SJonathan Peyton 
__kmp_win32_mutex_init(kmp_win32_mutex_t * mx)1503041982dSJonathan Peyton void __kmp_win32_mutex_init(kmp_win32_mutex_t *mx) {
1517cc577a4SJonathan Peyton   InitializeCriticalSection(&mx->cs);
1527cc577a4SJonathan Peyton #if USE_ITT_BUILD
1537cc577a4SJonathan Peyton   __kmp_itt_system_object_created(&mx->cs, "Critical Section");
1547cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
1557cc577a4SJonathan Peyton }
1567cc577a4SJonathan Peyton 
__kmp_win32_mutex_destroy(kmp_win32_mutex_t * mx)1573041982dSJonathan Peyton void __kmp_win32_mutex_destroy(kmp_win32_mutex_t *mx) {
1587cc577a4SJonathan Peyton   DeleteCriticalSection(&mx->cs);
1597cc577a4SJonathan Peyton }
1607cc577a4SJonathan Peyton 
__kmp_win32_mutex_lock(kmp_win32_mutex_t * mx)1613041982dSJonathan Peyton void __kmp_win32_mutex_lock(kmp_win32_mutex_t *mx) {
1627cc577a4SJonathan Peyton   EnterCriticalSection(&mx->cs);
1637cc577a4SJonathan Peyton }
1647cc577a4SJonathan Peyton 
__kmp_win32_mutex_trylock(kmp_win32_mutex_t * mx)1659b8bb323SJonathan Peyton int __kmp_win32_mutex_trylock(kmp_win32_mutex_t *mx) {
1669b8bb323SJonathan Peyton   return TryEnterCriticalSection(&mx->cs);
1679b8bb323SJonathan Peyton }
1689b8bb323SJonathan Peyton 
__kmp_win32_mutex_unlock(kmp_win32_mutex_t * mx)1693041982dSJonathan Peyton void __kmp_win32_mutex_unlock(kmp_win32_mutex_t *mx) {
1707cc577a4SJonathan Peyton   LeaveCriticalSection(&mx->cs);
1717cc577a4SJonathan Peyton }
1727cc577a4SJonathan Peyton 
__kmp_win32_cond_init(kmp_win32_cond_t * cv)1733041982dSJonathan Peyton void __kmp_win32_cond_init(kmp_win32_cond_t *cv) {
1747cc577a4SJonathan Peyton   cv->waiters_count_ = 0;
1757cc577a4SJonathan Peyton   cv->wait_generation_count_ = 0;
1767cc577a4SJonathan Peyton   cv->release_count_ = 0;
1777cc577a4SJonathan Peyton 
1787cc577a4SJonathan Peyton   /* Initialize the critical section */
1797cc577a4SJonathan Peyton   __kmp_win32_mutex_init(&cv->waiters_count_lock_);
1807cc577a4SJonathan Peyton 
1817cc577a4SJonathan Peyton   /* Create a manual-reset event. */
1827cc577a4SJonathan Peyton   cv->event_ = CreateEvent(NULL, // no security
1837cc577a4SJonathan Peyton                            TRUE, // manual-reset
1847cc577a4SJonathan Peyton                            FALSE, // non-signaled initially
1857cc577a4SJonathan Peyton                            NULL); // unnamed
1867cc577a4SJonathan Peyton #if USE_ITT_BUILD
1877cc577a4SJonathan Peyton   __kmp_itt_system_object_created(cv->event_, "Event");
1887cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
1897cc577a4SJonathan Peyton }
1907cc577a4SJonathan Peyton 
__kmp_win32_cond_destroy(kmp_win32_cond_t * cv)1913041982dSJonathan Peyton void __kmp_win32_cond_destroy(kmp_win32_cond_t *cv) {
1927cc577a4SJonathan Peyton   __kmp_win32_mutex_destroy(&cv->waiters_count_lock_);
1937cc577a4SJonathan Peyton   __kmp_free_handle(cv->event_);
1947cc577a4SJonathan Peyton   memset(cv, '\0', sizeof(*cv));
1957cc577a4SJonathan Peyton }
1967cc577a4SJonathan Peyton 
1977cc577a4SJonathan Peyton /* TODO associate cv with a team instead of a thread so as to optimize
1983041982dSJonathan Peyton    the case where we wake up a whole team */
1997cc577a4SJonathan Peyton 
200b727d384SJonathan Peyton template <class C>
__kmp_win32_cond_wait(kmp_win32_cond_t * cv,kmp_win32_mutex_t * mx,kmp_info_t * th,C * flag)201b727d384SJonathan Peyton static void __kmp_win32_cond_wait(kmp_win32_cond_t *cv, kmp_win32_mutex_t *mx,
202b727d384SJonathan Peyton                                   kmp_info_t *th, C *flag) {
2037cc577a4SJonathan Peyton   int my_generation;
2047cc577a4SJonathan Peyton   int last_waiter;
2057cc577a4SJonathan Peyton 
2067cc577a4SJonathan Peyton   /* Avoid race conditions */
2077cc577a4SJonathan Peyton   __kmp_win32_mutex_lock(&cv->waiters_count_lock_);
2087cc577a4SJonathan Peyton 
2097cc577a4SJonathan Peyton   /* Increment count of waiters */
2107cc577a4SJonathan Peyton   cv->waiters_count_++;
2117cc577a4SJonathan Peyton 
2127cc577a4SJonathan Peyton   /* Store current generation in our activation record. */
2137cc577a4SJonathan Peyton   my_generation = cv->wait_generation_count_;
2147cc577a4SJonathan Peyton 
2157cc577a4SJonathan Peyton   __kmp_win32_mutex_unlock(&cv->waiters_count_lock_);
2167cc577a4SJonathan Peyton   __kmp_win32_mutex_unlock(mx);
2177cc577a4SJonathan Peyton 
2187cc577a4SJonathan Peyton   for (;;) {
219b727d384SJonathan Peyton     int wait_done = 0;
220b727d384SJonathan Peyton     DWORD res, timeout = 5000; // just tried to quess an appropriate number
2217cc577a4SJonathan Peyton     /* Wait until the event is signaled */
222b727d384SJonathan Peyton     res = WaitForSingleObject(cv->event_, timeout);
2237cc577a4SJonathan Peyton 
224b727d384SJonathan Peyton     if (res == WAIT_OBJECT_0) {
225b727d384SJonathan Peyton       // event signaled
2267cc577a4SJonathan Peyton       __kmp_win32_mutex_lock(&cv->waiters_count_lock_);
2273041982dSJonathan Peyton       /* Exit the loop when the <cv->event_> is signaled and there are still
2283041982dSJonathan Peyton          waiting threads from this <wait_generation> that haven't been released
2293041982dSJonathan Peyton          from this wait yet. */
2307cc577a4SJonathan Peyton       wait_done = (cv->release_count_ > 0) &&
2317cc577a4SJonathan Peyton                   (cv->wait_generation_count_ != my_generation);
232b727d384SJonathan Peyton       __kmp_win32_mutex_unlock(&cv->waiters_count_lock_);
233b727d384SJonathan Peyton     } else if (res == WAIT_TIMEOUT || res == WAIT_FAILED) {
234b727d384SJonathan Peyton       // check if the flag and cv counters are in consistent state
235b727d384SJonathan Peyton       // as MS sent us debug dump whith inconsistent state of data
236b727d384SJonathan Peyton       __kmp_win32_mutex_lock(mx);
237b727d384SJonathan Peyton       typename C::flag_t old_f = flag->set_sleeping();
238b727d384SJonathan Peyton       if (!flag->done_check_val(old_f & ~KMP_BARRIER_SLEEP_STATE)) {
239b727d384SJonathan Peyton         __kmp_win32_mutex_unlock(mx);
240b727d384SJonathan Peyton         continue;
241b727d384SJonathan Peyton       }
242b727d384SJonathan Peyton       // condition fulfilled, exiting
243d8e4cb91STerry Wilmarth       flag->unset_sleeping();
244b727d384SJonathan Peyton       TCW_PTR(th->th.th_sleep_loc, NULL);
245d8e4cb91STerry Wilmarth       th->th.th_sleep_loc_type = flag_unset;
246d8e4cb91STerry Wilmarth       KF_TRACE(50, ("__kmp_win32_cond_wait: exiting, condition "
247d8e4cb91STerry Wilmarth                     "fulfilled: flag's loc(%p): %u\n",
248d8e4cb91STerry Wilmarth                     flag->get(), (unsigned int)flag->load()));
2497cc577a4SJonathan Peyton 
250b727d384SJonathan Peyton       __kmp_win32_mutex_lock(&cv->waiters_count_lock_);
251b727d384SJonathan Peyton       KMP_DEBUG_ASSERT(cv->waiters_count_ > 0);
252b727d384SJonathan Peyton       cv->release_count_ = cv->waiters_count_;
253b727d384SJonathan Peyton       cv->wait_generation_count_++;
254b727d384SJonathan Peyton       wait_done = 1;
2557cc577a4SJonathan Peyton       __kmp_win32_mutex_unlock(&cv->waiters_count_lock_);
2567cc577a4SJonathan Peyton 
257b727d384SJonathan Peyton       __kmp_win32_mutex_unlock(mx);
258b727d384SJonathan Peyton     }
2593041982dSJonathan Peyton     /* there used to be a semicolon after the if statement, it looked like a
2603041982dSJonathan Peyton        bug, so i removed it */
2617cc577a4SJonathan Peyton     if (wait_done)
2627cc577a4SJonathan Peyton       break;
2637cc577a4SJonathan Peyton   }
2647cc577a4SJonathan Peyton 
2657cc577a4SJonathan Peyton   __kmp_win32_mutex_lock(mx);
2667cc577a4SJonathan Peyton   __kmp_win32_mutex_lock(&cv->waiters_count_lock_);
2677cc577a4SJonathan Peyton 
2687cc577a4SJonathan Peyton   cv->waiters_count_--;
2697cc577a4SJonathan Peyton   cv->release_count_--;
2707cc577a4SJonathan Peyton 
2717cc577a4SJonathan Peyton   last_waiter = (cv->release_count_ == 0);
2727cc577a4SJonathan Peyton 
2737cc577a4SJonathan Peyton   __kmp_win32_mutex_unlock(&cv->waiters_count_lock_);
2747cc577a4SJonathan Peyton 
2757cc577a4SJonathan Peyton   if (last_waiter) {
2767cc577a4SJonathan Peyton     /* We're the last waiter to be notified, so reset the manual event. */
2777cc577a4SJonathan Peyton     ResetEvent(cv->event_);
2787cc577a4SJonathan Peyton   }
2797cc577a4SJonathan Peyton }
2807cc577a4SJonathan Peyton 
__kmp_win32_cond_broadcast(kmp_win32_cond_t * cv)2813041982dSJonathan Peyton void __kmp_win32_cond_broadcast(kmp_win32_cond_t *cv) {
2827cc577a4SJonathan Peyton   __kmp_win32_mutex_lock(&cv->waiters_count_lock_);
2837cc577a4SJonathan Peyton 
2847cc577a4SJonathan Peyton   if (cv->waiters_count_ > 0) {
2857cc577a4SJonathan Peyton     SetEvent(cv->event_);
2867cc577a4SJonathan Peyton     /* Release all the threads in this generation. */
2877cc577a4SJonathan Peyton 
2887cc577a4SJonathan Peyton     cv->release_count_ = cv->waiters_count_;
2897cc577a4SJonathan Peyton 
2907cc577a4SJonathan Peyton     /* Start a new generation. */
2917cc577a4SJonathan Peyton     cv->wait_generation_count_++;
2927cc577a4SJonathan Peyton   }
2937cc577a4SJonathan Peyton 
2947cc577a4SJonathan Peyton   __kmp_win32_mutex_unlock(&cv->waiters_count_lock_);
2957cc577a4SJonathan Peyton }
2967cc577a4SJonathan Peyton 
__kmp_win32_cond_signal(kmp_win32_cond_t * cv)2973041982dSJonathan Peyton void __kmp_win32_cond_signal(kmp_win32_cond_t *cv) {
2987cc577a4SJonathan Peyton   __kmp_win32_cond_broadcast(cv);
2997cc577a4SJonathan Peyton }
3007cc577a4SJonathan Peyton 
__kmp_enable(int new_state)3013041982dSJonathan Peyton void __kmp_enable(int new_state) {
3027cc577a4SJonathan Peyton   if (__kmp_init_runtime)
3037cc577a4SJonathan Peyton     LeaveCriticalSection(&__kmp_win32_section);
3047cc577a4SJonathan Peyton }
3057cc577a4SJonathan Peyton 
__kmp_disable(int * old_state)3063041982dSJonathan Peyton void __kmp_disable(int *old_state) {
3077cc577a4SJonathan Peyton   *old_state = 0;
3087cc577a4SJonathan Peyton 
3097cc577a4SJonathan Peyton   if (__kmp_init_runtime)
3107cc577a4SJonathan Peyton     EnterCriticalSection(&__kmp_win32_section);
3117cc577a4SJonathan Peyton }
3127cc577a4SJonathan Peyton 
__kmp_suspend_initialize(void)3133041982dSJonathan Peyton void __kmp_suspend_initialize(void) { /* do nothing */
3147cc577a4SJonathan Peyton }
3157cc577a4SJonathan Peyton 
__kmp_suspend_initialize_thread(kmp_info_t * th)316feac33ebSJonathan Peyton void __kmp_suspend_initialize_thread(kmp_info_t *th) {
317f8f788b2SAndrey Churbanov   int old_value = KMP_ATOMIC_LD_RLX(&th->th.th_suspend_init);
318f8f788b2SAndrey Churbanov   int new_value = TRUE;
319f8f788b2SAndrey Churbanov   // Return if already initialized
320f8f788b2SAndrey Churbanov   if (old_value == new_value)
321f8f788b2SAndrey Churbanov     return;
322f8f788b2SAndrey Churbanov   // Wait, then return if being initialized
323f8f788b2SAndrey Churbanov   if (old_value == -1 ||
324f8f788b2SAndrey Churbanov       !__kmp_atomic_compare_store(&th->th.th_suspend_init, old_value, -1)) {
325f8f788b2SAndrey Churbanov     while (KMP_ATOMIC_LD_ACQ(&th->th.th_suspend_init) != new_value) {
326f8f788b2SAndrey Churbanov       KMP_CPU_PAUSE();
327f8f788b2SAndrey Churbanov     }
328f8f788b2SAndrey Churbanov   } else {
329f8f788b2SAndrey Churbanov     // Claim to be the initializer and do initializations
3307cc577a4SJonathan Peyton     __kmp_win32_cond_init(&th->th.th_suspend_cv);
3317cc577a4SJonathan Peyton     __kmp_win32_mutex_init(&th->th.th_suspend_mx);
332f8f788b2SAndrey Churbanov     KMP_ATOMIC_ST_REL(&th->th.th_suspend_init, new_value);
3337cc577a4SJonathan Peyton   }
3347cc577a4SJonathan Peyton }
3357cc577a4SJonathan Peyton 
__kmp_suspend_uninitialize_thread(kmp_info_t * th)3363041982dSJonathan Peyton void __kmp_suspend_uninitialize_thread(kmp_info_t *th) {
337f8f788b2SAndrey Churbanov   if (KMP_ATOMIC_LD_ACQ(&th->th.th_suspend_init)) {
3383041982dSJonathan Peyton     /* this means we have initialize the suspension pthread objects for this
3393041982dSJonathan Peyton        thread in this instance of the process */
3407cc577a4SJonathan Peyton     __kmp_win32_cond_destroy(&th->th.th_suspend_cv);
3417cc577a4SJonathan Peyton     __kmp_win32_mutex_destroy(&th->th.th_suspend_mx);
342f8f788b2SAndrey Churbanov     KMP_ATOMIC_ST_REL(&th->th.th_suspend_init, FALSE);
3437cc577a4SJonathan Peyton   }
3447cc577a4SJonathan Peyton }
3457cc577a4SJonathan Peyton 
__kmp_try_suspend_mx(kmp_info_t * th)3469b8bb323SJonathan Peyton int __kmp_try_suspend_mx(kmp_info_t *th) {
3479b8bb323SJonathan Peyton   return __kmp_win32_mutex_trylock(&th->th.th_suspend_mx);
3489b8bb323SJonathan Peyton }
3499b8bb323SJonathan Peyton 
__kmp_lock_suspend_mx(kmp_info_t * th)3509b8bb323SJonathan Peyton void __kmp_lock_suspend_mx(kmp_info_t *th) {
3519b8bb323SJonathan Peyton   __kmp_win32_mutex_lock(&th->th.th_suspend_mx);
3529b8bb323SJonathan Peyton }
3539b8bb323SJonathan Peyton 
__kmp_unlock_suspend_mx(kmp_info_t * th)3549b8bb323SJonathan Peyton void __kmp_unlock_suspend_mx(kmp_info_t *th) {
3559b8bb323SJonathan Peyton   __kmp_win32_mutex_unlock(&th->th.th_suspend_mx);
3569b8bb323SJonathan Peyton }
3579b8bb323SJonathan Peyton 
3587cc577a4SJonathan Peyton /* This routine puts the calling thread to sleep after setting the
3593041982dSJonathan Peyton    sleep bit for the indicated flag variable to true. */
3607cc577a4SJonathan Peyton template <class C>
__kmp_suspend_template(int th_gtid,C * flag)3613041982dSJonathan Peyton static inline void __kmp_suspend_template(int th_gtid, C *flag) {
3627cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[th_gtid];
3637cc577a4SJonathan Peyton   typename C::flag_t old_spin;
3647cc577a4SJonathan Peyton 
3653041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_suspend_template: T#%d enter for flag's loc(%p)\n",
3663041982dSJonathan Peyton                 th_gtid, flag->get()));
3677cc577a4SJonathan Peyton 
3687cc577a4SJonathan Peyton   __kmp_suspend_initialize_thread(th);
369e0665a90STerry Wilmarth   __kmp_lock_suspend_mx(th);
3707cc577a4SJonathan Peyton 
3713041982dSJonathan Peyton   KF_TRACE(10, ("__kmp_suspend_template: T#%d setting sleep bit for flag's"
3723041982dSJonathan Peyton                 " loc(%p)\n",
3737cc577a4SJonathan Peyton                 th_gtid, flag->get()));
3747cc577a4SJonathan Peyton 
3753041982dSJonathan Peyton   /* TODO: shouldn't this use release semantics to ensure that
3763041982dSJonathan Peyton      __kmp_suspend_initialize_thread gets called first? */
3777cc577a4SJonathan Peyton   old_spin = flag->set_sleeping();
378d8e4cb91STerry Wilmarth   TCW_PTR(th->th.th_sleep_loc, (void *)flag);
379d8e4cb91STerry Wilmarth   th->th.th_sleep_loc_type = flag->get_type();
3809b8bb323SJonathan Peyton   if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME &&
3819b8bb323SJonathan Peyton       __kmp_pause_status != kmp_soft_paused) {
3829b8bb323SJonathan Peyton     flag->unset_sleeping();
383d8e4cb91STerry Wilmarth     TCW_PTR(th->th.th_sleep_loc, NULL);
384d8e4cb91STerry Wilmarth     th->th.th_sleep_loc_type = flag_unset;
385e0665a90STerry Wilmarth     __kmp_unlock_suspend_mx(th);
3869b8bb323SJonathan Peyton     return;
3879b8bb323SJonathan Peyton   }
3887cc577a4SJonathan Peyton 
3893041982dSJonathan Peyton   KF_TRACE(5, ("__kmp_suspend_template: T#%d set sleep bit for flag's"
390498c4b6fSAndreyChurbanov                " loc(%p)==%u\n",
391498c4b6fSAndreyChurbanov                th_gtid, flag->get(), (unsigned int)flag->load()));
3927cc577a4SJonathan Peyton 
393d8e4cb91STerry Wilmarth   if (flag->done_check_val(old_spin) || flag->done_check()) {
394d8e4cb91STerry Wilmarth     flag->unset_sleeping();
395d8e4cb91STerry Wilmarth     TCW_PTR(th->th.th_sleep_loc, NULL);
396d8e4cb91STerry Wilmarth     th->th.th_sleep_loc_type = flag_unset;
3973041982dSJonathan Peyton     KF_TRACE(5, ("__kmp_suspend_template: T#%d false alarm, reset sleep bit "
3983041982dSJonathan Peyton                  "for flag's loc(%p)\n",
3997cc577a4SJonathan Peyton                  th_gtid, flag->get()));
4007cc577a4SJonathan Peyton   } else {
4017cc577a4SJonathan Peyton #ifdef DEBUG_SUSPEND
4027cc577a4SJonathan Peyton     __kmp_suspend_count++;
4037cc577a4SJonathan Peyton #endif
4043041982dSJonathan Peyton     /* Encapsulate in a loop as the documentation states that this may "with
4053041982dSJonathan Peyton        low probability" return when the condition variable has not been signaled
4063041982dSJonathan Peyton        or broadcast */
4077cc577a4SJonathan Peyton     int deactivated = FALSE;
408d8e4cb91STerry Wilmarth 
4097cc577a4SJonathan Peyton     while (flag->is_sleeping()) {
4103041982dSJonathan Peyton       KF_TRACE(15, ("__kmp_suspend_template: T#%d about to perform "
4113041982dSJonathan Peyton                     "kmp_win32_cond_wait()\n",
4127cc577a4SJonathan Peyton                     th_gtid));
4133041982dSJonathan Peyton       // Mark the thread as no longer active (only in the first iteration of the
4143041982dSJonathan Peyton       // loop).
4157cc577a4SJonathan Peyton       if (!deactivated) {
4167cc577a4SJonathan Peyton         th->th.th_active = FALSE;
4177cc577a4SJonathan Peyton         if (th->th.th_active_in_pool) {
4187cc577a4SJonathan Peyton           th->th.th_active_in_pool = FALSE;
41937e2ef54SJonathan Peyton           KMP_ATOMIC_DEC(&__kmp_thread_pool_active_nth);
4207cc577a4SJonathan Peyton           KMP_DEBUG_ASSERT(TCR_4(__kmp_thread_pool_active_nth) >= 0);
4217cc577a4SJonathan Peyton         }
4227cc577a4SJonathan Peyton         deactivated = TRUE;
4234eb90e89SJohannes Doerfert       }
42425073a4eSTerry Wilmarth 
425d8e4cb91STerry Wilmarth       KMP_DEBUG_ASSERT(th->th.th_sleep_loc);
426d8e4cb91STerry Wilmarth       KMP_DEBUG_ASSERT(th->th.th_sleep_loc_type == flag->get_type());
427d8e4cb91STerry Wilmarth 
428d8e4cb91STerry Wilmarth       __kmp_win32_cond_wait(&th->th.th_suspend_cv, &th->th.th_suspend_mx, th,
429d8e4cb91STerry Wilmarth                             flag);
430d8e4cb91STerry Wilmarth 
4317cc577a4SJonathan Peyton #ifdef KMP_DEBUG
4327cc577a4SJonathan Peyton       if (flag->is_sleeping()) {
4333041982dSJonathan Peyton         KF_TRACE(100,
4343041982dSJonathan Peyton                  ("__kmp_suspend_template: T#%d spurious wakeup\n", th_gtid));
4357cc577a4SJonathan Peyton       }
4367cc577a4SJonathan Peyton #endif /* KMP_DEBUG */
4377cc577a4SJonathan Peyton 
4387cc577a4SJonathan Peyton     } // while
4397cc577a4SJonathan Peyton 
440d8e4cb91STerry Wilmarth     // We may have had the loop variable set before entering the loop body;
441d8e4cb91STerry Wilmarth     // so we need to reset sleep_loc.
442d8e4cb91STerry Wilmarth     TCW_PTR(th->th.th_sleep_loc, NULL);
443d8e4cb91STerry Wilmarth     th->th.th_sleep_loc_type = flag_unset;
444d8e4cb91STerry Wilmarth 
445d8e4cb91STerry Wilmarth     KMP_DEBUG_ASSERT(!flag->is_sleeping());
446d8e4cb91STerry Wilmarth     KMP_DEBUG_ASSERT(!th->th.th_sleep_loc);
447d8e4cb91STerry Wilmarth 
4487cc577a4SJonathan Peyton     // Mark the thread as active again (if it was previous marked as inactive)
4497cc577a4SJonathan Peyton     if (deactivated) {
4507cc577a4SJonathan Peyton       th->th.th_active = TRUE;
4517cc577a4SJonathan Peyton       if (TCR_4(th->th.th_in_pool)) {
45237e2ef54SJonathan Peyton         KMP_ATOMIC_INC(&__kmp_thread_pool_active_nth);
4537cc577a4SJonathan Peyton         th->th.th_active_in_pool = TRUE;
4547cc577a4SJonathan Peyton       }
4557cc577a4SJonathan Peyton     }
4567cc577a4SJonathan Peyton   }
4577cc577a4SJonathan Peyton 
458e0665a90STerry Wilmarth   __kmp_unlock_suspend_mx(th);
4597cc577a4SJonathan Peyton   KF_TRACE(30, ("__kmp_suspend_template: T#%d exit\n", th_gtid));
4607cc577a4SJonathan Peyton }
4617cc577a4SJonathan Peyton 
462e0665a90STerry Wilmarth template <bool C, bool S>
__kmp_suspend_32(int th_gtid,kmp_flag_32<C,S> * flag)463e0665a90STerry Wilmarth void __kmp_suspend_32(int th_gtid, kmp_flag_32<C, S> *flag) {
4647cc577a4SJonathan Peyton   __kmp_suspend_template(th_gtid, flag);
4657cc577a4SJonathan Peyton }
466e0665a90STerry Wilmarth template <bool C, bool S>
__kmp_suspend_64(int th_gtid,kmp_flag_64<C,S> * flag)467e0665a90STerry Wilmarth void __kmp_suspend_64(int th_gtid, kmp_flag_64<C, S> *flag) {
4687cc577a4SJonathan Peyton   __kmp_suspend_template(th_gtid, flag);
4697cc577a4SJonathan Peyton }
470d8e4cb91STerry Wilmarth template <bool C, bool S>
__kmp_atomic_suspend_64(int th_gtid,kmp_atomic_flag_64<C,S> * flag)471d8e4cb91STerry Wilmarth void __kmp_atomic_suspend_64(int th_gtid, kmp_atomic_flag_64<C, S> *flag) {
472d8e4cb91STerry Wilmarth   __kmp_suspend_template(th_gtid, flag);
473d8e4cb91STerry Wilmarth }
__kmp_suspend_oncore(int th_gtid,kmp_flag_oncore * flag)4747cc577a4SJonathan Peyton void __kmp_suspend_oncore(int th_gtid, kmp_flag_oncore *flag) {
4757cc577a4SJonathan Peyton   __kmp_suspend_template(th_gtid, flag);
4767cc577a4SJonathan Peyton }
4777cc577a4SJonathan Peyton 
478e0665a90STerry Wilmarth template void __kmp_suspend_32<false, false>(int, kmp_flag_32<false, false> *);
479e0665a90STerry Wilmarth template void __kmp_suspend_64<false, true>(int, kmp_flag_64<false, true> *);
480e0665a90STerry Wilmarth template void __kmp_suspend_64<true, false>(int, kmp_flag_64<true, false> *);
481d8e4cb91STerry Wilmarth template void
482d8e4cb91STerry Wilmarth __kmp_atomic_suspend_64<false, true>(int, kmp_atomic_flag_64<false, true> *);
483d8e4cb91STerry Wilmarth template void
484d8e4cb91STerry Wilmarth __kmp_atomic_suspend_64<true, false>(int, kmp_atomic_flag_64<true, false> *);
485e0665a90STerry Wilmarth 
4867cc577a4SJonathan Peyton /* This routine signals the thread specified by target_gtid to wake up
4873041982dSJonathan Peyton    after setting the sleep bit indicated by the flag argument to FALSE */
4887cc577a4SJonathan Peyton template <class C>
__kmp_resume_template(int target_gtid,C * flag)4893041982dSJonathan Peyton static inline void __kmp_resume_template(int target_gtid, C *flag) {
4907cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[target_gtid];
4917cc577a4SJonathan Peyton 
4927cc577a4SJonathan Peyton #ifdef KMP_DEBUG
4937cc577a4SJonathan Peyton   int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
4947cc577a4SJonathan Peyton #endif
4957cc577a4SJonathan Peyton 
4963041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_resume_template: T#%d wants to wakeup T#%d enter\n",
4973041982dSJonathan Peyton                 gtid, target_gtid));
4987cc577a4SJonathan Peyton 
4997cc577a4SJonathan Peyton   __kmp_suspend_initialize_thread(th);
500e0665a90STerry Wilmarth   __kmp_lock_suspend_mx(th);
5017cc577a4SJonathan Peyton 
502d8e4cb91STerry Wilmarth   if (!flag || flag != th->th.th_sleep_loc) {
503d8e4cb91STerry Wilmarth     // coming from __kmp_null_resume_wrapper, or thread is now sleeping on a
504d8e4cb91STerry Wilmarth     // different location; wake up at new location
5057cc577a4SJonathan Peyton     flag = (C *)th->th.th_sleep_loc;
5067cc577a4SJonathan Peyton   }
5077cc577a4SJonathan Peyton 
5083041982dSJonathan Peyton   // First, check if the flag is null or its type has changed. If so, someone
5093041982dSJonathan Peyton   // else woke it up.
510d8e4cb91STerry Wilmarth   if (!flag || flag->get_type() != th->th.th_sleep_loc_type) {
511d8e4cb91STerry Wilmarth     // simply shows what flag was cast to
5123041982dSJonathan Peyton     KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already "
5133041982dSJonathan Peyton                  "awake: flag's loc(%p)\n",
5147cc577a4SJonathan Peyton                  gtid, target_gtid, NULL));
515e0665a90STerry Wilmarth     __kmp_unlock_suspend_mx(th);
5167cc577a4SJonathan Peyton     return;
5173041982dSJonathan Peyton   } else {
518d8e4cb91STerry Wilmarth     if (!flag->is_sleeping()) {
5193041982dSJonathan Peyton       KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already "
520d8e4cb91STerry Wilmarth                    "awake: flag's loc(%p): %u\n",
521d8e4cb91STerry Wilmarth                    gtid, target_gtid, flag->get(), (unsigned int)flag->load()));
522e0665a90STerry Wilmarth       __kmp_unlock_suspend_mx(th);
5237cc577a4SJonathan Peyton       return;
5247cc577a4SJonathan Peyton     }
5257cc577a4SJonathan Peyton   }
526d8e4cb91STerry Wilmarth   KMP_DEBUG_ASSERT(flag);
527d8e4cb91STerry Wilmarth   flag->unset_sleeping();
5287cc577a4SJonathan Peyton   TCW_PTR(th->th.th_sleep_loc, NULL);
529d8e4cb91STerry Wilmarth   th->th.th_sleep_loc_type = flag_unset;
530d8e4cb91STerry Wilmarth 
5313041982dSJonathan Peyton   KF_TRACE(5, ("__kmp_resume_template: T#%d about to wakeup T#%d, reset sleep "
5323041982dSJonathan Peyton                "bit for flag's loc(%p)\n",
5337cc577a4SJonathan Peyton                gtid, target_gtid, flag->get()));
5347cc577a4SJonathan Peyton 
5357cc577a4SJonathan Peyton   __kmp_win32_cond_signal(&th->th.th_suspend_cv);
536e0665a90STerry Wilmarth   __kmp_unlock_suspend_mx(th);
5377cc577a4SJonathan Peyton 
5383041982dSJonathan Peyton   KF_TRACE(30, ("__kmp_resume_template: T#%d exiting after signaling wake up"
5393041982dSJonathan Peyton                 " for T#%d\n",
5407cc577a4SJonathan Peyton                 gtid, target_gtid));
5417cc577a4SJonathan Peyton }
5427cc577a4SJonathan Peyton 
543e0665a90STerry Wilmarth template <bool C, bool S>
__kmp_resume_32(int target_gtid,kmp_flag_32<C,S> * flag)544e0665a90STerry Wilmarth void __kmp_resume_32(int target_gtid, kmp_flag_32<C, S> *flag) {
5457cc577a4SJonathan Peyton   __kmp_resume_template(target_gtid, flag);
5467cc577a4SJonathan Peyton }
547e0665a90STerry Wilmarth template <bool C, bool S>
__kmp_resume_64(int target_gtid,kmp_flag_64<C,S> * flag)548e0665a90STerry Wilmarth void __kmp_resume_64(int target_gtid, kmp_flag_64<C, S> *flag) {
5497cc577a4SJonathan Peyton   __kmp_resume_template(target_gtid, flag);
5507cc577a4SJonathan Peyton }
551d8e4cb91STerry Wilmarth template <bool C, bool S>
__kmp_atomic_resume_64(int target_gtid,kmp_atomic_flag_64<C,S> * flag)552d8e4cb91STerry Wilmarth void __kmp_atomic_resume_64(int target_gtid, kmp_atomic_flag_64<C, S> *flag) {
553d8e4cb91STerry Wilmarth   __kmp_resume_template(target_gtid, flag);
554d8e4cb91STerry Wilmarth }
__kmp_resume_oncore(int target_gtid,kmp_flag_oncore * flag)5557cc577a4SJonathan Peyton void __kmp_resume_oncore(int target_gtid, kmp_flag_oncore *flag) {
5567cc577a4SJonathan Peyton   __kmp_resume_template(target_gtid, flag);
5577cc577a4SJonathan Peyton }
5587cc577a4SJonathan Peyton 
559e0665a90STerry Wilmarth template void __kmp_resume_32<false, true>(int, kmp_flag_32<false, true> *);
560d8e4cb91STerry Wilmarth template void __kmp_resume_32<false, false>(int, kmp_flag_32<false, false> *);
561e0665a90STerry Wilmarth template void __kmp_resume_64<false, true>(int, kmp_flag_64<false, true> *);
562d8e4cb91STerry Wilmarth template void
563d8e4cb91STerry Wilmarth __kmp_atomic_resume_64<false, true>(int, kmp_atomic_flag_64<false, true> *);
564e0665a90STerry Wilmarth 
__kmp_yield()565e47d32f1SJonathan Peyton void __kmp_yield() { Sleep(0); }
5667cc577a4SJonathan Peyton 
__kmp_gtid_set_specific(int gtid)5673041982dSJonathan Peyton void __kmp_gtid_set_specific(int gtid) {
5687cc577a4SJonathan Peyton   if (__kmp_init_gtid) {
5693041982dSJonathan Peyton     KA_TRACE(50, ("__kmp_gtid_set_specific: T#%d key:%d\n", gtid,
5703041982dSJonathan Peyton                   __kmp_gtid_threadprivate_key));
571*1234011bSJonathan Peyton     kmp_intptr_t g = (kmp_intptr_t)gtid;
572*1234011bSJonathan Peyton     if (!TlsSetValue(__kmp_gtid_threadprivate_key, (LPVOID)(g + 1)))
5737cc577a4SJonathan Peyton       KMP_FATAL(TLSSetValueFailed);
5747cc577a4SJonathan Peyton   } else {
5757cc577a4SJonathan Peyton     KA_TRACE(50, ("__kmp_gtid_set_specific: runtime shutdown, returning\n"));
5767cc577a4SJonathan Peyton   }
5777cc577a4SJonathan Peyton }
5787cc577a4SJonathan Peyton 
__kmp_gtid_get_specific()5793041982dSJonathan Peyton int __kmp_gtid_get_specific() {
5807cc577a4SJonathan Peyton   int gtid;
5817cc577a4SJonathan Peyton   if (!__kmp_init_gtid) {
5823041982dSJonathan Peyton     KA_TRACE(50, ("__kmp_gtid_get_specific: runtime shutdown, returning "
5833041982dSJonathan Peyton                   "KMP_GTID_SHUTDOWN\n"));
5847cc577a4SJonathan Peyton     return KMP_GTID_SHUTDOWN;
5857cc577a4SJonathan Peyton   }
5867cc577a4SJonathan Peyton   gtid = (int)(kmp_intptr_t)TlsGetValue(__kmp_gtid_threadprivate_key);
5877cc577a4SJonathan Peyton   if (gtid == 0) {
5887cc577a4SJonathan Peyton     gtid = KMP_GTID_DNE;
5893041982dSJonathan Peyton   } else {
5907cc577a4SJonathan Peyton     gtid--;
5917cc577a4SJonathan Peyton   }
5927cc577a4SJonathan Peyton   KA_TRACE(50, ("__kmp_gtid_get_specific: key:%d gtid:%d\n",
5937cc577a4SJonathan Peyton                 __kmp_gtid_threadprivate_key, gtid));
5947cc577a4SJonathan Peyton   return gtid;
5957cc577a4SJonathan Peyton }
5967cc577a4SJonathan Peyton 
__kmp_affinity_bind_thread(int proc)5973041982dSJonathan Peyton void __kmp_affinity_bind_thread(int proc) {
5987cc577a4SJonathan Peyton   if (__kmp_num_proc_groups > 1) {
5997cc577a4SJonathan Peyton     // Form the GROUP_AFFINITY struct directly, rather than filling
6007cc577a4SJonathan Peyton     // out a bit vector and calling __kmp_set_system_affinity().
6017cc577a4SJonathan Peyton     GROUP_AFFINITY ga;
6023041982dSJonathan Peyton     KMP_DEBUG_ASSERT((proc >= 0) && (proc < (__kmp_num_proc_groups * CHAR_BIT *
6033041982dSJonathan Peyton                                              sizeof(DWORD_PTR))));
6047cc577a4SJonathan Peyton     ga.Group = proc / (CHAR_BIT * sizeof(DWORD_PTR));
6057cc577a4SJonathan Peyton     ga.Mask = (unsigned long long)1 << (proc % (CHAR_BIT * sizeof(DWORD_PTR)));
6067cc577a4SJonathan Peyton     ga.Reserved[0] = ga.Reserved[1] = ga.Reserved[2] = 0;
6077cc577a4SJonathan Peyton 
6087cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT(__kmp_SetThreadGroupAffinity != NULL);
6097cc577a4SJonathan Peyton     if (__kmp_SetThreadGroupAffinity(GetCurrentThread(), &ga, NULL) == 0) {
6107cc577a4SJonathan Peyton       DWORD error = GetLastError();
6117cc577a4SJonathan Peyton       if (__kmp_affinity_verbose) { // AC: continue silently if not verbose
6127cc577a4SJonathan Peyton         kmp_msg_t err_code = KMP_ERR(error);
6133041982dSJonathan Peyton         __kmp_msg(kmp_ms_warning, KMP_MSG(CantSetThreadAffMask), err_code,
6143041982dSJonathan Peyton                   __kmp_msg_null);
6157cc577a4SJonathan Peyton         if (__kmp_generate_warnings == kmp_warnings_off) {
6167cc577a4SJonathan Peyton           __kmp_str_free(&err_code.str);
6177cc577a4SJonathan Peyton         }
6187cc577a4SJonathan Peyton       }
6197cc577a4SJonathan Peyton     }
6207cc577a4SJonathan Peyton   } else {
6217cc577a4SJonathan Peyton     kmp_affin_mask_t *mask;
6227cc577a4SJonathan Peyton     KMP_CPU_ALLOC_ON_STACK(mask);
6237cc577a4SJonathan Peyton     KMP_CPU_ZERO(mask);
6247cc577a4SJonathan Peyton     KMP_CPU_SET(proc, mask);
6257cc577a4SJonathan Peyton     __kmp_set_system_affinity(mask, TRUE);
6267cc577a4SJonathan Peyton     KMP_CPU_FREE_FROM_STACK(mask);
6277cc577a4SJonathan Peyton   }
6287cc577a4SJonathan Peyton }
6297cc577a4SJonathan Peyton 
__kmp_affinity_determine_capable(const char * env_var)6303041982dSJonathan Peyton void __kmp_affinity_determine_capable(const char *env_var) {
631498c4b6fSAndreyChurbanov   // All versions of Windows* OS (since Win '95) support
632498c4b6fSAndreyChurbanov   // SetThreadAffinityMask().
6337cc577a4SJonathan Peyton 
6347cc577a4SJonathan Peyton #if KMP_GROUP_AFFINITY
6357cc577a4SJonathan Peyton   KMP_AFFINITY_ENABLE(__kmp_num_proc_groups * sizeof(DWORD_PTR));
6367cc577a4SJonathan Peyton #else
6377cc577a4SJonathan Peyton   KMP_AFFINITY_ENABLE(sizeof(DWORD_PTR));
6387cc577a4SJonathan Peyton #endif
6397cc577a4SJonathan Peyton 
6403041982dSJonathan Peyton   KA_TRACE(10, ("__kmp_affinity_determine_capable: "
6413041982dSJonathan Peyton                 "Windows* OS affinity interface functional (mask size = "
6423041982dSJonathan Peyton                 "%" KMP_SIZE_T_SPEC ").\n",
6433041982dSJonathan Peyton                 __kmp_affin_mask_size));
6447cc577a4SJonathan Peyton }
6457cc577a4SJonathan Peyton 
__kmp_read_cpu_time(void)6463041982dSJonathan Peyton double __kmp_read_cpu_time(void) {
6477cc577a4SJonathan Peyton   FILETIME CreationTime, ExitTime, KernelTime, UserTime;
6487cc577a4SJonathan Peyton   int status;
6497cc577a4SJonathan Peyton   double cpu_time;
6507cc577a4SJonathan Peyton 
6517cc577a4SJonathan Peyton   cpu_time = 0;
6527cc577a4SJonathan Peyton 
6533041982dSJonathan Peyton   status = GetProcessTimes(GetCurrentProcess(), &CreationTime, &ExitTime,
6543041982dSJonathan Peyton                            &KernelTime, &UserTime);
6557cc577a4SJonathan Peyton 
6567cc577a4SJonathan Peyton   if (status) {
6577cc577a4SJonathan Peyton     double sec = 0;
6587cc577a4SJonathan Peyton 
6597cc577a4SJonathan Peyton     sec += KernelTime.dwHighDateTime;
6607cc577a4SJonathan Peyton     sec += UserTime.dwHighDateTime;
6617cc577a4SJonathan Peyton 
6627cc577a4SJonathan Peyton     /* Shift left by 32 bits */
6637cc577a4SJonathan Peyton     sec *= (double)(1 << 16) * (double)(1 << 16);
6647cc577a4SJonathan Peyton 
6657cc577a4SJonathan Peyton     sec += KernelTime.dwLowDateTime;
6667cc577a4SJonathan Peyton     sec += UserTime.dwLowDateTime;
6677cc577a4SJonathan Peyton 
6687cc577a4SJonathan Peyton     cpu_time += (sec * 100.0) / KMP_NSEC_PER_SEC;
6697cc577a4SJonathan Peyton   }
6707cc577a4SJonathan Peyton 
6717cc577a4SJonathan Peyton   return cpu_time;
6727cc577a4SJonathan Peyton }
6737cc577a4SJonathan Peyton 
__kmp_read_system_info(struct kmp_sys_info * info)6743041982dSJonathan Peyton int __kmp_read_system_info(struct kmp_sys_info *info) {
6757cc577a4SJonathan Peyton   info->maxrss = 0; /* the maximum resident set size utilized (in kilobytes) */
6767cc577a4SJonathan Peyton   info->minflt = 0; /* the number of page faults serviced without any I/O */
6777cc577a4SJonathan Peyton   info->majflt = 0; /* the number of page faults serviced that required I/O */
6783041982dSJonathan Peyton   info->nswap = 0; // the number of times a process was "swapped" out of memory
6793041982dSJonathan Peyton   info->inblock = 0; // the number of times the file system had to perform input
6803041982dSJonathan Peyton   info->oublock = 0; // number of times the file system had to perform output
6817cc577a4SJonathan Peyton   info->nvcsw = 0; /* the number of times a context switch was voluntarily */
6827cc577a4SJonathan Peyton   info->nivcsw = 0; /* the number of times a context switch was forced */
6837cc577a4SJonathan Peyton 
6847cc577a4SJonathan Peyton   return 1;
6857cc577a4SJonathan Peyton }
6867cc577a4SJonathan Peyton 
__kmp_runtime_initialize(void)6873041982dSJonathan Peyton void __kmp_runtime_initialize(void) {
6887cc577a4SJonathan Peyton   SYSTEM_INFO info;
6897cc577a4SJonathan Peyton   kmp_str_buf_t path;
6907cc577a4SJonathan Peyton   UINT path_size;
6917cc577a4SJonathan Peyton 
6927cc577a4SJonathan Peyton   if (__kmp_init_runtime) {
6937cc577a4SJonathan Peyton     return;
694bd3a7633SJonathan Peyton   }
6957cc577a4SJonathan Peyton 
6967cc577a4SJonathan Peyton #if KMP_DYNAMIC_LIB
6977cc577a4SJonathan Peyton   /* Pin dynamic library for the lifetime of application */
6987cc577a4SJonathan Peyton   {
6997cc577a4SJonathan Peyton     // First, turn off error message boxes
7007cc577a4SJonathan Peyton     UINT err_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
7017cc577a4SJonathan Peyton     HMODULE h;
7023041982dSJonathan Peyton     BOOL ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
7033041982dSJonathan Peyton                                      GET_MODULE_HANDLE_EX_FLAG_PIN,
7047cc577a4SJonathan Peyton                                  (LPCTSTR)&__kmp_serial_initialize, &h);
705b3d84790SMartin Storsjö     (void)ret;
7067cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT2(h && ret, "OpenMP RTL cannot find itself loaded");
7077cc577a4SJonathan Peyton     SetErrorMode(err_mode); // Restore error mode
7087cc577a4SJonathan Peyton     KA_TRACE(10, ("__kmp_runtime_initialize: dynamic library pinned\n"));
7097cc577a4SJonathan Peyton   }
7107cc577a4SJonathan Peyton #endif
7117cc577a4SJonathan Peyton 
7127cc577a4SJonathan Peyton   InitializeCriticalSection(&__kmp_win32_section);
7137cc577a4SJonathan Peyton #if USE_ITT_BUILD
7147cc577a4SJonathan Peyton   __kmp_itt_system_object_created(&__kmp_win32_section, "Critical Section");
7157cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
7167cc577a4SJonathan Peyton   __kmp_initialize_system_tick();
7177cc577a4SJonathan Peyton 
7187cc577a4SJonathan Peyton #if (KMP_ARCH_X86 || KMP_ARCH_X86_64)
7197cc577a4SJonathan Peyton   if (!__kmp_cpuinfo.initialized) {
7207cc577a4SJonathan Peyton     __kmp_query_cpuid(&__kmp_cpuinfo);
721bd3a7633SJonathan Peyton   }
7227cc577a4SJonathan Peyton #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
7237cc577a4SJonathan Peyton 
7247cc577a4SJonathan Peyton /* Set up minimum number of threads to switch to TLS gtid */
7258b3842fcSJonathan Peyton #if KMP_OS_WINDOWS && !KMP_DYNAMIC_LIB
7267cc577a4SJonathan Peyton   // Windows* OS, static library.
7273041982dSJonathan Peyton   /* New thread may use stack space previously used by another thread,
7283041982dSJonathan Peyton      currently terminated. On Windows* OS, in case of static linking, we do not
7293041982dSJonathan Peyton      know the moment of thread termination, and our structures (__kmp_threads
7303041982dSJonathan Peyton      and __kmp_root arrays) are still keep info about dead threads. This leads
7313041982dSJonathan Peyton      to problem in __kmp_get_global_thread_id() function: it wrongly finds gtid
7323041982dSJonathan Peyton      (by searching through stack addresses of all known threads) for
7333041982dSJonathan Peyton      unregistered foreign tread.
7347cc577a4SJonathan Peyton 
7353041982dSJonathan Peyton      Setting __kmp_tls_gtid_min to 0 workarounds this problem:
7363041982dSJonathan Peyton      __kmp_get_global_thread_id() does not search through stacks, but get gtid
7373041982dSJonathan Peyton      from TLS immediately.
7387cc577a4SJonathan Peyton       --ln
7397cc577a4SJonathan Peyton   */
7407cc577a4SJonathan Peyton   __kmp_tls_gtid_min = 0;
7417cc577a4SJonathan Peyton #else
7427cc577a4SJonathan Peyton   __kmp_tls_gtid_min = KMP_TLS_GTID_MIN;
7437cc577a4SJonathan Peyton #endif
7447cc577a4SJonathan Peyton 
7457cc577a4SJonathan Peyton   /* for the static library */
7467cc577a4SJonathan Peyton   if (!__kmp_gtid_threadprivate_key) {
7477cc577a4SJonathan Peyton     __kmp_gtid_threadprivate_key = TlsAlloc();
7487cc577a4SJonathan Peyton     if (__kmp_gtid_threadprivate_key == TLS_OUT_OF_INDEXES) {
7497cc577a4SJonathan Peyton       KMP_FATAL(TLSOutOfIndexes);
7507cc577a4SJonathan Peyton     }
7517cc577a4SJonathan Peyton   }
7527cc577a4SJonathan Peyton 
7537cc577a4SJonathan Peyton   // Load ntdll.dll.
7543041982dSJonathan Peyton   /* Simple GetModuleHandle( "ntdll.dl" ) is not suitable due to security issue
7553041982dSJonathan Peyton      (see http://www.microsoft.com/technet/security/advisory/2269637.mspx). We
7563041982dSJonathan Peyton      have to specify full path to the library. */
7577cc577a4SJonathan Peyton   __kmp_str_buf_init(&path);
7587cc577a4SJonathan Peyton   path_size = GetSystemDirectory(path.str, path.size);
7597cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(path_size > 0);
7607cc577a4SJonathan Peyton   if (path_size >= path.size) {
7617cc577a4SJonathan Peyton     // Buffer is too short.  Expand the buffer and try again.
7627cc577a4SJonathan Peyton     __kmp_str_buf_reserve(&path, path_size);
7637cc577a4SJonathan Peyton     path_size = GetSystemDirectory(path.str, path.size);
7647cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT(path_size > 0);
765bd3a7633SJonathan Peyton   }
7667cc577a4SJonathan Peyton   if (path_size > 0 && path_size < path.size) {
7677cc577a4SJonathan Peyton     // Now we have system directory name in the buffer.
7687cc577a4SJonathan Peyton     // Append backslash and name of dll to form full path,
7697cc577a4SJonathan Peyton     path.used = path_size;
7707cc577a4SJonathan Peyton     __kmp_str_buf_print(&path, "\\%s", "ntdll.dll");
7717cc577a4SJonathan Peyton 
7727cc577a4SJonathan Peyton     // Now load ntdll using full path.
7737cc577a4SJonathan Peyton     ntdll = GetModuleHandle(path.str);
7747cc577a4SJonathan Peyton   }
7757cc577a4SJonathan Peyton 
7767cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(ntdll != NULL);
7777cc577a4SJonathan Peyton   if (ntdll != NULL) {
7783041982dSJonathan Peyton     NtQuerySystemInformation = (NtQuerySystemInformation_t)GetProcAddress(
7793041982dSJonathan Peyton         ntdll, "NtQuerySystemInformation");
7807cc577a4SJonathan Peyton   }
7817cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(NtQuerySystemInformation != NULL);
7827cc577a4SJonathan Peyton 
7837cc577a4SJonathan Peyton #if KMP_GROUP_AFFINITY
7847cc577a4SJonathan Peyton   // Load kernel32.dll.
7857cc577a4SJonathan Peyton   // Same caveat - must use full system path name.
7867cc577a4SJonathan Peyton   if (path_size > 0 && path_size < path.size) {
7877cc577a4SJonathan Peyton     // Truncate the buffer back to just the system path length,
7887cc577a4SJonathan Peyton     // discarding "\\ntdll.dll", and replacing it with "kernel32.dll".
7897cc577a4SJonathan Peyton     path.used = path_size;
7907cc577a4SJonathan Peyton     __kmp_str_buf_print(&path, "\\%s", "kernel32.dll");
7917cc577a4SJonathan Peyton 
7927cc577a4SJonathan Peyton     // Load kernel32.dll using full path.
7937cc577a4SJonathan Peyton     kernel32 = GetModuleHandle(path.str);
7947cc577a4SJonathan Peyton     KA_TRACE(10, ("__kmp_runtime_initialize: kernel32.dll = %s\n", path.str));
7957cc577a4SJonathan Peyton 
7967cc577a4SJonathan Peyton     // Load the function pointers to kernel32.dll routines
7977cc577a4SJonathan Peyton     // that may or may not exist on this system.
7987cc577a4SJonathan Peyton     if (kernel32 != NULL) {
7993041982dSJonathan Peyton       __kmp_GetActiveProcessorCount =
8003041982dSJonathan Peyton           (kmp_GetActiveProcessorCount_t)GetProcAddress(
8013041982dSJonathan Peyton               kernel32, "GetActiveProcessorCount");
8023041982dSJonathan Peyton       __kmp_GetActiveProcessorGroupCount =
8033041982dSJonathan Peyton           (kmp_GetActiveProcessorGroupCount_t)GetProcAddress(
8043041982dSJonathan Peyton               kernel32, "GetActiveProcessorGroupCount");
8053041982dSJonathan Peyton       __kmp_GetThreadGroupAffinity =
8063041982dSJonathan Peyton           (kmp_GetThreadGroupAffinity_t)GetProcAddress(
8073041982dSJonathan Peyton               kernel32, "GetThreadGroupAffinity");
8083041982dSJonathan Peyton       __kmp_SetThreadGroupAffinity =
8093041982dSJonathan Peyton           (kmp_SetThreadGroupAffinity_t)GetProcAddress(
8103041982dSJonathan Peyton               kernel32, "SetThreadGroupAffinity");
8117cc577a4SJonathan Peyton 
8123041982dSJonathan Peyton       KA_TRACE(10, ("__kmp_runtime_initialize: __kmp_GetActiveProcessorCount"
8133041982dSJonathan Peyton                     " = %p\n",
8143041982dSJonathan Peyton                     __kmp_GetActiveProcessorCount));
8153041982dSJonathan Peyton       KA_TRACE(10, ("__kmp_runtime_initialize: "
8163041982dSJonathan Peyton                     "__kmp_GetActiveProcessorGroupCount = %p\n",
8173041982dSJonathan Peyton                     __kmp_GetActiveProcessorGroupCount));
8183041982dSJonathan Peyton       KA_TRACE(10, ("__kmp_runtime_initialize:__kmp_GetThreadGroupAffinity"
8193041982dSJonathan Peyton                     " = %p\n",
8203041982dSJonathan Peyton                     __kmp_GetThreadGroupAffinity));
8213041982dSJonathan Peyton       KA_TRACE(10, ("__kmp_runtime_initialize: __kmp_SetThreadGroupAffinity"
8223041982dSJonathan Peyton                     " = %p\n",
8233041982dSJonathan Peyton                     __kmp_SetThreadGroupAffinity));
8243041982dSJonathan Peyton       KA_TRACE(10, ("__kmp_runtime_initialize: sizeof(kmp_affin_mask_t) = %d\n",
8253041982dSJonathan Peyton                     sizeof(kmp_affin_mask_t)));
8267cc577a4SJonathan Peyton 
8277cc577a4SJonathan Peyton       // See if group affinity is supported on this system.
8287cc577a4SJonathan Peyton       // If so, calculate the #groups and #procs.
8297cc577a4SJonathan Peyton       //
8307cc577a4SJonathan Peyton       // Group affinity was introduced with Windows* 7 OS and
8317cc577a4SJonathan Peyton       // Windows* Server 2008 R2 OS.
8323041982dSJonathan Peyton       if ((__kmp_GetActiveProcessorCount != NULL) &&
8333041982dSJonathan Peyton           (__kmp_GetActiveProcessorGroupCount != NULL) &&
8343041982dSJonathan Peyton           (__kmp_GetThreadGroupAffinity != NULL) &&
8353041982dSJonathan Peyton           (__kmp_SetThreadGroupAffinity != NULL) &&
8363041982dSJonathan Peyton           ((__kmp_num_proc_groups = __kmp_GetActiveProcessorGroupCount()) >
8373041982dSJonathan Peyton            1)) {
8387cc577a4SJonathan Peyton         // Calculate the total number of active OS procs.
8397cc577a4SJonathan Peyton         int i;
8407cc577a4SJonathan Peyton 
8413041982dSJonathan Peyton         KA_TRACE(10, ("__kmp_runtime_initialize: %d processor groups"
8423041982dSJonathan Peyton                       " detected\n",
8433041982dSJonathan Peyton                       __kmp_num_proc_groups));
8447cc577a4SJonathan Peyton 
8457cc577a4SJonathan Peyton         __kmp_xproc = 0;
8467cc577a4SJonathan Peyton 
8477cc577a4SJonathan Peyton         for (i = 0; i < __kmp_num_proc_groups; i++) {
8487cc577a4SJonathan Peyton           DWORD size = __kmp_GetActiveProcessorCount(i);
8497cc577a4SJonathan Peyton           __kmp_xproc += size;
8503041982dSJonathan Peyton           KA_TRACE(10, ("__kmp_runtime_initialize: proc group %d size = %d\n",
8513041982dSJonathan Peyton                         i, size));
8527cc577a4SJonathan Peyton         }
8533041982dSJonathan Peyton       } else {
8543041982dSJonathan Peyton         KA_TRACE(10, ("__kmp_runtime_initialize: %d processor groups"
8553041982dSJonathan Peyton                       " detected\n",
8563041982dSJonathan Peyton                       __kmp_num_proc_groups));
8577cc577a4SJonathan Peyton       }
8587cc577a4SJonathan Peyton     }
8597cc577a4SJonathan Peyton   }
8607cc577a4SJonathan Peyton   if (__kmp_num_proc_groups <= 1) {
8617cc577a4SJonathan Peyton     GetSystemInfo(&info);
8627cc577a4SJonathan Peyton     __kmp_xproc = info.dwNumberOfProcessors;
8637cc577a4SJonathan Peyton   }
8647cc577a4SJonathan Peyton #else
865b3d84790SMartin Storsjö   (void)kernel32;
8667cc577a4SJonathan Peyton   GetSystemInfo(&info);
8677cc577a4SJonathan Peyton   __kmp_xproc = info.dwNumberOfProcessors;
8687cc577a4SJonathan Peyton #endif /* KMP_GROUP_AFFINITY */
8697cc577a4SJonathan Peyton 
8707cc577a4SJonathan Peyton   // If the OS said there were 0 procs, take a guess and use a value of 2.
8717cc577a4SJonathan Peyton   // This is done for Linux* OS, also.  Do we need error / warning?
8727cc577a4SJonathan Peyton   if (__kmp_xproc <= 0) {
8737cc577a4SJonathan Peyton     __kmp_xproc = 2;
8747cc577a4SJonathan Peyton   }
8757cc577a4SJonathan Peyton 
8763041982dSJonathan Peyton   KA_TRACE(5,
8773041982dSJonathan Peyton            ("__kmp_runtime_initialize: total processors = %d\n", __kmp_xproc));
8787cc577a4SJonathan Peyton 
8797cc577a4SJonathan Peyton   __kmp_str_buf_free(&path);
8807cc577a4SJonathan Peyton 
8817cc577a4SJonathan Peyton #if USE_ITT_BUILD
8827cc577a4SJonathan Peyton   __kmp_itt_initialize();
8837cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
8847cc577a4SJonathan Peyton 
8857cc577a4SJonathan Peyton   __kmp_init_runtime = TRUE;
8867cc577a4SJonathan Peyton } // __kmp_runtime_initialize
8877cc577a4SJonathan Peyton 
__kmp_runtime_destroy(void)8883041982dSJonathan Peyton void __kmp_runtime_destroy(void) {
8897cc577a4SJonathan Peyton   if (!__kmp_init_runtime) {
8907cc577a4SJonathan Peyton     return;
8917cc577a4SJonathan Peyton   }
8927cc577a4SJonathan Peyton 
8937cc577a4SJonathan Peyton #if USE_ITT_BUILD
8947cc577a4SJonathan Peyton   __kmp_itt_destroy();
8957cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
8967cc577a4SJonathan Peyton 
8977cc577a4SJonathan Peyton   /* we can't DeleteCriticalsection( & __kmp_win32_section ); */
8987cc577a4SJonathan Peyton   /* due to the KX_TRACE() commands */
8997cc577a4SJonathan Peyton   KA_TRACE(40, ("__kmp_runtime_destroy\n"));
9007cc577a4SJonathan Peyton 
9017cc577a4SJonathan Peyton   if (__kmp_gtid_threadprivate_key) {
9027cc577a4SJonathan Peyton     TlsFree(__kmp_gtid_threadprivate_key);
9037cc577a4SJonathan Peyton     __kmp_gtid_threadprivate_key = 0;
9047cc577a4SJonathan Peyton   }
9057cc577a4SJonathan Peyton 
9067cc577a4SJonathan Peyton   __kmp_affinity_uninitialize();
9077cc577a4SJonathan Peyton   DeleteCriticalSection(&__kmp_win32_section);
9087cc577a4SJonathan Peyton 
9097cc577a4SJonathan Peyton   ntdll = NULL;
9107cc577a4SJonathan Peyton   NtQuerySystemInformation = NULL;
9117cc577a4SJonathan Peyton 
9127cc577a4SJonathan Peyton #if KMP_ARCH_X86_64
9137cc577a4SJonathan Peyton   kernel32 = NULL;
9147cc577a4SJonathan Peyton   __kmp_GetActiveProcessorCount = NULL;
9157cc577a4SJonathan Peyton   __kmp_GetActiveProcessorGroupCount = NULL;
9167cc577a4SJonathan Peyton   __kmp_GetThreadGroupAffinity = NULL;
9177cc577a4SJonathan Peyton   __kmp_SetThreadGroupAffinity = NULL;
9187cc577a4SJonathan Peyton #endif // KMP_ARCH_X86_64
9197cc577a4SJonathan Peyton 
9207cc577a4SJonathan Peyton   __kmp_init_runtime = FALSE;
9217cc577a4SJonathan Peyton }
9227cc577a4SJonathan Peyton 
__kmp_terminate_thread(int gtid)9233041982dSJonathan Peyton void __kmp_terminate_thread(int gtid) {
9247cc577a4SJonathan Peyton   kmp_info_t *th = __kmp_threads[gtid];
9257cc577a4SJonathan Peyton 
9263041982dSJonathan Peyton   if (!th)
9273041982dSJonathan Peyton     return;
9287cc577a4SJonathan Peyton 
9297cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_terminate_thread: kill (%d)\n", gtid));
9307cc577a4SJonathan Peyton 
9317cc577a4SJonathan Peyton   if (TerminateThread(th->th.th_info.ds.ds_thread, (DWORD)-1) == FALSE) {
9327cc577a4SJonathan Peyton     /* It's OK, the thread may have exited already */
9337cc577a4SJonathan Peyton   }
9347cc577a4SJonathan Peyton   __kmp_free_handle(th->th.th_info.ds.ds_thread);
9357cc577a4SJonathan Peyton }
9367cc577a4SJonathan Peyton 
__kmp_clear_system_time(void)9373041982dSJonathan Peyton void __kmp_clear_system_time(void) {
9387cc577a4SJonathan Peyton   LARGE_INTEGER time;
939*1234011bSJonathan Peyton   QueryPerformanceCounter(&time);
9407cc577a4SJonathan Peyton   __kmp_win32_time = (kmp_int64)time.QuadPart;
9417cc577a4SJonathan Peyton }
9427cc577a4SJonathan Peyton 
__kmp_initialize_system_tick(void)9433041982dSJonathan Peyton void __kmp_initialize_system_tick(void) {
9447cc577a4SJonathan Peyton   {
9457cc577a4SJonathan Peyton     BOOL status;
9467cc577a4SJonathan Peyton     LARGE_INTEGER freq;
9477cc577a4SJonathan Peyton 
9487cc577a4SJonathan Peyton     status = QueryPerformanceFrequency(&freq);
9497cc577a4SJonathan Peyton     if (!status) {
9507cc577a4SJonathan Peyton       DWORD error = GetLastError();
9516a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(FunctionError, "QueryPerformanceFrequency()"),
9523041982dSJonathan Peyton                   KMP_ERR(error), __kmp_msg_null);
9537cc577a4SJonathan Peyton 
9543041982dSJonathan Peyton     } else {
9557cc577a4SJonathan Peyton       __kmp_win32_tick = ((double)1.0) / (double)freq.QuadPart;
9567cc577a4SJonathan Peyton     }
9577cc577a4SJonathan Peyton   }
9587cc577a4SJonathan Peyton }
9597cc577a4SJonathan Peyton 
9607cc577a4SJonathan Peyton /* Calculate the elapsed wall clock time for the user */
9617cc577a4SJonathan Peyton 
__kmp_elapsed(double * t)9623041982dSJonathan Peyton void __kmp_elapsed(double *t) {
9637cc577a4SJonathan Peyton   LARGE_INTEGER now;
964*1234011bSJonathan Peyton   QueryPerformanceCounter(&now);
9657cc577a4SJonathan Peyton   *t = ((double)now.QuadPart) * __kmp_win32_tick;
9667cc577a4SJonathan Peyton }
9677cc577a4SJonathan Peyton 
9687cc577a4SJonathan Peyton /* Calculate the elapsed wall clock tick for the user */
9697cc577a4SJonathan Peyton 
__kmp_elapsed_tick(double * t)9703041982dSJonathan Peyton void __kmp_elapsed_tick(double *t) { *t = __kmp_win32_tick; }
9717cc577a4SJonathan Peyton 
__kmp_read_system_time(double * delta)9723041982dSJonathan Peyton void __kmp_read_system_time(double *delta) {
9737cc577a4SJonathan Peyton   if (delta != NULL) {
9747cc577a4SJonathan Peyton     LARGE_INTEGER now;
975*1234011bSJonathan Peyton     QueryPerformanceCounter(&now);
9763041982dSJonathan Peyton     *delta = ((double)(((kmp_int64)now.QuadPart) - __kmp_win32_time)) *
9773041982dSJonathan Peyton              __kmp_win32_tick;
9787cc577a4SJonathan Peyton   }
9797cc577a4SJonathan Peyton }
9807cc577a4SJonathan Peyton 
9817cc577a4SJonathan Peyton /* Return the current time stamp in nsec */
__kmp_now_nsec()9823041982dSJonathan Peyton kmp_uint64 __kmp_now_nsec() {
9837cc577a4SJonathan Peyton   LARGE_INTEGER now;
9847cc577a4SJonathan Peyton   QueryPerformanceCounter(&now);
9857cc577a4SJonathan Peyton   return 1e9 * __kmp_win32_tick * now.QuadPart;
9867cc577a4SJonathan Peyton }
9877cc577a4SJonathan Peyton 
__kmp_launch_worker(void * arg)988498c4b6fSAndreyChurbanov extern "C" void *__stdcall __kmp_launch_worker(void *arg) {
9897cc577a4SJonathan Peyton   volatile void *stack_data;
9907cc577a4SJonathan Peyton   void *exit_val;
9917cc577a4SJonathan Peyton   void *padding = 0;
9927cc577a4SJonathan Peyton   kmp_info_t *this_thr = (kmp_info_t *)arg;
9937cc577a4SJonathan Peyton   int gtid;
9947cc577a4SJonathan Peyton 
9957cc577a4SJonathan Peyton   gtid = this_thr->th.th_info.ds.ds_gtid;
9967cc577a4SJonathan Peyton   __kmp_gtid_set_specific(gtid);
9977cc577a4SJonathan Peyton #ifdef KMP_TDATA_GTID
9987cc577a4SJonathan Peyton #error "This define causes problems with LoadLibrary() + declspec(thread) " \
9997cc577a4SJonathan Peyton         "on Windows* OS.  See CQ50564, tests kmp_load_library*.c and this MSDN " \
10007cc577a4SJonathan Peyton         "reference: http://support.microsoft.com/kb/118816"
10017cc577a4SJonathan Peyton //__kmp_gtid = gtid;
10027cc577a4SJonathan Peyton #endif
10037cc577a4SJonathan Peyton 
10047cc577a4SJonathan Peyton #if USE_ITT_BUILD
10057cc577a4SJonathan Peyton   __kmp_itt_thread_name(gtid);
10067cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
10077cc577a4SJonathan Peyton 
10087cc577a4SJonathan Peyton   __kmp_affinity_set_init_mask(gtid, FALSE);
10097cc577a4SJonathan Peyton 
10107cc577a4SJonathan Peyton #if KMP_ARCH_X86 || KMP_ARCH_X86_64
10113041982dSJonathan Peyton   // Set FP control regs to be a copy of the parallel initialization thread's.
10127cc577a4SJonathan Peyton   __kmp_clear_x87_fpu_status_word();
10137cc577a4SJonathan Peyton   __kmp_load_x87_fpu_control_word(&__kmp_init_x87_fpu_control_word);
10147cc577a4SJonathan Peyton   __kmp_load_mxcsr(&__kmp_init_mxcsr);
10157cc577a4SJonathan Peyton #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
10167cc577a4SJonathan Peyton 
10177cc577a4SJonathan Peyton   if (__kmp_stkoffset > 0 && gtid > 0) {
10187cc577a4SJonathan Peyton     padding = KMP_ALLOCA(gtid * __kmp_stkoffset);
1019*1234011bSJonathan Peyton     (void)padding;
10207cc577a4SJonathan Peyton   }
10217cc577a4SJonathan Peyton 
10227cc577a4SJonathan Peyton   KMP_FSYNC_RELEASING(&this_thr->th.th_info.ds.ds_alive);
10237cc577a4SJonathan Peyton   this_thr->th.th_info.ds.ds_thread_id = GetCurrentThreadId();
10247cc577a4SJonathan Peyton   TCW_4(this_thr->th.th_info.ds.ds_alive, TRUE);
10257cc577a4SJonathan Peyton 
10263041982dSJonathan Peyton   if (TCR_4(__kmp_gtid_mode) <
10273041982dSJonathan Peyton       2) { // check stack only if it is used to get gtid
10287cc577a4SJonathan Peyton     TCW_PTR(this_thr->th.th_info.ds.ds_stackbase, &stack_data);
10297cc577a4SJonathan Peyton     KMP_ASSERT(this_thr->th.th_info.ds.ds_stackgrow == FALSE);
10307cc577a4SJonathan Peyton     __kmp_check_stack_overlap(this_thr);
10317cc577a4SJonathan Peyton   }
10327cc577a4SJonathan Peyton   KMP_MB();
10337cc577a4SJonathan Peyton   exit_val = __kmp_launch_thread(this_thr);
10347cc577a4SJonathan Peyton   KMP_FSYNC_RELEASING(&this_thr->th.th_info.ds.ds_alive);
10357cc577a4SJonathan Peyton   TCW_4(this_thr->th.th_info.ds.ds_alive, FALSE);
10367cc577a4SJonathan Peyton   KMP_MB();
10377cc577a4SJonathan Peyton   return exit_val;
10387cc577a4SJonathan Peyton }
10397cc577a4SJonathan Peyton 
10407cc577a4SJonathan Peyton #if KMP_USE_MONITOR
10417cc577a4SJonathan Peyton /* The monitor thread controls all of the threads in the complex */
10427cc577a4SJonathan Peyton 
__kmp_launch_monitor(void * arg)10433041982dSJonathan Peyton void *__stdcall __kmp_launch_monitor(void *arg) {
10447cc577a4SJonathan Peyton   DWORD wait_status;
10457cc577a4SJonathan Peyton   kmp_thread_t monitor;
10467cc577a4SJonathan Peyton   int status;
10477cc577a4SJonathan Peyton   int interval;
10487cc577a4SJonathan Peyton   kmp_info_t *this_thr = (kmp_info_t *)arg;
10497cc577a4SJonathan Peyton 
10507cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(__kmp_init_monitor);
10513041982dSJonathan Peyton   TCW_4(__kmp_init_monitor, 2); // AC: Signal library that monitor has started
10527cc577a4SJonathan Peyton   // TODO: hide "2" in enum (like {true,false,started})
10537cc577a4SJonathan Peyton   this_thr->th.th_info.ds.ds_thread_id = GetCurrentThreadId();
10547cc577a4SJonathan Peyton   TCW_4(this_thr->th.th_info.ds.ds_alive, TRUE);
10557cc577a4SJonathan Peyton 
10567cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
10577cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_launch_monitor: launched\n"));
10587cc577a4SJonathan Peyton 
10597cc577a4SJonathan Peyton   monitor = GetCurrentThread();
10607cc577a4SJonathan Peyton 
10617cc577a4SJonathan Peyton   /* set thread priority */
10627cc577a4SJonathan Peyton   status = SetThreadPriority(monitor, THREAD_PRIORITY_HIGHEST);
10637cc577a4SJonathan Peyton   if (!status) {
10647cc577a4SJonathan Peyton     DWORD error = GetLastError();
10656a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantSetThreadPriority), KMP_ERR(error), __kmp_msg_null);
10667cc577a4SJonathan Peyton   }
10677cc577a4SJonathan Peyton 
10687cc577a4SJonathan Peyton   /* register us as monitor */
10697cc577a4SJonathan Peyton   __kmp_gtid_set_specific(KMP_GTID_MONITOR);
10707cc577a4SJonathan Peyton #ifdef KMP_TDATA_GTID
10717cc577a4SJonathan Peyton #error "This define causes problems with LoadLibrary() + declspec(thread) " \
10727cc577a4SJonathan Peyton         "on Windows* OS.  See CQ50564, tests kmp_load_library*.c and this MSDN " \
10737cc577a4SJonathan Peyton         "reference: http://support.microsoft.com/kb/118816"
10747cc577a4SJonathan Peyton //__kmp_gtid = KMP_GTID_MONITOR;
10757cc577a4SJonathan Peyton #endif
10767cc577a4SJonathan Peyton 
10777cc577a4SJonathan Peyton #if USE_ITT_BUILD
10783041982dSJonathan Peyton   __kmp_itt_thread_ignore(); // Instruct Intel(R) Threading Tools to ignore
10793041982dSJonathan Peyton // monitor thread.
10807cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
10817cc577a4SJonathan Peyton 
10827cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
10837cc577a4SJonathan Peyton 
10847cc577a4SJonathan Peyton   interval = (1000 / __kmp_monitor_wakeups); /* in milliseconds */
10857cc577a4SJonathan Peyton 
10867cc577a4SJonathan Peyton   while (!TCR_4(__kmp_global.g.g_done)) {
10877cc577a4SJonathan Peyton     /*  This thread monitors the state of the system */
10887cc577a4SJonathan Peyton 
10897cc577a4SJonathan Peyton     KA_TRACE(15, ("__kmp_launch_monitor: update\n"));
10907cc577a4SJonathan Peyton 
10917cc577a4SJonathan Peyton     wait_status = WaitForSingleObject(__kmp_monitor_ev, interval);
10927cc577a4SJonathan Peyton 
10937cc577a4SJonathan Peyton     if (wait_status == WAIT_TIMEOUT) {
10947cc577a4SJonathan Peyton       TCW_4(__kmp_global.g.g_time.dt.t_value,
10957cc577a4SJonathan Peyton             TCR_4(__kmp_global.g.g_time.dt.t_value) + 1);
10967cc577a4SJonathan Peyton     }
10977cc577a4SJonathan Peyton 
10987cc577a4SJonathan Peyton     KMP_MB(); /* Flush all pending memory write invalidates.  */
10997cc577a4SJonathan Peyton   }
11007cc577a4SJonathan Peyton 
11017cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_launch_monitor: finished\n"));
11027cc577a4SJonathan Peyton 
11037cc577a4SJonathan Peyton   status = SetThreadPriority(monitor, THREAD_PRIORITY_NORMAL);
11047cc577a4SJonathan Peyton   if (!status) {
11057cc577a4SJonathan Peyton     DWORD error = GetLastError();
11066a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantSetThreadPriority), KMP_ERR(error), __kmp_msg_null);
11077cc577a4SJonathan Peyton   }
11087cc577a4SJonathan Peyton 
11097cc577a4SJonathan Peyton   if (__kmp_global.g.g_abort != 0) {
11107cc577a4SJonathan Peyton     /* now we need to terminate the worker threads   */
11117cc577a4SJonathan Peyton     /* the value of t_abort is the signal we caught */
11127cc577a4SJonathan Peyton     int gtid;
11137cc577a4SJonathan Peyton 
11143041982dSJonathan Peyton     KA_TRACE(10, ("__kmp_launch_monitor: terminate sig=%d\n",
11153041982dSJonathan Peyton                   (__kmp_global.g.g_abort)));
11167cc577a4SJonathan Peyton 
11177cc577a4SJonathan Peyton     /* terminate the OpenMP worker threads */
11187cc577a4SJonathan Peyton     /* TODO this is not valid for sibling threads!!
11197cc577a4SJonathan Peyton      * the uber master might not be 0 anymore.. */
11207cc577a4SJonathan Peyton     for (gtid = 1; gtid < __kmp_threads_capacity; ++gtid)
11217cc577a4SJonathan Peyton       __kmp_terminate_thread(gtid);
11227cc577a4SJonathan Peyton 
11237cc577a4SJonathan Peyton     __kmp_cleanup();
11247cc577a4SJonathan Peyton 
11257cc577a4SJonathan Peyton     Sleep(0);
11267cc577a4SJonathan Peyton 
11273041982dSJonathan Peyton     KA_TRACE(10,
11283041982dSJonathan Peyton              ("__kmp_launch_monitor: raise sig=%d\n", __kmp_global.g.g_abort));
11297cc577a4SJonathan Peyton 
11307cc577a4SJonathan Peyton     if (__kmp_global.g.g_abort > 0) {
11317cc577a4SJonathan Peyton       raise(__kmp_global.g.g_abort);
11327cc577a4SJonathan Peyton     }
11337cc577a4SJonathan Peyton   }
11347cc577a4SJonathan Peyton 
11357cc577a4SJonathan Peyton   TCW_4(this_thr->th.th_info.ds.ds_alive, FALSE);
11367cc577a4SJonathan Peyton 
11377cc577a4SJonathan Peyton   KMP_MB();
11387cc577a4SJonathan Peyton   return arg;
11397cc577a4SJonathan Peyton }
11407cc577a4SJonathan Peyton #endif
11417cc577a4SJonathan Peyton 
__kmp_create_worker(int gtid,kmp_info_t * th,size_t stack_size)11423041982dSJonathan Peyton void __kmp_create_worker(int gtid, kmp_info_t *th, size_t stack_size) {
11437cc577a4SJonathan Peyton   kmp_thread_t handle;
11447cc577a4SJonathan Peyton   DWORD idThread;
11457cc577a4SJonathan Peyton 
11467cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_worker: try to create thread (%d)\n", gtid));
11477cc577a4SJonathan Peyton 
11487cc577a4SJonathan Peyton   th->th.th_info.ds.ds_gtid = gtid;
11497cc577a4SJonathan Peyton 
11507cc577a4SJonathan Peyton   if (KMP_UBER_GTID(gtid)) {
11517cc577a4SJonathan Peyton     int stack_data;
11527cc577a4SJonathan Peyton 
11533041982dSJonathan Peyton     /* TODO: GetCurrentThread() returns a pseudo-handle that is unsuitable for
11543041982dSJonathan Peyton        other threads to use. Is it appropriate to just use GetCurrentThread?
11553041982dSJonathan Peyton        When should we close this handle?  When unregistering the root? */
11567cc577a4SJonathan Peyton     {
11577cc577a4SJonathan Peyton       BOOL rc;
11583041982dSJonathan Peyton       rc = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
11593041982dSJonathan Peyton                            GetCurrentProcess(), &th->th.th_info.ds.ds_thread, 0,
11603041982dSJonathan Peyton                            FALSE, DUPLICATE_SAME_ACCESS);
11617cc577a4SJonathan Peyton       KMP_ASSERT(rc);
11623041982dSJonathan Peyton       KA_TRACE(10, (" __kmp_create_worker: ROOT Handle duplicated, th = %p, "
11633041982dSJonathan Peyton                     "handle = %" KMP_UINTPTR_SPEC "\n",
11643041982dSJonathan Peyton                     (LPVOID)th, th->th.th_info.ds.ds_thread));
11657cc577a4SJonathan Peyton       th->th.th_info.ds.ds_thread_id = GetCurrentThreadId();
11667cc577a4SJonathan Peyton     }
11673041982dSJonathan Peyton     if (TCR_4(__kmp_gtid_mode) < 2) { // check stack only if used to get gtid
11687cc577a4SJonathan Peyton       /* we will dynamically update the stack range if gtid_mode == 1 */
11697cc577a4SJonathan Peyton       TCW_PTR(th->th.th_info.ds.ds_stackbase, &stack_data);
11707cc577a4SJonathan Peyton       TCW_PTR(th->th.th_info.ds.ds_stacksize, 0);
11717cc577a4SJonathan Peyton       TCW_4(th->th.th_info.ds.ds_stackgrow, TRUE);
11727cc577a4SJonathan Peyton       __kmp_check_stack_overlap(th);
11737cc577a4SJonathan Peyton     }
11743041982dSJonathan Peyton   } else {
11757cc577a4SJonathan Peyton     KMP_MB(); /* Flush all pending memory write invalidates.  */
11767cc577a4SJonathan Peyton 
11777cc577a4SJonathan Peyton     /* Set stack size for this thread now. */
11783041982dSJonathan Peyton     KA_TRACE(10,
11793041982dSJonathan Peyton              ("__kmp_create_worker: stack_size = %" KMP_SIZE_T_SPEC " bytes\n",
11803041982dSJonathan Peyton               stack_size));
11817cc577a4SJonathan Peyton 
11827cc577a4SJonathan Peyton     stack_size += gtid * __kmp_stkoffset;
11837cc577a4SJonathan Peyton 
11847cc577a4SJonathan Peyton     TCW_PTR(th->th.th_info.ds.ds_stacksize, stack_size);
11857cc577a4SJonathan Peyton     TCW_4(th->th.th_info.ds.ds_stackgrow, FALSE);
11867cc577a4SJonathan Peyton 
11873041982dSJonathan Peyton     KA_TRACE(10,
11883041982dSJonathan Peyton              ("__kmp_create_worker: (before) stack_size = %" KMP_SIZE_T_SPEC
11893041982dSJonathan Peyton               " bytes, &__kmp_launch_worker = %p, th = %p, &idThread = %p\n",
11903041982dSJonathan Peyton               (SIZE_T)stack_size, (LPTHREAD_START_ROUTINE)&__kmp_launch_worker,
11917cc577a4SJonathan Peyton               (LPVOID)th, &idThread));
11927cc577a4SJonathan Peyton 
11933041982dSJonathan Peyton     handle = CreateThread(
11943041982dSJonathan Peyton         NULL, (SIZE_T)stack_size, (LPTHREAD_START_ROUTINE)__kmp_launch_worker,
11957cc577a4SJonathan Peyton         (LPVOID)th, STACK_SIZE_PARAM_IS_A_RESERVATION, &idThread);
11967cc577a4SJonathan Peyton 
11973041982dSJonathan Peyton     KA_TRACE(10,
11983041982dSJonathan Peyton              ("__kmp_create_worker: (after) stack_size = %" KMP_SIZE_T_SPEC
11997cc577a4SJonathan Peyton               " bytes, &__kmp_launch_worker = %p, th = %p, "
12007cc577a4SJonathan Peyton               "idThread = %u, handle = %" KMP_UINTPTR_SPEC "\n",
12013041982dSJonathan Peyton               (SIZE_T)stack_size, (LPTHREAD_START_ROUTINE)&__kmp_launch_worker,
12027cc577a4SJonathan Peyton               (LPVOID)th, idThread, handle));
12037cc577a4SJonathan Peyton 
12047cc577a4SJonathan Peyton     if (handle == 0) {
12057cc577a4SJonathan Peyton       DWORD error = GetLastError();
12066a393f75SJonathan Peyton       __kmp_fatal(KMP_MSG(CantCreateThread), KMP_ERR(error), __kmp_msg_null);
12077cc577a4SJonathan Peyton     } else {
12087cc577a4SJonathan Peyton       th->th.th_info.ds.ds_thread = handle;
12097cc577a4SJonathan Peyton     }
12107cc577a4SJonathan Peyton 
12117cc577a4SJonathan Peyton     KMP_MB(); /* Flush all pending memory write invalidates.  */
12127cc577a4SJonathan Peyton   }
12137cc577a4SJonathan Peyton 
12147cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_worker: done creating thread (%d)\n", gtid));
12157cc577a4SJonathan Peyton }
12167cc577a4SJonathan Peyton 
__kmp_still_running(kmp_info_t * th)12173041982dSJonathan Peyton int __kmp_still_running(kmp_info_t *th) {
12187cc577a4SJonathan Peyton   return (WAIT_TIMEOUT == WaitForSingleObject(th->th.th_info.ds.ds_thread, 0));
12197cc577a4SJonathan Peyton }
12207cc577a4SJonathan Peyton 
12217cc577a4SJonathan Peyton #if KMP_USE_MONITOR
__kmp_create_monitor(kmp_info_t * th)12223041982dSJonathan Peyton void __kmp_create_monitor(kmp_info_t *th) {
12237cc577a4SJonathan Peyton   kmp_thread_t handle;
12247cc577a4SJonathan Peyton   DWORD idThread;
12257cc577a4SJonathan Peyton   int ideal, new_ideal;
12267cc577a4SJonathan Peyton 
12277cc577a4SJonathan Peyton   if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME) {
12287cc577a4SJonathan Peyton     // We don't need monitor thread in case of MAX_BLOCKTIME
12293041982dSJonathan Peyton     KA_TRACE(10, ("__kmp_create_monitor: skipping monitor thread because of "
12303041982dSJonathan Peyton                   "MAX blocktime\n"));
12317cc577a4SJonathan Peyton     th->th.th_info.ds.ds_tid = 0; // this makes reap_monitor no-op
12327cc577a4SJonathan Peyton     th->th.th_info.ds.ds_gtid = 0;
12337cc577a4SJonathan Peyton     TCW_4(__kmp_init_monitor, 2); // Signal to stop waiting for monitor creation
12347cc577a4SJonathan Peyton     return;
12357cc577a4SJonathan Peyton   }
12367cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_monitor: try to create monitor\n"));
12377cc577a4SJonathan Peyton 
12387cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
12397cc577a4SJonathan Peyton 
12407cc577a4SJonathan Peyton   __kmp_monitor_ev = CreateEvent(NULL, TRUE, FALSE, NULL);
12417cc577a4SJonathan Peyton   if (__kmp_monitor_ev == NULL) {
12427cc577a4SJonathan Peyton     DWORD error = GetLastError();
12436a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantCreateEvent), KMP_ERR(error), __kmp_msg_null);
1244bd3a7633SJonathan Peyton   }
12457cc577a4SJonathan Peyton #if USE_ITT_BUILD
12467cc577a4SJonathan Peyton   __kmp_itt_system_object_created(__kmp_monitor_ev, "Event");
12477cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
12487cc577a4SJonathan Peyton 
12497cc577a4SJonathan Peyton   th->th.th_info.ds.ds_tid = KMP_GTID_MONITOR;
12507cc577a4SJonathan Peyton   th->th.th_info.ds.ds_gtid = KMP_GTID_MONITOR;
12517cc577a4SJonathan Peyton 
12527cc577a4SJonathan Peyton   // FIXME - on Windows* OS, if __kmp_monitor_stksize = 0, figure out how
12537cc577a4SJonathan Peyton   // to automatically expand stacksize based on CreateThread error code.
12547cc577a4SJonathan Peyton   if (__kmp_monitor_stksize == 0) {
12557cc577a4SJonathan Peyton     __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE;
12567cc577a4SJonathan Peyton   }
12577cc577a4SJonathan Peyton   if (__kmp_monitor_stksize < __kmp_sys_min_stksize) {
12587cc577a4SJonathan Peyton     __kmp_monitor_stksize = __kmp_sys_min_stksize;
12597cc577a4SJonathan Peyton   }
12607cc577a4SJonathan Peyton 
12617cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_monitor: requested stacksize = %d bytes\n",
12627cc577a4SJonathan Peyton                 (int)__kmp_monitor_stksize));
12637cc577a4SJonathan Peyton 
12647cc577a4SJonathan Peyton   TCW_4(__kmp_global.g.g_time.dt.t_value, 0);
12657cc577a4SJonathan Peyton 
12663041982dSJonathan Peyton   handle =
12673041982dSJonathan Peyton       CreateThread(NULL, (SIZE_T)__kmp_monitor_stksize,
12683041982dSJonathan Peyton                    (LPTHREAD_START_ROUTINE)__kmp_launch_monitor, (LPVOID)th,
12693041982dSJonathan Peyton                    STACK_SIZE_PARAM_IS_A_RESERVATION, &idThread);
12707cc577a4SJonathan Peyton   if (handle == 0) {
12717cc577a4SJonathan Peyton     DWORD error = GetLastError();
12726a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantCreateThread), KMP_ERR(error), __kmp_msg_null);
12733041982dSJonathan Peyton   } else
12747cc577a4SJonathan Peyton     th->th.th_info.ds.ds_thread = handle;
12757cc577a4SJonathan Peyton 
12767cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
12777cc577a4SJonathan Peyton 
12787cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_create_monitor: monitor created %p\n",
12797cc577a4SJonathan Peyton                 (void *)th->th.th_info.ds.ds_thread));
12807cc577a4SJonathan Peyton }
12817cc577a4SJonathan Peyton #endif
12827cc577a4SJonathan Peyton 
12833041982dSJonathan Peyton /* Check to see if thread is still alive.
12847cc577a4SJonathan Peyton    NOTE:  The ExitProcess(code) system call causes all threads to Terminate
12853041982dSJonathan Peyton    with a exit_val = code.  Because of this we can not rely on exit_val having
12863041982dSJonathan Peyton    any particular value.  So this routine may return STILL_ALIVE in exit_val
12873041982dSJonathan Peyton    even after the thread is dead. */
12887cc577a4SJonathan Peyton 
__kmp_is_thread_alive(kmp_info_t * th,DWORD * exit_val)12893041982dSJonathan Peyton int __kmp_is_thread_alive(kmp_info_t *th, DWORD *exit_val) {
12907cc577a4SJonathan Peyton   DWORD rc;
12917cc577a4SJonathan Peyton   rc = GetExitCodeThread(th->th.th_info.ds.ds_thread, exit_val);
12927cc577a4SJonathan Peyton   if (rc == 0) {
12937cc577a4SJonathan Peyton     DWORD error = GetLastError();
12946a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(FunctionError, "GetExitCodeThread()"), KMP_ERR(error),
12956a393f75SJonathan Peyton                 __kmp_msg_null);
1296bd3a7633SJonathan Peyton   }
12977cc577a4SJonathan Peyton   return (*exit_val == STILL_ACTIVE);
12987cc577a4SJonathan Peyton }
12997cc577a4SJonathan Peyton 
__kmp_exit_thread(int exit_status)13003041982dSJonathan Peyton void __kmp_exit_thread(int exit_status) {
13017cc577a4SJonathan Peyton   ExitThread(exit_status);
13027cc577a4SJonathan Peyton } // __kmp_exit_thread
13037cc577a4SJonathan Peyton 
13043041982dSJonathan Peyton // This is a common part for both __kmp_reap_worker() and __kmp_reap_monitor().
__kmp_reap_common(kmp_info_t * th)13053041982dSJonathan Peyton static void __kmp_reap_common(kmp_info_t *th) {
13067cc577a4SJonathan Peyton   DWORD exit_val;
13077cc577a4SJonathan Peyton 
13087cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
13097cc577a4SJonathan Peyton 
13103041982dSJonathan Peyton   KA_TRACE(
13113041982dSJonathan Peyton       10, ("__kmp_reap_common: try to reap (%d)\n", th->th.th_info.ds.ds_gtid));
13127cc577a4SJonathan Peyton 
13133041982dSJonathan Peyton   /* 2006-10-19:
13147cc577a4SJonathan Peyton      There are two opposite situations:
13153041982dSJonathan Peyton      1. Windows* OS keep thread alive after it resets ds_alive flag and
13163041982dSJonathan Peyton      exits from thread function. (For example, see C70770/Q394281 "unloading of
13173041982dSJonathan Peyton      dll based on OMP is very slow".)
13187cc577a4SJonathan Peyton      2. Windows* OS may kill thread before it resets ds_alive flag.
13197cc577a4SJonathan Peyton 
13203041982dSJonathan Peyton      Right solution seems to be waiting for *either* thread termination *or*
13213041982dSJonathan Peyton      ds_alive resetting. */
13227cc577a4SJonathan Peyton   {
1323e47d32f1SJonathan Peyton     // TODO: This code is very similar to KMP_WAIT. Need to generalize
1324e47d32f1SJonathan Peyton     // KMP_WAIT to cover this usage also.
13257cc577a4SJonathan Peyton     void *obj = NULL;
1326414544c9SEd Maste     kmp_uint32 spins;
13272e02579aSTerry Wilmarth     kmp_uint64 time;
13287cc577a4SJonathan Peyton #if USE_ITT_BUILD
13297cc577a4SJonathan Peyton     KMP_FSYNC_SPIN_INIT(obj, (void *)&th->th.th_info.ds.ds_alive);
13307cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
13317cc577a4SJonathan Peyton     KMP_INIT_YIELD(spins);
13322e02579aSTerry Wilmarth     KMP_INIT_BACKOFF(time);
13337cc577a4SJonathan Peyton     do {
13347cc577a4SJonathan Peyton #if USE_ITT_BUILD
13357cc577a4SJonathan Peyton       KMP_FSYNC_SPIN_PREPARE(obj);
13367cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
13377cc577a4SJonathan Peyton       __kmp_is_thread_alive(th, &exit_val);
13382e02579aSTerry Wilmarth       KMP_YIELD_OVERSUB_ELSE_SPIN(spins, time);
13397cc577a4SJonathan Peyton     } while (exit_val == STILL_ACTIVE && TCR_4(th->th.th_info.ds.ds_alive));
13407cc577a4SJonathan Peyton #if USE_ITT_BUILD
13417cc577a4SJonathan Peyton     if (exit_val == STILL_ACTIVE) {
13427cc577a4SJonathan Peyton       KMP_FSYNC_CANCEL(obj);
13437cc577a4SJonathan Peyton     } else {
13447cc577a4SJonathan Peyton       KMP_FSYNC_SPIN_ACQUIRED(obj);
1345bd3a7633SJonathan Peyton     }
13467cc577a4SJonathan Peyton #endif /* USE_ITT_BUILD */
13477cc577a4SJonathan Peyton   }
13487cc577a4SJonathan Peyton 
13497cc577a4SJonathan Peyton   __kmp_free_handle(th->th.th_info.ds.ds_thread);
13507cc577a4SJonathan Peyton 
13513041982dSJonathan Peyton   /* NOTE:  The ExitProcess(code) system call causes all threads to Terminate
13523041982dSJonathan Peyton      with a exit_val = code.  Because of this we can not rely on exit_val having
13533041982dSJonathan Peyton      any particular value. */
1354*1234011bSJonathan Peyton   kmp_intptr_t e = (kmp_intptr_t)exit_val;
13557cc577a4SJonathan Peyton   if (exit_val == STILL_ACTIVE) {
13567cc577a4SJonathan Peyton     KA_TRACE(1, ("__kmp_reap_common: thread still active.\n"));
1357*1234011bSJonathan Peyton   } else if ((void *)e != (void *)th) {
13587cc577a4SJonathan Peyton     KA_TRACE(1, ("__kmp_reap_common: ExitProcess / TerminateThread used?\n"));
1359bd3a7633SJonathan Peyton   }
13607cc577a4SJonathan Peyton 
13617cc577a4SJonathan Peyton   KA_TRACE(10,
13623041982dSJonathan Peyton            ("__kmp_reap_common: done reaping (%d), handle = %" KMP_UINTPTR_SPEC
13633041982dSJonathan Peyton             "\n",
13643041982dSJonathan Peyton             th->th.th_info.ds.ds_gtid, th->th.th_info.ds.ds_thread));
13657cc577a4SJonathan Peyton 
13667cc577a4SJonathan Peyton   th->th.th_info.ds.ds_thread = 0;
13677cc577a4SJonathan Peyton   th->th.th_info.ds.ds_tid = KMP_GTID_DNE;
13687cc577a4SJonathan Peyton   th->th.th_info.ds.ds_gtid = KMP_GTID_DNE;
13697cc577a4SJonathan Peyton   th->th.th_info.ds.ds_thread_id = 0;
13707cc577a4SJonathan Peyton 
13717cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
13727cc577a4SJonathan Peyton }
13737cc577a4SJonathan Peyton 
13747cc577a4SJonathan Peyton #if KMP_USE_MONITOR
__kmp_reap_monitor(kmp_info_t * th)13753041982dSJonathan Peyton void __kmp_reap_monitor(kmp_info_t *th) {
13767cc577a4SJonathan Peyton   int status;
13777cc577a4SJonathan Peyton 
13787cc577a4SJonathan Peyton   KA_TRACE(10, ("__kmp_reap_monitor: try to reap %p\n",
13797cc577a4SJonathan Peyton                 (void *)th->th.th_info.ds.ds_thread));
13807cc577a4SJonathan Peyton 
13817cc577a4SJonathan Peyton   // If monitor has been created, its tid and gtid should be KMP_GTID_MONITOR.
13827cc577a4SJonathan Peyton   // If both tid and gtid are 0, it means the monitor did not ever start.
13837cc577a4SJonathan Peyton   // If both tid and gtid are KMP_GTID_DNE, the monitor has been shut down.
13847cc577a4SJonathan Peyton   KMP_DEBUG_ASSERT(th->th.th_info.ds.ds_tid == th->th.th_info.ds.ds_gtid);
13857cc577a4SJonathan Peyton   if (th->th.th_info.ds.ds_gtid != KMP_GTID_MONITOR) {
13867cc577a4SJonathan Peyton     KA_TRACE(10, ("__kmp_reap_monitor: monitor did not start, returning\n"));
13877cc577a4SJonathan Peyton     return;
1388bd3a7633SJonathan Peyton   }
13897cc577a4SJonathan Peyton 
13907cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
13917cc577a4SJonathan Peyton 
13927cc577a4SJonathan Peyton   status = SetEvent(__kmp_monitor_ev);
13937cc577a4SJonathan Peyton   if (status == FALSE) {
13947cc577a4SJonathan Peyton     DWORD error = GetLastError();
13956a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantSetEvent), KMP_ERR(error), __kmp_msg_null);
13967cc577a4SJonathan Peyton   }
13973041982dSJonathan Peyton   KA_TRACE(10, ("__kmp_reap_monitor: reaping thread (%d)\n",
13983041982dSJonathan Peyton                 th->th.th_info.ds.ds_gtid));
13997cc577a4SJonathan Peyton   __kmp_reap_common(th);
14007cc577a4SJonathan Peyton 
14017cc577a4SJonathan Peyton   __kmp_free_handle(__kmp_monitor_ev);
14027cc577a4SJonathan Peyton 
14037cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
14047cc577a4SJonathan Peyton }
14057cc577a4SJonathan Peyton #endif
14067cc577a4SJonathan Peyton 
__kmp_reap_worker(kmp_info_t * th)14073041982dSJonathan Peyton void __kmp_reap_worker(kmp_info_t *th) {
14083041982dSJonathan Peyton   KA_TRACE(10, ("__kmp_reap_worker: reaping thread (%d)\n",
14093041982dSJonathan Peyton                 th->th.th_info.ds.ds_gtid));
14107cc577a4SJonathan Peyton   __kmp_reap_common(th);
14117cc577a4SJonathan Peyton }
14127cc577a4SJonathan Peyton 
14137cc577a4SJonathan Peyton #if KMP_HANDLE_SIGNALS
14147cc577a4SJonathan Peyton 
__kmp_team_handler(int signo)14153041982dSJonathan Peyton static void __kmp_team_handler(int signo) {
14167cc577a4SJonathan Peyton   if (__kmp_global.g.g_abort == 0) {
14177cc577a4SJonathan Peyton     // Stage 1 signal handler, let's shut down all of the threads.
14187cc577a4SJonathan Peyton     if (__kmp_debug_buf) {
14197cc577a4SJonathan Peyton       __kmp_dump_debug_buffer();
1420bd3a7633SJonathan Peyton     }
14217cc577a4SJonathan Peyton     KMP_MB(); // Flush all pending memory write invalidates.
14227cc577a4SJonathan Peyton     TCW_4(__kmp_global.g.g_abort, signo);
14237cc577a4SJonathan Peyton     KMP_MB(); // Flush all pending memory write invalidates.
14247cc577a4SJonathan Peyton     TCW_4(__kmp_global.g.g_done, TRUE);
14257cc577a4SJonathan Peyton     KMP_MB(); // Flush all pending memory write invalidates.
14267cc577a4SJonathan Peyton   }
14277cc577a4SJonathan Peyton } // __kmp_team_handler
14287cc577a4SJonathan Peyton 
__kmp_signal(int signum,sig_func_t handler)14293041982dSJonathan Peyton static sig_func_t __kmp_signal(int signum, sig_func_t handler) {
14307cc577a4SJonathan Peyton   sig_func_t old = signal(signum, handler);
14317cc577a4SJonathan Peyton   if (old == SIG_ERR) {
14327cc577a4SJonathan Peyton     int error = errno;
14336a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(FunctionError, "signal"), KMP_ERR(error),
14343041982dSJonathan Peyton                 __kmp_msg_null);
1435bd3a7633SJonathan Peyton   }
14367cc577a4SJonathan Peyton   return old;
14377cc577a4SJonathan Peyton }
14387cc577a4SJonathan Peyton 
__kmp_install_one_handler(int sig,sig_func_t handler,int parallel_init)14393041982dSJonathan Peyton static void __kmp_install_one_handler(int sig, sig_func_t handler,
14403041982dSJonathan Peyton                                       int parallel_init) {
14417cc577a4SJonathan Peyton   sig_func_t old;
14427cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
14437cc577a4SJonathan Peyton   KB_TRACE(60, ("__kmp_install_one_handler: called: sig=%d\n", sig));
14447cc577a4SJonathan Peyton   if (parallel_init) {
14457cc577a4SJonathan Peyton     old = __kmp_signal(sig, handler);
14467cc577a4SJonathan Peyton     // SIG_DFL on Windows* OS in NULL or 0.
14477cc577a4SJonathan Peyton     if (old == __kmp_sighldrs[sig]) {
14487cc577a4SJonathan Peyton       __kmp_siginstalled[sig] = 1;
14493041982dSJonathan Peyton     } else { // Restore/keep user's handler if one previously installed.
14507cc577a4SJonathan Peyton       old = __kmp_signal(sig, old);
1451bd3a7633SJonathan Peyton     }
14527cc577a4SJonathan Peyton   } else {
14537cc577a4SJonathan Peyton     // Save initial/system signal handlers to see if user handlers installed.
14543041982dSJonathan Peyton     // 2009-09-23: It is a dead code. On Windows* OS __kmp_install_signals
14553041982dSJonathan Peyton     // called once with parallel_init == TRUE.
14567cc577a4SJonathan Peyton     old = __kmp_signal(sig, SIG_DFL);
14577cc577a4SJonathan Peyton     __kmp_sighldrs[sig] = old;
14587cc577a4SJonathan Peyton     __kmp_signal(sig, old);
1459bd3a7633SJonathan Peyton   }
14607cc577a4SJonathan Peyton   KMP_MB(); /* Flush all pending memory write invalidates.  */
14617cc577a4SJonathan Peyton } // __kmp_install_one_handler
14627cc577a4SJonathan Peyton 
__kmp_remove_one_handler(int sig)14633041982dSJonathan Peyton static void __kmp_remove_one_handler(int sig) {
14647cc577a4SJonathan Peyton   if (__kmp_siginstalled[sig]) {
14657cc577a4SJonathan Peyton     sig_func_t old;
14667cc577a4SJonathan Peyton     KMP_MB(); // Flush all pending memory write invalidates.
14677cc577a4SJonathan Peyton     KB_TRACE(60, ("__kmp_remove_one_handler: called: sig=%d\n", sig));
14687cc577a4SJonathan Peyton     old = __kmp_signal(sig, __kmp_sighldrs[sig]);
14697cc577a4SJonathan Peyton     if (old != __kmp_team_handler) {
14703041982dSJonathan Peyton       KB_TRACE(10, ("__kmp_remove_one_handler: oops, not our handler, "
14713041982dSJonathan Peyton                     "restoring: sig=%d\n",
14723041982dSJonathan Peyton                     sig));
14737cc577a4SJonathan Peyton       old = __kmp_signal(sig, old);
1474bd3a7633SJonathan Peyton     }
14757cc577a4SJonathan Peyton     __kmp_sighldrs[sig] = NULL;
14767cc577a4SJonathan Peyton     __kmp_siginstalled[sig] = 0;
14777cc577a4SJonathan Peyton     KMP_MB(); // Flush all pending memory write invalidates.
1478bd3a7633SJonathan Peyton   }
14797cc577a4SJonathan Peyton } // __kmp_remove_one_handler
14807cc577a4SJonathan Peyton 
__kmp_install_signals(int parallel_init)14813041982dSJonathan Peyton void __kmp_install_signals(int parallel_init) {
14827cc577a4SJonathan Peyton   KB_TRACE(10, ("__kmp_install_signals: called\n"));
14837cc577a4SJonathan Peyton   if (!__kmp_handle_signals) {
14843041982dSJonathan Peyton     KB_TRACE(10, ("__kmp_install_signals: KMP_HANDLE_SIGNALS is false - "
14853041982dSJonathan Peyton                   "handlers not installed\n"));
14867cc577a4SJonathan Peyton     return;
1487bd3a7633SJonathan Peyton   }
14887cc577a4SJonathan Peyton   __kmp_install_one_handler(SIGINT, __kmp_team_handler, parallel_init);
14897cc577a4SJonathan Peyton   __kmp_install_one_handler(SIGILL, __kmp_team_handler, parallel_init);
14907cc577a4SJonathan Peyton   __kmp_install_one_handler(SIGABRT, __kmp_team_handler, parallel_init);
14917cc577a4SJonathan Peyton   __kmp_install_one_handler(SIGFPE, __kmp_team_handler, parallel_init);
14927cc577a4SJonathan Peyton   __kmp_install_one_handler(SIGSEGV, __kmp_team_handler, parallel_init);
14937cc577a4SJonathan Peyton   __kmp_install_one_handler(SIGTERM, __kmp_team_handler, parallel_init);
14947cc577a4SJonathan Peyton } // __kmp_install_signals
14957cc577a4SJonathan Peyton 
__kmp_remove_signals(void)14963041982dSJonathan Peyton void __kmp_remove_signals(void) {
14977cc577a4SJonathan Peyton   int sig;
14987cc577a4SJonathan Peyton   KB_TRACE(10, ("__kmp_remove_signals: called\n"));
14997cc577a4SJonathan Peyton   for (sig = 1; sig < NSIG; ++sig) {
15007cc577a4SJonathan Peyton     __kmp_remove_one_handler(sig);
1501bd3a7633SJonathan Peyton   }
15027cc577a4SJonathan Peyton } // __kmp_remove_signals
15037cc577a4SJonathan Peyton 
15047cc577a4SJonathan Peyton #endif // KMP_HANDLE_SIGNALS
15057cc577a4SJonathan Peyton 
15067cc577a4SJonathan Peyton /* Put the thread to sleep for a time period */
__kmp_thread_sleep(int millis)15073041982dSJonathan Peyton void __kmp_thread_sleep(int millis) {
15087cc577a4SJonathan Peyton   DWORD status;
15097cc577a4SJonathan Peyton 
15107cc577a4SJonathan Peyton   status = SleepEx((DWORD)millis, FALSE);
15117cc577a4SJonathan Peyton   if (status) {
15127cc577a4SJonathan Peyton     DWORD error = GetLastError();
15136a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(FunctionError, "SleepEx()"), KMP_ERR(error),
15143041982dSJonathan Peyton                 __kmp_msg_null);
15157cc577a4SJonathan Peyton   }
15167cc577a4SJonathan Peyton }
15177cc577a4SJonathan Peyton 
15183041982dSJonathan Peyton // Determine whether the given address is mapped into the current address space.
__kmp_is_address_mapped(void * addr)15193041982dSJonathan Peyton int __kmp_is_address_mapped(void *addr) {
15207cc577a4SJonathan Peyton   MEMORY_BASIC_INFORMATION lpBuffer;
15217cc577a4SJonathan Peyton   SIZE_T dwLength;
15227cc577a4SJonathan Peyton 
15237cc577a4SJonathan Peyton   dwLength = sizeof(MEMORY_BASIC_INFORMATION);
15247cc577a4SJonathan Peyton 
1525*1234011bSJonathan Peyton   VirtualQuery(addr, &lpBuffer, dwLength);
15267cc577a4SJonathan Peyton 
15277cc577a4SJonathan Peyton   return !(((lpBuffer.State == MEM_RESERVE) || (lpBuffer.State == MEM_FREE)) ||
15283041982dSJonathan Peyton            ((lpBuffer.Protect == PAGE_NOACCESS) ||
15293041982dSJonathan Peyton             (lpBuffer.Protect == PAGE_EXECUTE)));
15307cc577a4SJonathan Peyton }
15317cc577a4SJonathan Peyton 
__kmp_hardware_timestamp(void)15323041982dSJonathan Peyton kmp_uint64 __kmp_hardware_timestamp(void) {
15337cc577a4SJonathan Peyton   kmp_uint64 r = 0;
15347cc577a4SJonathan Peyton 
15357cc577a4SJonathan Peyton   QueryPerformanceCounter((LARGE_INTEGER *)&r);
15367cc577a4SJonathan Peyton   return r;
15377cc577a4SJonathan Peyton }
15387cc577a4SJonathan Peyton 
15397cc577a4SJonathan Peyton /* Free handle and check the error code */
__kmp_free_handle(kmp_thread_t tHandle)15403041982dSJonathan Peyton void __kmp_free_handle(kmp_thread_t tHandle) {
15413041982dSJonathan Peyton   /* called with parameter type HANDLE also, thus suppose kmp_thread_t defined
15423041982dSJonathan Peyton    * as HANDLE */
15437cc577a4SJonathan Peyton   BOOL rc;
15447cc577a4SJonathan Peyton   rc = CloseHandle(tHandle);
15457cc577a4SJonathan Peyton   if (!rc) {
15467cc577a4SJonathan Peyton     DWORD error = GetLastError();
15476a393f75SJonathan Peyton     __kmp_fatal(KMP_MSG(CantCloseHandle), KMP_ERR(error), __kmp_msg_null);
15487cc577a4SJonathan Peyton   }
15497cc577a4SJonathan Peyton }
15507cc577a4SJonathan Peyton 
__kmp_get_load_balance(int max)15513041982dSJonathan Peyton int __kmp_get_load_balance(int max) {
15527cc577a4SJonathan Peyton   static ULONG glb_buff_size = 100 * 1024;
15537cc577a4SJonathan Peyton 
1554ed5fe645SKelvin Li   // Saved count of the running threads for the thread balance algorithm
15553041982dSJonathan Peyton   static int glb_running_threads = 0;
15567cc577a4SJonathan Peyton   static double glb_call_time = 0; /* Thread balance algorithm call time */
15577cc577a4SJonathan Peyton 
15587cc577a4SJonathan Peyton   int running_threads = 0; // Number of running threads in the system.
15597cc577a4SJonathan Peyton   NTSTATUS status = 0;
15607cc577a4SJonathan Peyton   ULONG buff_size = 0;
15617cc577a4SJonathan Peyton   ULONG info_size = 0;
15627cc577a4SJonathan Peyton   void *buffer = NULL;
15637cc577a4SJonathan Peyton   PSYSTEM_PROCESS_INFORMATION spi = NULL;
15647cc577a4SJonathan Peyton   int first_time = 1;
15657cc577a4SJonathan Peyton 
15667cc577a4SJonathan Peyton   double call_time = 0.0; // start, finish;
15677cc577a4SJonathan Peyton 
15687cc577a4SJonathan Peyton   __kmp_elapsed(&call_time);
15697cc577a4SJonathan Peyton 
15707cc577a4SJonathan Peyton   if (glb_call_time &&
15717cc577a4SJonathan Peyton       (call_time - glb_call_time < __kmp_load_balance_interval)) {
15727cc577a4SJonathan Peyton     running_threads = glb_running_threads;
15737cc577a4SJonathan Peyton     goto finish;
15747cc577a4SJonathan Peyton   }
15757cc577a4SJonathan Peyton   glb_call_time = call_time;
15767cc577a4SJonathan Peyton 
15777cc577a4SJonathan Peyton   // Do not spend time on running algorithm if we have a permanent error.
15787cc577a4SJonathan Peyton   if (NtQuerySystemInformation == NULL) {
15797cc577a4SJonathan Peyton     running_threads = -1;
15807cc577a4SJonathan Peyton     goto finish;
1581bd3a7633SJonathan Peyton   }
15827cc577a4SJonathan Peyton 
15837cc577a4SJonathan Peyton   if (max <= 0) {
15847cc577a4SJonathan Peyton     max = INT_MAX;
1585bd3a7633SJonathan Peyton   }
15867cc577a4SJonathan Peyton 
15877cc577a4SJonathan Peyton   do {
15887cc577a4SJonathan Peyton 
15897cc577a4SJonathan Peyton     if (first_time) {
15907cc577a4SJonathan Peyton       buff_size = glb_buff_size;
15917cc577a4SJonathan Peyton     } else {
15927cc577a4SJonathan Peyton       buff_size = 2 * buff_size;
15937cc577a4SJonathan Peyton     }
15947cc577a4SJonathan Peyton 
15957cc577a4SJonathan Peyton     buffer = KMP_INTERNAL_REALLOC(buffer, buff_size);
15967cc577a4SJonathan Peyton     if (buffer == NULL) {
15977cc577a4SJonathan Peyton       running_threads = -1;
15987cc577a4SJonathan Peyton       goto finish;
1599bd3a7633SJonathan Peyton     }
16003041982dSJonathan Peyton     status = NtQuerySystemInformation(SystemProcessInformation, buffer,
16013041982dSJonathan Peyton                                       buff_size, &info_size);
16027cc577a4SJonathan Peyton     first_time = 0;
16037cc577a4SJonathan Peyton 
16047cc577a4SJonathan Peyton   } while (status == STATUS_INFO_LENGTH_MISMATCH);
16057cc577a4SJonathan Peyton   glb_buff_size = buff_size;
16067cc577a4SJonathan Peyton 
16077cc577a4SJonathan Peyton #define CHECK(cond)                                                            \
16087cc577a4SJonathan Peyton   {                                                                            \
16097cc577a4SJonathan Peyton     KMP_DEBUG_ASSERT(cond);                                                    \
16107cc577a4SJonathan Peyton     if (!(cond)) {                                                             \
16117cc577a4SJonathan Peyton       running_threads = -1;                                                    \
16127cc577a4SJonathan Peyton       goto finish;                                                             \
16137cc577a4SJonathan Peyton     }                                                                          \
16147cc577a4SJonathan Peyton   }
16157cc577a4SJonathan Peyton 
16167cc577a4SJonathan Peyton   CHECK(buff_size >= info_size);
16177cc577a4SJonathan Peyton   spi = PSYSTEM_PROCESS_INFORMATION(buffer);
16187cc577a4SJonathan Peyton   for (;;) {
16197cc577a4SJonathan Peyton     ptrdiff_t offset = uintptr_t(spi) - uintptr_t(buffer);
16203041982dSJonathan Peyton     CHECK(0 <= offset &&
16213041982dSJonathan Peyton           offset + sizeof(SYSTEM_PROCESS_INFORMATION) < info_size);
16227cc577a4SJonathan Peyton     HANDLE pid = spi->ProcessId;
16237cc577a4SJonathan Peyton     ULONG num = spi->NumberOfThreads;
16247cc577a4SJonathan Peyton     CHECK(num >= 1);
16253041982dSJonathan Peyton     size_t spi_size =
16263041982dSJonathan Peyton         sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD) * (num - 1);
16273041982dSJonathan Peyton     CHECK(offset + spi_size <
16283041982dSJonathan Peyton           info_size); // Make sure process info record fits the buffer.
16297cc577a4SJonathan Peyton     if (spi->NextEntryOffset != 0) {
16303041982dSJonathan Peyton       CHECK(spi_size <=
16313041982dSJonathan Peyton             spi->NextEntryOffset); // And do not overlap with the next record.
1632bd3a7633SJonathan Peyton     }
16333041982dSJonathan Peyton     // pid == 0 corresponds to the System Idle Process. It always has running
16343041982dSJonathan Peyton     // threads on all cores. So, we don't consider the running threads of this
16353041982dSJonathan Peyton     // process.
16367cc577a4SJonathan Peyton     if (pid != 0) {
16377cc577a4SJonathan Peyton       for (int i = 0; i < num; ++i) {
16387cc577a4SJonathan Peyton         THREAD_STATE state = spi->Threads[i].State;
16397cc577a4SJonathan Peyton         // Count threads that have Ready or Running state.
16407cc577a4SJonathan Peyton         // !!! TODO: Why comment does not match the code???
16417cc577a4SJonathan Peyton         if (state == StateRunning) {
16427cc577a4SJonathan Peyton           ++running_threads;
16437cc577a4SJonathan Peyton           // Stop counting running threads if the number is already greater than
16447cc577a4SJonathan Peyton           // the number of available cores
16457cc577a4SJonathan Peyton           if (running_threads >= max) {
16467cc577a4SJonathan Peyton             goto finish;
16477cc577a4SJonathan Peyton           }
1648bd3a7633SJonathan Peyton         }
1649bd3a7633SJonathan Peyton       }
1650bd3a7633SJonathan Peyton     }
16517cc577a4SJonathan Peyton     if (spi->NextEntryOffset == 0) {
16527cc577a4SJonathan Peyton       break;
1653bd3a7633SJonathan Peyton     }
16547cc577a4SJonathan Peyton     spi = PSYSTEM_PROCESS_INFORMATION(uintptr_t(spi) + spi->NextEntryOffset);
1655bd3a7633SJonathan Peyton   }
16567cc577a4SJonathan Peyton 
16577cc577a4SJonathan Peyton #undef CHECK
16587cc577a4SJonathan Peyton 
16597cc577a4SJonathan Peyton finish: // Clean up and exit.
16607cc577a4SJonathan Peyton 
16617cc577a4SJonathan Peyton   if (buffer != NULL) {
16627cc577a4SJonathan Peyton     KMP_INTERNAL_FREE(buffer);
1663bd3a7633SJonathan Peyton   }
16647cc577a4SJonathan Peyton 
16657cc577a4SJonathan Peyton   glb_running_threads = running_threads;
16667cc577a4SJonathan Peyton 
16677cc577a4SJonathan Peyton   return running_threads;
16687cc577a4SJonathan Peyton } //__kmp_get_load_balance()
16699d64275aSShilei Tian 
1670ffb21e7fSHansang Bae // Find symbol from the loaded modules
__kmp_lookup_symbol(const char * name)1671ffb21e7fSHansang Bae void *__kmp_lookup_symbol(const char *name) {
1672ffb21e7fSHansang Bae   HANDLE process = GetCurrentProcess();
1673ffb21e7fSHansang Bae   DWORD needed;
1674ffb21e7fSHansang Bae   HMODULE *modules = nullptr;
1675ffb21e7fSHansang Bae   if (!EnumProcessModules(process, modules, 0, &needed))
1676ffb21e7fSHansang Bae     return nullptr;
1677ffb21e7fSHansang Bae   DWORD num_modules = needed / sizeof(HMODULE);
1678ffb21e7fSHansang Bae   modules = (HMODULE *)malloc(num_modules * sizeof(HMODULE));
1679ffb21e7fSHansang Bae   if (!EnumProcessModules(process, modules, needed, &needed)) {
1680ffb21e7fSHansang Bae     free(modules);
1681ffb21e7fSHansang Bae     return nullptr;
1682ffb21e7fSHansang Bae   }
1683ffb21e7fSHansang Bae   void *proc = nullptr;
1684ffb21e7fSHansang Bae   for (uint32_t i = 0; i < num_modules; i++) {
1685ffb21e7fSHansang Bae     proc = (void *)GetProcAddress(modules[i], name);
1686ffb21e7fSHansang Bae     if (proc)
1687ffb21e7fSHansang Bae       break;
1688ffb21e7fSHansang Bae   }
1689ffb21e7fSHansang Bae   free(modules);
1690ffb21e7fSHansang Bae   return proc;
1691ffb21e7fSHansang Bae }
1692ffb21e7fSHansang Bae 
16939d64275aSShilei Tian // Functions for hidden helper task
__kmp_hidden_helper_worker_thread_wait()16949d64275aSShilei Tian void __kmp_hidden_helper_worker_thread_wait() {
16959d64275aSShilei Tian   KMP_ASSERT(0 && "Hidden helper task is not supported on Windows");
16969d64275aSShilei Tian }
16979d64275aSShilei Tian 
__kmp_do_initialize_hidden_helper_threads()16989d64275aSShilei Tian void __kmp_do_initialize_hidden_helper_threads() {
16999d64275aSShilei Tian   KMP_ASSERT(0 && "Hidden helper task is not supported on Windows");
17009d64275aSShilei Tian }
17019d64275aSShilei Tian 
__kmp_hidden_helper_threads_initz_wait()17029d64275aSShilei Tian void __kmp_hidden_helper_threads_initz_wait() {
17039d64275aSShilei Tian   KMP_ASSERT(0 && "Hidden helper task is not supported on Windows");
17049d64275aSShilei Tian }
17059d64275aSShilei Tian 
__kmp_hidden_helper_initz_release()17069d64275aSShilei Tian void __kmp_hidden_helper_initz_release() {
17079d64275aSShilei Tian   KMP_ASSERT(0 && "Hidden helper task is not supported on Windows");
17089d64275aSShilei Tian }
17099d64275aSShilei Tian 
__kmp_hidden_helper_main_thread_wait()17109d64275aSShilei Tian void __kmp_hidden_helper_main_thread_wait() {
17119d64275aSShilei Tian   KMP_ASSERT(0 && "Hidden helper task is not supported on Windows");
17129d64275aSShilei Tian }
17139d64275aSShilei Tian 
__kmp_hidden_helper_main_thread_release()17149d64275aSShilei Tian void __kmp_hidden_helper_main_thread_release() {
17159d64275aSShilei Tian   KMP_ASSERT(0 && "Hidden helper task is not supported on Windows");
17169d64275aSShilei Tian }
17179d64275aSShilei Tian 
__kmp_hidden_helper_worker_thread_signal()17189d64275aSShilei Tian void __kmp_hidden_helper_worker_thread_signal() {
17199d64275aSShilei Tian   KMP_ASSERT(0 && "Hidden helper task is not supported on Windows");
17209d64275aSShilei Tian }
17219d64275aSShilei Tian 
__kmp_hidden_helper_threads_deinitz_wait()17229d64275aSShilei Tian void __kmp_hidden_helper_threads_deinitz_wait() {
17239d64275aSShilei Tian   KMP_ASSERT(0 && "Hidden helper task is not supported on Windows");
17249d64275aSShilei Tian }
17259d64275aSShilei Tian 
__kmp_hidden_helper_threads_deinitz_release()17269d64275aSShilei Tian void __kmp_hidden_helper_threads_deinitz_release() {
17279d64275aSShilei Tian   KMP_ASSERT(0 && "Hidden helper task is not supported on Windows");
17289d64275aSShilei Tian }
1729