예제 #1
0
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 );
}
예제 #2
0
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;
}