PAPI  5.3.0.0
linux-common.c
Go to the documentation of this file.
00001 /*
00002 * File:    linux-common.c
00003 */
00004 
00005 #include <unistd.h>
00006 #include <string.h>
00007 #include <stdlib.h>
00008 #include <ctype.h>
00009 #include <err.h>
00010 #include <stdarg.h>
00011 #include <stdio.h>
00012 #include <errno.h>
00013 #include <syscall.h>
00014 #include <sys/utsname.h>
00015 #include <sys/time.h>
00016 
00017 #include "papi.h"
00018 #include "papi_internal.h"
00019 #include "papi_vector.h"
00020 
00021 #include "linux-memory.h"
00022 #include "linux-common.h"
00023 #include "linux-timer.h"
00024 
00025 #include "x86_cpuid_info.h"
00026 
00027 PAPI_os_info_t _papi_os_info;
00028 
00029 /* The locks used by Linux */
00030 
00031 #if defined(USE_PTHREAD_MUTEXES)
00032 pthread_mutex_t _papi_hwd_lock_data[PAPI_MAX_LOCK];
00033 #else
00034 volatile unsigned int _papi_hwd_lock_data[PAPI_MAX_LOCK];
00035 #endif
00036 
00037 
00038 static int _linux_init_locks(void) {
00039 
00040    int i;
00041 
00042    for ( i = 0; i < PAPI_MAX_LOCK; i++ ) {
00043 #if defined(USE_PTHREAD_MUTEXES)
00044        pthread_mutex_init(&_papi_hwd_lock_data[i],NULL);
00045 #else
00046        _papi_hwd_lock_data[i] = MUTEX_OPEN;
00047 #endif
00048    }
00049 
00050    return PAPI_OK;
00051 }
00052 
00053     
00054 int
00055 _linux_detect_hypervisor(char *virtual_vendor_name) {
00056 
00057     int retval=0;
00058 
00059 #if defined(__i386__)||defined(__x86_64__)
00060     retval=_x86_detect_hypervisor(virtual_vendor_name);
00061 #else
00062     (void) virtual_vendor_name;
00063 #endif
00064     
00065     return retval;
00066 }
00067 
00068 
00069 #define _PATH_SYS_SYSTEM "/sys/devices/system"
00070 #define _PATH_SYS_CPU0   _PATH_SYS_SYSTEM "/cpu/cpu0"
00071 
00072 static char pathbuf[PATH_MAX] = "/";
00073 
00074 
00075 static char *
00076 search_cpu_info( FILE * f, char *search_str, char *line )
00077 {
00078     /* This function courtesy of Rudolph Berrendorf! */
00079     /* See the home page for the German version of PAPI. */
00080     char *s;
00081 
00082     while ( fgets( line, 256, f ) != NULL ) {
00083         if ( strstr( line, search_str ) != NULL ) {
00084             /* ignore all characters in line up to : */
00085             for ( s = line; *s && ( *s != ':' ); ++s );
00086             if ( *s )
00087                 return s;
00088         }
00089     }
00090     return NULL;
00091 }
00092 
00093 static void
00094 decode_vendor_string( char *s, int *vendor )
00095 {
00096     if ( strcasecmp( s, "GenuineIntel" ) == 0 )
00097         *vendor = PAPI_VENDOR_INTEL;
00098     else if ( ( strcasecmp( s, "AMD" ) == 0 ) ||
00099               ( strcasecmp( s, "AuthenticAMD" ) == 0 ) )
00100         *vendor = PAPI_VENDOR_AMD;
00101     else if ( strcasecmp( s, "IBM" ) == 0 )
00102         *vendor = PAPI_VENDOR_IBM;
00103     else if ( strcasecmp( s, "Cray" ) == 0 )
00104         *vendor = PAPI_VENDOR_CRAY;
00105     else if ( strcasecmp( s, "ARM" ) == 0 )
00106         *vendor = PAPI_VENDOR_ARM;
00107     else if ( strcasecmp( s, "MIPS" ) == 0 )
00108         *vendor = PAPI_VENDOR_MIPS;
00109     else if ( strcasecmp( s, "SiCortex" ) == 0 )
00110         *vendor = PAPI_VENDOR_MIPS;
00111     else
00112         *vendor = PAPI_VENDOR_UNKNOWN;
00113 }
00114 
00115 static FILE *
00116 xfopen( const char *path, const char *mode )
00117 {
00118     FILE *fd = fopen( path, mode );
00119     if ( !fd )
00120         err( EXIT_FAILURE, "error: %s", path );
00121     return fd;
00122 }
00123 
00124 static FILE *
00125 path_vfopen( const char *mode, const char *path, va_list ap )
00126 {
00127     vsnprintf( pathbuf, sizeof ( pathbuf ), path, ap );
00128     return xfopen( pathbuf, mode );
00129 }
00130 
00131 
00132 static int
00133 path_sibling( const char *path, ... )
00134 {
00135     int c;
00136     long n;
00137     int result = 0;
00138     char s[2];
00139     FILE *fp;
00140     va_list ap;
00141     va_start( ap, path );
00142     fp = path_vfopen( "r", path, ap );
00143     va_end( ap );
00144 
00145     while ( ( c = fgetc( fp ) ) != EOF ) {
00146         if ( isxdigit( c ) ) {
00147             s[0] = ( char ) c;
00148             s[1] = '\0';
00149             for ( n = strtol( s, NULL, 16 ); n > 0; n /= 2 ) {
00150                 if ( n % 2 )
00151                     result++;
00152             }
00153         }
00154     }
00155 
00156     fclose( fp );
00157     return result;
00158 }
00159 
00160 static int
00161 path_exist( const char *path, ... )
00162 {
00163     va_list ap;
00164     va_start( ap, path );
00165     vsnprintf( pathbuf, sizeof ( pathbuf ), path, ap );
00166     va_end( ap );
00167     return access( pathbuf, F_OK ) == 0;
00168 }
00169 
00170 int
00171 _linux_get_cpu_info( PAPI_hw_info_t *hwinfo, int *cpuinfo_mhz )
00172 {
00173     int tmp, retval = PAPI_OK;
00174     char maxargs[PAPI_HUGE_STR_LEN], *t, *s;
00175     float mhz = 0.0;
00176     FILE *f;
00177 
00178     if ( ( f = fopen( "/proc/cpuinfo", "r" ) ) == NULL ) {
00179        PAPIERROR( "fopen(/proc/cpuinfo) errno %d", errno );
00180        return PAPI_ESYS;
00181     }
00182 
00183     /* All of this information maybe overwritten by the component */
00184 
00185         /* MHZ */
00186     rewind( f );
00187     s = search_cpu_info( f, "clock", maxargs );
00188     if ( !s ) {
00189        rewind( f );
00190        s = search_cpu_info( f, "cpu MHz", maxargs );
00191     }
00192     if ( s ) {
00193        sscanf( s + 1, "%f", &mhz );
00194     }
00195     *cpuinfo_mhz = mhz;
00196 
00197        /* Vendor Name and Vendor Code */
00198     rewind( f );
00199     s = search_cpu_info( f, "vendor_id", maxargs );
00200     if ( s && ( t = strchr( s + 2, '\n' ) ) ) {
00201        *t = '\0';
00202        strcpy( hwinfo->vendor_string, s + 2 );
00203     } else {
00204        rewind( f );
00205        s = search_cpu_info( f, "vendor", maxargs );
00206        if ( s && ( t = strchr( s + 2, '\n' ) ) ) {
00207       *t = '\0';
00208       strcpy( hwinfo->vendor_string, s + 2 );
00209        } else {
00210       rewind( f );
00211       s = search_cpu_info( f, "system type", maxargs );
00212       if ( s && ( t = strchr( s + 2, '\n' ) ) ) {
00213          *t = '\0';
00214          s = strtok( s + 2, " " );
00215          strcpy( hwinfo->vendor_string, s );
00216       } else {
00217          rewind( f );
00218          s = search_cpu_info( f, "platform", maxargs );
00219          if ( s && ( t = strchr( s + 2, '\n' ) ) ) {
00220         *t = '\0';
00221             s = strtok( s + 2, " " );
00222         if ( ( strcasecmp( s, "pSeries" ) == 0 ) ||
00223              ( strcasecmp( s, "PowerMac" ) == 0 ) ) {
00224            strcpy( hwinfo->vendor_string, "IBM" );
00225         }
00226          } else {
00227         rewind( f );
00228         s = search_cpu_info( f, "CPU implementer", maxargs );
00229         if ( s ) {
00230            strcpy( hwinfo->vendor_string, "ARM" );
00231         }
00232          }
00233       }
00234        }
00235     }
00236 
00237     if ( strlen( hwinfo->vendor_string ) ) {
00238        decode_vendor_string( hwinfo->vendor_string, &hwinfo->vendor );
00239     }
00240 
00241     /* Revision */
00242     rewind( f );
00243     s = search_cpu_info( f, "stepping", maxargs );
00244     if ( s ) {
00245        sscanf( s + 1, "%d", &tmp );
00246        hwinfo->revision = ( float ) tmp;
00247        hwinfo->cpuid_stepping = tmp;
00248     } else {
00249        rewind( f );
00250        s = search_cpu_info( f, "revision", maxargs );
00251        if ( s ) {
00252       sscanf( s + 1, "%d", &tmp );
00253       hwinfo->revision = ( float ) tmp;
00254       hwinfo->cpuid_stepping = tmp;
00255        }
00256     }
00257 
00258        /* Model Name */
00259     rewind( f );
00260     s = search_cpu_info( f, "model name", maxargs );
00261     if ( s && ( t = strchr( s + 2, '\n' ) ) ) {
00262        *t = '\0';
00263        strcpy( hwinfo->model_string, s + 2 );
00264     } else {
00265        rewind( f );
00266        s = search_cpu_info( f, "family", maxargs );
00267        if ( s && ( t = strchr( s + 2, '\n' ) ) ) {
00268       *t = '\0';
00269       strcpy( hwinfo->model_string, s + 2 );
00270        } else {
00271       rewind( f );
00272       s = search_cpu_info( f, "cpu model", maxargs );
00273       if ( s && ( t = strchr( s + 2, '\n' ) ) ) {
00274          *t = '\0';
00275          strtok( s + 2, " " );
00276          s = strtok( NULL, " " );
00277          strcpy( hwinfo->model_string, s );
00278       } else {
00279          rewind( f );
00280          s = search_cpu_info( f, "cpu", maxargs );
00281          if ( s && ( t = strchr( s + 2, '\n' ) ) ) {
00282         *t = '\0';
00283         /* get just the first token */
00284         s = strtok( s + 2, " " );
00285         strcpy( hwinfo->model_string, s );
00286          }
00287       }
00288        }
00289     }
00290 
00291        /* Family */
00292     rewind( f );
00293     s = search_cpu_info( f, "family", maxargs );
00294     if ( s ) {
00295        sscanf( s + 1, "%d", &tmp );
00296        hwinfo->cpuid_family = tmp;
00297     } else {
00298        rewind( f );
00299        s = search_cpu_info( f, "cpu family", maxargs );
00300        if ( s ) {
00301       sscanf( s + 1, "%d", &tmp );
00302       hwinfo->cpuid_family = tmp;
00303     }
00304     }
00305 
00306     /* CPU Model */
00307     rewind( f );
00308     s = search_cpu_info( f, "model", maxargs );
00309     if ( s ) {
00310        sscanf( s + 1, "%d", &tmp );
00311        hwinfo->model = tmp;
00312        hwinfo->cpuid_model = tmp;
00313     }
00314 
00315 
00316     /* The following members are set using the same methodology */
00317     /* used in lscpu.                                           */
00318 
00319     /* Total number of CPUs */
00320     /* The following line assumes totalcpus was initialized to zero! */
00321     while ( path_exist( _PATH_SYS_SYSTEM "/cpu/cpu%d", hwinfo->totalcpus ) )
00322         hwinfo->totalcpus++;
00323 
00324     /* Number of threads per core */
00325     if ( path_exist( _PATH_SYS_CPU0 "/topology/thread_siblings" ) )
00326         hwinfo->threads =
00327             path_sibling( _PATH_SYS_CPU0 "/topology/thread_siblings" );
00328 
00329     /* Number of cores per socket */
00330     if ( path_exist( _PATH_SYS_CPU0 "/topology/core_siblings" ) &&
00331          hwinfo->threads > 0 )
00332         hwinfo->cores =
00333             path_sibling( _PATH_SYS_CPU0 "/topology/core_siblings" ) /
00334             hwinfo->threads;
00335 
00336     /* Number of NUMA nodes */
00337     /* The following line assumes nnodes was initialized to zero! */
00338     while ( path_exist( _PATH_SYS_SYSTEM "/node/node%d", hwinfo->nnodes ) )
00339         hwinfo->nnodes++;
00340 
00341     /* Number of CPUs per node */
00342     hwinfo->ncpu =
00343         hwinfo->nnodes >
00344         1 ? hwinfo->totalcpus / hwinfo->nnodes : hwinfo->totalcpus;
00345 
00346     /* Number of sockets */
00347     if ( hwinfo->threads > 0 && hwinfo->cores > 0 )
00348         hwinfo->sockets = hwinfo->totalcpus / hwinfo->cores / hwinfo->threads;
00349 
00350 #if 0
00351     int *nodecpu;
00352     /* cpumap data is not currently part of the _papi_hw_info struct */
00353         nodecpu = malloc( (unsigned int) hwinfo->nnodes * sizeof(int) );
00354     if ( nodecpu ) {
00355        int i;
00356        for ( i = 0; i < hwinfo->nnodes; ++i ) {
00357            nodecpu[i] = path_sibling( 
00358                              _PATH_SYS_SYSTEM "/node/node%d/cpumap", i );
00359        }
00360     } else {
00361         PAPIERROR( "malloc failed for variable not currently used" );
00362     }
00363 #endif
00364 
00365 
00366     /* Fixup missing Megahertz Value */
00367     /* This is missing from cpuinfo on ARM and MIPS */
00368      if (*cpuinfo_mhz < 1.0) {
00369     rewind( f );
00370 
00371     s = search_cpu_info( f, "BogoMIPS", maxargs );
00372     if ((!s) || (sscanf( s + 1, "%f", &mhz ) != 1)) {
00373        INTDBG("Mhz detection failed. Please edit file %s at line %d.\n",
00374              __FILE__,__LINE__);
00375     }
00376 
00377     if (hwinfo->vendor == PAPI_VENDOR_MIPS) {
00378         /* MIPS has 2x clock multiplier */
00379         *cpuinfo_mhz = 2*(((int)mhz)+1);
00380 
00381         /* Also update version info on MIPS */
00382         rewind( f );
00383         s = search_cpu_info( f, "cpu model", maxargs );
00384         s = strstr(s+1," V")+2;
00385          strtok(s," ");
00386         sscanf(s, "%f ", &hwinfo->revision );
00387     }
00388     else {
00389         /* In general bogomips is proportional to number of CPUs */
00390         if (hwinfo->totalcpus) {
00391            if (mhz!=0) *cpuinfo_mhz = mhz / hwinfo->totalcpus;
00392         }
00393     }
00394      }
00395 
00396     fclose( f );
00397 
00398     return retval;
00399 }
00400 
00401 int
00402 _linux_get_mhz( int *sys_min_mhz, int *sys_max_mhz ) {
00403 
00404   FILE *fff;
00405   int result;
00406 
00407   /* Try checking for min MHz */
00408   /* Assume cpu0 exists */
00409   fff=fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq","r");
00410   if (fff==NULL) return PAPI_EINVAL;
00411   result=fscanf(fff,"%d",sys_min_mhz);
00412   fclose(fff);
00413   if (result!=1) return PAPI_EINVAL;
00414 
00415   fff=fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq","r");
00416   if (fff==NULL) return PAPI_EINVAL;
00417   result=fscanf(fff,"%d",sys_max_mhz);
00418   fclose(fff);
00419   if (result!=1) return PAPI_EINVAL;
00420 
00421   return PAPI_OK;
00422 
00423 }
00424 
00425 int
00426 _linux_get_system_info( papi_mdi_t *mdi ) {
00427 
00428     int retval;
00429 
00430     char maxargs[PAPI_HUGE_STR_LEN];
00431     pid_t pid;
00432 
00433     int cpuinfo_mhz,sys_min_khz,sys_max_khz;
00434 
00435     /* Software info */
00436 
00437     /* Path and args */
00438 
00439     pid = getpid(  );
00440     if ( pid < 0 ) {
00441         PAPIERROR( "getpid() returned < 0" );
00442         return PAPI_ESYS;
00443     }
00444     mdi->pid = pid;
00445 
00446     sprintf( maxargs, "/proc/%d/exe", ( int ) pid );
00447     if ( readlink( maxargs, mdi->exe_info.fullname, PAPI_HUGE_STR_LEN ) < 0 ) {
00448         PAPIERROR( "readlink(%s) returned < 0", maxargs );
00449         return PAPI_ESYS;
00450     }
00451 
00452     /* Careful, basename can modify it's argument */
00453 
00454     strcpy( maxargs, mdi->exe_info.fullname );
00455     strcpy( mdi->exe_info.address_info.name, basename( maxargs ) );
00456 
00457     SUBDBG( "Executable is %s\n", mdi->exe_info.address_info.name );
00458     SUBDBG( "Full Executable is %s\n", mdi->exe_info.fullname );
00459 
00460     /* Executable regions, may require reading /proc/pid/maps file */
00461 
00462     retval = _linux_update_shlib_info( mdi );
00463     SUBDBG( "Text: Start %p, End %p, length %d\n",
00464             mdi->exe_info.address_info.text_start,
00465             mdi->exe_info.address_info.text_end,
00466             ( int ) ( mdi->exe_info.address_info.text_end -
00467                       mdi->exe_info.address_info.text_start ) );
00468     SUBDBG( "Data: Start %p, End %p, length %d\n",
00469             mdi->exe_info.address_info.data_start,
00470             mdi->exe_info.address_info.data_end,
00471             ( int ) ( mdi->exe_info.address_info.data_end -
00472                       mdi->exe_info.address_info.data_start ) );
00473     SUBDBG( "Bss: Start %p, End %p, length %d\n",
00474             mdi->exe_info.address_info.bss_start,
00475             mdi->exe_info.address_info.bss_end,
00476             ( int ) ( mdi->exe_info.address_info.bss_end -
00477                       mdi->exe_info.address_info.bss_start ) );
00478 
00479     /* PAPI_preload_option information */
00480 
00481     strcpy( mdi->preload_info.lib_preload_env, "LD_PRELOAD" );
00482     mdi->preload_info.lib_preload_sep = ' ';
00483     strcpy( mdi->preload_info.lib_dir_env, "LD_LIBRARY_PATH" );
00484     mdi->preload_info.lib_dir_sep = ':';
00485 
00486     /* Hardware info */
00487 
00488     retval = _linux_get_cpu_info( &mdi->hw_info, &cpuinfo_mhz );
00489     if ( retval )
00490         return retval;
00491 
00492     /* Handle MHz */
00493 
00494     retval = _linux_get_mhz( &sys_min_khz, &sys_max_khz );
00495     if ( retval ) {
00496 
00497        mdi->hw_info.cpu_max_mhz=cpuinfo_mhz;
00498        mdi->hw_info.cpu_min_mhz=cpuinfo_mhz;
00499 
00500        /*
00501        mdi->hw_info.mhz=cpuinfo_mhz;
00502        mdi->hw_info.clock_mhz=cpuinfo_mhz;
00503        */
00504     }
00505     else {
00506        mdi->hw_info.cpu_max_mhz=sys_max_khz/1000;
00507        mdi->hw_info.cpu_min_mhz=sys_min_khz/1000;
00508 
00509        /*
00510        mdi->hw_info.mhz=sys_max_khz/1000;
00511        mdi->hw_info.clock_mhz=sys_max_khz/1000;
00512        */
00513     }
00514 
00515     /* Set Up Memory */
00516 
00517     retval = _linux_get_memory_info( &mdi->hw_info, mdi->hw_info.model );
00518     if ( retval )
00519         return retval;
00520 
00521     SUBDBG( "Found %d %s(%d) %s(%d) CPUs at %d Mhz.\n",
00522             mdi->hw_info.totalcpus,
00523             mdi->hw_info.vendor_string,
00524             mdi->hw_info.vendor, 
00525                 mdi->hw_info.model_string, 
00526                 mdi->hw_info.model,
00527                 mdi->hw_info.cpu_max_mhz);
00528 
00529     /* Get virtualization info */
00530     mdi->hw_info.virtualized=_linux_detect_hypervisor(mdi->hw_info.virtual_vendor_string);
00531 
00532     return PAPI_OK;
00533 }
00534 
00535 int 
00536 _papi_hwi_init_os(void) {
00537 
00538     int major=0,minor=0,sub=0;
00539     char *ptr;
00540     struct utsname uname_buffer;
00541 
00542     /* Initialize the locks */
00543     _linux_init_locks();
00544 
00545     /* Get the kernel info */
00546     uname(&uname_buffer);
00547 
00548     SUBDBG("Native kernel version %s\n",uname_buffer.release);
00549 
00550     strncpy(_papi_os_info.name,uname_buffer.sysname,PAPI_MAX_STR_LEN);
00551 
00552 #ifdef ASSUME_KERNEL
00553     strncpy(_papi_os_info.version,ASSUME_KERNEL,PAPI_MAX_STR_LEN);
00554     SUBDBG("Assuming kernel version %s\n",_papi_os_info.name);
00555 #else
00556     strncpy(_papi_os_info.version,uname_buffer.release,PAPI_MAX_STR_LEN);
00557 #endif
00558 
00559     ptr=strtok(_papi_os_info.version,".");
00560     if (ptr!=NULL) major=atoi(ptr);
00561 
00562     ptr=strtok(NULL,".");
00563     if (ptr!=NULL) minor=atoi(ptr);
00564 
00565     ptr=strtok(NULL,".");
00566     if (ptr!=NULL) sub=atoi(ptr);
00567 
00568    _papi_os_info.os_version=LINUX_VERSION(major,minor,sub);
00569 
00570    _papi_os_info.itimer_sig = PAPI_INT_MPX_SIGNAL;
00571    _papi_os_info.itimer_num = PAPI_INT_ITIMER;
00572    _papi_os_info.itimer_ns = PAPI_INT_MPX_DEF_US * 1000;
00573    _papi_os_info.itimer_res_ns = 1;
00574    _papi_os_info.clock_ticks = sysconf( _SC_CLK_TCK );
00575 
00576    /* Get Linux-specific system info */
00577    _linux_get_system_info( &_papi_hwi_system_info );
00578 
00579    return PAPI_OK;
00580 }
00581 
00582 
00583 
00584 int _linux_detect_nmi_watchdog() {
00585 
00586   int watchdog_detected=0,watchdog_value=0;
00587   FILE *fff;
00588 
00589   fff=fopen("/proc/sys/kernel/nmi_watchdog","r");
00590   if (fff!=NULL) {
00591      if (fscanf(fff,"%d",&watchdog_value)==1) {
00592         if (watchdog_value>0) watchdog_detected=1;
00593      }
00594      fclose(fff);
00595   }
00596 
00597   return watchdog_detected;
00598 }
00599 
00600 papi_os_vector_t _papi_os_vector = {
00601   .get_memory_info =   _linux_get_memory_info,
00602   .get_dmem_info =     _linux_get_dmem_info,
00603   .get_real_cycles =   _linux_get_real_cycles,
00604   .update_shlib_info = _linux_update_shlib_info,
00605   .get_system_info =   _linux_get_system_info,
00606 
00607 
00608 #if defined(HAVE_CLOCK_GETTIME)
00609   .get_real_usec =  _linux_get_real_usec_gettime,
00610 #elif defined(HAVE_GETTIMEOFDAY)
00611   .get_real_usec =  _linux_get_real_usec_gettimeofday,
00612 #else
00613   .get_real_usec =  _linux_get_real_usec_cycles,
00614 #endif
00615 
00616 
00617 #if defined(USE_PROC_PTTIMER)
00618   .get_virt_usec =   _linux_get_virt_usec_pttimer,
00619 #elif defined(HAVE_CLOCK_GETTIME_THREAD)
00620   .get_virt_usec =   _linux_get_virt_usec_gettime,
00621 #elif defined(HAVE_PER_THREAD_TIMES)
00622   .get_virt_usec =   _linux_get_virt_usec_times,
00623 #elif defined(HAVE_PER_THREAD_GETRUSAGE)
00624   .get_virt_usec =   _linux_get_virt_usec_rusage,
00625 #endif
00626 
00627 
00628 #if defined(HAVE_CLOCK_GETTIME)
00629   .get_real_nsec =  _linux_get_real_nsec_gettime,
00630 #endif
00631 
00632 #if defined(HAVE_CLOCK_GETTIME_THREAD)
00633   .get_virt_nsec =   _linux_get_virt_nsec_gettime,
00634 #endif
00635 
00636 
00637 };
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines