PAPI  5.1.0.2
linux-rapl.c
Go to the documentation of this file.
00001 
00016 #include <stdio.h>
00017 #include <unistd.h>
00018 #include <dirent.h>
00019 #include <fcntl.h>
00020 #include <string.h>
00021 #include <stdint.h>
00022 
00023 /* Headers required by PAPI */
00024 #include "papi.h"
00025 #include "papi_internal.h"
00026 #include "papi_vector.h"
00027 #include "papi_memory.h"
00028 
00029 
00030 /*
00031  * Platform specific RAPL Domains.
00032  * Note that PP1 RAPL Domain is supported on 062A only
00033  * And DRAM RAPL Domain is supported on 062D only
00034  */
00035 
00036 
00037 /* RAPL defines */
00038 #define MSR_RAPL_POWER_UNIT             0x606
00039 
00040 /* Package */
00041 #define MSR_PKG_RAPL_POWER_LIMIT        0x610
00042 #define MSR_PKG_ENERGY_STATUS           0x611
00043 #define MSR_PKG_PERF_STATUS             0x613
00044 #define MSR_PKG_POWER_INFO              0x614
00045 
00046 /* PP0 */
00047 #define MSR_PP0_POWER_LIMIT             0x638
00048 #define MSR_PP0_ENERGY_STATUS           0x639
00049 #define MSR_PP0_POLICY                  0x63A
00050 #define MSR_PP0_PERF_STATUS             0x63B
00051 
00052 /* PP1 */
00053 #define MSR_PP1_POWER_LIMIT             0x640
00054 #define MSR_PP1_ENERGY_STATUS           0x641
00055 #define MSR_PP1_POLICY                  0x642
00056 
00057 /* DRAM */
00058 #define MSR_DRAM_POWER_LIMIT            0x618
00059 #define MSR_DRAM_ENERGY_STATUS          0x619
00060 #define MSR_DRAM_PERF_STATUS            0x61B
00061 #define MSR_DRAM_POWER_INFO             0x61C
00062 
00063 /* RAPL bitsmasks */
00064 #define POWER_UNIT_OFFSET          0
00065 #define POWER_UNIT_MASK         0x0f
00066 
00067 #define ENERGY_UNIT_OFFSET      0x08
00068 #define ENERGY_UNIT_MASK        0x1f
00069 
00070 #define TIME_UNIT_OFFSET        0x10
00071 #define TIME_UNIT_MASK          0x0f
00072 
00073 /* RAPL POWER UNIT MASKS */
00074 #define POWER_INFO_UNIT_MASK     0x7fff
00075 #define THERMAL_SHIFT                 0
00076 #define MINIMUM_POWER_SHIFT          16
00077 #define MAXIMUM_POWER_SHIFT          32
00078 #define MAXIMUM_TIME_WINDOW_SHIFT    48
00079 
00080 
00081 typedef struct _rapl_register
00082 {
00083     unsigned int selector;
00084 } _rapl_register_t;
00085 
00086 typedef struct _rapl_native_event_entry
00087 {
00088   char name[PAPI_MAX_STR_LEN];
00089   char units[PAPI_MIN_STR_LEN];
00090   char description[PAPI_MAX_STR_LEN];
00091   int fd_offset;
00092   int msr;
00093   int type;
00094   int return_type;
00095   _rapl_register_t resources;
00096 } _rapl_native_event_entry_t;
00097 
00098 typedef struct _rapl_reg_alloc
00099 {
00100     _rapl_register_t ra_bits;
00101 } _rapl_reg_alloc_t;
00102 
00103 /* actually 32?  But setting this to be safe? */
00104 #define RAPL_MAX_COUNTERS 64
00105 
00106 typedef struct _rapl_control_state
00107 {
00108   int being_measured[RAPL_MAX_COUNTERS];
00109   long long count[RAPL_MAX_COUNTERS];
00110   int need_difference[RAPL_MAX_COUNTERS];
00111   long long lastupdate;
00112 } _rapl_control_state_t;
00113 
00114 
00115 typedef struct _rapl_context
00116 {
00117   long long start_count[RAPL_MAX_COUNTERS];
00118   _rapl_control_state_t state;
00119 } _rapl_context_t;
00120 
00121 
00122 papi_vector_t _rapl_vector;
00123 
00124 struct fd_array_t {
00125   int fd;
00126   int open;
00127 };
00128 
00129 static _rapl_native_event_entry_t * rapl_native_events=NULL;
00130 static int num_events       = 0;
00131 struct fd_array_t *fd_array=NULL;
00132 static int num_packages=0,num_cpus=0;
00133 
00134 int power_divisor,energy_divisor,time_divisor;
00135 
00136 
00137 #define PACKAGE_ENERGY      0
00138 #define PACKAGE_THERMAL     1
00139 #define PACKAGE_MINIMUM     2
00140 #define PACKAGE_MAXIMUM     3
00141 #define PACKAGE_TIME_WINDOW 4
00142 
00143 
00144 /***************************************************************************/
00145 /******  BEGIN FUNCTIONS  USED INTERNALLY SPECIFIC TO THIS COMPONENT *******/
00146 /***************************************************************************/
00147 
00148 
00149 static long long read_msr(int fd, int which) {
00150 
00151   uint64_t data;
00152 
00153   if ( fd<0 || pread(fd, &data, sizeof data, which) != sizeof data ) {
00154     perror("rdmsr:pread");
00155     exit(127);
00156   }
00157 
00158   return (long long)data;
00159 }
00160 
00161 static int open_fd(int offset) {
00162   
00163   int fd=-1;
00164   char filename[BUFSIZ];
00165 
00166   if (fd_array[offset].open==0) {
00167      sprintf(filename,"/dev/cpu/%d/msr",offset);
00168      fd = open(filename, O_RDONLY);
00169      if (fd>=0) {
00170         fd_array[offset].fd=fd;
00171     fd_array[offset].open=1;
00172      }
00173   }
00174   else {
00175     fd=fd_array[offset].fd;
00176   }
00177 
00178   return fd;
00179 }
00180 
00181 static long long read_rapl_energy(int index) {
00182        
00183    int fd;
00184    long long result;
00185 
00186    union {
00187       long long ll;
00188       double fp;
00189    } return_val;
00190 
00191    return_val.ll = 0; /* initialize to satisfy compiler */
00192    fd=open_fd(rapl_native_events[index].fd_offset);
00193    result=read_msr(fd,rapl_native_events[index].msr);
00194 
00195    if (rapl_native_events[index].type==PACKAGE_ENERGY) {
00196 
00197       return_val.ll = (long long)(((double)result/energy_divisor)*1e9);
00198    }
00199 
00200    if (rapl_native_events[index].type==PACKAGE_THERMAL) {
00201       return_val.fp = (double)
00202                       ((result>>THERMAL_SHIFT)&POWER_INFO_UNIT_MASK) /
00203                        (double)power_divisor;
00204    }
00205 
00206    if (rapl_native_events[index].type==PACKAGE_MINIMUM) {
00207        return_val.fp = (double)
00208                        ((result>>MINIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK)/
00209                         (double)power_divisor;
00210    }
00211 
00212    if (rapl_native_events[index].type==PACKAGE_MAXIMUM) {
00213       return_val.fp = (double)
00214                       ((result>>MAXIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK)/
00215                        (double)power_divisor;
00216    }
00217 
00218    if (rapl_native_events[index].type==PACKAGE_TIME_WINDOW) {
00219       return_val.fp =  (double)
00220                     ((result>>MAXIMUM_TIME_WINDOW_SHIFT)&POWER_INFO_UNIT_MASK)/
00221                      (double)time_divisor;
00222    }
00223 
00224    return return_val.ll;
00225 
00226 }
00227 
00228 static int
00229 get_kernel_nr_cpus()
00230 {
00231   FILE *fff;
00232   int num_read, nr_cpus = 1;
00233   fff=fopen("/sys/devices/system/cpu/kernel_max","r");
00234   if (fff==NULL) return nr_cpus;
00235   num_read=fscanf(fff,"%d",&nr_cpus);
00236   fclose(fff);
00237   if (num_read==1) {
00238     nr_cpus++;
00239   } else {
00240     nr_cpus = 1;
00241   }
00242   return nr_cpus;
00243 }
00244 
00245 /************************* PAPI Functions **********************************/
00246 
00247 
00248 /*
00249  * This is called whenever a thread is initialized
00250  */
00251 int 
00252 _rapl_init_thread( hwd_context_t *ctx )
00253 {
00254   ( void ) ctx;
00255 
00256   return PAPI_OK;
00257 }
00258 
00259 
00260 
00261 /* 
00262  * Called when PAPI process is initialized (i.e. PAPI_library_init)
00263  */
00264 int 
00265 _rapl_init_component( int cidx )
00266 {
00267      int i,j,fd;
00268      FILE *fff;
00269      char filename[BUFSIZ];
00270 
00271      int package_avail, dram_avail, pp0_avail, pp1_avail;
00272 
00273      long long result;
00274      int package;
00275 
00276      const PAPI_hw_info_t *hw_info;
00277 
00278      int nr_cpus = get_kernel_nr_cpus();
00279      int packages[nr_cpus];
00280      int cpu_to_use[nr_cpus];
00281 
00282      /* Fill with sentinel values */
00283      for (i=0; i<nr_cpus; ++i) {
00284        packages[i] = -1;
00285        cpu_to_use[i] = -1;
00286      }
00287 
00288 
00289      /* check if Intel processor */
00290      hw_info=&(_papi_hwi_system_info.hw_info);
00291 
00292      /* Ugh can't use PAPI_get_hardware_info() if 
00293     PAPI library not done initializing yet */
00294 
00295      if (hw_info->vendor!=PAPI_VENDOR_INTEL) {
00296         strncpy(_rapl_vector.cmp_info.disabled_reason,
00297         "Not an Intel processor",PAPI_MAX_STR_LEN);
00298         return PAPI_ENOSUPP;
00299      }
00300 
00301      /* check if SandyBridge */
00302 
00303      if (hw_info->cpuid_family==6) {
00304        if (hw_info->cpuid_model==42) {
00305       /* SandyBridge */
00306           package_avail=1;
00307           pp0_avail=1;
00308           pp1_avail=1;
00309           dram_avail=0;
00310        }
00311        else if (hw_info->cpuid_model==45) {
00312       /* SandyBridge-EP */
00313           package_avail=1;
00314           pp0_avail=1;
00315           pp1_avail=0;
00316           dram_avail=1;
00317        }
00318        else if (hw_info->cpuid_model==58) {
00319       /* IvyBridge */
00320           package_avail=1;
00321           pp0_avail=1;
00322           pp1_avail=1;
00323           dram_avail=0;
00324        }    
00325        else {
00326      /* not a supported model */
00327      strncpy(_rapl_vector.cmp_info.disabled_reason,
00328          "Not a SandyBridge processor",
00329          PAPI_MAX_STR_LEN);
00330      return PAPI_ENOIMPL;
00331        }
00332      }
00333      else {
00334        /* Not a family 6 machine */
00335        strncpy(_rapl_vector.cmp_info.disabled_reason,
00336            "Not a SandyBridge processor",PAPI_MAX_STR_LEN);
00337        return PAPI_ENOIMPL;
00338      }
00339 
00340 
00341      /* Detect how many packages */
00342      j=0;
00343      while(1) {
00344        int num_read;
00345 
00346        sprintf(filename,
00347            "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",j);
00348        fff=fopen(filename,"r");
00349        if (fff==NULL) break;
00350        num_read=fscanf(fff,"%d",&package);
00351        fclose(fff);
00352        if (num_read!=1) {
00353       fprintf(stderr,"error reading %s\n",filename);
00354        }
00355 
00356        /* Check if a new package */
00357        if (package < nr_cpus) {
00358          if (packages[package] == -1) {
00359            SUBDBG("Found package %d out of total %d\n",package,num_packages);
00360        packages[package]=package;
00361        cpu_to_use[package]=j;
00362        num_packages++;
00363          }
00364        } else {
00365      SUBDBG("Package outside of allowed range\n");
00366      strncpy(_rapl_vector.cmp_info.disabled_reason,
00367         "Package outside of allowed range",PAPI_MAX_STR_LEN);
00368      return PAPI_ESYS;
00369        }
00370 
00371        j++;
00372      }
00373      num_cpus=j;
00374 
00375      if (num_packages==0) {
00376         SUBDBG("Can't access /dev/cpu/*/msr\n");
00377     strncpy(_rapl_vector.cmp_info.disabled_reason,
00378         "Can't access /dev/cpu/*/msr",PAPI_MAX_STR_LEN);
00379     return PAPI_ESYS;
00380      }
00381 
00382      SUBDBG("Found %d packages with %d cpus\n",num_packages,num_cpus);
00383 
00384      /* Init fd_array */
00385 
00386      fd_array=papi_calloc(sizeof(struct fd_array_t),num_cpus);
00387      if (fd_array==NULL) return PAPI_ENOMEM;
00388 
00389      fd=open_fd(cpu_to_use[0]);
00390      if (fd<0) {
00391         strncpy(_rapl_vector.cmp_info.disabled_reason,
00392         "Can't open fd for cpu0",PAPI_MAX_STR_LEN);
00393         return PAPI_ESYS;
00394      }
00395 
00396      /* Calculate the units used */
00397      result=read_msr(fd,MSR_RAPL_POWER_UNIT);
00398   
00399      /* units are 0.5^UNIT_VALUE */
00400      /* which is the same as 1/(2^UNIT_VALUE) */
00401 
00402      power_divisor=1<<((result>>POWER_UNIT_OFFSET)&POWER_UNIT_MASK);
00403      energy_divisor=1<<((result>>ENERGY_UNIT_OFFSET)&ENERGY_UNIT_MASK);
00404      time_divisor=1<<((result>>TIME_UNIT_OFFSET)&TIME_UNIT_MASK);
00405 
00406      SUBDBG("Power units = %.3fW\n",1.0/power_divisor);
00407      SUBDBG("Energy units = %.8fJ\n",1.0/energy_divisor);
00408      SUBDBG("Time units = %.8fs\n",1.0/time_divisor);
00409 
00410 
00411      /* Allocate space for events */
00412 
00413      num_events= (package_avail*num_packages) +
00414                  (pp0_avail*num_packages) +
00415                  (pp1_avail*num_packages) +
00416                  (dram_avail*num_packages) + 
00417                  (4*num_packages);
00418 
00419      rapl_native_events = (_rapl_native_event_entry_t*)
00420           papi_calloc(sizeof(_rapl_native_event_entry_t),num_events);
00421 
00422 
00423      i=0;
00424 
00425      /* Create events for  package power info */
00426 
00427      for(j=0;j<num_packages;j++) {
00428     sprintf(rapl_native_events[i].name,
00429         "THERMAL_SPEC:PACKAGE%d",j);
00430     strncpy(rapl_native_events[i].units,"W",PAPI_MIN_STR_LEN);
00431     sprintf(rapl_native_events[i].description,
00432            "Thermal specification package %d",j);
00433     rapl_native_events[i].fd_offset=cpu_to_use[j];
00434     rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
00435     rapl_native_events[i].resources.selector = i + 1;
00436     rapl_native_events[i].type=PACKAGE_THERMAL;
00437     rapl_native_events[i].return_type=PAPI_DATATYPE_FP64;
00438     i++;
00439      }
00440 
00441      for(j=0;j<num_packages;j++) {
00442     sprintf(rapl_native_events[i].name,
00443         "MINIMUM_POWER:PACKAGE%d",j);
00444     strncpy(rapl_native_events[i].units,"W",PAPI_MIN_STR_LEN);
00445     sprintf(rapl_native_events[i].description,
00446            "Minimum power for package %d",j);
00447     rapl_native_events[i].fd_offset=cpu_to_use[j];
00448     rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
00449     rapl_native_events[i].resources.selector = i + 1;
00450     rapl_native_events[i].type=PACKAGE_MINIMUM;
00451     rapl_native_events[i].return_type=PAPI_DATATYPE_FP64;
00452 
00453     i++;
00454      }
00455 
00456      for(j=0;j<num_packages;j++) {
00457     sprintf(rapl_native_events[i].name,
00458         "MAXIMUM_POWER:PACKAGE%d",j);
00459     strncpy(rapl_native_events[i].units,"W",PAPI_MIN_STR_LEN);
00460     sprintf(rapl_native_events[i].description,
00461            "Maximum power for package %d",j);
00462     rapl_native_events[i].fd_offset=cpu_to_use[j];
00463     rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
00464     rapl_native_events[i].resources.selector = i + 1;
00465     rapl_native_events[i].type=PACKAGE_MAXIMUM;
00466     rapl_native_events[i].return_type=PAPI_DATATYPE_FP64;
00467 
00468     i++;
00469      }
00470 
00471      for(j=0;j<num_packages;j++) {
00472     sprintf(rapl_native_events[i].name,
00473         "MAXIMUM_TIME_WINDOW:PACKAGE%d",j);
00474     strncpy(rapl_native_events[i].units,"s",PAPI_MIN_STR_LEN);
00475     sprintf(rapl_native_events[i].description,
00476            "Maximum time window for package %d",j);
00477     rapl_native_events[i].fd_offset=cpu_to_use[j];
00478     rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
00479     rapl_native_events[i].resources.selector = i + 1;
00480     rapl_native_events[i].type=PACKAGE_TIME_WINDOW;
00481     rapl_native_events[i].return_type=PAPI_DATATYPE_FP64;
00482 
00483     i++;
00484      }
00485 
00486      /* Create Events for energy measurements */
00487 
00488      if (package_avail) {
00489         for(j=0;j<num_packages;j++) {
00490        sprintf(rapl_native_events[i].name,
00491            "PACKAGE_ENERGY:PACKAGE%d",j);
00492        strncpy(rapl_native_events[i].units,"nJ",PAPI_MIN_STR_LEN);
00493        sprintf(rapl_native_events[i].description,
00494            "Energy used by chip package %d",j);
00495        rapl_native_events[i].fd_offset=cpu_to_use[j];
00496        rapl_native_events[i].msr=MSR_PKG_ENERGY_STATUS;
00497        rapl_native_events[i].resources.selector = i + 1;
00498        rapl_native_events[i].type=PACKAGE_ENERGY;
00499        rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
00500 
00501        i++;
00502     }
00503      }
00504 
00505      if (pp1_avail) {
00506         for(j=0;j<num_packages;j++) {
00507        sprintf(rapl_native_events[i].name,
00508            "PP1_ENERGY:PACKAGE%d",j);
00509        strncpy(rapl_native_events[i].units,"nJ",PAPI_MIN_STR_LEN);
00510        sprintf(rapl_native_events[i].description,
00511            "Energy used by Power Plane 1 (Often GPU) on package %d",j);
00512            rapl_native_events[i].fd_offset=cpu_to_use[j];
00513        rapl_native_events[i].msr=MSR_PP1_ENERGY_STATUS;
00514        rapl_native_events[i].resources.selector = i + 1;
00515        rapl_native_events[i].type=PACKAGE_ENERGY;
00516        rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
00517 
00518        i++;
00519     }
00520      }
00521 
00522      if (dram_avail) {
00523         for(j=0;j<num_packages;j++) {
00524        sprintf(rapl_native_events[i].name,
00525            "DRAM_ENERGY:PACKAGE%d",j);
00526        strncpy(rapl_native_events[i].units,"nJ",PAPI_MIN_STR_LEN);
00527            sprintf(rapl_native_events[i].description,
00528            "Energy used by DRAM on package %d",j);
00529        rapl_native_events[i].fd_offset=cpu_to_use[j];
00530        rapl_native_events[i].msr=MSR_DRAM_ENERGY_STATUS;
00531        rapl_native_events[i].resources.selector = i + 1;
00532        rapl_native_events[i].type=PACKAGE_ENERGY;
00533        rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
00534 
00535        i++;
00536     }
00537      }
00538 
00539      if (pp0_avail) {
00540         for(j=0;j<num_packages;j++) {
00541 
00542            sprintf(rapl_native_events[i].name,
00543            "PP0_ENERGY:PACKAGE%d",j);
00544        strncpy(rapl_native_events[i].units,"nJ",PAPI_MIN_STR_LEN);
00545        sprintf(rapl_native_events[i].description,
00546            "Energy used by all cores in package %d",j);
00547        rapl_native_events[i].fd_offset=cpu_to_use[j];
00548        rapl_native_events[i].msr=MSR_PP0_ENERGY_STATUS;
00549        rapl_native_events[i].resources.selector = i + 1;
00550        rapl_native_events[i].type=PACKAGE_ENERGY;
00551        rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
00552 
00553        i++;
00554     }
00555      }
00556 
00557      /* Export the total number of events available */
00558      _rapl_vector.cmp_info.num_native_events = num_events;
00559 
00560      _rapl_vector.cmp_info.num_cntrs = num_events;
00561      _rapl_vector.cmp_info.num_mpx_cntrs = num_events;
00562 
00563 
00564      /* Export the component id */
00565      _rapl_vector.cmp_info.CmpIdx = cidx;
00566 
00567      return PAPI_OK;
00568 }
00569 
00570 
00571 /*
00572  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
00573  * functions
00574  */
00575 int 
00576 _rapl_init_control_state( hwd_control_state_t *ctl)
00577 {
00578 
00579   _rapl_control_state_t* control = (_rapl_control_state_t*) ctl;
00580   int i;
00581   
00582   for(i=0;i<RAPL_MAX_COUNTERS;i++) {
00583      control->being_measured[i]=0;
00584   }
00585 
00586   return PAPI_OK;
00587 }
00588 
00589 int 
00590 _rapl_start( hwd_context_t *ctx, hwd_control_state_t *ctl)
00591 {
00592   _rapl_context_t* context = (_rapl_context_t*) ctx;
00593   _rapl_control_state_t* control = (_rapl_control_state_t*) ctl;
00594   long long now = PAPI_get_real_usec();
00595   int i;
00596 
00597   for( i = 0; i < RAPL_MAX_COUNTERS; i++ ) {
00598      if ((control->being_measured[i]) && (control->need_difference[i])) {
00599         context->start_count[i]=read_rapl_energy(i);
00600      }
00601   }
00602 
00603   control->lastupdate = now;
00604 
00605   return PAPI_OK;
00606 }
00607 
00608 int 
00609 _rapl_read( hwd_context_t *ctx, hwd_control_state_t *ctl,
00610         long long **events, int flags)
00611 {
00612     (void) flags;
00613     (void) events;
00614 
00615     _rapl_context_t* context = (_rapl_context_t*) ctx;
00616     _rapl_control_state_t* control = (_rapl_control_state_t*) ctl;
00617     long long now = PAPI_get_real_usec();
00618     int i;
00619     long long temp;
00620 
00621     /* Only read the values from the kernel if enough time has passed */
00622     /* since the last read.  Otherwise return cached values.          */
00623 
00624     if ( now - control->lastupdate > 60000000 ) {
00625        printf("Warning!  Over 60s since last read, potential overflow!\n");
00626     }
00627 
00628     for( i = 0; i < RAPL_MAX_COUNTERS; i++ ) {
00629        if (control->being_measured[i]) {
00630 
00631       if (control->need_difference[i]) {
00632 
00633          temp=read_rapl_energy(i);
00634          control->count[i]=temp - context->start_count[i];
00635          /* overflow */
00636          if (control->count[i] < 0 ) {
00637             printf("Error! overflow!\n");
00638          }
00639       }
00640       else {
00641          control->count[i]=read_rapl_energy(i);
00642       }
00643 
00644        }
00645     }
00646     
00647     control->lastupdate = now;
00648     
00649     /* Pass back a pointer to our results */
00650     *events = control->count;
00651 
00652     return PAPI_OK;
00653 }
00654 
00655 int 
00656 _rapl_stop( hwd_context_t *ctx, hwd_control_state_t *ctl )
00657 {
00658 
00659     /* read values */
00660     _rapl_context_t* context = (_rapl_context_t*) ctx;
00661     _rapl_control_state_t* control = (_rapl_control_state_t*) ctl;
00662     long long now = PAPI_get_real_usec();
00663     int i;
00664     long long temp;
00665 
00666 
00667     if ( now - control->lastupdate > 60000000 ) {
00668        printf("Warning!  Over 60s since last read, potential overflow!\n");
00669     }
00670 
00671     for( i = 0; i < RAPL_MAX_COUNTERS; i++ ) {
00672        if (control->being_measured[i]) {
00673 
00674       if (control->need_difference[i]) {
00675 
00676          temp=read_rapl_energy(i);
00677          control->count[i]=temp - context->start_count[i];
00678          /* overflow */
00679          if (control->count[i] < 0 ) {
00680             printf("Error! overflow!\n");
00681          }
00682 
00683       }
00684       else {
00685          control->count[i]=read_rapl_energy(i);
00686       }
00687        }
00688     }
00689     
00690     control->lastupdate = now;
00691 
00692     return PAPI_OK;
00693 }
00694 
00695 /* Shutdown a thread */
00696 int
00697 _rapl_shutdown_thread( hwd_context_t *ctx )
00698 {
00699   ( void ) ctx;
00700   return PAPI_OK;
00701 }
00702 
00703 
00704 /*
00705  * Clean up what was setup in  rapl_init_component().
00706  */
00707 int 
00708 _rapl_shutdown_component( void ) 
00709 {
00710     int i;
00711 
00712     if (rapl_native_events) papi_free(rapl_native_events);
00713     if (fd_array) {
00714        for(i=0;i<num_cpus;i++) {
00715       if (fd_array[i].open) close(fd_array[i].fd);
00716        }
00717        papi_free(fd_array);
00718     }
00719 
00720     return PAPI_OK;
00721 }
00722 
00723 
00724 /* This function sets various options in the component
00725  * The valid codes being passed in are PAPI_SET_DEFDOM,
00726  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
00727  */
00728 int
00729 _rapl_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
00730 {
00731     ( void ) ctx;
00732     ( void ) code;
00733     ( void ) option;
00734 
00735   printf("CTL\n");
00736 
00737     return PAPI_OK;
00738 }
00739 
00740 
00741 int
00742 _rapl_update_control_state( hwd_control_state_t *ctl,
00743                 NativeInfo_t *native, int count,
00744                 hwd_context_t *ctx )
00745 {
00746   int i, index;
00747     ( void ) ctx;
00748 
00749     _rapl_control_state_t* control = (_rapl_control_state_t*) ctl;
00750 
00751     /* Ugh, what is this native[] stuff all about ?*/
00752     /* Mostly remap stuff in papi_internal */
00753 
00754     for(i=0;i<RAPL_MAX_COUNTERS;i++) {
00755        control->being_measured[i]=0;
00756     }
00757 
00758     for( i = 0; i < count; i++ ) {
00759        index=native[i].ni_event&PAPI_NATIVE_AND_MASK;
00760        native[i].ni_position=rapl_native_events[index].resources.selector - 1;
00761        control->being_measured[index]=1;
00762 
00763        /* Only need to subtract if it's a PACKAGE_ENERGY type */
00764        control->need_difference[index]=
00765      (rapl_native_events[index].type==PACKAGE_ENERGY);
00766     }
00767 
00768     return PAPI_OK;
00769 }
00770 
00771 
00772 /*
00773  * This function has to set the bits needed to count different domains
00774  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
00775  * By default return PAPI_EINVAL if none of those are specified
00776  * and PAPI_OK with success
00777  * PAPI_DOM_USER is only user context is counted
00778  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
00779  * PAPI_DOM_OTHER  is Exception/transient mode (like user TLB misses)
00780  * PAPI_DOM_ALL   is all of the domains
00781  */
00782 int
00783 _rapl_set_domain( hwd_control_state_t *ctl, int domain )
00784 {
00785     ( void ) ctl;
00786     (void) domain;
00787     
00788     /* In theory we only support system-wide mode */
00789     /* How to best handle that? */
00790 
00791     return PAPI_OK;
00792 }
00793 
00794 
00795 int
00796 _rapl_reset( hwd_context_t *ctx, hwd_control_state_t *ctl )
00797 {
00798     ( void ) ctx;
00799     ( void ) ctl;
00800     
00801     return PAPI_OK;
00802 }
00803 
00804 
00805 /*
00806  * Native Event functions
00807  */
00808 int
00809 _rapl_ntv_enum_events( unsigned int *EventCode, int modifier )
00810 {
00811 
00812      int index;
00813 
00814      switch ( modifier ) {
00815 
00816     case PAPI_ENUM_FIRST:
00817 
00818        if (num_events==0) {
00819           return PAPI_ENOEVNT;
00820        }
00821        *EventCode = 0;
00822 
00823        return PAPI_OK;
00824         
00825 
00826     case PAPI_ENUM_EVENTS:
00827     
00828        index = *EventCode & PAPI_NATIVE_AND_MASK;
00829 
00830        if ( index < num_events - 1 ) {
00831           *EventCode = *EventCode + 1;
00832           return PAPI_OK;
00833        } else {
00834           return PAPI_ENOEVNT;
00835        }
00836        break;
00837     
00838     default:
00839         return PAPI_EINVAL;
00840     }
00841 
00842     return PAPI_EINVAL;
00843 }
00844 
00845 /*
00846  *
00847  */
00848 int
00849 _rapl_ntv_code_to_name( unsigned int EventCode, char *name, int len )
00850 {
00851 
00852      int index = EventCode & PAPI_NATIVE_AND_MASK;
00853 
00854      if ( index >= 0 && index < num_events ) {
00855     strncpy( name, rapl_native_events[index].name, len );
00856     return PAPI_OK;
00857      }
00858 
00859      return PAPI_ENOEVNT;
00860 }
00861 
00862 /*
00863  *
00864  */
00865 int
00866 _rapl_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
00867 {
00868      int index = EventCode;
00869 
00870      if ( index >= 0 && index < num_events ) {
00871     strncpy( name, rapl_native_events[index].description, len );
00872     return PAPI_OK;
00873      }
00874      return PAPI_ENOEVNT;
00875 }
00876 
00877 int
00878 _rapl_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info) 
00879 {
00880 
00881   int index = EventCode;
00882 
00883   if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT;
00884 
00885   strncpy( info->symbol, rapl_native_events[index].name, 
00886        sizeof(info->symbol));
00887 
00888   strncpy( info->long_descr, rapl_native_events[index].description, 
00889        sizeof(info->symbol));
00890 
00891   strncpy( info->units, rapl_native_events[index].units, 
00892        sizeof(info->units));
00893 
00894   info->data_type = rapl_native_events[index].return_type;
00895 
00896   return PAPI_OK;
00897 }
00898 
00899 
00900 
00901 papi_vector_t _rapl_vector = {
00902     .cmp_info = { /* (unspecified values are initialized to 0) */
00903        .name = "rapl",
00904        .short_name = "rapl",
00905        .description = "Linux SandyBridge RAPL energy measurements",
00906        .version = "4.2.1",
00907        .default_domain = PAPI_DOM_USER,
00908        .default_granularity = PAPI_GRN_THR,
00909        .available_granularities = PAPI_GRN_THR,
00910        .hardware_intr_sig = PAPI_INT_SIGNAL,
00911        .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
00912     },
00913 
00914     /* sizes of framework-opaque component-private structures */
00915     .size = {
00916     .context = sizeof ( _rapl_context_t ),
00917     .control_state = sizeof ( _rapl_control_state_t ),
00918     .reg_value = sizeof ( _rapl_register_t ),
00919     .reg_alloc = sizeof ( _rapl_reg_alloc_t ),
00920     },
00921     /* function pointers in this component */
00922     .init_thread =          _rapl_init_thread,
00923     .init_component =       _rapl_init_component,
00924     .init_control_state =   _rapl_init_control_state,
00925     .start =                _rapl_start,
00926     .stop =                 _rapl_stop,
00927     .read =                 _rapl_read,
00928     .shutdown_thread =      _rapl_shutdown_thread,
00929     .shutdown_component =   _rapl_shutdown_component,
00930     .ctl =                  _rapl_ctl,
00931 
00932     .update_control_state = _rapl_update_control_state,
00933     .set_domain =           _rapl_set_domain,
00934     .reset =                _rapl_reset,
00935 
00936     .ntv_enum_events =      _rapl_ntv_enum_events,
00937     .ntv_code_to_name =     _rapl_ntv_code_to_name,
00938     .ntv_code_to_descr =    _rapl_ntv_code_to_descr,
00939     .ntv_code_to_info =     _rapl_ntv_code_to_info,
00940 };
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines