PAPI  5.0.1.0
multiattach2.c
Go to the documentation of this file.
00001 /* This file performs the following test: start, stop and timer functionality for
00002    an attached process as well as itself.
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;
00051 
00052     /* Set TESTS_QUIET variable */
00053     tests_quiet( argc, argv );
00054 
00055     /* init the library */
00056     retval = PAPI_library_init( PAPI_VER_CURRENT );
00057     if ( retval != PAPI_VER_CURRENT ) {
00058        test_fail_exit( __FILE__, __LINE__, "PAPI_library_init", retval );
00059     }
00060 
00061     /* get component info */
00062     if ( ( cmpinfo = PAPI_get_component_info( 0 ) ) == NULL ) {
00063        test_fail_exit( __FILE__, __LINE__, "PAPI_get_component_info", 0 );
00064     }
00065 
00066     /* see if we support attach */
00067     if ( cmpinfo->attach == 0 ) {
00068        test_skip( __FILE__, __LINE__, 
00069               "Platform does not support attaching",0 );
00070     }
00071 
00072     /* fork! */
00073     pid = fork(  );
00074     if ( pid < 0 ) {
00075       test_fail_exit( __FILE__, __LINE__, "fork()", PAPI_ESYS );
00076     }
00077 
00078     /* if child, wait_for_attach_and_loop */
00079     if ( pid == 0 ) {
00080        exit( wait_for_attach_and_loop( 2 ) );
00081     }
00082 
00083     /* add PAPI_TOT_CYC and one of the events in 
00084        PAPI_FP_INS, PAPI_FP_OPS or PAPI_TOT_INS, 
00085        depending on the availability of the event 
00086        on the platform                            */
00087     EventSet1 = add_two_events( &num_events1, &PAPI_event, &mask1 );
00088     EventSet2 = add_two_events( &num_events2, &PAPI_event2, &mask2 );
00089 
00090     if ( cmpinfo->attach_must_ptrace ) {
00091        if ( ptrace( PTRACE_ATTACH, pid, NULL, NULL ) == -1 ) {
00092           perror( "ptrace(PTRACE_ATTACH)" );
00093           return 1;
00094        }
00095        if ( waitpid( pid, &status, 0 ) == -1 ) {
00096           perror( "waitpid()" );
00097           exit( 1 );
00098        }
00099        if ( WIFSTOPPED( status ) == 0 ) {
00100           test_fail( __FILE__, __LINE__,
00101             "Child process didnt return true to WIFSTOPPED", 0 );
00102        }
00103     }
00104 
00105     retval = PAPI_attach( EventSet2, ( unsigned long ) pid );
00106     if ( retval != PAPI_OK ) {
00107        test_fail( __FILE__, __LINE__, "PAPI_attach", retval ); 
00108     }
00109 
00110     retval = PAPI_event_code_to_name( PAPI_event, event_name );
00111     if ( retval != PAPI_OK ) {
00112        test_fail( __FILE__, __LINE__, "PAPI_event_code_to_name", retval );
00113     }
00114     sprintf( add_event_str, "PAPI_add_event[%s]", event_name );
00115 
00116     /* num_events1 is greater than num_events2 so don't worry. */
00117 
00118     values = allocate_test_space( num_tests, num_events1 );
00119 
00120     /* get before values */
00121     elapsed_us = PAPI_get_real_usec(  );
00122     elapsed_cyc = PAPI_get_real_cyc(  );
00123     elapsed_virt_us = PAPI_get_virt_usec(  );
00124     elapsed_virt_cyc = PAPI_get_virt_cyc(  );
00125 
00126     /* Wait for the SIGSTOP. */
00127     if ( cmpinfo->attach_must_ptrace ) {
00128        if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) {
00129           perror( "ptrace(PTRACE_CONT)" );
00130           return 1;
00131        }
00132        if ( waitpid( pid, &status, 0 ) == -1 ) {
00133           perror( "waitpid()" );
00134           exit( 1 );
00135        }
00136        if ( WIFSTOPPED( status ) == 0 ) {
00137           test_fail( __FILE__, __LINE__,
00138             "Child process didn't return true to WIFSTOPPED", 0 );
00139        }
00140        if ( WSTOPSIG( status ) != SIGSTOP ) {
00141           test_fail( __FILE__, __LINE__,
00142              "Child process didn't stop on SIGSTOP", 0 );
00143        }
00144     }
00145 
00146     retval = PAPI_start( EventSet1 );
00147     if ( retval != PAPI_OK ) {
00148        test_fail( __FILE__, __LINE__, "PAPI_start", retval );
00149     }
00150 
00151     retval = PAPI_start( EventSet2 );
00152     if ( retval != PAPI_OK ) {
00153        test_fail( __FILE__, __LINE__, "PAPI_start", retval );      
00154     }
00155 
00156     /* Wait for the SIGSTOP. */
00157     if ( cmpinfo->attach_must_ptrace ) {
00158        if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) {
00159           perror( "ptrace(PTRACE_ATTACH)" );
00160           return 1;
00161        }
00162        if ( waitpid( pid, &status, 0 ) == -1 ) {
00163           perror( "waitpid()" );
00164           exit( 1 );
00165        }
00166        if ( WIFSTOPPED( status ) == 0 ) {
00167           test_fail( __FILE__, __LINE__,
00168             "Child process didn't return true to WIFSTOPPED", 0 );
00169        }
00170        if ( WSTOPSIG( status ) != SIGSTOP ) {
00171           test_fail( __FILE__, __LINE__,
00172              "Child process didn't stop on SIGSTOP", 0 );
00173        }
00174     }
00175 
00176     elapsed_virt_us = PAPI_get_virt_usec(  ) - elapsed_virt_us;
00177     elapsed_virt_cyc = PAPI_get_virt_cyc(  ) - elapsed_virt_cyc;
00178     elapsed_us = PAPI_get_real_usec(  ) - elapsed_us;
00179     elapsed_cyc = PAPI_get_real_cyc(  ) - elapsed_cyc;
00180 
00181     retval = PAPI_stop( EventSet1, values[0] );
00182     if ( retval != PAPI_OK ) {
00183        printf( "Warning: PAPI_stop returned error %d, probably ok.\n",
00184                 retval );
00185     }
00186 
00187     retval = PAPI_stop( EventSet2, values[1] );
00188     if ( retval != PAPI_OK ) {
00189        printf( "Warning: PAPI_stop returned error %d, probably ok.\n",
00190                 retval );
00191     }
00192 
00193     remove_test_events( &EventSet1, mask1 );
00194     remove_test_events( &EventSet2, mask2 );
00195 
00196     if ( cmpinfo->attach_must_ptrace ) {
00197        if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) {
00198           perror( "ptrace(PTRACE_CONT)" );
00199           return 1;
00200        }
00201     }
00202 
00203     if ( waitpid( pid, &status, 0 ) == -1 ) {
00204        perror( "waitpid()" );
00205        exit( 1 );
00206     }
00207     if ( WIFEXITED( status ) == 0 ) {
00208        test_fail( __FILE__, __LINE__,
00209              "Child process didn't return true to WIFEXITED", 0 );
00210     }
00211 
00212     /* This code isn't necessary as we know the child has exited,
00213        it *may* return an error if the component so chooses. 
00214            You should use read() instead. */
00215 
00216     printf( "Test case: multiple 3rd party attach start, stop.\n" );
00217     printf( "-----------------------------------------------\n" );
00218     tmp = PAPI_get_opt( PAPI_DEFDOM, NULL );
00219     printf( "Default domain is: %d (%s)\n", tmp, stringify_all_domains( tmp ) );
00220     tmp = PAPI_get_opt( PAPI_DEFGRN, NULL );
00221     printf( "Default granularity is: %d (%s)\n", tmp,
00222             stringify_granularity( tmp ) );
00223     printf( "Using %d iterations of c += a*b\n", NUM_FLOPS );
00224     printf( "-------------------------------------------------------------------------\n" );
00225 
00226     sprintf( add_event_str, "(PID self) %-12s : \t", 
00227              event_name );
00228     printf( TAB1, add_event_str, values[0][1] );
00229     sprintf( add_event_str, "(PID self) PAPI_TOT_CYC : \t" );
00230     printf( TAB1, add_event_str, values[0][0] );
00231     sprintf( add_event_str, "(PID %jd) %-12s : \t", ( intmax_t ) pid,
00232              event_name );
00233     printf( TAB1, add_event_str, values[1][1] );
00234     sprintf( add_event_str, "(PID %jd) PAPI_TOT_CYC : \t", 
00235          ( intmax_t ) pid );
00236     printf( TAB1, add_event_str, values[1][0] );
00237     printf( TAB1, "Real usec    : \t", elapsed_us );
00238     printf( TAB1, "Real cycles  : \t", elapsed_cyc );
00239     printf( TAB1, "Virt usec    : \t", elapsed_virt_us );
00240     printf( TAB1, "Virt cycles  : \t", elapsed_virt_cyc );
00241 
00242     printf( "-------------------------------------------------------------------------\n" );
00243 
00244     printf( "Verification: none\n" );
00245 
00246     test_pass( __FILE__, values, num_tests );
00247     
00248     return 0;
00249 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines