Performance-Monitoring Counters Library, for Intel/AMD Processors and Linux
This example introduces
/dev/pmc -- device driver, a loadable kernel module
/proc/pmc -- which process has control of the counters?
pmc_open() -- take control of the performance-monitoring counters
pmc_close() -- relinquish control of the performance-monitoring counters
pmc_load, pmc_unload -- load and unload the module
Previous example -- hardware registers
Download this example
Next example -- pmc_data_t
Return to Main Menu
Compile with
gcc -o menu4 -O `pmc_options` menu4.c -lpmc
Try these examples:
menu4
cat /proc/pmc
menu4 3 & cat /proc/pmc
menu4 3 ; cat /proc/pmc
menu4 3 & menu4 3 & cat /proc/pmc
/sbin/lsmod
menu4 3 & /sbin/lsmod
rabbit -g 0 -S 0 rabbit -g 0 -S 1 date
rabbit -g 0 -S 1 rabbit -g 0 -S 0 date
#include <pmc_lib.h>
/* for sleep() */
#include <unistd.h>
/* for atoi() */
#include <stdlib.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); }
if (pmc_open(0) == FALSE) /* open /dev/pmc */
{ exit(1); }
sleep( (argc > 0) ? atoi(argv[0]) : 0 );
pmc_close(); /* close /dev/pmc */
exit(0);
}
Synopsis
/dev/pmc
/proc/pmc
int pmc_open(const int save);
void pmc_close(void);
The pseudo-device /dev/pmc is used to gain exclusive access to the
performance-monitoring counters, and to perform some privileged
kernel-mode operations, such as selecting the events to monitor.
It is not intended for direct use by application programs; pmc_open(),
pmc_select() and pmc_close() should be used instead. The commands
pmc_load and pmc_unload can be used to load and unload the module
from the kernel; you will probably need root permission to do this.
The remainder of this section provides some background information only.
/dev/pmc is a misc device (major number 10, minor number set by the
installation). You should see something like
% ls -l /dev/pmc
crw-rw-rw- 1 root root 10, 200 Dec 21 16:00 /dev/pmc
The device driver is a loadable module, so access to /dev/pmc is only
allowed if the module has been installed. This can be part of a boot
script. The valid operations on /dev/pmc are
open()
enable the cache (see below)
if /dev/pmc is already open by another process,
return with errno set to EBUSY
increment the use count (shown by /sbin/lsmod)
close()
enable the cache (see below)
SMP: did we change processors? (see below)
decrement the use count
read()
read selected control and model-specific registers
write()
write selected control and model-specific registers
lseek()
perform selected privileged operations
If -DPMC_ALLOW_CACHE_DISABLE was selected during the installation
procedure, then pmc_configure() is allowed to disable the cache.
This is not recommended.
The current implementations are for Linux 2.0.x and 2.2.x kernels.
It's not a bug, it's a feature:
If the /dev/pmc code dies inside the module, the device remains open,
though its owning process has been killed. No other process can then
open /dev/pmc, or force it to be closed. The only cure is to reboot.
If this happens to you, please send a description of what you were
trying to do, and we will attempt to fix the code. If you want to fix
it yourself, try again with -DPMC_UNLOCKED in the Makefile.
Since control over the event counters is not part of the process state,
this code is unsafe on a multiprocessor system. However, it can be used
with an SMP kernel on a single processor. The problem is that the
counters can be configured on one processor, but then the process can
be moved to another processor, leaving the counters behind. A small
change to the kernel's scheduler could fix this.
We have no provision for safe coexistence with kernel patches or other
loadable modules (such as /dev/msr) that manipulate the event counters.
The pseudo-file /proc/pmc exists whenever the /dev/pmc module
has been installed, if the compiler option -DPMC_PROC was selected as
part of the installation procedure. To see which process owns /dev/pmc,
if any, try 'cat /proc/pmc'.
pmc_open() will take the following actions:
1. attempt to open /dev/pmc
2. compare versions of the device driver and library
3. verify that this is an Intel or AMD processor with all the right
features
4. register pmc_close() with atexit()
5. save the PMC control registers for later restoration by pmc_close():
save == 0, clear the initial state
save != 0, save the initial state
both options affect later restoration by pmc_close()
6. read the Time Stamp Counter marking the start of the experiment;
this can be modified later by pmc_start()
7. return TRUE if the counters are now available
(/dev/pmc has been opened by this process, to the exclusion of other
processes)
8. return FALSE if
this is not an Intel or AMD processor with all the right features, or
/dev/pmc is not built for the same processor type, or
/dev/pmc is already in use or could not be opened, or
atexit() failed to register pmc_close()
A second call to pmc_open() following a successful call will simply return
TRUE. If pmc_open() fails, an explanation is written to stderr, or to the
errfile indicated by pmc_getargs().
pmc_close() will take the following actions:
1. restore the initial state of the PMC control registers, as saved by
pmc_open()
2. close /dev/pmc
A second call to pmc_close() following a successful call will do nothing.
The prototype of pmc_close() is determined by the requirements of atexit();
we would prefer greater freedom in this regard.
Forward References, Man Pages
pmc_start(), pmc_configure(), pmc_select()
atoi(3), sleep(3), atexit(3), errno(3), lsmod(1)
Performance-Monitoring Counters Library, for Intel/AMD Processors and Linux
Author: Don Heller, dheller@scl.ameslab.gov
Last revised: 2 August 2000