PAPI  5.0.1.0
coretemp_freebsd.c
Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines