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

Packit 577717
/* $Id: global.c,v 1.37 2004/01/12 14:25:40 mikpe Exp $
Packit 577717
 *
Packit 577717
 * usage: ./global [sampling_interval_usec [sleep_interval_sec]]
Packit 577717
 *
Packit 577717
 * This test program illustrates how a process may use the
Packit 577717
 * Linux x86 Performance-Monitoring Counters interface to
Packit 577717
 * do system-wide performance monitoring.
Packit 577717
 *
Packit 577717
 * Copyright (C) 2000-2004  Mikael Pettersson
Packit 577717
 */
Packit 577717
#include <errno.h>
Packit 577717
#include <setjmp.h>
Packit 577717
#include <signal.h>
Packit 577717
#include <stddef.h>
Packit 577717
#include <stdio.h>
Packit 577717
#include <stdlib.h>
Packit 577717
#include <string.h>
Packit 577717
#include <unistd.h>
Packit 577717
#include "libperfctr.h"
Packit 577717
#include "arch.h"
Packit 577717
Packit 577717
static struct gperfctr *gperfctr;
Packit 577717
static struct perfctr_info info;
Packit 577717
static unsigned int nrcpus;
Packit 577717
static unsigned short *cpu_logical_map;
Packit 577717
struct gperfctr_state {	/* no longer defined in or used by the kernel */
Packit 577717
    unsigned int nrcpus;
Packit 577717
    struct gperfctr_cpu_state cpu_state[1]; /* actually 'nrcpus' */
Packit 577717
};
Packit 577717
static struct gperfctr_state *state;
Packit 577717
static struct gperfctr_state *prev_state;
Packit 577717
static unsigned int sample_num;
Packit 577717
int counting_mips;	/* for CPUs that cannot FLOPS */
Packit 577717
static unsigned long sampling_interval = 1000000; /* XXX: reduce for >4GHz CPUs */
Packit 577717
static unsigned int sleep_interval = 5;
Packit 577717
Packit 577717
static jmp_buf main_buf;
Packit 577717
Packit 577717
static void onint(int sig)	/* ^C handler */
Packit 577717
{
Packit 577717
    longjmp(main_buf, 1);
Packit 577717
}
Packit 577717
Packit 577717
static void catch_sigint(void)
Packit 577717
{
Packit 577717
    struct sigaction act;
Packit 577717
Packit 577717
    memset(&act, 0, sizeof act);
Packit 577717
    act.sa_handler = onint;
Packit 577717
    if( sigaction(SIGINT, &act, NULL) < 0 ) {
Packit 577717
	perror("unable to catch SIGINT");
Packit 577717
	exit(1);
Packit 577717
    }
Packit 577717
}
Packit 577717
Packit 577717
static unsigned int hweight32(unsigned int w)
Packit 577717
{
Packit 577717
    unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
Packit 577717
    res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
Packit 577717
    res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
Packit 577717
    res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
Packit 577717
    return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
Packit 577717
}
Packit 577717
Packit 577717
static void setup_cpu_logical_map_and_nrcpus(const struct perfctr_cpus_info *cpus_info)
Packit 577717
{
Packit 577717
    const unsigned int *cpus, *cpus_forbidden;
Packit 577717
    unsigned int nrwords, i, cpumask, bitmask;
Packit 577717
    unsigned int logical_cpu_nr, kernel_cpu_nr;
Packit 577717
Packit 577717
    cpus = cpus_info->cpus->mask;
Packit 577717
    cpus_forbidden = cpus_info->cpus_forbidden->mask;
Packit 577717
    nrwords = cpus_info->cpus->nrwords;
Packit 577717
Packit 577717
    nrcpus = 0;
Packit 577717
    for(i = 0; i < nrwords; ++i)
Packit 577717
	nrcpus += hweight32(cpus[i] & ~cpus_forbidden[i]);
Packit 577717
Packit 577717
    cpu_logical_map = malloc(nrcpus*sizeof(cpu_logical_map[0]));
Packit 577717
    if( !cpu_logical_map ) {
Packit 577717
	perror("malloc");
Packit 577717
	exit(1);
Packit 577717
    }
Packit 577717
Packit 577717
    logical_cpu_nr = 0;
Packit 577717
    for(i = 0; i < nrwords; ++i) {
Packit 577717
	cpumask = cpus[i] & ~cpus_forbidden[i];
Packit 577717
	kernel_cpu_nr = i * 8 * sizeof(int);
Packit 577717
	for(bitmask = 1; cpumask != 0; ++kernel_cpu_nr, bitmask <<= 1) {
Packit 577717
	    if( cpumask & bitmask ) {
Packit 577717
		cpumask &= ~bitmask;
Packit 577717
		cpu_logical_map[logical_cpu_nr] = kernel_cpu_nr;
Packit 577717
		++logical_cpu_nr;
Packit 577717
	    }
Packit 577717
	}
Packit 577717
    }
Packit 577717
Packit 577717
    if( logical_cpu_nr != nrcpus )
Packit 577717
	abort();
Packit 577717
}
Packit 577717
Packit 577717
static void do_init(void)
Packit 577717
{
Packit 577717
    struct perfctr_cpus_info *cpus_info;
Packit 577717
    size_t nbytes;
Packit 577717
    unsigned int i;
Packit 577717
Packit 577717
    gperfctr = gperfctr_open();
Packit 577717
    if( !gperfctr ) {
Packit 577717
	perror("gperfctr_open");
Packit 577717
	exit(1);
Packit 577717
    }
Packit 577717
    if( gperfctr_info(gperfctr, &info) < 0 ) {
Packit 577717
	perror("gperfctr_info");
Packit 577717
	exit(1);
Packit 577717
    }
Packit 577717
    cpus_info = gperfctr_cpus_info(gperfctr);
Packit 577717
    if( !cpus_info ) {
Packit 577717
	perror("gperfctr_info");
Packit 577717
	exit(1);
Packit 577717
    }
Packit 577717
    printf("\nPerfCtr Info:\n");
Packit 577717
    perfctr_info_print(&info;;
Packit 577717
    perfctr_cpus_info_print(cpus_info);
Packit 577717
Packit 577717
    /* use all non-forbidden CPUs */
Packit 577717
Packit 577717
    setup_cpu_logical_map_and_nrcpus(cpus_info);
Packit 577717
    free(cpus_info);
Packit 577717
Packit 577717
    /* now alloc state memory based on nrcpus */
Packit 577717
Packit 577717
    nbytes = offsetof(struct gperfctr_state, cpu_state[0])
Packit 577717
	+ nrcpus * sizeof(state->cpu_state[0]);
Packit 577717
    state = malloc(nbytes);
Packit 577717
    prev_state = malloc(nbytes);
Packit 577717
    if( !state || !prev_state ) {
Packit 577717
	perror("malloc");
Packit 577717
	exit(1);
Packit 577717
    }
Packit 577717
    memset(state, 0, nbytes);
Packit 577717
    memset(prev_state, 0, nbytes);
Packit 577717
Packit 577717
    /* format state to indicate which CPUs we want to sample */
Packit 577717
Packit 577717
    for(i = 0; i < nrcpus; ++i)
Packit 577717
	state->cpu_state[i].cpu = cpu_logical_map[i];
Packit 577717
    state->nrcpus = nrcpus;
Packit 577717
}
Packit 577717
Packit 577717
static int do_read(unsigned int sleep_interval)
Packit 577717
{
Packit 577717
    unsigned int i, cpu, ctr;
Packit 577717
Packit 577717
    for(i = 0; i < state->nrcpus; ++i) {
Packit 577717
	if( gperfctr_read(gperfctr, &state->cpu_state[i]) < 0 ) {
Packit 577717
	    perror("gperfctr_read");
Packit 577717
	    return -1;
Packit 577717
	}
Packit 577717
    }
Packit 577717
    printf("\nSample #%u\n", ++sample_num);
Packit 577717
    for(i = 0; i < state->nrcpus; ++i) {
Packit 577717
	cpu = state->cpu_state[i].cpu;
Packit 577717
	printf("\nCPU %d:\n", cpu);
Packit 577717
	if( state->cpu_state[i].cpu_control.tsc_on )
Packit 577717
	    printf("\ttsc\t%lld\n", state->cpu_state[i].sum.tsc);
Packit 577717
	for(ctr = 0; ctr < state->cpu_state[i].cpu_control.nractrs; ++ctr)
Packit 577717
	    printf("\tpmc[%d]\t%lld\n",
Packit 577717
		   ctr, state->cpu_state[i].sum.pmc[ctr]);
Packit 577717
	if( ctr >= 1 ) {	/* compute and display MFLOP/s or MIP/s */
Packit 577717
	    unsigned long long tsc = state->cpu_state[i].sum.tsc;
Packit 577717
	    unsigned long long prev_tsc = prev_state->cpu_state[i].sum.tsc;
Packit 577717
	    unsigned long long ticks = tsc - prev_tsc;
Packit 577717
	    unsigned long long pmc0 = state->cpu_state[i].sum.pmc[0];
Packit 577717
	    unsigned long long prev_pmc0 = prev_state->cpu_state[i].sum.pmc[0];
Packit 577717
	    unsigned long long ops = pmc0 - prev_pmc0;
Packit 577717
	    double seconds = state->cpu_state[i].cpu_control.tsc_on
Packit 577717
		? ((double)ticks * (double)(info.tsc_to_cpu_mult ? : 1) / (double)info.cpu_khz) / 1000.0
Packit 577717
		: (double)sleep_interval; /* don't div-by-0 on WinChip ... */
Packit 577717
	    printf("\tSince previous sample:\n");
Packit 577717
	    printf("\tSECONDS\t%.15g\n", seconds);
Packit 577717
	    printf("\t%s\t%llu\n", counting_mips ? "INSNS" : "FLOPS", ops);
Packit 577717
	    printf("\t%s/s\t%.15g\n",
Packit 577717
		   counting_mips ? "MIP" : "MFLOP",
Packit 577717
		   ((double)ops / seconds) / 1e6);
Packit 577717
	    prev_state->cpu_state[i].sum.tsc = tsc;
Packit 577717
	    prev_state->cpu_state[i].sum.pmc[0] = pmc0;
Packit 577717
	}
Packit 577717
    }
Packit 577717
    return 0;
Packit 577717
}
Packit 577717
Packit 577717
static void print_control(const struct perfctr_cpu_control *control)
Packit 577717
{
Packit 577717
    printf("\nControl used:\n");
Packit 577717
    perfctr_cpu_control_print(control);
Packit 577717
}
Packit 577717
Packit 577717
static void do_enable(unsigned long sampling_interval)
Packit 577717
{
Packit 577717
    struct perfctr_cpu_control cpu_control;
Packit 577717
    unsigned int i;
Packit 577717
Packit 577717
    setup_control(&info, &cpu_control);
Packit 577717
    print_control(&cpu_control);
Packit 577717
Packit 577717
    for(i = 0; i < nrcpus; ++i) {
Packit 577717
	struct gperfctr_cpu_control control;
Packit 577717
	control.cpu = cpu_logical_map[i];
Packit 577717
	control.cpu_control = cpu_control;
Packit 577717
	if( gperfctr_control(gperfctr, &control) < 0 ) {
Packit 577717
	    perror("gperfctr_control");
Packit 577717
	    exit(1);
Packit 577717
	}
Packit 577717
    }
Packit 577717
    if( gperfctr_start(gperfctr, sampling_interval) < 0 ) {
Packit 577717
	perror("gperfctr_start");
Packit 577717
	exit(1);
Packit 577717
    }
Packit 577717
}
Packit 577717
Packit 577717
int main(int argc, const char **argv)
Packit 577717
{
Packit 577717
    if( argc >= 2 ) {
Packit 577717
	sampling_interval = strtoul(argv[1], NULL, 0);
Packit 577717
	if( argc >= 3 )
Packit 577717
	    sleep_interval = strtoul(argv[2], NULL, 0);
Packit 577717
    }
Packit 577717
Packit 577717
    if( setjmp(main_buf) == 0 ) {
Packit 577717
	catch_sigint();
Packit 577717
	do_init();
Packit 577717
	do_enable(sampling_interval);
Packit 577717
	printf("\nSampling interval:\t%lu usec\n", sampling_interval);
Packit 577717
	printf("Sleep interval:\t\t%u sec\n", sleep_interval);
Packit 577717
	do {
Packit 577717
	    sleep(sleep_interval);
Packit 577717
	} while( do_read(sleep_interval) == 0 );
Packit 577717
    }
Packit 577717
    if( gperfctr ) {
Packit 577717
	printf("shutting down..\n");
Packit 577717
	gperfctr_stop(gperfctr);
Packit 577717
    }
Packit 577717
    return 0;
Packit 577717
}