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