blob: 33b018174b6ccbff70e8337b0409bafa78187fe8 [file] [log] [blame]
Jim Cownie5e8470a2013-09-27 10:38:44 +00001/*
Jonathan Peytonde4749b2016-12-14 23:01:24 +00002 * z_Windows_NT_util.cpp -- platform specific routines.
Jim Cownie5e8470a2013-09-27 10:38:44 +00003 */
4
Jim Cownie5e8470a2013-09-27 10:38:44 +00005//===----------------------------------------------------------------------===//
6//
Chandler Carruth57b08b02019-01-19 10:56:40 +00007// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8// See https://llvm.org/LICENSE.txt for license information.
9// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Jim Cownie5e8470a2013-09-27 10:38:44 +000010//
11//===----------------------------------------------------------------------===//
12
Jim Cownie5e8470a2013-09-27 10:38:44 +000013#include "kmp.h"
Jonathan Peyton30419822017-05-12 18:01:32 +000014#include "kmp_affinity.h"
Jim Cownie5e8470a2013-09-27 10:38:44 +000015#include "kmp_i18n.h"
16#include "kmp_io.h"
Jonathan Peyton30419822017-05-12 18:01:32 +000017#include "kmp_itt.h"
Jim Cownie4cc4bb42014-10-07 16:25:50 +000018#include "kmp_wait_release.h"
Jim Cownie5e8470a2013-09-27 10:38:44 +000019
Jim Cownie4cc4bb42014-10-07 16:25:50 +000020/* This code is related to NtQuerySystemInformation() function. This function
21 is used in the Load balance algorithm for OMP_DYNAMIC=true to find the
Jim Cownie5e8470a2013-09-27 10:38:44 +000022 number of running threads in the system. */
23
Jonathan Peyton30419822017-05-12 18:01:32 +000024#include <ntsecapi.h> // UNICODE_STRING
Jim Cownie5e8470a2013-09-27 10:38:44 +000025#include <ntstatus.h>
Jim Cownie5e8470a2013-09-27 10:38:44 +000026
27enum SYSTEM_INFORMATION_CLASS {
Jonathan Peyton30419822017-05-12 18:01:32 +000028 SystemProcessInformation = 5
Jim Cownie5e8470a2013-09-27 10:38:44 +000029}; // SYSTEM_INFORMATION_CLASS
30
31struct CLIENT_ID {
Jonathan Peyton30419822017-05-12 18:01:32 +000032 HANDLE UniqueProcess;
33 HANDLE UniqueThread;
Jim Cownie5e8470a2013-09-27 10:38:44 +000034}; // struct CLIENT_ID
35
36enum THREAD_STATE {
Jonathan Peyton30419822017-05-12 18:01:32 +000037 StateInitialized,
38 StateReady,
39 StateRunning,
40 StateStandby,
41 StateTerminated,
42 StateWait,
43 StateTransition,
44 StateUnknown
Jim Cownie5e8470a2013-09-27 10:38:44 +000045}; // enum THREAD_STATE
46
47struct VM_COUNTERS {
Jonathan Peyton30419822017-05-12 18:01:32 +000048 SIZE_T PeakVirtualSize;
49 SIZE_T VirtualSize;
50 ULONG PageFaultCount;
51 SIZE_T PeakWorkingSetSize;
52 SIZE_T WorkingSetSize;
53 SIZE_T QuotaPeakPagedPoolUsage;
54 SIZE_T QuotaPagedPoolUsage;
55 SIZE_T QuotaPeakNonPagedPoolUsage;
56 SIZE_T QuotaNonPagedPoolUsage;
57 SIZE_T PagefileUsage;
58 SIZE_T PeakPagefileUsage;
59 SIZE_T PrivatePageCount;
Jim Cownie5e8470a2013-09-27 10:38:44 +000060}; // struct VM_COUNTERS
61
62struct SYSTEM_THREAD {
Jonathan Peyton30419822017-05-12 18:01:32 +000063 LARGE_INTEGER KernelTime;
64 LARGE_INTEGER UserTime;
65 LARGE_INTEGER CreateTime;
66 ULONG WaitTime;
67 LPVOID StartAddress;
68 CLIENT_ID ClientId;
69 DWORD Priority;
70 LONG BasePriority;
71 ULONG ContextSwitchCount;
72 THREAD_STATE State;
73 ULONG WaitReason;
Jim Cownie5e8470a2013-09-27 10:38:44 +000074}; // SYSTEM_THREAD
75
Jonathan Peyton30419822017-05-12 18:01:32 +000076KMP_BUILD_ASSERT(offsetof(SYSTEM_THREAD, KernelTime) == 0);
Jim Cownie5e8470a2013-09-27 10:38:44 +000077#if KMP_ARCH_X86
Jonathan Peyton30419822017-05-12 18:01:32 +000078KMP_BUILD_ASSERT(offsetof(SYSTEM_THREAD, StartAddress) == 28);
79KMP_BUILD_ASSERT(offsetof(SYSTEM_THREAD, State) == 52);
Jim Cownie5e8470a2013-09-27 10:38:44 +000080#else
Jonathan Peyton30419822017-05-12 18:01:32 +000081KMP_BUILD_ASSERT(offsetof(SYSTEM_THREAD, StartAddress) == 32);
82KMP_BUILD_ASSERT(offsetof(SYSTEM_THREAD, State) == 68);
Jim Cownie5e8470a2013-09-27 10:38:44 +000083#endif
84
85struct SYSTEM_PROCESS_INFORMATION {
Jonathan Peyton30419822017-05-12 18:01:32 +000086 ULONG NextEntryOffset;
87 ULONG NumberOfThreads;
88 LARGE_INTEGER Reserved[3];
89 LARGE_INTEGER CreateTime;
90 LARGE_INTEGER UserTime;
91 LARGE_INTEGER KernelTime;
92 UNICODE_STRING ImageName;
93 DWORD BasePriority;
94 HANDLE ProcessId;
95 HANDLE ParentProcessId;
96 ULONG HandleCount;
97 ULONG Reserved2[2];
98 VM_COUNTERS VMCounters;
99 IO_COUNTERS IOCounters;
100 SYSTEM_THREAD Threads[1];
Jim Cownie5e8470a2013-09-27 10:38:44 +0000101}; // SYSTEM_PROCESS_INFORMATION
Jonathan Peyton30419822017-05-12 18:01:32 +0000102typedef SYSTEM_PROCESS_INFORMATION *PSYSTEM_PROCESS_INFORMATION;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000103
Jonathan Peyton30419822017-05-12 18:01:32 +0000104KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, NextEntryOffset) == 0);
105KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, CreateTime) == 32);
106KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, ImageName) == 56);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000107#if KMP_ARCH_X86
Jonathan Peyton30419822017-05-12 18:01:32 +0000108KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, ProcessId) == 68);
109KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, HandleCount) == 76);
110KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, VMCounters) == 88);
111KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, IOCounters) == 136);
112KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, Threads) == 184);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000113#else
Jonathan Peyton30419822017-05-12 18:01:32 +0000114KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, ProcessId) == 80);
115KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, HandleCount) == 96);
116KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, VMCounters) == 112);
117KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, IOCounters) == 208);
118KMP_BUILD_ASSERT(offsetof(SYSTEM_PROCESS_INFORMATION, Threads) == 256);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000119#endif
120
Jonathan Peyton30419822017-05-12 18:01:32 +0000121typedef NTSTATUS(NTAPI *NtQuerySystemInformation_t)(SYSTEM_INFORMATION_CLASS,
122 PVOID, ULONG, PULONG);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000123NtQuerySystemInformation_t NtQuerySystemInformation = NULL;
124
125HMODULE ntdll = NULL;
126
127/* End of NtQuerySystemInformation()-related code */
128
Jim Cownie5e8470a2013-09-27 10:38:44 +0000129static HMODULE kernel32 = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000130
Jim Cownie5e8470a2013-09-27 10:38:44 +0000131#if KMP_HANDLE_SIGNALS
Jonathan Peyton30419822017-05-12 18:01:32 +0000132typedef void (*sig_func_t)(int);
133static sig_func_t __kmp_sighldrs[NSIG];
134static int __kmp_siginstalled[NSIG];
Jim Cownie5e8470a2013-09-27 10:38:44 +0000135#endif
136
Jonathan Peytonb66d1aa2016-09-27 17:11:17 +0000137#if KMP_USE_MONITOR
Jonathan Peyton30419822017-05-12 18:01:32 +0000138static HANDLE __kmp_monitor_ev;
Jonathan Peytonb66d1aa2016-09-27 17:11:17 +0000139#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000140static kmp_int64 __kmp_win32_time;
141double __kmp_win32_tick;
142
143int __kmp_init_runtime = FALSE;
144CRITICAL_SECTION __kmp_win32_section;
145
Jonathan Peyton30419822017-05-12 18:01:32 +0000146void __kmp_win32_mutex_init(kmp_win32_mutex_t *mx) {
147 InitializeCriticalSection(&mx->cs);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000148#if USE_ITT_BUILD
Jonathan Peyton30419822017-05-12 18:01:32 +0000149 __kmp_itt_system_object_created(&mx->cs, "Critical Section");
Jim Cownie5e8470a2013-09-27 10:38:44 +0000150#endif /* USE_ITT_BUILD */
151}
152
Jonathan Peyton30419822017-05-12 18:01:32 +0000153void __kmp_win32_mutex_destroy(kmp_win32_mutex_t *mx) {
154 DeleteCriticalSection(&mx->cs);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000155}
156
Jonathan Peyton30419822017-05-12 18:01:32 +0000157void __kmp_win32_mutex_lock(kmp_win32_mutex_t *mx) {
158 EnterCriticalSection(&mx->cs);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000159}
160
Jonathan Peyton9b8bb322019-01-16 20:07:39 +0000161int __kmp_win32_mutex_trylock(kmp_win32_mutex_t *mx) {
162 return TryEnterCriticalSection(&mx->cs);
163}
164
Jonathan Peyton30419822017-05-12 18:01:32 +0000165void __kmp_win32_mutex_unlock(kmp_win32_mutex_t *mx) {
166 LeaveCriticalSection(&mx->cs);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000167}
168
Jonathan Peyton30419822017-05-12 18:01:32 +0000169void __kmp_win32_cond_init(kmp_win32_cond_t *cv) {
170 cv->waiters_count_ = 0;
171 cv->wait_generation_count_ = 0;
172 cv->release_count_ = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000173
Jonathan Peyton30419822017-05-12 18:01:32 +0000174 /* Initialize the critical section */
175 __kmp_win32_mutex_init(&cv->waiters_count_lock_);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000176
Jonathan Peyton30419822017-05-12 18:01:32 +0000177 /* Create a manual-reset event. */
178 cv->event_ = CreateEvent(NULL, // no security
179 TRUE, // manual-reset
180 FALSE, // non-signaled initially
181 NULL); // unnamed
Jim Cownie5e8470a2013-09-27 10:38:44 +0000182#if USE_ITT_BUILD
Jonathan Peyton30419822017-05-12 18:01:32 +0000183 __kmp_itt_system_object_created(cv->event_, "Event");
Jim Cownie5e8470a2013-09-27 10:38:44 +0000184#endif /* USE_ITT_BUILD */
185}
186
Jonathan Peyton30419822017-05-12 18:01:32 +0000187void __kmp_win32_cond_destroy(kmp_win32_cond_t *cv) {
188 __kmp_win32_mutex_destroy(&cv->waiters_count_lock_);
189 __kmp_free_handle(cv->event_);
190 memset(cv, '\0', sizeof(*cv));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000191}
192
193/* TODO associate cv with a team instead of a thread so as to optimize
Jonathan Peyton30419822017-05-12 18:01:32 +0000194 the case where we wake up a whole team */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000195
Jonathan Peytonb727d382019-04-04 20:35:29 +0000196template <class C>
197static void __kmp_win32_cond_wait(kmp_win32_cond_t *cv, kmp_win32_mutex_t *mx,
198 kmp_info_t *th, C *flag) {
Jonathan Peyton30419822017-05-12 18:01:32 +0000199 int my_generation;
200 int last_waiter;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000201
Jonathan Peyton30419822017-05-12 18:01:32 +0000202 /* Avoid race conditions */
203 __kmp_win32_mutex_lock(&cv->waiters_count_lock_);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000204
Jonathan Peyton30419822017-05-12 18:01:32 +0000205 /* Increment count of waiters */
206 cv->waiters_count_++;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000207
Jonathan Peyton30419822017-05-12 18:01:32 +0000208 /* Store current generation in our activation record. */
209 my_generation = cv->wait_generation_count_;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000210
Jonathan Peyton30419822017-05-12 18:01:32 +0000211 __kmp_win32_mutex_unlock(&cv->waiters_count_lock_);
212 __kmp_win32_mutex_unlock(mx);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000213
Jonathan Peyton30419822017-05-12 18:01:32 +0000214 for (;;) {
Jonathan Peytonb727d382019-04-04 20:35:29 +0000215 int wait_done = 0;
216 DWORD res, timeout = 5000; // just tried to quess an appropriate number
Jonathan Peyton30419822017-05-12 18:01:32 +0000217 /* Wait until the event is signaled */
Jonathan Peytonb727d382019-04-04 20:35:29 +0000218 res = WaitForSingleObject(cv->event_, timeout);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000219
Jonathan Peytonb727d382019-04-04 20:35:29 +0000220 if (res == WAIT_OBJECT_0) {
221 // event signaled
222 __kmp_win32_mutex_lock(&cv->waiters_count_lock_);
223 /* Exit the loop when the <cv->event_> is signaled and there are still
224 waiting threads from this <wait_generation> that haven't been released
225 from this wait yet. */
226 wait_done = (cv->release_count_ > 0) &&
227 (cv->wait_generation_count_ != my_generation);
228 __kmp_win32_mutex_unlock(&cv->waiters_count_lock_);
229 } else if (res == WAIT_TIMEOUT || res == WAIT_FAILED) {
230 // check if the flag and cv counters are in consistent state
231 // as MS sent us debug dump whith inconsistent state of data
232 __kmp_win32_mutex_lock(mx);
233 typename C::flag_t old_f = flag->set_sleeping();
234 if (!flag->done_check_val(old_f & ~KMP_BARRIER_SLEEP_STATE)) {
235 __kmp_win32_mutex_unlock(mx);
236 continue;
237 }
238 // condition fulfilled, exiting
239 old_f = flag->unset_sleeping();
240 KMP_DEBUG_ASSERT(old_f & KMP_BARRIER_SLEEP_STATE);
241 TCW_PTR(th->th.th_sleep_loc, NULL);
242 KF_TRACE(50, ("__kmp_win32_cond_wait: exiting, condition "
243 "fulfilled: flag's loc(%p): %u => %u\n",
244 flag->get(), old_f, *(flag->get())));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000245
Jonathan Peytonb727d382019-04-04 20:35:29 +0000246 __kmp_win32_mutex_lock(&cv->waiters_count_lock_);
247 KMP_DEBUG_ASSERT(cv->waiters_count_ > 0);
248 cv->release_count_ = cv->waiters_count_;
249 cv->wait_generation_count_++;
250 wait_done = 1;
251 __kmp_win32_mutex_unlock(&cv->waiters_count_lock_);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000252
Jonathan Peytonb727d382019-04-04 20:35:29 +0000253 __kmp_win32_mutex_unlock(mx);
254 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000255 /* there used to be a semicolon after the if statement, it looked like a
256 bug, so i removed it */
257 if (wait_done)
258 break;
259 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000260
Jonathan Peyton30419822017-05-12 18:01:32 +0000261 __kmp_win32_mutex_lock(mx);
262 __kmp_win32_mutex_lock(&cv->waiters_count_lock_);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000263
Jonathan Peyton30419822017-05-12 18:01:32 +0000264 cv->waiters_count_--;
265 cv->release_count_--;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000266
Jonathan Peyton30419822017-05-12 18:01:32 +0000267 last_waiter = (cv->release_count_ == 0);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000268
Jonathan Peyton30419822017-05-12 18:01:32 +0000269 __kmp_win32_mutex_unlock(&cv->waiters_count_lock_);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000270
Jonathan Peyton30419822017-05-12 18:01:32 +0000271 if (last_waiter) {
272 /* We're the last waiter to be notified, so reset the manual event. */
273 ResetEvent(cv->event_);
274 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000275}
276
Jonathan Peyton30419822017-05-12 18:01:32 +0000277void __kmp_win32_cond_broadcast(kmp_win32_cond_t *cv) {
278 __kmp_win32_mutex_lock(&cv->waiters_count_lock_);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000279
Jonathan Peyton30419822017-05-12 18:01:32 +0000280 if (cv->waiters_count_ > 0) {
281 SetEvent(cv->event_);
282 /* Release all the threads in this generation. */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000283
Jonathan Peyton30419822017-05-12 18:01:32 +0000284 cv->release_count_ = cv->waiters_count_;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000285
Jonathan Peyton30419822017-05-12 18:01:32 +0000286 /* Start a new generation. */
287 cv->wait_generation_count_++;
288 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000289
Jonathan Peyton30419822017-05-12 18:01:32 +0000290 __kmp_win32_mutex_unlock(&cv->waiters_count_lock_);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000291}
292
Jonathan Peyton30419822017-05-12 18:01:32 +0000293void __kmp_win32_cond_signal(kmp_win32_cond_t *cv) {
294 __kmp_win32_cond_broadcast(cv);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000295}
296
Jonathan Peyton30419822017-05-12 18:01:32 +0000297void __kmp_enable(int new_state) {
298 if (__kmp_init_runtime)
299 LeaveCriticalSection(&__kmp_win32_section);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000300}
301
Jonathan Peyton30419822017-05-12 18:01:32 +0000302void __kmp_disable(int *old_state) {
303 *old_state = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000304
Jonathan Peyton30419822017-05-12 18:01:32 +0000305 if (__kmp_init_runtime)
306 EnterCriticalSection(&__kmp_win32_section);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000307}
308
Jonathan Peyton30419822017-05-12 18:01:32 +0000309void __kmp_suspend_initialize(void) { /* do nothing */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000310}
311
Jonathan Peyton30419822017-05-12 18:01:32 +0000312static void __kmp_suspend_initialize_thread(kmp_info_t *th) {
313 if (!TCR_4(th->th.th_suspend_init)) {
314 /* this means we haven't initialized the suspension pthread objects for this
315 thread in this instance of the process */
316 __kmp_win32_cond_init(&th->th.th_suspend_cv);
317 __kmp_win32_mutex_init(&th->th.th_suspend_mx);
318 TCW_4(th->th.th_suspend_init, TRUE);
319 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000320}
321
Jonathan Peyton30419822017-05-12 18:01:32 +0000322void __kmp_suspend_uninitialize_thread(kmp_info_t *th) {
323 if (TCR_4(th->th.th_suspend_init)) {
324 /* this means we have initialize the suspension pthread objects for this
325 thread in this instance of the process */
326 __kmp_win32_cond_destroy(&th->th.th_suspend_cv);
327 __kmp_win32_mutex_destroy(&th->th.th_suspend_mx);
328 TCW_4(th->th.th_suspend_init, FALSE);
329 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000330}
331
Jonathan Peyton9b8bb322019-01-16 20:07:39 +0000332int __kmp_try_suspend_mx(kmp_info_t *th) {
333 return __kmp_win32_mutex_trylock(&th->th.th_suspend_mx);
334}
335
336void __kmp_lock_suspend_mx(kmp_info_t *th) {
337 __kmp_win32_mutex_lock(&th->th.th_suspend_mx);
338}
339
340void __kmp_unlock_suspend_mx(kmp_info_t *th) {
341 __kmp_win32_mutex_unlock(&th->th.th_suspend_mx);
342}
343
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000344/* This routine puts the calling thread to sleep after setting the
Jonathan Peyton30419822017-05-12 18:01:32 +0000345 sleep bit for the indicated flag variable to true. */
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000346template <class C>
Jonathan Peyton30419822017-05-12 18:01:32 +0000347static inline void __kmp_suspend_template(int th_gtid, C *flag) {
348 kmp_info_t *th = __kmp_threads[th_gtid];
349 int status;
350 typename C::flag_t old_spin;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000351
Jonathan Peyton30419822017-05-12 18:01:32 +0000352 KF_TRACE(30, ("__kmp_suspend_template: T#%d enter for flag's loc(%p)\n",
353 th_gtid, flag->get()));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000354
Jonathan Peyton30419822017-05-12 18:01:32 +0000355 __kmp_suspend_initialize_thread(th);
356 __kmp_win32_mutex_lock(&th->th.th_suspend_mx);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000357
Jonathan Peyton30419822017-05-12 18:01:32 +0000358 KF_TRACE(10, ("__kmp_suspend_template: T#%d setting sleep bit for flag's"
359 " loc(%p)\n",
360 th_gtid, flag->get()));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000361
Jonathan Peyton30419822017-05-12 18:01:32 +0000362 /* TODO: shouldn't this use release semantics to ensure that
363 __kmp_suspend_initialize_thread gets called first? */
364 old_spin = flag->set_sleeping();
Jonathan Peyton9b8bb322019-01-16 20:07:39 +0000365#if OMP_50_ENABLED
366 if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME &&
367 __kmp_pause_status != kmp_soft_paused) {
368 flag->unset_sleeping();
369 __kmp_win32_mutex_unlock(&th->th.th_suspend_mx);
370 return;
371 }
372#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000373
Jonathan Peyton30419822017-05-12 18:01:32 +0000374 KF_TRACE(5, ("__kmp_suspend_template: T#%d set sleep bit for flag's"
375 " loc(%p)==%d\n",
376 th_gtid, flag->get(), *(flag->get())));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000377
Jonathan Peyton30419822017-05-12 18:01:32 +0000378 if (flag->done_check_val(old_spin)) {
379 old_spin = flag->unset_sleeping();
380 KF_TRACE(5, ("__kmp_suspend_template: T#%d false alarm, reset sleep bit "
381 "for flag's loc(%p)\n",
382 th_gtid, flag->get()));
383 } else {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000384#ifdef DEBUG_SUSPEND
Jonathan Peyton30419822017-05-12 18:01:32 +0000385 __kmp_suspend_count++;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000386#endif
Jonathan Peyton30419822017-05-12 18:01:32 +0000387 /* Encapsulate in a loop as the documentation states that this may "with
388 low probability" return when the condition variable has not been signaled
389 or broadcast */
390 int deactivated = FALSE;
391 TCW_PTR(th->th.th_sleep_loc, (void *)flag);
392 while (flag->is_sleeping()) {
393 KF_TRACE(15, ("__kmp_suspend_template: T#%d about to perform "
394 "kmp_win32_cond_wait()\n",
395 th_gtid));
396 // Mark the thread as no longer active (only in the first iteration of the
397 // loop).
398 if (!deactivated) {
399 th->th.th_active = FALSE;
400 if (th->th.th_active_in_pool) {
401 th->th.th_active_in_pool = FALSE;
Jonathan Peyton37e2ef52018-07-09 17:36:22 +0000402 KMP_ATOMIC_DEC(&__kmp_thread_pool_active_nth);
Jonathan Peyton30419822017-05-12 18:01:32 +0000403 KMP_DEBUG_ASSERT(TCR_4(__kmp_thread_pool_active_nth) >= 0);
404 }
405 deactivated = TRUE;
Jonathan Peytonb727d382019-04-04 20:35:29 +0000406 __kmp_win32_cond_wait(&th->th.th_suspend_cv, &th->th.th_suspend_mx, th,
407 flag);
Jonathan Peyton30419822017-05-12 18:01:32 +0000408 } else {
Jonathan Peytonb727d382019-04-04 20:35:29 +0000409 __kmp_win32_cond_wait(&th->th.th_suspend_cv, &th->th.th_suspend_mx, th,
410 flag);
Jonathan Peyton30419822017-05-12 18:01:32 +0000411 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000412
413#ifdef KMP_DEBUG
Jonathan Peyton30419822017-05-12 18:01:32 +0000414 if (flag->is_sleeping()) {
415 KF_TRACE(100,
416 ("__kmp_suspend_template: T#%d spurious wakeup\n", th_gtid));
417 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000418#endif /* KMP_DEBUG */
419
Jonathan Peyton30419822017-05-12 18:01:32 +0000420 } // while
Jim Cownie5e8470a2013-09-27 10:38:44 +0000421
Jonathan Peyton30419822017-05-12 18:01:32 +0000422 // Mark the thread as active again (if it was previous marked as inactive)
423 if (deactivated) {
424 th->th.th_active = TRUE;
425 if (TCR_4(th->th.th_in_pool)) {
Jonathan Peyton37e2ef52018-07-09 17:36:22 +0000426 KMP_ATOMIC_INC(&__kmp_thread_pool_active_nth);
Jonathan Peyton30419822017-05-12 18:01:32 +0000427 th->th.th_active_in_pool = TRUE;
428 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000429 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000430 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000431
Jonathan Peyton30419822017-05-12 18:01:32 +0000432 __kmp_win32_mutex_unlock(&th->th.th_suspend_mx);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000433
Jonathan Peyton30419822017-05-12 18:01:32 +0000434 KF_TRACE(30, ("__kmp_suspend_template: T#%d exit\n", th_gtid));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000435}
436
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000437void __kmp_suspend_32(int th_gtid, kmp_flag_32 *flag) {
Jonathan Peyton30419822017-05-12 18:01:32 +0000438 __kmp_suspend_template(th_gtid, flag);
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000439}
440void __kmp_suspend_64(int th_gtid, kmp_flag_64 *flag) {
Jonathan Peyton30419822017-05-12 18:01:32 +0000441 __kmp_suspend_template(th_gtid, flag);
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000442}
443void __kmp_suspend_oncore(int th_gtid, kmp_flag_oncore *flag) {
Jonathan Peyton30419822017-05-12 18:01:32 +0000444 __kmp_suspend_template(th_gtid, flag);
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000445}
446
Jim Cownie5e8470a2013-09-27 10:38:44 +0000447/* This routine signals the thread specified by target_gtid to wake up
Jonathan Peyton30419822017-05-12 18:01:32 +0000448 after setting the sleep bit indicated by the flag argument to FALSE */
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000449template <class C>
Jonathan Peyton30419822017-05-12 18:01:32 +0000450static inline void __kmp_resume_template(int target_gtid, C *flag) {
451 kmp_info_t *th = __kmp_threads[target_gtid];
452 int status;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000453
454#ifdef KMP_DEBUG
Jonathan Peyton30419822017-05-12 18:01:32 +0000455 int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000456#endif
457
Jonathan Peyton30419822017-05-12 18:01:32 +0000458 KF_TRACE(30, ("__kmp_resume_template: T#%d wants to wakeup T#%d enter\n",
459 gtid, target_gtid));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000460
Jonathan Peyton30419822017-05-12 18:01:32 +0000461 __kmp_suspend_initialize_thread(th);
462 __kmp_win32_mutex_lock(&th->th.th_suspend_mx);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000463
Jonathan Peyton30419822017-05-12 18:01:32 +0000464 if (!flag) { // coming from __kmp_null_resume_wrapper
465 flag = (C *)th->th.th_sleep_loc;
466 }
467
468 // First, check if the flag is null or its type has changed. If so, someone
469 // else woke it up.
470 if (!flag || flag->get_type() != flag->get_ptr_type()) { // get_ptr_type
471 // simply shows what
472 // flag was cast to
473 KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already "
474 "awake: flag's loc(%p)\n",
475 gtid, target_gtid, NULL));
476 __kmp_win32_mutex_unlock(&th->th.th_suspend_mx);
477 return;
478 } else {
479 typename C::flag_t old_spin = flag->unset_sleeping();
480 if (!flag->is_sleeping_val(old_spin)) {
481 KF_TRACE(5, ("__kmp_resume_template: T#%d exiting, thread T#%d already "
482 "awake: flag's loc(%p): %u => %u\n",
483 gtid, target_gtid, flag->get(), old_spin, *(flag->get())));
484 __kmp_win32_mutex_unlock(&th->th.th_suspend_mx);
485 return;
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000486 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000487 }
488 TCW_PTR(th->th.th_sleep_loc, NULL);
489 KF_TRACE(5, ("__kmp_resume_template: T#%d about to wakeup T#%d, reset sleep "
490 "bit for flag's loc(%p)\n",
491 gtid, target_gtid, flag->get()));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000492
Jonathan Peyton30419822017-05-12 18:01:32 +0000493 __kmp_win32_cond_signal(&th->th.th_suspend_cv);
494 __kmp_win32_mutex_unlock(&th->th.th_suspend_mx);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000495
Jonathan Peyton30419822017-05-12 18:01:32 +0000496 KF_TRACE(30, ("__kmp_resume_template: T#%d exiting after signaling wake up"
497 " for T#%d\n",
498 gtid, target_gtid));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000499}
500
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000501void __kmp_resume_32(int target_gtid, kmp_flag_32 *flag) {
Jonathan Peyton30419822017-05-12 18:01:32 +0000502 __kmp_resume_template(target_gtid, flag);
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000503}
504void __kmp_resume_64(int target_gtid, kmp_flag_64 *flag) {
Jonathan Peyton30419822017-05-12 18:01:32 +0000505 __kmp_resume_template(target_gtid, flag);
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000506}
507void __kmp_resume_oncore(int target_gtid, kmp_flag_oncore *flag) {
Jonathan Peyton30419822017-05-12 18:01:32 +0000508 __kmp_resume_template(target_gtid, flag);
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000509}
510
Jonathan Peytone47d32f2019-02-28 19:11:29 +0000511void __kmp_yield() { Sleep(0); }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000512
Jonathan Peyton30419822017-05-12 18:01:32 +0000513void __kmp_gtid_set_specific(int gtid) {
514 if (__kmp_init_gtid) {
515 KA_TRACE(50, ("__kmp_gtid_set_specific: T#%d key:%d\n", gtid,
516 __kmp_gtid_threadprivate_key));
517 if (!TlsSetValue(__kmp_gtid_threadprivate_key, (LPVOID)(gtid + 1)))
518 KMP_FATAL(TLSSetValueFailed);
519 } else {
520 KA_TRACE(50, ("__kmp_gtid_set_specific: runtime shutdown, returning\n"));
521 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000522}
523
Jonathan Peyton30419822017-05-12 18:01:32 +0000524int __kmp_gtid_get_specific() {
525 int gtid;
526 if (!__kmp_init_gtid) {
527 KA_TRACE(50, ("__kmp_gtid_get_specific: runtime shutdown, returning "
528 "KMP_GTID_SHUTDOWN\n"));
529 return KMP_GTID_SHUTDOWN;
530 }
531 gtid = (int)(kmp_intptr_t)TlsGetValue(__kmp_gtid_threadprivate_key);
532 if (gtid == 0) {
533 gtid = KMP_GTID_DNE;
534 } else {
535 gtid--;
536 }
537 KA_TRACE(50, ("__kmp_gtid_get_specific: key:%d gtid:%d\n",
538 __kmp_gtid_threadprivate_key, gtid));
539 return gtid;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000540}
541
Jonathan Peyton30419822017-05-12 18:01:32 +0000542void __kmp_affinity_bind_thread(int proc) {
543 if (__kmp_num_proc_groups > 1) {
544 // Form the GROUP_AFFINITY struct directly, rather than filling
545 // out a bit vector and calling __kmp_set_system_affinity().
546 GROUP_AFFINITY ga;
547 KMP_DEBUG_ASSERT((proc >= 0) && (proc < (__kmp_num_proc_groups * CHAR_BIT *
548 sizeof(DWORD_PTR))));
549 ga.Group = proc / (CHAR_BIT * sizeof(DWORD_PTR));
550 ga.Mask = (unsigned long long)1 << (proc % (CHAR_BIT * sizeof(DWORD_PTR)));
551 ga.Reserved[0] = ga.Reserved[1] = ga.Reserved[2] = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000552
Jonathan Peyton30419822017-05-12 18:01:32 +0000553 KMP_DEBUG_ASSERT(__kmp_SetThreadGroupAffinity != NULL);
554 if (__kmp_SetThreadGroupAffinity(GetCurrentThread(), &ga, NULL) == 0) {
555 DWORD error = GetLastError();
556 if (__kmp_affinity_verbose) { // AC: continue silently if not verbose
557 kmp_msg_t err_code = KMP_ERR(error);
558 __kmp_msg(kmp_ms_warning, KMP_MSG(CantSetThreadAffMask), err_code,
559 __kmp_msg_null);
560 if (__kmp_generate_warnings == kmp_warnings_off) {
561 __kmp_str_free(&err_code.str);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000562 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000563 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000564 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000565 } else {
566 kmp_affin_mask_t *mask;
567 KMP_CPU_ALLOC_ON_STACK(mask);
568 KMP_CPU_ZERO(mask);
569 KMP_CPU_SET(proc, mask);
570 __kmp_set_system_affinity(mask, TRUE);
571 KMP_CPU_FREE_FROM_STACK(mask);
572 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000573}
574
Jonathan Peyton30419822017-05-12 18:01:32 +0000575void __kmp_affinity_determine_capable(const char *env_var) {
576// All versions of Windows* OS (since Win '95) support SetThreadAffinityMask().
Jim Cownie5e8470a2013-09-27 10:38:44 +0000577
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000578#if KMP_GROUP_AFFINITY
Jonathan Peyton30419822017-05-12 18:01:32 +0000579 KMP_AFFINITY_ENABLE(__kmp_num_proc_groups * sizeof(DWORD_PTR));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000580#else
Jonathan Peyton30419822017-05-12 18:01:32 +0000581 KMP_AFFINITY_ENABLE(sizeof(DWORD_PTR));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000582#endif
583
Jonathan Peyton30419822017-05-12 18:01:32 +0000584 KA_TRACE(10, ("__kmp_affinity_determine_capable: "
585 "Windows* OS affinity interface functional (mask size = "
586 "%" KMP_SIZE_T_SPEC ").\n",
587 __kmp_affin_mask_size));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000588}
589
Jonathan Peyton30419822017-05-12 18:01:32 +0000590double __kmp_read_cpu_time(void) {
591 FILETIME CreationTime, ExitTime, KernelTime, UserTime;
592 int status;
593 double cpu_time;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000594
Jonathan Peyton30419822017-05-12 18:01:32 +0000595 cpu_time = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000596
Jonathan Peyton30419822017-05-12 18:01:32 +0000597 status = GetProcessTimes(GetCurrentProcess(), &CreationTime, &ExitTime,
598 &KernelTime, &UserTime);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000599
Jonathan Peyton30419822017-05-12 18:01:32 +0000600 if (status) {
601 double sec = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000602
Jonathan Peyton30419822017-05-12 18:01:32 +0000603 sec += KernelTime.dwHighDateTime;
604 sec += UserTime.dwHighDateTime;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000605
Jonathan Peyton30419822017-05-12 18:01:32 +0000606 /* Shift left by 32 bits */
607 sec *= (double)(1 << 16) * (double)(1 << 16);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000608
Jonathan Peyton30419822017-05-12 18:01:32 +0000609 sec += KernelTime.dwLowDateTime;
610 sec += UserTime.dwLowDateTime;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000611
Jonathan Peyton30419822017-05-12 18:01:32 +0000612 cpu_time += (sec * 100.0) / KMP_NSEC_PER_SEC;
613 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000614
Jonathan Peyton30419822017-05-12 18:01:32 +0000615 return cpu_time;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000616}
617
Jonathan Peyton30419822017-05-12 18:01:32 +0000618int __kmp_read_system_info(struct kmp_sys_info *info) {
619 info->maxrss = 0; /* the maximum resident set size utilized (in kilobytes) */
620 info->minflt = 0; /* the number of page faults serviced without any I/O */
621 info->majflt = 0; /* the number of page faults serviced that required I/O */
622 info->nswap = 0; // the number of times a process was "swapped" out of memory
623 info->inblock = 0; // the number of times the file system had to perform input
624 info->oublock = 0; // number of times the file system had to perform output
625 info->nvcsw = 0; /* the number of times a context switch was voluntarily */
626 info->nivcsw = 0; /* the number of times a context switch was forced */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000627
Jonathan Peyton30419822017-05-12 18:01:32 +0000628 return 1;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000629}
630
Jonathan Peyton30419822017-05-12 18:01:32 +0000631void __kmp_runtime_initialize(void) {
632 SYSTEM_INFO info;
633 kmp_str_buf_t path;
634 UINT path_size;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000635
Jonathan Peyton30419822017-05-12 18:01:32 +0000636 if (__kmp_init_runtime) {
637 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000638 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000639
Jonathan Peyton99016992015-05-26 17:32:53 +0000640#if KMP_DYNAMIC_LIB
Jonathan Peyton30419822017-05-12 18:01:32 +0000641 /* Pin dynamic library for the lifetime of application */
642 {
643 // First, turn off error message boxes
644 UINT err_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
645 HMODULE h;
646 BOOL ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
647 GET_MODULE_HANDLE_EX_FLAG_PIN,
648 (LPCTSTR)&__kmp_serial_initialize, &h);
649 KMP_DEBUG_ASSERT2(h && ret, "OpenMP RTL cannot find itself loaded");
650 SetErrorMode(err_mode); // Restore error mode
651 KA_TRACE(10, ("__kmp_runtime_initialize: dynamic library pinned\n"));
652 }
Andrey Churbanov9bf53282015-01-29 17:18:20 +0000653#endif
654
Jonathan Peyton30419822017-05-12 18:01:32 +0000655 InitializeCriticalSection(&__kmp_win32_section);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000656#if USE_ITT_BUILD
Jonathan Peyton30419822017-05-12 18:01:32 +0000657 __kmp_itt_system_object_created(&__kmp_win32_section, "Critical Section");
Jim Cownie5e8470a2013-09-27 10:38:44 +0000658#endif /* USE_ITT_BUILD */
Jonathan Peyton30419822017-05-12 18:01:32 +0000659 __kmp_initialize_system_tick();
Jim Cownie5e8470a2013-09-27 10:38:44 +0000660
Jonathan Peyton30419822017-05-12 18:01:32 +0000661#if (KMP_ARCH_X86 || KMP_ARCH_X86_64)
662 if (!__kmp_cpuinfo.initialized) {
663 __kmp_query_cpuid(&__kmp_cpuinfo);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000664 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000665#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000666
Jonathan Peyton30419822017-05-12 18:01:32 +0000667/* Set up minimum number of threads to switch to TLS gtid */
Jonathan Peyton8b3842f2018-10-05 17:59:39 +0000668#if KMP_OS_WINDOWS && !KMP_DYNAMIC_LIB
Jonathan Peyton30419822017-05-12 18:01:32 +0000669 // Windows* OS, static library.
670 /* New thread may use stack space previously used by another thread,
671 currently terminated. On Windows* OS, in case of static linking, we do not
672 know the moment of thread termination, and our structures (__kmp_threads
673 and __kmp_root arrays) are still keep info about dead threads. This leads
674 to problem in __kmp_get_global_thread_id() function: it wrongly finds gtid
675 (by searching through stack addresses of all known threads) for
676 unregistered foreign tread.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000677
Jonathan Peyton30419822017-05-12 18:01:32 +0000678 Setting __kmp_tls_gtid_min to 0 workarounds this problem:
679 __kmp_get_global_thread_id() does not search through stacks, but get gtid
680 from TLS immediately.
681 --ln
682 */
683 __kmp_tls_gtid_min = 0;
684#else
685 __kmp_tls_gtid_min = KMP_TLS_GTID_MIN;
686#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000687
Jonathan Peyton30419822017-05-12 18:01:32 +0000688 /* for the static library */
689 if (!__kmp_gtid_threadprivate_key) {
690 __kmp_gtid_threadprivate_key = TlsAlloc();
691 if (__kmp_gtid_threadprivate_key == TLS_OUT_OF_INDEXES) {
692 KMP_FATAL(TLSOutOfIndexes);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000693 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000694 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000695
Jonathan Peyton30419822017-05-12 18:01:32 +0000696 // Load ntdll.dll.
697 /* Simple GetModuleHandle( "ntdll.dl" ) is not suitable due to security issue
698 (see http://www.microsoft.com/technet/security/advisory/2269637.mspx). We
699 have to specify full path to the library. */
700 __kmp_str_buf_init(&path);
701 path_size = GetSystemDirectory(path.str, path.size);
702 KMP_DEBUG_ASSERT(path_size > 0);
703 if (path_size >= path.size) {
704 // Buffer is too short. Expand the buffer and try again.
705 __kmp_str_buf_reserve(&path, path_size);
706 path_size = GetSystemDirectory(path.str, path.size);
707 KMP_DEBUG_ASSERT(path_size > 0);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000708 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000709 if (path_size > 0 && path_size < path.size) {
710 // Now we have system directory name in the buffer.
711 // Append backslash and name of dll to form full path,
712 path.used = path_size;
713 __kmp_str_buf_print(&path, "\\%s", "ntdll.dll");
Jim Cownie5e8470a2013-09-27 10:38:44 +0000714
Jonathan Peyton30419822017-05-12 18:01:32 +0000715 // Now load ntdll using full path.
716 ntdll = GetModuleHandle(path.str);
717 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000718
Jonathan Peyton30419822017-05-12 18:01:32 +0000719 KMP_DEBUG_ASSERT(ntdll != NULL);
720 if (ntdll != NULL) {
721 NtQuerySystemInformation = (NtQuerySystemInformation_t)GetProcAddress(
722 ntdll, "NtQuerySystemInformation");
723 }
724 KMP_DEBUG_ASSERT(NtQuerySystemInformation != NULL);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000725
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000726#if KMP_GROUP_AFFINITY
Jonathan Peyton30419822017-05-12 18:01:32 +0000727 // Load kernel32.dll.
728 // Same caveat - must use full system path name.
729 if (path_size > 0 && path_size < path.size) {
730 // Truncate the buffer back to just the system path length,
731 // discarding "\\ntdll.dll", and replacing it with "kernel32.dll".
732 path.used = path_size;
733 __kmp_str_buf_print(&path, "\\%s", "kernel32.dll");
Jim Cownie5e8470a2013-09-27 10:38:44 +0000734
Jonathan Peyton30419822017-05-12 18:01:32 +0000735 // Load kernel32.dll using full path.
736 kernel32 = GetModuleHandle(path.str);
737 KA_TRACE(10, ("__kmp_runtime_initialize: kernel32.dll = %s\n", path.str));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000738
Jonathan Peyton30419822017-05-12 18:01:32 +0000739 // Load the function pointers to kernel32.dll routines
740 // that may or may not exist on this system.
741 if (kernel32 != NULL) {
742 __kmp_GetActiveProcessorCount =
743 (kmp_GetActiveProcessorCount_t)GetProcAddress(
744 kernel32, "GetActiveProcessorCount");
745 __kmp_GetActiveProcessorGroupCount =
746 (kmp_GetActiveProcessorGroupCount_t)GetProcAddress(
747 kernel32, "GetActiveProcessorGroupCount");
748 __kmp_GetThreadGroupAffinity =
749 (kmp_GetThreadGroupAffinity_t)GetProcAddress(
750 kernel32, "GetThreadGroupAffinity");
751 __kmp_SetThreadGroupAffinity =
752 (kmp_SetThreadGroupAffinity_t)GetProcAddress(
753 kernel32, "SetThreadGroupAffinity");
Jim Cownie5e8470a2013-09-27 10:38:44 +0000754
Jonathan Peyton30419822017-05-12 18:01:32 +0000755 KA_TRACE(10, ("__kmp_runtime_initialize: __kmp_GetActiveProcessorCount"
756 " = %p\n",
757 __kmp_GetActiveProcessorCount));
758 KA_TRACE(10, ("__kmp_runtime_initialize: "
759 "__kmp_GetActiveProcessorGroupCount = %p\n",
760 __kmp_GetActiveProcessorGroupCount));
761 KA_TRACE(10, ("__kmp_runtime_initialize:__kmp_GetThreadGroupAffinity"
762 " = %p\n",
763 __kmp_GetThreadGroupAffinity));
764 KA_TRACE(10, ("__kmp_runtime_initialize: __kmp_SetThreadGroupAffinity"
765 " = %p\n",
766 __kmp_SetThreadGroupAffinity));
767 KA_TRACE(10, ("__kmp_runtime_initialize: sizeof(kmp_affin_mask_t) = %d\n",
768 sizeof(kmp_affin_mask_t)));
Andrey Churbanovdf6555b2015-01-27 17:00:03 +0000769
Jonathan Peyton30419822017-05-12 18:01:32 +0000770 // See if group affinity is supported on this system.
771 // If so, calculate the #groups and #procs.
772 //
773 // Group affinity was introduced with Windows* 7 OS and
774 // Windows* Server 2008 R2 OS.
775 if ((__kmp_GetActiveProcessorCount != NULL) &&
776 (__kmp_GetActiveProcessorGroupCount != NULL) &&
777 (__kmp_GetThreadGroupAffinity != NULL) &&
778 (__kmp_SetThreadGroupAffinity != NULL) &&
779 ((__kmp_num_proc_groups = __kmp_GetActiveProcessorGroupCount()) >
780 1)) {
781 // Calculate the total number of active OS procs.
782 int i;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000783
Jonathan Peyton30419822017-05-12 18:01:32 +0000784 KA_TRACE(10, ("__kmp_runtime_initialize: %d processor groups"
785 " detected\n",
786 __kmp_num_proc_groups));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000787
Jonathan Peyton30419822017-05-12 18:01:32 +0000788 __kmp_xproc = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000789
Jonathan Peyton30419822017-05-12 18:01:32 +0000790 for (i = 0; i < __kmp_num_proc_groups; i++) {
791 DWORD size = __kmp_GetActiveProcessorCount(i);
792 __kmp_xproc += size;
793 KA_TRACE(10, ("__kmp_runtime_initialize: proc group %d size = %d\n",
794 i, size));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000795 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000796 } else {
797 KA_TRACE(10, ("__kmp_runtime_initialize: %d processor groups"
798 " detected\n",
799 __kmp_num_proc_groups));
800 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000801 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000802 }
803 if (__kmp_num_proc_groups <= 1) {
804 GetSystemInfo(&info);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000805 __kmp_xproc = info.dwNumberOfProcessors;
Jonathan Peyton30419822017-05-12 18:01:32 +0000806 }
807#else
808 GetSystemInfo(&info);
809 __kmp_xproc = info.dwNumberOfProcessors;
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000810#endif /* KMP_GROUP_AFFINITY */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000811
Jonathan Peyton30419822017-05-12 18:01:32 +0000812 // If the OS said there were 0 procs, take a guess and use a value of 2.
813 // This is done for Linux* OS, also. Do we need error / warning?
814 if (__kmp_xproc <= 0) {
815 __kmp_xproc = 2;
816 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000817
Jonathan Peyton30419822017-05-12 18:01:32 +0000818 KA_TRACE(5,
819 ("__kmp_runtime_initialize: total processors = %d\n", __kmp_xproc));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000820
Jonathan Peyton30419822017-05-12 18:01:32 +0000821 __kmp_str_buf_free(&path);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000822
823#if USE_ITT_BUILD
Jonathan Peyton30419822017-05-12 18:01:32 +0000824 __kmp_itt_initialize();
Jim Cownie5e8470a2013-09-27 10:38:44 +0000825#endif /* USE_ITT_BUILD */
826
Jonathan Peyton30419822017-05-12 18:01:32 +0000827 __kmp_init_runtime = TRUE;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000828} // __kmp_runtime_initialize
829
Jonathan Peyton30419822017-05-12 18:01:32 +0000830void __kmp_runtime_destroy(void) {
831 if (!__kmp_init_runtime) {
832 return;
833 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000834
835#if USE_ITT_BUILD
Jonathan Peyton30419822017-05-12 18:01:32 +0000836 __kmp_itt_destroy();
Jim Cownie5e8470a2013-09-27 10:38:44 +0000837#endif /* USE_ITT_BUILD */
838
Jonathan Peyton30419822017-05-12 18:01:32 +0000839 /* we can't DeleteCriticalsection( & __kmp_win32_section ); */
840 /* due to the KX_TRACE() commands */
841 KA_TRACE(40, ("__kmp_runtime_destroy\n"));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000842
Jonathan Peyton30419822017-05-12 18:01:32 +0000843 if (__kmp_gtid_threadprivate_key) {
844 TlsFree(__kmp_gtid_threadprivate_key);
845 __kmp_gtid_threadprivate_key = 0;
846 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000847
Jonathan Peyton30419822017-05-12 18:01:32 +0000848 __kmp_affinity_uninitialize();
849 DeleteCriticalSection(&__kmp_win32_section);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000850
Jonathan Peyton30419822017-05-12 18:01:32 +0000851 ntdll = NULL;
852 NtQuerySystemInformation = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000853
854#if KMP_ARCH_X86_64
Jonathan Peyton30419822017-05-12 18:01:32 +0000855 kernel32 = NULL;
856 __kmp_GetActiveProcessorCount = NULL;
857 __kmp_GetActiveProcessorGroupCount = NULL;
858 __kmp_GetThreadGroupAffinity = NULL;
859 __kmp_SetThreadGroupAffinity = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000860#endif // KMP_ARCH_X86_64
861
Jonathan Peyton30419822017-05-12 18:01:32 +0000862 __kmp_init_runtime = FALSE;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000863}
864
Jonathan Peyton30419822017-05-12 18:01:32 +0000865void __kmp_terminate_thread(int gtid) {
866 kmp_info_t *th = __kmp_threads[gtid];
Jim Cownie5e8470a2013-09-27 10:38:44 +0000867
Jonathan Peyton30419822017-05-12 18:01:32 +0000868 if (!th)
869 return;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000870
Jonathan Peyton30419822017-05-12 18:01:32 +0000871 KA_TRACE(10, ("__kmp_terminate_thread: kill (%d)\n", gtid));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000872
Jonathan Peyton30419822017-05-12 18:01:32 +0000873 if (TerminateThread(th->th.th_info.ds.ds_thread, (DWORD)-1) == FALSE) {
874 /* It's OK, the thread may have exited already */
875 }
876 __kmp_free_handle(th->th.th_info.ds.ds_thread);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000877}
878
Jonathan Peyton30419822017-05-12 18:01:32 +0000879void __kmp_clear_system_time(void) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000880 BOOL status;
Jonathan Peyton30419822017-05-12 18:01:32 +0000881 LARGE_INTEGER time;
882 status = QueryPerformanceCounter(&time);
883 __kmp_win32_time = (kmp_int64)time.QuadPart;
884}
Jim Cownie5e8470a2013-09-27 10:38:44 +0000885
Jonathan Peyton30419822017-05-12 18:01:32 +0000886void __kmp_initialize_system_tick(void) {
887 {
888 BOOL status;
889 LARGE_INTEGER freq;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000890
Jonathan Peyton30419822017-05-12 18:01:32 +0000891 status = QueryPerformanceFrequency(&freq);
892 if (!status) {
893 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +0000894 __kmp_fatal(KMP_MSG(FunctionError, "QueryPerformanceFrequency()"),
895 KMP_ERR(error), __kmp_msg_null);
Jonathan Peyton30419822017-05-12 18:01:32 +0000896
897 } else {
898 __kmp_win32_tick = ((double)1.0) / (double)freq.QuadPart;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000899 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000900 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000901}
902
903/* Calculate the elapsed wall clock time for the user */
904
Jonathan Peyton30419822017-05-12 18:01:32 +0000905void __kmp_elapsed(double *t) {
906 BOOL status;
907 LARGE_INTEGER now;
908 status = QueryPerformanceCounter(&now);
909 *t = ((double)now.QuadPart) * __kmp_win32_tick;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000910}
911
912/* Calculate the elapsed wall clock tick for the user */
913
Jonathan Peyton30419822017-05-12 18:01:32 +0000914void __kmp_elapsed_tick(double *t) { *t = __kmp_win32_tick; }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000915
Jonathan Peyton30419822017-05-12 18:01:32 +0000916void __kmp_read_system_time(double *delta) {
917 if (delta != NULL) {
918 BOOL status;
919 LARGE_INTEGER now;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000920
Jonathan Peyton30419822017-05-12 18:01:32 +0000921 status = QueryPerformanceCounter(&now);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000922
Jonathan Peyton30419822017-05-12 18:01:32 +0000923 *delta = ((double)(((kmp_int64)now.QuadPart) - __kmp_win32_time)) *
924 __kmp_win32_tick;
925 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000926}
927
Jonathan Peytonb66d1aa2016-09-27 17:11:17 +0000928/* Return the current time stamp in nsec */
Jonathan Peyton30419822017-05-12 18:01:32 +0000929kmp_uint64 __kmp_now_nsec() {
930 LARGE_INTEGER now;
931 QueryPerformanceCounter(&now);
932 return 1e9 * __kmp_win32_tick * now.QuadPart;
Jonathan Peytonb66d1aa2016-09-27 17:11:17 +0000933}
934
Andrey Churbanovf700e9e2018-12-10 13:45:00 +0000935extern "C"
Jonathan Peyton30419822017-05-12 18:01:32 +0000936void *__stdcall __kmp_launch_worker(void *arg) {
937 volatile void *stack_data;
938 void *exit_val;
939 void *padding = 0;
940 kmp_info_t *this_thr = (kmp_info_t *)arg;
941 int gtid;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000942
Jonathan Peyton30419822017-05-12 18:01:32 +0000943 gtid = this_thr->th.th_info.ds.ds_gtid;
944 __kmp_gtid_set_specific(gtid);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000945#ifdef KMP_TDATA_GTID
Jonathan Peyton30419822017-05-12 18:01:32 +0000946#error "This define causes problems with LoadLibrary() + declspec(thread) " \
Jim Cownie5e8470a2013-09-27 10:38:44 +0000947 "on Windows* OS. See CQ50564, tests kmp_load_library*.c and this MSDN " \
948 "reference: http://support.microsoft.com/kb/118816"
Jonathan Peyton30419822017-05-12 18:01:32 +0000949//__kmp_gtid = gtid;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000950#endif
951
952#if USE_ITT_BUILD
Jonathan Peyton30419822017-05-12 18:01:32 +0000953 __kmp_itt_thread_name(gtid);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000954#endif /* USE_ITT_BUILD */
955
Jonathan Peyton30419822017-05-12 18:01:32 +0000956 __kmp_affinity_set_init_mask(gtid, FALSE);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000957
958#if KMP_ARCH_X86 || KMP_ARCH_X86_64
Jonathan Peyton30419822017-05-12 18:01:32 +0000959 // Set FP control regs to be a copy of the parallel initialization thread's.
960 __kmp_clear_x87_fpu_status_word();
961 __kmp_load_x87_fpu_control_word(&__kmp_init_x87_fpu_control_word);
962 __kmp_load_mxcsr(&__kmp_init_mxcsr);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000963#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
964
Jonathan Peyton30419822017-05-12 18:01:32 +0000965 if (__kmp_stkoffset > 0 && gtid > 0) {
966 padding = KMP_ALLOCA(gtid * __kmp_stkoffset);
967 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000968
Jonathan Peyton30419822017-05-12 18:01:32 +0000969 KMP_FSYNC_RELEASING(&this_thr->th.th_info.ds.ds_alive);
970 this_thr->th.th_info.ds.ds_thread_id = GetCurrentThreadId();
971 TCW_4(this_thr->th.th_info.ds.ds_alive, TRUE);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000972
Jonathan Peyton30419822017-05-12 18:01:32 +0000973 if (TCR_4(__kmp_gtid_mode) <
974 2) { // check stack only if it is used to get gtid
975 TCW_PTR(this_thr->th.th_info.ds.ds_stackbase, &stack_data);
976 KMP_ASSERT(this_thr->th.th_info.ds.ds_stackgrow == FALSE);
977 __kmp_check_stack_overlap(this_thr);
978 }
979 KMP_MB();
980 exit_val = __kmp_launch_thread(this_thr);
981 KMP_FSYNC_RELEASING(&this_thr->th.th_info.ds.ds_alive);
982 TCW_4(this_thr->th.th_info.ds.ds_alive, FALSE);
983 KMP_MB();
984 return exit_val;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000985}
986
Jonathan Peytonb66d1aa2016-09-27 17:11:17 +0000987#if KMP_USE_MONITOR
Jim Cownie5e8470a2013-09-27 10:38:44 +0000988/* The monitor thread controls all of the threads in the complex */
989
Jonathan Peyton30419822017-05-12 18:01:32 +0000990void *__stdcall __kmp_launch_monitor(void *arg) {
991 DWORD wait_status;
992 kmp_thread_t monitor;
993 int status;
994 int interval;
995 kmp_info_t *this_thr = (kmp_info_t *)arg;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000996
Jonathan Peyton30419822017-05-12 18:01:32 +0000997 KMP_DEBUG_ASSERT(__kmp_init_monitor);
998 TCW_4(__kmp_init_monitor, 2); // AC: Signal library that monitor has started
999 // TODO: hide "2" in enum (like {true,false,started})
1000 this_thr->th.th_info.ds.ds_thread_id = GetCurrentThreadId();
1001 TCW_4(this_thr->th.th_info.ds.ds_alive, TRUE);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001002
Jonathan Peyton30419822017-05-12 18:01:32 +00001003 KMP_MB(); /* Flush all pending memory write invalidates. */
1004 KA_TRACE(10, ("__kmp_launch_monitor: launched\n"));
Jim Cownie5e8470a2013-09-27 10:38:44 +00001005
Jonathan Peyton30419822017-05-12 18:01:32 +00001006 monitor = GetCurrentThread();
Jim Cownie5e8470a2013-09-27 10:38:44 +00001007
Jonathan Peyton30419822017-05-12 18:01:32 +00001008 /* set thread priority */
1009 status = SetThreadPriority(monitor, THREAD_PRIORITY_HIGHEST);
1010 if (!status) {
1011 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +00001012 __kmp_fatal(KMP_MSG(CantSetThreadPriority), KMP_ERR(error), __kmp_msg_null);
Jonathan Peyton30419822017-05-12 18:01:32 +00001013 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001014
Jonathan Peyton30419822017-05-12 18:01:32 +00001015 /* register us as monitor */
1016 __kmp_gtid_set_specific(KMP_GTID_MONITOR);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001017#ifdef KMP_TDATA_GTID
Jonathan Peyton30419822017-05-12 18:01:32 +00001018#error "This define causes problems with LoadLibrary() + declspec(thread) " \
Jim Cownie5e8470a2013-09-27 10:38:44 +00001019 "on Windows* OS. See CQ50564, tests kmp_load_library*.c and this MSDN " \
1020 "reference: http://support.microsoft.com/kb/118816"
Jonathan Peyton30419822017-05-12 18:01:32 +00001021//__kmp_gtid = KMP_GTID_MONITOR;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001022#endif
1023
1024#if USE_ITT_BUILD
Jonathan Peyton30419822017-05-12 18:01:32 +00001025 __kmp_itt_thread_ignore(); // Instruct Intel(R) Threading Tools to ignore
1026// monitor thread.
Jim Cownie5e8470a2013-09-27 10:38:44 +00001027#endif /* USE_ITT_BUILD */
1028
Jonathan Peyton30419822017-05-12 18:01:32 +00001029 KMP_MB(); /* Flush all pending memory write invalidates. */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001030
Jonathan Peyton30419822017-05-12 18:01:32 +00001031 interval = (1000 / __kmp_monitor_wakeups); /* in milliseconds */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001032
Jonathan Peyton30419822017-05-12 18:01:32 +00001033 while (!TCR_4(__kmp_global.g.g_done)) {
1034 /* This thread monitors the state of the system */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001035
Jonathan Peyton30419822017-05-12 18:01:32 +00001036 KA_TRACE(15, ("__kmp_launch_monitor: update\n"));
Jim Cownie5e8470a2013-09-27 10:38:44 +00001037
Jonathan Peyton30419822017-05-12 18:01:32 +00001038 wait_status = WaitForSingleObject(__kmp_monitor_ev, interval);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001039
Jonathan Peyton30419822017-05-12 18:01:32 +00001040 if (wait_status == WAIT_TIMEOUT) {
1041 TCW_4(__kmp_global.g.g_time.dt.t_value,
1042 TCR_4(__kmp_global.g.g_time.dt.t_value) + 1);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001043 }
1044
Jonathan Peyton30419822017-05-12 18:01:32 +00001045 KMP_MB(); /* Flush all pending memory write invalidates. */
1046 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001047
Jonathan Peyton30419822017-05-12 18:01:32 +00001048 KA_TRACE(10, ("__kmp_launch_monitor: finished\n"));
1049
1050 status = SetThreadPriority(monitor, THREAD_PRIORITY_NORMAL);
1051 if (!status) {
1052 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +00001053 __kmp_fatal(KMP_MSG(CantSetThreadPriority), KMP_ERR(error), __kmp_msg_null);
Jonathan Peyton30419822017-05-12 18:01:32 +00001054 }
1055
1056 if (__kmp_global.g.g_abort != 0) {
1057 /* now we need to terminate the worker threads */
1058 /* the value of t_abort is the signal we caught */
1059 int gtid;
1060
1061 KA_TRACE(10, ("__kmp_launch_monitor: terminate sig=%d\n",
1062 (__kmp_global.g.g_abort)));
1063
1064 /* terminate the OpenMP worker threads */
1065 /* TODO this is not valid for sibling threads!!
1066 * the uber master might not be 0 anymore.. */
1067 for (gtid = 1; gtid < __kmp_threads_capacity; ++gtid)
1068 __kmp_terminate_thread(gtid);
1069
1070 __kmp_cleanup();
1071
1072 Sleep(0);
1073
1074 KA_TRACE(10,
1075 ("__kmp_launch_monitor: raise sig=%d\n", __kmp_global.g.g_abort));
1076
1077 if (__kmp_global.g.g_abort > 0) {
1078 raise(__kmp_global.g.g_abort);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001079 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001080 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001081
Jonathan Peyton30419822017-05-12 18:01:32 +00001082 TCW_4(this_thr->th.th_info.ds.ds_alive, FALSE);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001083
Jonathan Peyton30419822017-05-12 18:01:32 +00001084 KMP_MB();
1085 return arg;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001086}
Jonathan Peytonb66d1aa2016-09-27 17:11:17 +00001087#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +00001088
Jonathan Peyton30419822017-05-12 18:01:32 +00001089void __kmp_create_worker(int gtid, kmp_info_t *th, size_t stack_size) {
1090 kmp_thread_t handle;
1091 DWORD idThread;
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001092
Jonathan Peyton30419822017-05-12 18:01:32 +00001093 KA_TRACE(10, ("__kmp_create_worker: try to create thread (%d)\n", gtid));
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001094
Jonathan Peyton30419822017-05-12 18:01:32 +00001095 th->th.th_info.ds.ds_gtid = gtid;
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001096
Jonathan Peyton30419822017-05-12 18:01:32 +00001097 if (KMP_UBER_GTID(gtid)) {
1098 int stack_data;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001099
Jonathan Peyton30419822017-05-12 18:01:32 +00001100 /* TODO: GetCurrentThread() returns a pseudo-handle that is unsuitable for
1101 other threads to use. Is it appropriate to just use GetCurrentThread?
1102 When should we close this handle? When unregistering the root? */
1103 {
1104 BOOL rc;
1105 rc = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
1106 GetCurrentProcess(), &th->th.th_info.ds.ds_thread, 0,
1107 FALSE, DUPLICATE_SAME_ACCESS);
1108 KMP_ASSERT(rc);
1109 KA_TRACE(10, (" __kmp_create_worker: ROOT Handle duplicated, th = %p, "
1110 "handle = %" KMP_UINTPTR_SPEC "\n",
1111 (LPVOID)th, th->th.th_info.ds.ds_thread));
1112 th->th.th_info.ds.ds_thread_id = GetCurrentThreadId();
Jim Cownie5e8470a2013-09-27 10:38:44 +00001113 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001114 if (TCR_4(__kmp_gtid_mode) < 2) { // check stack only if used to get gtid
1115 /* we will dynamically update the stack range if gtid_mode == 1 */
1116 TCW_PTR(th->th.th_info.ds.ds_stackbase, &stack_data);
1117 TCW_PTR(th->th.th_info.ds.ds_stacksize, 0);
1118 TCW_4(th->th.th_info.ds.ds_stackgrow, TRUE);
1119 __kmp_check_stack_overlap(th);
1120 }
1121 } else {
1122 KMP_MB(); /* Flush all pending memory write invalidates. */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001123
Jonathan Peyton30419822017-05-12 18:01:32 +00001124 /* Set stack size for this thread now. */
1125 KA_TRACE(10,
1126 ("__kmp_create_worker: stack_size = %" KMP_SIZE_T_SPEC " bytes\n",
1127 stack_size));
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001128
Jonathan Peyton30419822017-05-12 18:01:32 +00001129 stack_size += gtid * __kmp_stkoffset;
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001130
Jonathan Peyton30419822017-05-12 18:01:32 +00001131 TCW_PTR(th->th.th_info.ds.ds_stacksize, stack_size);
1132 TCW_4(th->th.th_info.ds.ds_stackgrow, FALSE);
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001133
Jonathan Peyton30419822017-05-12 18:01:32 +00001134 KA_TRACE(10,
1135 ("__kmp_create_worker: (before) stack_size = %" KMP_SIZE_T_SPEC
1136 " bytes, &__kmp_launch_worker = %p, th = %p, &idThread = %p\n",
1137 (SIZE_T)stack_size, (LPTHREAD_START_ROUTINE)&__kmp_launch_worker,
1138 (LPVOID)th, &idThread));
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001139
Jonathan Peyton30419822017-05-12 18:01:32 +00001140 handle = CreateThread(
1141 NULL, (SIZE_T)stack_size, (LPTHREAD_START_ROUTINE)__kmp_launch_worker,
1142 (LPVOID)th, STACK_SIZE_PARAM_IS_A_RESERVATION, &idThread);
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001143
Jonathan Peyton30419822017-05-12 18:01:32 +00001144 KA_TRACE(10,
1145 ("__kmp_create_worker: (after) stack_size = %" KMP_SIZE_T_SPEC
1146 " bytes, &__kmp_launch_worker = %p, th = %p, "
1147 "idThread = %u, handle = %" KMP_UINTPTR_SPEC "\n",
1148 (SIZE_T)stack_size, (LPTHREAD_START_ROUTINE)&__kmp_launch_worker,
1149 (LPVOID)th, idThread, handle));
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001150
Jonathan Peyton30419822017-05-12 18:01:32 +00001151 if (handle == 0) {
1152 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +00001153 __kmp_fatal(KMP_MSG(CantCreateThread), KMP_ERR(error), __kmp_msg_null);
Jonathan Peyton30419822017-05-12 18:01:32 +00001154 } else {
1155 th->th.th_info.ds.ds_thread = handle;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001156 }
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001157
Jonathan Peyton30419822017-05-12 18:01:32 +00001158 KMP_MB(); /* Flush all pending memory write invalidates. */
1159 }
1160
1161 KA_TRACE(10, ("__kmp_create_worker: done creating thread (%d)\n", gtid));
Jim Cownie5e8470a2013-09-27 10:38:44 +00001162}
1163
Jonathan Peyton30419822017-05-12 18:01:32 +00001164int __kmp_still_running(kmp_info_t *th) {
1165 return (WAIT_TIMEOUT == WaitForSingleObject(th->th.th_info.ds.ds_thread, 0));
Jim Cownie5e8470a2013-09-27 10:38:44 +00001166}
1167
Jonathan Peytonb66d1aa2016-09-27 17:11:17 +00001168#if KMP_USE_MONITOR
Jonathan Peyton30419822017-05-12 18:01:32 +00001169void __kmp_create_monitor(kmp_info_t *th) {
1170 kmp_thread_t handle;
1171 DWORD idThread;
1172 int ideal, new_ideal;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001173
Jonathan Peyton30419822017-05-12 18:01:32 +00001174 if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME) {
1175 // We don't need monitor thread in case of MAX_BLOCKTIME
1176 KA_TRACE(10, ("__kmp_create_monitor: skipping monitor thread because of "
1177 "MAX blocktime\n"));
1178 th->th.th_info.ds.ds_tid = 0; // this makes reap_monitor no-op
1179 th->th.th_info.ds.ds_gtid = 0;
1180 TCW_4(__kmp_init_monitor, 2); // Signal to stop waiting for monitor creation
1181 return;
1182 }
1183 KA_TRACE(10, ("__kmp_create_monitor: try to create monitor\n"));
Jim Cownie5e8470a2013-09-27 10:38:44 +00001184
Jonathan Peyton30419822017-05-12 18:01:32 +00001185 KMP_MB(); /* Flush all pending memory write invalidates. */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001186
Jonathan Peyton30419822017-05-12 18:01:32 +00001187 __kmp_monitor_ev = CreateEvent(NULL, TRUE, FALSE, NULL);
1188 if (__kmp_monitor_ev == NULL) {
1189 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +00001190 __kmp_fatal(KMP_MSG(CantCreateEvent), KMP_ERR(error), __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001191 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001192#if USE_ITT_BUILD
Jonathan Peyton30419822017-05-12 18:01:32 +00001193 __kmp_itt_system_object_created(__kmp_monitor_ev, "Event");
Jim Cownie5e8470a2013-09-27 10:38:44 +00001194#endif /* USE_ITT_BUILD */
1195
Jonathan Peyton30419822017-05-12 18:01:32 +00001196 th->th.th_info.ds.ds_tid = KMP_GTID_MONITOR;
1197 th->th.th_info.ds.ds_gtid = KMP_GTID_MONITOR;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001198
Jonathan Peyton30419822017-05-12 18:01:32 +00001199 // FIXME - on Windows* OS, if __kmp_monitor_stksize = 0, figure out how
1200 // to automatically expand stacksize based on CreateThread error code.
1201 if (__kmp_monitor_stksize == 0) {
1202 __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE;
1203 }
1204 if (__kmp_monitor_stksize < __kmp_sys_min_stksize) {
1205 __kmp_monitor_stksize = __kmp_sys_min_stksize;
1206 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001207
Jonathan Peyton30419822017-05-12 18:01:32 +00001208 KA_TRACE(10, ("__kmp_create_monitor: requested stacksize = %d bytes\n",
1209 (int)__kmp_monitor_stksize));
Jim Cownie5e8470a2013-09-27 10:38:44 +00001210
Jonathan Peyton30419822017-05-12 18:01:32 +00001211 TCW_4(__kmp_global.g.g_time.dt.t_value, 0);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001212
Jonathan Peyton30419822017-05-12 18:01:32 +00001213 handle =
1214 CreateThread(NULL, (SIZE_T)__kmp_monitor_stksize,
1215 (LPTHREAD_START_ROUTINE)__kmp_launch_monitor, (LPVOID)th,
1216 STACK_SIZE_PARAM_IS_A_RESERVATION, &idThread);
1217 if (handle == 0) {
1218 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +00001219 __kmp_fatal(KMP_MSG(CantCreateThread), KMP_ERR(error), __kmp_msg_null);
Jonathan Peyton30419822017-05-12 18:01:32 +00001220 } else
1221 th->th.th_info.ds.ds_thread = handle;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001222
Jonathan Peyton30419822017-05-12 18:01:32 +00001223 KMP_MB(); /* Flush all pending memory write invalidates. */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001224
Jonathan Peyton30419822017-05-12 18:01:32 +00001225 KA_TRACE(10, ("__kmp_create_monitor: monitor created %p\n",
1226 (void *)th->th.th_info.ds.ds_thread));
Jim Cownie5e8470a2013-09-27 10:38:44 +00001227}
Jonathan Peytonb66d1aa2016-09-27 17:11:17 +00001228#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +00001229
Jonathan Peyton30419822017-05-12 18:01:32 +00001230/* Check to see if thread is still alive.
1231 NOTE: The ExitProcess(code) system call causes all threads to Terminate
1232 with a exit_val = code. Because of this we can not rely on exit_val having
1233 any particular value. So this routine may return STILL_ALIVE in exit_val
1234 even after the thread is dead. */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001235
Jonathan Peyton30419822017-05-12 18:01:32 +00001236int __kmp_is_thread_alive(kmp_info_t *th, DWORD *exit_val) {
1237 DWORD rc;
1238 rc = GetExitCodeThread(th->th.th_info.ds.ds_thread, exit_val);
1239 if (rc == 0) {
1240 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +00001241 __kmp_fatal(KMP_MSG(FunctionError, "GetExitCodeThread()"), KMP_ERR(error),
1242 __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001243 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001244 return (*exit_val == STILL_ACTIVE);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001245}
1246
Jonathan Peyton30419822017-05-12 18:01:32 +00001247void __kmp_exit_thread(int exit_status) {
1248 ExitThread(exit_status);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001249} // __kmp_exit_thread
1250
Jonathan Peyton30419822017-05-12 18:01:32 +00001251// This is a common part for both __kmp_reap_worker() and __kmp_reap_monitor().
1252static void __kmp_reap_common(kmp_info_t *th) {
1253 DWORD exit_val;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001254
Jonathan Peyton30419822017-05-12 18:01:32 +00001255 KMP_MB(); /* Flush all pending memory write invalidates. */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001256
Jonathan Peyton30419822017-05-12 18:01:32 +00001257 KA_TRACE(
1258 10, ("__kmp_reap_common: try to reap (%d)\n", th->th.th_info.ds.ds_gtid));
Jim Cownie5e8470a2013-09-27 10:38:44 +00001259
Jonathan Peyton30419822017-05-12 18:01:32 +00001260 /* 2006-10-19:
1261 There are two opposite situations:
1262 1. Windows* OS keep thread alive after it resets ds_alive flag and
1263 exits from thread function. (For example, see C70770/Q394281 "unloading of
1264 dll based on OMP is very slow".)
1265 2. Windows* OS may kill thread before it resets ds_alive flag.
Jim Cownie5e8470a2013-09-27 10:38:44 +00001266
Jonathan Peyton30419822017-05-12 18:01:32 +00001267 Right solution seems to be waiting for *either* thread termination *or*
1268 ds_alive resetting. */
1269 {
Jonathan Peytone47d32f2019-02-28 19:11:29 +00001270 // TODO: This code is very similar to KMP_WAIT. Need to generalize
1271 // KMP_WAIT to cover this usage also.
Jonathan Peyton30419822017-05-12 18:01:32 +00001272 void *obj = NULL;
Ed Maste414544c2017-07-07 21:06:05 +00001273 kmp_uint32 spins;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001274#if USE_ITT_BUILD
Jonathan Peyton30419822017-05-12 18:01:32 +00001275 KMP_FSYNC_SPIN_INIT(obj, (void *)&th->th.th_info.ds.ds_alive);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001276#endif /* USE_ITT_BUILD */
Jonathan Peyton30419822017-05-12 18:01:32 +00001277 KMP_INIT_YIELD(spins);
1278 do {
Jim Cownie5e8470a2013-09-27 10:38:44 +00001279#if USE_ITT_BUILD
Jonathan Peyton30419822017-05-12 18:01:32 +00001280 KMP_FSYNC_SPIN_PREPARE(obj);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001281#endif /* USE_ITT_BUILD */
Jonathan Peyton30419822017-05-12 18:01:32 +00001282 __kmp_is_thread_alive(th, &exit_val);
Jonathan Peytone47d32f2019-02-28 19:11:29 +00001283 KMP_YIELD_OVERSUB_ELSE_SPIN(spins);
Jonathan Peyton30419822017-05-12 18:01:32 +00001284 } while (exit_val == STILL_ACTIVE && TCR_4(th->th.th_info.ds.ds_alive));
Jim Cownie5e8470a2013-09-27 10:38:44 +00001285#if USE_ITT_BUILD
Jonathan Peyton30419822017-05-12 18:01:32 +00001286 if (exit_val == STILL_ACTIVE) {
1287 KMP_FSYNC_CANCEL(obj);
1288 } else {
1289 KMP_FSYNC_SPIN_ACQUIRED(obj);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001290 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001291#endif /* USE_ITT_BUILD */
1292 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001293
Jonathan Peyton30419822017-05-12 18:01:32 +00001294 __kmp_free_handle(th->th.th_info.ds.ds_thread);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001295
Jonathan Peyton30419822017-05-12 18:01:32 +00001296 /* NOTE: The ExitProcess(code) system call causes all threads to Terminate
1297 with a exit_val = code. Because of this we can not rely on exit_val having
1298 any particular value. */
1299 if (exit_val == STILL_ACTIVE) {
1300 KA_TRACE(1, ("__kmp_reap_common: thread still active.\n"));
1301 } else if ((void *)exit_val != (void *)th) {
1302 KA_TRACE(1, ("__kmp_reap_common: ExitProcess / TerminateThread used?\n"));
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001303 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001304
Jonathan Peyton30419822017-05-12 18:01:32 +00001305 KA_TRACE(10,
1306 ("__kmp_reap_common: done reaping (%d), handle = %" KMP_UINTPTR_SPEC
1307 "\n",
1308 th->th.th_info.ds.ds_gtid, th->th.th_info.ds.ds_thread));
1309
1310 th->th.th_info.ds.ds_thread = 0;
1311 th->th.th_info.ds.ds_tid = KMP_GTID_DNE;
1312 th->th.th_info.ds.ds_gtid = KMP_GTID_DNE;
1313 th->th.th_info.ds.ds_thread_id = 0;
1314
1315 KMP_MB(); /* Flush all pending memory write invalidates. */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001316}
1317
Jonathan Peytonb66d1aa2016-09-27 17:11:17 +00001318#if KMP_USE_MONITOR
Jonathan Peyton30419822017-05-12 18:01:32 +00001319void __kmp_reap_monitor(kmp_info_t *th) {
1320 int status;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001321
Jonathan Peyton30419822017-05-12 18:01:32 +00001322 KA_TRACE(10, ("__kmp_reap_monitor: try to reap %p\n",
1323 (void *)th->th.th_info.ds.ds_thread));
Jim Cownie5e8470a2013-09-27 10:38:44 +00001324
Jonathan Peyton30419822017-05-12 18:01:32 +00001325 // If monitor has been created, its tid and gtid should be KMP_GTID_MONITOR.
1326 // If both tid and gtid are 0, it means the monitor did not ever start.
1327 // If both tid and gtid are KMP_GTID_DNE, the monitor has been shut down.
1328 KMP_DEBUG_ASSERT(th->th.th_info.ds.ds_tid == th->th.th_info.ds.ds_gtid);
1329 if (th->th.th_info.ds.ds_gtid != KMP_GTID_MONITOR) {
1330 KA_TRACE(10, ("__kmp_reap_monitor: monitor did not start, returning\n"));
1331 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001332 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001333
Jonathan Peyton30419822017-05-12 18:01:32 +00001334 KMP_MB(); /* Flush all pending memory write invalidates. */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001335
Jonathan Peyton30419822017-05-12 18:01:32 +00001336 status = SetEvent(__kmp_monitor_ev);
1337 if (status == FALSE) {
1338 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +00001339 __kmp_fatal(KMP_MSG(CantSetEvent), KMP_ERR(error), __kmp_msg_null);
Jonathan Peyton30419822017-05-12 18:01:32 +00001340 }
1341 KA_TRACE(10, ("__kmp_reap_monitor: reaping thread (%d)\n",
1342 th->th.th_info.ds.ds_gtid));
1343 __kmp_reap_common(th);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001344
Jonathan Peyton30419822017-05-12 18:01:32 +00001345 __kmp_free_handle(__kmp_monitor_ev);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001346
Jonathan Peyton30419822017-05-12 18:01:32 +00001347 KMP_MB(); /* Flush all pending memory write invalidates. */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001348}
Jonathan Peytonb66d1aa2016-09-27 17:11:17 +00001349#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +00001350
Jonathan Peyton30419822017-05-12 18:01:32 +00001351void __kmp_reap_worker(kmp_info_t *th) {
1352 KA_TRACE(10, ("__kmp_reap_worker: reaping thread (%d)\n",
1353 th->th.th_info.ds.ds_gtid));
1354 __kmp_reap_common(th);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001355}
1356
Jim Cownie5e8470a2013-09-27 10:38:44 +00001357#if KMP_HANDLE_SIGNALS
1358
Jonathan Peyton30419822017-05-12 18:01:32 +00001359static void __kmp_team_handler(int signo) {
1360 if (__kmp_global.g.g_abort == 0) {
1361 // Stage 1 signal handler, let's shut down all of the threads.
1362 if (__kmp_debug_buf) {
1363 __kmp_dump_debug_buffer();
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001364 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001365 KMP_MB(); // Flush all pending memory write invalidates.
1366 TCW_4(__kmp_global.g.g_abort, signo);
1367 KMP_MB(); // Flush all pending memory write invalidates.
1368 TCW_4(__kmp_global.g.g_done, TRUE);
1369 KMP_MB(); // Flush all pending memory write invalidates.
1370 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001371} // __kmp_team_handler
1372
Jonathan Peyton30419822017-05-12 18:01:32 +00001373static sig_func_t __kmp_signal(int signum, sig_func_t handler) {
1374 sig_func_t old = signal(signum, handler);
1375 if (old == SIG_ERR) {
1376 int error = errno;
Jonathan Peyton6a393f72017-09-05 15:43:58 +00001377 __kmp_fatal(KMP_MSG(FunctionError, "signal"), KMP_ERR(error),
1378 __kmp_msg_null);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001379 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001380 return old;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001381}
1382
Jonathan Peyton30419822017-05-12 18:01:32 +00001383static void __kmp_install_one_handler(int sig, sig_func_t handler,
1384 int parallel_init) {
1385 sig_func_t old;
1386 KMP_MB(); /* Flush all pending memory write invalidates. */
1387 KB_TRACE(60, ("__kmp_install_one_handler: called: sig=%d\n", sig));
1388 if (parallel_init) {
1389 old = __kmp_signal(sig, handler);
1390 // SIG_DFL on Windows* OS in NULL or 0.
1391 if (old == __kmp_sighldrs[sig]) {
1392 __kmp_siginstalled[sig] = 1;
1393 } else { // Restore/keep user's handler if one previously installed.
1394 old = __kmp_signal(sig, old);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001395 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001396 } else {
1397 // Save initial/system signal handlers to see if user handlers installed.
1398 // 2009-09-23: It is a dead code. On Windows* OS __kmp_install_signals
1399 // called once with parallel_init == TRUE.
1400 old = __kmp_signal(sig, SIG_DFL);
1401 __kmp_sighldrs[sig] = old;
1402 __kmp_signal(sig, old);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001403 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001404 KMP_MB(); /* Flush all pending memory write invalidates. */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001405} // __kmp_install_one_handler
1406
Jonathan Peyton30419822017-05-12 18:01:32 +00001407static void __kmp_remove_one_handler(int sig) {
1408 if (__kmp_siginstalled[sig]) {
1409 sig_func_t old;
1410 KMP_MB(); // Flush all pending memory write invalidates.
1411 KB_TRACE(60, ("__kmp_remove_one_handler: called: sig=%d\n", sig));
1412 old = __kmp_signal(sig, __kmp_sighldrs[sig]);
1413 if (old != __kmp_team_handler) {
1414 KB_TRACE(10, ("__kmp_remove_one_handler: oops, not our handler, "
1415 "restoring: sig=%d\n",
1416 sig));
1417 old = __kmp_signal(sig, old);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001418 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001419 __kmp_sighldrs[sig] = NULL;
1420 __kmp_siginstalled[sig] = 0;
1421 KMP_MB(); // Flush all pending memory write invalidates.
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001422 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001423} // __kmp_remove_one_handler
1424
Jonathan Peyton30419822017-05-12 18:01:32 +00001425void __kmp_install_signals(int parallel_init) {
1426 KB_TRACE(10, ("__kmp_install_signals: called\n"));
1427 if (!__kmp_handle_signals) {
1428 KB_TRACE(10, ("__kmp_install_signals: KMP_HANDLE_SIGNALS is false - "
1429 "handlers not installed\n"));
1430 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001431 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001432 __kmp_install_one_handler(SIGINT, __kmp_team_handler, parallel_init);
1433 __kmp_install_one_handler(SIGILL, __kmp_team_handler, parallel_init);
1434 __kmp_install_one_handler(SIGABRT, __kmp_team_handler, parallel_init);
1435 __kmp_install_one_handler(SIGFPE, __kmp_team_handler, parallel_init);
1436 __kmp_install_one_handler(SIGSEGV, __kmp_team_handler, parallel_init);
1437 __kmp_install_one_handler(SIGTERM, __kmp_team_handler, parallel_init);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001438} // __kmp_install_signals
1439
Jonathan Peyton30419822017-05-12 18:01:32 +00001440void __kmp_remove_signals(void) {
1441 int sig;
1442 KB_TRACE(10, ("__kmp_remove_signals: called\n"));
1443 for (sig = 1; sig < NSIG; ++sig) {
1444 __kmp_remove_one_handler(sig);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001445 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001446} // __kmp_remove_signals
1447
Jim Cownie5e8470a2013-09-27 10:38:44 +00001448#endif // KMP_HANDLE_SIGNALS
1449
1450/* Put the thread to sleep for a time period */
Jonathan Peyton30419822017-05-12 18:01:32 +00001451void __kmp_thread_sleep(int millis) {
1452 DWORD status;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001453
Jonathan Peyton30419822017-05-12 18:01:32 +00001454 status = SleepEx((DWORD)millis, FALSE);
1455 if (status) {
1456 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +00001457 __kmp_fatal(KMP_MSG(FunctionError, "SleepEx()"), KMP_ERR(error),
1458 __kmp_msg_null);
Jonathan Peyton30419822017-05-12 18:01:32 +00001459 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001460}
1461
Jonathan Peyton30419822017-05-12 18:01:32 +00001462// Determine whether the given address is mapped into the current address space.
1463int __kmp_is_address_mapped(void *addr) {
1464 DWORD status;
1465 MEMORY_BASIC_INFORMATION lpBuffer;
1466 SIZE_T dwLength;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001467
Jonathan Peyton30419822017-05-12 18:01:32 +00001468 dwLength = sizeof(MEMORY_BASIC_INFORMATION);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001469
Jonathan Peyton30419822017-05-12 18:01:32 +00001470 status = VirtualQuery(addr, &lpBuffer, dwLength);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001471
Jonathan Peyton30419822017-05-12 18:01:32 +00001472 return !(((lpBuffer.State == MEM_RESERVE) || (lpBuffer.State == MEM_FREE)) ||
1473 ((lpBuffer.Protect == PAGE_NOACCESS) ||
1474 (lpBuffer.Protect == PAGE_EXECUTE)));
Jim Cownie5e8470a2013-09-27 10:38:44 +00001475}
1476
Jonathan Peyton30419822017-05-12 18:01:32 +00001477kmp_uint64 __kmp_hardware_timestamp(void) {
1478 kmp_uint64 r = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001479
Jonathan Peyton30419822017-05-12 18:01:32 +00001480 QueryPerformanceCounter((LARGE_INTEGER *)&r);
1481 return r;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001482}
1483
1484/* Free handle and check the error code */
Jonathan Peyton30419822017-05-12 18:01:32 +00001485void __kmp_free_handle(kmp_thread_t tHandle) {
1486 /* called with parameter type HANDLE also, thus suppose kmp_thread_t defined
1487 * as HANDLE */
1488 BOOL rc;
1489 rc = CloseHandle(tHandle);
1490 if (!rc) {
1491 DWORD error = GetLastError();
Jonathan Peyton6a393f72017-09-05 15:43:58 +00001492 __kmp_fatal(KMP_MSG(CantCloseHandle), KMP_ERR(error), __kmp_msg_null);
Jonathan Peyton30419822017-05-12 18:01:32 +00001493 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001494}
1495
Jonathan Peyton30419822017-05-12 18:01:32 +00001496int __kmp_get_load_balance(int max) {
1497 static ULONG glb_buff_size = 100 * 1024;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001498
Jonathan Peyton30419822017-05-12 18:01:32 +00001499 // Saved count of the running threads for the thread balance algortihm
1500 static int glb_running_threads = 0;
1501 static double glb_call_time = 0; /* Thread balance algorithm call time */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001502
Jonathan Peyton30419822017-05-12 18:01:32 +00001503 int running_threads = 0; // Number of running threads in the system.
1504 NTSTATUS status = 0;
1505 ULONG buff_size = 0;
1506 ULONG info_size = 0;
1507 void *buffer = NULL;
1508 PSYSTEM_PROCESS_INFORMATION spi = NULL;
1509 int first_time = 1;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001510
Jonathan Peyton30419822017-05-12 18:01:32 +00001511 double call_time = 0.0; // start, finish;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001512
Jonathan Peyton30419822017-05-12 18:01:32 +00001513 __kmp_elapsed(&call_time);
Jim Cownie5e8470a2013-09-27 10:38:44 +00001514
Jonathan Peyton30419822017-05-12 18:01:32 +00001515 if (glb_call_time &&
1516 (call_time - glb_call_time < __kmp_load_balance_interval)) {
1517 running_threads = glb_running_threads;
1518 goto finish;
1519 }
1520 glb_call_time = call_time;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001521
Jonathan Peyton30419822017-05-12 18:01:32 +00001522 // Do not spend time on running algorithm if we have a permanent error.
1523 if (NtQuerySystemInformation == NULL) {
1524 running_threads = -1;
1525 goto finish;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001526 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001527
1528 if (max <= 0) {
1529 max = INT_MAX;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001530 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001531
1532 do {
1533
1534 if (first_time) {
1535 buff_size = glb_buff_size;
1536 } else {
1537 buff_size = 2 * buff_size;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001538 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001539
Jonathan Peyton30419822017-05-12 18:01:32 +00001540 buffer = KMP_INTERNAL_REALLOC(buffer, buff_size);
1541 if (buffer == NULL) {
1542 running_threads = -1;
1543 goto finish;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001544 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001545 status = NtQuerySystemInformation(SystemProcessInformation, buffer,
1546 buff_size, &info_size);
1547 first_time = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001548
Jonathan Peyton30419822017-05-12 18:01:32 +00001549 } while (status == STATUS_INFO_LENGTH_MISMATCH);
1550 glb_buff_size = buff_size;
1551
1552#define CHECK(cond) \
1553 { \
1554 KMP_DEBUG_ASSERT(cond); \
1555 if (!(cond)) { \
1556 running_threads = -1; \
1557 goto finish; \
1558 } \
1559 }
1560
1561 CHECK(buff_size >= info_size);
1562 spi = PSYSTEM_PROCESS_INFORMATION(buffer);
1563 for (;;) {
1564 ptrdiff_t offset = uintptr_t(spi) - uintptr_t(buffer);
1565 CHECK(0 <= offset &&
1566 offset + sizeof(SYSTEM_PROCESS_INFORMATION) < info_size);
1567 HANDLE pid = spi->ProcessId;
1568 ULONG num = spi->NumberOfThreads;
1569 CHECK(num >= 1);
1570 size_t spi_size =
1571 sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD) * (num - 1);
1572 CHECK(offset + spi_size <
1573 info_size); // Make sure process info record fits the buffer.
1574 if (spi->NextEntryOffset != 0) {
1575 CHECK(spi_size <=
1576 spi->NextEntryOffset); // And do not overlap with the next record.
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001577 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001578 // pid == 0 corresponds to the System Idle Process. It always has running
1579 // threads on all cores. So, we don't consider the running threads of this
1580 // process.
1581 if (pid != 0) {
1582 for (int i = 0; i < num; ++i) {
1583 THREAD_STATE state = spi->Threads[i].State;
1584 // Count threads that have Ready or Running state.
1585 // !!! TODO: Why comment does not match the code???
1586 if (state == StateRunning) {
1587 ++running_threads;
1588 // Stop counting running threads if the number is already greater than
1589 // the number of available cores
1590 if (running_threads >= max) {
Jim Cownie5e8470a2013-09-27 10:38:44 +00001591 goto finish;
Jonathan Peyton30419822017-05-12 18:01:32 +00001592 }
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001593 }
1594 }
1595 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001596 if (spi->NextEntryOffset == 0) {
1597 break;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001598 }
Jonathan Peyton30419822017-05-12 18:01:32 +00001599 spi = PSYSTEM_PROCESS_INFORMATION(uintptr_t(spi) + spi->NextEntryOffset);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001600 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001601
Jonathan Peyton30419822017-05-12 18:01:32 +00001602#undef CHECK
Jim Cownie5e8470a2013-09-27 10:38:44 +00001603
Jonathan Peyton30419822017-05-12 18:01:32 +00001604finish: // Clean up and exit.
Jim Cownie5e8470a2013-09-27 10:38:44 +00001605
Jonathan Peyton30419822017-05-12 18:01:32 +00001606 if (buffer != NULL) {
1607 KMP_INTERNAL_FREE(buffer);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +00001608 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001609
Jonathan Peyton30419822017-05-12 18:01:32 +00001610 glb_running_threads = running_threads;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001611
Jonathan Peyton30419822017-05-12 18:01:32 +00001612 return running_threads;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001613} //__kmp_get_load_balance()