Here we present some simple examples of how to use the libpfm library. There is
also more complete set of examples included with the library
source code. The example on this page use version 2.0 of the library which is not
compatible with version 3.0. For version 3.0 examples, click here.
Example of a self-monitoring process using the opcode matcher PMC8 on Itanium 2
/*
* main libpfm include file
*/
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <perfmon/pfmlib.h>
#include <perfmon/pfmlib_itanium2.h>
int
main(int argc, char **argv)
{
char *name;
int i, ret;
pid_t mypid = getpid();
pfmlib_param_t evt;
pfmlib_ita2_param_t ita2_evt;
pfarg_reg_t pd[1];
pfarg_context_t ctx[1];
/*
* Initialize libpfm (required before we use it)
*/
if (pfm_initialize() != PFMLIB_SUCCESS) {
fprintf(stderr, "cannot initialize libpfm\n");
exit(1);
}
/*
* initialize local variables
*/
memset(pd, 0, sizeof(pd));
memset(ctx, 0, sizeof(ctx));
memset(&evt,0, sizeof(evt));
memset(&ita2_evt,0, sizeof(ita2_evt));
/*
* find event descriptor for our event
*/
ret = pfm_find_event("IA64_TAGGED_INST_RETIRED_IBRP0_PMC8",
&evt.pfp_events[0].event);
if (ret != PFMLIB_SUCCESS) {
fprintf(stderr,"ia64_tagged_inst_retired not found\n");
exit(1);
}
/*
* setup the magic number in the Itanium 2 specific
* structure (required, otherwise config will be ignored).
*/
ita2_evt.pfp_magic = PFMLIB_ITA2_PARAM_MAGIC;
/*
* link the model specific description to the
* generic description
*/
evt.pfp_model = &ita2_evt;
/*
* indicate that we are using the PMC8 opcode matcher
*/
ita2_evt.pfp_ita2_pmc8.opcm_used = 1;
/*
* load value to install in PMC8 (some control fields may be
* modified by library). Here it is the pattern for the
* br.cloop instruction.
*/
ita2_evt.pfp_ita2_pmc8.pmc_val = 0x1400028003fff1fa;
/*
* set the default privilege mode for all counters:
* PFM_PLM3 : user level only
*/
evt.pfp_dfl_plm = PFM_PLM3;
/*
* how many events we are interested in
*/
evt.pfp_event_count = 1;
/*
* let the library figure out the values for the PMCS
*/
ret = pfm_dispatch_events(&evt);
if (ret != PFMLIB_SUCCESS) {
fprintf(stderr, "cannot configure events: %s\n",
pfm_strerror(ret));
exit(1);
}
/*
* now create the context for self monitoring/per-task
*/
ret = perfmonctl(mypid, PFM_CREATE_CONTEXT, ctx, 1);
if (ret == -1) {
fprintf(stderr, "PFM_CREATE_CONTEXT errno %d\n", errno);
exit(1);
}
/*
* Initialize the PMU with safe values. psr.up is cleared.
*/
ret = perfmonctl(mypid, PFM_ENABLE, NULL, 0);
if (ret == -1) {
fprintf(stderr, "PFM_ENABLE errno %d\n",errno);
exit(1);
}
/*
* Now prepare the arguments to write the PMDs.
* counters are pair of PMC/PMD and they use the same
* index. We propagate the indexes used for the PMCs
* back to their equivalent PMDs.
*/
for (i=0; i < evt.pfp_event_count; i++) {
pd[i].reg_num = evt.pfp_pc[i].reg_num;
}
/*
* Now program the PMC registers.
* In this case, we write two PMC registers
*/
ret = perfmonctl(mypid, PFM_WRITE_PMCS, evt.pfp_pc, evt.pfp_pc_count);
if (ret == -1) {
fprintf(stderr, "PFM_WRITE_PMCS errno %d\n",errno);
exit(1);
}
/*
* We reset the PMDs that go with the PMCs
*/
ret = perfmonctl(mypid, PFM_WRITE_PMDS, pd, evt.pfp_event_count);
if (ret == -1) {
fprintf(stderr, "PFM_WRITE_PMDS errno %d\n",errno);
exit(1);
}
/*
* start monitoring. For self-monitoring tasks, it is possible to
* use the lightweight library call instead of PFM_START
*/
pfm_start();
/*
*
* code to monitor goes here
*
*/
/*
* stop monitoring. For self-monitoring tasks, it is possible to
* use the lightweight library call instead of PFM_STOP
*/
pfm_stop();
/*
* now read the results
*/
ret = perfmonctl(mypid, PFM_READ_PMDS, pd, evt.pfp_event_count);
if (ret == -1) {
fprintf(stderr, "PFM_READ_PMDS errno %d\n",errno);
exit(1);
}
/*
* and finally, print the results
*/
for (i=0; i < evt.pfp_event_count; i++) {
pfm_get_event_name(evt.pfp_events[i].event, &name);
printf("PMD%u %20lu %s\n",
pd[i].reg_num,
pd[i].reg_value,
name);
}
/*
* destroy the perfmon context
*/
ret = perfmonctl(mypid, PFM_DESTROY_CONTEXT, NULL, 0);
if (ret == -1) {
fprintf(stderr, "PFM_DESTROY errno %d\n",errno);
exit(1);
}
return 0;
}