|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* pfmlib_common.c: set of functions common to all PMU models
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (c) 2001-2006 Hewlett-Packard Development Company, L.P.
|
|
Packit |
577717 |
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
Packit |
577717 |
* of this software and associated documentation files (the "Software"), to deal
|
|
Packit |
577717 |
* in the Software without restriction, including without limitation the rights
|
|
Packit |
577717 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
Packit |
577717 |
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
Packit |
577717 |
* subject to the following conditions:
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* The above copyright notice and this permission notice shall be included in all
|
|
Packit |
577717 |
* copies or substantial portions of the Software.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
Packit |
577717 |
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
Packit |
577717 |
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
Packit |
577717 |
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
Packit |
577717 |
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
Packit |
577717 |
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#ifndef _GNU_SOURCE
|
|
Packit |
577717 |
#define _GNU_SOURCE /* for getline */
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#include <sys/types.h>
|
|
Packit |
577717 |
#include <ctype.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
#include <stdarg.h>
|
|
Packit |
577717 |
#include <limits.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include <perfmon/pfmlib.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include "pfmlib_priv.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static pfm_pmu_support_t *supported_pmus[]=
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_IA64
|
|
Packit |
577717 |
&montecito_support,
|
|
Packit |
577717 |
&itanium2_support,
|
|
Packit |
577717 |
&itanium_support,
|
|
Packit |
577717 |
&generic_ia64_support, /* must always be last for IA-64 */
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_X86_64
|
|
Packit |
577717 |
&amd64_support,
|
|
Packit |
577717 |
&pentium4_support,
|
|
Packit |
577717 |
&core_support,
|
|
Packit |
577717 |
&intel_atom_support,
|
|
Packit |
577717 |
&intel_nhm_support,
|
|
Packit |
577717 |
&intel_wsm_support,
|
|
Packit |
577717 |
&gen_ia32_support, /* must always be last for x86-64 */
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_I386
|
|
Packit |
577717 |
&i386_pii_support,
|
|
Packit |
577717 |
&i386_ppro_support,
|
|
Packit |
577717 |
&i386_p6_support,
|
|
Packit |
577717 |
&i386_pm_support,
|
|
Packit |
577717 |
&coreduo_support,
|
|
Packit |
577717 |
&amd64_support,
|
|
Packit |
577717 |
&pentium4_support,
|
|
Packit |
577717 |
&core_support,
|
|
Packit |
577717 |
&intel_atom_support,
|
|
Packit |
577717 |
&intel_nhm_support,
|
|
Packit |
577717 |
&intel_wsm_support,
|
|
Packit |
577717 |
&gen_ia32_support, /* must always be last for i386 */
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_MIPS64
|
|
Packit |
577717 |
&generic_mips64_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_SICORTEX
|
|
Packit |
577717 |
&sicortex_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_POWERPC
|
|
Packit |
577717 |
&gen_powerpc_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_SPARC
|
|
Packit |
577717 |
&sparc_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_CRAYX2
|
|
Packit |
577717 |
&crayx2_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_CELL
|
|
Packit |
577717 |
&cell_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
NULL
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* contains runtime configuration options for the library.
|
|
Packit |
577717 |
* mostly for debug purposes.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pfm_config_t pfm_config = {
|
|
Packit |
577717 |
.current = NULL
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int forced_pmu = PFMLIB_NO_PMU;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check environment variables for:
|
|
Packit |
577717 |
* LIBPFM_VERBOSE : enable verbose output (must be 1)
|
|
Packit |
577717 |
* LIBPFM_DEBUG : enable debug output (must be 1)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_check_debug_env(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
char *str;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
libpfm_fp = stderr;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
str = getenv("LIBPFM_VERBOSE");
|
|
Packit |
577717 |
if (str && *str >= '0' && *str <= '9') {
|
|
Packit |
577717 |
pfm_config.options.pfm_verbose = *str - '0';
|
|
Packit |
577717 |
pfm_config.options_env_set = 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
str = getenv("LIBPFM_DEBUG");
|
|
Packit |
577717 |
if (str && *str >= '0' && *str <= '9') {
|
|
Packit |
577717 |
pfm_config.options.pfm_debug = *str - '0';
|
|
Packit |
577717 |
pfm_config.options_env_set = 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
str = getenv("LIBPFM_DEBUG_STDOUT");
|
|
Packit |
577717 |
if (str)
|
|
Packit |
577717 |
libpfm_fp = stdout;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
str = getenv("LIBPFM_FORCE_PMU");
|
|
Packit |
577717 |
if (str)
|
|
Packit |
577717 |
forced_pmu = atoi(str);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_initialize(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_pmu_support_t **p = supported_pmus;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_check_debug_env();
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* syscall mapping, no failure on error
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pfm_init_syscalls();
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while(*p) {
|
|
Packit |
577717 |
DPRINT("trying %s\n", (*p)->pmu_name);
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check for forced_pmu
|
|
Packit |
577717 |
* pmu_type can never be zero
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if ((*p)->pmu_type == forced_pmu) {
|
|
Packit |
577717 |
__pfm_vbprintf("PMU forced to %s\n", (*p)->pmu_name);
|
|
Packit |
577717 |
goto found;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (forced_pmu == PFMLIB_NO_PMU && (*p)->pmu_detect() == PFMLIB_SUCCESS)
|
|
Packit |
577717 |
goto found;
|
|
Packit |
577717 |
p++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
found:
|
|
Packit |
577717 |
DPRINT("found %s\n", (*p)->pmu_name);
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* run a few sanity checks
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if ((*p)->pmc_count >= PFMLIB_MAX_PMCS)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((*p)->pmd_count >= PFMLIB_MAX_PMDS)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((*p)->pmu_init) {
|
|
Packit |
577717 |
ret = (*p)->pmu_init();
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_current = *p;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_set_options(pfmlib_options_t *opt)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (opt == NULL)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* environment variables override program presets
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (pfm_config.options_env_set == 0)
|
|
Packit |
577717 |
pfm_config.options = *opt;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* return the name corresponding to the pmu type. Only names
|
|
Packit |
577717 |
* of PMU actually compiled in the library will be returned.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_pmu_name_bytype(int type, char *name, size_t maxlen)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_pmu_support_t **p = supported_pmus;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (name == NULL || maxlen < 1) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while (*p) {
|
|
Packit |
577717 |
if ((*p)->pmu_type == type) goto found;
|
|
Packit |
577717 |
p++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
found:
|
|
Packit |
577717 |
strncpy(name, (*p)->pmu_name, maxlen-1);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* make sure the string is null terminated */
|
|
Packit |
577717 |
name[maxlen-1] = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_list_supported_pmus(int (*pf)(const char *fmt,...))
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_pmu_support_t **p;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pf == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
(*pf)("supported PMU models: ");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (p = supported_pmus; *p; p++) {
|
|
Packit |
577717 |
(*pf)("[%s] ", (*p)->pmu_name);;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
(*pf)("\ndetected host PMU: %s\n", pfm_current ? pfm_current->pmu_name : "not detected yet");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_pmu_name(char *name, int maxlen)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (name == NULL || maxlen < 1) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
strncpy(name, pfm_current->pmu_name, maxlen-1);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
name[maxlen-1] = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_pmu_type(int *type)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (type == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*type = pfm_current->pmu_type;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* boolean return value
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_is_pmu_supported(int type)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_pmu_support_t **p = supported_pmus;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while (*p) {
|
|
Packit |
577717 |
if ((*p)->pmu_type == type) return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
p++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_force_pmu(int type)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_pmu_support_t **p = supported_pmus;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while (*p) {
|
|
Packit |
577717 |
if ((*p)->pmu_type == type) goto found;
|
|
Packit |
577717 |
p++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
found:
|
|
Packit |
577717 |
pfm_current = *p;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_find_event_byname(const char *n, unsigned int *idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
char *p, *e;
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
size_t len;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (n == NULL || idx == NULL)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* this function ignores any ':' separator
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
p = strchr(n, ':');
|
|
Packit |
577717 |
if (!p)
|
|
Packit |
577717 |
len = strlen(n);
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
len = p - n;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we do case insensitive comparisons
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* event names must match completely
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(i=0; i < pfm_current->pme_count; i++) {
|
|
Packit |
577717 |
e = pfm_current->get_event_name(i);
|
|
Packit |
577717 |
if (!e)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
if (!strncasecmp(e, n, len)
|
|
Packit |
577717 |
&& len == strlen(e))
|
|
Packit |
577717 |
goto found;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTFOUND;
|
|
Packit |
577717 |
found:
|
|
Packit |
577717 |
*idx = i;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_find_event_bycode(int code, unsigned int *idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_regmask_t impl_cnt;
|
|
Packit |
577717 |
unsigned int i, j, num_cnt;
|
|
Packit |
577717 |
int code2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (idx == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_current->flags & PFMLIB_MULT_CODE_EVENT) {
|
|
Packit |
577717 |
pfm_current->get_impl_counters(&impl_cnt);
|
|
Packit |
577717 |
num_cnt = pfm_current->num_cnt;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < pfm_current->pme_count; i++) {
|
|
Packit |
577717 |
for(j=0; num_cnt; j++) {
|
|
Packit |
577717 |
if (pfm_regmask_isset(&impl_cnt, j)) {
|
|
Packit |
577717 |
pfm_current->get_event_code(i, j, &code2);
|
|
Packit |
577717 |
if (code2 == code)
|
|
Packit |
577717 |
goto found;
|
|
Packit |
577717 |
num_cnt--;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
for(i=0; i < pfm_current->pme_count; i++) {
|
|
Packit |
577717 |
pfm_current->get_event_code(i, PFMLIB_CNT_FIRST, &code2);
|
|
Packit |
577717 |
if (code2 == code) goto found;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTFOUND;
|
|
Packit |
577717 |
found:
|
|
Packit |
577717 |
*idx = i;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_find_event(const char *v, unsigned int *ev)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned long number;
|
|
Packit |
577717 |
char *endptr = NULL;
|
|
Packit |
577717 |
int ret = PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (v == NULL || ev == NULL)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (isdigit((int)*v)) {
|
|
Packit |
577717 |
number = strtoul(v,&endptr, 0);
|
|
Packit |
577717 |
/* check for errors */
|
|
Packit |
577717 |
if (*endptr!='\0')
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (number <= INT_MAX) {
|
|
Packit |
577717 |
int the_int_number = (int)number;
|
|
Packit |
577717 |
ret = pfm_find_event_bycode(the_int_number, ev);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else
|
|
Packit |
577717 |
ret = pfm_find_event_byname(v, ev);
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_find_event_bycode_next(int code, unsigned int i, unsigned int *next)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int code2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!next)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(++i; i < pfm_current->pme_count; i++) {
|
|
Packit |
577717 |
pfm_current->get_event_code(i, PFMLIB_CNT_FIRST, &code2);
|
|
Packit |
577717 |
if (code2 == code) goto found;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTFOUND;
|
|
Packit |
577717 |
found:
|
|
Packit |
577717 |
*next = i;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_do_find_event_mask(unsigned int ev, const char *str, unsigned int *mask_idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i, c, num_masks = 0;
|
|
Packit |
577717 |
unsigned long mask_val = -1;
|
|
Packit |
577717 |
char *endptr = NULL;
|
|
Packit |
577717 |
char *mask_name;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* empty mask name */
|
|
Packit |
577717 |
if (*str == '\0')
|
|
Packit |
577717 |
return PFMLIB_ERR_UMASK;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
num_masks = pfm_num_masks(ev);
|
|
Packit |
577717 |
for (i = 0; i < num_masks; i++) {
|
|
Packit |
577717 |
mask_name = pfm_current->get_event_mask_name(ev, i);
|
|
Packit |
577717 |
if (!mask_name)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
if (strcasecmp(mask_name, str))
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
*mask_idx = i;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/* don't give up yet; check for a exact numerical value */
|
|
Packit |
577717 |
mask_val = strtoul(str, &endptr, 0);
|
|
Packit |
577717 |
if (mask_val != ULONG_MAX && endptr && *endptr == '\0') {
|
|
Packit |
577717 |
for (i = 0; i < num_masks; i++) {
|
|
Packit |
577717 |
pfm_current->get_event_mask_code(ev, i, &c);
|
|
Packit |
577717 |
if (mask_val == c) {
|
|
Packit |
577717 |
*mask_idx = i;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_ERR_UMASK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_find_event_mask(unsigned int ev, const char *str, unsigned int *mask_idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (str == NULL || mask_idx == NULL || ev >= pfm_current->pme_count)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pfm_do_find_event_mask(ev, str, mask_idx);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check if unit mask is not already present
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
pfm_check_duplicates(pfmlib_event_t *e, unsigned int u)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int j;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(j=0; j < e->num_masks; j++) {
|
|
Packit |
577717 |
if (e->unit_masks[j] == u)
|
|
Packit |
577717 |
return PFMLIB_ERR_UMASK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_add_numeric_masks(pfmlib_event_t *e, const char *str)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i, j, c;
|
|
Packit |
577717 |
unsigned int num_masks = 0;
|
|
Packit |
577717 |
unsigned long mask_val = -1, m = 0;
|
|
Packit |
577717 |
char *endptr = NULL;
|
|
Packit |
577717 |
int ret = PFMLIB_ERR_UMASK;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* empty mask name */
|
|
Packit |
577717 |
if (*str == '\0')
|
|
Packit |
577717 |
return PFMLIB_ERR_UMASK;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
num_masks = pfm_num_masks(e->event);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* add to the existing list of unit masks
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
j = e->num_masks;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* use unsigned long to benefit from radix wildcard
|
|
Packit |
577717 |
* and error checking of strtoul()
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
mask_val = strtoul(str, &endptr, 0);
|
|
Packit |
577717 |
if (endptr && *endptr != '\0')
|
|
Packit |
577717 |
return PFMLIB_ERR_UMASK;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* look for a numerical match
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (i = 0; i < num_masks; i++) {
|
|
Packit |
577717 |
pfm_current->get_event_mask_code(e->event, i, &c);
|
|
Packit |
577717 |
if ((mask_val & c) == (unsigned long)c) {
|
|
Packit |
577717 |
/* ignore duplicates */
|
|
Packit |
577717 |
if (pfm_check_duplicates(e, i) == PFMLIB_SUCCESS) {
|
|
Packit |
577717 |
if (j == PFMLIB_MAX_MASKS_PER_EVENT) {
|
|
Packit |
577717 |
ret = PFMLIB_ERR_TOOMANY;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
e->unit_masks[j++] = i;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
m |= c;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* all bits accounted for
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (mask_val == m) {
|
|
Packit |
577717 |
e->num_masks = j;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* extra bits left over;
|
|
Packit |
577717 |
* reset and flag error
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (i = e->num_masks; i < j; i++)
|
|
Packit |
577717 |
e->unit_masks[i] = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_event_name(unsigned int i, char *name, size_t maxlen)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
size_t l, j;
|
|
Packit |
577717 |
char *str;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (i >= pfm_current->pme_count || name == NULL || maxlen < 1)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
str = pfm_current->get_event_name(i);
|
|
Packit |
577717 |
if (!str)
|
|
Packit |
577717 |
return PFMLIB_ERR_BADHOST;
|
|
Packit |
577717 |
l = strlen(str);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we fail if buffer is too small, simply because otherwise we
|
|
Packit |
577717 |
* get partial names which are useless for subsequent calls
|
|
Packit |
577717 |
* users mus invoke pfm_get_event_name_max_len() to correctly size
|
|
Packit |
577717 |
* the buffer for this call
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if ((maxlen-1) < l)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(j=0; j < l; j++)
|
|
Packit |
577717 |
name[j] = (char)toupper(str[j]);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
name[l] = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_event_code(unsigned int i, int *code)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (i >= pfm_current->pme_count || code == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pfm_current->get_event_code(i, PFMLIB_CNT_FIRST, code);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_event_code_counter(unsigned int i, unsigned int cnt, int *code)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (i >= pfm_current->pme_count || code == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pfm_current->get_event_code(i, cnt, code);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_event_counters(unsigned int i, pfmlib_regmask_t *counters)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (i >= pfm_current->pme_count) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_current->get_event_counters(i, counters);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_event_mask_name(unsigned int ev, unsigned int mask, char *name, size_t maxlen)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
char *str;
|
|
Packit |
577717 |
unsigned int num;
|
|
Packit |
577717 |
size_t l, j;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ev >= pfm_current->pme_count || name == NULL || maxlen < 1)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
num = pfm_num_masks(ev);
|
|
Packit |
577717 |
if (num == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (mask >= num)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
str = pfm_current->get_event_mask_name(ev, mask);
|
|
Packit |
577717 |
if (!str)
|
|
Packit |
577717 |
return PFMLIB_ERR_BADHOST;
|
|
Packit |
577717 |
l = strlen(str);
|
|
Packit |
577717 |
if (l >= (maxlen-1))
|
|
Packit |
577717 |
return PFMLIB_ERR_FULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
strcpy(name, str);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* present nice uniform names
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
l = strlen(name);
|
|
Packit |
577717 |
for(j=0; j < l; j++)
|
|
Packit |
577717 |
if (islower(name[j]))
|
|
Packit |
577717 |
name[j] = (char)toupper(name[j]);
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_num_events(unsigned int *count)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (count == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*count = pfm_current->pme_count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_num_event_masks(unsigned int ev, unsigned int *count)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ev >= pfm_current->pme_count || count == NULL)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*count = pfm_num_masks(ev);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if 0
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check that the unavailable PMCs registers correspond
|
|
Packit |
577717 |
* to implemented PMC registers
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_check_unavail_pmcs(pfmlib_regmask_t *pmcs)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_regmask_t impl_pmcs;
|
|
Packit |
577717 |
pfm_current->get_impl_pmcs(&impl_pmcs);
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i=0; i < PFMLIB_REG_BV; i++) {
|
|
Packit |
577717 |
if ((pmcs->bits[i] & impl_pmcs.bits[i]) != pmcs->bits[i])
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we do not check if pfp_unavail_pmcs contains only implemented PMC
|
|
Packit |
577717 |
* registers. In other words, invalid registers are ignored
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_dispatch_events(
|
|
Packit |
577717 |
pfmlib_input_param_t *inp, void *model_in,
|
|
Packit |
577717 |
pfmlib_output_param_t *outp, void *model_out)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned count;
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* at least one input and one output set must exist */
|
|
Packit |
577717 |
if (!inp && !model_in)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
if (!outp && !model_out)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!inp)
|
|
Packit |
577717 |
count = 0;
|
|
Packit |
577717 |
else if (inp->pfp_dfl_plm == 0)
|
|
Packit |
577717 |
/* the default priv level must be set to something */
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
else if (inp->pfp_event_count >= PFMLIB_MAX_PMCS)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
else if (inp->pfp_event_count > pfm_current->num_cnt)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
count = inp->pfp_event_count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check that event and unit masks descriptors are correct
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (i=0; i < count; i++) {
|
|
Packit |
577717 |
ret = __pfm_check_event(inp->pfp_events+i);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* reset output data structure */
|
|
Packit |
577717 |
if (outp)
|
|
Packit |
577717 |
memset(outp, 0, sizeof(*outp));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pfm_current->dispatch_events(inp, model_in, outp, model_out);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* more or less obosleted by pfm_get_impl_counters()
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_num_counters(unsigned int *num)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (num == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*num = pfm_current->num_cnt;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_num_pmcs(unsigned int *num)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (num == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*num = pfm_current->pmc_count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_num_pmds(unsigned int *num)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (num == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*num = pfm_current->pmd_count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
if (impl_pmcs == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(impl_pmcs , 0, sizeof(*impl_pmcs));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_current->get_impl_pmcs(impl_pmcs);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
if (impl_pmds == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(impl_pmds, 0, sizeof(*impl_pmds));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_current->get_impl_pmds(impl_pmds);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_impl_counters(pfmlib_regmask_t *impl_counters)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
if (impl_counters == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(impl_counters, 0, sizeof(*impl_counters));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_current->get_impl_counters(impl_counters);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_hw_counter_width(unsigned int *width)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
if (width == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_current->get_hw_counter_width(width);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* sorry, only English supported at this point! */
|
|
Packit |
577717 |
static char *pfmlib_err_list[]=
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
"success",
|
|
Packit |
577717 |
"not supported",
|
|
Packit |
577717 |
"invalid parameters",
|
|
Packit |
577717 |
"pfmlib not initialized",
|
|
Packit |
577717 |
"event not found",
|
|
Packit |
577717 |
"cannot assign events to counters",
|
|
Packit |
577717 |
"buffer is full or too small",
|
|
Packit |
577717 |
"event used more than once",
|
|
Packit |
577717 |
"invalid model specific magic number",
|
|
Packit |
577717 |
"invalid combination of model specific features",
|
|
Packit |
577717 |
"incompatible event sets",
|
|
Packit |
577717 |
"incompatible events combination",
|
|
Packit |
577717 |
"too many events or unit masks",
|
|
Packit |
577717 |
"code range too big",
|
|
Packit |
577717 |
"empty code range",
|
|
Packit |
577717 |
"invalid code range",
|
|
Packit |
577717 |
"too many code ranges",
|
|
Packit |
577717 |
"invalid data range",
|
|
Packit |
577717 |
"too many data ranges",
|
|
Packit |
577717 |
"not supported by host cpu",
|
|
Packit |
577717 |
"code range is not bundle-aligned",
|
|
Packit |
577717 |
"code range requires some flags in rr_flags",
|
|
Packit |
577717 |
"invalid or missing unit mask",
|
|
Packit |
577717 |
"out of memory"
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
static size_t pfmlib_err_count = sizeof(pfmlib_err_list)/sizeof(char *);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
char *
|
|
Packit |
577717 |
pfm_strerror(int code)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
code = -code;
|
|
Packit |
577717 |
if (code <0 || code >= pfmlib_err_count) return "unknown error code";
|
|
Packit |
577717 |
return pfmlib_err_list[code];
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_version(unsigned int *version)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (version == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
*version = PFMLIB_VERSION;
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_max_event_name_len(size_t *len)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i, j, num_masks;
|
|
Packit |
577717 |
size_t max = 0, l;
|
|
Packit |
577717 |
char *str;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
if (len == NULL)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < pfm_current->pme_count; i++) {
|
|
Packit |
577717 |
str = pfm_current->get_event_name(i);
|
|
Packit |
577717 |
if (!str)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
l = strlen(str);
|
|
Packit |
577717 |
if (l > max) max = l;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
num_masks = pfm_num_masks(i);
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we need to add up all length because unit masks can
|
|
Packit |
577717 |
* be combined typically. We add 1 to account for ':'
|
|
Packit |
577717 |
* which is inserted as the unit mask separator
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (j = 0; j < num_masks; j++) {
|
|
Packit |
577717 |
str = pfm_current->get_event_mask_name(i, j);
|
|
Packit |
577717 |
if (!str)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
l += 1 + strlen(str);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (l > max) max = l;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
*len = max;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* return the index of the event that counts elapsed cycles
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_cycle_event(pfmlib_event_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
if (e == NULL)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pfm_current->get_cycle_event)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(e, 0, sizeof(*e));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pfm_current->get_cycle_event(e);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* return the index of the event that retired instructions
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_inst_retired_event(pfmlib_event_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
if (e == NULL)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pfm_current->get_inst_retired_event)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(e, 0, sizeof(*e));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pfm_current->get_inst_retired_event(e);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_event_description(unsigned int i, char **str)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (i >= pfm_current->pme_count || str == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_current->get_event_desc == NULL) {
|
|
Packit |
577717 |
*str = strdup("no description available");
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return pfm_current->get_event_desc(i, str);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_event_mask_description(unsigned int event_idx, unsigned int mask_idx, char **desc)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (event_idx >= pfm_current->pme_count || desc == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_current->get_event_mask_desc == NULL) {
|
|
Packit |
577717 |
*desc = strdup("no description available");
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (mask_idx >= pfm_current->get_num_event_masks(event_idx))
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pfm_current->get_event_mask_desc(event_idx, mask_idx, desc);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_event_mask_code(unsigned int event_idx, unsigned int mask_idx, unsigned int *code)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (event_idx >= pfm_current->pme_count || code == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_current->get_event_mask_code == NULL) {
|
|
Packit |
577717 |
*code = 0;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (mask_idx >= pfm_current->get_num_event_masks(event_idx))
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pfm_current->get_event_mask_code(event_idx, mask_idx, code);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_full_event_name(pfmlib_event_t *e, char *name, size_t maxlen)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
char *str;
|
|
Packit |
577717 |
size_t l, j;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (e == NULL || name == NULL || maxlen < 1)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = __pfm_check_event(e);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* make sure the string is at least empty
|
|
Packit |
577717 |
* important for programs that do not check return value
|
|
Packit |
577717 |
* from this function!
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
*name = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
str = pfm_current->get_event_name(e->event);
|
|
Packit |
577717 |
if (!str)
|
|
Packit |
577717 |
return PFMLIB_ERR_BADHOST;
|
|
Packit |
577717 |
l = strlen(str);
|
|
Packit |
577717 |
if (l > (maxlen-1))
|
|
Packit |
577717 |
return PFMLIB_ERR_FULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
strcpy(name, str);
|
|
Packit |
577717 |
maxlen -= l + 1;
|
|
Packit |
577717 |
for(j=0; j < e->num_masks; j++) {
|
|
Packit |
577717 |
str = pfm_current->get_event_mask_name(e->event, e->unit_masks[j]);
|
|
Packit |
577717 |
if (!str)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
l = strlen(str);
|
|
Packit |
577717 |
if (l > (maxlen-1))
|
|
Packit |
577717 |
return PFMLIB_ERR_FULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
strcat(name, ":");
|
|
Packit |
577717 |
strcat(name, str);
|
|
Packit |
577717 |
maxlen -= l + 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* present nice uniform names
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
l = strlen(name);
|
|
Packit |
577717 |
for(j=0; j < l; j++)
|
|
Packit |
577717 |
if (islower(name[j]))
|
|
Packit |
577717 |
name[j] = (char)toupper(name[j]);
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_find_full_event(const char *v, pfmlib_event_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
char *str, *p, *q;
|
|
Packit |
577717 |
unsigned int j, mask;
|
|
Packit |
577717 |
int ret = PFMLIB_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (v == NULL || e == NULL)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(e, 0, sizeof(*e));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* must copy string because we modify it when parsing
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
str = strdup(v);
|
|
Packit |
577717 |
if (!str)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOMEM;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* find event. this function ignores ':' separator
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfm_find_event_byname(str, &e->event);
|
|
Packit |
577717 |
if (ret)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* get number of unit masks for event
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
j = pfm_num_masks(e->event);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* look for colon (unit mask separator)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
p = strchr(str, ':');
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* If no unit masks available and none specified, we're done */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((j == 0) && (p == NULL)) {
|
|
Packit |
577717 |
free(str);
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = PFMLIB_ERR_UMASK;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* error if:
|
|
Packit |
577717 |
* - event has no unit mask and at least one is passed
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (p && !j)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* error if:
|
|
Packit |
577717 |
* - event has unit masks, no default unit mask, and none is passed
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (j && !p) {
|
|
Packit |
577717 |
if (pfm_current->has_umask_default
|
|
Packit |
577717 |
&& pfm_current->has_umask_default(e->event)) {
|
|
Packit |
577717 |
free(str);
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* skip : */
|
|
Packit |
577717 |
p++;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* separator is passed but there is nothing behind it
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (!*p)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* parse unit masks */
|
|
Packit |
577717 |
for( q = p; q ; p = q) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
q = strchr(p,':');
|
|
Packit |
577717 |
if (q)
|
|
Packit |
577717 |
*q++ = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* text or exact unit mask value match
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfm_do_find_event_mask(e->event, p, &mask);
|
|
Packit |
577717 |
if (ret == PFMLIB_ERR_UMASK) {
|
|
Packit |
577717 |
ret = pfm_add_numeric_masks(e, p);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS)
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
} else if (ret == PFMLIB_SUCCESS) {
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* ignore duplicates
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfm_check_duplicates(e, mask);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS) {
|
|
Packit |
577717 |
ret = PFMLIB_SUCCESS;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (e->num_masks == PFMLIB_MAX_MASKS_PER_EVENT) {
|
|
Packit |
577717 |
ret = PFMLIB_ERR_TOOMANY;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
e->unit_masks[e->num_masks] = mask;
|
|
Packit |
577717 |
e->num_masks++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
error:
|
|
Packit |
577717 |
free(str);
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|