int main( int argc, char **argv ) { int status, retval, num_tests = 1, tmp; int EventSet1 = PAPI_NULL; long long **values; long long elapsed_us, elapsed_cyc, elapsed_virt_us, elapsed_virt_cyc; char event_name[PAPI_MAX_STR_LEN];; const PAPI_hw_info_t *hw_info; const PAPI_component_info_t *cmpinfo; pid_t pid; /* Fork before doing anything with the PMU */ setbuf(stdout,NULL); pid = fork( ); if ( pid < 0 ) test_fail( __FILE__, __LINE__, "fork()", PAPI_ESYS ); if ( pid == 0 ) exit( wait_for_attach_and_loop( ) ); tests_quiet( argc, argv ); /* Set TESTS_QUIET variable */ /* Master only process below here */ 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 ); hw_info = PAPI_get_hardware_info( ); if ( hw_info == NULL ) test_fail_exit( __FILE__, __LINE__, "PAPI_get_hardware_info", 0 ); /* add PAPI_TOT_CYC and one of the events in PAPI_FP_INS, PAPI_FP_OPS or PAPI_TOT_INS, depending on the availability of the event on the platform */ retval = PAPI_create_eventset(&EventSet1); if ( retval != PAPI_OK ) test_fail_exit( __FILE__, __LINE__, "PAPI_attach", retval ); /* Force addition of component */ retval = PAPI_assign_eventset_component( EventSet1, 0 ); if ( retval != PAPI_OK ) test_fail( __FILE__, __LINE__, "PAPI_assign_eventset_component", retval ); /* The following call causes this test to fail for perf_events */ retval = PAPI_attach( EventSet1, ( unsigned long ) pid ); if ( retval != PAPI_OK ) test_fail_exit( __FILE__, __LINE__, "PAPI_attach", retval ); sprintf(event_name,"PAPI_TOT_CYC"); retval = PAPI_add_event(EventSet1, PAPI_TOT_CYC); if ( retval != PAPI_OK ) test_fail_exit( __FILE__, __LINE__, "PAPI_add_event", retval ); retval = PAPI_add_event(EventSet1, PAPI_FP_INS); if ( retval == PAPI_ENOEVNT ) { test_warn( __FILE__, __LINE__, "PAPI_FP_INS", retval); } else if ( retval != PAPI_OK ) { test_fail_exit( __FILE__, __LINE__, "PAPI_add_event", retval ); } values = allocate_test_space( 1, 2); 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( ); printf("must_ptrace is %d\n",cmpinfo->attach_must_ptrace); pid_t child = wait( &status ); printf( "Debugger exited wait() with %d\n",child ); if (WIFSTOPPED( status )) { printf( "Child has stopped due to signal %d (%s)\n", WSTOPSIG( status ), strsignal(WSTOPSIG( status )) ); } if (WIFSIGNALED( status )) { printf( "Child %ld received signal %d (%s)\n", (long)child, WTERMSIG(status) , strsignal(WTERMSIG( status )) ); } printf("After %d\n",retval); retval = PAPI_start( EventSet1 ); if ( retval != PAPI_OK ) test_fail_exit( __FILE__, __LINE__, "PAPI_start", retval ); printf("Continuing\n"); #if defined(__FreeBSD__) if ( ptrace( PT_CONTINUE, pid, (caddr_t) 1, 0 ) == -1 ) { #else if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) { #endif perror( "ptrace(PTRACE_CONT)" ); return 1; } do { child = wait( &status ); printf( "Debugger exited wait() with %d\n", child); if (WIFSTOPPED( status )) { printf( "Child has stopped due to signal %d (%s)\n", WSTOPSIG( status ), strsignal(WSTOPSIG( status )) ); } if (WIFSIGNALED( status )) { printf( "Child %ld received signal %d (%s)\n", (long)child, WTERMSIG(status) , strsignal(WTERMSIG( status )) ); } } while (!WIFEXITED( status )); printf("Child exited with value %d\n",WEXITSTATUS(status)); if (WEXITSTATUS(status) != 0) test_fail_exit( __FILE__, __LINE__, "Exit status of child to attach to", PAPI_EMISC); retval = PAPI_stop( EventSet1, values[0] ); if ( retval != PAPI_OK ) test_fail_exit( __FILE__, __LINE__, "PAPI_stop", retval ); 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_cleanup_eventset(EventSet1); if (retval != PAPI_OK) test_fail_exit( __FILE__, __LINE__, "PAPI_cleanup_eventset", retval ); retval = PAPI_destroy_eventset(&EventSet1); if (retval != PAPI_OK) test_fail_exit( __FILE__, __LINE__, "PAPI_destroy_eventset", retval ); printf( "Test case: 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" ); printf( "Test type : \t 1\n" ); printf( TAB1, "PAPI_TOT_CYC : \t", ( values[0] )[0] ); printf( TAB1, "PAPI_FP_INS : \t", ( values[0] )[1] ); 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 ); exit( 1 ); }
int main(int argc, char **argv) { int i; long page_size=getpagesize(); double error; long long start_before,stop_after; void *addr[MAX_EVENTS],*addr2[MAX_EVENTS]; struct perf_event_attr pe; int fd[MAX_EVENTS],fd2[MAX_EVENTS],ret1,ret2; int status; unsigned long long values[MAX_EVENTS],enabled[MAX_EVENTS],running[MAX_EVENTS]; unsigned long long values2[MAX_EVENTS],enabled2[MAX_EVENTS],running2[MAX_EVENTS]; int count=2; pid_t pid,pid2; quiet=test_quiet(); if (!quiet) { printf("This test checks if rdpmc multi-attach works.\n\n"); } /* See if we support rdpmc access */ if (!detect_rdpmc(quiet)) { test_skip(test_string); } /*********************************/ /* start and pause two children */ /*********************************/ /* fork a child */ pid = fork(); if ( pid < 0 ) { fprintf(stderr,"Failed fork\n"); test_fail(test_string); } else if (pid==0) { /* in child */ exit(wait_for_attach_and_loop(1)); } if ( ptrace( PTRACE_ATTACH, pid, NULL, NULL ) == -1 ) { fprintf(stderr,"Error attaching to %d\n",pid); return -1; } if ( waitpid( pid, &status, 0 ) == -1 ) { fprintf(stderr,"Error waitpid %d\n",pid); return -1; } if ( WIFSTOPPED( status ) == 0 ) { fprintf(stderr,"WIFSTOPPED didn't happen %d\n",pid); test_fail(test_string); } /* fork a second child */ pid2 = fork(); if ( pid2 < 0 ) { fprintf(stderr,"Failed fork\n"); test_fail(test_string); } else if (pid2==0) { /* in child */ exit(wait_for_attach_and_loop(2)); } if ( ptrace( PTRACE_ATTACH, pid2, NULL, NULL ) == -1 ) { fprintf(stderr,"Error attaching to %d\n",pid2); return -1; } if ( waitpid( pid2, &status, 0 ) == -1 ) { fprintf(stderr,"Error waitpid %d\n",pid2); return -1; } if ( WIFSTOPPED( status ) == 0 ) { fprintf(stderr,"WIFSTOPPED didn't happen %d\n",pid2); test_fail(test_string); } /*****************************/ /* TEST START/WORK/READ/STOP */ /*****************************/ /* Open event, pid1 */ memset(&pe,0,sizeof(struct perf_event_attr)); pe.type=PERF_TYPE_HARDWARE; pe.size=sizeof(struct perf_event_attr); fd[0]=-1; for(i=0;i<count;i++) { if (i==0) { pe.config=PERF_COUNT_HW_INSTRUCTIONS; pe.disabled=1; pe.pinned=1; } else { pe.config=PERF_COUNT_HW_CPU_CYCLES; pe.disabled=0; pe.pinned=0; } fd[i]=perf_event_open(&pe,pid,-1,fd[0],0); if (fd[i]<0) { fprintf(stderr,"Error opening event %d\n",i); test_fail(test_string); } /* mmap() event */ addr[i]=mmap(NULL,page_size, PROT_READ, MAP_SHARED,fd[i],0); if (addr[i] == MAP_FAILED) { fprintf(stderr,"Error mmap()ing event %d!\n",i); test_fail(test_string); } } /* Open event, pid2 */ memset(&pe,0,sizeof(struct perf_event_attr)); pe.type=PERF_TYPE_HARDWARE; pe.size=sizeof(struct perf_event_attr); fd2[0]=-1; for(i=0;i<count;i++) { if (i==0) { pe.config=PERF_COUNT_HW_INSTRUCTIONS; pe.disabled=1; pe.pinned=1; } else { pe.config=PERF_COUNT_HW_CPU_CYCLES; pe.disabled=0; pe.pinned=0; } fd2[i]=perf_event_open(&pe,pid2,-1,fd2[0],0); if (fd2[i]<0) { fprintf(stderr,"Error opening event %d\n",i); test_fail(test_string); } /* mmap() event */ addr2[i]=mmap(NULL,page_size, PROT_READ, MAP_SHARED,fd2[i],0); if (addr2[i] == MAP_FAILED) { fprintf(stderr,"Error mmap()ing event %d!\n",i); test_fail(test_string); } } /* start */ start_before=rdtsc(); ret1=ioctl(fd[0], PERF_EVENT_IOC_ENABLE,0); /* start up pid */ if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) { fprintf(stderr,"Couldn't continue %d\n",pid); return -1; } if ( waitpid( pid, &status, 0 ) == -1 ) { fprintf(stderr,"Couldn't waitpid() %d\n",pid ); return -1; } if ( WIFSTOPPED( status ) == 0 ) { test_fail(test_string); } if ( WSTOPSIG( status ) != SIGSTOP ) { test_fail(test_string); } ret1=ioctl(fd2[0], PERF_EVENT_IOC_ENABLE,0); /* start up pid2 */ if ( ptrace( PTRACE_CONT, pid2, NULL, NULL ) == -1 ) { fprintf(stderr,"Couldn't continue %d\n",pid2); return -1; } if ( waitpid( pid2, &status, 0 ) == -1 ) { fprintf(stderr,"Couldn't waitpid() %d\n",pid2 ); return -1; } if ( WIFSTOPPED( status ) == 0 ) { test_fail(test_string); } if ( WSTOPSIG( status ) != SIGSTOP ) { test_fail(test_string); } /* Wait for the SIGSTOP. */ if ( ptrace( PTRACE_CONT, pid, NULL, NULL ) == -1 ) { fprintf(stderr, "sigstop fail\n" ); return -1; } if ( waitpid( pid, &status, 0 ) == -1 ) { fprintf(stderr, "waitpid() pid\n" ); return -1; } if ( WIFSTOPPED( status ) == 0 ) { test_fail(test_string); } if ( WSTOPSIG( status ) != SIGSTOP ) { test_fail(test_string); } /* Wait for the SIGSTOP. */ if ( ptrace( PTRACE_CONT, pid2, NULL, NULL ) == -1 ) { fprintf(stderr, "sigstop fail\n" ); return -1; } if ( waitpid( pid2, &status, 0 ) == -1 ) { fprintf(stderr, "waitpid() pid\n" ); return -1; } if ( WIFSTOPPED( status ) == 0 ) { test_fail(test_string); } if ( WSTOPSIG( status ) != SIGSTOP ) { test_fail(test_string); } /* read */ for(i=0;i<count;i++) { values[i] = mmap_read_self(addr[i], &enabled[i], &running[i]); } /* stop */ ret2=ioctl(fd[0], PERF_EVENT_IOC_DISABLE,0); ret2=ioctl(fd2[0], PERF_EVENT_IOC_DISABLE,0); for(i=0;i<count;i++) { values2[i] = mmap_read_self(addr2[i], &enabled2[i], &running2[i]); } stop_after=rdtsc(); if (ret1<0) { fprintf(stderr,"Error starting!\n"); test_fail(test_string); } if (ret2<0) { fprintf(stderr,"Error stopping!\n"); test_fail(test_string); } if (values[0]<0) { if (!quiet) printf("rdpmc support not available.\n"); test_yellow_no(test_string); } for(i=0;i<count;i++) { close(fd[i]); close(fd2[i]); munmap(addr[i],page_size); munmap(addr2[i],page_size); } if (!quiet) { printf("Trying attach: %lld cycles\n", stop_after-start_before); for(i=0;i<count;i++) { if (values[i]==-1) { printf("\t* RDPMC 1 Event %x -- rdpmc not supported\n",i); } else { printf("\t* RDPMC 1 Event %x -- count: %lld enabled %lld running: %lld\n", i,values[i],enabled[i],running[i]); } } for(i=0;i<count;i++) { if (values2[i]==-1) { printf("\t* RDPMC 2 Event %x -- rdpmc not supported\n",i); } else { printf("\t* RDPMC 2 Event %x -- count: %lld enabled %lld running: %lld\n", i,values2[i],enabled2[i],running2[i]); } } } if (!quiet) printf("\n"); if ((values[0]!=-1) || (values2[0]!=-1)) { error=display_error(values[0], values[0], values[0], 1000000ULL,quiet); if ((error>10.0) || ( error<-10.0)) { if (!quiet) printf("Error out of range!\n"); test_fail(test_string); } error=display_error(values2[0], values2[0], values2[0], 2000000ULL,quiet); if ((error>10.0) || ( error<-10.0)) { if (!quiet) printf("Error out of range!\n"); test_fail(test_string); } if (!quiet) { printf("Should not have worked\n"); } test_fail(test_string); } for(i=0;i<count;i++) { close(fd[i]); munmap(addr[i],page_size); } test_pass(test_string); return 0; }