|
PAPI
5.1.0.2
|
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 };