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(&param,0, sizeof(param));
            memset(pd, 0, sizeof(pd));

            ret = pfm_find_event("cpu_cycles", &param.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(&param);
            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