{
int status, retval, num_tests = 2, tmp;
int EventSet1 = PAPI_NULL, EventSet2 = PAPI_NULL;
int PAPI_event, PAPI_event2, mask1, mask2;
int num_events1, num_events2;
long long **values;
long long elapsed_us, elapsed_cyc, elapsed_virt_us, elapsed_virt_cyc;
char event_name[PAPI_MAX_STR_LEN], add_event_str[PAPI_MAX_STR_LEN];
const PAPI_component_info_t *cmpinfo;
pid_t pid;
tests_quiet( argc, argv );
retval = PAPI_library_init( PAPI_VER_CURRENT );
if ( retval != PAPI_VER_CURRENT ) {
test_fail_exit( __FILE__, __LINE__, "PAPI_library_init", retval );
}
if ( ( cmpinfo = PAPI_get_component_info( 0 ) ) == NULL ) {
test_fail_exit( __FILE__, __LINE__, "PAPI_get_component_info", 0 );
}
if ( cmpinfo->attach == 0 ) {
test_skip( __FILE__, __LINE__,
"Platform does not support attaching",0 );
}
pid = fork( );
if ( pid < 0 ) {
test_fail_exit( __FILE__, __LINE__, "fork()", PAPI_ESYS );
}
if ( pid == 0 ) {
exit( wait_for_attach_and_loop( 2 ) );
}
EventSet1 = add_two_events( &num_events1, &PAPI_event, &mask1 );
EventSet2 = add_two_events( &num_events2, &PAPI_event2, &mask2 );
if ( cmpinfo->attach_must_ptrace ) {
if ( ptrace( PTRACE_ATTACH, pid, NULL, NULL ) == -1 ) {
perror( "ptrace(PTRACE_ATTACH)" );
return 1;
}
if ( waitpid( pid, &status, 0 ) == -1 ) {
perror( "waitpid()" );
exit( 1 );
}
if ( WIFSTOPPED( status ) == 0 ) {
test_fail( __FILE__, __LINE__,
"Child process didnt return true to WIFSTOPPED", 0 );
}
}
retval = PAPI_attach( EventSet2, ( unsigned long ) pid );
if ( retval != PAPI_OK ) {
test_fail( __FILE__, __LINE__, "PAPI_attach", retval );
}
retval = PAPI_event_code_to_name( PAPI_event, event_name );
if ( retval != PAPI_OK ) {
test_fail( __FILE__, __LINE__, "PAPI_event_code_to_name", retval );
}
sprintf( add_event_str, "PAPI_add_event[%s]", event_name );
values = allocate_test_space( num_tests, num_events1 );
elapsed_us = PAPI_get_real_usec( );
elapsed_cyc = PAPI_get_real_cyc( );
elapsed_virt_us = PAPI_get_virt_usec( );
elapsed_virt_cyc = PAPI_get_virt_cyc( );
if ( cmpinfo->attach_must_ptrace ) {
if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) {
perror( "ptrace(PTRACE_CONT)" );
return 1;
}
if ( waitpid( pid, &status, 0 ) == -1 ) {
perror( "waitpid()" );
exit( 1 );
}
if ( WIFSTOPPED( status ) == 0 ) {
test_fail( __FILE__, __LINE__,
"Child process didn't return true to WIFSTOPPED", 0 );
}
if ( WSTOPSIG( status ) != SIGSTOP ) {
test_fail( __FILE__, __LINE__,
"Child process didn't stop on SIGSTOP", 0 );
}
}
retval = PAPI_start( EventSet1 );
if ( retval != PAPI_OK ) {
test_fail( __FILE__, __LINE__, "PAPI_start", retval );
}
retval = PAPI_start( EventSet2 );
if ( retval != PAPI_OK ) {
test_fail( __FILE__, __LINE__, "PAPI_start", retval );
}
if ( cmpinfo->attach_must_ptrace ) {
if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) {
perror( "ptrace(PTRACE_ATTACH)" );
return 1;
}
if ( waitpid( pid, &status, 0 ) == -1 ) {
perror( "waitpid()" );
exit( 1 );
}
if ( WIFSTOPPED( status ) == 0 ) {
test_fail( __FILE__, __LINE__,
"Child process didn't return true to WIFSTOPPED", 0 );
}
if ( WSTOPSIG( status ) != SIGSTOP ) {
test_fail( __FILE__, __LINE__,
"Child process didn't stop on SIGSTOP", 0 );
}
}
elapsed_virt_us = PAPI_get_virt_usec( ) - elapsed_virt_us;
elapsed_virt_cyc = PAPI_get_virt_cyc( ) - elapsed_virt_cyc;
elapsed_us = PAPI_get_real_usec( ) - elapsed_us;
elapsed_cyc = PAPI_get_real_cyc( ) - elapsed_cyc;
retval = PAPI_stop( EventSet1, values[0] );
if ( retval != PAPI_OK ) {
printf( "Warning: PAPI_stop returned error %d, probably ok.\n",
retval );
}
retval = PAPI_stop( EventSet2, values[1] );
if ( retval != PAPI_OK ) {
printf( "Warning: PAPI_stop returned error %d, probably ok.\n",
retval );
}
remove_test_events( &EventSet1, mask1 );
remove_test_events( &EventSet2, mask2 );
if ( cmpinfo->attach_must_ptrace ) {
if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) {
perror( "ptrace(PTRACE_CONT)" );
return 1;
}
}
if ( waitpid( pid, &status, 0 ) == -1 ) {
perror( "waitpid()" );
exit( 1 );
}
if ( WIFEXITED( status ) == 0 ) {
test_fail( __FILE__, __LINE__,
"Child process didn't return true to WIFEXITED", 0 );
}
printf( "Test case: multiple 3rd party attach start, stop.\n" );
printf( "-----------------------------------------------\n" );
tmp = PAPI_get_opt( PAPI_DEFDOM, NULL );
printf( "Default domain is: %d (%s)\n", tmp, stringify_all_domains( tmp ) );
tmp = PAPI_get_opt( PAPI_DEFGRN, NULL );
printf( "Default granularity is: %d (%s)\n", tmp,
stringify_granularity( tmp ) );
printf( "Using %d iterations of c += a*b\n", NUM_FLOPS );
printf( "-------------------------------------------------------------------------\n" );
sprintf( add_event_str, "(PID self) %-12s : \t",
event_name );
printf( TAB1, add_event_str, values[0][1] );
sprintf( add_event_str, "(PID self) PAPI_TOT_CYC : \t" );
printf( TAB1, add_event_str, values[0][0] );
sprintf( add_event_str, "(PID %jd) %-12s : \t", ( intmax_t ) pid,
event_name );
printf( TAB1, add_event_str, values[1][1] );
sprintf( add_event_str, "(PID %jd) PAPI_TOT_CYC : \t",
( intmax_t ) pid );
printf( TAB1, add_event_str, values[1][0] );
printf( TAB1, "Real usec : \t", elapsed_us );
printf( TAB1, "Real cycles : \t", elapsed_cyc );
printf( TAB1, "Virt usec : \t", elapsed_virt_us );
printf( TAB1, "Virt cycles : \t", elapsed_virt_cyc );
printf( "-------------------------------------------------------------------------\n" );
printf( "Verification: none\n" );
test_pass( __FILE__, values, num_tests );
return 0;
}