Blame src/libpfm4/perf_examples/self_smpl_multi.c

Packit Service a1973e
/*
Packit Service a1973e
 *
Packit Service a1973e
 * self_smpl_multi.c - multi-thread self-sampling program
Packit Service a1973e
 *
Packit Service a1973e
 * Copyright (c) 2009  Google, Inc
Packit Service a1973e
 * Modified by Stephane Eranian <eranian@gmail.com>
Packit Service a1973e
 *
Packit Service a1973e
 * Based on:
Packit Service a1973e
 * Copyright (c) 2008 Mark W. Krentel
Packit Service a1973e
 * Contributed by Mark W. Krentel <krentel@cs.rice.edu>
Packit Service a1973e
 * Modified by Stephane Eranian <eranian@gmail.com>
Packit Service a1973e
 *
Packit Service a1973e
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit Service a1973e
 * of this software and associated documentation files (the "Software"), to deal
Packit Service a1973e
 * in the Software without restriction, including without limitation the rights
Packit Service a1973e
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
Packit Service a1973e
 * of the Software, and to permit persons to whom the Software is furnished to do so,
Packit Service a1973e
 * subject to the following conditions:
Packit Service a1973e
 *
Packit Service a1973e
 * The above copyright notice and this permission notice shall be included in all
Packit Service a1973e
 * copies or substantial portions of the Software.
Packit Service a1973e
 *
Packit Service a1973e
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
Packit Service a1973e
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
Packit Service a1973e
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
Packit Service a1973e
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
Packit Service a1973e
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
Packit Service a1973e
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit Service a1973e
 *
Packit Service a1973e
 * This file is part of libpfm, a performance monitoring support library for
Packit Service a1973e
 * applications on Linux.
Packit Service a1973e
 *
Packit Service a1973e
 *  Test perfmon overflow without PAPI.
Packit Service a1973e
 *
Packit Service a1973e
 *  Create a new thread, launch perfmon overflow counters in both
Packit Service a1973e
 *  threads, print the number of interrupts per thread and per second,
Packit Service a1973e
 *  and look for anomalous interrupts.  Look for mismatched thread
Packit Service a1973e
 *  ids, bad message type, or failed pfm_restart().
Packit Service a1973e
 *
Packit Service a1973e
 *  self_smpl_multi is a test program to stress signal delivery in the context
Packit Service a1973e
 *  of a multi-threaded self-sampling program which is common with PAPI and HPC.
Packit Service a1973e
 * 
Packit Service a1973e
 *  There is an issue with existing (as of 2.6.30) kernel which do not provide
Packit Service a1973e
 *  a reliable way of having the signal delivered to the thread in which the
Packit Service a1973e
 *  counter overflow occurred. This is problematic for many self-monitoring
Packit Service a1973e
 *  program.
Packit Service a1973e
 *
Packit Service a1973e
 *  This program demonstrates the issue by tracking the number of times
Packit Service a1973e
 *  the signal goes to the wrong thread. The bad behavior is exacerbated
Packit Service a1973e
 *  if the monitored threads, themselves, already use signals. Here we
Packit Service a1973e
 *  use SIGLARM.
Packit Service a1973e
 *
Packit Service a1973e
 *  Note that kernel developers have been made aware of this problem and
Packit Service a1973e
 *  a fix has been proposed. It introduces a new F_SETOWN_EX command to
Packit Service a1973e
 *  fcntl().
Packit Service a1973e
 */
Packit Service a1973e
#include <sys/time.h>
Packit Service a1973e
#include <sys/types.h>
Packit Service a1973e
#include <err.h>
Packit Service a1973e
#include <errno.h>
Packit Service a1973e
#include <fcntl.h>
Packit Service a1973e
#include <pthread.h>
Packit Service a1973e
#include <signal.h>
Packit Service a1973e
#include <stdio.h>
Packit Service a1973e
#include <stdlib.h>
Packit Service a1973e
#include <string.h>
Packit Service a1973e
#include <unistd.h>
Packit Service a1973e
#include <getopt.h>
Packit Service a1973e
#include <sys/ioctl.h>
Packit Service a1973e
#include <sys/mman.h>
Packit Service a1973e
Packit Service a1973e
#include "perf_util.h"
Packit Service a1973e
Packit Service a1973e
#define PROGRAM_TIME  8
Packit Service a1973e
#define THRESHOLD  20000000
Packit Service a1973e
Packit Service a1973e
static int program_time = PROGRAM_TIME;
Packit Service a1973e
static int threshold = THRESHOLD;
Packit Service a1973e
static int signum = SIGIO;
Packit Service a1973e
static pthread_barrier_t barrier;
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
static int buffer_pages = 1;
Packit Service a1973e
Packit Service a1973e
#define MAX_THR  128
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 *  the following definitions come
Packit Service a1973e
 *  from the F_SETOWN_EX patch from Peter Zijlstra
