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