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_wrapper_getpid.h"
00049 #include "kmp_str.h"
00050 #include <float.h>
00051 #include "kmp_i18n.h"
00052
00053
00054
00055
00056 static const char *unknown = "unknown";
00057
00058 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
00059
00060
00061
00062
00063
00064 static int trace_level = 5;
00065
00066
00067
00068
00069
00070
00071 int
00072 __kmp_get_physical_id( int log_per_phy, int apic_id )
00073 {
00074 int index_lsb, index_msb, temp;
00075
00076 if (log_per_phy > 1) {
00077 index_lsb = 0;
00078 index_msb = 31;
00079
00080 temp = log_per_phy;
00081 while ( (temp & 1) == 0 ) {
00082 temp >>= 1;
00083 index_lsb++;
00084 }
00085
00086 temp = log_per_phy;
00087 while ( (temp & 0x80000000)==0 ) {
00088 temp <<= 1;
00089 index_msb--;
00090 }
00091
00092
00093 if (index_lsb != index_msb) index_msb++;
00094
00095 return ( (int) (apic_id >> index_msb) );
00096 }
00097
00098 return apic_id;
00099 }
00100
00101
00102
00103
00104
00105
00106
00107 int
00108 __kmp_get_logical_id( int log_per_phy, int apic_id )
00109 {
00110 unsigned current_bit;
00111 int bits_seen;
00112 unsigned mask;
00113
00114 if (log_per_phy <= 1) return ( 0 );
00115
00116 bits_seen = 0;
00117
00118 for (current_bit = 1; log_per_phy != 0; current_bit <<= 1) {
00119 if ( log_per_phy & current_bit ) {
00120 log_per_phy &= ~current_bit;
00121 bits_seen++;
00122 }
00123 }
00124
00125
00126 if (bits_seen == 1) {
00127 current_bit >>= 1;
00128 }
00129
00130 return ( (int) ((current_bit - 1) & apic_id) );
00131 }
00132
00133
00134 static
00135 kmp_uint64
00136 __kmp_parse_frequency(
00137 char const * frequency
00138 ) {
00139
00140 double value = 0.0;
00141 char const * unit = NULL;
00142 kmp_uint64 result = ~ 0;
00143
00144 if ( frequency == NULL ) {
00145 return result;
00146 };
00147 value = strtod( frequency, (char * *) & unit );
00148 if ( 0 < value && value <= DBL_MAX ) {
00149 if ( strcmp( unit, "MHz" ) == 0 ) {
00150 value = value * 1.0E+6;
00151 } else if ( strcmp( unit, "GHz" ) == 0 ) {
00152 value = value * 1.0E+9;
00153 } else if ( strcmp( unit, "THz" ) == 0 ) {
00154 value = value * 1.0E+12;
00155 } else {
00156 return result;
00157 };
00158 result = value;
00159 };
00160 return result;
00161
00162 };
00163
00164 void
00165 __kmp_query_cpuid( kmp_cpuinfo_t *p )
00166 {
00167 struct kmp_cpuid buf;
00168 int max_arg;
00169 int log_per_phy;
00170 int cflush_size;
00171
00172 p->initialized = 1;
00173
00174 p->sse2 = 1;
00175
00176 __kmp_x86_cpuid( 0, 0, &buf );
00177
00178 KA_TRACE( trace_level, ("INFO: CPUID %d: EAX=0x%08X EBX=0x%08X ECX=0x%08X EDX=0x%08X\n",
00179 0, buf.eax, buf.ebx, buf.ecx, buf.edx ) );
00180
00181 max_arg = buf.eax;
00182
00183 p->apic_id = -1;
00184
00185 if (max_arg >= 1) {
00186 int i;
00187 kmp_uint32 t, data[ 4 ];
00188
00189 __kmp_x86_cpuid( 1, 0, &buf );
00190 KA_TRACE( trace_level, ("INFO: CPUID %d: EAX=0x%08X EBX=0x%08X ECX=0x%08X EDX=0x%08X\n",
00191 1, buf.eax, buf.ebx, buf.ecx, buf.edx ) );
00192
00193 {
00194 #define get_value(reg,lo,mask) ( ( ( reg ) >> ( lo ) ) & ( mask ) )
00195
00196 p->signature = buf.eax;
00197 p->family = get_value( buf.eax, 20, 0xff ) + get_value( buf.eax, 8, 0x0f );
00198 p->model = ( get_value( buf.eax, 16, 0x0f ) << 4 ) + get_value( buf.eax, 4, 0x0f );
00199 p->stepping = get_value( buf.eax, 0, 0x0f );
00200
00201 #undef get_value
00202
00203 KA_TRACE( trace_level, (" family = %d, model = %d, stepping = %d\n", p->family, p->model, p->stepping ) );
00204 }
00205
00206 for ( t = buf.ebx, i = 0; i < 4; t >>= 8, ++i ) {
00207 data[ i ] = (t & 0xff);
00208 };
00209
00210 p->sse2 = ( buf.edx >> 26 ) & 1;
00211
00212 #ifdef KMP_DEBUG
00213
00214 if ( (buf.edx >> 4) & 1 ) {
00215
00216 KA_TRACE( trace_level, (" TSC" ) );
00217 }
00218 if ( (buf.edx >> 8) & 1 ) {
00219
00220 KA_TRACE( trace_level, (" CX8" ) );
00221 }
00222 if ( (buf.edx >> 9) & 1 ) {
00223
00224 KA_TRACE( trace_level, (" APIC" ) );
00225 }
00226 if ( (buf.edx >> 15) & 1 ) {
00227
00228 KA_TRACE( trace_level, (" CMOV" ) );
00229 }
00230 if ( (buf.edx >> 18) & 1 ) {
00231
00232 KA_TRACE( trace_level, (" PSN" ) );
00233 }
00234 if ( (buf.edx >> 19) & 1 ) {
00235
00236 cflush_size = data[ 1 ] * 8;
00237 KA_TRACE( trace_level, (" CLFLUSH(%db)", cflush_size ) );
00238
00239 }
00240 if ( (buf.edx >> 21) & 1 ) {
00241
00242 KA_TRACE( trace_level, (" DTES" ) );
00243 }
00244 if ( (buf.edx >> 22) & 1 ) {
00245
00246 KA_TRACE( trace_level, (" ACPI" ) );
00247 }
00248 if ( (buf.edx >> 23) & 1 ) {
00249
00250 KA_TRACE( trace_level, (" MMX" ) );
00251 }
00252 if ( (buf.edx >> 25) & 1 ) {
00253
00254 KA_TRACE( trace_level, (" SSE" ) );
00255 }
00256 if ( (buf.edx >> 26) & 1 ) {
00257
00258 KA_TRACE( trace_level, (" SSE2" ) );
00259 }
00260 if ( (buf.edx >> 27) & 1 ) {
00261
00262 KA_TRACE( trace_level, (" SLFSNP" ) );
00263 }
00264 #endif
00265
00266 __kmp_ht_capable = FALSE;
00267 if ( (buf.edx >> 28) & 1 ) {
00268
00269
00270 __kmp_ht_capable = TRUE;
00271
00272
00273 log_per_phy = data[ 2 ];
00274 __kmp_ht_log_per_phy = log_per_phy;
00275
00276 p->apic_id = data[ 3 ];
00277 KA_TRACE( trace_level, (" HT(%d TPUs)", log_per_phy ) );
00278
00279 if( log_per_phy > 1 ) {
00280
00281 #if KMP_OS_DARWIN
00282 p->cpu_stackoffset = 4 * 1024;
00283 #else
00284 p->cpu_stackoffset = 1 * 1024;
00285 #endif
00286 }
00287
00288 p->physical_id = __kmp_get_physical_id( log_per_phy, p->apic_id );
00289 p->logical_id = __kmp_get_logical_id( log_per_phy, p->apic_id );
00290 }
00291 #ifdef KMP_DEBUG
00292 if ( (buf.edx >> 29) & 1 ) {
00293
00294 KA_TRACE( trace_level, (" ATHROTL" ) );
00295 }
00296 KA_TRACE( trace_level, (" ]\n" ) );
00297
00298 for (i = 2; i <= max_arg; ++i) {
00299 __kmp_x86_cpuid( i, 0, &buf );
00300 KA_TRACE( trace_level,
00301 ( "INFO: CPUID %d: EAX=0x%08X EBX=0x%08X ECX=0x%08X EDX=0x%08X\n",
00302 i, buf.eax, buf.ebx, buf.ecx, buf.edx ) );
00303 }
00304 #endif
00305 };
00306
00307 {
00308
00309 union kmp_cpu_brand_string {
00310 struct kmp_cpuid buf[ 3 ];
00311 char string[ sizeof( struct kmp_cpuid ) * 3 + 1 ];
00312 };
00313 union kmp_cpu_brand_string brand;
00314 int i;
00315
00316 p->frequency = 0;
00317
00318
00319 for ( i = 0; i < 3; ++ i ) {
00320 __kmp_x86_cpuid( 0x80000002 + i, 0, &brand.buf[ i ] );
00321 };
00322 brand.string[ sizeof( brand.string ) - 1 ] = 0;
00323 KA_TRACE( trace_level, ( "cpu brand string: \"%s\"\n", brand.string ) );
00324
00325
00326 p->frequency = __kmp_parse_frequency( strrchr( brand.string, ' ' ) );
00327 KA_TRACE( trace_level, ( "cpu frequency from brand string: %" KMP_UINT64_SPEC "\n", p->frequency ) );
00328 }
00329 }
00330
00331 #endif
00332
00333
00334
00335
00336 void
00337 __kmp_expand_host_name( char *buffer, size_t size )
00338 {
00339 KMP_DEBUG_ASSERT(size >= sizeof(unknown));
00340 #if KMP_OS_WINDOWS
00341 {
00342 DWORD s = size;
00343
00344 if (! GetComputerNameA( buffer, & s ))
00345 strcpy( buffer, unknown );
00346 }
00347 #else
00348 buffer[size - 2] = 0;
00349 if (gethostname( buffer, size ) || buffer[size - 2] != 0)
00350 strcpy( buffer, unknown );
00351 #endif
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 void
00364 __kmp_expand_file_name( char *result, size_t rlen, char *pattern )
00365 {
00366 char *pos = result, *end = result + rlen - 1;
00367 char buffer[256];
00368 int default_cpu_width = 1;
00369 int snp_result;
00370
00371 KMP_DEBUG_ASSERT(rlen > 0);
00372 *end = 0;
00373 {
00374 int i;
00375 for(i = __kmp_xproc; i >= 10; i /= 10, ++default_cpu_width);
00376 }
00377
00378 if (pattern != NULL) {
00379 while (*pattern != '\0' && pos < end) {
00380 if (*pattern != '%') {
00381 *pos++ = *pattern++;
00382 } else {
00383 char *old_pattern = pattern;
00384 int width = 1;
00385 int cpu_width = default_cpu_width;
00386
00387 ++pattern;
00388
00389 if (*pattern >= '0' && *pattern <= '9') {
00390 width = 0;
00391 do {
00392 width = (width * 10) + *pattern++ - '0';
00393 } while (*pattern >= '0' && *pattern <= '9');
00394 if (width < 0 || width > 1024)
00395 width = 1;
00396
00397 cpu_width = width;
00398 }
00399
00400 switch (*pattern) {
00401 case 'H':
00402 case 'h':
00403 {
00404 __kmp_expand_host_name( buffer, sizeof( buffer ) );
00405 strncpy( pos, buffer, end - pos + 1);
00406 if(*end == 0) {
00407 while ( *pos )
00408 ++pos;
00409 ++pattern;
00410 } else
00411 pos = end;
00412 }
00413 break;
00414 case 'P':
00415 case 'p':
00416 {
00417 snp_result = snprintf( pos, end - pos + 1, "%0*d", cpu_width, __kmp_dflt_team_nth );
00418 if(snp_result >= 0 && snp_result <= end - pos) {
00419 while ( *pos )
00420 ++pos;
00421 ++pattern;
00422 } else
00423 pos = end;
00424 }
00425 break;
00426 case 'I':
00427 case 'i':
00428 {
00429 pid_t id = getpid();
00430 snp_result = snprintf( pos, end - pos + 1, "%0*d", width, id );
00431 if(snp_result >= 0 && snp_result <= end - pos) {
00432 while ( *pos )
00433 ++pos;
00434 ++pattern;
00435 } else
00436 pos = end;
00437 break;
00438 }
00439 case '%':
00440 {
00441 *pos++ = '%';
00442 ++pattern;
00443 break;
00444 }
00445 default:
00446 {
00447 *pos++ = '%';
00448 pattern = old_pattern + 1;
00449 break;
00450 }
00451 }
00452 }
00453 }
00454
00455 if(*pattern != '\0')
00456 KMP_FATAL( FileNameTooLong );
00457 }
00458
00459 *pos = '\0';
00460 }
00461
00462