Packit Service a1973e
 * Check out: http://lkml.org/lkml/2009/8/4/128 
Packit Service a1973e
 */
Packit Service a1973e
#ifndef F_SETOWN_EX
Packit Service a1973e
#define F_SETOWN_EX	15
Packit Service a1973e
#define F_GETOWN_EX	16
Packit Service a1973e
Packit Service a1973e
#define F_OWNER_TID	0
Packit Service a1973e
#define F_OWNER_PID	1
Packit Service a1973e
#define F_OWNER_PGRP	2
Packit Service a1973e
Packit Service a1973e
struct f_owner_ex {
Packit Service a1973e
	int	type;
Packit Service a1973e
	pid_t	pid;
Packit Service a1973e
};
Packit Service a1973e
#endif
Packit Service a1973e
Packit Service a1973e
struct over_args {
Packit Service a1973e
	int fd;
Packit Service a1973e
	pid_t tid;
Packit Service a1973e
	int id;
Packit Service a1973e
	perf_event_desc_t *fds;
Packit Service a1973e
};
Packit Service a1973e
Packit Service a1973e
struct over_args fd2ov[MAX_THR];
Packit Service a1973e
Packit Service a1973e
long count[MAX_THR];
Packit Service a1973e
long total[MAX_THR];
Packit Service a1973e
long iter[MAX_THR];
Packit Service a1973e
long mismatch[MAX_THR];
Packit Service a1973e
long bad_msg[MAX_THR];
Packit Service a1973e
long bad_restart[MAX_THR];
Packit Service a1973e
int fown;
Packit Service a1973e
Packit Service a1973e
static __thread int myid; /* TLS */
Packit Service a1973e
static __thread perf_event_desc_t *fds; /* TLS */
Packit Service a1973e
static __thread int num_fds; /* TLS */
Packit Service a1973e
Packit Service a1973e
pid_t
Packit Service a1973e
gettid(void)
Packit Service a1973e
{
Packit Service a1973e
	return (pid_t)syscall(__NR_gettid);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
void
Packit Service a1973e
user_callback(int m)
Packit Service a1973e
{
Packit Service a1973e
	count[m]++;
Packit Service a1973e
	total[m]++;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
void
Packit Service a1973e
do_cycles(void)
Packit Service a1973e
{
Packit Service a1973e
	struct timeval start, last, now;
Packit Service a1973e
	unsigned long x, sum;
Packit Service a1973e
Packit Service a1973e
	gettimeofday(&start, NULL);
Packit Service a1973e
	last = start;
Packit Service a1973e
	count[myid] = 0;
Packit Service a1973e
	total[myid] = 0;
Packit Service a1973e
	iter[myid] = 0;
Packit Service a1973e
Packit Service a1973e
	do {
Packit Service a1973e
Packit Service a1973e
		sum = 1;
Packit Service a1973e
		for (x = 1; x < 250000; x++) {
Packit Service a1973e
			/* signal pending to private queue because of
Packit Service a1973e
			 * pthread_kill(), i.e., tkill()
Packit Service a1973e
			 */
Packit Service a1973e
			if ((x % 5000) == 0)
Packit Service a1973e
				pthread_kill(pthread_self(), SIGUSR1);
Packit Service a1973e
			sum += x;
Packit Service a1973e
		}
Packit Service a1973e
		iter[myid]++;
Packit Service a1973e
Packit Service a1973e
		gettimeofday(&now, NULL);
Packit Service a1973e
		if (now.tv_sec > last.tv_sec) {
Packit Service a1973e
			printf("%ld: myid = %3d, fd = %3d, count = %4ld, iter = %4ld, rate = %ld/Kiter\n",
Packit Service a1973e
				(long)(now.tv_sec - start.tv_sec),
Packit Service a1973e
				myid,
Packit Service a1973e
				fd2ov[myid].fd,
Packit Service a1973e
				count[myid], iter[myid],
Packit Service a1973e
				(1000 * count[myid])/iter[myid]);
Packit Service a1973e
Packit Service a1973e
			count[myid] = 0;
Packit Service a1973e
			iter[myid] = 0;
Packit Service a1973e
			last = now;
Packit Service a1973e
		}
Packit Service a1973e
	} while (now.tv_sec < start.tv_sec + program_time);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
#define DPRINT(str)   \
Packit Service a1973e
printf("(%s) si->fd = %d, ov->self = 0x%lx, self = 0x%lx\n",   \
Packit Service a1973e
       str, fd, (unsigned long)ov->self, (unsigned long)self)
Packit Service a1973e
void
Packit Service a1973e
sigusr1_handler(int sig, siginfo_t *info, void *context)
Packit Service a1973e
{
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * a signal handler cannot safely invoke printf()
Packit Service a1973e
 */
Packit Service a1973e
void
Packit Service a1973e
sigio_handler(int sig, siginfo_t *info, void *context)
Packit Service a1973e
{
Packit Service a1973e
	perf_event_desc_t *fdx;
Packit Service a1973e
	struct perf_event_header ehdr;
Packit Service a1973e
	struct over_args *ov;
Packit Service a1973e
	int fd, i, ret;
Packit Service a1973e
	pid_t tid;
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
	 * positive si_code indicate kernel generated signal
Packit Service a1973e
	 * which is normal for SIGIO
Packit Service a1973e
	 */
Packit Service a1973e
	if (info->si_code < 0)
Packit Service a1973e
		errx(1, "signal not generated by kernel");
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
	 * SIGPOLL = SIGIO
Packit Service a1973e
	 * expect POLL_HUP instead of POLL_IN because we are
Packit Service a1973e
	 * in one-shot mode (IOC_REFRESH)
Packit Service a1973e
	 */
Packit Service a1973e
	if (info->si_code != POLL_HUP)
Packit Service a1973e
		errx(1, "signal not generated by SIGIO: %d", info->si_code);
Packit Service a1973e
Packit Service a1973e
	fd = info->si_fd;
Packit Service a1973e
 	tid = gettid();
Packit Service a1973e
Packit Service a1973e
	for(i=0; i < MAX_THR; i++)
Packit Service a1973e
		if (fd2ov[i].fd == fd)
Packit Service a1973e
			break;
Packit Service a1973e
Packit Service a1973e
	if (i == MAX_THR)
Packit Service a1973e
		errx(1, "bad info.si_fd: %d", fd);
Packit Service a1973e
Packit Service a1973e
 	ov = &fd2ov[i];
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
 	 * current thread id may not always match the id
Packit Service a1973e
 	 * associated with the file descriptor
Packit Service a1973e
 	 *
Packit Service a1973e
 	 * We need to use the other's thread fds info
Packit Service a1973e
 	 * otherwise, it is going to get stuck with no
Packit Service a1973e
 	 * more samples generated
Packit Service a1973e
 	 */
Packit Service a1973e
	if (tid != ov->tid) {
Packit Service a1973e
		mismatch[myid]++;
Packit Service a1973e
		fdx = ov->fds;
Packit Service a1973e
	} else {
Packit Service a1973e
		fdx = fds;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
 	 * read sample header
Packit Service a1973e
 	 */
Packit Service a1973e
	ret = perf_read_buffer(fdx+0, &ehdr, sizeof(ehdr));
Packit Service a1973e
	if (ret) {
Packit Service a1973e
		errx(1, "cannot read event header");
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
	 * message we do not handle
Packit Service a1973e
	 */
Packit Service a1973e
	if (ehdr.type != PERF_RECORD_SAMPLE) {
Packit Service a1973e
		bad_msg[myid]++;
Packit Service a1973e
		goto skip;
Packit Service a1973e
	}
Packit Service a1973e
	user_callback(myid);
Packit Service a1973e
skip:
Packit Service a1973e
	/* mark sample as consumed */
Packit Service a1973e
	perf_skip_buffer(fdx+0, ehdr.size);
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
	 * re-arm period, next notification after wakeup_events
Packit Service a1973e
	 */
Packit Service a1973e
	ret = ioctl(fd, PERF_EVENT_IOC_REFRESH, 1);
Packit Service a1973e
	if (ret)
Packit Service a1973e
		err(1, "cannot refresh");
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
void
Packit Service a1973e
overflow_start(char *name)
Packit Service a1973e
{
Packit Service a1973e
	struct f_owner_ex fown_ex;
Packit Service a1973e
	struct over_args *ov;
Packit Service a1973e
	size_t pgsz;
Packit Service a1973e
	int ret, fd, flags;
Packit Service a1973e
Packit Service a1973e
	fds = NULL;
Packit Service a1973e
	num_fds = 0;
Packit Service a1973e
	ret = perf_setup_list_events("cycles", &fds, &num_fds);
Packit Service a1973e
	if (ret || !num_fds)
Packit Service a1973e
		errx(1, "cannot monitor event");
Packit Service a1973e
Packit Service a1973e
	pgsz = sysconf(_SC_PAGESIZE);
Packit Service a1973e
	ov = &fd2ov[myid];
Packit Service a1973e
Packit Service a1973e
	/* do not enable now */
Packit Service a1973e
	fds[0].hw.disabled = 1;
Packit Service a1973e
Packit Service a1973e
	/* notify after 1 sample */
Packit Service a1973e
	fds[0].hw.wakeup_events = 1;
Packit Service a1973e
	fds[0].hw.sample_type = PERF_SAMPLE_IP;
Packit Service a1973e
	fds[0].hw.sample_period = threshold;
Packit Service a1973e
	fds[0].hw.read_format = 0;
Packit Service a1973e
Packit Service a1973e
	fds[0].fd = fd = perf_event_open(&fds[0].hw, gettid(), -1, -1, 0);
Packit Service a1973e
	if (fd == -1)
Packit Service a1973e
		err(1, "cannot attach event %s", fds[0].name);
Packit Service a1973e
Packit Service a1973e
	ov->fd = fd;
Packit Service a1973e
	ov->tid = gettid();
Packit Service a1973e
	ov->id = myid;
Packit Service a1973e
	ov->fds = fds;
Packit Service a1973e
Packit Service a1973e
	flags = fcntl(fd, F_GETFL, 0);
Packit Service a1973e
	if (fcntl(fd, F_SETFL, flags | O_ASYNC) < 0)
Packit Service a1973e
		err(1, "fcntl SETFL failed");
Packit Service a1973e
Packit Service a1973e
	fown_ex.type = F_OWNER_TID;
Packit Service a1973e
	fown_ex.pid  = gettid();
Packit Service a1973e
	ret = fcntl(fd,
Packit Service a1973e
		    (fown ? F_SETOWN_EX : F_SETOWN), 
Packit Service a1973e
		    (fown ? (unsigned long)&fown_ex: (unsigned long)gettid()));
Packit Service a1973e
	if (ret)
Packit Service a1973e
		err(1, "fcntl SETOWN failed");
Packit Service a1973e
Packit Service a1973e
	if (fcntl(fd, F_SETSIG, signum) < 0)
Packit Service a1973e
		err(1, "fcntl SETSIG failed");
Packit Service a1973e
Packit Service a1973e
	fds[0].buf = mmap(NULL, (buffer_pages + 1)* pgsz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
Packit Service a1973e
	if (fds[0].buf == MAP_FAILED)
Packit Service a1973e
		err(1, "cannot mmap buffer");
Packit Service a1973e
	
Packit Service a1973e
	fds[0].pgmsk = (buffer_pages * pgsz) - 1;
Packit Service a1973e
Packit Service a1973e
	printf("launch %s: fd: %d, tid: %d\n", name, fd, ov->tid);
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
 	 * activate event for wakeup_events (samples)
Packit Service a1973e
 	 */
Packit Service a1973e
	ret = ioctl(fd, PERF_EVENT_IOC_REFRESH , 1);
Packit Service a1973e
	if (ret == -1)
Packit Service a1973e
		err(1, "cannot refresh");
Packit Service a1973e
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
void
Packit Service a1973e
overflow_stop(void)
Packit Service a1973e
{
Packit Service a1973e
	int ret;
Packit Service a1973e
	ret = ioctl(fd2ov[myid].fd, PERF_EVENT_IOC_DISABLE, 0);
Packit Service a1973e
	if (ret)
Packit Service a1973e
		err(1, "cannot stop");
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
void *
Packit Service a1973e
my_thread(void *v)
Packit Service a1973e
{
Packit Service a1973e
	int retval = 0;
Packit Service a1973e
	
Packit Service a1973e
	myid = (unsigned long)v;
Packit Service a1973e
Packit Service a1973e
	pthread_barrier_wait(&barrier);
Packit Service a1973e
Packit Service a1973e
	overflow_start("side");
Packit Service a1973e
	do_cycles();
Packit Service a1973e
	overflow_stop();
Packit Service a1973e
Packit Service a1973e
	perf_free_fds(fds, num_fds);
Packit Service a1973e
Packit Service a1973e
	pthread_exit((void *)&retval);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void
Packit Service a1973e
usage(void)
Packit Service a1973e
{
Packit Service a1973e
	printf("self_smpl_multi [-t secs] [-p period] [-s signal] [-f] [-n threads]\n"
Packit Service a1973e
		"-t secs: duration of the run in seconds\n"
Packit Service a1973e
		"-p period: sampling period in CPU cycles\n"
Packit Service a1973e
		"-s signal: signal to use (default: SIGIO)\n"
Packit Service a1973e
		"-n thread: number of threads to create (default: 1)\n"
Packit Service a1973e
		"-f : use F_SETOWN_EX for correct delivery of signal to thread (default: off)\n");
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 *  Program args: program_time, threshold, signum.
Packit Service a1973e
 */
Packit Service a1973e
int
Packit Service a1973e
main(int argc, char **argv)
Packit Service a1973e
{
Packit Service a1973e
	struct sigaction sa;
Packit Service a1973e
	pthread_t allthr[MAX_THR];
Packit Service a1973e
	sigset_t set, old, new;
Packit Service a1973e
	int i, ret, max_thr = 1;
Packit Service a1973e
Packit Service a1973e
	while ((i=getopt(argc, argv, "t:p:s:fhn:")) != EOF) {
Packit Service a1973e
		switch(i) {
Packit Service a1973e
		case 'h':
Packit Service a1973e
			usage();
Packit Service a1973e
			return 0;
Packit Service a1973e
		case 't':
Packit Service a1973e
			program_time = atoi(optarg);
Packit Service a1973e
			break;
Packit Service a1973e
		case 'p':
Packit Service a1973e
			threshold = atoi(optarg);
Packit Service a1973e
			break;
Packit Service a1973e
		case 's':
Packit Service a1973e
			signum = atoi(optarg);
Packit Service a1973e
			break;
Packit Service a1973e
		case 'f':
Packit Service a1973e
			fown = 1;
Packit Service a1973e
			break;
Packit Service a1973e
		case 'n':
Packit Service a1973e
			max_thr = atoi(optarg);
Packit Service a1973e
			if (max_thr >= MAX_THR)
Packit Service a1973e
				errx(1, "no more than %d threads", MAX_THR);
Packit Service a1973e
			break;
Packit Service a1973e
		default:
Packit Service a1973e
			errx(1, "invalid option");
Packit Service a1973e
		}
Packit Service a1973e
	}
Packit Service a1973e
	printf("program_time = %d, threshold = %d, signum = %d fcntl(%s), threads = %d\n",
Packit Service a1973e
		program_time, threshold, signum,
Packit Service a1973e
		fown ? "F_SETOWN_EX" : "F_SETOWN",
Packit Service a1973e
		max_thr);
Packit Service a1973e
Packit Service a1973e
	for (i = 0; i < MAX_THR; i++) {
Packit Service a1973e
		mismatch[i] = 0;
Packit Service a1973e
		bad_msg[i] = 0;
Packit Service a1973e
		bad_restart[i] = 0;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	memset(&sa, 0, sizeof(sa));
Packit Service a1973e
	sigemptyset(&set);
Packit Service a1973e
Packit Service a1973e
	sa.sa_sigaction = sigusr1_handler;
Packit Service a1973e
	sa.sa_mask = set;
Packit Service a1973e
	sa.sa_flags = SA_SIGINFO;
Packit Service a1973e
Packit Service a1973e
	if (sigaction(SIGUSR1, &sa, NULL) != 0)
Packit Service a1973e
		errx(1, "sigaction failed");
Packit Service a1973e
Packit Service a1973e
	memset(&sa, 0, sizeof(sa));
Packit Service a1973e
	sigemptyset(&set);
Packit Service a1973e
Packit Service a1973e
	sa.sa_sigaction = sigio_handler;
Packit Service a1973e
	sa.sa_mask = set;
Packit Service a1973e
	sa.sa_flags = SA_SIGINFO;
Packit Service a1973e
Packit Service a1973e
	if (sigaction(signum, &sa, NULL) != 0)
Packit Service a1973e
		errx(1, "sigaction failed");
Packit Service a1973e
Packit Service a1973e
	if (pfm_initialize() != PFM_SUCCESS)
Packit Service a1973e
		errx(1, "pfm_initialize failed");
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
 	 * +1 because main thread is also using the barrier
Packit Service a1973e
 	 */
Packit Service a1973e
	pthread_barrier_init(&barrier, 0, max_thr+1);
Packit Service a1973e
Packit Service a1973e
	for(i=0; i < max_thr; i++) {
Packit Service a1973e
		ret = pthread_create(allthr+i, NULL, my_thread, (void *)(unsigned long)i);
Packit Service a1973e
		if (ret)
Packit Service a1973e
			err(1, "pthread_create failed");
Packit Service a1973e
	}
Packit Service a1973e
	myid = i;
Packit Service a1973e
	sigemptyset(&set);
Packit Service a1973e
	sigemptyset(&new;;
Packit Service a1973e
	sigaddset(&set, SIGIO);
Packit Service a1973e
	sigaddset(&new, SIGIO);
Packit Service a1973e
Packit Service a1973e
	if (pthread_sigmask(SIG_BLOCK, &set, NULL))
Packit Service a1973e
		err(1, "cannot mask SIGIO in main thread");
Packit Service a1973e
Packit Service a1973e
	ret = sigprocmask(SIG_SETMASK, NULL, &old;;
Packit Service a1973e
	if (ret)
Packit Service a1973e
		err(1, "sigprocmask failed");
Packit Service a1973e
Packit Service a1973e
	if (sigismember(&old, SIGIO)) {
Packit Service a1973e
		warnx("program started with SIGIO masked, unmasking it now\n");
Packit Service a1973e
		ret = sigprocmask(SIG_UNBLOCK, &new, NULL);
Packit Service a1973e
		if (ret)
Packit Service a1973e
			err(1, "sigprocmask failed");
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	pthread_barrier_wait(&barrier);
Packit Service a1973e
	printf("\n\n");
Packit Service a1973e
Packit Service a1973e
	for (i = 0; i < max_thr; i++) {
Packit Service a1973e
		pthread_join(allthr[i], NULL);
Packit Service a1973e
	}
Packit Service a1973e
	printf("\n\n");
Packit Service a1973e
	for (i = 0; i < max_thr; i++) {
Packit Service a1973e
		printf("myid = %3d, fd = %3d, total = %4ld, mismatch = %ld, "
Packit Service a1973e
			"bad_msg = %ld, bad_restart = %ld\n",
Packit Service a1973e
			fd2ov[i].id, fd2ov[i].fd, total[i], mismatch[i],
Packit Service a1973e
			bad_msg[i], bad_restart[i]);
Packit Service a1973e
	}
Packit Service a1973e
	/* free libpfm resources cleanly */
Packit Service a1973e
	pfm_terminate();
Packit Service a1973e
Packit Service a1973e
	return (0);
Packit Service a1973e
}