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

Packit 577717
/* $Id: perfex.c,v 1.35 2005/01/16 22:51:20 mikpe Exp $
Packit 577717
 *
Packit 577717
 * NAME
Packit 577717
 *	perfex - a command-line interface to processor performance counters
Packit 577717
 *
Packit 577717
 * SYNOPSIS
Packit 577717
 *	perfex [-e event] .. [--p4pe=value] [--p4pmv=value] [-o file] command
Packit 577717
 *	perfex { -i | -l | -L }
Packit 577717
 *
Packit 577717
 * DESCRIPTION
Packit 577717
 *	The given command is executed; after it is complete, perfex
Packit 577717
 *	prints the values of the various hardware performance counters.
Packit 577717
 *
Packit 577717
 * OPTIONS
Packit 577717
 *	-e event | --event=event
Packit 577717
 *		Specify an event to be counted.
Packit 577717
 *		Multiple event specifiers may be given, limited by the
Packit 577717
 *		number of available performance counters in the processor.
Packit 577717
 *
Packit 577717
 *		The full syntax of an event specifier is "evntsel/escr@pmc".
Packit 577717
 *		All three components are 32-bit processor-specific numbers,
Packit 577717
 *		written in decimal or hexadecimal notation.
Packit 577717
 *
Packit 577717
 *		"evntsel" is the primary processor-specific event selection
Packit 577717
 *		code to use for this event. This field is mandatory.
Packit 577717
 *
Packit 577717
 *		"/escr" is used to specify additional event selection data
Packit 577717
 *		for Pentium 4 processors. "evntsel" is put in the counter's
Packit 577717
 *		CCCR register, and "escr" is put in the associated ESCR
Packit 577717
 *		register.
Packit 577717
 *
Packit 577717
 *		"@pmc" describes which CPU counter number to assign this
Packit 577717
 *		event to. When omitted, the events are assigned in the
Packit 577717
 *		order listed, starting from 0. Either all or none of the
Packit 577717
 *		event specifiers should use the "@pmc" notation.
Packit 577717
 *		Explicit counter assignment via "@pmc" is required on
Packit 577717
 *		Pentium 4 and VIA C3 processors.
Packit 577717
 *
Packit 577717
 *		The counts, together with an event description are written
Packit 577717
 *		to the result file (default is stderr).
Packit 577717
 *
Packit 577717
 *	--p4pe=value | --p4_pebs_enable=value
Packit 577717
 *	--p4pmv=value | --p4_pebs_matrix_vert=value
Packit 577717
 *		Specify the value to be stored in the auxiliary control
Packit 577717
 *		register PEBS_ENABLE or PEBS_MATRIX_VERT, which are used
Packit 577717
 *		for replay tagging events on Pentium 4 processors.
Packit 577717
 *		Note: Intel's documentation states that bit 25 should be
Packit 577717
 *		set in PEBS_ENABLE, but this is not true and the driver
Packit 577717
 *		will disallow it.
Packit 577717
 *
Packit 577717
 *	-i | --info
Packit 577717
 *		Instead of running a command, generate output which
Packit 577717
 *		identifies the current processor and its capabilities.
Packit 577717
 *
Packit 577717
 *	-l | --list
Packit 577717
 *		Instead of running a command, generate output which
Packit 577717
 *		identifies the current processor and its capabilities,
Packit 577717
 *		and lists its countable events.
Packit 577717
 *
Packit 577717
 *	-L | --long-list
Packit 577717
 *		Like -l, but list the events in a more detailed format.
Packit 577717
 *
Packit 577717
 *	-o file | --output=file
Packit 577717
 *		Write the results to file instead of stderr.
Packit 577717
 *
Packit 577717
 * EXAMPLES
Packit 577717
 *	The following commands count the number of retired instructions
Packit 577717
 *	in user-mode on an Intel P6 processor:
Packit 577717
 *
Packit 577717
 *	perfex -e 0x004100C0 some_program
Packit 577717
 *	perfex --event=0x004100C0 some_program
Packit 577717
 *
Packit 577717
 *	The following command does the same on an Intel Pentium 4 processor:
Packit 577717
 *
Packit 577717
 *	perfex -e 0x00039000/0x04000204@0x8000000C some_program
Packit 577717
 *
Packit 577717
 *	Explanation: Program IQ_CCCR0 with required flags, ESCR select 4
Packit 577717
 *	(== CRU_ESCR0), and Enable. Program CRU_ESCR0 with event 2
Packit 577717
 *	(instr_retired), NBOGUSNTAG, CPL>0. Map this event to IQ_COUNTER0
Packit 577717
 *	(0xC) with fast RDPMC enabled.
Packit 577717
 *
Packit 577717
 *	The following command counts the number of L1 cache read misses
Packit 577717
 *	on a Pentium 4 processor:
Packit 577717
 *
Packit 577717
 *	perfex -e 0x0003B000/0x12000204@0x8000000C --p4pe=0x01000001 --p4pmv=0x1 some_program
Packit 577717
 *
Packit 577717
 *	Explanation: IQ_CCCR0 is bound to CRU_ESCR2, CRU_ESCR2 is set up
Packit 577717
 *	for replay_event with non-bogus uops and CPL>0, and PEBS_ENABLE
Packit 577717
 *	and PEBS_MATRIX_VERT are set up for the 1stL_cache_load_miss_retired
Packit 577717
 *	metric. Note that bit 25 is NOT set in PEBS_ENABLE.
Packit 577717
 *
Packit 577717
 * DEPENDENCIES
Packit 577717
 *	perfex only works on Linux systems which have been modified
Packit 577717
 *	to include the perfctr kernel extension. Perfctr is available at
Packit 577717
 *	http://www.csd.uu.se/~mikpe/linux/perfctr/.
Packit 577717
 *
Packit 577717
 * NOTES
Packit 577717
 *	perfex is superficially similar to IRIX' perfex(1).
Packit 577717
 *	The -a, -mp, -s, and -x options are not yet implemented.
Packit 577717
 *
Packit 577717
 * Copyright (C) 1999-2004  Mikael Pettersson
Packit 577717
 */
