PAPI  5.0.1.0
linux-mx.c
Go to the documentation of this file.
00001 
00007 #include "papi.h"
00008 #include "papi_internal.h"
00009 #include "papi_vector.h"
00010 
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013 #include <unistd.h>
00014 #include <string.h>
00015 #include <ctype.h>
00016 
00017 #define MX_MAX_COUNTERS 100
00018 #define MX_MAX_COUNTER_TERMS  MX_MAX_COUNTERS
00019 
00020 #define LINELEN 128
00021 
00022 typedef struct MX_register
00023 {
00024     /* indicate which counters this event can live on */
00025     unsigned int selector;
00026 } MX_register_t;
00027 
00028 typedef struct MX_native_event_entry
00029 {
00030     /* description of the resources required by this native event */
00031     MX_register_t resources;
00032     /* If it exists, then this is the name of this event */
00033     char *name;
00034     /* If it exists, then this is the description of this event */
00035     char *description;
00036 } MX_native_event_entry_t;
00037 
00038 typedef struct MX_reg_alloc
00039 {
00040     MX_register_t ra_bits;
00041 } MX_reg_alloc_t;
00042 
00043 typedef struct MX_control_state
00044 {
00045   long long start_count[MX_MAX_COUNTERS];
00046   long long current_count[MX_MAX_COUNTERS];
00047   long long difference[MX_MAX_COUNTERS];
00048   int which_counter[MX_MAX_COUNTERS];
00049   int num_events;
00050 } MX_control_state_t;
00051 
00052 typedef struct MX_context
00053 {
00054     MX_control_state_t state;
00055 } MX_context_t;
00056 
00057 
00058 MX_native_event_entry_t mx_native_table[] = {
00059     {{1,  }, "LANAI_UPTIME", "Lanai uptime (seconds)"},
00060     {{2,  }, "COUNTERS_UPTIME", "Counters uptime (seconds)"},
00061     {{3,  }, "BAD_CRC8", "Bad CRC8 (Port 0)"},
00062     {{4,  }, "BAD_CRC32", "Bad CRC32 (Port 0)"},
00063     {{5,  }, "UNSTRIPPED_ROUTE", "Unstripped route (Port 0)"},
00064     {{6,  }, "PKT_DESC_INVALID", "pkt_desc_invalid (Port 0)"},
00065     {{7,  }, "RECV_PKT_ERRORS", "recv_pkt_errors (Port 0)"},
00066     {{8,  }, "PKT_MISROUTED", "pkt_misrouted (Port 0)"},
00067     {{9,  }, "DATA_SRC_UNKNOWN", "data_src_unknown"},
00068     {{10,  }, "DATA_BAD_ENDPT", "data_bad_endpt"},
00069     {{11,  }, "DATA_ENDPT_CLOSED", "data_endpt_closed"},
00070     {{12,  }, "DATA_BAD_SESSION", "data_bad_session"},
00071     {{13,  }, "PUSH_BAD_WINDOW", "push_bad_window"},
00072     {{14,  }, "PUSH_DUPLICATE", "push_duplicate"},
00073     {{15,  }, "PUSH_OBSOLETE", "push_obsolete"},
00074     {{16,  }, "PUSH_RACE_DRIVER", "push_race_driver"},
00075     {{17,  }, "PUSH_BAD_SEND_HANDLE_MAGIC", "push_bad_send_handle_magic"},
00076     {{18,  }, "PUSH_BAD_SRC_MAGIC", "push_bad_src_magic"},
00077     {{19,  }, "PULL_OBSOLETE", "pull_obsolete"},
00078     {{20,  }, "PULL_NOTIFY_OBSOLETE", "pull_notify_obsolete"},
00079     {{21,  }, "PULL_RACE_DRIVER", "pull_race_driver"},
00080     {{22,  }, "ACK_BAD_TYPE", "ack_bad_type"},
00081     {{23,  }, "ACK_BAD_MAGIC", "ack_bad_magic"},
00082     {{24,  }, "ACK_RESEND_RACE", "ack_resend_race"},
00083     {{25,  }, "LATE_ACK", "Late ack"},
00084     {{26,  }, "ACK_NACK_FRAMES_IN_PIPE", "ack_nack_frames_in_pipe"},
00085     {{27,  }, "NACK_BAD_ENDPT", "nack_bad_endpt"},
00086     {{28,  }, "NACK_ENDPT_CLOSED", "nack_endpt_closed"},
00087     {{29,  }, "NACK_BAD_SESSION", "nack_bad_session"},
00088     {{30,  }, "NACK_BAD_RDMAWIN", "nack_bad_rdmawin"},
00089     {{31,  }, "NACK_EVENTQ_FULL", "nack_eventq_full"},
00090     {{32,  }, "SEND_BAD_RDMAWIN", "send_bad_rdmawin"},
00091     {{33,  }, "CONNECT_TIMEOUT", "connect_timeout"},
00092     {{34,  }, "CONNECT_SRC_UNKNOWN", "connect_src_unknown"},
00093     {{35,  }, "QUERY_BAD_MAGIC", "query_bad_magic"},
00094     {{36,  }, "QUERY_TIMED_OUT", "query_timed_out"},
00095     {{37,  }, "QUERY_SRC_UNKNOWN", "query_src_unknown"},
00096     {{38,  }, "RAW_SENDS", "Raw sends (Port 0)"},
00097     {{39,  }, "RAW_RECEIVES", "Raw receives (Port 0)"},
00098     {{40,  }, "RAW_OVERSIZED_PACKETS", "Raw oversized packets (Port 0)"},
00099     {{41,  }, "RAW_RECV_OVERRUN", "raw_recv_overrun"},
00100     {{42,  }, "RAW_DISABLED", "raw_disabled"},
00101     {{43,  }, "CONNECT_SEND", "connect_send"},
00102     {{44,  }, "CONNECT_RECV", "connect_recv"},
00103     {{45,  }, "ACK_SEND", "ack_send (Port 0)"},
00104     {{46,  }, "ACK_RECV", "ack_recv (Port 0)"},
00105     {{47,  }, "PUSH_SEND", "push_send (Port 0)"},
00106     {{48,  }, "PUSH_RECV", "push_recv (Port 0)"},
00107     {{49,  }, "QUERY_SEND", "query_send (Port 0)"},
00108     {{50,  }, "QUERY_RECV", "query_recv (Port 0)"},
00109     {{51,  }, "REPLY_SEND", "reply_send (Port 0)"},
00110     {{52,  }, "REPLY_RECV", "reply_recv (Port 0)"},
00111     {{53,  }, "QUERY_UNKNOWN", "query_unknown (Port 0)"},
00112 /*   {{ 54,  }, "QUERY_UNKNOWN", "query_unknown (Port 0)"},*/
00113     {{55,  }, "DATA_SEND_NULL", "data_send_null (Port 0)"},
00114     {{56,  }, "DATA_SEND_SMALL", "data_send_small (Port 0)"},
00115     {{57,  }, "DATA_SEND_MEDIUM", "data_send_medium (Port 0)"},
00116     {{58,  }, "DATA_SEND_RNDV", "data_send_rndv (Port 0)"},
00117     {{59,  }, "DATA_SEND_PULL", "data_send_pull (Port 0)"},
00118     {{60,  }, "DATA_RECV_NULL", "data_recv_null (Port 0)"},
00119     {{61,  }, "DATA_RECV_SMALL_INLINE", "data_recv_small_inline (Port 0)"},
00120     {{62,  }, "DATA_RECV_SMALL_COPY", "data_recv_small_copy (Port 0)"},
00121     {{63,  }, "DATA_RECV_MEDIUM", "data_recv_medium (Port 0)"},
00122     {{64,  }, "DATA_RECV_RNDV", "data_recv_rndv (Port 0)"},
00123     {{65,  }, "DATA_RECV_PULL", "data_recv_pull (Port 0)"},
00124     {{66,  }, "ETHER_SEND_UNICAST_CNT", "ether_send_unicast_cnt (Port 0)"},
00125     {{67,  }, "ETHER_SEND_MULTICAST_CNT", "ether_send_multicast_cnt (Port 0)"},
00126     {{68,  }, "ETHER_RECV_SMALL_CNT", "ether_recv_small_cnt (Port 0)"},
00127     {{69,  }, "ETHER_RECV_BIG_CNT", "ether_recv_big_cnt (Port 0)"},
00128     {{70,  }, "ETHER_OVERRUN", "ether_overrun"},
00129     {{71,  }, "ETHER_OVERSIZED", "ether_oversized"},
00130     {{72,  }, "DATA_RECV_NO_CREDITS", "data_recv_no_credits"},
00131     {{73,  }, "PACKETS_RECENT", "Packets resent"},
00132     {{74,  }, "PACKETS_DROPPED", "Packets dropped (data send side)"},
00133     {{75,  }, "MAPPER_ROUTES_UPDATE", "Mapper routes update"},
00134     {{76,  }, "ROUTE_DISPERSION", "Route dispersion (Port 0)"},
00135     {{77,  }, "OUT_OF_SEND_HANDLES", "out_of_send_handles"},
00136     {{78,  }, "OUT_OF_PULL_HANDLES", "out_of_pull_handles"},
00137     {{79,  }, "OUT_OF_PUSH_HANDLES", "out_of_push_handles"},
00138     {{80,  }, "MEDIUM_CONT_RACE", "medium_cont_race"},
00139     {{81,  }, "CMD_TYPE_UNKNOWN", "cmd_type_unknown"},
00140     {{82,  }, "UREQ_TYPE_UNKNOWN", "ureq_type_unknown"},
00141     {{83,  }, "INTERRUPTS_OVERRUN", "Interrupts overrun"},
00142     {{84,  }, "WAITING_FOR_INTERRUPT_DMA", "Waiting for interrupt DMA"},
00143     {{85,  }, "WAITING_FOR_INTERRUPT_ACK", "Waiting for interrupt Ack"},
00144     {{86,  }, "WAITING_FOR_INTERRUPT_TIMER", "Waiting for interrupt Timer"},
00145     {{87,  }, "SLABS_RECYCLING", "Slabs recycling"},
00146     {{88,  }, "SLABS_PRESSURE", "Slabs pressure"},
00147     {{89,  }, "SLABS_STARVATION", "Slabs starvation"},
00148     {{90,  }, "OUT_OF_RDMA_HANDLES", "out_of_rdma handles"},
00149     {{91,  }, "EVENTQ_FULL", "eventq_full"},
00150     {{92,  }, "BUFFER_DROP", "buffer_drop (Port 0)"},
00151     {{93,  }, "MEMORY_DROP", "memory_drop (Port 0)"},
00152     {{94,  }, "HARDWARE_FLOW_CONTROL", "Hardware flow control (Port 0)"},
00153     {{95,  }, "SIMULATED_PACKETS_LOST", "(Devel) Simulated packets lost (Port 0)"},
00154     {{96,  }, "LOGGING_FRAMES_DUMPED", "(Logging) Logging frames dumped"},
00155     {{97,  }, "WAKE_INTERRUPTS", "Wake interrupts"},
00156     {{98,  }, "AVERTED_WAKEUP_RACE", "Averted wakeup race"},
00157     {{99,  }, "DMA_METADATA_RACE", "Dma metadata race"},
00158     {{0, }, "", ""}
00159 };
00160 
00161 static int num_events=0;
00162 papi_vector_t _mx_vector;
00163 
00164 static char mx_counters_exe[BUFSIZ];
00165 
00166 static int
00167 read_mx_counters( long long *counters )
00168 {
00169     FILE *fp;
00170     char line[LINELEN];
00171     int i, linenum;
00172 
00173     /* Open a pipe to the mx_counters executable */
00174 
00175     fp = popen( mx_counters_exe, "r" );
00176     if ( !fp ) {
00177        perror( "popen" );
00178        return PAPI_ECMP;
00179     }
00180 
00181 
00182     /* A line of output looks something similar to:       */
00183         /* "    Lanai uptime (seconds):     766268 (0xbb13c)" */
00184 
00185     /* This code may fail if number of ports on card > 1 */
00186 
00187     linenum = 0;
00188     while ( fgets( line, LINELEN, fp ) ) {
00189       //       printf("%s",line);
00190        for(i=0; line[i]!= '\0' && i<LINELEN-1;i++) {
00191 
00192           /* skip to colon */
00193           if (line[i]==':') {
00194 
00195              /* read in value */
00196              if (line[i+1]!='\0') {
00197            //       printf("Line %d trying %s",linenum,&line[i+1]);
00198                 sscanf(&line[i+1],"%lld",&counters[linenum]);
00199             linenum++;
00200             break;
00201          }
00202           }
00203        }
00204        if (linenum>=MX_MAX_COUNTERS) break;
00205     }
00206 
00207     pclose( fp );
00208 
00209     return PAPI_OK;
00210 }
00211 
00212 
00213 
00214 /*
00215  * Component setup and shutdown
00216  */
00217 
00218 /* Initialize hardware counters, setup the function vector table
00219  * and get hardware information, this routine is called when the 
00220  * PAPI process is initialized (IE PAPI_library_init)
00221  */
00222 int
00223 _mx_init_component(  )
00224 {
00225 
00226     FILE *fff;
00227     char test_string[BUFSIZ];
00228 
00229     /* detect if MX available */
00230 
00231     strncpy(mx_counters_exe,"mx_counters 2> /dev/null",BUFSIZ);
00232     fff=popen(mx_counters_exe,"r");
00233     /* popen only returns NULL if "sh" fails, not the actual command */
00234     if (fgets(test_string,BUFSIZ,fff)==NULL) {
00235        pclose(fff);
00236        strncpy(mx_counters_exe,"./components/mx/utils/fake_mx_counters 2> /dev/null",BUFSIZ);
00237        fff=popen(mx_counters_exe,"r");
00238        if (fgets(test_string,BUFSIZ,fff)==NULL) {
00239           pclose(fff);
00240           /* neither real nor fake found */
00241           strncpy(_mx_vector.cmp_info.disabled_reason,
00242               "No MX utilities found",PAPI_MAX_STR_LEN);
00243           return PAPI_ECMP;
00244        }
00245     }
00246     pclose(fff);
00247 
00248     num_events=MX_MAX_COUNTERS;
00249     _mx_vector.cmp_info.num_native_events=num_events;
00250 
00251     return PAPI_OK;
00252 }
00253 
00254 
00255 /*
00256  * This is called whenever a thread is initialized
00257  */
00258 int
00259 _mx_init_thread( hwd_context_t * ctx )
00260 {
00261     ( void ) ctx;            /*unused */
00262     return PAPI_OK;
00263 }
00264 
00265 
00266 int
00267 _mx_shutdown_component(void) 
00268 {
00269   return PAPI_OK;
00270 }
00271 
00272 int
00273 _mx_shutdown_thread( hwd_context_t * ctx )
00274 {
00275     ( void ) ctx;            /*unused */
00276     return PAPI_OK;
00277 }
00278 
00279 
00280 
00281 /*
00282  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
00283  * functions
00284  */
00285 int
00286 _mx_init_control_state( hwd_control_state_t *ctl )
00287 {
00288     ( void ) ctl;            /*unused */
00289 
00290     return PAPI_OK;
00291 }
00292 
00293 int
00294 _mx_update_control_state( hwd_control_state_t *ctl, NativeInfo_t *native,
00295               int count, hwd_context_t *ctx )
00296 {
00297     ( void ) ctx;            /*unused */
00298     int i, index;
00299     
00300     MX_control_state_t *mx_ctl = (MX_control_state_t *)ctl;
00301 
00302     for(i=0; i<count; i++ ) {
00303         index = native[i].ni_event;
00304         mx_ctl->which_counter[i]=index;
00305         //      printf("Mapping event# %d to HW counter %d (count=%d)\n",
00306         //     i,index,count); 
00307         native[i].ni_position = i;
00308     }
00309 
00310     mx_ctl->num_events=count;
00311 
00312     return PAPI_OK;
00313 }
00314 
00315 
00316 int
00317 _mx_start( hwd_context_t *ctx, hwd_control_state_t *ctl )
00318 {
00319 
00320         long long mx_counters[MX_MAX_COUNTERS];
00321 
00322     ( void ) ctx;            /*unused */
00323 
00324     MX_control_state_t *mx_ctl = (MX_control_state_t *)ctl;
00325     int i;
00326 
00327     read_mx_counters( mx_counters );
00328 
00329     //  for(i=0;i<MX_MAX_COUNTERS;i++) printf("%d %lld\n",i,mx_counters[i]);
00330 
00331     for(i=0;i<mx_ctl->num_events;i++) {
00332            mx_ctl->current_count[i]=
00333              mx_counters[mx_ctl->which_counter[i]];
00334        mx_ctl->start_count[i]=mx_ctl->current_count[i];
00335     }
00336 
00337     return PAPI_OK;
00338 }
00339 
00340 
00341 int
00342 _mx_stop( hwd_context_t *ctx, hwd_control_state_t *ctl )
00343 {
00344     ( void ) ctx;            /*unused */
00345 
00346         long long mx_counters[MX_MAX_COUNTERS];
00347     MX_control_state_t *mx_ctl = (MX_control_state_t *)ctl;
00348     int i;
00349 
00350     read_mx_counters( mx_counters );
00351 
00352     for(i=0;i<mx_ctl->num_events;i++) {
00353            mx_ctl->current_count[i]=
00354              mx_counters[mx_ctl->which_counter[i]];
00355     }
00356 
00357     return PAPI_OK;
00358 }
00359 
00360 int
00361 _mx_read( hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events,
00362          int flags )
00363 {
00364     ( void ) ctx;            /*unused */
00365     ( void ) flags;          /*unused */
00366     int i;
00367         long long mx_counters[MX_MAX_COUNTERS];
00368 
00369     MX_control_state_t *mx_ctl = (MX_control_state_t *)ctl;
00370 
00371     read_mx_counters( mx_counters );
00372 
00373     for ( i = 0; i < mx_ctl->num_events; i++ ) {
00374             mx_ctl->current_count[i]=
00375              mx_counters[mx_ctl->which_counter[i]];
00376         mx_ctl->difference[i] = mx_ctl->current_count[i]-
00377                                    mx_ctl->start_count[i];
00378     }
00379     *events = mx_ctl->difference;
00380 
00381     return PAPI_OK;
00382 }
00383 
00384 
00385 int
00386 _mx_reset( hwd_context_t * ctx, hwd_control_state_t * ctrl )
00387 {
00388     _mx_start( ctx, ctrl );
00389     return PAPI_OK;
00390 }
00391 
00392 int
00393 _mx_write( hwd_context_t * ctx, hwd_control_state_t * ctrl, long long *from )
00394 {
00395     ( void ) ctx;            /*unused */
00396     ( void ) ctrl;           /*unused */
00397     ( void ) from;           /*unused */
00398 
00399     return PAPI_OK;
00400 }
00401 
00402 /*
00403  * Functions for setting up various options
00404  */
00405 
00406 /* This function sets various options in the component
00407  * The valid codes being passed in are PAPI_SET_DEFDOM,
00408  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
00409  */
00410 int
00411 _mx_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option )
00412 {
00413     ( void ) ctx;            /*unused */
00414     ( void ) code;           /*unused */
00415     ( void ) option;         /*unused */
00416 
00417     return PAPI_OK;
00418 }
00419 
00420 /*
00421  * This function has to set the bits needed to count different domains
00422  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
00423  * By default return PAPI_EINVAL if none of those are specified
00424  * and PAPI_OK with success
00425  * PAPI_DOM_USER is only user context is counted
00426  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
00427  * PAPI_DOM_OTHER  is Exception/transient mode (like user TLB misses)
00428  * PAPI_DOM_ALL   is all of the domains
00429  */
00430 int
00431 _mx_set_domain( hwd_control_state_t * cntrl, int domain )
00432 {
00433     ( void ) cntrl;          /*unused */
00434     int found = 0;
00435     if ( PAPI_DOM_USER & domain ) {
00436         found = 1;
00437     }
00438     if ( PAPI_DOM_KERNEL & domain ) {
00439         found = 1;
00440     }
00441     if ( PAPI_DOM_OTHER & domain ) {
00442         found = 1;
00443     }
00444     if ( !found )
00445         return PAPI_EINVAL;
00446     return PAPI_OK;
00447 }
00448 
00449 
00450 
00451 int
00452 _mx_ntv_code_to_name( unsigned int EventCode, char *name, int len )
00453 {
00454 
00455     int event=EventCode;
00456 
00457     if (event >=0 && event < num_events) {
00458       strncpy( name, mx_native_table[event].name, len );
00459       return PAPI_OK;
00460     }
00461     return PAPI_ENOEVNT;
00462 
00463 
00464 }
00465 
00466 int
00467 _mx_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
00468 {
00469     int event=EventCode;
00470 
00471     if (event >=0 && event < num_events) {
00472        strncpy( name, mx_native_table[event].description, len );
00473        return PAPI_OK;
00474     }
00475     return PAPI_ENOEVNT;
00476 }
00477 
00478 
00479 
00480 int
00481 _mx_ntv_enum_events( unsigned int *EventCode, int modifier )
00482 {
00483 
00484     if ( modifier == PAPI_ENUM_FIRST ) {
00485        if (num_events==0) return PAPI_ENOEVNT;
00486        *EventCode = 0;
00487        return PAPI_OK;
00488     }
00489 
00490     if ( modifier == PAPI_ENUM_EVENTS ) {
00491         int index = *EventCode;
00492 
00493         if ( mx_native_table[index + 1].resources.selector ) {
00494             *EventCode = *EventCode + 1;
00495             return PAPI_OK;
00496         } else {
00497             return PAPI_ENOEVNT;
00498         }
00499     }
00500         
00501         return PAPI_EINVAL;
00502 }
00503 
00504 
00505 papi_vector_t _mx_vector = {
00506     .cmp_info = {
00507         .name = "mx",
00508         .short_name = "mx",
00509         .version = "1.4",
00510         .description = "Myricom MX (Myrinet Express) statistics",
00511         .num_mpx_cntrs = MX_MAX_COUNTERS,
00512         .num_cntrs = MX_MAX_COUNTERS,
00513         .default_domain = PAPI_DOM_USER,
00514         .default_granularity = PAPI_GRN_THR,
00515         .available_granularities = PAPI_GRN_THR,
00516         .hardware_intr_sig = PAPI_INT_SIGNAL,
00517 
00518         /* component specific cmp_info initializations */
00519         .fast_real_timer = 0,
00520         .fast_virtual_timer = 0,
00521         .attach = 0,
00522         .attach_must_ptrace = 0,
00523         .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
00524   },
00525 
00526     /* sizes of framework-opaque component-private structures */
00527     .size = {
00528         .context = sizeof ( MX_context_t ),
00529         .control_state = sizeof ( MX_control_state_t ),
00530         .reg_value = sizeof ( MX_register_t ),
00531         .reg_alloc = sizeof ( MX_reg_alloc_t ),
00532   },
00533         /* function pointers in this component */
00534     .init_thread =          _mx_init_thread,
00535     .init_component =       _mx_init_component,
00536     .init_control_state =   _mx_init_control_state,
00537     .start =                _mx_start,
00538     .stop =                 _mx_stop,
00539     .read =                 _mx_read,
00540     .shutdown_thread =      _mx_shutdown_thread,
00541     .shutdown_component =   _mx_shutdown_component,
00542     .ctl =                  _mx_ctl,
00543     .update_control_state = _mx_update_control_state,
00544     .set_domain =           _mx_set_domain,
00545     .reset =                _mx_reset,
00546 
00547     .ntv_enum_events =      _mx_ntv_enum_events,
00548     .ntv_code_to_name =     _mx_ntv_code_to_name,
00549     .ntv_code_to_descr =    _mx_ntv_code_to_descr,
00550 };
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines