Performance-Monitoring Counters Library, for Intel/AMD Processors and Linux
This example introduces
   pmc_getargs()  -- initialize data structures, read command-line arguments

Previous example       -- pmc_control_t
Download this example
Next example           -- pmc_event_set_t
Return to Main Menu


Compile with gcc -o menu2 -O `pmc_options` menu2.c -lpmc Try these examples: menu2 -h menu2 -p menu2 -v menu2 -g 0 -l -c -d menu2 -g 0 menu2 -g 0 -o foo -L bar menu2
#include <pmc_lib.h> int main(int argc, char * argv[]) { pmc_control_t Ctl = pmc_control_null; if (pmc_getargs(stderr, argv[0], &argc, &argv, &Ctl) == FALSE) { exit(1); } pmc_control_print(stdout, "initialized by pmc_getargs()", &Ctl); exit(0); }
Synopsis int pmc_getargs (FILE * errfile, const char * prog, int * argc, char ** argv[], pmc_control_t * ctl);
pmc_getargs() should be called before any other routine in the library. Its role is to initialize internal data structures and process command-line options. pmc_getargs() reads from the command line, and modifies argc, argv and Ctl to reflect the options it has taken. Note the extra level of indirection required with argc and argv, compared to the usual main() arguments. pmc_getargs() does not read the environment variables, or any command line argument past "--" or the first one that does not look like an option. Any values set in Ctl before calling pmc_getargs() are untouched before reading the command line. The options are taken strictly in order from the command line. errfile and prog are used throughout the library for error messages, -Verbose output, and the report by pmc_print_results(). If errfile is NULL, then stderr is assumed. prog identifies the controlling program in the error messages. If prog is NULL, then (*argv)[0] is used, if possible, otherwise a default name is used. argc and argv should be taken from the addresses of the usual main() arguments; *argc is decremented and *argv is incremented after the command-line options are scanned successfully. If argc or argv is NULL, it is as if *argc == 0, and all the defaults for rabbit are used. *ctl is updated from its initial value using argv and internal data structures. ctl should not be NULL. pmc_getargs() returns TRUE (1) or FALSE (0), according to success or failure, or may exit() if the command line options are faulty, or if they only request a listing of some kind. If changing main()'s arguments argc and argv offends your sensibilities, then use something like int Argc = argc; char * Argv[] = argv; char * program = argv[0]; if (pmc_getargs(stderr, program, &Argc, &Argv, &Ctl) == FALSE) { exit(1); }
The help option '-h' provides a summary of the available options, which vary according to the underlying processor. There are two classes of options used by pmc_getargs(). The "one-dash" class uses no additional option, or only one, while the "two-dash" class uses two (Intel) or four (AMD) additional options provided as a comma-separated string. Some variations are accepted, for example '-s=10' (same as '-s 10') or --e 121 (same as '--e 121,121'). The option letters used by pmc_getargs() are - C I L R S V a c d f g h i l m n o p r s t v w -- A E M P b c d e i m o u Any of the command line options -h -l -c -d -p -v -I -m 0 -a will cause pmc_getargs() to print to stdout and then exit(0). Some incorrect options or combinations of options will cause printing to errfile and then exit(1).
To use pmc_getargs() only to initialize Ctl and some internal data structures, Ctl = pmc_control_null; if (pmc_getargs(stderr, program, NULL, NULL, &Ctl) == FALSE) { exit(1); } Assigning the fields of Ctl directly requires knowledge of the processor that you might not want to install into the program. Some things should be left to the user through the command line or in a script. On a Pentium Pro, the code would look something like this: (we are not recommending that you copy this example) pmc_counter_t Ctr[2]; /* the second counter is not used here */ pmc_event_set_t Evnt[2]; /* event pairs */ Evnt[0][0] = DATA_MEM_REFS; /* Intel Pentium Pro, Pentium II/III */ Evnt[0][1] = BUS_TRAN_MEM; /* event codes */ Ctl.event[0] = Evnt[0][0]; Ctl.event[1] = Evnt[0][1]; /* count events (0) or clocks (1) */ Ctl.duration[0] = 0; Ctl.duration[1] = 0; /* enable (1) or disable(0) for CPL = 1,2,3 */ Ctl.user[0] = 1; Ctl.user[1] = 1; /* enable (1) or disable(0) for CPL = 0 */ Ctl.os[0] = 0; Ctl.os[1] = 0; /* for unit mask, L2 MESI protocol */ Ctl.mesi[0] = 0xf; Ctl.mesi[1] = 0xf; /* for unit mask, external bus logic */ Ctl.bus[0] = 0; Ctl.bus[1] = 0; /* counter mask, comparison invert flag */ Ctl.invt[0] = 0; Ctl.invt[1] = 0; /* counter mask */ Ctl.mask[0] = 0; Ctl.mask[1] = 0; /* pin control */ Ctl.pc[0] = Ctl.pc[1] = 0; /* APIC flag */ Ctl.apic[0] = Ctl.apic[1] = 0; /* enable */ Ctl.enable[0] = Ctl.enable[1] = 1; /* don't forget this! */ /* processor Mcycles per second */ Ctl.mhz = 200; /* samples per second */ Ctl.sample_rate = 0; /* samples per fflush() */ Ctl.flush_rate = 0; /* samples per rotation of events */ Ctl.rotate_rate = 0; /* number of event pairs */ Ctl.event_pairs = 1; /* event pairs */ Ctl.events = Evnt; /* event counters */ Ctl.counters = Ctr; /* flag from -input */ Ctl.file_input = FALSE; /* flag from -output */ Ctl.file_output = FALSE; strcpy(Ctl.input_file, "(unused)"); strcpy(Ctl.output_directory, "(unused)"); /* initialize the counter */ pmc_counter_init(&Ctr[0], &Ctl); Now the only question is, was some field overlooked? Probably yes. That's why you should use pmc_getargs().
Forward References, Man Pages pmc_event_set_t pmc_counter_t pmc_counter_init() pmc_print_results() strcpy(3)

Performance-Monitoring Counters Library, for Intel/AMD Processors and Linux
Author: Don Heller, dheller@scl.ameslab.gov
Last revised: 2 August 2000