Packit 577717
Packit 577717
/*
Packit 577717
 * Theory of operation:
Packit 577717
 * - Parent creates a socketpair().
Packit 577717
 * - Parent forks.
Packit 577717
 * - Child creates and sets up its perfctrs.
Packit 577717
 * - Child sends its perfctr fd to parent via the socketpair().
Packit 577717
 * - Child exec:s the command.
Packit 577717
 * - Parent waits for child to exit.
Packit 577717
 * - Parent receives child's perfctr fd via the socketpair().
Packit 577717
 * - Parent retrieves child's final control and counts via the fd.
Packit 577717
 */
Packit 577717
Packit 577717
#include <sys/socket.h>
Packit 577717
#include <sys/uio.h>
Packit 577717
#include <sys/wait.h>
Packit 577717
#include <errno.h>
Packit 577717
#include <getopt.h>
Packit 577717
#include <stddef.h>	/* for offsetof() */
Packit 577717
#include <stdio.h>
Packit 577717
#include <stdlib.h>
Packit 577717
#include <string.h>	/* for strerror() */
Packit 577717
#include <unistd.h>
Packit 577717
#include "libperfctr.h"
Packit 577717
#include "arch.h"
Packit 577717
Packit 577717
/*
Packit 577717
 * Our child-to-parent protocol is the following:
Packit 577717
 * There is an int-sized data packet, with an optional 'struct cmsg_fd'
Packit 577717
 * control message attached.
Packit 577717
 * The data packet (which must be present, as control messages don't
Packit 577717
 * work with zero-sized payloads) contains an 'int' status.
Packit 577717
 * If status != 0, then it is an 'errno' value from the child's
Packit 577717
 * perfctr setup code.
Packit 577717
 */
