Hi Stephane, I've gone ahead and coded some of the APIs we've been discussing. There are 5 new external APIs: pfm_find_event_mask() pfm_get_max_event_mask_name_len() pfm_get_num_event_masks() pfm_get_event_mask_name() pfm_get_event_mask_description()
and 3 new arch-module APIs (in pfm_pmu_support_t): get_event_mask_name() get_num_event_masks() get_event_mask_desc() The pfmlib_event_t structure gets an array of unit-mask identifiers and a count of unit-masks. Both of these new fields could be changed from unsigned int to unsigned short or unsigned char if we'd like to reduce the memory usage. I also made some additions to pfm_print_event_info() and pfm_print_event_info_byindex() to output info about the unit-masks. Here's my current patch against the libpfm CVS tree. Let me know what you think. I have not yet added the unit-mask code to the pentium4 module I'm working on, so this new code is untested right now. But it does compile - so it must work. :) Thanks, -- Kevin Corry [EMAIL PROTECTED] http://www.ibm.com/linux/ http://evms.sourceforge.net/ Add unit-mask APIs to libpfm. Signed-Off-By: Kevin Corry <[EMAIL PROTECTED]> Index: include/perfmon/pfmlib.h =================================================================== RCS file: /cvsroot/perfmon2/libpfm/include/perfmon/pfmlib.h,v retrieving revision 1.3 diff -u -r1.3 pfmlib.h --- include/perfmon/pfmlib.h 15 May 2006 13:57:01 -0000 1.3 +++ include/perfmon/pfmlib.h 9 Jun 2006 19:34:40 -0000 @@ -79,6 +79,8 @@ unsigned int event; /* event descriptor */ unsigned int plm; /* event privilege level mask */ unsigned long flags; /* per-event flag */ + unsigned int unit_masks[32]; /* unit-mask identifiers */ + unsigned int num_masks; /* number of masks specified in 'unit_masks' */ unsigned long reserved[2]; /* for future use */ } pfmlib_event_t; @@ -164,14 +166,19 @@ extern int pfm_find_event_byname(const char *name, unsigned int *idx); extern int pfm_find_event_bycode(int code, unsigned int *idx); extern int pfm_find_event_bycode_next(int code, unsigned int start, unsigned int *next); +extern int pfm_find_event_mask(unsigned int event_idx, const char *str, unsigned int *mask_idx); extern int pfm_get_max_event_name_len(size_t *len); +extern int pfm_get_max_event_mask_name_len(unsigned int event_idx, size_t *len); extern int pfm_get_num_events(unsigned int *count); +extern int pfm_get_num_event_masks(unsigned int event_idx, unsigned int *count); extern int pfm_get_event_name(unsigned int idx, char *name, size_t maxlen); extern int pfm_get_event_code(unsigned int idx, int *code); extern int pfm_get_event_counters(unsigned int idx, pfmlib_regmask_t *counters); extern int pfm_get_event_description(unsigned int idx, char **str); extern int pfm_get_event_code_counter(unsigned int idx, unsigned int cnt, int *code); +extern int pfm_get_event_mask_name(unsigned int event_idx, unsigned int mask_idx, char *name, size_t maxlen); +extern int pfm_get_event_mask_description(unsigned int event_idx, unsigned int mask_idx, char **desc); extern int pfm_print_event_info(const char *name, int (*pf)(const char *fmt,...)); extern int pfm_print_event_info_byindex(unsigned int idx, int (*pf)(const char *fmt,...)); Index: lib/pfmlib_common.c =================================================================== RCS file: /cvsroot/perfmon2/libpfm/lib/pfmlib_common.c,v retrieving revision 1.4 diff -u -r1.4 pfmlib_common.c --- lib/pfmlib_common.c 2 Jun 2006 12:55:01 -0000 1.4 +++ lib/pfmlib_common.c 9 Jun 2006 19:34:40 -0000 @@ -335,6 +335,29 @@ } int +pfm_find_event_mask(unsigned int event_idx, const char *str, unsigned int *mask_idx) +{ + unsigned int i, num_masks = 0; + + if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT; + + if (str == NULL || mask_idx == NULL) return PFMLIB_ERR_INVAL; + + if (pfm_current->get_num_event_masks && + pfm_current->get_event_mask_name) { + pfm_current->get_num_event_masks(event_idx, &num_masks); + for (i = 0; i < num_masks; i++) { + if (!strcasecmp(pfm_current->get_event_mask_name(event_idx, i), str)) { + *mask_idx = i; + return PFMLIB_SUCCESS; + } + } + } + + return PFMLIB_ERR_NOTFOUND; +} + +int pfm_get_event_name(unsigned int i, char *name, size_t maxlen) { if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT; @@ -381,6 +404,20 @@ return PFMLIB_SUCCESS; } +int +pfm_get_event_mask_name(unsigned int event_idx, unsigned int mask_idx, char *name, size_t maxlen) +{ + if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT; + + if (event_idx >= pfm_current->pme_count || name == NULL || maxlen < 1) return PFMLIB_ERR_INVAL; + + if (pfm_current->get_event_mask_name) { + strncpy(name, pfm_current->get_event_mask_name(event_idx, mask_idx), maxlen-1); + name[maxlen-1] = '\0'; + } + + return PFMLIB_SUCCESS; +} int pfm_get_num_events(unsigned int *count) @@ -394,6 +431,20 @@ return PFMLIB_SUCCESS; } +int +pfm_get_num_event_masks(unsigned int event_idx, unsigned int *count) +{ + if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT; + + if (event_idx >= pfm_current->pme_count || count == NULL) return PFMLIB_ERR_INVAL; + + if (pfm_current->get_num_event_masks == NULL) { + *count = 0; + return PFMLIB_SUCCESS; + } + + return pfm_current->get_num_event_masks(event_idx, count); +} /* * Function used to print information about a specific events. More than @@ -408,6 +459,7 @@ int code, ret, n; int event_is_digit = 0; unsigned int idx, next_idx, num_counters, i; + unsigned int num_masks; if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT; @@ -457,6 +509,15 @@ } (*pf)( "]\n"); + if (pfm_current->get_num_event_masks && + pfm_current->get_event_mask_name) { + pfm_current->get_num_event_masks(idx, &num_masks); + for (i = 0; i < num_masks; i++) { + (*pf)("Unit-mask %d: %s\n", + i, pfm_current->get_event_mask_name(idx, i)); + } + } + /* print PMU specific information */ if (pfm_current->print_info) { pfm_current->print_info(idx, pf); @@ -473,7 +534,7 @@ pfm_print_event_info_byindex(unsigned int v, int (*pf)(const char *fmt,...)) { pfmlib_regmask_t cmask, impl_counters; - unsigned int i, n; + unsigned int i, n, num_masks; int code; if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT; @@ -499,6 +560,15 @@ } (*pf)( "]\n"); + if (pfm_current->get_num_event_masks && + pfm_current->get_event_mask_name) { + pfm_current->get_num_event_masks(v, &num_masks); + for (i = 0; i < num_masks; i++) { + (*pf)("Unit-mask %d: %s\n", + v, pfm_current->get_event_mask_name(v, i)); + } + } + /* print PMU specific information */ if (pfm_current->print_info) { pfm_current->print_info(v, pf); @@ -721,6 +791,30 @@ return PFMLIB_SUCCESS; } +int +pfm_get_max_event_mask_name_len(unsigned int event_idx, size_t *len) +{ + unsigned int i, num_masks; + size_t l, max = 0; + + if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT; + + if (event_idx >= pfm_current->pme_count || len == NULL) return PFMLIB_ERR_INVAL; + + if (pfm_current->get_num_event_masks && + pfm_current->get_event_mask_name) { + pfm_current->get_num_event_masks(event_idx, &num_masks); + for (i = 0; i < num_masks; i++) { + l = strlen(pfm_current->get_event_mask_name(event_idx, i)); + if (l > max) max = l; + } + } + + *len = max; + + return PFMLIB_SUCCESS; +} + /* * return the index of the event that counts elapsed cycles */ @@ -768,3 +862,19 @@ } return pfm_current->get_event_desc(i, str); } + +int +pfm_get_event_mask_description(unsigned int event_idx, unsigned int mask_idx, char **desc) +{ + if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT; + + if (event_idx >= pfm_current->pme_count || desc == NULL) return PFMLIB_ERR_INVAL; + + if (pfm_current->get_event_mask_desc == NULL) { + *desc = NULL; + return PFMLIB_SUCCESS; + } + + return pfm_current->get_event_mask_desc(event_idx, mask_idx, desc); +} + Index: lib/pfmlib_priv.h =================================================================== RCS file: /cvsroot/perfmon2/libpfm/lib/pfmlib_priv.h,v retrieving revision 1.3 diff -u -r1.3 pfmlib_priv.h --- lib/pfmlib_priv.h 2 Jun 2006 12:55:01 -0000 1.3 +++ lib/pfmlib_priv.h 9 Jun 2006 19:34:40 -0000 @@ -41,7 +41,9 @@ unsigned int flags; int (*get_event_code)(unsigned int i, unsigned int cnt, int *code); char *(*get_event_name)(unsigned int i); + char *(*get_event_mask_name)(unsigned int event_idx, unsigned int mask_idx); void (*get_event_counters)(unsigned int i, pfmlib_regmask_t *counters); + int (*get_num_event_masks)(unsigned int event_idx, unsigned int *count); int (*print_info)(unsigned int v, int (*pf)(const char *fmt,...)); int (*dispatch_events)(pfmlib_input_param_t *p, void *model_in, pfmlib_output_param_t *q, void *model_out); int (*pmu_detect)(void); @@ -50,6 +52,7 @@ void (*get_impl_counters)(pfmlib_regmask_t *impl_counters); void (*get_hw_counter_width)(unsigned int *width); int (*get_event_desc)(unsigned int i, char **buf); + int (*get_event_mask_desc)(unsigned int event_idx, unsigned int mask_idx, char **buf); } pfm_pmu_support_t; #define PFMLIB_MULT_CODE_EVENT 0x1 /* more than one code per event (depending on counter) */ _______________________________________________ perfmon mailing list [email protected] http://www.hpl.hp.com/hosted/linux/mail-archives/perfmon/
