Esempio n. 1
0
void perf_start(const char* kname) {
  if (!enabled) return;

  char* prof_envvar = getenv("MXPA_PROFILE");

  int tids[32];
  int ntid;
  get_tids(tids, &ntid);
  g_nthreads = ntid;

  int n;
  for (n = 0; n < ntid; n++) {
    int ret;
    ret = perf_setup_list_events(prof_envvar, &(g_fds[n]), &num_fds);
    perf_event_desc_t *fds = g_fds[n];
    int cpu = -1;
    int group_fd = -1;
    int pid = tids[n];
    fds[0].fd = -1;
    int i;
    for(i=0; i < num_fds; i++) {
      fds[i].hw.read_format = PERF_FORMAT_SCALE;
      fds[i].hw.disabled = 1; /* do not start now */
      fds[i].hw.inherit = 1;  /* XXX child process will inherit, when forked only? */

      /* each event is in an independent group (multiplexing likely) */
      fds[i].fd = perf_event_open(&fds[i].hw, pid, cpu, group_fd, 0);
      if (fds[i].fd == -1) {
        fprintf(stderr, "cannot open event %d\n", i);
        exit(2);
      }
    }
  }
  prctl(PR_TASK_PERF_EVENTS_ENABLE);
}
Esempio n. 2
0
void perfevent_initialize(char*events) {
  int i, ret;
  perfevent_events = strdup(events);

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

  ret = perf_setup_list_events(events, &perfevent_fds, &perfevent_num_fds);
  if (ret || !perfevent_num_fds)
    errx(1, "cannot setup events");

  perfevent_fds[0].fd = -1;
  for(i=0; i < perfevent_num_fds; i++) {
    /* request timing information necessary for scaling */
    perfevent_fds[i].hw.read_format = PERF_FORMAT_SCALE;

    perfevent_fds[i].hw.disabled = (i == 0); /* do not start now */
    perfevent_fds[i].hw.inherit = 1; /* pass on to child threads */

    /* each event is in an independent group (multiplexing likely) */
    perfevent_fds[i].fd = perf_event_open(&perfevent_fds[i].hw, 0, -1, perfevent_fds[0].fd, 0);
    if (perfevent_fds[i].fd == -1)
      err(1, "cannot open event %d", i);
  }
}
Esempio n. 3
0
int
measure(pid_t pid)
{
	perf_event_desc_t *fds = NULL;
	int i, ret, num_fds = 0;
	char fn[32];

	if (pfm_initialize() != PFM_SUCCESS)
		errx(1, "libpfm initialization failed\n");

	ret = perf_setup_list_events(options.events, &fds, &num_fds);
	if (ret || (num_fds == 0))
		exit(1);

	fds[0].fd = -1;
	for(i=0; i < num_fds; i++) {
		fds[i].hw.disabled = 0; /* start immediately */

		/* request timing information necessary for scaling counts */
		fds[i].hw.read_format = PERF_FORMAT_SCALE;
		fds[i].hw.pinned = !i && options.pinned;
		fds[i].fd = perf_event_open(&fds[i].hw, pid, -1, (options.group? fds[0].fd : -1), 0);
		if (fds[i].fd == -1)
			errx(1, "cannot attach event %s", fds[i].name);
	}
	/*
	 * no notification is generated by perf_counters
	 * when the monitored thread exits. Thus we need
	 * to poll /proc/ to detect it has disappeared,
	 * otherwise we have to wait until the end of the
	 * timeout
	 */
	sprintf(fn, "/proc/%d/status", pid);

	while(access(fn, F_OK) == 0 && options.delay) {
		sleep(1);
		options.delay--;
		if (options.print)
			print_counts(fds, num_fds, 1);
	}
	if (options.delay)
		warn("thread %d terminated before timeout", pid);

	if (!options.print)
		print_counts(fds, num_fds, 0);

	for(i=0; i < num_fds; i++)
		close(fds[i].fd);

	free(fds);

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

	return 0;
}
Esempio n. 4
0
int
mainloop(char **arg)
{
	static uint64_t ovfl_count; /* static to avoid setjmp issue */
	struct pollfd pollfds[1];
	sigset_t bmask;
	int go[2], ready[2];
	size_t pgsz;
	size_t map_size = 0;
	pid_t pid;
	int status, ret;
	int i;
	char buf;

	if (pfm_initialize() != PFM_SUCCESS)
		errx(1, "libpfm initialization failed\n");

	pgsz = sysconf(_SC_PAGESIZE);
	map_size = (options.mmap_pages+1)*pgsz;

	/*
	 * does allocate fds
	 */
	ret  = perf_setup_list_events(options.events, &fds, &num_fds);
	if (ret || !num_fds)
		errx(1, "cannot setup event list");

	memset(pollfds, 0, sizeof(pollfds));

	ret = pipe(ready);
	if (ret)
		err(1, "cannot create pipe ready");

	ret = pipe(go);
	if (ret)
		err(1, "cannot create pipe go");

	/*
	 * Create the child task
	 */
//	if ((pid=fork()) == -1)
//		err(1, "cannot fork process\n");

/*	if (pid == 0) {
		close(ready[0]);
		close(go[1]);
*/
		/*
		 * let the parent know we exist
		 */
/*		close(ready[1]);
		if (read(go[0], &buf, 1) == -1)
			err(1, "unable to read go_pipe");

		exit(child(arg));
	}
*/
	int tid;
	pid = getpid();
	tid = gettid();
	printf("From C - pid : %d, tid : %d\n",pid, tid);	
	
	close(ready[1]);
	close(go[0]);

	if (read(ready[0], &buf, 1) == -1)
		err(1, "unable to read child_ready_pipe");

	close(ready[0]);

	fds[0].fd = -1;

	fds[0].hw.sample_period=10000;
	if (!fds[0].hw.sample_period)
		errx(1, "need to set sampling period or freq on first event, use :period= or :freq=");

	for(i=0; i < num_fds; i++) {

		if (i == 0) {
			fds[i].hw.disabled = 1;
			fds[i].hw.enable_on_exec = 1; /* start immediately */
		} else
			fds[i].hw.disabled = 0;


		if (options.opt_inherit)
			fds[i].hw.inherit = 1;

		if (fds[i].hw.sample_period) {
			/*
			 * set notification threshold to be halfway through the buffer
			 */
			fds[i].hw.wakeup_watermark = (options.mmap_pages*pgsz) / 2;
			fds[i].hw.watermark = 1;

			fds[i].hw.sample_type = PERF_SAMPLE_IP|PERF_SAMPLE_TID|PERF_SAMPLE_READ|PERF_SAMPLE_TIME|PERF_SAMPLE_PERIOD;
			/*
			 * if we have more than one event, then record event identifier to help with parsing
			 */
			if (num_fds > 1)
				fds[i].hw.sample_type |= PERF_SAMPLE_IDENTIFIER;

			fprintf(options.output_file,"%s period=%"PRIu64" freq=%d\n", fds[i].name, fds[i].hw.sample_period, fds[i].hw.freq);

			fds[i].hw.read_format = PERF_FORMAT_SCALE;

			if (fds[i].hw.freq)
				fds[i].hw.sample_type |= PERF_SAMPLE_PERIOD;
			
			fds[i].hw.sample_period=10000;
			if (options.mem_mode)
				fds[i].hw.sample_type |= PERF_SAMPLE_WEIGHT | PERF_SAMPLE_DATA_SRC | PERF_SAMPLE_ADDR;
			if (options.branch_mode) {
				fds[i].hw.sample_type |= PERF_SAMPLE_BRANCH_STACK;
				fds[i].hw.branch_sample_type = PERF_SAMPLE_BRANCH_ANY;
			}
		}
		/*
		 * we are grouping the events, so there may be a limit
		 */
		fds[i].fd = perf_event_open(&fds[i].hw, tid+1, options.cpu, fds[0].fd, 0);
		if (fds[i].fd == -1) {
			if (fds[i].hw.precise_ip)
				err(1, "cannot attach event %s: precise mode may not be supported", fds[i].name);
			err(1, "cannot attach event %s", fds[i].name);
		}
	}

	/*
	 * kernel adds the header page to the size of the mmapped region
	 */
	fds[0].buf = mmap(NULL, map_size, PROT_READ|PROT_WRITE, MAP_SHARED, fds[0].fd, 0);
	if (fds[0].buf == MAP_FAILED)
		err(1, "cannot mmap buffer");

	/* does not include header page */
	fds[0].pgmsk = (options.mmap_pages*pgsz)-1;

	/*
	 * send samples for all events to first event's buffer
	 */
	for (i = 1; i < num_fds; i++) {
		if (!fds[i].hw.sample_period)
			continue;
		ret = ioctl(fds[i].fd, PERF_EVENT_IOC_SET_OUTPUT, fds[0].fd);
		if (ret)
			err(1, "cannot redirect sampling output");
	}

	if (num_fds > 1 && fds[0].fd > -1) {
		for(i = 0; i < num_fds; i++) {
			/*
			 * read the event identifier using ioctl
			 * new method replaced the trick with PERF_FORMAT_GROUP + PERF_FORMAT_ID + read()
			 */
			ret = ioctl(fds[i].fd, PERF_EVENT_IOC_ID, &fds[i].id);
			if (ret == -1)
				err(1, "cannot read ID");
			fprintf(options.output_file,"ID %"PRIu64"  %s\n", fds[i].id, fds[i].name);
		}
	}

	pollfds[0].fd = fds[0].fd;
	pollfds[0].events = POLLIN;
	
	for(i=0; i < num_fds; i++) {
		ret = ioctl(fds[i].fd, PERF_EVENT_IOC_ENABLE, 0);
		if (ret)
			err(1, "cannot enable event %s\n", fds[i].name);
	}
	signal(SIGCHLD, cld_handler);

	close(go[1]);

	if (setjmp(jbuf) == 1)
		goto terminate_session;

	sigemptyset(&bmask);
	sigaddset(&bmask, SIGCHLD);

	/*
	 * core loop
	 */
	for(;;) {
		ret = poll(pollfds, 1, -1);
		if (ret < 0 && errno == EINTR)
			break;
		ovfl_count++;
		ret = sigprocmask(SIG_SETMASK, &bmask, NULL);
		if (ret)
			err(1, "setmask");
		process_smpl_buf(&fds[0]);
		ret = sigprocmask(SIG_UNBLOCK, &bmask, NULL);
		if (ret)
			err(1, "unblock");
	}
	printf("How was you day??\n");
terminate_session:
	/*
	 * cleanup child
	 */
	wait4(pid, &status, 0, NULL);

	for(i=0; i < num_fds; i++)
		close(fds[i].fd);

	/* check for partial event buffer */
	process_smpl_buf(&fds[0]);
	munmap(fds[0].buf, map_size);

	perf_free_fds(fds, num_fds);

	fprintf(options.output_file,
		"%"PRIu64" samples collected in %"PRIu64" poll events, %"PRIu64" lost samples\n",
		collected_samples,
		ovfl_count, lost_samples);

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

	fclose(options.output_file);

	return 0;
}
Esempio n. 5
0
int
setup_cpu(int cpu, int fd)
{
	uint64_t *val;
	int ret, flags;
	int i;

	/*
	 * does allocate fds
	 */
	ret = perf_setup_list_events(options.events, &fds, &num_fds);
	if (ret || !num_fds)
		errx(1, "cannot setup event list");

	if (!fds[0].hw.sample_period)
		errx(1, "need to set sampling period or freq on first event, use :period= or :freq=");

	fds[0].fd = -1;
	for(i=0; i < num_fds; i++) {

		fds[i].hw.disabled = !i; /* start immediately */

		if (options.cgroup) {
			flags = PERF_FLAG_PID_CGROUP;
		} else {
			flags = 0;
		}

		if (options.pin)
			fds[i].hw.pinned = 1;

		if (fds[i].hw.sample_period) {
			/*
			 * set notification threshold to be halfway through the buffer
			 */
			if (fds[i].hw.sample_period) {
				fds[i].hw.wakeup_watermark = (options.mmap_pages*pgsz) / 2;
				fds[i].hw.watermark = 1;
			}

			fds[i].hw.sample_type = PERF_SAMPLE_IP|PERF_SAMPLE_TID|PERF_SAMPLE_READ|PERF_SAMPLE_TIME|PERF_SAMPLE_PERIOD|PERF_SAMPLE_STREAM_ID|PERF_SAMPLE_CPU;
			printf("%s period=%"PRIu64" freq=%d\n", fds[i].name, fds[i].hw.sample_period, fds[i].hw.freq);

			fds[i].hw.read_format = PERF_FORMAT_SCALE;
			if (num_fds > 1)
				fds[i].hw.read_format |= PERF_FORMAT_GROUP|PERF_FORMAT_ID;

			if (fds[i].hw.freq)
				fds[i].hw.sample_type |= PERF_SAMPLE_PERIOD;
		}

		fds[i].fd = perf_event_open(&fds[i].hw, -1, cpu, fds[0].fd, flags);
		if (fds[i].fd == -1) {
			if (fds[i].hw.precise_ip)
				err(1, "cannot attach event %s: precise mode may not be supported", fds[i].name);
			err(1, "cannot attach event %s", fds[i].name);
		}
	}

	/*
	 * kernel adds the header page to the size of the mmapped region
	 */
	fds[0].buf = mmap(NULL, map_size, PROT_READ|PROT_WRITE, MAP_SHARED, fds[0].fd, 0);
	if (fds[0].buf == MAP_FAILED)
		err(1, "cannot mmap buffer");

	/* does not include header page */
	fds[0].pgmsk = (options.mmap_pages*pgsz)-1;

	/*
	 * send samples for all events to first event's buffer
	 */
	for (i = 1; i < num_fds; i++) {
		if (!fds[i].hw.sample_period)
			continue;
		ret = ioctl(fds[i].fd, PERF_EVENT_IOC_SET_OUTPUT, fds[0].fd);
		if (ret)
			err(1, "cannot redirect sampling output");
	}

	/*
	 * we are using PERF_FORMAT_GROUP, therefore the structure
	 * of val is as follows:
	 *
	 *      { u64           nr;
	 *        { u64         time_enabled; } && PERF_FORMAT_ENABLED
	 *        { u64         time_running; } && PERF_FORMAT_RUNNING
	 *        { u64         value;
	 *          { u64       id;           } && PERF_FORMAT_ID
	 *        }             cntr[nr];
	 *      }
	 * We are skipping the first 3 values (nr, time_enabled, time_running)
	 * and then for each event we get a pair of values.
	 */
	if (num_fds > 1) {
		sz = (3+2*num_fds)*sizeof(uint64_t);
		val = malloc(sz);
		if (!val)
			err(1, "cannot allocated memory");

		ret = read(fds[0].fd, val, sz);
		if (ret == -1)
			err(1, "cannot read id %zu", sizeof(val));

		for(i=0; i < num_fds; i++) {
			fds[i].id = val[2*i+1+3];
			printf("%"PRIu64"  %s\n", fds[i].id, fds[i].name);
		}
		free(val);
	}
	return 0;
}
Esempio n. 6
0
static void
measure(void)
{
	perf_event_desc_t *fds = NULL;
	int num_fds = 0;
	uint64_t values[3];
	ssize_t n;
	int i, ret;
	int pr[2], pw[2];
	pid_t pid;
	char cc = '0';

	ret = pfm_initialize();
	if (ret != PFM_SUCCESS)
		err(1, "cannot initialize libpfm");

	if (options.cpu == -1) {
		srandom(getpid());
		options.cpu = random() % sysconf(_SC_NPROCESSORS_ONLN);
	}

	ret = pipe(pr);
	if (ret)
		err(1, "cannot create read pipe");

	ret = pipe(pw);
	if (ret)
		err(1, "cannot create write pipe");

	ret = perf_setup_list_events(options.events, &fds, &num_fds);
	if (ret || !num_fds)
		exit(1);

	for(i=0; i < num_fds; i++) {
		fds[i].hw.disabled = 1;
		fds[i].hw.read_format = PERF_FORMAT_SCALE;

		fds[i].fd = perf_event_open(&fds[i].hw, 0, -1, -1, 0);
		if (fds[i].fd == -1)
			err(1, "cannot open event %d", i);
	}

	/*
 	 * Pin to CPU0, inherited by child process. That will enforce
 	 * the ping-pionging and thus stress the PMU context switch 
 	 * which is what we want
 	 */
	ret = pin_cpu(getpid(), options.cpu);
	if (ret)
		err(1, "cannot pin to CPU%d", options.cpu);

	printf("Both processes pinned to CPU%d, running for %d seconds\n", options.cpu, options.delay);

	/*
 	 * create second process which is not monitoring at the moment
 	 */
	switch(pid=fork()) {
		case -1:
			err(1, "cannot create child\n");
		case 0:
			/* do not inherit session fd */
			for(i=0; i < num_fds; i++)
				close(fds[i].fd);
			/* pr[]: write master, read child */
			/* pw[]: read master, write child */
			close(pr[1]); close(pw[0]);
			do_child(pr[0], pw[1]);
			exit(1);
	}

	close(pr[0]);
	close(pw[1]);

	/*
	 * Let's roll now
	 */
	prctl(PR_TASK_PERF_EVENTS_ENABLE);
	signal(SIGALRM, sig_handler);
	alarm(options.delay);

	/*
	 * ping pong loop
	 */
	while(!quit) {
		n = write(pr[1], "c", 1);
		if (n < 1)
			err(1, "write failed");
		n = read(pw[0], &cc, 1);
		if (n < 1)
			err(1, "read failed");
	}

	prctl(PR_TASK_PERF_EVENTS_DISABLE);

	for(i=0; i < num_fds; i++) {
		uint64_t val;
		double ratio;

		ret = read(fds[i].fd, values, sizeof(values));
		if (ret == -1)
			err(1,"pfm_read error");
		if (ret != sizeof(values))
			errx(1, "did not read correct amount %d", ret);

		val = perf_scale(values);
		ratio = perf_scale_ratio(values);

		if (ratio == 1.0)
			printf("%20"PRIu64" %s\n", val, fds[i].name);
		else
			if (ratio == 0.0)
				printf("%20"PRIu64" %s (did not run: competing session)\n", val, fds[i].name);
			else
				printf("%20"PRIu64" %s (scaled from %.2f%% of time)\n", val, fds[i].name, ratio*100.0);
	}
	/*
	 * kill child process
	 */
	kill(SIGKILL, pid);

	/*
 	 * close pipes
 	 */
	close(pr[1]);
	close(pw[0]);
	/*
	 * and destroy our session
	 */
	for(i=0; i < num_fds; i++)
		close(fds[i].fd);

	perf_free_fds(fds, num_fds);

	/* free libpfm resources cleanly */
	pfm_terminate();
}
Esempio n. 7
0
int
mainloop(char **arg)
{
	static uint64_t ovfl_count; /* static to avoid setjmp issue */
	struct pollfd pollfds[1];
	sigset_t bmask;
	int go[2], ready[2];
	uint64_t *val;
	size_t sz, pgsz;
	size_t map_size = 0;
	pid_t pid;
	int status, ret;
	int i;
	char buf;

	if (pfm_initialize() != PFM_SUCCESS)
		errx(1, "libpfm initialization failed\n");

	pgsz = sysconf(_SC_PAGESIZE);
	map_size = (options.mmap_pages+1)*pgsz;

	/*
	 * does allocate fds
	 */
	ret  = perf_setup_list_events(options.events, &fds, &num_fds);
	if (ret || !num_fds)
		errx(1, "cannot setup event list");

	memset(pollfds, 0, sizeof(pollfds));

	ret = pipe(ready);
	if (ret)
		err(1, "cannot create pipe ready");

	ret = pipe(go);
	if (ret)
		err(1, "cannot create pipe go");

	/*
	 * Create the child task
	 */
	if ((pid=fork()) == -1)
		err(1, "cannot fork process\n");

	if (pid == 0) {
		close(ready[0]);
		close(go[1]);

		/*
		 * let the parent know we exist
		 */
		close(ready[1]);
		if (read(go[0], &buf, 1) == -1)
			err(1, "unable to read go_pipe");

		exit(child(arg));
	}
	close(ready[1]);
	close(go[0]);

	if (read(ready[0], &buf, 1) == -1)
		err(1, "unable to read child_ready_pipe");

	close(ready[0]);

	fds[0].fd = -1;

	if (!fds[0].hw.sample_period)
		errx(1, "need to set sampling period or freq on first event, use :period= or :freq=");

	for(i=0; i < num_fds; i++) {

		if (i == 0) {
			fds[i].hw.disabled = 1;
			fds[i].hw.enable_on_exec = 1; /* start immediately */
		} else
			fds[i].hw.disabled = 0;


		if (options.opt_inherit)
			fds[i].hw.inherit = 1;

		if (fds[i].hw.sample_period) {
			/*
			 * set notification threshold to be halfway through the buffer
			 */
			fds[i].hw.wakeup_watermark = (options.mmap_pages*pgsz) / 2;
			fds[i].hw.watermark = 1;

			fds[i].hw.sample_type = PERF_SAMPLE_IP|PERF_SAMPLE_TID|PERF_SAMPLE_READ|PERF_SAMPLE_TIME|PERF_SAMPLE_PERIOD|PERF_SAMPLE_STREAM_ID;
			fprintf(options.output_file,"%s period=%"PRIu64" freq=%d\n", fds[i].name, fds[i].hw.sample_period, fds[i].hw.freq);

			fds[i].hw.read_format = PERF_FORMAT_SCALE;
			if (num_fds > 1)
				fds[i].hw.read_format |= PERF_FORMAT_GROUP|PERF_FORMAT_ID;

			if (fds[i].hw.freq)
				fds[i].hw.sample_type |= PERF_SAMPLE_PERIOD;
		}

		fds[i].fd = perf_event_open(&fds[i].hw, pid, options.cpu, fds[0].fd, 0);
		if (fds[i].fd == -1) {
			if (fds[i].hw.precise_ip)
				err(1, "cannot attach event %s: precise mode may not be supported", fds[i].name);
			err(1, "cannot attach event %s", fds[i].name);
		}
	}

	/*
	 * kernel adds the header page to the size of the mmapped region
	 */
	fds[0].buf = mmap(NULL, map_size, PROT_READ|PROT_WRITE, MAP_SHARED, fds[0].fd, 0);
	if (fds[0].buf == MAP_FAILED)
		err(1, "cannot mmap buffer");

	/* does not include header page */
	fds[0].pgmsk = (options.mmap_pages*pgsz)-1;

	/*
	 * send samples for all events to first event's buffer
	 */
	for (i = 1; i < num_fds; i++) {
		if (!fds[i].hw.sample_period)
			continue;
		ret = ioctl(fds[i].fd, PERF_EVENT_IOC_SET_OUTPUT, fds[0].fd);
		if (ret)
			err(1, "cannot redirect sampling output");
	}

	/*
	 * we are using PERF_FORMAT_GROUP, therefore the structure
	 * of val is as follows:
	 *
	 *      { u64           nr;
	 *        { u64         time_enabled; } && PERF_FORMAT_ENABLED
	 *        { u64         time_running; } && PERF_FORMAT_RUNNING
	 *        { u64         value;
	 *          { u64       id;           } && PERF_FORMAT_ID
	 *        }             cntr[nr];
	 * We are skipping the first 3 values (nr, time_enabled, time_running)
	 * and then for each event we get a pair of values.
	 */
	if (num_fds > 1) {
		sz = (3+2*num_fds)*sizeof(uint64_t);
		val = malloc(sz);
		if (!val)
			err(1, "cannot allocate memory");

		ret = read(fds[0].fd, val, sz);
		if (ret == -1)
			err(1, "cannot read id %zu", sizeof(val));


		for(i=0; i < num_fds; i++) {
			fds[i].id = val[2*i+1+3];
			fprintf(options.output_file,"%"PRIu64"  %s\n", fds[i].id, fds[i].name);
		}
		free(val);
	}

	pollfds[0].fd = fds[0].fd;
	pollfds[0].events = POLLIN;
	
	for(i=0; i < num_fds; i++) {
		ret = ioctl(fds[i].fd, PERF_EVENT_IOC_ENABLE, 0);
		if (ret)
			err(1, "cannot enable event %s\n", fds[i].name);
	}
	signal(SIGCHLD, cld_handler);

	close(go[1]);

	if (setjmp(jbuf) == 1)
		goto terminate_session;

	sigemptyset(&bmask);
	sigaddset(&bmask, SIGCHLD);

	/*
	 * core loop
	 */
	for(;;) {
		ret = poll(pollfds, 1, -1);
		if (ret < 0 && errno == EINTR)
			break;
		ovfl_count++;
		ret = sigprocmask(SIG_SETMASK, &bmask, NULL);
		if (ret)
			err(1, "setmask");
		process_smpl_buf(&fds[0]);
		ret = sigprocmask(SIG_UNBLOCK, &bmask, NULL);
		if (ret)
			err(1, "unblock");
	}
terminate_session:
	/*
	 * cleanup child
	 */
	wait4(pid, &status, 0, NULL);

	for(i=0; i < num_fds; i++)
		close(fds[i].fd);

	/* check for partial event buffer */
	process_smpl_buf(&fds[0]);
	munmap(fds[0].buf, map_size);

	perf_free_fds(fds, num_fds);

	fprintf(options.output_file,
		"%"PRIu64" samples collected in %"PRIu64" poll events, %"PRIu64" lost samples\n",
		collected_samples,
		ovfl_count, lost_samples);

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

	fclose(options.output_file);

	return 0;
}
Esempio n. 8
0
int
parent(char **arg)
{
	perf_event_desc_t *fds = NULL;
	int status, ret, i, num_fds = 0, grp, group_fd;
	int ready[2], go[2];
	char buf;
	pid_t pid;

//        output_file = fopen(file_name, "w");

        //if (chroot("/home/pittdvs/cpu2006/benchspec/CPU2006/464.h264ref/run/run_base_ref_amd64-m64-gcc42-nn.0000"))
         //   err(1, "err on chroot()");

	if (pfm_initialize() != PFM_SUCCESS)
		errx(1, "libpfm initialization failed");

	for (grp = 0; grp < options.num_groups; grp++) {
		int ret;
		ret = perf_setup_list_events(options.events[grp], &fds, &num_fds);
		if (ret || !num_fds)
			exit(1);
	}

	pid = options.pid;
	if (!pid) {
		ret = pipe(ready);
		if (ret)
			err(1, "cannot create pipe ready");

		ret = pipe(go);
		if (ret)
			err(1, "cannot create pipe go");


		/*
		 * Create the child task
		 */
		if ((pid=fork()) == -1)
			err(1, "Cannot fork process");

		/*
		 * and launch the child code
		 *
		 * The pipe is used to avoid a race condition
		 * between for() and exec(). We need the pid
		 * of the new tak but we want to start measuring
		 * at the first user level instruction. Thus we
		 * need to prevent exec until we have attached
		 * the events.
		 */
		if (pid == 0) {
			close(ready[0]);
			close(go[1]);

			/*
			 * let the parent know we exist
			 */
			close(ready[1]);
			if (read(go[0], &buf, 1) == -1)
				err(1, "unable to read go_pipe");


			exit(child(arg));
		}

		close(ready[1]);
		close(go[0]);

		if (read(ready[0], &buf, 1) == -1)
			err(1, "unable to read child_ready_pipe");

		close(ready[0]);
	}

	for(i=0; i < num_fds; i++) {
		int is_group_leader; /* boolean */

		is_group_leader = perf_is_group_leader(fds, i);
		if (is_group_leader) {
			/* this is the group leader */
			group_fd = -1;
		} else {
			group_fd = fds[fds[i].group_leader].fd;
		}

		/*
		 * create leader disabled with enable_on-exec
		 */
		if (!options.pid) {
			fds[i].hw.disabled = is_group_leader;
			fds[i].hw.enable_on_exec = is_group_leader;
		}

		fds[i].hw.read_format = PERF_FORMAT_SCALE;
		/* request timing information necessary for scaling counts */
		if (is_group_leader && options.format_group)
			fds[i].hw.read_format |= PERF_FORMAT_GROUP;

		if (options.inherit)
			fds[i].hw.inherit = 1;

		if (options.pin && is_group_leader)
			fds[i].hw.pinned = 1;
		fds[i].fd = perf_event_open(&fds[i].hw, pid, -1, group_fd, 0);
		if (fds[i].fd == -1) {
			warn("cannot attach event%d %s", i, fds[i].name);
			goto error;
		}
	}

	if (!options.pid)
		close(go[1]);

	if (options.print) {
		if (!options.pid) {
			while(waitpid(pid, &status, WNOHANG) == 0 && quit == 0) {
				//sleep(1);
                                //usleep(10000);
                                msleep(100);
                                //better_sleep(0.05); // 50ms
				print_counts(fds, num_fds);
			}
		} else {
			while(quit == 0) {
				sleep(1);                                
				print_counts(fds, num_fds);
			}
		}
	} else {
		if (!options.pid)
			waitpid(pid, &status, 0);
		else
			pause();
		print_counts(fds, num_fds);
	}

	for(i=0; i < num_fds; i++)
		close(fds[i].fd);

	free(fds);

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

  //      fclose(output_file);

	return 0;
error:
	free(fds);
	if (!options.pid)
		kill(SIGKILL, pid);

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

//        fclose(output_file);

	return -1;
}
Esempio n. 9
0
void
setup_cpu(int cpu, int cfd)
{
	perf_event_desc_t *fds = NULL;
	int old_total, total = 0, num;
	int i, j, n, ret, is_lead, group_fd;
	unsigned long flags;
	pid_t pid;

	for(i=0, j=0; i < options.num_groups; i++) {
		old_total = total;
		ret = perf_setup_list_events(options.events[i], &fds, &total);
		if (ret)
			errx(1, "cannot setup events\n");

		all_fds[cpu] = fds;

		num = total - old_total;

		options.nevents[i] = num;

		for(n=0; n < num; n++, j++) {

			is_lead = perf_is_group_leader(fds, j);
			if (is_lead) {
				fds[j].hw.disabled = 1;
				group_fd = -1;
			} else {
				fds[j].hw.disabled = 0;
				group_fd = fds[fds[j].group_leader].fd;
			}
			fds[j].hw.size = sizeof(struct perf_event_attr);

			if (options.cgroup_name) {
				flags = PERF_FLAG_PID_CGROUP;
				pid = cfd;
				//fds[j].hw.cgroup = 1;
				//fds[j].hw.cgroup_fd = cfd;
			} else {
				flags = 0;
				pid = -1;
			}

			if (options.pin && is_lead)
				fds[j].hw.pinned = 1;

			if (options.excl && is_lead)
				fds[j].hw.exclusive = 1;

			/* request timing information necessary for scaling counts */
			fds[j].hw.read_format = PERF_FORMAT_SCALE;
			fds[j].fd = perf_event_open(&fds[j].hw, pid, cpu, group_fd, flags);
			if (fds[j].fd == -1) {
				if (errno == EACCES)
					err(1, "you need to be root to run system-wide on this machine");

				warn("cannot attach event %s to CPU%ds, skipping it", fds[j].name, cpu);
				goto error;
			}
		}
	}
	return;
error:
	for (i=0; i < j; i++) {
		close(fds[i].fd);
		fds[i].fd = -1;
	}
}
Esempio n. 10
0
int
main(int argc, char **argv)
{
	struct sigaction act;
	uint64_t *val;
	size_t sz, pgsz;
	int ret, i;

	setlocale(LC_ALL, "");

	ret = pfm_initialize();
	if (ret != PFM_SUCCESS)
		errx(1, "Cannot initialize library: %s", pfm_strerror(ret));

	pgsz = sysconf(_SC_PAGESIZE);

	/*
	 * Install the signal handler (SIGIO)
	 * need SA_SIGINFO because we need the fd
	 * in the signal handler
	 */
	memset(&act, 0, sizeof(act));
	act.sa_sigaction = sigio_handler;
	act.sa_flags = SA_SIGINFO;
	sigaction (SIGIO, &act, 0);

	/*
 	 * allocates fd for us
 	 */
	ret = perf_setup_list_events("cycles,"
				       "instructions",
					&fds, &num_fds);
	if (ret || (num_fds == 0))
		exit(1);

	fds[0].fd = -1;
	for(i=0; i < num_fds; i++) {

		/* want a notification for every each added to the buffer */
		fds[i].hw.disabled = !i;
		if (!i) {
			fds[i].hw.wakeup_events = 1;
			fds[i].hw.sample_type = PERF_SAMPLE_IP|PERF_SAMPLE_READ|PERF_SAMPLE_PERIOD;
			fds[i].hw.sample_period = SMPL_PERIOD;

			/* read() returns event identification for signal handler */
			fds[i].hw.read_format = PERF_FORMAT_GROUP|PERF_FORMAT_ID|PERF_FORMAT_SCALE;
		}

		fds[i].fd = perf_event_open(&fds[i].hw, 0, -1, fds[0].fd, 0);
		if (fds[i].fd == -1)
			err(1, "cannot attach event %s", fds[i].name);
	}
	
	sz = (3+2*num_fds)*sizeof(uint64_t);
	val = malloc(sz);
	if (!val)
		err(1, "cannot allocated memory");
	/*
	 * On overflow, the non lead events are stored in the sample.
	 * However we need some key to figure the order in which they
	 * were laid out in the buffer. The file descriptor does not
	 * work for this. Instead, we extract a unique ID for each event.
	 * That id will be part of the sample for each event value.
	 * Therefore we will be able to match value to events
	 *
	 * PERF_FORMAT_ID: returns unique 64-bit identifier in addition
	 * to event value.
	 */
	ret = read(fds[0].fd, val, sz);
	if (ret == -1)
		err(1, "cannot read id %zu", sizeof(val));

	/*
	 * we are using PERF_FORMAT_GROUP, therefore the structure
	 * of val is as follows:
	 *
	 *      { u64           nr;
	 *        { u64         time_enabled; } && PERF_FORMAT_ENABLED
	 *        { u64         time_running; } && PERF_FORMAT_RUNNING
	 *        { u64         value;                  
	 *          { u64       id;           } && PERF_FORMAT_ID
	 *        }             cntr[nr];               
	 * We are skipping the first 3 values (nr, time_enabled, time_running)
	 * and then for each event we get a pair of values.
	 */ 
	for(i=0; i < num_fds; i++) {
		fds[i].id = val[2*i+1+3];
		printf("%"PRIu64"  %s\n", fds[i].id, fds[i].name);
	}
	 
	fds[0].buf = mmap(NULL, (buffer_pages+1)*pgsz, PROT_READ|PROT_WRITE, MAP_SHARED, fds[0].fd, 0);
	if (fds[0].buf == MAP_FAILED)
		err(1, "cannot mmap buffer");
	
	fds[0].pgmsk = (buffer_pages * pgsz) - 1;

	/*
	 * setup asynchronous notification on the file descriptor
	 */
	ret = fcntl(fds[0].fd, F_SETFL, fcntl(fds[0].fd, F_GETFL, 0) | O_ASYNC);
	if (ret == -1)
		err(1, "cannot set ASYNC");

	/*
 	 * necessary if we want to get the file descriptor for
 	 * which the SIGIO is sent in siginfo->si_fd.
 	 * SA_SIGINFO in itself is not enough
 	 */
	ret = fcntl(fds[0].fd, F_SETSIG, SIGIO);
	if (ret == -1)
		err(1, "cannot setsig");

	/*
	 * get ownership of the descriptor
	 */
	ret = fcntl(fds[0].fd, F_SETOWN, getpid());
	if (ret == -1)
		err(1, "cannot setown");

	/*
	 * enable the group for one period
	 */
	ret = ioctl(fds[0].fd, PERF_EVENT_IOC_REFRESH , 1);
	if (ret == -1)
		err(1, "cannot refresh");

	busyloop();

	ret = ioctl(fds[0].fd, PERF_EVENT_IOC_DISABLE, 1);
	if (ret == -1)
		err(1, "cannot disable");

	/*
	 * destroy our session
	 */
	for(i=0; i < num_fds; i++)
		close(fds[i].fd);

	perf_free_fds(fds, num_fds);
	free(val);

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

	return 0;
}