Jump to content United States-English
HP.com Home Products and Services Support and Drivers Solutions How to Buy
» Contact HP

hp.com home


libpfm-3.0 library code examples

» 

HP Labs

» Research
» News and events
» Technical reports
» About HP Labs
» Careers @ HP Labs
» People
» Worldwide sites
» Downloads
Content starts here

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 3.0 of the library which is not compatible with version 2.0. For version 2.0 examples, click here.

Here we present an example using an Itanium 2 specific feature, namely the opcode matcher PMC8. Statements higlighted in green show Itanium 2 specific code.


Example of a self-monitoring process using the opcode matcher PMC8 on Itanium 2

/*
 * we must include the perfmon, pfmlib, and Itanium2 specific header files
 */
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <perfmon/pfmlib.h>

#include <perfmon/perfmon.h>
#include <perfmon/pfmlib_itanium2.h>


#define MAX_EVT_NAME_LEN	256
#define NUM_PMCS PFMLIB_MAX_PMCS
#define NUM_PMDS PFMLIB_MAX_PMDS

int
main(int argc, char **argv)
{
  int i, ret, fd;
  pfmlib_input_param_t inp;
  pfmlib_output_param_t outp;
  pfmlib_ita2_input_param_t ita2_inp;
  pfarg_reg_t pc[NUM_PMCS];
  pfarg_reg_t pd[NUM_PMDS];
  pfarg_context_t ctx[1];
  pfarg_load_t load_args;
  char name[MAX_EVT_NAME_LEN];

  /*
   * 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(pc, 0, sizeof(pc));
  memset(ctx, 0, sizeof(ctx));
  memset(&inp,0, sizeof(inp));
  memset(&outp,0, sizeof(outp));
  memset(&load_args,0, sizeof(load_args));
  memset(&ita2_inp,0, sizeof(ita2_inp));

  /*
   * find event descriptor for our event
   */
  ret = pfm_find_event("IA64_TAGGED_INST_RETIRED_IBRP0_PMC8",
                       &inp.pfp_events[0].event);
  if (ret != PFMLIB_SUCCESS) {
     fprintf(stderr,"ia64_tagged_inst_retired not found\n");
     exit(1);
   }
  /*
   * indicate that we are using the PMC8 opcode matcher
   */
  ita2_inp.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_inp.pfp_ita2_pmc8.pmc_val = 0x1400028003fff1fa;

  /*
   * set the default privilege mode for all counters:
   *   PFM_PLM3 : user level only
   */
  inp.pfp_dfl_plm = PFM_PLM3; 

  /*
   * how many events we are interested in
   */
  inp.pfp_event_count = 1;

  /*
   * let the library figure out the values for the PMCS
   */
  ret = pfm_dispatch_events(&inp, &ita2_inp, &outp, NULL);
  if (ret != PFMLIB_SUCCESS) {
    fprintf(stderr, "cannot configure events: %s\n", 
            pfm_strerror(ret));
    exit(1);
  }
  /*
   * copy the library parameters to the OS-specific structures.
   * Here we propagate the PMC indexes and values.
   */
  for (i=0; i < outp.pfp_pmc_count; i++) {
    pc[i].reg_num   = outp.pfp_pmcs[i].reg_num;
    pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
  }
  /*
   * propagate the PMC indexes to the PMD arguments to the
   * kernel. This is required for counting monitors.
   */
  for (i=0; i < inp.pfp_event_count; i++) {
    pd[i].reg_num   = pc[i].reg_num;
  }
  /*
   * now create the context
   */
   ret = perfmonctl(0, PFM_CREATE_CONTEXT, ctx, 1);
  if (ret == -1) {
    fprintf(stderr, "PFM_CREATE_CONTEXT errno %d\n", errno);
    exit(1);
  }
  /*
   * extract the file descriptor identifying the context
   */
  fd = ctx[0].ctx_fd;

  /*
   * Now program the PMC registers.
   * In this case, we write two PMC registers
   */
   ret = perfmonctl(fd, PFM_WRITE_PMCS, pc, outp.pfp_pmc_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(fd, PFM_WRITE_PMDS, pd, inp.pfp_event_count);
  if (ret == -1) {
    fprintf(stderr, "PFM_WRITE_PMDS errno %d\n",errno);
    exit(1);
  }
  /*
   * attach the perfmon context to ourself
   */
   load_args.load_pid = getpid();
   ret = perfmonctl(fd, PFM_LOAD_CONTEXT, &load_args, 1);
  if (ret  == -1) {
    fprintf(stderr, "PFM_LOAD_CONTEXT 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_self_start(fd);

  /* 
   *
   * 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_self_stop(fd);

  /*
   * now read the results
   */
   ret = perfmonctl(fd, PFM_READ_PMDS, pd, inp.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 < inp.pfp_event_count; i++) {
    pfm_get_event_name(inp.pfp_events[i].event, name, MAX_EVT_NAME_LEN);
    printf("PMD%u %20lu %s\n", 
            pd[i].reg_num, 
            pd[i].reg_value, 
            name);
  }
  /*
   * destroy the perfmon context
   */
  close(fd);
  return 0;
}


perfmon project links

» project home
» perfmon overview
» libpfm overview
» pfmon overview
» mailing list
» downloads
» bibliography
» presentations

libpfm links

» FAQ
» examples
» man pages
Printable version
Privacy statement Using this site means you accept its terms Feedback to HP Labs
© 2009 Hewlett-Packard Development Company, L.P.