pfm_dispatch_events - setup PMC arguments
SYNOPSIS
#include <perfmon/pfmlib.h>
int pfm_dispatch_events(pfmlib_param_t *param);
DESCRIPTION
This function is the central piece of the library. It is
important to understand that the library does not effec
tively program the PMU, i.e., it does not make any kernel
perfmonctl() calls. The PMU is never actually accessed by
the library. Instead, the library helps applications pre
pare the arguments to pass to the kernel, in particular it
can setup the values to write into the PMC registers. The
application describes what it wants to measure in the
param argument of type pfmlib_param_t and the resulting
values for the PMC will be stored in a table in that
structure.
The typical sequence of calls first starts by initializing
the library, then each event to be monitored is searched
using variations of the pfm_find_event function. The
results are stored into the pfmlib_param_t structure.
Other adjustments are made in this structure. Then
pfm_dispatch_events is called. Upon successful return
from this function, the PMC registers can be programmed
using the PFM_WRITE_PMCS command using the values returned
by pfm_dispatch_events.
The pfmlib_param_t structure is defined as follows:
typedef struct
int event;
unsigned int plm;
} pfmlib_event_t;
typedef struct {
unsigned int pfp_event_count;
unsigned int pfp_pc_count;
unsigned int pfp_flags;
unsigned int pfp_dfl_plm;
pfmlib_event_t pfp_events[PMU_MAX_PMCS];
pfarg_reg_t pfp_pc[PMU_MAX_PMCS];
void *pfp_model;
} pfmlib_param_t;
The structure mostly contains two tables. The first one,
called pfp_events describes the events to be measured and
is given as input. The second table, called pfp_pc is used
to stores the values for each of the PMC involved in the
number of submitted events is indicated by
pfp_event_count, i.e., the number of valid entries in
pfp_events. The number of valid entries in pfp_pc is
stored in pfp_pc_count and is only valid upon successful
return from the call. Depending on the PMU implementation,
the number of PMC registers to program can be bigger than
the number of submitted events. The application must
never use pfp_event_count to represent the number of PMCS.
Each event, in a pfmlib_event_t, is represented by its
opaque descriptor, which must have been obtained with
pfm_find_event() or derivatives, and a privilege level
mask in plm. The plm field is a bitmask where each bit
indicates a set of privilege levels at which to monitor.
The IA-64 architecture support four different levels, 0
being the most privileged level used by the kernel and 3
being the least privileged level used by all applications.
It is possible to monitor at more than one level at a
time. The library defines a set of constant to designate
privilege levels:
PFM_PLM0
monitor at the kernel privilege level
PFM_PLM1
monitor at privilege level 1
PFM_PLM2
monitor at privilege level 2
PFM_PLM3
monitor at the user privilege level
To monitor at both level and kernel levels for the first
event, the application can simply use:
event[0].plm = PFM_PLM0|PFM_PLM3;
Events with a plm value of 0 will use the default privi
lege level mask as indicated by pfp_dfl_plm which must be
set to any combinations of values described above. It is
illegal to have a value of 0 for this field.
The IA-64 PMU supports two different types of performance
monitors: user and privileged monitors. They are not radi
cally different in nature but they are controlled using
two distinct mechanisms allowing concurrent use. The user
monitors are designed to monitor per process execution.
The privilege monitors are designed to monitor an entire
system , i.e., for a system wide monitoring session. The
kernel enforces this distinction and the library needs to
are programmed. For all system wide sessions, the user
must set the PFMLIB_PFP_SYSTEMWIDE in the pfp_flags field
to ensure proper programming of the PMC registers. When
this flag is not set, the library will assume the applica
tion is using user monitors for a per-process session.
The pfp_model field is pointing to an optional PMU model
specific extension to the pfmlib_param_r structure. Some
models support more advanced features than what is speci
fied in the architecture. The model specific module of
the library knows about those extensions and can program
additional PMC registers when necessary. Even though
existing PMU models do have extensions, applications are
not required to use them to setup interesting monitoring
sessions. This is typically true when an application only
does counting of events. If this field is NULL then the
model specific features will not be accessible to the
application. Information about model specific support for
this library is provided in separate man pages.
EXAMPLE
A typical sequence of operation to monitor CPU_CYCLES for
a per-process session is as follows:
#include <perfmon/pfmlib.h>
...
pfmlib_param_t param;
pfarg_context_t ctx[1];
pfarg_reg_t pd[1];
int ret;
if (pfm_initialize() != PFMLIB_SUCCESS) {
fprintf(stderr, "can't initialize library\n");
exit(1);
}
memset(¶m,0, sizeof(param));
memset(pd, 0, sizeof(pd));
ret = pfm_find_event("cpu_cycles", ¶m.pfp_events[0].event);
if (ret != PFMLIB_SUCCESS) {
fprintf(stderr, "cannot find cpu_cycles event\n");
exit(1);
}
param.pfp_dfl_plm = PFM_PLM3;
param.pfp_event_count = 1;
ret = pfm_dispatch_events(¶m);
if (ret != PFMLIB_SUCCESS) {
fprintf(stderr, "cannot dispatch: %s\n", pfm_strerror(ret));
exit(1);
}
/* match the PMD register with the PMC controlling it (for counters) */
pd[0].reg_num = evt.pfp_pc[0].reg_num;
...
...
}
if (perfmonctl(getpid(), PFM_ENABLE, NULL, 0) == -1) {
...
}
if (perfmonctl(getpid(), PFM_WRITE_PMCS, evt.pfp_pc, evt.pfp_pc_count) == -1) {
...
}
if (perfmonctl(getpid(), PFM_WRITE_PMDS, pd, evt.pfp_event_count) == -1) {
...
}
pfm_start();
/* code to monitor */
pfm_stop();
if (perfmonctl(getpid(), PFM_READ_PMDS, pd, evt.pfp_event_count) == -1) {
...
}
printf("results: %lu0, pd[0].reg_value);
...
RETURN
The function returns whether or not the call was success
ful. A return value of PFMLIB_SUCCESS indicates sucess,
otherwise the value is the error code.
ERRORS
PFMLIB_ERR_NOINIT The library has not been initialized
properly.
PFMLIB_ERR_INVAL
Some arguments were invalid. For instance the value
of *count is zero. This can also be due to he con
tent of the pfmlib_param_t structure.
PFMLIB_ERR_NOTFOUND
No matching event was found.
PFMLIB_ERR_TOOMANY
The number of events to monitor exceed the number
of implemented counters.
PFMLIB_ERR_NOASSIGN
The events cannot be dispatched to the PMC because
events have conflicting constraints.
PFMLIB_ERR_MAGIC
The model specific extension does not have the
right magic number.
The set of events and features cannot be combined.
PFMLIB_ERR_EVTMANY
An event has been supplied more than once and is
causing resource (PMC) conflicts.
PFMLIB_ERR_IRRINVAL
Invalid code range restriction (Itanium, Itanium
2).
PFMLIB_ERR_IRRALIGN
Code range has invalid alignment (Itanium, Itanium
2).
PFMLIB_ERR_IRRTOOMANY
Cannot satisfy all the code ranges (Itanium, Ita
nium 2).
PFMLIB_ERR_DRRTOOMANY
Cannot satisfy all the data ranges (Itanium, Ita
nium 2).
PFMLIB_ERR_DRRINVAL
Invalid data range restriction (Itanium, Itanium
2).
PFMLIB_ERR_EVTSET
Some events belong to incompatible sets (Itanium
2).
PFMLIB_ERR_EVTINCOMP
Some events cannot be measured at the same time
(Itanium 2).
PFMLIB_ERR_IRRTOOBIG
Code range is too big (Itanium 2).
SEE ALSO
pfmlib_itanium(3), pfmlib_itanium2(3)
AUTHOR
Stephane Eranian <eranian@hpl.hp.com>
Man(1) output converted with
man2html