|
PAPI
5.0.1.0
|
00001 /****************************/ 00002 /* THIS IS OPEN SOURCE CODE */ 00003 /****************************/ 00004 00022 #include <sys/types.h> 00023 #include <sys/resource.h> 00024 #include <sys/sysctl.h> 00025 00026 #include <stdio.h> 00027 #include <string.h> 00028 #include <stdlib.h> 00029 #include <inttypes.h> 00030 00031 /* Headers required by PAPI */ 00032 #include "papi.h" 00033 #include "papi_internal.h" 00034 #include "papi_vector.h" 00035 #include "papi_memory.h" 00036 00037 #define CORETEMP_MAX_COUNTERS 32 /* Can we tune this dynamically? */ 00038 #define TRUE (1==1) 00039 #define FALSE (1!=1) 00040 #define UNREFERENCED(x) (void)x 00041 00042 /* Structure that stores private information for each event */ 00043 typedef struct coretemp_register 00044 { 00045 int mib[4]; 00046 /* Access to registers through these MIBs + sysctl (3) call */ 00047 00048 unsigned int selector; 00051 } coretemp_register_t; 00052 00054 typedef struct coretemp_native_event_entry 00055 { 00056 coretemp_register_t resources; 00057 char name[PAPI_MAX_STR_LEN]; 00058 char description[PAPI_MAX_STR_LEN]; 00059 } coretemp_native_event_entry_t; 00060 00061 /* This structure is used when doing register allocation 00062 it possibly is not necessary when there are no 00063 register constraints */ 00064 typedef struct coretemp_reg_alloc 00065 { 00066 coretemp_register_t ra_bits; 00067 } coretemp_reg_alloc_t; 00068 00069 /* Holds control flags, usually out-of band configuration of the hardware */ 00070 typedef struct coretemp_control_state 00071 { 00072 int added[CORETEMP_MAX_COUNTERS]; 00073 long_long counters[CORETEMP_MAX_COUNTERS]; 00074 } coretemp_control_state_t; 00075 00076 /* Holds per-thread information */ 00077 typedef struct coretemp_context 00078 { 00079 coretemp_control_state_t state; 00080 } coretemp_context_t; 00081 00083 static coretemp_native_event_entry_t *coretemp_native_table; 00084 00086 static int CORETEMP_NUM_EVENTS = 0; 00087 00088 00089 /********************************************************************/ 00090 /* Below are the functions required by the PAPI component interface */ 00091 /********************************************************************/ 00092 00094 int coretemp_init_thread (hwd_context_t * ctx) 00095 { 00096 int mib[4]; 00097 size_t len; 00098 UNREFERENCED(ctx); 00099 00100 SUBDBG("coretemp_init_thread %p...\n", ctx); 00101 00102 #if 0 00103 /* what does this do? VMW */ 00104 00105 len = 4; 00106 if (sysctlnametomib ("dev.coretemp.0.%driver", mib, &len) == -1) 00107 return PAPI_ECMP; 00108 #endif 00109 00110 return PAPI_OK; 00111 } 00112 00113 00118 int coretemp_init_component () 00119 { 00120 int ret; 00121 int i; 00122 int mib[4]; 00123 size_t len; 00124 char tmp[128]; 00125 00126 SUBDBG("coretemp_init_component...\n"); 00127 00128 /* Count the number of cores (counters) that have sensors allocated */ 00129 i = 0; 00130 CORETEMP_NUM_EVENTS = 0; 00131 sprintf (tmp, "dev.coretemp.%d.%%driver", i); 00132 len = 4; 00133 ret = sysctlnametomib (tmp, mib, &len); 00134 while (ret != -1) 00135 { 00136 CORETEMP_NUM_EVENTS++; 00137 i++; 00138 sprintf (tmp, "dev.coretemp.%d.%%driver", i); 00139 len = 4; 00140 ret = sysctlnametomib (tmp, mib, &len); 00141 } 00142 00143 /* Allocate memory for the our event table */ 00144 coretemp_native_table = (coretemp_native_event_entry_t *) 00145 papi_malloc (sizeof (coretemp_native_event_entry_t) * CORETEMP_NUM_EVENTS); 00146 if (coretemp_native_table == NULL) 00147 { 00148 perror( "malloc():Could not get memory for coretemp events table" ); 00149 return PAPI_ENOMEM; 00150 } 00151 00152 /* Allocate native events internal structures */ 00153 for (i = 0; i < CORETEMP_NUM_EVENTS; i++) 00154 { 00155 /* Event name */ 00156 sprintf (coretemp_native_table[i].name, "CORETEMP_CPU_%d", i); 00157 00158 /* Event description */ 00159 sprintf (coretemp_native_table[i].description, "CPU On-Die Thermal Sensor #%d", i); 00160 00161 /* Event extra bits -> save MIB to faster access later */ 00162 sprintf (tmp, "dev.cpu.%d.temperature", i); 00163 len = 4; 00164 if (sysctlnametomib (tmp, coretemp_native_table[i].resources.mib, &len) == -1) 00165 return PAPI_ECMP; 00166 00167 coretemp_native_table[i].resources.selector = i+1; 00168 } 00169 00170 return PAPI_OK; 00171 } 00172 00173 00175 int coretemp_init_control_state (hwd_control_state_t * ctrl) 00176 { 00177 int i; 00178 00179 SUBDBG("coretemp_init_control_state... %p\n", ctrl); 00180 coretemp_control_state_t *c = (coretemp_control_state_t *) ctrl; 00181 00182 for (i = 0; i < CORETEMP_MAX_COUNTERS; i++) 00183 c->added[i] = FALSE; 00184 00185 return PAPI_OK; 00186 } 00187 00188 00193 int coretemp_ntv_enum_events (unsigned int *EventCode, int modifier) 00194 { 00195 00196 switch ( modifier ) 00197 { 00198 /* return EventCode of first event */ 00199 case PAPI_ENUM_FIRST: 00200 *EventCode = 0; 00201 return PAPI_OK; 00202 break; 00203 00204 /* return EventCode of passed-in Event */ 00205 case PAPI_ENUM_EVENTS: 00206 { 00207 int index = *EventCode; 00208 00209 if ( index < CORETEMP_NUM_EVENTS - 1 ) 00210 { 00211 *EventCode = *EventCode + 1; 00212 return PAPI_OK; 00213 } 00214 else 00215 return PAPI_ENOEVNT; 00216 break; 00217 } 00218 00219 default: 00220 return PAPI_EINVAL; 00221 } 00222 00223 return PAPI_EINVAL; 00224 } 00225 00231 int coretemp_ntv_code_to_name (unsigned int EventCode, char *name, int len) 00232 { 00233 int index = EventCode; 00234 00235 strncpy( name, coretemp_native_table[index].name, len ); 00236 00237 return PAPI_OK; 00238 } 00239 00245 int coretemp_ntv_code_to_descr (unsigned int EventCode, char *name, int len) 00246 { 00247 int index = EventCode; 00248 00249 strncpy( name, coretemp_native_table[index].description, len ); 00250 00251 return PAPI_OK; 00252 } 00253 00256 int coretemp_ntv_code_to_bits (unsigned int EventCode, hwd_register_t * bits) 00257 { 00258 UNREFERENCED(EventCode); 00259 UNREFERENCED(bits); 00260 00261 return PAPI_OK; 00262 } 00263 00265 int coretemp_update_control_state( hwd_control_state_t * ptr, 00266 NativeInfo_t * native, int count, hwd_context_t * ctx ) 00267 { 00268 int i, index; 00269 coretemp_control_state_t *c = (coretemp_control_state_t *) ptr; 00270 UNREFERENCED(ctx); 00271 00272 SUBDBG("coretemp_update_control_state %p %p...\n", ptr, ctx); 00273 00274 for (i = 0; i < count; i++) 00275 { 00276 index = native[i].ni_event; 00277 native[i].ni_position = coretemp_native_table[index].resources.selector - 1; 00278 c->added[native[i].ni_position] = TRUE; 00279 00280 SUBDBG ("\nnative[%i].ni_position = coretemp_native_table[%i].resources.selector-1 = %i;\n", 00281 i, index, native[i].ni_position ); 00282 } 00283 00284 return PAPI_OK; 00285 } 00286 00288 int coretemp_start (hwd_context_t * ctx, hwd_control_state_t * ctrl) 00289 { 00290 UNREFERENCED(ctx); 00291 UNREFERENCED(ctrl); 00292 00293 SUBDBG( "coretemp_start %p %p...\n", ctx, ctrl ); 00294 00295 /* Nothing to be done */ 00296 00297 return PAPI_OK; 00298 } 00299 00300 00302 int coretemp_stop (hwd_context_t * ctx, hwd_control_state_t * ctrl) 00303 { 00304 UNREFERENCED(ctx); 00305 UNREFERENCED(ctrl); 00306 00307 SUBDBG("coretemp_stop %p %p...\n", ctx, ctrl); 00308 00309 /* Nothing to be done */ 00310 00311 return PAPI_OK; 00312 } 00313 00314 00316 int coretemp_read (hwd_context_t * ctx, hwd_control_state_t * ctrl, 00317 long_long ** events, int flags) 00318 { 00319 int i; 00320 coretemp_control_state_t *c = (coretemp_control_state_t *) ctrl; 00321 UNREFERENCED(ctx); 00322 UNREFERENCED(flags); 00323 00324 SUBDBG("coretemp_read... %p %d\n", ctx, flags); 00325 00326 for (i = 0; i < CORETEMP_MAX_COUNTERS; i++) 00327 if (c->added[i]) 00328 { 00329 int tmp; 00330 size_t len = sizeof(tmp); 00331 00332 if (sysctl (coretemp_native_table[i].resources.mib, 4, &tmp, &len, NULL, 0) == -1) 00333 c->counters[i] = 0; 00334 else 00335 c->counters[i] = tmp/10; 00336 /* Coretemp module returns temperature in tenths of kelvin 00337 Kelvin are useful to avoid negative values... but will have 00338 negative temperatures ??? */ 00339 } 00340 00341 *events = c->counters; 00342 00343 return PAPI_OK; 00344 } 00345 00347 /* otherwise, the updated state is written to ESI->hw_start */ 00348 int coretemp_write (hwd_context_t * ctx, hwd_control_state_t * ctrl, 00349 long_long events[] ) 00350 { 00351 UNREFERENCED(ctx); 00352 UNREFERENCED(events); 00353 UNREFERENCED(ctrl); 00354 00355 SUBDBG("coretemp_write... %p %p\n", ctx, ctrl); 00356 00357 /* These sensor counters cannot be writtn */ 00358 00359 return PAPI_OK; 00360 } 00361 00362 00364 int coretemp_reset(hwd_context_t * ctx, hwd_control_state_t * ctrl) 00365 { 00366 UNREFERENCED(ctx); 00367 UNREFERENCED(ctrl); 00368 00369 SUBDBG("coretemp_reset ctx=%p ctrl=%p...\n", ctx, ctrl); 00370 00371 /* These sensors cannot be reseted */ 00372 00373 return PAPI_OK; 00374 } 00375 00377 int coretemp_shutdown_component (void) 00378 { 00379 00380 SUBDBG( "coretemp_shutdown_component... %p\n", ctx ); 00381 00382 /* Last chance to clean up */ 00383 papi_free (coretemp_native_table); 00384 00385 return PAPI_OK; 00386 } 00387 00388 00389 00395 int coretemp_ctl (hwd_context_t * ctx, int code, _papi_int_option_t * option) 00396 { 00397 UNREFERENCED(ctx); 00398 UNREFERENCED(code); 00399 UNREFERENCED(option); 00400 00401 SUBDBG( "coretemp_ctl... %p %d %p\n", ctx, code, option ); 00402 00403 /* FIXME. This should maybe set up more state, such as which counters are active and */ 00404 /* counter mappings. */ 00405 00406 return PAPI_OK; 00407 } 00408 00418 int coretemp_set_domain (hwd_control_state_t * cntrl, int domain) 00419 { 00420 int found = 0; 00421 UNREFERENCED(cntrl); 00422 00423 SUBDBG ("coretemp_set_domain... %p %d\n", cntrl, domain); 00424 00425 if (PAPI_DOM_USER & domain) 00426 { 00427 SUBDBG( " PAPI_DOM_USER \n" ); 00428 found = 1; 00429 } 00430 if (PAPI_DOM_KERNEL & domain) 00431 { 00432 SUBDBG( " PAPI_DOM_KERNEL \n" ); 00433 found = 1; 00434 } 00435 if (PAPI_DOM_OTHER & domain) 00436 { 00437 SUBDBG( " PAPI_DOM_OTHER \n" ); 00438 found = 1; 00439 } 00440 if (PAPI_DOM_ALL & domain) 00441 { 00442 SUBDBG( " PAPI_DOM_ALL \n" ); 00443 found = 1; 00444 } 00445 if (!found) 00446 return PAPI_EINVAL ; 00447 00448 return PAPI_OK; 00449 } 00450 00451 00453 papi_vector_t _coretemp_freebsd_vector = { 00454 .cmp_info = { 00455 /* default component information (unspecified values are initialized to 0) */ 00456 .name = "coretemp_freebsd", 00457 .short_name = "coretemp", 00458 .version = "5.0", 00459 .num_mpx_cntrs = CORETEMP_MAX_COUNTERS, 00460 .num_cntrs = CORETEMP_MAX_COUNTERS, 00461 .default_domain = PAPI_DOM_USER, 00462 .available_domains = PAPI_DOM_USER, 00463 .default_granularity = PAPI_GRN_THR, 00464 .available_granularities = PAPI_GRN_THR, 00465 .hardware_intr_sig = PAPI_INT_SIGNAL, 00466 00467 /* component specific cmp_info initializations */ 00468 .fast_real_timer = 0, 00469 .fast_virtual_timer = 0, 00470 .attach = 0, 00471 .attach_must_ptrace = 0, 00472 } 00473 , 00474 00475 /* sizes of framework-opaque component-private structures */ 00476 .size = { 00477 .context = sizeof ( coretemp_context_t ), 00478 .control_state = sizeof ( coretemp_control_state_t ), 00479 .reg_value = sizeof ( coretemp_register_t ), 00480 .reg_alloc = sizeof ( coretemp_reg_alloc_t ), 00481 } 00482 , 00483 /* function pointers in this component */ 00484 .init_thread = coretemp_init_thread, 00485 .init_component = coretemp_init_component, 00486 .init_control_state = coretemp_init_control_state, 00487 .start = coretemp_start, 00488 .stop = coretemp_stop, 00489 .read = coretemp_read, 00490 .write = coretemp_write, 00491 .shutdown_component = coretemp_shutdown_component, 00492 .ctl = coretemp_ctl, 00493 00494 .update_control_state = coretemp_update_control_state, 00495 .set_domain = coretemp_set_domain, 00496 .reset = coretemp_reset, 00497 00498 .ntv_enum_events = coretemp_ntv_enum_events, 00499 .ntv_code_to_name = coretemp_ntv_code_to_name, 00500 .ntv_code_to_descr = coretemp_ntv_code_to_descr, 00501 .ntv_code_to_bits = coretemp_ntv_code_to_bits, 00502 }; 00503