Blame src/perfctr-2.7.x/examples/signal/signal.c

Packit Service a1973e
/* $Id: signal.c,v 1.20 2005/04/08 14:37:55 mikpe Exp $
Packit Service a1973e
 *
Packit Service a1973e
 * This test program illustrates how performance counter overflow
Packit Service a1973e
 * can be caught and sent to the process as a user-specified signal.
Packit Service a1973e
 *
Packit Service a1973e
 * Limitations:
Packit Service a1973e
 * - Requires a 2.4 or newer kernel with local APIC support.
Packit Service a1973e
 * - Requires a CPU with a local APIC (P4, P6, K8, K7).
Packit Service a1973e
 *
Packit Service a1973e
 * Copyright (C) 2001-2004  Mikael Pettersson
Packit Service a1973e
 */
Packit Service a1973e
#define __USE_GNU /* enable symbolic names for gregset_t[] indices */
Packit Service a1973e
#include <sys/ucontext.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 "libperfctr.h"
Packit Service a1973e
#include "arch.h"
Packit Service a1973e
Packit Service a1973e
static struct vperfctr *vperfctr;
Packit Service a1973e
static struct perfctr_info info;
Packit Service a1973e
Packit Service a1973e
static void do_open(void)
Packit Service a1973e
{
Packit Service a1973e
    vperfctr = vperfctr_open();
Packit Service a1973e
    if( !vperfctr ) {
Packit Service a1973e
	perror("vperfctr_open");
Packit Service a1973e
	exit(1);
Packit Service a1973e
    }
Packit Service a1973e
    if( vperfctr_info(vperfctr, &info) < 0 ) {
Packit Service a1973e
	perror("vperfctr_info");
Packit Service a1973e
	exit(1);
Packit Service a1973e
    }
Packit Service a1973e
    if( !(info.cpu_features & PERFCTR_FEATURE_PCINT) )
Packit Service a1973e
	printf("PCINT not supported -- expect failure\n");
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void on_sigio(int sig, siginfo_t *si, void *puc)
Packit Service a1973e
{
Packit Service a1973e
    struct ucontext *uc;
Packit Service a1973e
    unsigned long pc;
Packit Service a1973e
    unsigned int pmc_mask;
Packit Service a1973e
Packit Service a1973e
    if( sig != SIGIO ) {
Packit Service a1973e
	printf("%s: unexpected signal %d\n", __FUNCTION__, sig);
Packit Service a1973e
	return;
Packit Service a1973e
    }
Packit Service a1973e
    if( si->si_code != SI_PMC_OVF ) {
Packit Service a1973e
	printf("%s: unexpected si_code #%x\n", __FUNCTION__, si->si_code);
Packit Service a1973e
	return;
Packit Service a1973e
    }
Packit Service a1973e
    if( (pmc_mask = si->si_pmc_ovf_mask) == 0 ) {
Packit Service a1973e
	printf("%s: overflow PMCs not identified\n", __FUNCTION__);
Packit Service a1973e
	return;
Packit Service a1973e
    }
Packit Service a1973e
    uc = puc;
Packit Service a1973e
    pc = ucontext_pc(uc);
Packit Service a1973e
    if( !vperfctr_is_running(vperfctr) ) {
Packit Service a1973e
	/*
Packit Service a1973e
	 * My theory is that this happens if a perfctr overflowed
Packit Service a1973e
	 * at the very instruction for the VPERFCTR_STOP call.
Packit Service a1973e
	 * Signal delivery is delayed until the kernel returns to
Packit Service a1973e
	 * user-space, at which time VPERFCTR_STOP will already
Packit Service a1973e
	 * have marked the vperfctr as stopped. In this case, we
Packit Service a1973e
	 * cannot and must not attempt to IRESUME it.
Packit Service a1973e
	 * This can be triggered by counting e.g. BRANCHES and setting
Packit Service a1973e
	 * the overflow limit ridiculously low.
Packit Service a1973e
	 */
Packit Service a1973e
	printf("%s: unexpected overflow from PMC set %#x at pc %#lx\n",
Packit Service a1973e
	       __FUNCTION__, pmc_mask, pc);
Packit Service a1973e
	return;
Packit Service a1973e
    }
Packit Service a1973e
    printf("%s: PMC overflow set %#x at pc %#lx\n", __FUNCTION__, pmc_mask, pc);
Packit Service a1973e
    if( vperfctr_iresume(vperfctr) < 0 ) {
Packit Service a1973e
	perror("vperfctr_iresume");
Packit Service a1973e
	abort();
Packit Service a1973e
    }
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void do_sigaction(void)
Packit Service a1973e
{
Packit Service a1973e
    struct sigaction sa;
Packit Service a1973e
    memset(&sa, 0, sizeof sa);
Packit Service a1973e
    sa.sa_sigaction = on_sigio;
Packit Service a1973e
    sa.sa_flags = SA_SIGINFO;
Packit Service a1973e
    if( sigaction(SIGIO, &sa, NULL) < 0 ) {
Packit Service a1973e
	perror("sigaction");
Packit Service a1973e
	exit(1);
Packit Service a1973e
    }
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void do_control(void)
Packit Service a1973e
{
Packit Service a1973e
    struct vperfctr_control control;
Packit Service a1973e
Packit Service a1973e
    memset(&control, 0, sizeof control);
Packit Service a1973e
    do_setup(&info, &control.cpu_control);
Packit Service a1973e
    control.si_signo = SIGIO;
Packit Service a1973e
Packit Service a1973e
    printf("Control used:\n");
Packit Service a1973e
    perfctr_cpu_control_print(&control.cpu_control);
Packit Service a1973e
    printf("\n");
Packit Service a1973e
Packit Service a1973e
    if( vperfctr_control(vperfctr, &control) < 0 ) {
Packit Service a1973e
	perror("vperfctr_control");
Packit Service a1973e
	exit(1);
Packit Service a1973e
    }
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void do_stop(void)
Packit Service a1973e
{
Packit Service a1973e
    struct sigaction sa;
Packit Service a1973e
Packit Service a1973e
    if( vperfctr_stop(vperfctr) )
Packit Service a1973e
	perror("vperfctr_stop");
Packit Service a1973e
    memset(&sa, 0, sizeof sa);
Packit Service a1973e
    sa.sa_handler = SIG_DFL;
Packit Service a1973e
    if( sigaction(SIGIO, &sa, NULL) < 0 ) {
Packit Service a1973e
	perror("sigaction");
Packit Service a1973e
	exit(1);
Packit Service a1973e
    }
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
#define N 150
Packit Service a1973e
static double v[N], w[N];
Packit Service a1973e
static double it;
Packit Service a1973e
Packit Service a1973e
static void do_dotprod(void)
Packit Service a1973e
{
Packit Service a1973e
    int i;
Packit Service a1973e
    double sum;
Packit Service a1973e
Packit Service a1973e
    sum = 0.0;
Packit Service a1973e
    for(i = 0; i < N; ++i)
Packit Service a1973e
	sum += v[i] * w[i];
Packit Service a1973e
    it = sum;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int main(void)
Packit Service a1973e
{
Packit Service a1973e
    do_sigaction();
Packit Service a1973e
    do_open();
Packit Service a1973e
    do_control();
Packit Service a1973e
    do_dotprod();
Packit Service a1973e
    do_stop();
Packit Service a1973e
    return 0;
Packit Service a1973e
}