blob: 5e1424089b16acdf94364b15f9accf12e63bd310 [file] [log] [blame]
Jim Cownie5e8470a2013-09-27 10:38:44 +00001/*
2 * z_Windows_NT_util.c -- platform specific routines.
Jim Cownie5e8470a2013-09-27 10:38:44 +00003 */
4
5
6//===----------------------------------------------------------------------===//
7//
8// The LLVM Compiler Infrastructure
9//
10// This file is dual licensed under the MIT and the University of Illinois Open
11// Source Licenses. See LICENSE.txt for details.
12//
13//===----------------------------------------------------------------------===//
14
15
16#include "kmp.h"
17#include "kmp_itt.h"
18#include "kmp_i18n.h"
19#include "kmp_io.h"
Jim Cownie4cc4bb42014-10-07 16:25:50 +000020#include "kmp_wait_release.h"
Jim Cownie5e8470a2013-09-27 10:38:44 +000021
Jim Cownie4cc4bb42014-10-07 16:25:50 +000022/* This code is related to NtQuerySystemInformation() function. This function
23 is used in the Load balance algorithm for OMP_DYNAMIC=true to find the
Jim Cownie5e8470a2013-09-27 10:38:44 +000024 number of running threads in the system. */
25
26#include <ntstatus.h>
27#include <ntsecapi.h> // UNICODE_STRING
28
29enum SYSTEM_INFORMATION_CLASS {
30 SystemProcessInformation = 5
31}; // SYSTEM_INFORMATION_CLASS
32
33struct CLIENT_ID {
34 HANDLE UniqueProcess;
35 HANDLE UniqueThread;
36}; // struct CLIENT_ID
37
38enum THREAD_STATE {
39 StateInitialized,
40 StateReady,
41 StateRunning,
42 StateStandby,
43 StateTerminated,
44 StateWait,
45 StateTransition,
46 StateUnknown
47}; // enum THREAD_STATE
48
49struct VM_COUNTERS {
50 SIZE_T PeakVirtualSize;
51 SIZE_T VirtualSize;
52 ULONG PageFaultCount;
53 SIZE_T PeakWorkingSetSize;
54 SIZE_T WorkingSetSize;
55 SIZE_T QuotaPeakPagedPoolUsage;
56 SIZE_T QuotaPagedPoolUsage;
57 SIZE_T QuotaPeakNonPagedPoolUsage;
58 SIZE_T QuotaNonPagedPoolUsage;
59 SIZE_T PagefileUsage;
60 SIZE_T PeakPagefileUsage;
61 SIZE_T PrivatePageCount;
62}; // struct VM_COUNTERS
63
64struct SYSTEM_THREAD {
65 LARGE_INTEGER KernelTime;
66 LARGE_INTEGER UserTime;
67 LARGE_INTEGER CreateTime;
68 ULONG WaitTime;
69 LPVOID StartAddress;
70 CLIENT_ID ClientId;
71 DWORD Priority;
72 LONG BasePriority;
73 ULONG ContextSwitchCount;
74 THREAD_STATE State;
75 ULONG WaitReason;
76}; // SYSTEM_THREAD
77
78KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, KernelTime ) == 0 );
79#if KMP_ARCH_X86
80 KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, StartAddress ) == 28 );
81 KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, State ) == 52 );
82#else
83 KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, StartAddress ) == 32 );
84 KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, State ) == 68 );
85#endif
86
87struct SYSTEM_PROCESS_INFORMATION {
88 ULONG NextEntryOffset;
89 ULONG NumberOfThreads;
90 LARGE_INTEGER Reserved[ 3 ];
91 LARGE_INTEGER CreateTime;
92 LARGE_INTEGER UserTime;
93 LARGE_INTEGER KernelTime;
94 UNICODE_STRING ImageName;
95 DWORD BasePriority;
96 HANDLE ProcessId;
97 HANDLE ParentProcessId;
98 ULONG HandleCount;
99 ULONG Reserved2[ 2 ];
100 VM_COUNTERS VMCounters;
101 IO_COUNTERS IOCounters;
102 SYSTEM_THREAD Threads[ 1 ];
103}; // SYSTEM_PROCESS_INFORMATION
104typedef SYSTEM_PROCESS_INFORMATION * PSYSTEM_PROCESS_INFORMATION;
105
106KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, NextEntryOffset ) == 0 );
107KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, CreateTime ) == 32 );
108KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, ImageName ) == 56 );
109#if KMP_ARCH_X86
110 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, ProcessId ) == 68 );
111 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, HandleCount ) == 76 );
112 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, VMCounters ) == 88 );
113 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, IOCounters ) == 136 );
114 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, Threads ) == 184 );
115#else
116 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, ProcessId ) == 80 );
117 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, HandleCount ) == 96 );
118 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, VMCounters ) == 112 );
119 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, IOCounters ) == 208 );
120 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, Threads ) == 256 );
121#endif
122
123typedef NTSTATUS (NTAPI *NtQuerySystemInformation_t)( SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG );
124NtQuerySystemInformation_t NtQuerySystemInformation = NULL;
125
126HMODULE ntdll = NULL;
127
128/* End of NtQuerySystemInformation()-related code */
129
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000130#if KMP_GROUP_AFFINITY
Jim Cownie5e8470a2013-09-27 10:38:44 +0000131static HMODULE kernel32 = NULL;
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000132#endif /* KMP_GROUP_AFFINITY */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000133
134/* ----------------------------------------------------------------------------------- */
135/* ----------------------------------------------------------------------------------- */
136
Jim Cownie5e8470a2013-09-27 10:38:44 +0000137#if KMP_HANDLE_SIGNALS
138 typedef void (* sig_func_t )( int );
139 static sig_func_t __kmp_sighldrs[ NSIG ];
140 static int __kmp_siginstalled[ NSIG ];
141#endif
142
143static HANDLE __kmp_monitor_ev;
144static kmp_int64 __kmp_win32_time;
145double __kmp_win32_tick;
146
147int __kmp_init_runtime = FALSE;
148CRITICAL_SECTION __kmp_win32_section;
149
150void
151__kmp_win32_mutex_init( kmp_win32_mutex_t *mx )
152{
153 InitializeCriticalSection( & mx->cs );
154#if USE_ITT_BUILD
155 __kmp_itt_system_object_created( & mx->cs, "Critical Section" );
156#endif /* USE_ITT_BUILD */
157}
158
159void
160__kmp_win32_mutex_destroy( kmp_win32_mutex_t *mx )
161{
162 DeleteCriticalSection( & mx->cs );
163}
164
165void
166__kmp_win32_mutex_lock( kmp_win32_mutex_t *mx )
167{
168 EnterCriticalSection( & mx->cs );
169}
170
171void
172__kmp_win32_mutex_unlock( kmp_win32_mutex_t *mx )
173{
174 LeaveCriticalSection( & mx->cs );
175}
176
177void
178__kmp_win32_cond_init( kmp_win32_cond_t *cv )
179{
180 cv->waiters_count_ = 0;
181 cv->wait_generation_count_ = 0;
182 cv->release_count_ = 0;
183
184 /* Initialize the critical section */
185 __kmp_win32_mutex_init( & cv->waiters_count_lock_ );
186
187 /* Create a manual-reset event. */
188 cv->event_ = CreateEvent( NULL, // no security
189 TRUE, // manual-reset
190 FALSE, // non-signaled initially
191 NULL ); // unnamed
192#if USE_ITT_BUILD
193 __kmp_itt_system_object_created( cv->event_, "Event" );
194#endif /* USE_ITT_BUILD */
195}
196
197void
198__kmp_win32_cond_destroy( kmp_win32_cond_t *cv )
199{
200 __kmp_win32_mutex_destroy( & cv->waiters_count_lock_ );
201 __kmp_free_handle( cv->event_ );
202 memset( cv, '\0', sizeof( *cv ) );
203}
204
205/* TODO associate cv with a team instead of a thread so as to optimize
206 * the case where we wake up a whole team */
207
208void
209__kmp_win32_cond_wait( kmp_win32_cond_t *cv, kmp_win32_mutex_t *mx, kmp_info_t *th, int need_decrease_load )
210{
211 int my_generation;
212 int last_waiter;
213
214 /* Avoid race conditions */
215 __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
216
217 /* Increment count of waiters */
218 cv->waiters_count_++;
219
220 /* Store current generation in our activation record. */
221 my_generation = cv->wait_generation_count_;
222
223 __kmp_win32_mutex_unlock( &cv->waiters_count_lock_ );
224 __kmp_win32_mutex_unlock( mx );
225
Jim Cownie5e8470a2013-09-27 10:38:44 +0000226 for (;;) {
227 int wait_done;
228
229 /* Wait until the event is signaled */
230 WaitForSingleObject( cv->event_, INFINITE );
231
232 __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
233
234 /* Exit the loop when the <cv->event_> is signaled and
235 * there are still waiting threads from this <wait_generation>
236 * that haven't been released from this wait yet. */
237 wait_done = ( cv->release_count_ > 0 ) &&
238 ( cv->wait_generation_count_ != my_generation );
239
240 __kmp_win32_mutex_unlock( &cv->waiters_count_lock_);
241
242 /* there used to be a semicolon after the if statement,
243 * it looked like a bug, so i removed it */
244 if( wait_done )
245 break;
246 }
247
248 __kmp_win32_mutex_lock( mx );
249 __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
250
251 cv->waiters_count_--;
252 cv->release_count_--;
253
254 last_waiter = ( cv->release_count_ == 0 );
255
256 __kmp_win32_mutex_unlock( &cv->waiters_count_lock_ );
257
258 if( last_waiter ) {
259 /* We're the last waiter to be notified, so reset the manual event. */
260 ResetEvent( cv->event_ );
261 }
262}
263
264void
265__kmp_win32_cond_broadcast( kmp_win32_cond_t *cv )
266{
267 __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
268
269 if( cv->waiters_count_ > 0 ) {
270 SetEvent( cv->event_ );
271 /* Release all the threads in this generation. */
272
273 cv->release_count_ = cv->waiters_count_;
274
275 /* Start a new generation. */
276 cv->wait_generation_count_++;
277 }
278
279 __kmp_win32_mutex_unlock( &cv->waiters_count_lock_ );
280}
281
282void
283__kmp_win32_cond_signal( kmp_win32_cond_t *cv )
284{
285 __kmp_win32_cond_broadcast( cv );
286}
287
288/* ------------------------------------------------------------------------ */
289/* ------------------------------------------------------------------------ */
290
291void
292__kmp_enable( int new_state )
293{
294 if (__kmp_init_runtime)
295 LeaveCriticalSection( & __kmp_win32_section );
296}
297
298void
299__kmp_disable( int *old_state )
300{
301 *old_state = 0;
302
303 if (__kmp_init_runtime)
304 EnterCriticalSection( & __kmp_win32_section );
305}
306
307void
308__kmp_suspend_initialize( void )
309{
310 /* do nothing */
311}
312
313static void
314__kmp_suspend_initialize_thread( kmp_info_t *th )
315{
316 if ( ! TCR_4( th->th.th_suspend_init ) ) {
317 /* this means we haven't initialized the suspension pthread objects for this thread
318 in this instance of the process */
319 __kmp_win32_cond_init( &th->th.th_suspend_cv );
320 __kmp_win32_mutex_init( &th->th.th_suspend_mx );
321 TCW_4( th->th.th_suspend_init, TRUE );
322 }
323}
324
325void
326__kmp_suspend_uninitialize_thread( kmp_info_t *th )
327{
328 if ( TCR_4( th->th.th_suspend_init ) ) {
329 /* this means we have initialize the suspension pthread objects for this thread
330 in this instance of the process */
331 __kmp_win32_cond_destroy( & th->th.th_suspend_cv );
332 __kmp_win32_mutex_destroy( & th->th.th_suspend_mx );
333 TCW_4( th->th.th_suspend_init, FALSE );
334 }
335}
336
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000337/* This routine puts the calling thread to sleep after setting the
338 * sleep bit for the indicated flag variable to true.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000339 */
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000340template <class C>
341static inline void __kmp_suspend_template( int th_gtid, C *flag )
Jim Cownie5e8470a2013-09-27 10:38:44 +0000342{
343 kmp_info_t *th = __kmp_threads[th_gtid];
344 int status;
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000345 typename C::flag_t old_spin;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000346
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000347 KF_TRACE( 30, ("__kmp_suspend_template: T#%d enter for flag's loc(%p)\n", th_gtid, flag->get() ) );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000348
349 __kmp_suspend_initialize_thread( th );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000350 __kmp_win32_mutex_lock( &th->th.th_suspend_mx );
351
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000352 KF_TRACE( 10, ( "__kmp_suspend_template: T#%d setting sleep bit for flag's loc(%p)\n",
353 th_gtid, flag->get() ) );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000354
355 /* TODO: shouldn't this use release semantics to ensure that __kmp_suspend_initialize_thread
356 gets called first?
357 */
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000358 old_spin = flag->set_sleeping();
Jim Cownie5e8470a2013-09-27 10:38:44 +0000359
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000360 KF_TRACE( 5, ( "__kmp_suspend_template: T#%d set sleep bit for flag's loc(%p)==%d\n",
361 th_gtid, flag->get(), *(flag->get()) ) );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000362
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000363 if ( flag->done_check_val(old_spin) ) {
364 old_spin = flag->unset_sleeping();
365 KF_TRACE( 5, ( "__kmp_suspend_template: T#%d false alarm, reset sleep bit for flag's loc(%p)\n",
366 th_gtid, flag->get()) );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000367 } else {
368#ifdef DEBUG_SUSPEND
369 __kmp_suspend_count++;
370#endif
Jim Cownie5e8470a2013-09-27 10:38:44 +0000371 /* Encapsulate in a loop as the documentation states that this may
372 * "with low probability" return when the condition variable has
373 * not been signaled or broadcast
374 */
375 int deactivated = FALSE;
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000376 TCW_PTR(th->th.th_sleep_loc, (void *)flag);
377 while ( flag->is_sleeping() ) {
378 KF_TRACE( 15, ("__kmp_suspend_template: T#%d about to perform kmp_win32_cond_wait()\n",
Jim Cownie5e8470a2013-09-27 10:38:44 +0000379 th_gtid ) );
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000380 // Mark the thread as no longer active (only in the first iteration of the loop).
Jim Cownie5e8470a2013-09-27 10:38:44 +0000381 if ( ! deactivated ) {
382 th->th.th_active = FALSE;
383 if ( th->th.th_active_in_pool ) {
384 th->th.th_active_in_pool = FALSE;
385 KMP_TEST_THEN_DEC32(
386 (kmp_int32 *) &__kmp_thread_pool_active_nth );
387 KMP_DEBUG_ASSERT( TCR_4(__kmp_thread_pool_active_nth) >= 0 );
388 }
389 deactivated = TRUE;
390
Jim Cownie5e8470a2013-09-27 10:38:44 +0000391 __kmp_win32_cond_wait( &th->th.th_suspend_cv, &th->th.th_suspend_mx, 0, 0 );
392 }
393 else {
394 __kmp_win32_cond_wait( &th->th.th_suspend_cv, &th->th.th_suspend_mx, 0, 0 );
395 }
396
397#ifdef KMP_DEBUG
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000398 if( flag->is_sleeping() ) {
399 KF_TRACE( 100, ("__kmp_suspend_template: T#%d spurious wakeup\n", th_gtid ));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000400 }
401#endif /* KMP_DEBUG */
402
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000403 } // while
Jim Cownie5e8470a2013-09-27 10:38:44 +0000404
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000405 // Mark the thread as active again (if it was previous marked as inactive)
Jim Cownie5e8470a2013-09-27 10:38:44 +0000406 if ( deactivated ) {
407 th->th.th_active = TRUE;
408 if ( TCR_4(th->th.th_in_pool) ) {
409 KMP_TEST_THEN_INC32(
410 (kmp_int32 *) &__kmp_thread_pool_active_nth );
411 th->th.th_active_in_pool = TRUE;
412 }
413 }
414 }
415
Jim Cownie5e8470a2013-09-27 10:38:44 +0000416 __kmp_win32_mutex_unlock( &th->th.th_suspend_mx );
417
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000418 KF_TRACE( 30, ("__kmp_suspend_template: T#%d exit\n", th_gtid ) );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000419}
420
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000421void __kmp_suspend_32(int th_gtid, kmp_flag_32 *flag) {
422 __kmp_suspend_template(th_gtid, flag);
423}
424void __kmp_suspend_64(int th_gtid, kmp_flag_64 *flag) {
425 __kmp_suspend_template(th_gtid, flag);
426}
427void __kmp_suspend_oncore(int th_gtid, kmp_flag_oncore *flag) {
428 __kmp_suspend_template(th_gtid, flag);
429}
430
431
Jim Cownie5e8470a2013-09-27 10:38:44 +0000432/* This routine signals the thread specified by target_gtid to wake up
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000433 * after setting the sleep bit indicated by the flag argument to FALSE
Jim Cownie5e8470a2013-09-27 10:38:44 +0000434 */
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000435template <class C>
436static inline void __kmp_resume_template( int target_gtid, C *flag )
Jim Cownie5e8470a2013-09-27 10:38:44 +0000437{
438 kmp_info_t *th = __kmp_threads[target_gtid];
439 int status;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000440
441#ifdef KMP_DEBUG
442 int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
443#endif
444
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000445 KF_TRACE( 30, ( "__kmp_resume_template: T#%d wants to wakeup T#%d enter\n", gtid, target_gtid ) );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000446
447 __kmp_suspend_initialize_thread( th );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000448 __kmp_win32_mutex_lock( &th->th.th_suspend_mx );
449
Jonathan Peyton3f5dfc22015-11-09 16:31:51 +0000450 if (!flag) { // coming from __kmp_null_resume_wrapper
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000451 flag = (C *)th->th.th_sleep_loc;
452 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000453
Jonathan Peyton3f5dfc22015-11-09 16:31:51 +0000454 // First, check if the flag is null or its type has changed. If so, someone else woke it up.
455 if (!flag || flag->get_type() != flag->get_ptr_type()) { // get_ptr_type simply shows what flag was cast to
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000456 KF_TRACE( 5, ( "__kmp_resume_template: T#%d exiting, thread T#%d already awake: flag's loc(%p)\n",
457 gtid, target_gtid, NULL ) );
458 __kmp_win32_mutex_unlock( &th->th.th_suspend_mx );
459 return;
460 }
461 else {
462 typename C::flag_t old_spin = flag->unset_sleeping();
463 if ( !flag->is_sleeping_val(old_spin) ) {
464 KF_TRACE( 5, ( "__kmp_resume_template: T#%d exiting, thread T#%d already awake: flag's loc(%p): "
465 "%u => %u\n",
466 gtid, target_gtid, flag->get(), old_spin, *(flag->get()) ) );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000467 __kmp_win32_mutex_unlock( &th->th.th_suspend_mx );
468 return;
469 }
470 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000471 TCW_PTR(th->th.th_sleep_loc, NULL);
472
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000473 KF_TRACE( 5, ( "__kmp_resume_template: T#%d about to wakeup T#%d, reset sleep bit for flag's loc(%p)\n",
474 gtid, target_gtid, flag->get() ) );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000475
Jim Cownie5e8470a2013-09-27 10:38:44 +0000476 __kmp_win32_cond_signal( &th->th.th_suspend_cv );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000477 __kmp_win32_mutex_unlock( &th->th.th_suspend_mx );
478
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000479 KF_TRACE( 30, ( "__kmp_resume_template: T#%d exiting after signaling wake up for T#%d\n",
Jim Cownie5e8470a2013-09-27 10:38:44 +0000480 gtid, target_gtid ) );
481}
482
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000483void __kmp_resume_32(int target_gtid, kmp_flag_32 *flag) {
484 __kmp_resume_template(target_gtid, flag);
485}
486void __kmp_resume_64(int target_gtid, kmp_flag_64 *flag) {
487 __kmp_resume_template(target_gtid, flag);
488}
489void __kmp_resume_oncore(int target_gtid, kmp_flag_oncore *flag) {
490 __kmp_resume_template(target_gtid, flag);
491}
492
493
Jim Cownie5e8470a2013-09-27 10:38:44 +0000494/* ------------------------------------------------------------------------ */
495/* ------------------------------------------------------------------------ */
496
497void
498__kmp_yield( int cond )
499{
500 if (cond)
501 Sleep(0);
502}
503
504/* ------------------------------------------------------------------------ */
505/* ------------------------------------------------------------------------ */
506
507void
508__kmp_gtid_set_specific( int gtid )
509{
510 KA_TRACE( 50, ("__kmp_gtid_set_specific: T#%d key:%d\n",
511 gtid, __kmp_gtid_threadprivate_key ));
512 KMP_ASSERT( __kmp_init_runtime );
513 if( ! TlsSetValue( __kmp_gtid_threadprivate_key, (LPVOID)(gtid+1)) )
514 KMP_FATAL( TLSSetValueFailed );
515}
516
517int
518__kmp_gtid_get_specific()
519{
520 int gtid;
521 if( !__kmp_init_runtime ) {
522 KA_TRACE( 50, ("__kmp_get_specific: runtime shutdown, returning KMP_GTID_SHUTDOWN\n" ) );
523 return KMP_GTID_SHUTDOWN;
524 }
525 gtid = (int)(kmp_intptr_t)TlsGetValue( __kmp_gtid_threadprivate_key );
526 if ( gtid == 0 ) {
527 gtid = KMP_GTID_DNE;
528 }
529 else {
530 gtid--;
531 }
532 KA_TRACE( 50, ("__kmp_gtid_get_specific: key:%d gtid:%d\n",
533 __kmp_gtid_threadprivate_key, gtid ));
534 return gtid;
535}
536
537/* ------------------------------------------------------------------------ */
538/* ------------------------------------------------------------------------ */
539
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000540#if KMP_GROUP_AFFINITY
Jim Cownie5e8470a2013-09-27 10:38:44 +0000541
542//
543// Only 1 DWORD in the mask should have any procs set.
544// Return the appropriate index, or -1 for an invalid mask.
545//
546int
547__kmp_get_proc_group( kmp_affin_mask_t const *mask )
548{
549 int i;
550 int group = -1;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000551 for (i = 0; i < __kmp_num_proc_groups; i++) {
552 if (mask[i] == 0) {
553 continue;
554 }
555 if (group >= 0) {
556 return -1;
557 }
558 group = i;
559 }
560 return group;
561}
562
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000563#endif /* KMP_GROUP_AFFINITY */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000564
565int
566__kmp_set_system_affinity( kmp_affin_mask_t const *mask, int abort_on_error )
567{
568
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000569#if KMP_GROUP_AFFINITY
Jim Cownie5e8470a2013-09-27 10:38:44 +0000570
571 if (__kmp_num_proc_groups > 1) {
572 //
573 // Check for a valid mask.
574 //
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000575 GROUP_AFFINITY ga;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000576 int group = __kmp_get_proc_group( mask );
577 if (group < 0) {
578 if (abort_on_error) {
579 KMP_FATAL(AffinityInvalidMask, "kmp_set_affinity");
580 }
581 return -1;
582 }
583
584 //
585 // Transform the bit vector into a GROUP_AFFINITY struct
586 // and make the system call to set affinity.
587 //
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000588 ga.Group = group;
589 ga.Mask = mask[group];
590 ga.Reserved[0] = ga.Reserved[1] = ga.Reserved[2] = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000591
592 KMP_DEBUG_ASSERT(__kmp_SetThreadGroupAffinity != NULL);
593 if (__kmp_SetThreadGroupAffinity(GetCurrentThread(), &ga, NULL) == 0) {
594 DWORD error = GetLastError();
595 if (abort_on_error) {
596 __kmp_msg(
597 kmp_ms_fatal,
598 KMP_MSG( CantSetThreadAffMask ),
599 KMP_ERR( error ),
600 __kmp_msg_null
601 );
602 }
603 return error;
604 }
605 }
606 else
607
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000608#endif /* KMP_GROUP_AFFINITY */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000609
610 {
611 if (!SetThreadAffinityMask( GetCurrentThread(), *mask )) {
612 DWORD error = GetLastError();
613 if (abort_on_error) {
614 __kmp_msg(
615 kmp_ms_fatal,
616 KMP_MSG( CantSetThreadAffMask ),
617 KMP_ERR( error ),
618 __kmp_msg_null
619 );
620 }
621 return error;
622 }
623 }
624 return 0;
625}
626
627int
628__kmp_get_system_affinity( kmp_affin_mask_t *mask, int abort_on_error )
629{
630
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000631#if KMP_GROUP_AFFINITY
Jim Cownie5e8470a2013-09-27 10:38:44 +0000632
633 if (__kmp_num_proc_groups > 1) {
634 KMP_CPU_ZERO(mask);
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000635 GROUP_AFFINITY ga;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000636 KMP_DEBUG_ASSERT(__kmp_GetThreadGroupAffinity != NULL);
637
638 if (__kmp_GetThreadGroupAffinity(GetCurrentThread(), &ga) == 0) {
639 DWORD error = GetLastError();
640 if (abort_on_error) {
641 __kmp_msg(
642 kmp_ms_fatal,
643 KMP_MSG(FunctionError, "GetThreadGroupAffinity()"),
644 KMP_ERR(error),
645 __kmp_msg_null
646 );
647 }
648 return error;
649 }
650
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000651 if ((ga.Group < 0) || (ga.Group > __kmp_num_proc_groups)
652 || (ga.Mask == 0)) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000653 return -1;
654 }
655
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000656 mask[ga.Group] = ga.Mask;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000657 }
658 else
659
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000660#endif /* KMP_GROUP_AFFINITY */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000661
662 {
663 kmp_affin_mask_t newMask, sysMask, retval;
664
665 if (!GetProcessAffinityMask(GetCurrentProcess(), &newMask, &sysMask)) {
666 DWORD error = GetLastError();
667 if (abort_on_error) {
668 __kmp_msg(
669 kmp_ms_fatal,
670 KMP_MSG(FunctionError, "GetProcessAffinityMask()"),
671 KMP_ERR(error),
672 __kmp_msg_null
673 );
674 }
675 return error;
676 }
677 retval = SetThreadAffinityMask(GetCurrentThread(), newMask);
678 if (! retval) {
679 DWORD error = GetLastError();
680 if (abort_on_error) {
681 __kmp_msg(
682 kmp_ms_fatal,
683 KMP_MSG(FunctionError, "SetThreadAffinityMask()"),
684 KMP_ERR(error),
685 __kmp_msg_null
686 );
687 }
688 return error;
689 }
690 newMask = SetThreadAffinityMask(GetCurrentThread(), retval);
691 if (! newMask) {
692 DWORD error = GetLastError();
693 if (abort_on_error) {
694 __kmp_msg(
695 kmp_ms_fatal,
696 KMP_MSG(FunctionError, "SetThreadAffinityMask()"),
697 KMP_ERR(error),
698 __kmp_msg_null
699 );
700 }
701 }
702 *mask = retval;
703 }
704 return 0;
705}
706
707void
708__kmp_affinity_bind_thread( int proc )
709{
710
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000711#if KMP_GROUP_AFFINITY
Jim Cownie5e8470a2013-09-27 10:38:44 +0000712
713 if (__kmp_num_proc_groups > 1) {
714 //
715 // Form the GROUP_AFFINITY struct directly, rather than filling
716 // out a bit vector and calling __kmp_set_system_affinity().
717 //
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000718 GROUP_AFFINITY ga;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000719 KMP_DEBUG_ASSERT((proc >= 0) && (proc < (__kmp_num_proc_groups
720 * CHAR_BIT * sizeof(DWORD_PTR))));
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000721 ga.Group = proc / (CHAR_BIT * sizeof(DWORD_PTR));
722 ga.Mask = (unsigned long long)1 << (proc % (CHAR_BIT * sizeof(DWORD_PTR)));
723 ga.Reserved[0] = ga.Reserved[1] = ga.Reserved[2] = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000724
725 KMP_DEBUG_ASSERT(__kmp_SetThreadGroupAffinity != NULL);
726 if (__kmp_SetThreadGroupAffinity(GetCurrentThread(), &ga, NULL) == 0) {
727 DWORD error = GetLastError();
728 if (__kmp_affinity_verbose) { // AC: continue silently if not verbose
729 __kmp_msg(
730 kmp_ms_warning,
731 KMP_MSG( CantSetThreadAffMask ),
732 KMP_ERR( error ),
733 __kmp_msg_null
734 );
735 }
736 }
737 }
738 else
739
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000740#endif /* KMP_GROUP_AFFINITY */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000741
742 {
743 kmp_affin_mask_t mask;
744 KMP_CPU_ZERO(&mask);
745 KMP_CPU_SET(proc, &mask);
746 __kmp_set_system_affinity(&mask, TRUE);
747 }
748}
749
750void
751__kmp_affinity_determine_capable( const char *env_var )
752{
753 //
754 // All versions of Windows* OS (since Win '95) support SetThreadAffinityMask().
755 //
756
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000757#if KMP_GROUP_AFFINITY
Andrey Churbanov1f037e42015-03-10 09:15:26 +0000758 KMP_AFFINITY_ENABLE(__kmp_num_proc_groups*sizeof(kmp_affin_mask_t));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000759#else
Andrey Churbanov1f037e42015-03-10 09:15:26 +0000760 KMP_AFFINITY_ENABLE(sizeof(kmp_affin_mask_t));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000761#endif
762
763 KA_TRACE( 10, (
764 "__kmp_affinity_determine_capable: "
765 "Windows* OS affinity interface functional (mask size = %" KMP_SIZE_T_SPEC ").\n",
766 __kmp_affin_mask_size
767 ) );
768}
769
770double
771__kmp_read_cpu_time( void )
772{
773 FILETIME CreationTime, ExitTime, KernelTime, UserTime;
774 int status;
775 double cpu_time;
776
777 cpu_time = 0;
778
779 status = GetProcessTimes( GetCurrentProcess(), &CreationTime,
780 &ExitTime, &KernelTime, &UserTime );
781
782 if (status) {
783 double sec = 0;
784
785 sec += KernelTime.dwHighDateTime;
786 sec += UserTime.dwHighDateTime;
787
788 /* Shift left by 32 bits */
789 sec *= (double) (1 << 16) * (double) (1 << 16);
790
791 sec += KernelTime.dwLowDateTime;
792 sec += UserTime.dwLowDateTime;
793
Jonathan Peyton1e7a1dd2015-06-04 17:29:13 +0000794 cpu_time += (sec * 100.0) / KMP_NSEC_PER_SEC;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000795 }
796
797 return cpu_time;
798}
799
800int
801__kmp_read_system_info( struct kmp_sys_info *info )
802{
803 info->maxrss = 0; /* the maximum resident set size utilized (in kilobytes) */
804 info->minflt = 0; /* the number of page faults serviced without any I/O */
805 info->majflt = 0; /* the number of page faults serviced that required I/O */
806 info->nswap = 0; /* the number of times a process was "swapped" out of memory */
807 info->inblock = 0; /* the number of times the file system had to perform input */
808 info->oublock = 0; /* the number of times the file system had to perform output */
809 info->nvcsw = 0; /* the number of times a context switch was voluntarily */
810 info->nivcsw = 0; /* the number of times a context switch was forced */
811
812 return 1;
813}
814
815/* ------------------------------------------------------------------------ */
816/* ------------------------------------------------------------------------ */
817
818
819void
820__kmp_runtime_initialize( void )
821{
822 SYSTEM_INFO info;
823 kmp_str_buf_t path;
824 UINT path_size;
825
826 if ( __kmp_init_runtime ) {
827 return;
828 };
829
Jonathan Peyton99016992015-05-26 17:32:53 +0000830#if KMP_DYNAMIC_LIB
Andrey Churbanov9bf53282015-01-29 17:18:20 +0000831 /* Pin dynamic library for the lifetime of application */
832 {
833 // First, turn off error message boxes
834 UINT err_mode = SetErrorMode (SEM_FAILCRITICALERRORS);
835 HMODULE h;
836 BOOL ret = GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
837 |GET_MODULE_HANDLE_EX_FLAG_PIN,
838 (LPCTSTR)&__kmp_serial_initialize, &h);
839 KMP_DEBUG_ASSERT2(h && ret, "OpenMP RTL cannot find itself loaded");
840 SetErrorMode (err_mode); // Restore error mode
841 KA_TRACE( 10, ("__kmp_runtime_initialize: dynamic library pinned\n") );
842 }
843#endif
844
Jim Cownie5e8470a2013-09-27 10:38:44 +0000845 InitializeCriticalSection( & __kmp_win32_section );
846#if USE_ITT_BUILD
847 __kmp_itt_system_object_created( & __kmp_win32_section, "Critical Section" );
848#endif /* USE_ITT_BUILD */
849 __kmp_initialize_system_tick();
850
851 #if (KMP_ARCH_X86 || KMP_ARCH_X86_64)
852 if ( ! __kmp_cpuinfo.initialized ) {
853 __kmp_query_cpuid( & __kmp_cpuinfo );
854 }; // if
855 #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
856
Jim Cownie5e8470a2013-09-27 10:38:44 +0000857 /* Set up minimum number of threads to switch to TLS gtid */
Jonathan Peyton99016992015-05-26 17:32:53 +0000858 #if KMP_OS_WINDOWS && ! defined KMP_DYNAMIC_LIB
Jim Cownie5e8470a2013-09-27 10:38:44 +0000859 // Windows* OS, static library.
860 /*
861 New thread may use stack space previously used by another thread, currently terminated.
862 On Windows* OS, in case of static linking, we do not know the moment of thread termination,
863 and our structures (__kmp_threads and __kmp_root arrays) are still keep info about dead
864 threads. This leads to problem in __kmp_get_global_thread_id() function: it wrongly
865 finds gtid (by searching through stack addresses of all known threads) for unregistered
866 foreign tread.
867
868 Setting __kmp_tls_gtid_min to 0 workarounds this problem: __kmp_get_global_thread_id()
Jonathan Peyton1406f012015-05-22 22:35:51 +0000869 does not search through stacks, but get gtid from TLS immediately.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000870
871 --ln
872 */
873 __kmp_tls_gtid_min = 0;
874 #else
875 __kmp_tls_gtid_min = KMP_TLS_GTID_MIN;
876 #endif
877
878 /* for the static library */
879 if ( !__kmp_gtid_threadprivate_key ) {
880 __kmp_gtid_threadprivate_key = TlsAlloc();
881 if( __kmp_gtid_threadprivate_key == TLS_OUT_OF_INDEXES ) {
882 KMP_FATAL( TLSOutOfIndexes );
883 }
884 }
885
886
887 //
888 // Load ntdll.dll.
889 //
890 /*
891 Simple
892 GetModuleHandle( "ntdll.dl" )
893 is not suitable due to security issue (see
894 http://www.microsoft.com/technet/security/advisory/2269637.mspx). We have to specify full
895 path to the library.
896 */
897 __kmp_str_buf_init( & path );
898 path_size = GetSystemDirectory( path.str, path.size );
899 KMP_DEBUG_ASSERT( path_size > 0 );
900 if ( path_size >= path.size ) {
901 //
902 // Buffer is too short. Expand the buffer and try again.
903 //
904 __kmp_str_buf_reserve( & path, path_size );
905 path_size = GetSystemDirectory( path.str, path.size );
906 KMP_DEBUG_ASSERT( path_size > 0 );
907 }; // if
908 if ( path_size > 0 && path_size < path.size ) {
909 //
910 // Now we have system directory name in the buffer.
911 // Append backslash and name of dll to form full path,
912 //
913 path.used = path_size;
914 __kmp_str_buf_print( & path, "\\%s", "ntdll.dll" );
915
916 //
917 // Now load ntdll using full path.
918 //
919 ntdll = GetModuleHandle( path.str );
920 }
921
922 KMP_DEBUG_ASSERT( ntdll != NULL );
923 if ( ntdll != NULL ) {
924 NtQuerySystemInformation = (NtQuerySystemInformation_t) GetProcAddress( ntdll, "NtQuerySystemInformation" );
925 }
926 KMP_DEBUG_ASSERT( NtQuerySystemInformation != NULL );
927
Andrey Churbanov7daf9802015-01-27 16:52:57 +0000928#if KMP_GROUP_AFFINITY
Jim Cownie5e8470a2013-09-27 10:38:44 +0000929 //
930 // Load kernel32.dll.
931 // Same caveat - must use full system path name.
932 //
933 if ( path_size > 0 && path_size < path.size ) {
934 //
935 // Truncate the buffer back to just the system path length,
936 // discarding "\\ntdll.dll", and replacing it with "kernel32.dll".
937 //
938 path.used = path_size;
939 __kmp_str_buf_print( & path, "\\%s", "kernel32.dll" );
940
941 //
942 // Load kernel32.dll using full path.
943 //
944 kernel32 = GetModuleHandle( path.str );
Andrey Churbanovdf6555b2015-01-27 17:00:03 +0000945 KA_TRACE( 10, ("__kmp_runtime_initialize: kernel32.dll = %s\n", path.str ) );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000946
947 //
948 // Load the function pointers to kernel32.dll routines
949 // that may or may not exist on this system.
950 //
951 if ( kernel32 != NULL ) {
952 __kmp_GetActiveProcessorCount = (kmp_GetActiveProcessorCount_t) GetProcAddress( kernel32, "GetActiveProcessorCount" );
953 __kmp_GetActiveProcessorGroupCount = (kmp_GetActiveProcessorGroupCount_t) GetProcAddress( kernel32, "GetActiveProcessorGroupCount" );
954 __kmp_GetThreadGroupAffinity = (kmp_GetThreadGroupAffinity_t) GetProcAddress( kernel32, "GetThreadGroupAffinity" );
955 __kmp_SetThreadGroupAffinity = (kmp_SetThreadGroupAffinity_t) GetProcAddress( kernel32, "SetThreadGroupAffinity" );
956
Andrey Churbanovdf6555b2015-01-27 17:00:03 +0000957 KA_TRACE( 10, ("__kmp_runtime_initialize: __kmp_GetActiveProcessorCount = %p\n", __kmp_GetActiveProcessorCount ) );
958 KA_TRACE( 10, ("__kmp_runtime_initialize: __kmp_GetActiveProcessorGroupCount = %p\n", __kmp_GetActiveProcessorGroupCount ) );
959 KA_TRACE( 10, ("__kmp_runtime_initialize:__kmp_GetThreadGroupAffinity = %p\n", __kmp_GetThreadGroupAffinity ) );
960 KA_TRACE( 10, ("__kmp_runtime_initialize: __kmp_SetThreadGroupAffinity = %p\n", __kmp_SetThreadGroupAffinity ) );
961 KA_TRACE( 10, ("__kmp_runtime_initialize: sizeof(kmp_affin_mask_t) = %d\n", sizeof(kmp_affin_mask_t) ) );
962
Jim Cownie5e8470a2013-09-27 10:38:44 +0000963 //
964 // See if group affinity is supported on this system.
965 // If so, calculate the #groups and #procs.
966 //
Jim Cownie4cc4bb42014-10-07 16:25:50 +0000967 // Group affinity was introduced with Windows* 7 OS and
Jim Cownie5e8470a2013-09-27 10:38:44 +0000968 // Windows* Server 2008 R2 OS.
969 //
970 if ( ( __kmp_GetActiveProcessorCount != NULL )
971 && ( __kmp_GetActiveProcessorGroupCount != NULL )
972 && ( __kmp_GetThreadGroupAffinity != NULL )
973 && ( __kmp_SetThreadGroupAffinity != NULL )
974 && ( ( __kmp_num_proc_groups
975 = __kmp_GetActiveProcessorGroupCount() ) > 1 ) ) {
976 //
977 // Calculate the total number of active OS procs.
978 //
979 int i;
980
981 KA_TRACE( 10, ("__kmp_runtime_initialize: %d processor groups detected\n", __kmp_num_proc_groups ) );
982
983 __kmp_xproc = 0;
984
985 for ( i = 0; i < __kmp_num_proc_groups; i++ ) {
986 DWORD size = __kmp_GetActiveProcessorCount( i );
987 __kmp_xproc += size;
Andrey Churbanovdf6555b2015-01-27 17:00:03 +0000988 KA_TRACE( 10, ("__kmp_runtime_initialize: proc group %d size = %d\n", i, size ) );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000989 }
Andrey Churbanovdf6555b2015-01-27 17:00:03 +0000990 }
991 else {
992 KA_TRACE( 10, ("__kmp_runtime_initialize: %d processor groups detected\n", __kmp_num_proc_groups ) );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000993 }
994 }
995 }
996 if ( __kmp_num_proc_groups <= 1 ) {
997 GetSystemInfo( & info );
998 __kmp_xproc = info.dwNumberOfProcessors;
999 }
1000#else
1001 GetSystemInfo( & info );
1002 __kmp_xproc = info.dwNumberOfProcessors;
Andrey Churbanov7daf9802015-01-27 16:52:57 +00001003#endif /* KMP_GROUP_AFFINITY */
Jim Cownie5e8470a2013-09-27 10:38:44 +00001004
1005 //
1006 // If the OS said there were 0 procs, take a guess and use a value of 2.
1007 // This is done for Linux* OS, also. Do we need error / warning?
1008 //
1009 if ( __kmp_xproc <= 0 ) {
1010 __kmp_xproc = 2;
1011 }
1012
1013 KA_TRACE( 5, ("__kmp_runtime_initialize: total processors = %d\n", __kmp_xproc) );
1014
1015 __kmp_str_buf_free( & path );
1016
1017#if USE_ITT_BUILD
1018 __kmp_itt_initialize();
1019#endif /* USE_ITT_BUILD */
1020
1021 __kmp_init_runtime = TRUE;
1022} // __kmp_runtime_initialize
1023
1024void
1025__kmp_runtime_destroy( void )
1026{
1027 if ( ! __kmp_init_runtime ) {
1028 return;
1029 }
1030
1031#if USE_ITT_BUILD
1032 __kmp_itt_destroy();
1033#endif /* USE_ITT_BUILD */
1034
1035 /* we can't DeleteCriticalsection( & __kmp_win32_section ); */
1036 /* due to the KX_TRACE() commands */
1037 KA_TRACE( 40, ("__kmp_runtime_destroy\n" ));
1038
1039 if( __kmp_gtid_threadprivate_key ) {
1040 TlsFree( __kmp_gtid_threadprivate_key );
1041 __kmp_gtid_threadprivate_key = 0;
1042 }
1043
1044 __kmp_affinity_uninitialize();
1045 DeleteCriticalSection( & __kmp_win32_section );
1046
1047 ntdll = NULL;
1048 NtQuerySystemInformation = NULL;
1049
1050#if KMP_ARCH_X86_64
1051 kernel32 = NULL;
1052 __kmp_GetActiveProcessorCount = NULL;
1053 __kmp_GetActiveProcessorGroupCount = NULL;
1054 __kmp_GetThreadGroupAffinity = NULL;
1055 __kmp_SetThreadGroupAffinity = NULL;
1056#endif // KMP_ARCH_X86_64
1057
1058 __kmp_init_runtime = FALSE;
1059}
1060
1061
1062void
1063__kmp_terminate_thread( int gtid )
1064{
1065 kmp_info_t *th = __kmp_threads[ gtid ];
1066
1067 if( !th ) return;
1068
1069 KA_TRACE( 10, ("__kmp_terminate_thread: kill (%d)\n", gtid ) );
1070
1071 if (TerminateThread( th->th.th_info.ds.ds_thread, (DWORD) -1) == FALSE) {
1072 /* It's OK, the thread may have exited already */
1073 }
1074 __kmp_free_handle( th->th.th_info.ds.ds_thread );
1075}
1076
1077/* ------------------------------------------------------------------------ */
1078/* ------------------------------------------------------------------------ */
1079
1080void
1081__kmp_clear_system_time( void )
1082{
1083 BOOL status;
1084 LARGE_INTEGER time;
1085 status = QueryPerformanceCounter( & time );
1086 __kmp_win32_time = (kmp_int64) time.QuadPart;
1087}
1088
1089void
1090__kmp_initialize_system_tick( void )
1091{
1092 {
1093 BOOL status;
1094 LARGE_INTEGER freq;
1095
1096 status = QueryPerformanceFrequency( & freq );
1097 if (! status) {
1098 DWORD error = GetLastError();
1099 __kmp_msg(
1100 kmp_ms_fatal,
1101 KMP_MSG( FunctionError, "QueryPerformanceFrequency()" ),
1102 KMP_ERR( error ),
1103 __kmp_msg_null
1104 );
1105
1106 }
1107 else {
1108 __kmp_win32_tick = ((double) 1.0) / (double) freq.QuadPart;
1109 }
1110 }
1111}
1112
1113/* Calculate the elapsed wall clock time for the user */
1114
1115void
1116__kmp_elapsed( double *t )
1117{
1118 BOOL status;
1119 LARGE_INTEGER now;
1120 status = QueryPerformanceCounter( & now );
1121 *t = ((double) now.QuadPart) * __kmp_win32_tick;
1122}
1123
1124/* Calculate the elapsed wall clock tick for the user */
1125
1126void
1127__kmp_elapsed_tick( double *t )
1128{
1129 *t = __kmp_win32_tick;
1130}
1131
1132void
1133__kmp_read_system_time( double *delta )
1134{
Jim Cownie5e8470a2013-09-27 10:38:44 +00001135 if (delta != NULL) {
1136 BOOL status;
1137 LARGE_INTEGER now;
1138
1139 status = QueryPerformanceCounter( & now );
1140
1141 *delta = ((double) (((kmp_int64) now.QuadPart) - __kmp_win32_time))
1142 * __kmp_win32_tick;
1143 }
1144}
1145
1146/* ------------------------------------------------------------------------ */
1147/* ------------------------------------------------------------------------ */
1148
Jim Cownie5e8470a2013-09-27 10:38:44 +00001149void * __stdcall
1150__kmp_launch_worker( void *arg )
1151{
1152 volatile void *stack_data;
1153 void *exit_val;
1154 void *padding = 0;
1155 kmp_info_t *this_thr = (kmp_info_t *) arg;
1156 int gtid;
1157
1158 gtid = this_thr->th.th_info.ds.ds_gtid;
1159 __kmp_gtid_set_specific( gtid );
1160#ifdef KMP_TDATA_GTID
1161 #error "This define causes problems with LoadLibrary() + declspec(thread) " \
1162 "on Windows* OS. See CQ50564, tests kmp_load_library*.c and this MSDN " \
1163 "reference: http://support.microsoft.com/kb/118816"
1164 //__kmp_gtid = gtid;
1165#endif
1166
1167#if USE_ITT_BUILD
1168 __kmp_itt_thread_name( gtid );
1169#endif /* USE_ITT_BUILD */
1170
1171 __kmp_affinity_set_init_mask( gtid, FALSE );
1172
1173#if KMP_ARCH_X86 || KMP_ARCH_X86_64
1174 //
1175 // Set the FP control regs to be a copy of
1176 // the parallel initialization thread's.
1177 //
1178 __kmp_clear_x87_fpu_status_word();
1179 __kmp_load_x87_fpu_control_word( &__kmp_init_x87_fpu_control_word );
1180 __kmp_load_mxcsr( &__kmp_init_mxcsr );
1181#endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
1182
1183 if ( __kmp_stkoffset > 0 && gtid > 0 ) {
Andrey Churbanov74bf17b2015-04-02 13:27:08 +00001184 padding = KMP_ALLOCA( gtid * __kmp_stkoffset );
Jim Cownie5e8470a2013-09-27 10:38:44 +00001185 }
1186
1187 KMP_FSYNC_RELEASING( &this_thr -> th.th_info.ds.ds_alive );
1188 this_thr -> th.th_info.ds.ds_thread_id = GetCurrentThreadId();
1189 TCW_4( this_thr -> th.th_info.ds.ds_alive, TRUE );
1190
1191 if ( TCR_4(__kmp_gtid_mode) < 2 ) { // check stack only if it is used to get gtid
1192 TCW_PTR(this_thr->th.th_info.ds.ds_stackbase, &stack_data);
1193 KMP_ASSERT( this_thr -> th.th_info.ds.ds_stackgrow == FALSE );
1194 __kmp_check_stack_overlap( this_thr );
1195 }
1196 KMP_MB();
1197 exit_val = __kmp_launch_thread( this_thr );
1198 KMP_FSYNC_RELEASING( &this_thr -> th.th_info.ds.ds_alive );
1199 TCW_4( this_thr -> th.th_info.ds.ds_alive, FALSE );
1200 KMP_MB();
1201 return exit_val;
1202}
1203
Jim Cownie5e8470a2013-09-27 10:38:44 +00001204/* The monitor thread controls all of the threads in the complex */
1205
1206void * __stdcall
1207__kmp_launch_monitor( void *arg )
1208{
1209 DWORD wait_status;
1210 kmp_thread_t monitor;
1211 int status;
1212 int interval;
1213 kmp_info_t *this_thr = (kmp_info_t *) arg;
1214
1215 KMP_DEBUG_ASSERT(__kmp_init_monitor);
1216 TCW_4( __kmp_init_monitor, 2 ); // AC: Signal the library that monitor has started
1217 // TODO: hide "2" in enum (like {true,false,started})
1218 this_thr -> th.th_info.ds.ds_thread_id = GetCurrentThreadId();
1219 TCW_4( this_thr -> th.th_info.ds.ds_alive, TRUE );
1220
1221 KMP_MB(); /* Flush all pending memory write invalidates. */
1222 KA_TRACE( 10, ("__kmp_launch_monitor: launched\n" ) );
1223
1224 monitor = GetCurrentThread();
1225
1226 /* set thread priority */
1227 status = SetThreadPriority( monitor, THREAD_PRIORITY_HIGHEST );
1228 if (! status) {
1229 DWORD error = GetLastError();
1230 __kmp_msg(
1231 kmp_ms_fatal,
1232 KMP_MSG( CantSetThreadPriority ),
1233 KMP_ERR( error ),
1234 __kmp_msg_null
1235 );
1236 }
1237
1238 /* register us as monitor */
1239 __kmp_gtid_set_specific( KMP_GTID_MONITOR );
1240#ifdef KMP_TDATA_GTID
1241 #error "This define causes problems with LoadLibrary() + declspec(thread) " \
1242 "on Windows* OS. See CQ50564, tests kmp_load_library*.c and this MSDN " \
1243 "reference: http://support.microsoft.com/kb/118816"
1244 //__kmp_gtid = KMP_GTID_MONITOR;
1245#endif
1246
1247#if USE_ITT_BUILD
1248 __kmp_itt_thread_ignore(); // Instruct Intel(R) Threading Tools to ignore monitor thread.
1249#endif /* USE_ITT_BUILD */
1250
1251 KMP_MB(); /* Flush all pending memory write invalidates. */
1252
1253 interval = ( 1000 / __kmp_monitor_wakeups ); /* in milliseconds */
1254
1255 while (! TCR_4(__kmp_global.g.g_done)) {
1256 /* This thread monitors the state of the system */
1257
1258 KA_TRACE( 15, ( "__kmp_launch_monitor: update\n" ) );
1259
1260 wait_status = WaitForSingleObject( __kmp_monitor_ev, interval );
1261
1262 if (wait_status == WAIT_TIMEOUT) {
1263 TCW_4( __kmp_global.g.g_time.dt.t_value,
1264 TCR_4( __kmp_global.g.g_time.dt.t_value ) + 1 );
1265 }
1266
1267 KMP_MB(); /* Flush all pending memory write invalidates. */
1268 }
1269
1270 KA_TRACE( 10, ("__kmp_launch_monitor: finished\n" ) );
1271
1272 status = SetThreadPriority( monitor, THREAD_PRIORITY_NORMAL );
1273 if (! status) {
1274 DWORD error = GetLastError();
1275 __kmp_msg(
1276 kmp_ms_fatal,
1277 KMP_MSG( CantSetThreadPriority ),
1278 KMP_ERR( error ),
1279 __kmp_msg_null
1280 );
1281 }
1282
1283 if (__kmp_global.g.g_abort != 0) {
1284 /* now we need to terminate the worker threads */
1285 /* the value of t_abort is the signal we caught */
1286
1287 int gtid;
1288
1289 KA_TRACE( 10, ("__kmp_launch_monitor: terminate sig=%d\n", (__kmp_global.g.g_abort) ) );
1290
1291 /* terminate the OpenMP worker threads */
1292 /* TODO this is not valid for sibling threads!!
1293 * the uber master might not be 0 anymore.. */
1294 for (gtid = 1; gtid < __kmp_threads_capacity; ++gtid)
1295 __kmp_terminate_thread( gtid );
1296
1297 __kmp_cleanup();
1298
1299 Sleep( 0 );
1300
1301 KA_TRACE( 10, ("__kmp_launch_monitor: raise sig=%d\n", (__kmp_global.g.g_abort) ) );
1302
1303 if (__kmp_global.g.g_abort > 0) {
1304 raise( __kmp_global.g.g_abort );
1305 }
1306 }
1307
1308 TCW_4( this_thr -> th.th_info.ds.ds_alive, FALSE );
1309
1310 KMP_MB();
1311 return arg;
1312}
1313
1314void
1315__kmp_create_worker( int gtid, kmp_info_t *th, size_t stack_size )
1316{
1317 kmp_thread_t handle;
1318 DWORD idThread;
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001319
Jim Cownie5e8470a2013-09-27 10:38:44 +00001320 KA_TRACE( 10, ("__kmp_create_worker: try to create thread (%d)\n", gtid ) );
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001321
Jim Cownie5e8470a2013-09-27 10:38:44 +00001322 th->th.th_info.ds.ds_gtid = gtid;
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001323
Jim Cownie5e8470a2013-09-27 10:38:44 +00001324 if ( KMP_UBER_GTID(gtid) ) {
1325 int stack_data;
1326
1327 /* TODO: GetCurrentThread() returns a pseudo-handle that is unsuitable for other threads to use.
1328 Is it appropriate to just use GetCurrentThread? When should we close this handle? When
1329 unregistering the root?
1330 */
1331 {
1332 BOOL rc;
1333 rc = DuplicateHandle(
1334 GetCurrentProcess(),
1335 GetCurrentThread(),
1336 GetCurrentProcess(),
1337 &th->th.th_info.ds.ds_thread,
1338 0,
1339 FALSE,
1340 DUPLICATE_SAME_ACCESS
1341 );
1342 KMP_ASSERT( rc );
1343 KA_TRACE( 10, (" __kmp_create_worker: ROOT Handle duplicated, th = %p, handle = %" KMP_UINTPTR_SPEC "\n",
1344 (LPVOID)th,
1345 th->th.th_info.ds.ds_thread ) );
1346 th->th.th_info.ds.ds_thread_id = GetCurrentThreadId();
1347 }
1348 if ( TCR_4(__kmp_gtid_mode) < 2 ) { // check stack only if it is used to get gtid
1349 /* we will dynamically update the stack range if gtid_mode == 1 */
1350 TCW_PTR(th->th.th_info.ds.ds_stackbase, &stack_data);
1351 TCW_PTR(th->th.th_info.ds.ds_stacksize, 0);
1352 TCW_4(th->th.th_info.ds.ds_stackgrow, TRUE);
1353 __kmp_check_stack_overlap( th );
1354 }
1355 }
1356 else {
1357 KMP_MB(); /* Flush all pending memory write invalidates. */
1358
1359 /* Set stack size for this thread now. */
1360 KA_TRACE( 10, ( "__kmp_create_worker: stack_size = %" KMP_SIZE_T_SPEC
1361 " bytes\n", stack_size ) );
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001362
Jim Cownie5e8470a2013-09-27 10:38:44 +00001363 stack_size += gtid * __kmp_stkoffset;
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001364
Jim Cownie5e8470a2013-09-27 10:38:44 +00001365 TCW_PTR(th->th.th_info.ds.ds_stacksize, stack_size);
1366 TCW_4(th->th.th_info.ds.ds_stackgrow, FALSE);
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001367
Jim Cownie5e8470a2013-09-27 10:38:44 +00001368 KA_TRACE( 10, ( "__kmp_create_worker: (before) stack_size = %"
1369 KMP_SIZE_T_SPEC
1370 " bytes, &__kmp_launch_worker = %p, th = %p, "
1371 "&idThread = %p\n",
1372 (SIZE_T) stack_size,
1373 (LPTHREAD_START_ROUTINE) & __kmp_launch_worker,
1374 (LPVOID) th, &idThread ) );
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001375
Jonathan Peyton749b4d52016-01-27 21:02:04 +00001376 handle = CreateThread( NULL, (SIZE_T) stack_size,
1377 (LPTHREAD_START_ROUTINE) __kmp_launch_worker,
1378 (LPVOID) th, STACK_SIZE_PARAM_IS_A_RESERVATION, &idThread );
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001379
Jim Cownie5e8470a2013-09-27 10:38:44 +00001380 KA_TRACE( 10, ( "__kmp_create_worker: (after) stack_size = %"
1381 KMP_SIZE_T_SPEC
1382 " bytes, &__kmp_launch_worker = %p, th = %p, "
1383 "idThread = %u, handle = %" KMP_UINTPTR_SPEC "\n",
1384 (SIZE_T) stack_size,
1385 (LPTHREAD_START_ROUTINE) & __kmp_launch_worker,
1386 (LPVOID) th, idThread, handle ) );
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001387
Jonathan Peyton749b4d52016-01-27 21:02:04 +00001388 if ( handle == 0 ) {
1389 DWORD error = GetLastError();
1390 __kmp_msg(kmp_ms_fatal, KMP_MSG( CantCreateThread ), KMP_ERR( error ), __kmp_msg_null);
1391 } else {
1392 th->th.th_info.ds.ds_thread = handle;
1393 }
1394
Jim Cownie5e8470a2013-09-27 10:38:44 +00001395 KMP_MB(); /* Flush all pending memory write invalidates. */
1396 }
Jim Cownie4cc4bb42014-10-07 16:25:50 +00001397
Jim Cownie5e8470a2013-09-27 10:38:44 +00001398 KA_TRACE( 10, ("__kmp_create_worker: done creating thread (%d)\n", gtid ) );
1399}
1400
1401int
1402__kmp_still_running(kmp_info_t *th) {
1403 return (WAIT_TIMEOUT == WaitForSingleObject( th->th.th_info.ds.ds_thread, 0));
1404}
1405
1406void
1407__kmp_create_monitor( kmp_info_t *th )
1408{
1409 kmp_thread_t handle;
1410 DWORD idThread;
1411 int ideal, new_ideal;
Jim Cownie5e8470a2013-09-27 10:38:44 +00001412
Jonathan Peyton4fee5f62015-12-18 23:20:36 +00001413 if( __kmp_dflt_blocktime == KMP_MAX_BLOCKTIME ) {
1414 // We don't need monitor thread in case of MAX_BLOCKTIME
1415 KA_TRACE( 10, ("__kmp_create_monitor: skipping monitor thread because of MAX blocktime\n" ) );
1416 th->th.th_info.ds.ds_tid = 0; // this makes reap_monitor no-op
1417 th->th.th_info.ds.ds_gtid = 0;
1418 TCW_4( __kmp_init_monitor, 2 ); // Signal to stop waiting for monitor creation
1419 return;
1420 }
Jim Cownie5e8470a2013-09-27 10:38:44 +00001421 KA_TRACE( 10, ("__kmp_create_monitor: try to create monitor\n" ) );
1422
1423 KMP_MB(); /* Flush all pending memory write invalidates. */
1424
1425 __kmp_monitor_ev = CreateEvent( NULL, TRUE, FALSE, NULL );
1426 if ( __kmp_monitor_ev == NULL ) {
1427 DWORD error = GetLastError();
1428 __kmp_msg(
1429 kmp_ms_fatal,
1430 KMP_MSG( CantCreateEvent ),
1431 KMP_ERR( error ),
1432 __kmp_msg_null
1433 );
1434 }; // if
1435#if USE_ITT_BUILD
1436 __kmp_itt_system_object_created( __kmp_monitor_ev, "Event" );
1437#endif /* USE_ITT_BUILD */
1438
1439 th->th.th_info.ds.ds_tid = KMP_GTID_MONITOR;
1440 th->th.th_info.ds.ds_gtid = KMP_GTID_MONITOR;
1441
1442 // FIXME - on Windows* OS, if __kmp_monitor_stksize = 0, figure out how
1443 // to automatically expand stacksize based on CreateThread error code.
1444 if ( __kmp_monitor_stksize == 0 ) {
1445 __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE;
1446 }
1447 if ( __kmp_monitor_stksize < __kmp_sys_min_stksize ) {
1448 __kmp_monitor_stksize = __kmp_sys_min_stksize;
1449 }
1450
1451 KA_TRACE( 10, ("__kmp_create_monitor: requested stacksize = %d bytes\n",
1452 (int) __kmp_monitor_stksize ) );
1453
1454 TCW_4( __kmp_global.g.g_time.dt.t_value, 0 );
1455
1456 handle = CreateThread( NULL, (SIZE_T) __kmp_monitor_stksize,
1457 (LPTHREAD_START_ROUTINE) __kmp_launch_monitor,
1458 (LPVOID) th, STACK_SIZE_PARAM_IS_A_RESERVATION, &idThread );
1459 if (handle == 0) {
1460 DWORD error = GetLastError();
1461 __kmp_msg(
1462 kmp_ms_fatal,
1463 KMP_MSG( CantCreateThread ),
1464 KMP_ERR( error ),
1465 __kmp_msg_null
1466 );
1467 }
1468 else
1469 th->th.th_info.ds.ds_thread = handle;
1470
1471 KMP_MB(); /* Flush all pending memory write invalidates. */
1472
1473 KA_TRACE( 10, ("__kmp_create_monitor: monitor created %p\n",
1474 (void *) th->th.th_info.ds.ds_thread ) );
1475}
1476
1477/*
1478 Check to see if thread is still alive.
1479
1480 NOTE: The ExitProcess(code) system call causes all threads to Terminate
1481 with a exit_val = code. Because of this we can not rely on
1482 exit_val having any particular value. So this routine may
1483 return STILL_ALIVE in exit_val even after the thread is dead.
1484*/
1485
1486int
1487__kmp_is_thread_alive( kmp_info_t * th, DWORD *exit_val )
1488{
1489 DWORD rc;
1490 rc = GetExitCodeThread( th->th.th_info.ds.ds_thread, exit_val );
1491 if ( rc == 0 ) {
1492 DWORD error = GetLastError();
1493 __kmp_msg(
1494 kmp_ms_fatal,
1495 KMP_MSG( FunctionError, "GetExitCodeThread()" ),
1496 KMP_ERR( error ),
1497 __kmp_msg_null
1498 );
1499 }; // if
1500 return ( *exit_val == STILL_ACTIVE );
1501}
1502
1503
1504void
1505__kmp_exit_thread(
1506 int exit_status
1507) {
1508 ExitThread( exit_status );
1509} // __kmp_exit_thread
1510
1511/*
1512 This is a common part for both __kmp_reap_worker() and __kmp_reap_monitor().
1513*/
1514static void
1515__kmp_reap_common( kmp_info_t * th )
1516{
1517 DWORD exit_val;
1518
1519 KMP_MB(); /* Flush all pending memory write invalidates. */
1520
1521 KA_TRACE( 10, ( "__kmp_reap_common: try to reap (%d)\n", th->th.th_info.ds.ds_gtid ) );
1522
1523 /*
1524 2006-10-19:
1525
1526 There are two opposite situations:
1527
1528 1. Windows* OS keep thread alive after it resets ds_alive flag and exits from thread
1529 function. (For example, see C70770/Q394281 "unloading of dll based on OMP is very
1530 slow".)
1531 2. Windows* OS may kill thread before it resets ds_alive flag.
1532
1533 Right solution seems to be waiting for *either* thread termination *or* ds_alive resetting.
1534
1535 */
1536
1537 {
1538 // TODO: This code is very similar to KMP_WAIT_YIELD. Need to generalize KMP_WAIT_YIELD to
1539 // cover this usage also.
1540 void * obj = NULL;
1541 register kmp_uint32 spins;
1542#if USE_ITT_BUILD
1543 KMP_FSYNC_SPIN_INIT( obj, (void*) & th->th.th_info.ds.ds_alive );
1544#endif /* USE_ITT_BUILD */
1545 KMP_INIT_YIELD( spins );
1546 do {
1547#if USE_ITT_BUILD
1548 KMP_FSYNC_SPIN_PREPARE( obj );
1549#endif /* USE_ITT_BUILD */
1550 __kmp_is_thread_alive( th, &exit_val );
Jim Cownie5e8470a2013-09-27 10:38:44 +00001551 KMP_YIELD( TCR_4(__kmp_nth) > __kmp_avail_proc );
1552 KMP_YIELD_SPIN( spins );
1553 } while ( exit_val == STILL_ACTIVE && TCR_4( th->th.th_info.ds.ds_alive ) );
1554#if USE_ITT_BUILD
1555 if ( exit_val == STILL_ACTIVE ) {
1556 KMP_FSYNC_CANCEL( obj );
1557 } else {
1558 KMP_FSYNC_SPIN_ACQUIRED( obj );
1559 }; // if
1560#endif /* USE_ITT_BUILD */
1561 }
1562
1563 __kmp_free_handle( th->th.th_info.ds.ds_thread );
1564
1565 /*
1566 * NOTE: The ExitProcess(code) system call causes all threads to Terminate
1567 * with a exit_val = code. Because of this we can not rely on
1568 * exit_val having any particular value.
1569 */
1570 if ( exit_val == STILL_ACTIVE ) {
1571 KA_TRACE( 1, ( "__kmp_reap_common: thread still active.\n" ) );
1572 } else if ( (void *) exit_val != (void *) th) {
1573 KA_TRACE( 1, ( "__kmp_reap_common: ExitProcess / TerminateThread used?\n" ) );
1574 }; // if
1575
1576 KA_TRACE( 10,
1577 (
1578 "__kmp_reap_common: done reaping (%d), handle = %" KMP_UINTPTR_SPEC "\n",
1579 th->th.th_info.ds.ds_gtid,
1580 th->th.th_info.ds.ds_thread
1581 )
1582 );
1583
1584 th->th.th_info.ds.ds_thread = 0;
1585 th->th.th_info.ds.ds_tid = KMP_GTID_DNE;
1586 th->th.th_info.ds.ds_gtid = KMP_GTID_DNE;
1587 th->th.th_info.ds.ds_thread_id = 0;
1588
1589 KMP_MB(); /* Flush all pending memory write invalidates. */
1590}
1591
1592void
1593__kmp_reap_monitor( kmp_info_t *th )
1594{
1595 int status;
1596
1597 KA_TRACE( 10, ("__kmp_reap_monitor: try to reap %p\n",
1598 (void *) th->th.th_info.ds.ds_thread ) );
1599
1600 // If monitor has been created, its tid and gtid should be KMP_GTID_MONITOR.
1601 // If both tid and gtid are 0, it means the monitor did not ever start.
1602 // If both tid and gtid are KMP_GTID_DNE, the monitor has been shut down.
1603 KMP_DEBUG_ASSERT( th->th.th_info.ds.ds_tid == th->th.th_info.ds.ds_gtid );
1604 if ( th->th.th_info.ds.ds_gtid != KMP_GTID_MONITOR ) {
Jonathan Peyton4fee5f62015-12-18 23:20:36 +00001605 KA_TRACE( 10, ("__kmp_reap_monitor: monitor did not start, returning\n") );
Jim Cownie5e8470a2013-09-27 10:38:44 +00001606 return;
1607 }; // if
1608
1609 KMP_MB(); /* Flush all pending memory write invalidates. */
1610
1611 status = SetEvent( __kmp_monitor_ev );
1612 if ( status == FALSE ) {
1613 DWORD error = GetLastError();
1614 __kmp_msg(
1615 kmp_ms_fatal,
1616 KMP_MSG( CantSetEvent ),
1617 KMP_ERR( error ),
1618 __kmp_msg_null
1619 );
1620 }
1621 KA_TRACE( 10, ( "__kmp_reap_monitor: reaping thread (%d)\n", th->th.th_info.ds.ds_gtid ) );
1622 __kmp_reap_common( th );
1623
1624 __kmp_free_handle( __kmp_monitor_ev );
1625
1626 KMP_MB(); /* Flush all pending memory write invalidates. */
1627}
1628
1629void
1630__kmp_reap_worker( kmp_info_t * th )
1631{
1632 KA_TRACE( 10, ( "__kmp_reap_worker: reaping thread (%d)\n", th->th.th_info.ds.ds_gtid ) );
1633 __kmp_reap_common( th );
1634}
1635
1636/* ------------------------------------------------------------------------ */
1637/* ------------------------------------------------------------------------ */
1638
1639#if KMP_HANDLE_SIGNALS
1640
1641
1642static void
1643__kmp_team_handler( int signo )
1644{
1645 if ( __kmp_global.g.g_abort == 0 ) {
1646 // Stage 1 signal handler, let's shut down all of the threads.
1647 if ( __kmp_debug_buf ) {
1648 __kmp_dump_debug_buffer();
1649 }; // if
1650 KMP_MB(); // Flush all pending memory write invalidates.
1651 TCW_4( __kmp_global.g.g_abort, signo );
1652 KMP_MB(); // Flush all pending memory write invalidates.
1653 TCW_4( __kmp_global.g.g_done, TRUE );
1654 KMP_MB(); // Flush all pending memory write invalidates.
1655 }
1656} // __kmp_team_handler
1657
1658
1659
1660static
1661sig_func_t __kmp_signal( int signum, sig_func_t handler ) {
1662 sig_func_t old = signal( signum, handler );
1663 if ( old == SIG_ERR ) {
1664 int error = errno;
1665 __kmp_msg( kmp_ms_fatal, KMP_MSG( FunctionError, "signal" ), KMP_ERR( error ), __kmp_msg_null );
1666 }; // if
1667 return old;
1668}
1669
1670static void
1671__kmp_install_one_handler(
1672 int sig,
1673 sig_func_t handler,
1674 int parallel_init
1675) {
1676 sig_func_t old;
1677 KMP_MB(); /* Flush all pending memory write invalidates. */
1678 KB_TRACE( 60, ("__kmp_install_one_handler: called: sig=%d\n", sig ) );
1679 if ( parallel_init ) {
1680 old = __kmp_signal( sig, handler );
1681 // SIG_DFL on Windows* OS in NULL or 0.
1682 if ( old == __kmp_sighldrs[ sig ] ) {
1683 __kmp_siginstalled[ sig ] = 1;
1684 } else {
1685 // Restore/keep user's handler if one previously installed.
1686 old = __kmp_signal( sig, old );
1687 }; // if
1688 } else {
1689 // Save initial/system signal handlers to see if user handlers installed.
1690 // 2009-09-23: It is a dead code. On Windows* OS __kmp_install_signals called once with
1691 // parallel_init == TRUE.
1692 old = __kmp_signal( sig, SIG_DFL );
1693 __kmp_sighldrs[ sig ] = old;
1694 __kmp_signal( sig, old );
1695 }; // if
1696 KMP_MB(); /* Flush all pending memory write invalidates. */
1697} // __kmp_install_one_handler
1698
1699static void
1700__kmp_remove_one_handler( int sig ) {
1701 if ( __kmp_siginstalled[ sig ] ) {
1702 sig_func_t old;
1703 KMP_MB(); // Flush all pending memory write invalidates.
1704 KB_TRACE( 60, ( "__kmp_remove_one_handler: called: sig=%d\n", sig ) );
1705 old = __kmp_signal( sig, __kmp_sighldrs[ sig ] );
1706 if ( old != __kmp_team_handler ) {
1707 KB_TRACE( 10, ( "__kmp_remove_one_handler: oops, not our handler, restoring: sig=%d\n", sig ) );
1708 old = __kmp_signal( sig, old );
1709 }; // if
1710 __kmp_sighldrs[ sig ] = NULL;
1711 __kmp_siginstalled[ sig ] = 0;
1712 KMP_MB(); // Flush all pending memory write invalidates.
1713 }; // if
1714} // __kmp_remove_one_handler
1715
1716
1717void
1718__kmp_install_signals( int parallel_init )
1719{
1720 KB_TRACE( 10, ( "__kmp_install_signals: called\n" ) );
1721 if ( ! __kmp_handle_signals ) {
1722 KB_TRACE( 10, ( "__kmp_install_signals: KMP_HANDLE_SIGNALS is false - handlers not installed\n" ) );
1723 return;
1724 }; // if
1725 __kmp_install_one_handler( SIGINT, __kmp_team_handler, parallel_init );
1726 __kmp_install_one_handler( SIGILL, __kmp_team_handler, parallel_init );
1727 __kmp_install_one_handler( SIGABRT, __kmp_team_handler, parallel_init );
1728 __kmp_install_one_handler( SIGFPE, __kmp_team_handler, parallel_init );
1729 __kmp_install_one_handler( SIGSEGV, __kmp_team_handler, parallel_init );
1730 __kmp_install_one_handler( SIGTERM, __kmp_team_handler, parallel_init );
1731} // __kmp_install_signals
1732
1733
1734void
1735__kmp_remove_signals( void )
1736{
1737 int sig;
1738 KB_TRACE( 10, ("__kmp_remove_signals: called\n" ) );
1739 for ( sig = 1; sig < NSIG; ++ sig ) {
1740 __kmp_remove_one_handler( sig );
1741 }; // for sig
1742} // __kmp_remove_signals
1743
1744
1745#endif // KMP_HANDLE_SIGNALS
1746
1747/* Put the thread to sleep for a time period */
1748void
1749__kmp_thread_sleep( int millis )
1750{
1751 DWORD status;
1752
1753 status = SleepEx( (DWORD) millis, FALSE );
1754 if ( status ) {
1755 DWORD error = GetLastError();
1756 __kmp_msg(
1757 kmp_ms_fatal,
1758 KMP_MSG( FunctionError, "SleepEx()" ),
1759 KMP_ERR( error ),
1760 __kmp_msg_null
1761 );
1762 }
1763}
1764
1765/* Determine whether the given address is mapped into the current address space. */
1766int
1767__kmp_is_address_mapped( void * addr )
1768{
1769 DWORD status;
1770 MEMORY_BASIC_INFORMATION lpBuffer;
1771 SIZE_T dwLength;
1772
1773 dwLength = sizeof(MEMORY_BASIC_INFORMATION);
1774
1775 status = VirtualQuery( addr, &lpBuffer, dwLength );
1776
1777 return !((( lpBuffer.State == MEM_RESERVE) || ( lpBuffer.State == MEM_FREE )) ||
1778 (( lpBuffer.Protect == PAGE_NOACCESS ) || ( lpBuffer.Protect == PAGE_EXECUTE )));
1779}
1780
1781kmp_uint64
1782__kmp_hardware_timestamp(void)
1783{
1784 kmp_uint64 r = 0;
1785
1786 QueryPerformanceCounter((LARGE_INTEGER*) &r);
1787 return r;
1788}
1789
1790/* Free handle and check the error code */
1791void
1792__kmp_free_handle( kmp_thread_t tHandle )
1793{
1794/* called with parameter type HANDLE also, thus suppose kmp_thread_t defined as HANDLE */
1795 BOOL rc;
1796 rc = CloseHandle( tHandle );
1797 if ( !rc ) {
1798 DWORD error = GetLastError();
1799 __kmp_msg(
1800 kmp_ms_fatal,
1801 KMP_MSG( CantCloseHandle ),
1802 KMP_ERR( error ),
1803 __kmp_msg_null
1804 );
1805 }
1806}
1807
1808int
1809__kmp_get_load_balance( int max ) {
1810
1811 static ULONG glb_buff_size = 100 * 1024;
1812
1813 static int glb_running_threads = 0; /* Saved count of the running threads for the thread balance algortihm */
1814 static double glb_call_time = 0; /* Thread balance algorithm call time */
1815
1816 int running_threads = 0; // Number of running threads in the system.
1817 NTSTATUS status = 0;
1818 ULONG buff_size = 0;
1819 ULONG info_size = 0;
1820 void * buffer = NULL;
1821 PSYSTEM_PROCESS_INFORMATION spi = NULL;
1822 int first_time = 1;
1823
1824 double call_time = 0.0; //start, finish;
1825
1826 __kmp_elapsed( & call_time );
1827
1828 if ( glb_call_time &&
1829 ( call_time - glb_call_time < __kmp_load_balance_interval ) ) {
1830 running_threads = glb_running_threads;
1831 goto finish;
1832 }
1833 glb_call_time = call_time;
1834
1835 // Do not spend time on running algorithm if we have a permanent error.
1836 if ( NtQuerySystemInformation == NULL ) {
1837 running_threads = -1;
1838 goto finish;
1839 }; // if
1840
1841 if ( max <= 0 ) {
1842 max = INT_MAX;
1843 }; // if
1844
1845 do {
1846
1847 if ( first_time ) {
1848 buff_size = glb_buff_size;
1849 } else {
1850 buff_size = 2 * buff_size;
1851 }
1852
1853 buffer = KMP_INTERNAL_REALLOC( buffer, buff_size );
1854 if ( buffer == NULL ) {
1855 running_threads = -1;
1856 goto finish;
1857 }; // if
1858 status = NtQuerySystemInformation( SystemProcessInformation, buffer, buff_size, & info_size );
1859 first_time = 0;
1860
1861 } while ( status == STATUS_INFO_LENGTH_MISMATCH );
1862 glb_buff_size = buff_size;
1863
1864 #define CHECK( cond ) \
1865 { \
1866 KMP_DEBUG_ASSERT( cond ); \
1867 if ( ! ( cond ) ) { \
1868 running_threads = -1; \
1869 goto finish; \
1870 } \
1871 }
1872
1873 CHECK( buff_size >= info_size );
1874 spi = PSYSTEM_PROCESS_INFORMATION( buffer );
1875 for ( ; ; ) {
1876 ptrdiff_t offset = uintptr_t( spi ) - uintptr_t( buffer );
1877 CHECK( 0 <= offset && offset + sizeof( SYSTEM_PROCESS_INFORMATION ) < info_size );
1878 HANDLE pid = spi->ProcessId;
1879 ULONG num = spi->NumberOfThreads;
1880 CHECK( num >= 1 );
1881 size_t spi_size = sizeof( SYSTEM_PROCESS_INFORMATION ) + sizeof( SYSTEM_THREAD ) * ( num - 1 );
1882 CHECK( offset + spi_size < info_size ); // Make sure process info record fits the buffer.
1883 if ( spi->NextEntryOffset != 0 ) {
1884 CHECK( spi_size <= spi->NextEntryOffset ); // And do not overlap with the next record.
1885 }; // if
1886 // pid == 0 corresponds to the System Idle Process. It always has running threads
1887 // on all cores. So, we don't consider the running threads of this process.
1888 if ( pid != 0 ) {
1889 for ( int i = 0; i < num; ++ i ) {
1890 THREAD_STATE state = spi->Threads[ i ].State;
1891 // Count threads that have Ready or Running state.
1892 // !!! TODO: Why comment does not match the code???
1893 if ( state == StateRunning ) {
1894 ++ running_threads;
1895 // Stop counting running threads if the number is already greater than
1896 // the number of available cores
1897 if ( running_threads >= max ) {
1898 goto finish;
1899 }
1900 } // if
1901 }; // for i
1902 } // if
1903 if ( spi->NextEntryOffset == 0 ) {
1904 break;
1905 }; // if
1906 spi = PSYSTEM_PROCESS_INFORMATION( uintptr_t( spi ) + spi->NextEntryOffset );
1907 }; // forever
1908
1909 #undef CHECK
1910
1911 finish: // Clean up and exit.
1912
1913 if ( buffer != NULL ) {
1914 KMP_INTERNAL_FREE( buffer );
1915 }; // if
1916
1917 glb_running_threads = running_threads;
1918
1919 return running_threads;
1920
1921} //__kmp_get_load_balance()
1922