z_Windows_NT_util.c

Go to the documentation of this file.
00001 /*
00002  * z_Windows_NT_util.c -- platform specific routines.
00003  * $Revision: 42248 $
00004  * $Date: 2013-04-03 07:08:13 -0500 (Wed, 03 Apr 2013) $
00005  */
00006 
00007 /* <copyright>
00008     Copyright (c) 1997-2013 Intel Corporation.  All Rights Reserved.
00009 
00010     Redistribution and use in source and binary forms, with or without
00011     modification, are permitted provided that the following conditions
00012     are met:
00013 
00014       * Redistributions of source code must retain the above copyright
00015         notice, this list of conditions and the following disclaimer.
00016       * Redistributions in binary form must reproduce the above copyright
00017         notice, this list of conditions and the following disclaimer in the
00018         documentation and/or other materials provided with the distribution.
00019       * Neither the name of Intel Corporation nor the names of its
00020         contributors may be used to endorse or promote products derived
00021         from this software without specific prior written permission.
00022 
00023     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00026     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00027     HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 
00035 
00036 ------------------------------------------------------------------------
00037 
00038     Portions of this software are protected under the following patents:
00039         U.S. Patent 5,812,852
00040         U.S. Patent 6,792,599
00041         U.S. Patent 7,069,556
00042         U.S. Patent 7,328,433
00043         U.S. Patent 7,500,242
00044 
00045 </copyright> */
00046 
00047 #include "kmp.h"
00048 #include "kmp_i18n.h"
00049 #include "kmp_io.h"
00050 
00051 
00052 
00053 /* ----------------------------------------------------------------------------------- */
00054 /* ----------------------------------------------------------------------------------- */
00055 
00056 /* This code is related to NtQuerySystemInformation() function. This function 
00057    is used in the Load balance algorithm for OMP_DYNAMIC=true to find the 
00058    number of running threads in the system. */
00059 
00060 #include <ntstatus.h>
00061 #include <ntsecapi.h>   // UNICODE_STRING
00062 
00063 enum SYSTEM_INFORMATION_CLASS {
00064     SystemProcessInformation = 5
00065 }; // SYSTEM_INFORMATION_CLASS
00066 
00067 struct CLIENT_ID {
00068     HANDLE UniqueProcess;
00069     HANDLE UniqueThread;
00070 }; // struct CLIENT_ID
00071 
00072 enum THREAD_STATE {
00073     StateInitialized,
00074     StateReady,
00075     StateRunning,
00076     StateStandby,
00077     StateTerminated,
00078     StateWait,
00079     StateTransition,
00080     StateUnknown
00081 }; // enum THREAD_STATE
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 }; // struct VM_COUNTERS
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 }; // SYSTEM_THREAD
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 }; // SYSTEM_PROCESS_INFORMATION
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 /* End of NtQuerySystemInformation()-related code */
00163 
00164 #if KMP_ARCH_X86_64
00165 static HMODULE kernel32 = NULL;
00166 #endif /* KMP_ARCH_X86_64 */
00167 
00168 /* ----------------------------------------------------------------------------------- */
00169 /* ----------------------------------------------------------------------------------- */
00170 
00171 
00172 // Why do we have multiple copies of __kmp_static_delay() and __kmp_static_yield() in many files?
00173 #ifdef KMP_DEBUG
00174 
00175 static void
00176 __kmp_static_delay( int arg ) {
00177     /* Work around weird code-gen bug that causes assert to trip */
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 )     /* nothing to do */
00188 
00189 #endif /* KMP_DEBUG */
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     /* Initialize the critical section */
00242     __kmp_win32_mutex_init( & cv->waiters_count_lock_ );
00243 
00244     /* Create a manual-reset event. */
00245     cv->event_ = CreateEvent( NULL,     // no security
00246                               TRUE,     // manual-reset
00247                               FALSE,    // non-signaled initially
00248                               NULL );   // unnamed
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 /* TODO associate cv with a team instead of a thread so as to optimize
00260  * the case where we wake up a whole team */
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     /* Avoid race conditions */
00269     __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
00270 
00271     /* Increment count of waiters */
00272     cv->waiters_count_++;
00273 
00274     /* Store current generation in our activation record. */
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         /* Wait until the event is signaled */
00285         WaitForSingleObject( cv->event_, INFINITE );
00286 
00287         __kmp_win32_mutex_lock( &cv->waiters_count_lock_ );
00288 
00289         /* Exit the loop when the <cv->event_> is signaled and
00290          * there are still waiting threads from this <wait_generation>
00291          * that haven't been released from this wait yet.              */
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         /* there used to be a semicolon after the if statement,
00298          * it looked like a bug, so i removed it */
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         /* We're the last waiter to be notified, so reset the manual event. */
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         /* Release all the threads in this generation. */
00327 
00328         cv->release_count_ = cv->waiters_count_;
00329 
00330         /* Start a new generation. */
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     /* do nothing */
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       /* this means we haven't initialized the suspension pthread objects for this thread
00373          in this instance of the process */
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       /* this means we have initialize the suspension pthread objects for this thread
00385          in this instance of the process */
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  * This routine puts the calling thread to sleep after setting the
00394  * sleep bit for the indicated spin variable to true.
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     /* TODO: shouldn't this use release semantics to ensure that __kmp_suspend_initialize_thread
00414        gets called first?
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         /* Encapsulate in a loop as the documentation states that this may
00433          * "with low probability" return when the condition variable has
00434          * not been signaled or broadcast
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             // Mark the thread as no longer active
00446             // (only in the first iteration of the loop).
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 /* KMP_DEBUG */
00470 
00471     } // while
00472 
00473         //
00474         // Mark the thread as active again
00475         // (if it was previous marked as inactive)
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 /* This routine signals the thread specified by target_gtid to wake up
00494  * after setting the sleep bit indicated by the spin argument to FALSE
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 // Only 1 DWORD in the mask should have any procs set.
00600 // Return the appropriate index, or -1 for an invalid mask.
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 /* KMP_ARCH_X86_64 */
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         // Check for a valid mask.
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         // Transform the bit vector into a GROUP_AFFINITY struct
00643         // and make the system call to set affinity.
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 /* KMP_ARCH_X86_64 */
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 /* KMP_ARCH_X86_64 */
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         // Form the GROUP_AFFINITY struct directly, rather than filling
00773         // out a bit vector and calling __kmp_set_system_affinity().
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) { // AC: continue silently if not 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 /* KMP_ARCH_X86_64 */
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     // All versions of Windows* OS (since Win '95) support SetThreadAffinityMask().
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         /* Shift left by 32 bits */
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;                   /* the maximum resident set size utilized (in kilobytes)     */
00861     info->minflt  = 0;                   /* the number of page faults serviced without any I/O        */
00862     info->majflt  = 0;                   /* the number of page faults serviced that required I/O      */
00863     info->nswap   = 0;                   /* the number of times a process was "swapped" out of memory */
00864     info->inblock = 0;                   /* the number of times the file system had to perform input  */
00865     info->oublock = 0;                   /* the number of times the file system had to perform output */
00866     info->nvcsw   = 0;                   /* the number of times a context switch was voluntarily      */
00867     info->nivcsw  = 0;                   /* the number of times a context switch was forced           */
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         }; // if
00894     #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
00895 
00896     if ( __kmp_cpu_frequency == 0 ) {
00897         // __kmp_hardware_timestamp() calls to QueryPerformanceCounter(). If
00898         // __kmp_hardware_timestamp() rewritten to use RDTSC instruction (or its 64 analog),
00899         // probably we should try to get frequency from __kmp_cpuinfo.frequency first (see
00900         // z_Linux_util.c).
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         }; // if
00912     }; // if
00913 
00914     /* Set up minimum number of threads to switch to TLS gtid */
00915     #if KMP_OS_WINDOWS && ! defined GUIDEDLL_EXPORTS 
00916         // Windows* OS, static library.
00917         /*
00918             New thread may use stack space previously used by another thread, currently terminated.
00919             On Windows* OS, in case of static linking, we do not know the moment of thread termination,
00920             and our structures (__kmp_threads and __kmp_root arrays) are still keep info about dead
00921             threads. This leads to problem in __kmp_get_global_thread_id() function: it wrongly
00922             finds gtid (by searching through stack addresses of all known threads) for unregistered
00923             foreign tread.
00924 
00925             Setting __kmp_tls_gtid_min to 0 workarounds this problem: __kmp_get_global_thread_id()
00926             does not search through stacks, but get gtid from TLS immediatelly.
00927 
00928             --ln
00929         */
00930         __kmp_tls_gtid_min = 0;
00931     #else
00932         __kmp_tls_gtid_min = KMP_TLS_GTID_MIN;
00933     #endif
00934 
00935     /* for the static library */
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     // Load ntdll.dll.
00946     //
00947     /*
00948         Simple
00949             GetModuleHandle( "ntdll.dl" )
00950         is not suitable due to security issue (see
00951         http://www.microsoft.com/technet/security/advisory/2269637.mspx). We have to specify full
00952         path to the library.
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         // Buffer is too short.  Expand the buffer and try again.
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     }; // if
00965     if ( path_size > 0 && path_size < path.size ) {
00966         //
00967         // Now we have system directory name in the buffer.
00968         // Append backslash and name of dll to form full path,
00969         //
00970         path.used = path_size;
00971         __kmp_str_buf_print( & path, "\\%s", "ntdll.dll" );
00972 
00973         //
00974         // Now load ntdll using full path.
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     // Load kernel32.dll.
00988     // Same caveat - must use full system path name.
00989     //
00990     if ( path_size > 0 && path_size < path.size ) {
00991         //
00992         // Truncate the buffer back to just the system path length,
00993         // discarding "\\ntdll.dll", and replacing it with "kernel32.dll".
00994         //
00995         path.used = path_size;
00996         __kmp_str_buf_print( & path, "\\%s", "kernel32.dll" );
00997 
00998         //
00999         // Load kernel32.dll using full path.
01000         //
01001         kernel32 = GetModuleHandle( path.str );
01002 
01003         //
01004         // Load the function pointers to kernel32.dll routines
01005         // that may or may not exist on this system.
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             // See if group affinity is supported on this system.
01015             // If so, calculate the #groups and #procs.
01016             //
01017             // Group affinity was introduced with Windows* 7 OS and 
01018             // Windows* Server 2008 R2 OS.
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                 // Calculate the total number of active OS procs.
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     // If the OS said there were 0 procs, take a guess and use a value of 2.
01054     // This is done for Linux* OS, also.  Do we need error / warning?
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 } // __kmp_runtime_initialize
01067 
01068 void
01069 __kmp_runtime_destroy( void )
01070 {
01071     if ( ! __kmp_init_runtime ) {
01072         return;
01073     }
01074 
01075 
01076     /* we can't DeleteCriticalsection( & __kmp_win32_section ); */
01077     /* due to the KX_TRACE() commands */
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         /* It's OK, the thread may have exited already */
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 /* Calculate the elapsed wall clock time for the user */
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 /* Calculate the elapsed wall clock tick for the user */
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  * Change thread to the affinity mask pointed to by affin_mask argument
01193  * and return a pointer to the old value in the old_mask argument, if argument
01194  * is non-NULL.
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     /* Make sure old value is correct in thread data structures */
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     //__kmp_gtid = gtid;
01247 #endif
01248 
01249 
01250     __kmp_affinity_set_init_mask( gtid, FALSE );
01251 
01252 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
01253     //
01254     // Set the FP control regs to be a copy of
01255     // the parallel initialization thread's.
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 /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
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 ) { // check stack only if it is used to get gtid
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 /* The monitor thread controls all of the threads in the complex */
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 );    // AC: Signal the library that monitor has started
01295                                        // TODO: hide "2" in enum (like {true,false,started})
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();       /* Flush all pending memory write invalidates.  */
01300     KA_TRACE( 10, ("__kmp_launch_monitor: launched\n" ) );
01301 
01302     monitor = GetCurrentThread();
01303 
01304     /* set thread priority */
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     /* register us as monitor */
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     //__kmp_gtid = KMP_GTID_MONITOR;
01323 #endif
01324 
01325 
01326     KMP_MB();       /* Flush all pending memory write invalidates.  */
01327 
01328     interval = ( 1000 / __kmp_monitor_wakeups ); /* in milliseconds */
01329 
01330     while (! TCR_4(__kmp_global.g.g_done)) {
01331         /*  This thread monitors the state of the system */
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();       /* Flush all pending memory write invalidates.  */
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         /* now we need to terminate the worker threads   */
01360         /* the value of t_abort is the signal we caught */
01361 
01362         int gtid;
01363 
01364         KA_TRACE( 10, ("__kmp_launch_monitor: terminate sig=%d\n", (__kmp_global.g.g_abort) ) );
01365 
01366         /* terminate the OpenMP worker threads */
01367         /* TODO this is not valid for sibling threads!!
01368          * the uber master might not be 0 anymore.. */
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         /* TODO: GetCurrentThread() returns a pseudo-handle that is unsuitable for other threads to use.
01403            Is it appropriate to just use GetCurrentThread?  When should we close this handle?  When
01404            unregistering the root?
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 ) { // check stack only if it is used to get gtid
01424             /* we will dynamically update the stack range if gtid_mode == 1 */
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();       /* Flush all pending memory write invalidates.  */
01433 
01434         /* Set stack size for this thread now. */
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();       /* Flush all pending memory write invalidates.  */
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();       /* Flush all pending memory write invalidates.  */
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     }; // if
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     // FIXME - on Windows* OS, if __kmp_monitor_stksize = 0, figure out how
01516     // to automatically expand stacksize based on CreateThread error code.
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();       /* Flush all pending memory write invalidates.  */
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   Check to see if thread is still alive.
01552 
01553   NOTE:  The ExitProcess(code) system call causes all threads to Terminate
01554          with a exit_val = code.  Because of this we can not rely on
01555          exit_val having any particular value.  So this routine may
01556          return STILL_ALIVE in exit_val even after the thread is dead.
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     }; // if
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 } // __kmp_exit_thread
01583 
01584 /*
01585     This is a common part for both __kmp_reap_worker() and __kmp_reap_monitor().
01586 */
01587 static void
01588 __kmp_reap_common( kmp_info_t * th )
01589 {
01590     DWORD exit_val;
01591 
01592     KMP_MB();       /* Flush all pending memory write invalidates.  */
01593 
01594     KA_TRACE( 10, ( "__kmp_reap_common: try to reap (%d)\n", th->th.th_info.ds.ds_gtid ) );
01595 
01596     /*
01597         2006-10-19:
01598 
01599         There are two opposite situations:
01600 
01601             1. Windows* OS keep thread alive after it resets ds_alive flag and exits from thread
01602                function. (For example, see C70770/Q394281 "unloading of dll based on OMP is very
01603                slow".)
01604             2. Windows* OS may kill thread before it resets ds_alive flag.
01605 
01606         Right solution seems to be waiting for *either* thread termination *or* ds_alive resetting.
01607 
01608     */
01609 
01610     {
01611         // TODO: This code is very similar to KMP_WAIT_YIELD. Need to generalize KMP_WAIT_YIELD to
01612         // cover this usage also.
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      * NOTE:  The ExitProcess(code) system call causes all threads to Terminate
01628      *        with a exit_val = code.  Because of this we can not rely on
01629      *        exit_val having any particular value.
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     }; // if
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();       /* Flush all pending memory write invalidates.  */
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     // If monitor has been created, its tid and gtid should be KMP_GTID_MONITOR.
01662     // If both tid and gtid are 0, it means the monitor did not ever start.
01663     // If both tid and gtid are KMP_GTID_DNE, the monitor has been shut down.
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     }; // if
01668 
01669     KMP_MB();       /* Flush all pending memory write invalidates.  */
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();       /* Flush all pending memory write invalidates.  */
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         // Stage 1 signal handler, let's shut down all of the threads.
01707         if ( __kmp_debug_buf ) {
01708             __kmp_dump_debug_buffer();
01709         }; // if
01710         KMP_MB();       // Flush all pending memory write invalidates.
01711         TCW_4( __kmp_global.g.g_abort, signo );
01712         KMP_MB();       // Flush all pending memory write invalidates.
01713         TCW_4( __kmp_global.g.g_done, TRUE );
01714         KMP_MB();       // Flush all pending memory write invalidates.
01715     }
01716 } // __kmp_team_handler
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     }; // if
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();       /* Flush all pending memory write invalidates.  */
01738     KB_TRACE( 60, ("__kmp_install_one_handler: called: sig=%d\n", sig ) );
01739     if ( parallel_init ) {
01740         old = __kmp_signal( sig, handler );
01741         // SIG_DFL on Windows* OS in NULL or 0.
01742         if ( old == __kmp_sighldrs[ sig ] ) {
01743             __kmp_siginstalled[ sig ] = 1;
01744         } else {
01745             // Restore/keep user's handler if one previously installed.
01746             old = __kmp_signal( sig, old );
01747         }; // if
01748     } else {
01749         // Save initial/system signal handlers to see if user handlers installed.
01750         // 2009-09-23: It is a dead code. On Windows* OS __kmp_install_signals called once with
01751         // parallel_init == TRUE.
01752         old = __kmp_signal( sig, SIG_DFL );
01753         __kmp_sighldrs[ sig ] = old;
01754         __kmp_signal( sig, old );
01755     }; // if
01756     KMP_MB();       /* Flush all pending memory write invalidates.  */
01757 } // __kmp_install_one_handler
01758 
01759 static void
01760 __kmp_remove_one_handler( int sig ) {
01761     if ( __kmp_siginstalled[ sig ] ) {
01762         sig_func_t old;
01763         KMP_MB();       // Flush all pending memory write invalidates.
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         }; // if
01770         __kmp_sighldrs[ sig ] = NULL;
01771         __kmp_siginstalled[ sig ] = 0;
01772         KMP_MB();       // Flush all pending memory write invalidates.
01773     }; // if
01774 } // __kmp_remove_one_handler
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     }; // if
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 } // __kmp_install_signals
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     }; // for sig
01802 } // __kmp_remove_signals
01803 
01804 
01805 #endif // KMP_HANDLE_SIGNALS
01806 
01807 /* Put the thread to sleep for a time period */
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 /* Determine whether the given address is mapped into the current address space. */
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 /* Free handle and check the error code */
01851 void
01852 __kmp_free_handle( kmp_thread_t tHandle )
01853 {
01854 /* called with parameter type HANDLE also, thus suppose kmp_thread_t defined as HANDLE */
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;  /* Saved count of the running threads for the thread balance algortihm */
01874     static double  glb_call_time        = 0;  /* Thread balance algorithm call time */
01875 
01876     int running_threads = 0;              // Number of running threads in the system.
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; //start, finish;
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     // Do not spend time on running algorithm if we have a permanent error.
01896     if ( NtQuerySystemInformation == NULL ) {
01897         running_threads = -1;
01898         goto finish;
01899     }; // if
01900 
01901     if ( max <= 0 ) {
01902         max = INT_MAX;
01903     }; // if
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         }; // if
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 );          // Make sure process info record fits the buffer.
01943         if ( spi->NextEntryOffset != 0 ) {
01944             CHECK( spi_size <= spi->NextEntryOffset );   // And do not overlap with the next record.
01945         }; // if
01946         // pid == 0 corresponds to the System Idle Process. It always has running threads
01947         // on all cores. So, we don't consider the running threads of this process.
01948         if ( pid != 0 ) {
01949             for ( int i = 0; i < num; ++ i ) {
01950                 THREAD_STATE state = spi->Threads[ i ].State;
01951                 // Count threads that have Ready or Running state.
01952                 // !!! TODO: Why comment does not match the code???
01953                 if ( state == StateRunning ) {
01954                     ++ running_threads;
01955                     // Stop counting running threads if the number is already greater than
01956                     // the number of available cores
01957                     if ( running_threads >= max ) {
01958                         goto finish;
01959                     }
01960                 } // if
01961             }; // for i
01962         } // if
01963         if ( spi->NextEntryOffset == 0 ) {
01964             break;
01965         }; // if
01966         spi = PSYSTEM_PROCESS_INFORMATION( uintptr_t( spi ) + spi->NextEntryOffset );
01967     }; // forever
01968 
01969     #undef CHECK
01970 
01971     finish: // Clean up and exit.
01972 
01973         if ( buffer != NULL ) {
01974             KMP_INTERNAL_FREE( buffer );
01975         }; // if
01976 
01977         glb_running_threads = running_threads;
01978 
01979         return running_threads;
01980 
01981 } //__kmp_get_load_balance()
01982 

Generated on 25 Aug 2013 for libomp_oss by  doxygen 1.6.1