Packit 577717
Packit 577717
struct cmsg_fd {
Packit 577717
    struct cmsghdr hdr;
Packit 577717
    int fd;
Packit 577717
    /* 64-bit machines pad here, which causes problems since
Packit 577717
       the kernel derives the number of fds from the size.
Packit 577717
       The CMSG_FD_TRUE_SIZE macro gives the true payload size. */
Packit 577717
};
Packit 577717
#define CMSG_FD_TRUE_SIZE	(offsetof(struct cmsg_fd, fd) + sizeof(int))
Packit 577717
#define CMSG_FD_PADDED_SIZE	sizeof(struct cmsg_fd)
Packit 577717
Packit 577717
static int my_send(int sock, int fd, int status)
Packit 577717
{
Packit 577717
    struct msghdr msg;
Packit 577717
    struct iovec iov;
Packit 577717
    struct cmsg_fd cmsg_fd;
Packit 577717
    int buf[1];
Packit 577717
Packit 577717
    msg.msg_name = NULL;
Packit 577717
    msg.msg_namelen = 0;
Packit 577717
    msg.msg_flags = 0;
Packit 577717
Packit 577717
    buf[0] = status;
Packit 577717
    iov.iov_base = buf;
Packit 577717
    iov.iov_len = sizeof buf;
Packit 577717
    msg.msg_iov = &iov;
Packit 577717
    msg.msg_iovlen = 1;
Packit 577717
Packit 577717
    if( status != 0 ) {	/* errno, don't send fd */
Packit 577717
	msg.msg_control = 0;
Packit 577717
	msg.msg_controllen = 0;
Packit 577717
    } else {
Packit 577717
	cmsg_fd.hdr.cmsg_len = CMSG_FD_TRUE_SIZE;
Packit 577717
	cmsg_fd.hdr.cmsg_level = SOL_SOCKET;
Packit 577717
	cmsg_fd.hdr.cmsg_type = SCM_RIGHTS;
Packit 577717
	cmsg_fd.fd = fd;
Packit 577717
	msg.msg_control = &cmsg_fd;
Packit 577717
	msg.msg_controllen = CMSG_FD_TRUE_SIZE;
Packit 577717
    }
Packit 577717
    return sendmsg(sock, &msg, 0) == sizeof buf ? 0 : -1;
Packit 577717
}
Packit 577717
Packit 577717
static int my_send_fd(int sock, int fd)
Packit 577717
{
Packit 577717
    return my_send(sock, fd, 0);
Packit 577717
}
Packit 577717
Packit 577717
static int my_send_err(int sock)
Packit 577717
{
Packit 577717
    return my_send(sock, -1, errno);
Packit 577717
}
Packit 577717
Packit 577717
static int my_receive(int sock, int *fd)
Packit 577717
{
Packit 577717
    struct msghdr msg;
Packit 577717
    struct iovec iov;
Packit 577717
    struct cmsg_fd cmsg_fd;
Packit 577717
    int buf[1];
Packit 577717
Packit 577717
    msg.msg_name = NULL;
Packit 577717
    msg.msg_namelen = 0;
Packit 577717
    msg.msg_flags = 0;
Packit 577717
Packit 577717
    buf[0] = -1;
Packit 577717
    iov.iov_base = buf;
Packit 577717
    iov.iov_len = sizeof(buf);
Packit 577717
    msg.msg_iov = &iov;
Packit 577717
    msg.msg_iovlen = 1;
Packit 577717
Packit 577717
    memset(&cmsg_fd, ~0, sizeof cmsg_fd);
Packit 577717
    msg.msg_control = &cmsg_fd;
Packit 577717
    msg.msg_controllen = CMSG_FD_TRUE_SIZE;
Packit 577717
Packit 577717
    if( recvmsg(sock, &msg, 0) != sizeof buf )
Packit 577717
	return -1;
Packit 577717
Packit 577717
    if( buf[0] == 0 &&
Packit 577717
	msg.msg_control == &cmsg_fd &&
Packit 577717
	msg.msg_controllen == CMSG_FD_PADDED_SIZE &&
Packit 577717
	cmsg_fd.hdr.cmsg_type == SCM_RIGHTS &&
Packit 577717
	cmsg_fd.hdr.cmsg_level == SOL_SOCKET &&
Packit 577717
	cmsg_fd.hdr.cmsg_len == CMSG_FD_TRUE_SIZE &&
Packit 577717
	cmsg_fd.fd >= 0 ) {
Packit 577717
	*fd = cmsg_fd.fd;
Packit 577717
	return 0;
Packit 577717
    }
Packit 577717
Packit 577717
    if( msg.msg_controllen == 0 && buf[0] != 0 )
Packit 577717
	errno = buf[0];
Packit 577717
    else
Packit 577717
	errno = EPROTO;
Packit 577717
    return -1;
Packit 577717
}
Packit 577717
Packit 577717
static int do_open_self(int creat)
Packit 577717
{
Packit 577717
    int fd;
Packit 577717
Packit 577717
    fd = _vperfctr_open(creat);
Packit 577717
    if( fd >= 0 && perfctr_abi_check_fd(fd) < 0 ) {
Packit 577717
	close(fd);
Packit 577717
	return -1;
Packit 577717
    }
Packit 577717
    return fd;
Packit 577717
}
Packit 577717
Packit 577717
static int do_child(int sock, const struct vperfctr_control *control, char **argv)
Packit 577717
{
Packit 577717
    int fd;
Packit 577717
Packit 577717
    fd = do_open_self(1);
Packit 577717
    if( fd < 0 ) {
Packit 577717
	my_send_err(sock);
Packit 577717
	return 1;
Packit 577717
    }
Packit 577717
    if( _vperfctr_control(fd, control) < 0 ) {
Packit 577717
	my_send_err(sock);
Packit 577717
	return 1;
Packit 577717
    }
Packit 577717
    if( my_send_fd(sock, fd) < 0 ) {
Packit 577717
	my_send_err(sock);	/* well, we can try.. */
Packit 577717
	return 1;
Packit 577717
    }
Packit 577717
    close(fd);
Packit 577717
    close(sock);
Packit 577717
    execvp(argv[0], argv);
Packit 577717
    perror(argv[0]);
Packit 577717
    return 1;
Packit 577717
}
Packit 577717
Packit 577717
static int do_parent(int sock, int child_pid, FILE *resfile)
Packit 577717
{
Packit 577717
    int child_status;
Packit 577717
    int fd;
Packit 577717
    struct perfctr_sum_ctrs sum;
Packit 577717
    struct vperfctr_control control;
Packit 577717
    struct perfctr_sum_ctrs children;
Packit 577717
Packit 577717
    /* this can be done before or after the recvmsg() */
Packit 577717
    if( waitpid(child_pid, &child_status, 0) < 0 ) {
Packit 577717
	perror("perfex: waitpid");
Packit 577717
	return 1;
Packit 577717
    }
Packit 577717
    if( !WIFEXITED(child_status) ) {
Packit 577717
	fprintf(stderr, "perfex: child did not exit normally\n");
Packit 577717
	return 1;
Packit 577717
    }
Packit 577717
    if( my_receive(sock, &fd) < 0 ) {
Packit 577717
	perror("perfex: receiving fd/status");
Packit 577717
	return 1;
Packit 577717
    }
Packit 577717
    close(sock);
Packit 577717
    /* XXX: surely we don't need to repeat the ABI check here? */
Packit 577717
    if( _vperfctr_read_sum(fd, &sum) < 0 ) {
Packit 577717
	perror("perfex: read_sum");
Packit 577717
	return 1;
Packit 577717
    }
Packit 577717
    if( _vperfctr_read_control(fd, &control) < 0 ) {
Packit 577717
	perror("perfex: read_control");
Packit 577717
	return 1;
Packit 577717
    }
Packit 577717
    if( _vperfctr_read_children(fd, &children) < 0 ) {
Packit 577717
	perror("perfex: read_children");
Packit 577717
	return 1;
Packit 577717
    }
Packit 577717
    close(fd);
Packit 577717
Packit 577717
    do_print(resfile, &control.cpu_control, &sum, &children);
Packit 577717
Packit 577717
    return WEXITSTATUS(child_status);
Packit 577717
}
Packit 577717
Packit 577717
static int do_perfex(const struct vperfctr_control *control, char **argv, FILE *resfile)
Packit 577717
{
Packit 577717
    int pid;
Packit 577717
    int sv[2];
Packit 577717
Packit 577717
    if( socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) < 0 ) {
Packit 577717
	perror("perfex: socketpair");
Packit 577717
	return 1;
Packit 577717
    }
