Corey,

Sorry for the delay, busy week.


I think this is getting quite complicated.

Let's go back to the problem we were trying to solve.

The idea is to have an API for tools to discover what are the
default settings for each possible event. Today, some attributes
may be omitted by users in which case the library may pick
some default or simply fail,e.g., unit masks.

It seems we would like to relax some of the constraints a little
bit. For instance, we would like the library to pick a default
unit mask for some events. I seem to recall Oprofile does that.

For other attributes such as modifiers (edge, invert, anythread,)
or priv level, we would like the library to pick some defaults as
well. Note that it already does that, all modifiers are 0, unless
hardcoded by the events or unit masks.

In either case, we need an API to query the defaults, such that
a tool could at least print the full event name string when it prints
the final count. That way, the user would know what was actually
measured. For instance, if I pass UOPS_ISSUED, it is interesting
to know that UOPS_ISSUED:ANY was actually measured.

There could be multiple default unit masks per event. For instance,
On Intel X86, certain events have unit masks "groups":

        { .name = "L2_LD",
          .code = 0x29,
          .flags = INTEL_X86_CSPEC|INTEL_X86_MESI,
          .cntmsk = 0x3,
         .modmsk = INTEL_V2_ATTRS,
          .desc =  "L2 cache reads",
          .umasks = {
                INTEL_CORE_MESI_UMASKS,
                INTEL_CORE_SPECIFICITY_UMASKS,
                INTEL_CORE_HW_PREFETCH_UMASKS
           },

Where:
#define INTEL_CORE_SPECIFICITY_UMASKS \
                { .uname = "SELF",\
                  .udesc = "This core",\
                  .ucode = 0x40\
                },\
                { .uname = "BOTH_CORES",\
                  .udesc = "Both cores",\
                  .ucode = 0xc0\
                }

#define INTEL_CORE_HW_PREFETCH_UMASKS \
                { .uname = "ANY",\
                  .udesc = "All inclusive",\
                  .ucode = 0x30\
                },\
                { .uname = "PREFETCH",\
                  .udesc = "Hardware prefetch only",\
                  .ucode = 0x10\
                }

In this particular case, a reasonable default would be

L2_LD:ANY:MESI:CORE_SELF:u=1:k=0:i=0:e=0:c=0

I think the only reasonable approach would be for the
tool to iterate over all the attributes and query 'default'
information. So here, it would return:

M: is_dfl=0
E: is_dfl=0
S: is_dfl=0
I: is_dfl=0
MESI: is_dfl=1 value=0xf (unit mask value)
CORE_BOTH: is_dfl=0
CORE_SELF: is_dfl=1
u: is_dfl=1 value=1
k: is_dfl=0
i: is_dfl=0
e: is_dfl=0
c: is_dfl=0

Now how do we go about implementing this?
I have avoided passing complex data structures to libpfm thus far.
The main reason is extensibility and simplicity. The downside
is you have lots of simple calls. We could continue down that
path and add a call just to return the default setting information.
Alternatively, we could go with what I proposed in an earlier
message, basically two calls, one for events, one for attributes
which cover all existing functionalities + the default settings.

If we go with a dedicated call, then we either have to pass
a struct and a pointer to a boolean (is_default) and a void *
to get the value out.

I have been toying with the structure approach using the following:
typedef struct {
        const char *name;
        const char *desc;
        pfm_pmu_t pmu;
        int idx;
        int nattrs;
        int size;
        uint64_t code;
        uint64_t reserved[9];
} pfm_event_info_t;

typedef struct {
        const char *name;
        const char *desc;
        pfm_attr_t type;
        struct {
                int is_dfl:1; /* is default */
                int reserved:31;
        };
        int idx;
        int size;
        uint64_t code;
        union {
                uint64_t dfl_val64;
                const char *dfl_str;
                int dfl_bool;
                int dfl_int;
        };
        uint64_t reserved1[6];
} pfm_event_attr_info_t;

int pfm_get_event_info(int idx, pfm_event_info_t *info, size_t sz);
int pfm_get_event_attr_info(int idx, int attr_idx,
pfm_event_attr_info_t *info, size_t sz);

Advantage is that this is clearly more compact, a couple of calls and you get
everything you need. The more I think about it, the more I think this could be
a workable solution. The type of values is already well covered. There are
reserved field for future extensions. The size parameter is to enable extensions
the way they do it with perf_events.

What do you think?

------------------------------------------------------------------------------
Join us December 9, 2009 for the Red Hat Virtual Experience,
a free event focused on virtualization and cloud computing. 
Attend in-depth sessions from your desk. Your couch. Anywhere.
http://p.sf.net/sfu/redhat-sfdev2dev
_______________________________________________
perfmon2-devel mailing list
perfmon2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perfmon2-devel

Reply via email to