|
PAPI
5.0.1.0
|
00001 #include <unistd.h> 00002 #include <string.h> 00003 #include <stdlib.h> 00004 #include <ctype.h> 00005 #include <err.h> 00006 #include <stdarg.h> 00007 #include <stdio.h> 00008 #include <errno.h> 00009 #include <sys/utsname.h> 00010 00011 #include <time.h> 00012 #include <sys/time.h> 00013 #include <sys/times.h> 00014 00015 00016 #include "papi.h" 00017 #include "papi_internal.h" 00018 #include "papi_vector.h" 00019 00020 #include "darwin-memory.h" 00021 #include "darwin-common.h" 00022 00023 #include "x86_cpuid_info.h" 00024 00025 PAPI_os_info_t _papi_os_info; 00026 00027 /* The locks used by Darwin */ 00028 00029 #if defined(USE_PTHREAD_MUTEXES) 00030 pthread_mutex_t _papi_hwd_lock_data[PAPI_MAX_LOCK]; 00031 #else 00032 volatile unsigned int _papi_hwd_lock_data[PAPI_MAX_LOCK]; 00033 #endif 00034 00035 00036 static int _darwin_init_locks(void) { 00037 00038 int i; 00039 00040 for ( i = 0; i < PAPI_MAX_LOCK; i++ ) { 00041 #if defined(USE_PTHREAD_MUTEXES) 00042 pthread_mutex_init(&_papi_hwd_lock_data[i],NULL); 00043 #else 00044 _papi_hwd_lock_data[i] = MUTEX_OPEN; 00045 #endif 00046 } 00047 00048 return PAPI_OK; 00049 } 00050 00051 00052 int 00053 _darwin_detect_hypervisor(char *virtual_vendor_name) { 00054 00055 int retval=0; 00056 00057 #if defined(__i386__)||defined(__x86_64__) 00058 retval=_x86_detect_hypervisor(virtual_vendor_name); 00059 #else 00060 (void) virtual_vendor_name; 00061 #endif 00062 00063 return retval; 00064 } 00065 00066 00067 #define _PATH_SYS_SYSTEM "/sys/devices/system" 00068 #define _PATH_SYS_CPU0 _PATH_SYS_SYSTEM "/cpu/cpu0" 00069 00070 static char pathbuf[PATH_MAX] = "/"; 00071 00072 00073 static char * 00074 search_cpu_info( FILE * f, char *search_str, char *line ) 00075 { 00076 /* This function courtesy of Rudolph Berrendorf! */ 00077 /* See the home page for the German version of PAPI. */ 00078 char *s; 00079 00080 while ( fgets( line, 256, f ) != NULL ) { 00081 if ( strstr( line, search_str ) != NULL ) { 00082 /* ignore all characters in line up to : */ 00083 for ( s = line; *s && ( *s != ':' ); ++s ); 00084 if ( *s ) 00085 return s; 00086 } 00087 } 00088 return NULL; 00089 } 00090 00091 00092 00093 int 00094 _darwin_get_cpu_info( PAPI_hw_info_t *hwinfo, int *cpuinfo_mhz ) 00095 { 00096 00097 int mib[4]; 00098 size_t len; 00099 char buffer[BUFSIZ]; 00100 long long ll; 00101 00102 /* "sysctl -a" shows lots of info we can get on OSX */ 00103 00104 /**********/ 00105 /* Vendor */ 00106 /**********/ 00107 len = 3; 00108 sysctlnametomib("machdep.cpu.vendor", mib, &len); 00109 00110 len = BUFSIZ; 00111 if (sysctl(mib, 3, &buffer, &len, NULL, 0) == -1) { 00112 return PAPI_ESYS; 00113 } 00114 strncpy( hwinfo->vendor_string,buffer,len); 00115 00116 hwinfo->vendor = PAPI_VENDOR_INTEL; 00117 00118 00119 /**************/ 00120 /* Model Name */ 00121 /**************/ 00122 len = 3; 00123 sysctlnametomib("machdep.cpu.brand_string", mib, &len); 00124 00125 len = BUFSIZ; 00126 if (sysctl(mib, 3, &buffer, &len, NULL, 0) == -1) { 00127 return PAPI_ESYS; 00128 } 00129 strncpy( hwinfo->model_string,buffer,len); 00130 00131 /************/ 00132 /* Revision */ 00133 /************/ 00134 len = 3; 00135 sysctlnametomib("machdep.cpu.stepping", mib, &len); 00136 00137 len = BUFSIZ; 00138 if (sysctl(mib, 3, &buffer, &len, NULL, 0) == -1) { 00139 return PAPI_ESYS; 00140 } 00141 00142 hwinfo->cpuid_stepping=buffer[0]; 00143 hwinfo->revision=(float)(hwinfo->cpuid_stepping); 00144 00145 /**********/ 00146 /* Family */ 00147 /**********/ 00148 len = 3; 00149 sysctlnametomib("machdep.cpu.family", mib, &len); 00150 00151 len = BUFSIZ; 00152 if (sysctl(mib, 3, &buffer, &len, NULL, 0) == -1) { 00153 return PAPI_ESYS; 00154 } 00155 00156 hwinfo->cpuid_family=buffer[0]; 00157 00158 /**********/ 00159 /* Model */ 00160 /**********/ 00161 len = 3; 00162 sysctlnametomib("machdep.cpu.model", mib, &len); 00163 00164 len = BUFSIZ; 00165 if (sysctl(mib, 3, &buffer, &len, NULL, 0) == -1) { 00166 return PAPI_ESYS; 00167 } 00168 00169 hwinfo->cpuid_model=buffer[0]; 00170 hwinfo->model=hwinfo->cpuid_model; 00171 00172 /*************/ 00173 /* Frequency */ 00174 /*************/ 00175 len = 2; 00176 sysctlnametomib("hw.cpufrequency_max", mib, &len); 00177 00178 len = 8; 00179 if (sysctl(mib, 2, &ll, &len, NULL, 0) == -1) { 00180 return PAPI_ESYS; 00181 } 00182 00183 hwinfo->cpu_max_mhz=(int)(ll/(1000*1000)); 00184 00185 len = 2; 00186 sysctlnametomib("hw.cpufrequency_min", mib, &len); 00187 00188 len = 8; 00189 if (sysctl(mib, 2, &ll, &len, NULL, 0) == -1) { 00190 return PAPI_ESYS; 00191 } 00192 00193 hwinfo->cpu_min_mhz=(int)(ll/(1000*1000)); 00194 00195 /**********/ 00196 /* ncpu */ 00197 /**********/ 00198 len = 2; 00199 sysctlnametomib("hw.ncpu", mib, &len); 00200 00201 len = BUFSIZ; 00202 if (sysctl(mib, 2, &buffer, &len, NULL, 0) == -1) { 00203 return PAPI_ESYS; 00204 } 00205 00206 hwinfo->totalcpus=buffer[0]; 00207 00208 00209 return PAPI_OK; 00210 } 00211 00212 00213 int 00214 _darwin_get_system_info( papi_mdi_t *mdi ) { 00215 00216 int retval; 00217 00218 char maxargs[PAPI_HUGE_STR_LEN]; 00219 pid_t pid; 00220 00221 int cpuinfo_mhz,sys_min_khz,sys_max_khz; 00222 00223 /* Software info */ 00224 00225 /* Path and args */ 00226 00227 pid = getpid( ); 00228 if ( pid < 0 ) { 00229 PAPIERROR( "getpid() returned < 0" ); 00230 return PAPI_ESYS; 00231 } 00232 mdi->pid = pid; 00233 00234 #if 0 00235 sprintf( maxargs, "/proc/%d/exe", ( int ) pid ); 00236 if ( readlink( maxargs, mdi->exe_info.fullname, PAPI_HUGE_STR_LEN ) < 0 ) { 00237 PAPIERROR( "readlink(%s) returned < 0", maxargs ); 00238 return PAPI_ESYS; 00239 } 00240 00241 /* Careful, basename can modify it's argument */ 00242 00243 strcpy( maxargs, mdi->exe_info.fullname ); 00244 strcpy( mdi->exe_info.address_info.name, basename( maxargs ) ); 00245 00246 SUBDBG( "Executable is %s\n", mdi->exe_info.address_info.name ); 00247 SUBDBG( "Full Executable is %s\n", mdi->exe_info.fullname ); 00248 00249 /* Executable regions, may require reading /proc/pid/maps file */ 00250 00251 retval = _darwin_update_shlib_info( mdi ); 00252 SUBDBG( "Text: Start %p, End %p, length %d\n", 00253 mdi->exe_info.address_info.text_start, 00254 mdi->exe_info.address_info.text_end, 00255 ( int ) ( mdi->exe_info.address_info.text_end - 00256 mdi->exe_info.address_info.text_start ) ); 00257 SUBDBG( "Data: Start %p, End %p, length %d\n", 00258 mdi->exe_info.address_info.data_start, 00259 mdi->exe_info.address_info.data_end, 00260 ( int ) ( mdi->exe_info.address_info.data_end - 00261 mdi->exe_info.address_info.data_start ) ); 00262 SUBDBG( "Bss: Start %p, End %p, length %d\n", 00263 mdi->exe_info.address_info.bss_start, 00264 mdi->exe_info.address_info.bss_end, 00265 ( int ) ( mdi->exe_info.address_info.bss_end - 00266 mdi->exe_info.address_info.bss_start ) ); 00267 #endif 00268 /* PAPI_preload_option information */ 00269 00270 strcpy( mdi->preload_info.lib_preload_env, "LD_PRELOAD" ); 00271 mdi->preload_info.lib_preload_sep = ' '; 00272 strcpy( mdi->preload_info.lib_dir_env, "LD_LIBRARY_PATH" ); 00273 mdi->preload_info.lib_dir_sep = ':'; 00274 00275 /* Hardware info */ 00276 00277 retval = _darwin_get_cpu_info( &mdi->hw_info, &cpuinfo_mhz ); 00278 if ( retval ) { 00279 return retval; 00280 } 00281 00282 /* Set Up Memory */ 00283 00284 retval = _darwin_get_memory_info( &mdi->hw_info, mdi->hw_info.model ); 00285 if ( retval ) 00286 return retval; 00287 00288 SUBDBG( "Found %d %s(%d) %s(%d) CPUs at %d Mhz.\n", 00289 mdi->hw_info.totalcpus, 00290 mdi->hw_info.vendor_string, 00291 mdi->hw_info.vendor, 00292 mdi->hw_info.model_string, 00293 mdi->hw_info.model, 00294 mdi->hw_info.cpu_max_mhz); 00295 00296 /* Get virtualization info */ 00297 mdi->hw_info.virtualized=_darwin_detect_hypervisor(mdi->hw_info.virtual_vendor_string); 00298 00299 return PAPI_OK; 00300 } 00301 00302 int 00303 _papi_hwi_init_os(void) { 00304 00305 int major=0,minor=0,sub=0; 00306 char *ptr; 00307 struct utsname uname_buffer; 00308 00309 /* Initialize the locks */ 00310 _darwin_init_locks(); 00311 00312 /* Get the kernel info */ 00313 uname(&uname_buffer); 00314 00315 SUBDBG("Native kernel version %s\n",uname_buffer.release); 00316 00317 strncpy(_papi_os_info.name,uname_buffer.sysname,PAPI_MAX_STR_LEN); 00318 00319 strncpy(_papi_os_info.version,uname_buffer.release,PAPI_MAX_STR_LEN); 00320 00321 ptr=strtok(_papi_os_info.version,"."); 00322 if (ptr!=NULL) major=atoi(ptr); 00323 00324 ptr=strtok(NULL,"."); 00325 if (ptr!=NULL) minor=atoi(ptr); 00326 00327 ptr=strtok(NULL,"."); 00328 if (ptr!=NULL) sub=atoi(ptr); 00329 00330 // _papi_os_info.os_version=LINUX_VERSION(major,minor,sub); 00331 00332 _papi_os_info.itimer_sig = PAPI_INT_MPX_SIGNAL; 00333 _papi_os_info.itimer_num = PAPI_INT_ITIMER; 00334 _papi_os_info.itimer_ns = PAPI_INT_MPX_DEF_US * 1000; 00335 _papi_os_info.itimer_res_ns = 1; 00336 _papi_os_info.clock_ticks = sysconf( _SC_CLK_TCK ); 00337 00338 /* Get Darwin-specific system info */ 00339 _darwin_get_system_info( &_papi_hwi_system_info ); 00340 00341 return PAPI_OK; 00342 } 00343 00344 00345 static inline long long 00346 get_cycles( void ) 00347 { 00348 long long ret = 0; 00349 #ifdef __x86_64__ 00350 do { 00351 unsigned int a, d; 00352 asm volatile ( "rdtsc":"=a" ( a ), "=d"( d ) ); 00353 ( ret ) = ( ( long long ) a ) | ( ( ( long long ) d ) << 32 ); 00354 } 00355 while ( 0 ); 00356 #else 00357 __asm__ __volatile__( "rdtsc":"=A"( ret ): ); 00358 #endif 00359 return ret; 00360 } 00361 00362 long long 00363 _darwin_get_real_cycles( void ) 00364 { 00365 long long retval; 00366 00367 retval = get_cycles( ); 00368 00369 return retval; 00370 } 00371 00372 00373 long long 00374 _darwin_get_real_usec_gettimeofday( void ) 00375 { 00376 00377 long long retval; 00378 00379 struct timeval buffer; 00380 gettimeofday( &buffer, NULL ); 00381 retval = ( long long ) buffer.tv_sec * ( long long ) 1000000; 00382 retval += ( long long ) ( buffer.tv_usec ); 00383 00384 return retval; 00385 } 00386 00387 00388 long long 00389 _darwin_get_virt_usec_times( void ) 00390 { 00391 00392 long long retval; 00393 00394 struct tms buffer; 00395 00396 times( &buffer ); 00397 00398 SUBDBG( "user %d system %d\n", ( int ) buffer.tms_utime, 00399 ( int ) buffer.tms_stime ); 00400 retval = ( long long ) ( ( buffer.tms_utime + buffer.tms_stime ) * 00401 1000000 / sysconf( _SC_CLK_TCK )); 00402 00403 /* NOT CLOCKS_PER_SEC as in the headers! */ 00404 00405 return retval; 00406 } 00407 00408 00409 00410 00411 00412 papi_os_vector_t _papi_os_vector = { 00413 .get_memory_info = _darwin_get_memory_info, 00414 .get_dmem_info = _darwin_get_dmem_info, 00415 .get_real_cycles = _darwin_get_real_cycles, 00416 .update_shlib_info = _darwin_update_shlib_info, 00417 .get_system_info = _darwin_get_system_info, 00418 00419 .get_real_usec = _darwin_get_real_usec_gettimeofday, 00420 .get_virt_usec = _darwin_get_virt_usec_times, 00421 00422 };