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