Packit 577717
    pid = fork();
Packit 577717
    if( pid < 0 ) {
Packit 577717
	perror("perfex: fork");
Packit 577717
	return 1;
Packit 577717
    }
Packit 577717
    if( pid == 0 ) {
Packit 577717
	close(sv[0]);
Packit 577717
	return do_child(sv[1], control, argv);
Packit 577717
    } else {
Packit 577717
	close(sv[1]);
Packit 577717
	return do_parent(sv[0], pid, resfile);
Packit 577717
    }
Packit 577717
}
Packit 577717
Packit 577717
static int get_info(struct perfctr_info *info)
Packit 577717
{
Packit 577717
    int fd;
Packit 577717
Packit 577717
    fd = do_open_self(0);
Packit 577717
    if( fd < 0 ) {
Packit 577717
	perror("perfex: open perfctrs");
Packit 577717
	return -1;
Packit 577717
    }
Packit 577717
    if( perfctr_info(fd, info) < 0 ) {
Packit 577717
	perror("perfex: perfctr_info");
Packit 577717
	close(fd);
Packit 577717
	return -1;
Packit 577717
    }
Packit 577717
    close(fd);
Packit 577717
    return 0;
Packit 577717
}
Packit 577717
Packit 577717
static struct perfctr_cpus_info *get_cpus_info(void)
Packit 577717
{
Packit 577717
    int fd;
Packit 577717
    struct perfctr_cpus_info *cpus_info;
Packit 577717
Packit 577717
    fd = do_open_self(0);
Packit 577717
    if( fd < 0 ) {
Packit 577717
	perror("perfex: open perfctrs");
Packit 577717
	return NULL;
Packit 577717
    }
Packit 577717
    cpus_info = perfctr_cpus_info(fd);
Packit 577717
    if( !cpus_info )
Packit 577717
	perror("perfex: perfctr_cpus_info");
Packit 577717
    close(fd);
Packit 577717
    return cpus_info;
Packit 577717
}
Packit 577717
Packit 577717
static int do_info(const struct perfctr_info *info)
Packit 577717
{
Packit 577717
    struct perfctr_cpus_info *cpus_info;
Packit 577717
Packit 577717
    cpus_info = get_cpus_info();
Packit 577717
    printf("PerfCtr Info:\n");
Packit 577717
    perfctr_info_print(info);
Packit 577717
    if( cpus_info ) {
Packit 577717
	perfctr_cpus_info_print(cpus_info);
Packit 577717
	free(cpus_info);
Packit 577717
    }
Packit 577717
    return 0;
Packit 577717
}
Packit 577717
Packit 577717
static void do_print_event(const struct perfctr_event *event, int long_format,
Packit 577717
			   const char *event_prefix)
