00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include "kmp.h"
00048 #include "kmp_i18n.h"
00049 #include "kmp_io.h"
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 #include <ntstatus.h>
00061 #include <ntsecapi.h>
00062
00063 enum SYSTEM_INFORMATION_CLASS {
00064 SystemProcessInformation = 5
00065 };
00066
00067 struct CLIENT_ID {
00068 HANDLE UniqueProcess;
00069 HANDLE UniqueThread;
00070 };
00071
00072 enum THREAD_STATE {
00073 StateInitialized,
00074 StateReady,
00075 StateRunning,
00076 StateStandby,
00077 StateTerminated,
00078 StateWait,
00079 StateTransition,
00080 StateUnknown
00081 };
00082
00083 struct VM_COUNTERS {
00084 SIZE_T PeakVirtualSize;
00085 SIZE_T VirtualSize;
00086 ULONG PageFaultCount;
00087 SIZE_T PeakWorkingSetSize;
00088 SIZE_T WorkingSetSize;
00089 SIZE_T QuotaPeakPagedPoolUsage;
00090 SIZE_T QuotaPagedPoolUsage;
00091 SIZE_T QuotaPeakNonPagedPoolUsage;
00092 SIZE_T QuotaNonPagedPoolUsage;
00093 SIZE_T PagefileUsage;
00094 SIZE_T PeakPagefileUsage;
00095 SIZE_T PrivatePageCount;
00096 };
00097
00098 struct SYSTEM_THREAD {
00099 LARGE_INTEGER KernelTime;
00100 LARGE_INTEGER UserTime;
00101 LARGE_INTEGER CreateTime;
00102 ULONG WaitTime;
00103 LPVOID StartAddress;
00104 CLIENT_ID ClientId;
00105 DWORD Priority;
00106 LONG BasePriority;
00107 ULONG ContextSwitchCount;
00108 THREAD_STATE State;
00109 ULONG WaitReason;
00110 };
00111
00112 KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, KernelTime ) == 0 );
00113 #if KMP_ARCH_X86
00114 KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, StartAddress ) == 28 );
00115 KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, State ) == 52 );
00116 #else
00117 KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, StartAddress ) == 32 );
00118 KMP_BUILD_ASSERT( offsetof( SYSTEM_THREAD, State ) == 68 );
00119 #endif
00120
00121 struct SYSTEM_PROCESS_INFORMATION {
00122 ULONG NextEntryOffset;
00123 ULONG NumberOfThreads;
00124 LARGE_INTEGER Reserved[ 3 ];
00125 LARGE_INTEGER CreateTime;
00126 LARGE_INTEGER UserTime;
00127 LARGE_INTEGER KernelTime;
00128 UNICODE_STRING ImageName;
00129 DWORD BasePriority;
00130 HANDLE ProcessId;
00131 HANDLE ParentProcessId;
00132 ULONG HandleCount;
00133 ULONG Reserved2[ 2 ];
00134 VM_COUNTERS VMCounters;
00135 IO_COUNTERS IOCounters;
00136 SYSTEM_THREAD Threads[ 1 ];
00137 };
00138 typedef SYSTEM_PROCESS_INFORMATION * PSYSTEM_PROCESS_INFORMATION;
00139
00140 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, NextEntryOffset ) == 0 );
00141 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, CreateTime ) == 32 );
00142 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, ImageName ) == 56 );
00143 #if KMP_ARCH_X86
00144 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, ProcessId ) == 68 );
00145 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, HandleCount ) == 76 );
00146 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, VMCounters ) == 88 );
00147 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, IOCounters ) == 136 );
00148 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, Threads ) == 184 );
00149 #else
00150 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, ProcessId ) == 80 );
00151 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, HandleCount ) == 96 );
00152 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, VMCounters ) == 112 );
00153 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, IOCounters ) == 208 );
00154 KMP_BUILD_ASSERT( offsetof( SYSTEM_PROCESS_INFORMATION, Threads ) == 256 );
00155 #endif
00156
00157 typedef NTSTATUS (NTAPI *NtQuerySystemInformation_t)( SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG );
00158 NtQuerySystemInformation_t NtQuerySystemInformation = NULL;
00159
00160 HMODULE ntdll = NULL;
00161
00162
00163
00164 #if KMP_ARCH_X86_64
00165 static HMODULE kernel32 = NULL;
00166 #endif
00167
00168
00169
00170
00171
00172
00173 #ifdef KMP_DEBUG
00174
00175 static void
00176 __kmp_static_delay( int arg ) {
00177
00178 #if KMP_ARCH_X86_64 && KMP_OS_LINUX
00179 KMP_ASSERT( arg != 0 );
00180 #else
00181 KMP_ASSERT( arg >= 0 );
00182 #endif
00183 }
00184
00185 #else
00186
00187 #define __kmp_static_delay( arg )
00188
00189 #endif
00190
00191 static void
00192 __kmp_static_yield( int arg )
00193 {
00194 __kmp_yield( arg );
00195 }
00196
00197 #if KMP_HANDLE_SIGNALS
00198 typedef void (* sig_func_t )( int );
00199 static sig_func_t __kmp_sighldrs[ NSIG ];
00200 static int __kmp_siginstalled[ NSIG ];
00201 #endif
00202
00203 static HANDLE __kmp_monitor_ev;
00204 static kmp_int64 __kmp_win32_time;
00205 double __kmp_win32_tick;
00206
00207 int __kmp_init_runtime = FALSE;
00208 CRITICAL_SECTION __kmp_win32_section;
00209
00210 void
00211 __kmp_win32_mutex_init( kmp_win32_mutex_t *mx )
00212 {
00213 InitializeCriticalSection( & mx->cs );
00214 }
00215
00216 void
00217 __kmp_win32_mutex_destroy( kmp_win32_mutex_t *mx )
00218 {
00219 DeleteCriticalSection( & mx->cs );
00220 }
00221
00222 void
00223 __kmp_win32_mutex_lock( kmp_win32_mutex_t *mx )
00224 {
00225 EnterCriticalSection( & mx->cs );
00226 }
00227
00228 void
00229 __kmp_win32_mutex_unlock( kmp_win32_mutex_t *mx )
00230 {
00231 LeaveCriticalSection( & mx->cs );
00232 }
00233
00234 void
00235 __kmp_win32_cond_init( kmp_win32_cond_t *cv )
00236 {
00237 cv->waiters_count_ = 0;
00238 cv->wait_generation_count_ = 0;
00239 cv->release_count_ = 0;
00240
00241
00242 __kmp_win32_mutex_init( & cv->waiters_count_lock_ );
00243
00244
00245 cv->event_ = CreateEvent( NULL,
00246 TRUE,
00247 FALSE,
00248 NULL );
00249 }
00250
00251 void
00252 __kmp_win32_cond_destroy( kmp_win32_cond_t *cv )
00253 {
00254 __kmp_win32_mutex_destroy( & cv->waiters_count_lock_ );
00255 __kmp_free_handle( cv->event_ );
00256 memset( cv, '\0', sizeof( *cv ) );
00257 }
00258
00259
00260
00261
00262 void
00263 __kmp_win32_cond_wait( kmp_win32_cond_t *cv, kmp_win32_mutex_t *mx, kmp_info_t *th, int need_decrease_load )
00264 {
00265 int my_generation;
00266 int last_waiter;
00267
00268
00269 __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
00270
00271
00272 cv->waiters_count_++;
00273
00274
00275 my_generation = cv->wait_generation_count_;
00276
00277 __kmp_win32_mutex_unlock( &cv->waiters_count_lock_ );
00278 __kmp_win32_mutex_unlock( mx );
00279
00280
00281 for (;;) {
00282 int wait_done;
00283
00284
00285 WaitForSingleObject( cv->event_, INFINITE );
00286
00287 __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
00288
00289
00290
00291
00292 wait_done = ( cv->release_count_ > 0 ) &&
00293 ( cv->wait_generation_count_ != my_generation );
00294
00295 __kmp_win32_mutex_unlock( &cv->waiters_count_lock_);
00296
00297
00298
00299 if( wait_done )
00300 break;
00301 }
00302
00303 __kmp_win32_mutex_lock( mx );
00304 __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
00305
00306 cv->waiters_count_--;
00307 cv->release_count_--;
00308
00309 last_waiter = ( cv->release_count_ == 0 );
00310
00311 __kmp_win32_mutex_unlock( &cv->waiters_count_lock_ );
00312
00313 if( last_waiter ) {
00314
00315 ResetEvent( cv->event_ );
00316 }
00317 }
00318
00319 void
00320 __kmp_win32_cond_broadcast( kmp_win32_cond_t *cv )
00321 {
00322 __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
00323
00324 if( cv->waiters_count_ > 0 ) {
00325 SetEvent( cv->event_ );
00326
00327
00328 cv->release_count_ = cv->waiters_count_;
00329
00330
00331 cv->wait_generation_count_++;
00332 }
00333
00334 __kmp_win32_mutex_unlock( &cv->waiters_count_lock_ );
00335 }
00336
00337 void
00338 __kmp_win32_cond_signal( kmp_win32_cond_t *cv )
00339 {
00340 __kmp_win32_cond_broadcast( cv );
00341 }
00342
00343
00344
00345
00346 void
00347 __kmp_enable( int new_state )
00348 {
00349 if (__kmp_init_runtime)
00350 LeaveCriticalSection( & __kmp_win32_section );
00351 }
00352
00353 void
00354 __kmp_disable( int *old_state )
00355 {
00356 *old_state = 0;
00357
00358 if (__kmp_init_runtime)
00359 EnterCriticalSection( & __kmp_win32_section );
00360 }
00361
00362 void
00363 __kmp_suspend_initialize( void )
00364 {
00365
00366 }
00367
00368 static void
00369 __kmp_suspend_initialize_thread( kmp_info_t *th )
00370 {
00371 if ( ! TCR_4( th->th.th_suspend_init ) ) {
00372
00373
00374 __kmp_win32_cond_init( &th->th.th_suspend_cv );
00375 __kmp_win32_mutex_init( &th->th.th_suspend_mx );
00376 TCW_4( th->th.th_suspend_init, TRUE );
00377 }
00378 }
00379
00380 void
00381 __kmp_suspend_uninitialize_thread( kmp_info_t *th )
00382 {
00383 if ( TCR_4( th->th.th_suspend_init ) ) {
00384
00385
00386 __kmp_win32_cond_destroy( & th->th.th_suspend_cv );
00387 __kmp_win32_mutex_destroy( & th->th.th_suspend_mx );
00388 TCW_4( th->th.th_suspend_init, FALSE );
00389 }
00390 }
00391
00392
00393
00394
00395
00396
00397 void
00398 __kmp_suspend( int th_gtid, volatile kmp_uint *spinner, kmp_uint checker )
00399 {
00400 kmp_info_t *th = __kmp_threads[th_gtid];
00401 int status;
00402 kmp_uint old_spin;
00403
00404 KF_TRACE( 30, ("__kmp_suspend: T#%d enter for spin = %p\n", th_gtid, spinner ) );
00405
00406 __kmp_suspend_initialize_thread( th );
00407
00408 __kmp_win32_mutex_lock( &th->th.th_suspend_mx );
00409
00410 KF_TRACE( 10, ( "__kmp_suspend: T#%d setting sleep bit for spin(%p)\n",
00411 th_gtid, spinner ) );
00412
00413
00414
00415
00416 old_spin = __kmp_test_then_or32( (volatile kmp_int32 *) spinner,
00417 KMP_BARRIER_SLEEP_STATE );
00418
00419 KF_TRACE( 5, ( "__kmp_suspend: T#%d set sleep bit for spin(%p)==%d\n",
00420 th_gtid, spinner, *spinner ) );
00421
00422 if ( old_spin == checker ) {
00423 __kmp_test_then_and32( (volatile kmp_int32 *) spinner, ~(KMP_BARRIER_SLEEP_STATE) );
00424
00425 KF_TRACE( 5, ( "__kmp_suspend: T#%d false alarm, reset sleep bit for spin(%p)\n",
00426 th_gtid, spinner) );
00427 } else {
00428 #ifdef DEBUG_SUSPEND
00429 __kmp_suspend_count++;
00430 #endif
00431
00432
00433
00434
00435
00436 int deactivated = FALSE;
00437 TCW_PTR(th->th.th_sleep_loc, spinner);
00438 while ( TCR_4( *spinner ) & KMP_BARRIER_SLEEP_STATE ) {
00439
00440 KF_TRACE( 15, ("__kmp_suspend: T#%d about to perform kmp_win32_cond_wait()\n",
00441 th_gtid ) );
00442
00443
00444
00445
00446
00447
00448 if ( ! deactivated ) {
00449 th->th.th_active = FALSE;
00450 if ( th->th.th_active_in_pool ) {
00451 th->th.th_active_in_pool = FALSE;
00452 KMP_TEST_THEN_DEC32(
00453 (kmp_int32 *) &__kmp_thread_pool_active_nth );
00454 KMP_DEBUG_ASSERT( TCR_4(__kmp_thread_pool_active_nth) >= 0 );
00455 }
00456 deactivated = TRUE;
00457
00458
00459 __kmp_win32_cond_wait( &th->th.th_suspend_cv, &th->th.th_suspend_mx, 0, 0 );
00460 }
00461 else {
00462 __kmp_win32_cond_wait( &th->th.th_suspend_cv, &th->th.th_suspend_mx, 0, 0 );
00463 }
00464
00465 #ifdef KMP_DEBUG
00466 if( (*spinner) & KMP_BARRIER_SLEEP_STATE ) {
00467 KF_TRACE( 100, ("__kmp_suspend: T#%d spurious wakeup\n", th_gtid ));
00468 }
00469 #endif
00470
00471 }
00472
00473
00474
00475
00476
00477 if ( deactivated ) {
00478 th->th.th_active = TRUE;
00479 if ( TCR_4(th->th.th_in_pool) ) {
00480 KMP_TEST_THEN_INC32(
00481 (kmp_int32 *) &__kmp_thread_pool_active_nth );
00482 th->th.th_active_in_pool = TRUE;
00483 }
00484 }
00485 }
00486
00487
00488 __kmp_win32_mutex_unlock( &th->th.th_suspend_mx );
00489
00490 KF_TRACE( 30, ("__kmp_suspend: T#%d exit\n", th_gtid ) );
00491 }
00492
00493
00494
00495
00496 void
00497 __kmp_resume( int target_gtid, volatile kmp_uint *spin )
00498 {
00499 kmp_info_t *th = __kmp_threads[target_gtid];
00500 int status;
00501 kmp_uint32 old_spin;
00502
00503 #ifdef KMP_DEBUG
00504 int gtid = TCR_4(__kmp_init_gtid) ? __kmp_get_gtid() : -1;
00505 #endif
00506
00507 KF_TRACE( 30, ( "__kmp_resume: T#%d wants to wakeup T#%d enter\n",
00508 gtid, target_gtid ) );
00509
00510 __kmp_suspend_initialize_thread( th );
00511
00512 __kmp_win32_mutex_lock( &th->th.th_suspend_mx );
00513
00514 if ( spin == NULL ) {
00515 spin = (volatile kmp_uint *)TCR_PTR(th->th.th_sleep_loc);
00516 if ( spin == NULL ) {
00517 KF_TRACE( 5, ( "__kmp_resume: T#%d exiting, thread T#%d already awake - spin(%p)\n",
00518 gtid, target_gtid, spin ) );
00519
00520 __kmp_win32_mutex_unlock( &th->th.th_suspend_mx );
00521 return;
00522 }
00523 }
00524
00525 TCW_PTR(th->th.th_sleep_loc, NULL);
00526 old_spin = __kmp_test_then_and32( (kmp_int32 volatile *) spin, ~( KMP_BARRIER_SLEEP_STATE ) );
00527
00528 if ( ( old_spin & KMP_BARRIER_SLEEP_STATE ) == 0 ) {
00529 KF_TRACE( 5, ( "__kmp_resume: T#%d exiting, thread T#%d already awake - spin(%p): "
00530 "%u => %u\n",
00531 gtid, target_gtid, spin, old_spin, *spin ) );
00532
00533 __kmp_win32_mutex_unlock( &th->th.th_suspend_mx );
00534 return;
00535 }
00536 TCW_PTR(th->th.th_sleep_loc, NULL);
00537
00538 KF_TRACE( 5, ( "__kmp_resume: T#%d about to wakeup T#%d, reset sleep bit for spin(%p)\n",
00539 gtid, target_gtid, spin) );
00540
00541
00542 __kmp_win32_cond_signal( &th->th.th_suspend_cv );
00543
00544 __kmp_win32_mutex_unlock( &th->th.th_suspend_mx );
00545
00546 KF_TRACE( 30, ( "__kmp_resume: T#%d exiting after signaling wake up for T#%d\n",
00547 gtid, target_gtid ) );
00548 }
00549
00550
00551
00552
00553 void
00554 __kmp_yield( int cond )
00555 {
00556 if (cond)
00557 Sleep(0);
00558 }
00559
00560
00561
00562
00563 void
00564 __kmp_gtid_set_specific( int gtid )
00565 {
00566 KA_TRACE( 50, ("__kmp_gtid_set_specific: T#%d key:%d\n",
00567 gtid, __kmp_gtid_threadprivate_key ));
00568 KMP_ASSERT( __kmp_init_runtime );
00569 if( ! TlsSetValue( __kmp_gtid_threadprivate_key, (LPVOID)(gtid+1)) )
00570 KMP_FATAL( TLSSetValueFailed );
00571 }
00572
00573 int
00574 __kmp_gtid_get_specific()
00575 {
00576 int gtid;
00577 if( !__kmp_init_runtime ) {
00578 KA_TRACE( 50, ("__kmp_get_specific: runtime shutdown, returning KMP_GTID_SHUTDOWN\n" ) );
00579 return KMP_GTID_SHUTDOWN;
00580 }
00581 gtid = (int)(kmp_intptr_t)TlsGetValue( __kmp_gtid_threadprivate_key );
00582 if ( gtid == 0 ) {
00583 gtid = KMP_GTID_DNE;
00584 }
00585 else {
00586 gtid--;
00587 }
00588 KA_TRACE( 50, ("__kmp_gtid_get_specific: key:%d gtid:%d\n",
00589 __kmp_gtid_threadprivate_key, gtid ));
00590 return gtid;
00591 }
00592
00593
00594
00595
00596 #if KMP_ARCH_X86_64
00597
00598
00599
00600
00601
00602 int
00603 __kmp_get_proc_group( kmp_affin_mask_t const *mask )
00604 {
00605 int i;
00606 int group = -1;
00607 struct GROUP_AFFINITY new_ga, prev_ga;
00608 for (i = 0; i < __kmp_num_proc_groups; i++) {
00609 if (mask[i] == 0) {
00610 continue;
00611 }
00612 if (group >= 0) {
00613 return -1;
00614 }
00615 group = i;
00616 }
00617 return group;
00618 }
00619
00620 #endif
00621
00622 int
00623 __kmp_set_system_affinity( kmp_affin_mask_t const *mask, int abort_on_error )
00624 {
00625
00626 #if KMP_ARCH_X86_64
00627
00628 if (__kmp_num_proc_groups > 1) {
00629
00630
00631
00632 struct GROUP_AFFINITY ga;
00633 int group = __kmp_get_proc_group( mask );
00634 if (group < 0) {
00635 if (abort_on_error) {
00636 KMP_FATAL(AffinityInvalidMask, "kmp_set_affinity");
00637 }
00638 return -1;
00639 }
00640
00641
00642
00643
00644
00645 ga.group = group;
00646 ga.mask = mask[group];
00647 ga.reserved[0] = ga.reserved[1] = ga.reserved[2] = 0;
00648
00649 KMP_DEBUG_ASSERT(__kmp_SetThreadGroupAffinity != NULL);
00650 if (__kmp_SetThreadGroupAffinity(GetCurrentThread(), &ga, NULL) == 0) {
00651 DWORD error = GetLastError();
00652 if (abort_on_error) {
00653 __kmp_msg(
00654 kmp_ms_fatal,
00655 KMP_MSG( CantSetThreadAffMask ),
00656 KMP_ERR( error ),
00657 __kmp_msg_null
00658 );
00659 }
00660 return error;
00661 }
00662 }
00663 else
00664
00665 #endif
00666
00667 {
00668 if (!SetThreadAffinityMask( GetCurrentThread(), *mask )) {
00669 DWORD error = GetLastError();
00670 if (abort_on_error) {
00671 __kmp_msg(
00672 kmp_ms_fatal,
00673 KMP_MSG( CantSetThreadAffMask ),
00674 KMP_ERR( error ),
00675 __kmp_msg_null
00676 );
00677 }
00678 return error;
00679 }
00680 }
00681 return 0;
00682 }
00683
00684 int
00685 __kmp_get_system_affinity( kmp_affin_mask_t *mask, int abort_on_error )
00686 {
00687
00688 #if KMP_ARCH_X86_64
00689
00690 if (__kmp_num_proc_groups > 1) {
00691 KMP_CPU_ZERO(mask);
00692 struct GROUP_AFFINITY ga;
00693 KMP_DEBUG_ASSERT(__kmp_GetThreadGroupAffinity != NULL);
00694
00695 if (__kmp_GetThreadGroupAffinity(GetCurrentThread(), &ga) == 0) {
00696 DWORD error = GetLastError();
00697 if (abort_on_error) {
00698 __kmp_msg(
00699 kmp_ms_fatal,
00700 KMP_MSG(FunctionError, "GetThreadGroupAffinity()"),
00701 KMP_ERR(error),
00702 __kmp_msg_null
00703 );
00704 }
00705 return error;
00706 }
00707
00708 if ((ga.group < 0) || (ga.group > __kmp_num_proc_groups)
00709 || (ga.mask == 0)) {
00710 return -1;
00711 }
00712
00713 mask[ga.group] = ga.mask;
00714 }
00715 else
00716
00717 #endif
00718
00719 {
00720 kmp_affin_mask_t newMask, sysMask, retval;
00721
00722 if (!GetProcessAffinityMask(GetCurrentProcess(), &newMask, &sysMask)) {
00723 DWORD error = GetLastError();
00724 if (abort_on_error) {
00725 __kmp_msg(
00726 kmp_ms_fatal,
00727 KMP_MSG(FunctionError, "GetProcessAffinityMask()"),
00728 KMP_ERR(error),
00729 __kmp_msg_null
00730 );
00731 }
00732 return error;
00733 }
00734 retval = SetThreadAffinityMask(GetCurrentThread(), newMask);
00735 if (! retval) {
00736 DWORD error = GetLastError();
00737 if (abort_on_error) {
00738 __kmp_msg(
00739 kmp_ms_fatal,
00740 KMP_MSG(FunctionError, "SetThreadAffinityMask()"),
00741 KMP_ERR(error),
00742 __kmp_msg_null
00743 );
00744 }
00745 return error;
00746 }
00747 newMask = SetThreadAffinityMask(GetCurrentThread(), retval);
00748 if (! newMask) {
00749 DWORD error = GetLastError();
00750 if (abort_on_error) {
00751 __kmp_msg(
00752 kmp_ms_fatal,
00753 KMP_MSG(FunctionError, "SetThreadAffinityMask()"),
00754 KMP_ERR(error),
00755 __kmp_msg_null
00756 );
00757 }
00758 }
00759 *mask = retval;
00760 }
00761 return 0;
00762 }
00763
00764 void
00765 __kmp_affinity_bind_thread( int proc )
00766 {
00767
00768 #if KMP_ARCH_X86_64
00769
00770 if (__kmp_num_proc_groups > 1) {
00771
00772
00773
00774
00775 struct GROUP_AFFINITY ga;
00776 KMP_DEBUG_ASSERT((proc >= 0) && (proc < (__kmp_num_proc_groups
00777 * CHAR_BIT * sizeof(DWORD_PTR))));
00778 ga.group = proc / (CHAR_BIT * sizeof(DWORD_PTR));
00779 ga.mask = 1 << (proc % (CHAR_BIT * sizeof(DWORD_PTR)));
00780 ga.reserved[0] = ga.reserved[1] = ga.reserved[2] = 0;
00781
00782 KMP_DEBUG_ASSERT(__kmp_SetThreadGroupAffinity != NULL);
00783 if (__kmp_SetThreadGroupAffinity(GetCurrentThread(), &ga, NULL) == 0) {
00784 DWORD error = GetLastError();
00785 if (__kmp_affinity_verbose) {
00786 __kmp_msg(
00787 kmp_ms_warning,
00788 KMP_MSG( CantSetThreadAffMask ),
00789 KMP_ERR( error ),
00790 __kmp_msg_null
00791 );
00792 }
00793 }
00794 }
00795 else
00796
00797 #endif
00798
00799 {
00800 kmp_affin_mask_t mask;
00801 KMP_CPU_ZERO(&mask);
00802 KMP_CPU_SET(proc, &mask);
00803 __kmp_set_system_affinity(&mask, TRUE);
00804 }
00805 }
00806
00807 void
00808 __kmp_affinity_determine_capable( const char *env_var )
00809 {
00810
00811
00812
00813
00814 #if KMP_ARCH_X86_64
00815 __kmp_affin_mask_size = __kmp_num_proc_groups * sizeof(kmp_affin_mask_t);
00816 #else
00817 __kmp_affin_mask_size = sizeof(kmp_affin_mask_t);
00818 #endif
00819
00820 KA_TRACE( 10, (
00821 "__kmp_affinity_determine_capable: "
00822 "Windows* OS affinity interface functional (mask size = %" KMP_SIZE_T_SPEC ").\n",
00823 __kmp_affin_mask_size
00824 ) );
00825 }
00826
00827 double
00828 __kmp_read_cpu_time( void )
00829 {
00830 FILETIME CreationTime, ExitTime, KernelTime, UserTime;
00831 int status;
00832 double cpu_time;
00833
00834 cpu_time = 0;
00835
00836 status = GetProcessTimes( GetCurrentProcess(), &CreationTime,
00837 &ExitTime, &KernelTime, &UserTime );
00838
00839 if (status) {
00840 double sec = 0;
00841
00842 sec += KernelTime.dwHighDateTime;
00843 sec += UserTime.dwHighDateTime;
00844
00845
00846 sec *= (double) (1 << 16) * (double) (1 << 16);
00847
00848 sec += KernelTime.dwLowDateTime;
00849 sec += UserTime.dwLowDateTime;
00850
00851 cpu_time += (sec * 100.0) / NSEC_PER_SEC;
00852 }
00853
00854 return cpu_time;
00855 }
00856
00857 int
00858 __kmp_read_system_info( struct kmp_sys_info *info )
00859 {
00860 info->maxrss = 0;
00861 info->minflt = 0;
00862 info->majflt = 0;
00863 info->nswap = 0;
00864 info->inblock = 0;
00865 info->oublock = 0;
00866 info->nvcsw = 0;
00867 info->nivcsw = 0;
00868
00869 return 1;
00870 }
00871
00872
00873
00874
00875
00876 void
00877 __kmp_runtime_initialize( void )
00878 {
00879 SYSTEM_INFO info;
00880 kmp_str_buf_t path;
00881 UINT path_size;
00882
00883 if ( __kmp_init_runtime ) {
00884 return;
00885 };
00886
00887 InitializeCriticalSection( & __kmp_win32_section );
00888 __kmp_initialize_system_tick();
00889
00890 #if (KMP_ARCH_X86 || KMP_ARCH_X86_64)
00891 if ( ! __kmp_cpuinfo.initialized ) {
00892 __kmp_query_cpuid( & __kmp_cpuinfo );
00893 };
00894 #endif
00895
00896 if ( __kmp_cpu_frequency == 0 ) {
00897
00898
00899
00900
00901 LARGE_INTEGER freq;
00902 BOOL rc;
00903 rc = QueryPerformanceFrequency( & freq );
00904 if ( rc ) {
00905 KMP_DEBUG_ASSERT( sizeof( __kmp_cpu_frequency ) >= sizeof( freq.QuadPart ) );
00906 KMP_DEBUG_ASSERT( freq.QuadPart >= 0 );
00907 __kmp_cpu_frequency = freq.QuadPart;
00908 KA_TRACE( 5, ( "cpu frequency: %" KMP_UINT64_SPEC "\n", __kmp_cpu_frequency ) );
00909 } else {
00910 __kmp_cpu_frequency = ~ 0;
00911 };
00912 };
00913
00914
00915 #if KMP_OS_WINDOWS && ! defined GUIDEDLL_EXPORTS
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930 __kmp_tls_gtid_min = 0;
00931 #else
00932 __kmp_tls_gtid_min = KMP_TLS_GTID_MIN;
00933 #endif
00934
00935
00936 if ( !__kmp_gtid_threadprivate_key ) {
00937 __kmp_gtid_threadprivate_key = TlsAlloc();
00938 if( __kmp_gtid_threadprivate_key == TLS_OUT_OF_INDEXES ) {
00939 KMP_FATAL( TLSOutOfIndexes );
00940 }
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 __kmp_str_buf_init( & path );
00955 path_size = GetSystemDirectory( path.str, path.size );
00956 KMP_DEBUG_ASSERT( path_size > 0 );
00957 if ( path_size >= path.size ) {
00958
00959
00960
00961 __kmp_str_buf_reserve( & path, path_size );
00962 path_size = GetSystemDirectory( path.str, path.size );
00963 KMP_DEBUG_ASSERT( path_size > 0 );
00964 };
00965 if ( path_size > 0 && path_size < path.size ) {
00966
00967
00968
00969
00970 path.used = path_size;
00971 __kmp_str_buf_print( & path, "\\%s", "ntdll.dll" );
00972
00973
00974
00975
00976 ntdll = GetModuleHandle( path.str );
00977 }
00978
00979 KMP_DEBUG_ASSERT( ntdll != NULL );
00980 if ( ntdll != NULL ) {
00981 NtQuerySystemInformation = (NtQuerySystemInformation_t) GetProcAddress( ntdll, "NtQuerySystemInformation" );
00982 }
00983 KMP_DEBUG_ASSERT( NtQuerySystemInformation != NULL );
00984
00985 #if KMP_ARCH_X86_64
00986
00987
00988
00989
00990 if ( path_size > 0 && path_size < path.size ) {
00991
00992
00993
00994
00995 path.used = path_size;
00996 __kmp_str_buf_print( & path, "\\%s", "kernel32.dll" );
00997
00998
00999
01000
01001 kernel32 = GetModuleHandle( path.str );
01002
01003
01004
01005
01006
01007 if ( kernel32 != NULL ) {
01008 __kmp_GetActiveProcessorCount = (kmp_GetActiveProcessorCount_t) GetProcAddress( kernel32, "GetActiveProcessorCount" );
01009 __kmp_GetActiveProcessorGroupCount = (kmp_GetActiveProcessorGroupCount_t) GetProcAddress( kernel32, "GetActiveProcessorGroupCount" );
01010 __kmp_GetThreadGroupAffinity = (kmp_GetThreadGroupAffinity_t) GetProcAddress( kernel32, "GetThreadGroupAffinity" );
01011 __kmp_SetThreadGroupAffinity = (kmp_SetThreadGroupAffinity_t) GetProcAddress( kernel32, "SetThreadGroupAffinity" );
01012
01013
01014
01015
01016
01017
01018
01019
01020 if ( ( __kmp_GetActiveProcessorCount != NULL )
01021 && ( __kmp_GetActiveProcessorGroupCount != NULL )
01022 && ( __kmp_GetThreadGroupAffinity != NULL )
01023 && ( __kmp_SetThreadGroupAffinity != NULL )
01024 && ( ( __kmp_num_proc_groups
01025 = __kmp_GetActiveProcessorGroupCount() ) > 1 ) ) {
01026
01027
01028
01029 int i;
01030
01031 KA_TRACE( 10, ("__kmp_runtime_initialize: %d processor groups detected\n", __kmp_num_proc_groups ) );
01032
01033 __kmp_xproc = 0;
01034
01035 for ( i = 0; i < __kmp_num_proc_groups; i++ ) {
01036 DWORD size = __kmp_GetActiveProcessorCount( i );
01037 __kmp_xproc += size;
01038 KA_TRACE( 20, ("__kmp_runtime_initialize: proc group %d size = %d\n", i, size ) );
01039 }
01040 }
01041 }
01042 }
01043 if ( __kmp_num_proc_groups <= 1 ) {
01044 GetSystemInfo( & info );
01045 __kmp_xproc = info.dwNumberOfProcessors;
01046 }
01047 #else
01048 GetSystemInfo( & info );
01049 __kmp_xproc = info.dwNumberOfProcessors;
01050 #endif // KMP_ARCH_X86_64
01051
01052
01053
01054
01055
01056 if ( __kmp_xproc <= 0 ) {
01057 __kmp_xproc = 2;
01058 }
01059
01060 KA_TRACE( 5, ("__kmp_runtime_initialize: total processors = %d\n", __kmp_xproc) );
01061
01062 __kmp_str_buf_free( & path );
01063
01064
01065 __kmp_init_runtime = TRUE;
01066 }
01067
01068 void
01069 __kmp_runtime_destroy( void )
01070 {
01071 if ( ! __kmp_init_runtime ) {
01072 return;
01073 }
01074
01075
01076
01077
01078 KA_TRACE( 40, ("__kmp_runtime_destroy\n" ));
01079
01080 if( __kmp_gtid_threadprivate_key ) {
01081 TlsFree( __kmp_gtid_threadprivate_key );
01082 __kmp_gtid_threadprivate_key = 0;
01083 }
01084
01085 __kmp_affinity_uninitialize();
01086 DeleteCriticalSection( & __kmp_win32_section );
01087
01088 ntdll = NULL;
01089 NtQuerySystemInformation = NULL;
01090
01091 #if KMP_ARCH_X86_64
01092 kernel32 = NULL;
01093 __kmp_GetActiveProcessorCount = NULL;
01094 __kmp_GetActiveProcessorGroupCount = NULL;
01095 __kmp_GetThreadGroupAffinity = NULL;
01096 __kmp_SetThreadGroupAffinity = NULL;
01097 #endif // KMP_ARCH_X86_64
01098
01099 __kmp_init_runtime = FALSE;
01100 }
01101
01102
01103 void
01104 __kmp_terminate_thread( int gtid )
01105 {
01106 kmp_info_t *th = __kmp_threads[ gtid ];
01107
01108 if( !th ) return;
01109
01110 KA_TRACE( 10, ("__kmp_terminate_thread: kill (%d)\n", gtid ) );
01111
01112 if (TerminateThread( th->th.th_info.ds.ds_thread, (DWORD) -1) == FALSE) {
01113
01114 }
01115 __kmp_free_handle( th->th.th_info.ds.ds_thread );
01116 }
01117
01118
01119
01120
01121 void
01122 __kmp_clear_system_time( void )
01123 {
01124 BOOL status;
01125 LARGE_INTEGER time;
01126 status = QueryPerformanceCounter( & time );
01127 __kmp_win32_time = (kmp_int64) time.QuadPart;
01128 }
01129
01130 void
01131 __kmp_initialize_system_tick( void )
01132 {
01133 {
01134 BOOL status;
01135 LARGE_INTEGER freq;
01136
01137 status = QueryPerformanceFrequency( & freq );
01138 if (! status) {
01139 DWORD error = GetLastError();
01140 __kmp_msg(
01141 kmp_ms_fatal,
01142 KMP_MSG( FunctionError, "QueryPerformanceFrequency()" ),
01143 KMP_ERR( error ),
01144 __kmp_msg_null
01145 );
01146
01147 }
01148 else {
01149 __kmp_win32_tick = ((double) 1.0) / (double) freq.QuadPart;
01150 }
01151 }
01152 }
01153
01154
01155
01156 void
01157 __kmp_elapsed( double *t )
01158 {
01159 BOOL status;
01160 LARGE_INTEGER now;
01161 status = QueryPerformanceCounter( & now );
01162 *t = ((double) now.QuadPart) * __kmp_win32_tick;
01163 }
01164
01165
01166
01167 void
01168 __kmp_elapsed_tick( double *t )
01169 {
01170 *t = __kmp_win32_tick;
01171 }
01172
01173 void
01174 __kmp_read_system_time( double *delta )
01175 {
01176
01177 if (delta != NULL) {
01178 BOOL status;
01179 LARGE_INTEGER now;
01180
01181 status = QueryPerformanceCounter( & now );
01182
01183 *delta = ((double) (((kmp_int64) now.QuadPart) - __kmp_win32_time))
01184 * __kmp_win32_tick;
01185 }
01186 }
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197 void
01198 __kmp_change_thread_affinity_mask( int gtid, kmp_affin_mask_t *new_mask,
01199 kmp_affin_mask_t *old_mask )
01200 {
01201 kmp_info_t *th = __kmp_threads[ gtid ];
01202
01203 KMP_DEBUG_ASSERT( *new_mask != 0 );
01204
01205 if ( old_mask != NULL ) {
01206 *old_mask = SetThreadAffinityMask( th -> th.th_info.ds.ds_thread, *new_mask );
01207
01208 if (! *old_mask ) {
01209 DWORD error = GetLastError();
01210 __kmp_msg(
01211 kmp_ms_fatal,
01212 KMP_MSG( CantSetThreadAffMask ),
01213 KMP_ERR( error ),
01214 __kmp_msg_null
01215 );
01216 }
01217 }
01218 if (__kmp_affinity_verbose)
01219 KMP_INFORM( ChangeAffMask, "KMP_AFFINITY (Bind)", gtid, *old_mask, *new_mask );
01220
01221
01222 KMP_DEBUG_ASSERT( old_mask != NULL && *old_mask == *(th -> th.th_affin_mask ));
01223
01224 KMP_CPU_COPY(th -> th.th_affin_mask, new_mask);
01225 }
01226
01227
01228
01229
01230
01231 void * __stdcall
01232 __kmp_launch_worker( void *arg )
01233 {
01234 volatile void *stack_data;
01235 void *exit_val;
01236 void *padding = 0;
01237 kmp_info_t *this_thr = (kmp_info_t *) arg;
01238 int gtid;
01239
01240 gtid = this_thr->th.th_info.ds.ds_gtid;
01241 __kmp_gtid_set_specific( gtid );
01242 #ifdef KMP_TDATA_GTID
01243 #error "This define causes problems with LoadLibrary() + declspec(thread) " \
01244 "on Windows* OS. See CQ50564, tests kmp_load_library*.c and this MSDN " \
01245 "reference: http://support.microsoft.com/kb/118816"
01246
01247 #endif
01248
01249
01250 __kmp_affinity_set_init_mask( gtid, FALSE );
01251
01252 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
01253
01254
01255
01256
01257 __kmp_clear_x87_fpu_status_word();
01258 __kmp_load_x87_fpu_control_word( &__kmp_init_x87_fpu_control_word );
01259 __kmp_load_mxcsr( &__kmp_init_mxcsr );
01260 #endif
01261
01262 if ( __kmp_stkoffset > 0 && gtid > 0 ) {
01263 padding = _alloca( gtid * __kmp_stkoffset );
01264 }
01265
01266 this_thr -> th.th_info.ds.ds_thread_id = GetCurrentThreadId();
01267 TCW_4( this_thr -> th.th_info.ds.ds_alive, TRUE );
01268
01269 if ( TCR_4(__kmp_gtid_mode) < 2 ) {
01270 TCW_PTR(this_thr->th.th_info.ds.ds_stackbase, &stack_data);
01271 KMP_ASSERT( this_thr -> th.th_info.ds.ds_stackgrow == FALSE );
01272 __kmp_check_stack_overlap( this_thr );
01273 }
01274 KMP_MB();
01275 exit_val = __kmp_launch_thread( this_thr );
01276 TCW_4( this_thr -> th.th_info.ds.ds_alive, FALSE );
01277 KMP_MB();
01278 return exit_val;
01279 }
01280
01281
01282
01283
01284 void * __stdcall
01285 __kmp_launch_monitor( void *arg )
01286 {
01287 DWORD wait_status;
01288 kmp_thread_t monitor;
01289 int status;
01290 int interval;
01291 kmp_info_t *this_thr = (kmp_info_t *) arg;
01292
01293 KMP_DEBUG_ASSERT(__kmp_init_monitor);
01294 TCW_4( __kmp_init_monitor, 2 );
01295
01296 this_thr -> th.th_info.ds.ds_thread_id = GetCurrentThreadId();
01297 TCW_4( this_thr -> th.th_info.ds.ds_alive, TRUE );
01298
01299 KMP_MB();
01300 KA_TRACE( 10, ("__kmp_launch_monitor: launched\n" ) );
01301
01302 monitor = GetCurrentThread();
01303
01304
01305 status = SetThreadPriority( monitor, THREAD_PRIORITY_HIGHEST );
01306 if (! status) {
01307 DWORD error = GetLastError();
01308 __kmp_msg(
01309 kmp_ms_fatal,
01310 KMP_MSG( CantSetThreadPriority ),
01311 KMP_ERR( error ),
01312 __kmp_msg_null
01313 );
01314 }
01315
01316
01317 __kmp_gtid_set_specific( KMP_GTID_MONITOR );
01318 #ifdef KMP_TDATA_GTID
01319 #error "This define causes problems with LoadLibrary() + declspec(thread) " \
01320 "on Windows* OS. See CQ50564, tests kmp_load_library*.c and this MSDN " \
01321 "reference: http://support.microsoft.com/kb/118816"
01322
01323 #endif
01324
01325
01326 KMP_MB();
01327
01328 interval = ( 1000 / __kmp_monitor_wakeups );
01329
01330 while (! TCR_4(__kmp_global.g.g_done)) {
01331
01332
01333 KA_TRACE( 15, ( "__kmp_launch_monitor: update\n" ) );
01334
01335 wait_status = WaitForSingleObject( __kmp_monitor_ev, interval );
01336
01337 if (wait_status == WAIT_TIMEOUT) {
01338 TCW_4( __kmp_global.g.g_time.dt.t_value,
01339 TCR_4( __kmp_global.g.g_time.dt.t_value ) + 1 );
01340 }
01341
01342 KMP_MB();
01343 }
01344
01345 KA_TRACE( 10, ("__kmp_launch_monitor: finished\n" ) );
01346
01347 status = SetThreadPriority( monitor, THREAD_PRIORITY_NORMAL );
01348 if (! status) {
01349 DWORD error = GetLastError();
01350 __kmp_msg(
01351 kmp_ms_fatal,
01352 KMP_MSG( CantSetThreadPriority ),
01353 KMP_ERR( error ),
01354 __kmp_msg_null
01355 );
01356 }
01357
01358 if (__kmp_global.g.g_abort != 0) {
01359
01360
01361
01362 int gtid;
01363
01364 KA_TRACE( 10, ("__kmp_launch_monitor: terminate sig=%d\n", (__kmp_global.g.g_abort) ) );
01365
01366
01367
01368
01369 for (gtid = 1; gtid < __kmp_threads_capacity; ++gtid)
01370 __kmp_terminate_thread( gtid );
01371
01372 __kmp_cleanup();
01373
01374 Sleep( 0 );
01375
01376 KA_TRACE( 10, ("__kmp_launch_monitor: raise sig=%d\n", (__kmp_global.g.g_abort) ) );
01377
01378 if (__kmp_global.g.g_abort > 0) {
01379 raise( __kmp_global.g.g_abort );
01380 }
01381 }
01382
01383 TCW_4( this_thr -> th.th_info.ds.ds_alive, FALSE );
01384
01385 KMP_MB();
01386 return arg;
01387 }
01388
01389 void
01390 __kmp_create_worker( int gtid, kmp_info_t *th, size_t stack_size )
01391 {
01392 kmp_thread_t handle;
01393 DWORD idThread;
01394
01395 KA_TRACE( 10, ("__kmp_create_worker: try to create thread (%d)\n", gtid ) );
01396
01397 th->th.th_info.ds.ds_gtid = gtid;
01398
01399 if ( KMP_UBER_GTID(gtid) ) {
01400 int stack_data;
01401
01402
01403
01404
01405
01406 {
01407 BOOL rc;
01408 rc = DuplicateHandle(
01409 GetCurrentProcess(),
01410 GetCurrentThread(),
01411 GetCurrentProcess(),
01412 &th->th.th_info.ds.ds_thread,
01413 0,
01414 FALSE,
01415 DUPLICATE_SAME_ACCESS
01416 );
01417 KMP_ASSERT( rc );
01418 KA_TRACE( 10, (" __kmp_create_worker: ROOT Handle duplicated, th = %p, handle = %" KMP_UINTPTR_SPEC "\n",
01419 (LPVOID)th,
01420 th->th.th_info.ds.ds_thread ) );
01421 th->th.th_info.ds.ds_thread_id = GetCurrentThreadId();
01422 }
01423 if ( TCR_4(__kmp_gtid_mode) < 2 ) {
01424
01425 TCW_PTR(th->th.th_info.ds.ds_stackbase, &stack_data);
01426 TCW_PTR(th->th.th_info.ds.ds_stacksize, 0);
01427 TCW_4(th->th.th_info.ds.ds_stackgrow, TRUE);
01428 __kmp_check_stack_overlap( th );
01429 }
01430 }
01431 else {
01432 KMP_MB();
01433
01434
01435 KA_TRACE( 10, ( "__kmp_create_worker: stack_size = %" KMP_SIZE_T_SPEC
01436 " bytes\n", stack_size ) );
01437
01438 stack_size += gtid * __kmp_stkoffset;
01439
01440 TCW_PTR(th->th.th_info.ds.ds_stacksize, stack_size);
01441 TCW_4(th->th.th_info.ds.ds_stackgrow, FALSE);
01442
01443 KA_TRACE( 10, ( "__kmp_create_worker: (before) stack_size = %"
01444 KMP_SIZE_T_SPEC
01445 " bytes, &__kmp_launch_worker = %p, th = %p, "
01446 "&idThread = %p\n",
01447 (SIZE_T) stack_size,
01448 (LPTHREAD_START_ROUTINE) & __kmp_launch_worker,
01449 (LPVOID) th, &idThread ) );
01450
01451 {
01452 handle = CreateThread( NULL, (SIZE_T) stack_size,
01453 (LPTHREAD_START_ROUTINE) __kmp_launch_worker,
01454 (LPVOID) th, STACK_SIZE_PARAM_IS_A_RESERVATION, &idThread );
01455 }
01456
01457 KA_TRACE( 10, ( "__kmp_create_worker: (after) stack_size = %"
01458 KMP_SIZE_T_SPEC
01459 " bytes, &__kmp_launch_worker = %p, th = %p, "
01460 "idThread = %u, handle = %" KMP_UINTPTR_SPEC "\n",
01461 (SIZE_T) stack_size,
01462 (LPTHREAD_START_ROUTINE) & __kmp_launch_worker,
01463 (LPVOID) th, idThread, handle ) );
01464
01465 {
01466 if ( handle == 0 ) {
01467 DWORD error = GetLastError();
01468 __kmp_msg(
01469 kmp_ms_fatal,
01470 KMP_MSG( CantCreateThread ),
01471 KMP_ERR( error ),
01472 __kmp_msg_null
01473 );
01474 } else {
01475 th->th.th_info.ds.ds_thread = handle;
01476 }
01477 }
01478 KMP_MB();
01479 }
01480
01481 KA_TRACE( 10, ("__kmp_create_worker: done creating thread (%d)\n", gtid ) );
01482 }
01483
01484 int
01485 __kmp_still_running(kmp_info_t *th) {
01486 return (WAIT_TIMEOUT == WaitForSingleObject( th->th.th_info.ds.ds_thread, 0));
01487 }
01488
01489 void
01490 __kmp_create_monitor( kmp_info_t *th )
01491 {
01492 kmp_thread_t handle;
01493 DWORD idThread;
01494 int ideal, new_ideal;
01495 int caller_gtid = __kmp_get_gtid();
01496
01497 KA_TRACE( 10, ("__kmp_create_monitor: try to create monitor\n" ) );
01498
01499 KMP_MB();
01500
01501 __kmp_monitor_ev = CreateEvent( NULL, TRUE, FALSE, NULL );
01502 if ( __kmp_monitor_ev == NULL ) {
01503 DWORD error = GetLastError();
01504 __kmp_msg(
01505 kmp_ms_fatal,
01506 KMP_MSG( CantCreateEvent ),
01507 KMP_ERR( error ),
01508 __kmp_msg_null
01509 );
01510 };
01511
01512 th->th.th_info.ds.ds_tid = KMP_GTID_MONITOR;
01513 th->th.th_info.ds.ds_gtid = KMP_GTID_MONITOR;
01514
01515
01516
01517 if ( __kmp_monitor_stksize == 0 ) {
01518 __kmp_monitor_stksize = KMP_DEFAULT_MONITOR_STKSIZE;
01519 }
01520 if ( __kmp_monitor_stksize < __kmp_sys_min_stksize ) {
01521 __kmp_monitor_stksize = __kmp_sys_min_stksize;
01522 }
01523
01524 KA_TRACE( 10, ("__kmp_create_monitor: requested stacksize = %d bytes\n",
01525 (int) __kmp_monitor_stksize ) );
01526
01527 TCW_4( __kmp_global.g.g_time.dt.t_value, 0 );
01528
01529 handle = CreateThread( NULL, (SIZE_T) __kmp_monitor_stksize,
01530 (LPTHREAD_START_ROUTINE) __kmp_launch_monitor,
01531 (LPVOID) th, STACK_SIZE_PARAM_IS_A_RESERVATION, &idThread );
01532 if (handle == 0) {
01533 DWORD error = GetLastError();
01534 __kmp_msg(
01535 kmp_ms_fatal,
01536 KMP_MSG( CantCreateThread ),
01537 KMP_ERR( error ),
01538 __kmp_msg_null
01539 );
01540 }
01541 else
01542 th->th.th_info.ds.ds_thread = handle;
01543
01544 KMP_MB();
01545
01546 KA_TRACE( 10, ("__kmp_create_monitor: monitor created %p\n",
01547 (void *) th->th.th_info.ds.ds_thread ) );
01548 }
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559 int
01560 __kmp_is_thread_alive( kmp_info_t * th, DWORD *exit_val )
01561 {
01562 DWORD rc;
01563 rc = GetExitCodeThread( th->th.th_info.ds.ds_thread, exit_val );
01564 if ( rc == 0 ) {
01565 DWORD error = GetLastError();
01566 __kmp_msg(
01567 kmp_ms_fatal,
01568 KMP_MSG( FunctionError, "GetExitCodeThread()" ),
01569 KMP_ERR( error ),
01570 __kmp_msg_null
01571 );
01572 };
01573 return ( *exit_val == STILL_ACTIVE );
01574 }
01575
01576
01577 void
01578 __kmp_exit_thread(
01579 int exit_status
01580 ) {
01581 ExitThread( exit_status );
01582 }
01583
01584
01585
01586
01587 static void
01588 __kmp_reap_common( kmp_info_t * th )
01589 {
01590 DWORD exit_val;
01591
01592 KMP_MB();
01593
01594 KA_TRACE( 10, ( "__kmp_reap_common: try to reap (%d)\n", th->th.th_info.ds.ds_gtid ) );
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610 {
01611
01612
01613 void * obj = NULL;
01614 register kmp_uint32 spins;
01615 KMP_INIT_YIELD( spins );
01616 do {
01617 __kmp_is_thread_alive( th, &exit_val );
01618 __kmp_static_delay( TRUE );
01619 KMP_YIELD( TCR_4(__kmp_nth) > __kmp_avail_proc );
01620 KMP_YIELD_SPIN( spins );
01621 } while ( exit_val == STILL_ACTIVE && TCR_4( th->th.th_info.ds.ds_alive ) );
01622 }
01623
01624 __kmp_free_handle( th->th.th_info.ds.ds_thread );
01625
01626
01627
01628
01629
01630
01631 if ( exit_val == STILL_ACTIVE ) {
01632 KA_TRACE( 1, ( "__kmp_reap_common: thread still active.\n" ) );
01633 } else if ( (void *) exit_val != (void *) th) {
01634 KA_TRACE( 1, ( "__kmp_reap_common: ExitProcess / TerminateThread used?\n" ) );
01635 };
01636
01637 KA_TRACE( 10,
01638 (
01639 "__kmp_reap_common: done reaping (%d), handle = %" KMP_UINTPTR_SPEC "\n",
01640 th->th.th_info.ds.ds_gtid,
01641 th->th.th_info.ds.ds_thread
01642 )
01643 );
01644
01645 th->th.th_info.ds.ds_thread = 0;
01646 th->th.th_info.ds.ds_tid = KMP_GTID_DNE;
01647 th->th.th_info.ds.ds_gtid = KMP_GTID_DNE;
01648 th->th.th_info.ds.ds_thread_id = 0;
01649
01650 KMP_MB();
01651 }
01652
01653 void
01654 __kmp_reap_monitor( kmp_info_t *th )
01655 {
01656 int status;
01657
01658 KA_TRACE( 10, ("__kmp_reap_monitor: try to reap %p\n",
01659 (void *) th->th.th_info.ds.ds_thread ) );
01660
01661
01662
01663
01664 KMP_DEBUG_ASSERT( th->th.th_info.ds.ds_tid == th->th.th_info.ds.ds_gtid );
01665 if ( th->th.th_info.ds.ds_gtid != KMP_GTID_MONITOR ) {
01666 return;
01667 };
01668
01669 KMP_MB();
01670
01671 status = SetEvent( __kmp_monitor_ev );
01672 if ( status == FALSE ) {
01673 DWORD error = GetLastError();
01674 __kmp_msg(
01675 kmp_ms_fatal,
01676 KMP_MSG( CantSetEvent ),
01677 KMP_ERR( error ),
01678 __kmp_msg_null
01679 );
01680 }
01681 KA_TRACE( 10, ( "__kmp_reap_monitor: reaping thread (%d)\n", th->th.th_info.ds.ds_gtid ) );
01682 __kmp_reap_common( th );
01683
01684 __kmp_free_handle( __kmp_monitor_ev );
01685
01686 KMP_MB();
01687 }
01688
01689 void
01690 __kmp_reap_worker( kmp_info_t * th )
01691 {
01692 KA_TRACE( 10, ( "__kmp_reap_worker: reaping thread (%d)\n", th->th.th_info.ds.ds_gtid ) );
01693 __kmp_reap_common( th );
01694 }
01695
01696
01697
01698
01699 #if KMP_HANDLE_SIGNALS
01700
01701
01702 static void
01703 __kmp_team_handler( int signo )
01704 {
01705 if ( __kmp_global.g.g_abort == 0 ) {
01706
01707 if ( __kmp_debug_buf ) {
01708 __kmp_dump_debug_buffer();
01709 };
01710 KMP_MB();
01711 TCW_4( __kmp_global.g.g_abort, signo );
01712 KMP_MB();
01713 TCW_4( __kmp_global.g.g_done, TRUE );
01714 KMP_MB();
01715 }
01716 }
01717
01718
01719
01720 static
01721 sig_func_t __kmp_signal( int signum, sig_func_t handler ) {
01722 sig_func_t old = signal( signum, handler );
01723 if ( old == SIG_ERR ) {
01724 int error = errno;
01725 __kmp_msg( kmp_ms_fatal, KMP_MSG( FunctionError, "signal" ), KMP_ERR( error ), __kmp_msg_null );
01726 };
01727 return old;
01728 }
01729
01730 static void
01731 __kmp_install_one_handler(
01732 int sig,
01733 sig_func_t handler,
01734 int parallel_init
01735 ) {
01736 sig_func_t old;
01737 KMP_MB();
01738 KB_TRACE( 60, ("__kmp_install_one_handler: called: sig=%d\n", sig ) );
01739 if ( parallel_init ) {
01740 old = __kmp_signal( sig, handler );
01741
01742 if ( old == __kmp_sighldrs[ sig ] ) {
01743 __kmp_siginstalled[ sig ] = 1;
01744 } else {
01745
01746 old = __kmp_signal( sig, old );
01747 };
01748 } else {
01749
01750
01751
01752 old = __kmp_signal( sig, SIG_DFL );
01753 __kmp_sighldrs[ sig ] = old;
01754 __kmp_signal( sig, old );
01755 };
01756 KMP_MB();
01757 }
01758
01759 static void
01760 __kmp_remove_one_handler( int sig ) {
01761 if ( __kmp_siginstalled[ sig ] ) {
01762 sig_func_t old;
01763 KMP_MB();
01764 KB_TRACE( 60, ( "__kmp_remove_one_handler: called: sig=%d\n", sig ) );
01765 old = __kmp_signal( sig, __kmp_sighldrs[ sig ] );
01766 if ( old != __kmp_team_handler ) {
01767 KB_TRACE( 10, ( "__kmp_remove_one_handler: oops, not our handler, restoring: sig=%d\n", sig ) );
01768 old = __kmp_signal( sig, old );
01769 };
01770 __kmp_sighldrs[ sig ] = NULL;
01771 __kmp_siginstalled[ sig ] = 0;
01772 KMP_MB();
01773 };
01774 }
01775
01776
01777 void
01778 __kmp_install_signals( int parallel_init )
01779 {
01780 KB_TRACE( 10, ( "__kmp_install_signals: called\n" ) );
01781 if ( ! __kmp_handle_signals ) {
01782 KB_TRACE( 10, ( "__kmp_install_signals: KMP_HANDLE_SIGNALS is false - handlers not installed\n" ) );
01783 return;
01784 };
01785 __kmp_install_one_handler( SIGINT, __kmp_team_handler, parallel_init );
01786 __kmp_install_one_handler( SIGILL, __kmp_team_handler, parallel_init );
01787 __kmp_install_one_handler( SIGABRT, __kmp_team_handler, parallel_init );
01788 __kmp_install_one_handler( SIGFPE, __kmp_team_handler, parallel_init );
01789 __kmp_install_one_handler( SIGSEGV, __kmp_team_handler, parallel_init );
01790 __kmp_install_one_handler( SIGTERM, __kmp_team_handler, parallel_init );
01791 }
01792
01793
01794 void
01795 __kmp_remove_signals( void )
01796 {
01797 int sig;
01798 KB_TRACE( 10, ("__kmp_remove_signals: called\n" ) );
01799 for ( sig = 1; sig < NSIG; ++ sig ) {
01800 __kmp_remove_one_handler( sig );
01801 };
01802 }
01803
01804
01805 #endif // KMP_HANDLE_SIGNALS
01806
01807
01808 void
01809 __kmp_thread_sleep( int millis )
01810 {
01811 DWORD status;
01812
01813 status = SleepEx( (DWORD) millis, FALSE );
01814 if ( status ) {
01815 DWORD error = GetLastError();
01816 __kmp_msg(
01817 kmp_ms_fatal,
01818 KMP_MSG( FunctionError, "SleepEx()" ),
01819 KMP_ERR( error ),
01820 __kmp_msg_null
01821 );
01822 }
01823 }
01824
01825
01826 int
01827 __kmp_is_address_mapped( void * addr )
01828 {
01829 DWORD status;
01830 MEMORY_BASIC_INFORMATION lpBuffer;
01831 SIZE_T dwLength;
01832
01833 dwLength = sizeof(MEMORY_BASIC_INFORMATION);
01834
01835 status = VirtualQuery( addr, &lpBuffer, dwLength );
01836
01837 return !((( lpBuffer.State == MEM_RESERVE) || ( lpBuffer.State == MEM_FREE )) ||
01838 (( lpBuffer.Protect == PAGE_NOACCESS ) || ( lpBuffer.Protect == PAGE_EXECUTE )));
01839 }
01840
01841 kmp_uint64
01842 __kmp_hardware_timestamp(void)
01843 {
01844 kmp_uint64 r = 0;
01845
01846 QueryPerformanceCounter((LARGE_INTEGER*) &r);
01847 return r;
01848 }
01849
01850
01851 void
01852 __kmp_free_handle( kmp_thread_t tHandle )
01853 {
01854
01855 BOOL rc;
01856 rc = CloseHandle( tHandle );
01857 if ( !rc ) {
01858 DWORD error = GetLastError();
01859 __kmp_msg(
01860 kmp_ms_fatal,
01861 KMP_MSG( CantCloseHandle ),
01862 KMP_ERR( error ),
01863 __kmp_msg_null
01864 );
01865 }
01866 }
01867
01868 int
01869 __kmp_get_load_balance( int max ) {
01870
01871 static ULONG glb_buff_size = 100 * 1024;
01872
01873 static int glb_running_threads = 0;
01874 static double glb_call_time = 0;
01875
01876 int running_threads = 0;
01877 NTSTATUS status = 0;
01878 ULONG buff_size = 0;
01879 ULONG info_size = 0;
01880 void * buffer = NULL;
01881 PSYSTEM_PROCESS_INFORMATION spi = NULL;
01882 int first_time = 1;
01883
01884 double call_time = 0.0;
01885
01886 __kmp_elapsed( & call_time );
01887
01888 if ( glb_call_time &&
01889 ( call_time - glb_call_time < __kmp_load_balance_interval ) ) {
01890 running_threads = glb_running_threads;
01891 goto finish;
01892 }
01893 glb_call_time = call_time;
01894
01895
01896 if ( NtQuerySystemInformation == NULL ) {
01897 running_threads = -1;
01898 goto finish;
01899 };
01900
01901 if ( max <= 0 ) {
01902 max = INT_MAX;
01903 };
01904
01905 do {
01906
01907 if ( first_time ) {
01908 buff_size = glb_buff_size;
01909 } else {
01910 buff_size = 2 * buff_size;
01911 }
01912
01913 buffer = KMP_INTERNAL_REALLOC( buffer, buff_size );
01914 if ( buffer == NULL ) {
01915 running_threads = -1;
01916 goto finish;
01917 };
01918 status = NtQuerySystemInformation( SystemProcessInformation, buffer, buff_size, & info_size );
01919 first_time = 0;
01920
01921 } while ( status == STATUS_INFO_LENGTH_MISMATCH );
01922 glb_buff_size = buff_size;
01923
01924 #define CHECK( cond ) \
01925 { \
01926 KMP_DEBUG_ASSERT( cond ); \
01927 if ( ! ( cond ) ) { \
01928 running_threads = -1; \
01929 goto finish; \
01930 } \
01931 }
01932
01933 CHECK( buff_size >= info_size );
01934 spi = PSYSTEM_PROCESS_INFORMATION( buffer );
01935 for ( ; ; ) {
01936 ptrdiff_t offset = uintptr_t( spi ) - uintptr_t( buffer );
01937 CHECK( 0 <= offset && offset + sizeof( SYSTEM_PROCESS_INFORMATION ) < info_size );
01938 HANDLE pid = spi->ProcessId;
01939 ULONG num = spi->NumberOfThreads;
01940 CHECK( num >= 1 );
01941 size_t spi_size = sizeof( SYSTEM_PROCESS_INFORMATION ) + sizeof( SYSTEM_THREAD ) * ( num - 1 );
01942 CHECK( offset + spi_size < info_size );
01943 if ( spi->NextEntryOffset != 0 ) {
01944 CHECK( spi_size <= spi->NextEntryOffset );
01945 };
01946
01947
01948 if ( pid != 0 ) {
01949 for ( int i = 0; i < num; ++ i ) {
01950 THREAD_STATE state = spi->Threads[ i ].State;
01951
01952
01953 if ( state == StateRunning ) {
01954 ++ running_threads;
01955
01956
01957 if ( running_threads >= max ) {
01958 goto finish;
01959 }
01960 }
01961 };
01962 }
01963 if ( spi->NextEntryOffset == 0 ) {
01964 break;
01965 };
01966 spi = PSYSTEM_PROCESS_INFORMATION( uintptr_t( spi ) + spi->NextEntryOffset );
01967 };
01968
01969 #undef CHECK
01970
01971 finish:
01972
01973 if ( buffer != NULL ) {
01974 KMP_INTERNAL_FREE( buffer );
01975 };
01976
01977 glb_running_threads = running_threads;
01978
01979 return running_threads;
01980
01981 }
01982