|
PAPI
5.3.0.0
|
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( int cidx ) 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 /* Export the component id */ 00252 _mx_vector.cmp_info.CmpIdx = cidx; 00253 00254 00255 return PAPI_OK; 00256 } 00257 00258 00259 /* 00260 * This is called whenever a thread is initialized 00261 */ 00262 int 00263 _mx_init_thread( hwd_context_t * ctx ) 00264 { 00265 ( void ) ctx; /*unused */ 00266 return PAPI_OK; 00267 } 00268 00269 00270 int 00271 _mx_shutdown_component(void) 00272 { 00273 return PAPI_OK; 00274 } 00275 00276 int 00277 _mx_shutdown_thread( hwd_context_t * ctx ) 00278 { 00279 ( void ) ctx; /*unused */ 00280 return PAPI_OK; 00281 } 00282 00283 00284 00285 /* 00286 * Control of counters (Reading/Writing/Starting/Stopping/Setup) 00287 * functions 00288 */ 00289 int 00290 _mx_init_control_state( hwd_control_state_t *ctl ) 00291 { 00292 ( void ) ctl; /*unused */ 00293 00294 return PAPI_OK; 00295 } 00296 00297 int 00298 _mx_update_control_state( hwd_control_state_t *ctl, NativeInfo_t *native, 00299 int count, hwd_context_t *ctx ) 00300 { 00301 ( void ) ctx; /*unused */ 00302 int i, index; 00303 00304 MX_control_state_t *mx_ctl = (MX_control_state_t *)ctl; 00305 00306 for(i=0; i<count; i++ ) { 00307 index = native[i].ni_event; 00308 mx_ctl->which_counter[i]=index; 00309 // printf("Mapping event# %d to HW counter %d (count=%d)\n", 00310 // i,index,count); 00311 native[i].ni_position = i; 00312 } 00313 00314 mx_ctl->num_events=count; 00315 00316 return PAPI_OK; 00317 } 00318 00319 00320 int 00321 _mx_start( hwd_context_t *ctx, hwd_control_state_t *ctl ) 00322 { 00323 00324 long long mx_counters[MX_MAX_COUNTERS]; 00325 00326 ( void ) ctx; /*unused */ 00327 00328 MX_control_state_t *mx_ctl = (MX_control_state_t *)ctl; 00329 int i; 00330 00331 read_mx_counters( mx_counters ); 00332 00333 // for(i=0;i<MX_MAX_COUNTERS;i++) printf("%d %lld\n",i,mx_counters[i]); 00334 00335 for(i=0;i<mx_ctl->num_events;i++) { 00336 mx_ctl->current_count[i]= 00337 mx_counters[mx_ctl->which_counter[i]]; 00338 mx_ctl->start_count[i]=mx_ctl->current_count[i]; 00339 } 00340 00341 return PAPI_OK; 00342 } 00343 00344 00345 int 00346 _mx_stop( hwd_context_t *ctx, hwd_control_state_t *ctl ) 00347 { 00348 ( void ) ctx; /*unused */ 00349 00350 long long mx_counters[MX_MAX_COUNTERS]; 00351 MX_control_state_t *mx_ctl = (MX_control_state_t *)ctl; 00352 int i; 00353 00354 read_mx_counters( mx_counters ); 00355 00356 for(i=0;i<mx_ctl->num_events;i++) { 00357 mx_ctl->current_count[i]= 00358 mx_counters[mx_ctl->which_counter[i]]; 00359 } 00360 00361 return PAPI_OK; 00362 } 00363 00364 int 00365 _mx_read( hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, 00366 int flags ) 00367 { 00368 ( void ) ctx; /*unused */ 00369 ( void ) flags; /*unused */ 00370 int i; 00371 long long mx_counters[MX_MAX_COUNTERS]; 00372 00373 MX_control_state_t *mx_ctl = (MX_control_state_t *)ctl; 00374 00375 read_mx_counters( mx_counters ); 00376 00377 for ( i = 0; i < mx_ctl->num_events; i++ ) { 00378 mx_ctl->current_count[i]= 00379 mx_counters[mx_ctl->which_counter[i]]; 00380 mx_ctl->difference[i] = mx_ctl->current_count[i]- 00381 mx_ctl->start_count[i]; 00382 } 00383 *events = mx_ctl->difference; 00384 00385 return PAPI_OK; 00386 } 00387 00388 00389 int 00390 _mx_reset( hwd_context_t * ctx, hwd_control_state_t * ctrl ) 00391 { 00392 _mx_start( ctx, ctrl ); 00393 return PAPI_OK; 00394 } 00395 00396 int 00397 _mx_write( hwd_context_t * ctx, hwd_control_state_t * ctrl, long long *from ) 00398 { 00399 ( void ) ctx; /*unused */ 00400 ( void ) ctrl; /*unused */ 00401 ( void ) from; /*unused */ 00402 00403 return PAPI_OK; 00404 } 00405 00406 /* 00407 * Functions for setting up various options 00408 */ 00409 00410 /* This function sets various options in the component 00411 * The valid codes being passed in are PAPI_SET_DEFDOM, 00412 * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT 00413 */ 00414 int 00415 _mx_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option ) 00416 { 00417 ( void ) ctx; /*unused */ 00418 ( void ) code; /*unused */ 00419 ( void ) option; /*unused */ 00420 00421 return PAPI_OK; 00422 } 00423 00424 /* 00425 * This function has to set the bits needed to count different domains 00426 * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER 00427 * By default return PAPI_EINVAL if none of those are specified 00428 * and PAPI_OK with success 00429 * PAPI_DOM_USER is only user context is counted 00430 * PAPI_DOM_KERNEL is only the Kernel/OS context is counted 00431 * PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses) 00432 * PAPI_DOM_ALL is all of the domains 00433 */ 00434 int 00435 _mx_set_domain( hwd_control_state_t * cntrl, int domain ) 00436 { 00437 ( void ) cntrl; /*unused */ 00438 int found = 0; 00439 if ( PAPI_DOM_USER & domain ) { 00440 found = 1; 00441 } 00442 if ( PAPI_DOM_KERNEL & domain ) { 00443 found = 1; 00444 } 00445 if ( PAPI_DOM_OTHER & domain ) { 00446 found = 1; 00447 } 00448 if ( !found ) 00449 return PAPI_EINVAL; 00450 return PAPI_OK; 00451 } 00452 00453 00454 00455 int 00456 _mx_ntv_code_to_name( unsigned int EventCode, char *name, int len ) 00457 { 00458 00459 int event=EventCode; 00460 00461 if (event >=0 && event < num_events) { 00462 strncpy( name, mx_native_table[event].name, len ); 00463 return PAPI_OK; 00464 } 00465 return PAPI_ENOEVNT; 00466 00467 00468 } 00469 00470 int 00471 _mx_ntv_code_to_descr( unsigned int EventCode, char *name, int len ) 00472 { 00473 int event=EventCode; 00474 00475 if (event >=0 && event < num_events) { 00476 strncpy( name, mx_native_table[event].description, len ); 00477 return PAPI_OK; 00478 } 00479 return PAPI_ENOEVNT; 00480 } 00481 00482 00483 00484 int 00485 _mx_ntv_enum_events( unsigned int *EventCode, int modifier ) 00486 { 00487 00488 if ( modifier == PAPI_ENUM_FIRST ) { 00489 if (num_events==0) return PAPI_ENOEVNT; 00490 *EventCode = 0; 00491 return PAPI_OK; 00492 } 00493 00494 if ( modifier == PAPI_ENUM_EVENTS ) { 00495 int index = *EventCode; 00496 00497 if ( mx_native_table[index + 1].resources.selector ) { 00498 *EventCode = *EventCode + 1; 00499 return PAPI_OK; 00500 } else { 00501 return PAPI_ENOEVNT; 00502 } 00503 } 00504 00505 return PAPI_EINVAL; 00506 } 00507 00508 00509 papi_vector_t _mx_vector = { 00510 .cmp_info = { 00511 .name = "mx", 00512 .short_name = "mx", 00513 .version = "1.4", 00514 .description = "Myricom MX (Myrinet Express) statistics", 00515 .num_mpx_cntrs = MX_MAX_COUNTERS, 00516 .num_cntrs = MX_MAX_COUNTERS, 00517 .default_domain = PAPI_DOM_USER, 00518 .default_granularity = PAPI_GRN_THR, 00519 .available_granularities = PAPI_GRN_THR, 00520 .hardware_intr_sig = PAPI_INT_SIGNAL, 00521 00522 /* component specific cmp_info initializations */ 00523 .fast_real_timer = 0, 00524 .fast_virtual_timer = 0, 00525 .attach = 0, 00526 .attach_must_ptrace = 0, 00527 .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL, 00528 }, 00529 00530 /* sizes of framework-opaque component-private structures */ 00531 .size = { 00532 .context = sizeof ( MX_context_t ), 00533 .control_state = sizeof ( MX_control_state_t ), 00534 .reg_value = sizeof ( MX_register_t ), 00535 .reg_alloc = sizeof ( MX_reg_alloc_t ), 00536 }, 00537 /* function pointers in this component */ 00538 .init_thread = _mx_init_thread, 00539 .init_component = _mx_init_component, 00540 .init_control_state = _mx_init_control_state, 00541 .start = _mx_start, 00542 .stop = _mx_stop, 00543 .read = _mx_read, 00544 .shutdown_thread = _mx_shutdown_thread, 00545 .shutdown_component = _mx_shutdown_component, 00546 .ctl = _mx_ctl, 00547 .update_control_state = _mx_update_control_state, 00548 .set_domain = _mx_set_domain, 00549 .reset = _mx_reset, 00550 00551 .ntv_enum_events = _mx_ntv_enum_events, 00552 .ntv_code_to_name = _mx_ntv_code_to_name, 00553 .ntv_code_to_descr = _mx_ntv_code_to_descr, 00554 };