Packit 577717
{
Packit 577717
    printf("%s%s", event_prefix, event->name);
Packit 577717
    if( long_format )
Packit 577717
	printf(":0x%02X:0x%X:0x%X",
Packit 577717
	       event->evntsel,
Packit 577717
	       event->counters_set,
Packit 577717
	       event->unit_mask ? event->unit_mask->default_value : 0);
Packit 577717
    printf("\n");
Packit 577717
}
Packit 577717
Packit 577717
static void do_print_event_set(const struct perfctr_event_set *event_set,
Packit 577717
			       int long_format)
Packit 577717
{
Packit 577717
    unsigned int i;
Packit 577717
Packit 577717
    if( event_set->include )
Packit 577717
	do_print_event_set(event_set->include, long_format);
Packit 577717
    for(i = 0; i < event_set->nevents; ++i)
Packit 577717
	do_print_event(&event_set->events[i], long_format, event_set->event_prefix);
Packit 577717
}
Packit 577717
Packit 577717
static int do_list(const struct perfctr_info *info, int long_format)
Packit 577717
{
Packit 577717
    const struct perfctr_event_set *event_set;
Packit 577717
    unsigned int nrctrs;
Packit 577717
Packit 577717
    printf("CPU type %s\n", perfctr_info_cpu_name(info));
Packit 577717
    printf("%s time-stamp counter available\n",
Packit 577717
	   (info->cpu_features & PERFCTR_FEATURE_RDTSC) ? "One" : "No");
Packit 577717
    nrctrs = perfctr_info_nrctrs(info);
Packit 577717
    printf("%u performance counter%s available\n",
Packit 577717
	   nrctrs, (nrctrs == 1) ? "" : "s");
Packit 577717
    printf("Overflow interrupts%s available\n",
Packit 577717
	   (info->cpu_features & PERFCTR_FEATURE_PCINT) ? "" : " not");
Packit 577717
Packit 577717
    event_set = perfctr_cpu_event_set(info->cpu_type);
Packit 577717
    if( !event_set ) {
Packit 577717
	fprintf(stderr, "perfex: perfctr_cpu_event_set(%u) failed\n",
Packit 577717
		info->cpu_type);
Packit 577717
	return 1;
Packit 577717
    }
Packit 577717
    if( !event_set->nevents ) /* the 'generic' CPU type */
Packit 577717
	return 0;
Packit 577717
    printf("\nEvents Available:\n");
Packit 577717
    if( long_format )
Packit 577717
	printf("Name:EvntSel:CounterSet:DefaultUnitMask\n");
Packit 577717
    do_print_event_set(event_set, long_format);
Packit 577717
    return 0;
Packit 577717
}
Packit 577717
Packit 577717
/* Hack while phasing out an old number parsing bug. */
Packit 577717
static unsigned int strtoul_base = 16;
Packit 577717
static unsigned int quiet;
Packit 577717
Packit 577717
unsigned long my_strtoul(const char *nptr, char **endptr)
Packit 577717
{
Packit 577717
    unsigned long val1;
Packit 577717
Packit 577717
    val1 = strtoul(nptr, endptr, strtoul_base);
Packit 577717
    if (strtoul_base == 16 && !quiet) {
Packit 577717
	unsigned long val2 = strtoul(nptr, NULL, 0);
Packit 577717
	if (val1 != val2)
Packit 577717
	    fprintf(stderr, "perfex: warning: string '%s' is base-dependent, assuming base 16."
Packit 577717
		    " Please prefix hexadecimal numbers with '0x'.\n",
Packit 577717
		    nptr);
Packit 577717
    }
Packit 577717
    return val1;
Packit 577717
}
Packit 577717
Packit 577717
static const struct option long_options[] = {
Packit 577717
    { "decimal", 0, NULL, 'd' },
Packit 577717
    { "event", 1, NULL, 'e' },
Packit 577717
    { "help", 0, NULL, 'h' },
Packit 577717
    { "hex", 0, NULL, 'x' },
Packit 577717
    { "info", 0, NULL, 'i' },
Packit 577717
    { "list", 0, NULL, 'l' },
Packit 577717
    { "long-list", 0, NULL, 'L' },
Packit 577717
    { "output", 1, NULL, 'o' },
Packit 577717
    ARCH_LONG_OPTIONS
Packit 577717
    { 0 }
Packit 577717
};
Packit 577717
Packit 577717
static void do_usage(void)
Packit 577717
{
Packit 577717
    fprintf(stderr, "Usage:  perfex [options] <command> [<command arg>] ...\n");
Packit 577717
    fprintf(stderr, "\tperfex -i\n");
Packit 577717
    fprintf(stderr, "\tperfex -h\n");
Packit 577717
    fprintf(stderr, "\n");
Packit 577717
    fprintf(stderr, "Options:\n");
Packit 577717
    fprintf(stderr, "\t-e <event> | --event=<event>\tEvent to be counted\n");
Packit 577717
    fprintf(stderr, "\t-h | --help\t\t\tPrint this help text\n");
Packit 577717
    fprintf(stderr, "\t-o <file> | --output=<file>\tWrite output to file (default is stderr)\n");
Packit 577717
    fprintf(stderr, "\t-i | --info\t\t\tPrint PerfCtr driver information\n");
Packit 577717
    fprintf(stderr, "\t-l | --list\t\t\tList available events\n");
Packit 577717
    fprintf(stderr, "\t-L | --long-list\t\tList available events in long format\n");
Packit 577717
    fprintf(stderr, "\t-d | --decimal\t\t\tAllow decimal numbers in event specifications\n");
Packit 577717
    fprintf(stderr, "\t-x | --hex\t\t\tOnly accept hexadecimal numbers in event specifications\n");
Packit 577717
    do_arch_usage();
Packit 577717
}
Packit 577717
Packit 577717
int main(int argc, char **argv)
Packit 577717
{
Packit 577717
    struct perfctr_info info;
Packit 577717
    struct vperfctr_control control;
Packit 577717
    int n;
Packit 577717
    FILE *resfile;
Packit 577717
Packit 577717
    /* prime info, as we'll need it in most cases */
Packit 577717
    if( get_info(&info) )
Packit 577717
	return 1;
Packit 577717
Packit 577717
    memset(&control, 0, sizeof control);
Packit 577717
    if( info.cpu_features & PERFCTR_FEATURE_RDTSC )
Packit 577717
	control.cpu_control.tsc_on = 1;
Packit 577717
    n = 0;
Packit 577717
    resfile = stderr;
Packit 577717
Packit 577717
    for(;;) {
Packit 577717
	/* the '+' is there to prevent permutation of argv[] */
Packit 577717
	int ch = getopt_long(argc, argv, "+de:hilLo:x", long_options, NULL);
Packit 577717
	switch( ch ) {
Packit 577717
	  case -1:	/* no more options */
Packit 577717
	    if( optind >= argc ) {
Packit 577717
		fprintf(stderr, "perfex: command missing\n");
Packit 577717
		return 1;
Packit 577717
	    }
Packit 577717
	    argv += optind;
Packit 577717
	    break;
Packit 577717
	  case 'h':
Packit 577717
	    do_usage();
Packit 577717
	    return 0;
Packit 577717
	  case 'i':
Packit 577717
	    return do_info(&info;;
Packit 577717
	  case 'l':
Packit 577717
	    return do_list(&info, 0);
Packit 577717
	  case 'L':
Packit 577717
	    return do_list(&info, 1);
Packit 577717
	  case 'o':
Packit 577717
	    if( (resfile = fopen(optarg, "w")) == NULL ) {
Packit 577717
		fprintf(stderr, "perfex: %s: %s\n", optarg, strerror(errno));
Packit 577717
		return 1;
Packit 577717
	    }
Packit 577717
	    continue;
Packit 577717
	  case 'd':
Packit 577717
	    strtoul_base = 0;
Packit 577717
	    continue;
Packit 577717
	  case 'x':
Packit 577717
	    strtoul_base = 16;
Packit 577717
	    quiet = 1;
Packit 577717
	    continue;
Packit 577717
	  case 'e':
Packit 577717
	    n = do_event_spec(n, optarg, &control.cpu_control);
Packit 577717
	    continue;
Packit 577717
	  default:
Packit 577717
	    if( do_arch_option(ch, optarg, &control.cpu_control) < 0 ) {
Packit 577717
		do_usage();
Packit 577717
		return 1;
Packit 577717
	    }
Packit 577717
	    continue;
Packit 577717
	}
Packit 577717
	break;
Packit 577717
    }
Packit 577717
Packit 577717
    return do_perfex(&control, argv, resfile);
Packit 577717
}