|
PAPI
5.0.1.0
|
00001 /* This file performs the following test: start, stop and timer functionality for 00002 multiple attached processes. 00003 00004 - It attempts to use the following two counters. It may use less depending on 00005 hardware counter resource limitations. These are counted in the default counting 00006 domain and default granularity, depending on the platform. Usually this is 00007 the user domain (PAPI_DOM_USER) and thread context (PAPI_GRN_THR). 00008 + PAPI_FP_INS 00009 + PAPI_TOT_CYC 00010 - Get us. 00011 - Start counters 00012 - Do flops 00013 - Stop and read counters 00014 - Get us. 00015 */ 00016 00017 #include "papi_test.h" 00018 #include <sys/ptrace.h> 00019 #include <inttypes.h> 00020 00021 #ifdef _AIX 00022 #define _LINUX_SOURCE_COMPAT 00023 #endif 00024 00025 #if defined(__FreeBSD__) 00026 # define PTRACE_ATTACH PT_ATTACH 00027 # define PTRACE_CONT PT_CONTINUE 00028 #endif 00029 00030 int 00031 wait_for_attach_and_loop( int num ) 00032 { 00033 kill( getpid( ), SIGSTOP ); 00034 do_flops( NUM_FLOPS * num ); 00035 kill( getpid( ), SIGSTOP ); 00036 return ( 0 ); 00037 } 00038 00039 int 00040 main( int argc, char **argv ) 00041 { 00042 int status, retval, num_tests = 2, tmp; 00043 int EventSet1 = PAPI_NULL, EventSet2 = PAPI_NULL; 00044 int PAPI_event, PAPI_event2, mask1, mask2; 00045 int num_events1, num_events2; 00046 long long **values; 00047 long long elapsed_us, elapsed_cyc, elapsed_virt_us, elapsed_virt_cyc; 00048 char event_name[PAPI_MAX_STR_LEN], add_event_str[PAPI_MAX_STR_LEN]; 00049 const PAPI_component_info_t *cmpinfo; 00050 pid_t pid, pid2; 00051 double ratio1,ratio2; 00052 00053 /* Set TESTS_QUIET variable */ 00054 tests_quiet( argc, argv ); 00055 00056 /* Initialize the library */ 00057 retval = PAPI_library_init( PAPI_VER_CURRENT ); 00058 if ( retval != PAPI_VER_CURRENT ) { 00059 test_fail_exit( __FILE__, __LINE__, "PAPI_library_init", retval ); 00060 } 00061 00062 /* get the component info and check if we support attach */ 00063 if ( ( cmpinfo = PAPI_get_component_info( 0 ) ) == NULL ) { 00064 test_fail_exit( __FILE__, __LINE__, "PAPI_get_component_info", 0 ); 00065 } 00066 00067 if ( cmpinfo->attach == 0 ) { 00068 test_skip( __FILE__, __LINE__, 00069 "Platform does not support attaching", 0 ); 00070 } 00071 00072 /* fork off first child */ 00073 pid = fork( ); 00074 if ( pid < 0 ) { 00075 test_fail_exit( __FILE__, __LINE__, "fork()", PAPI_ESYS ); 00076 } 00077 if ( pid == 0 ) { 00078 exit( wait_for_attach_and_loop( 1 ) ); 00079 } 00080 00081 /* fork off second child, does twice as much */ 00082 pid2 = fork( ); 00083 if ( pid2 < 0 ) { 00084 test_fail_exit( __FILE__, __LINE__, "fork()", PAPI_ESYS ); 00085 } 00086 if ( pid2 == 0 ) { 00087 exit( wait_for_attach_and_loop( 2 ) ); 00088 } 00089 00090 /* add PAPI_TOT_CYC and one of the events in 00091 PAPI_FP_INS, PAPI_FP_OPS or PAPI_TOT_INS, 00092 depending on the availability of the event 00093 on the platform */ 00094 EventSet1 = add_two_events( &num_events1, &PAPI_event, &mask1 ); 00095 EventSet2 = add_two_events( &num_events2, &PAPI_event2, &mask2 ); 00096 00097 if ( cmpinfo->attach_must_ptrace ) { 00098 if ( ptrace( PTRACE_ATTACH, pid, NULL, NULL ) == -1 ) { 00099 perror( "ptrace(PTRACE_ATTACH)" ); 00100 return 1 ; 00101 } 00102 if ( waitpid( pid, &status, 0 ) == -1 ) { 00103 perror( "waitpid()" ); 00104 exit( 1 ); 00105 } 00106 if ( WIFSTOPPED( status ) == 0 ) { 00107 test_fail( __FILE__, __LINE__, 00108 "Child process didnt return true to WIFSTOPPED", 0 ); 00109 } 00110 00111 if ( ptrace( PTRACE_ATTACH, pid2, NULL, NULL ) == -1 ) { 00112 perror( "ptrace(PTRACE_ATTACH)" ); 00113 return 1; 00114 } 00115 if ( waitpid( pid2, &status, 0 ) == -1 ) { 00116 perror( "waitpid()" ); 00117 exit( 1 ); 00118 } 00119 if ( WIFSTOPPED( status ) == 0 ) { 00120 test_fail( __FILE__, __LINE__, 00121 "Child process didnt return true to WIFSTOPPED", 0 ); 00122 } 00123 } 00124 00125 retval = PAPI_attach( EventSet1, ( unsigned long ) pid ); 00126 if ( retval != PAPI_OK ) { 00127 test_fail( __FILE__, __LINE__, "PAPI_attach", retval ); 00128 } 00129 00130 retval = PAPI_attach( EventSet2, ( unsigned long ) pid2 ); 00131 if ( retval != PAPI_OK ) { 00132 test_fail( __FILE__, __LINE__, "PAPI_attach", retval ); 00133 } 00134 00135 retval = PAPI_event_code_to_name( PAPI_event, event_name ); 00136 if ( retval != PAPI_OK ) { 00137 test_fail( __FILE__, __LINE__, "PAPI_event_code_to_name", retval ); 00138 } 00139 sprintf( add_event_str, "PAPI_add_event[%s]", event_name ); 00140 00141 /* num_events1 is greater than num_events2 so don't worry. */ 00142 00143 values = allocate_test_space( num_tests, num_events1 ); 00144 00145 /* Gather before values */ 00146 elapsed_us = PAPI_get_real_usec( ); 00147 elapsed_cyc = PAPI_get_real_cyc( ); 00148 elapsed_virt_us = PAPI_get_virt_usec( ); 00149 elapsed_virt_cyc = PAPI_get_virt_cyc( ); 00150 00151 /* Wait for the SIGSTOP. */ 00152 if ( cmpinfo->attach_must_ptrace ) { 00153 if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) { 00154 perror( "ptrace(PTRACE_CONT)" ); 00155 return 1; 00156 } 00157 if ( waitpid( pid, &status, 0 ) == -1 ) { 00158 perror( "waitpid()" ); 00159 exit( 1 ); 00160 } 00161 if ( WIFSTOPPED( status ) == 0 ) { 00162 test_fail( __FILE__, __LINE__, 00163 "Child process didn't return true to WIFSTOPPED", 0 ); 00164 } 00165 if ( WSTOPSIG( status ) != SIGSTOP ) { 00166 test_fail( __FILE__, __LINE__, 00167 "Child process didn't stop on SIGSTOP", 0 ); 00168 } 00169 00170 if ( ptrace( PTRACE_CONT, pid2, NULL, NULL ) == -1 ) { 00171 perror( "ptrace(PTRACE_CONT)" ); 00172 return 1; 00173 } 00174 if ( waitpid( pid2, &status, 0 ) == -1 ) { 00175 perror( "waitpid()" ); 00176 exit( 1 ); 00177 } 00178 if ( WIFSTOPPED( status ) == 0 ) { 00179 test_fail( __FILE__, __LINE__, 00180 "Child process didn't return true to WIFSTOPPED", 0 ); 00181 } 00182 if ( WSTOPSIG( status ) != SIGSTOP ) { 00183 test_fail( __FILE__, __LINE__, 00184 "Child process didn't stop on SIGSTOP", 0 ); 00185 } 00186 } 00187 00188 /* start first child */ 00189 retval = PAPI_start( EventSet1 ); 00190 if ( retval != PAPI_OK ) { 00191 test_fail( __FILE__, __LINE__, "PAPI_start", retval ); 00192 } 00193 00194 /* start second child */ 00195 retval = PAPI_start( EventSet2 ); 00196 if ( retval != PAPI_OK ) { 00197 test_fail( __FILE__, __LINE__, "PAPI_start", retval ); 00198 } 00199 00200 /* Wait for the SIGSTOP. */ 00201 if ( cmpinfo->attach_must_ptrace ) { 00202 if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) { 00203 perror( "ptrace(PTRACE_ATTACH)" ); 00204 return 1; 00205 } 00206 if ( waitpid( pid, &status, 0 ) == -1 ) { 00207 perror( "waitpid()" ); 00208 exit( 1 ); 00209 } 00210 if ( WIFSTOPPED( status ) == 0 ) { 00211 test_fail( __FILE__, __LINE__, 00212 "Child process didn't return true to WIFSTOPPED", 0 ); 00213 } 00214 if ( WSTOPSIG( status ) != SIGSTOP ) { 00215 test_fail( __FILE__, __LINE__, 00216 "Child process didn't stop on SIGSTOP", 0 ); 00217 } 00218 00219 if ( ptrace( PTRACE_CONT, pid2, NULL, NULL ) == -1 ) { 00220 perror( "ptrace(PTRACE_ATTACH)" ); 00221 return 1; 00222 } 00223 if ( waitpid( pid2, &status, 0 ) == -1 ) { 00224 perror( "waitpid()" ); 00225 exit( 1 ); 00226 } 00227 if ( WIFSTOPPED( status ) == 0 ) { 00228 test_fail( __FILE__, __LINE__, 00229 "Child process didn't return true to WIFSTOPPED", 0 ); 00230 } 00231 if ( WSTOPSIG( status ) != SIGSTOP ) { 00232 test_fail( __FILE__, __LINE__, 00233 "Child process didn't stop on SIGSTOP", 0 ); 00234 } 00235 } 00236 00237 elapsed_virt_us = PAPI_get_virt_usec( ) - elapsed_virt_us; 00238 elapsed_virt_cyc = PAPI_get_virt_cyc( ) - elapsed_virt_cyc; 00239 elapsed_us = PAPI_get_real_usec( ) - elapsed_us; 00240 elapsed_cyc = PAPI_get_real_cyc( ) - elapsed_cyc; 00241 00242 /* stop first child */ 00243 retval = PAPI_stop( EventSet1, values[0] ); 00244 if ( retval != PAPI_OK ) { 00245 printf( "Warning: PAPI_stop returned error %d, probably ok.\n", 00246 retval ); 00247 } 00248 00249 /* stop second child */ 00250 retval = PAPI_stop( EventSet2, values[1] ); 00251 if ( retval != PAPI_OK ) { 00252 printf( "Warning: PAPI_stop returned error %d, probably ok.\n", 00253 retval ); 00254 } 00255 00256 remove_test_events( &EventSet1, mask1 ); 00257 remove_test_events( &EventSet2, mask2 ); 00258 00259 if ( cmpinfo->attach_must_ptrace ) { 00260 if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) { 00261 perror( "ptrace(PTRACE_CONT)" ); 00262 return 1; 00263 } 00264 if ( ptrace( PTRACE_CONT, pid2, NULL, NULL ) == -1 ) { 00265 perror( "ptrace(PTRACE_CONT)" ); 00266 return 1; 00267 } 00268 } 00269 00270 if ( waitpid( pid, &status, 0 ) == -1 ) { 00271 perror( "waitpid()" ); 00272 exit( 1 ); 00273 } 00274 if ( WIFEXITED( status ) == 0 ) { 00275 test_fail( __FILE__, __LINE__, 00276 "Child process didn't return true to WIFEXITED", 0 ); 00277 } 00278 00279 if ( waitpid( pid2, &status, 0 ) == -1 ) { 00280 perror( "waitpid()" ); 00281 exit( 1 ); 00282 } 00283 if ( WIFEXITED( status ) == 0 ) { 00284 test_fail( __FILE__, __LINE__, 00285 "Child process didn't return true to WIFEXITED", 0 ); 00286 } 00287 00288 /* This code isn't necessary as we know the child has exited, */ 00289 /* it *may* return an error if the component so chooses. You */ 00290 /* should use read() instead. */ 00291 00292 printf( "Test case: multiple 3rd party attach start, stop.\n" ); 00293 printf( "-----------------------------------------------\n" ); 00294 tmp = PAPI_get_opt( PAPI_DEFDOM, NULL ); 00295 printf( "Default domain is: %d (%s)\n", tmp, 00296 stringify_all_domains( tmp ) ); 00297 tmp = PAPI_get_opt( PAPI_DEFGRN, NULL ); 00298 printf( "Default granularity is: %d (%s)\n", tmp, 00299 stringify_granularity( tmp ) ); 00300 printf( "Using %d iterations of c += a*b\n", NUM_FLOPS ); 00301 printf( "-------------------------------------------------------------------------\n" ); 00302 00303 sprintf( add_event_str, "(PID %jd) %-12s : \t", ( intmax_t ) pid, 00304 event_name ); 00305 printf( TAB1, add_event_str, values[0][1] ); 00306 sprintf( add_event_str, "(PID %jd) PAPI_TOT_CYC : \t", 00307 ( intmax_t ) pid ); 00308 printf( TAB1, add_event_str, values[0][0] ); 00309 sprintf( add_event_str, "(PID %jd) %-12s : \t", ( intmax_t ) pid2, 00310 event_name ); 00311 printf( TAB1, add_event_str,values[1][1] ); 00312 sprintf( add_event_str, "(PID %jd) PAPI_TOT_CYC : \t", 00313 ( intmax_t ) pid2 ); 00314 printf( TAB1, add_event_str, values[1][0] ); 00315 printf( TAB1, "Real usec : \t", elapsed_us ); 00316 printf( TAB1, "Real cycles : \t", elapsed_cyc ); 00317 printf( TAB1, "Virt usec : \t", elapsed_virt_us ); 00318 printf( TAB1, "Virt cycles : \t", elapsed_virt_cyc ); 00319 00320 printf 00321 ( "-------------------------------------------------------------------------\n" ); 00322 00323 printf("Verification: pid %d results should be twice pid %d\n",pid2,pid ); 00324 00325 ratio1=(double)values[1][0]/(double)values[0][0]; 00326 ratio2=(double)values[1][1]/(double)values[0][1]; 00327 00328 printf("\t%lld/%lld = %lf\n",values[1][0],values[0][0],ratio1); 00329 00330 00331 if ((ratio1 >2.15 ) || (ratio1 < 1.85)) { 00332 printf("Ratio out of range, should be ~2.0 not %lf\n",ratio1); 00333 test_fail( __FILE__, __LINE__, 00334 "Error: Counter ratio not two", 0 ); 00335 } 00336 00337 printf("\t%lld/%lld = %lf\n",values[1][1],values[0][1],ratio2); 00338 00339 if ((ratio2 >2.75 ) || (ratio2 < 1.25)) { 00340 printf("Ratio out of range, should be ~2.0, not %lf\n",ratio2); 00341 test_fail( __FILE__, __LINE__, 00342 "Known issue: Counter ratio not two", 0 ); 00343 } 00344 00345 test_pass( __FILE__, values, num_tests ); 00346 return 0; 00347 }