|
PAPI
5.0.1.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( ) 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 };