[ create a new paste ] login | about

Link: http://codepad.org/T5y4z0gV    [ raw code | fork ]

C, pasted on Aug 23:
/* changed perf_examples/self_basic.c from perfmon2 library.
the purpose is to demonstrate how one can count events for 
a binary within a c program. */


#include <sys/types.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <locale.h>
#include <sys/ioctl.h>
#include <err.h>
#include <sys/wait.h>

#include <perfmon/pfmlib_perf_event.h>

#define N 30

int
main(int argc, char **argv)
{
	struct perf_event_attr attr;
	int fd, ret;
	uint64_t count = 0, values[3];
	pid_t child_pid; 
	int status;

	setlocale(LC_ALL, "");

	/*
	 * Initialize libpfm library (required before we can use it)
	 */
	ret = pfm_initialize();
	if (ret != PFM_SUCCESS)
		errx(1, "cannot initialize library: %s", pfm_strerror(ret));

	memset(&attr, 0, sizeof(attr));

	/*
 	 * 1st argument: event string
 	 * 2nd argument: default privilege level (used if not specified in the event string)
 	 * 3rd argument: the perf_event_attr to initialize
 	 */
	ret = pfm_get_perf_event_encoding("cycles,PM_RUN_CYC", PFM_PLM0|PFM_PLM3, &attr, NULL, NULL);
	if (ret != PFM_SUCCESS)
		errx(1, "cannot find encoding: %s", pfm_strerror(ret));

	/*
	 * request timing information because event may be multiplexed
	 * and thus it may not count all the time. The scaling information
	 * will be used to scale the raw count as if the event had run all
	 * along
	 */
	attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING;

	/* do not start immediately after perf_event_open() */
	attr.disabled = 1;

		
	if( (child_pid = fork()) == 0) //child
	{
		

		printf("child is running, pid is %d\n", getpid());	
		char *cmd[] = {"ls", "/", "-l", (char *)0};
		execv("/bin/ls", cmd);
		exit(0);
			
	}else if(child_pid < 0){ //failed
		err(1, "Failed to fork");
		exit(0);
	}else { //parent
		

		printf("Back to parent, child pid is: %d\n", child_pid);	
		/*
		 * create the event and attach to self
		 * Note that it attaches only to the main thread, there is no inheritance
		 * to threads that may be created subsequently.
		 *
		 * if mulithreaded, then getpid() must be replaced by gettid()
		 */
		fd = perf_event_open(&attr, child_pid, -1, -1, 0);
		if (fd < 0) 
			err(1, "cannot create event");
		/*
		 * start counting now
		 */
		ret = ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
		if (ret)
			err(1, "ioctl(enable) failed");
		wait(&status); //wait for the child to exit
		/*
		 * stop counting
		 */
		ret = ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
		if (ret)
			err(1, "ioctl(disable) failed");
		/*
		 * read the count + scaling values
		 *
		 * It is not necessary to stop an event to read its value
		 */
		ret = read(fd, values, sizeof(values));
		if (ret != sizeof(values))
			err(1, "cannot read results: %s", strerror(errno));

		/*
		 * scale count
		 *
		 * values[0] = raw count
		 * values[1] = TIME_ENABLED
		 * values[2] = TIME_RUNNING
		 */
		if (values[2])
			count = (uint64_t)((double)values[0] * values[1]/values[2]);

		printf("this is a test");
		printf("count=%'"PRIu64"\n", count);
		printf("count=%'"PRIu64"\n", values[0]);
		printf("count=%'"PRIu64"\n", values[1]);
		printf("count=%'"PRIu64"\n", values[2]);
		printf("count=%'"PRIu64"\n", values[3]);

		close(fd);


	}	

	/* free libpfm resources cleanly */
	pfm_terminate();

	return 0;
}


Create a new paste based on this one


Comments: