This patch adds the generic perfmon2 headers including the public
head perfmon.h which can be used by applications. The other
headers are for kernel use only.
Signed-off-by: Stephane Eranian <[email protected]>
--
Index: o/include/linux/perfmon.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ o/include/linux/perfmon.h 2008-06-05 10:58:36.000000000 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2001-2006 Hewlett-Packard Development Company, L.P.
+ * Contributed by Stephane Eranian <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#ifndef __LINUX_PERFMON_H__
+#define __LINUX_PERFMON_H__
+
+/*
+ * This file contains all the user visible generic definitions for the
+ * interface. Model-specific user-visible definitions are located in
+ * the asm/perfmon.h file.
+ */
+
+/*
+ * include arch-specific user interface definitions
+ */
+#include <asm/perfmon.h>
+
+/*
+ * defined by each arch
+ */
+#define PFM_MAX_PMCS PFM_ARCH_MAX_PMCS
+#define PFM_MAX_PMDS PFM_ARCH_MAX_PMDS
+
+/*
+ * number of elements for each type of bitvector
+ * all bitvectors use u64 fixed size type on all architectures.
+ */
+#define PFM_BVSIZE(x) (((x)+(sizeof(u64)<<3)-1) / (sizeof(u64)<<3))
+#define PFM_PMD_BV PFM_BVSIZE(PFM_MAX_PMDS)
+#define PFM_PMC_BV PFM_BVSIZE(PFM_MAX_PMCS)
+
+/*
+ * default value for the user and group security parameters in
+ * /proc/sys/kernel/perfmon/sys_group
+ * /proc/sys/kernel/perfmon/task_group
+ */
+#define PFM_GROUP_PERM_ANY -1 /* any user/group */
+
+/*
+ * perfmon version number
+ */
+#define PFM_VERSION_MAJ 2U
+#define PFM_VERSION_MIN 99U
+#define PFM_VERSION (((PFM_VERSION_MAJ&0xffff)<<16)|\
+ (PFM_VERSION_MIN & 0xffff))
+#define PFM_VERSION_MAJOR(x) (((x)>>16) & 0xffff)
+#define PFM_VERSION_MINOR(x) ((x) & 0xffff)
+
+#endif /* __LINUX_PERFMON_H__ */
Index: o/include/linux/perfmon_kern.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ o/include/linux/perfmon_kern.h 2008-06-05 10:58:38.000000000 +0200
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2001-2006 Hewlett-Packard Development Company, L.P.
+ * Contributed by Stephane Eranian <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+
+#ifndef __LINUX_PERFMON_KERN_H__
+#define __LINUX_PERFMON_KERN_H__
+/*
+ * This file contains all the definitions of data structures, variables, macros
+ * that are to be shared between generic code and arch-specific code
+ *
+ * For generic only definitions, use perfmon/perfmon_priv.h
+ */
+#ifdef __KERNEL__
+
+#include <linux/file.h>
+#include <linux/sched.h>
+#include <linux/perfmon.h>
+
+#ifdef CONFIG_PERFMON
+
+/*
+ * system adminstrator configuration controls available via
+ * the /sys/kerne/perfmon interface
+ */
+struct pfm_controls {
+ u32 debug; /* debugging control bitmask */
+ gid_t task_group; /* gid to create a per-task context */
+ size_t arg_mem_max; /* maximum vector argument size */
+};
+extern struct pfm_controls pfm_controls;
+
+/*
+ * software PMD
+ */
+struct pfm_pmd {
+ u64 value; /* 64-bit value */
+ u64 lval; /* last reset value */
+};
+
+/*
+ * event_set: encapsulates the full PMU state
+ */
+struct pfm_event_set {
+ u16 nused_pmds; /* max number of used PMDs */
+ u16 nused_pmcs; /* max number of used PMCs */
+ u32 priv_flags; /* private flags (see below) */
+ u32 npend_ovfls; /* number of pending PMD overflow */
+ u32 pad2; /* padding */
+ u64 used_pmds[PFM_PMD_BV]; /* used PMDs */
+ u64 povfl_pmds[PFM_PMD_BV]; /* pending overflowed PMDs */
+ u64 used_pmcs[PFM_PMC_BV]; /* used PMCs */
+ u64 pmcs[PFM_MAX_PMCS]; /* PMC values */
+
+ struct pfm_pmd pmds[PFM_MAX_PMDS];
+};
+
+/*
+ * common private event set flags (priv_flags)
+ *
+ * upper 16 bits: for arch-specific use
+ * lower 16 bits: for common use
+ */
+#define PFM_SETFL_PRIV_MOD_PMDS 0x1 /* PMD register(s) modified */
+#define PFM_SETFL_PRIV_MOD_PMCS 0x2 /* PMC register(s) modified */
+#define PFM_SETFL_PRIV_MOD_BOTH (PFM_SETFL_PRIV_MOD_PMDS \
+ | PFM_SETFL_PRIV_MOD_PMCS)
+
+
+/*
+ * context flags
+ */
+struct pfm_context_flags {
+ unsigned int started:1; /* pfm_start() issued */
+ unsigned int is_self:1; /* per-thread and self-montoring */
+ unsigned int work_type:2; /* type of work for pfm_handle_work */
+ unsigned int reserved:28; /* for future use */
+};
+/*
+ * values for work_type (TIF_PERFMON_WORK must be set)
+ */
+#define PFM_WORK_NONE 0 /* nothing to do */
+#define PFM_WORK_ZOMBIE 1 /* cleanup zombie context */
+
+
+/*
+ * perfmon context state
+ */
+#define PFM_CTX_UNLOADED 1 /* context is detached */
+#define PFM_CTX_LOADED 2 /* context is attached */
+#define PFM_CTX_ZOMBIE 3 /* context lost owner but still attached */
+
+/*
+ * context: contains all the state of a session
+ */
+struct pfm_context {
+ spinlock_t lock; /* context protection */
+
+ struct pfm_context_flags flags;
+ u32 state; /* current state */
+ struct task_struct *task; /* attached task */
+
+ u64 last_act; /* last activation */
+ u32 last_cpu; /* last CPU used (SMP only) */
+
+ struct pfm_event_set *active_set; /* active set */
+ struct pfm_event_set _set0; /* event set 0 */
+};
+
+/*
+ * logging
+ */
+#define PFM_ERR(f, x...) printk(KERN_ERR "perfmon: " f "\n", ## x)
+#define PFM_WARN(f, x...) printk(KERN_WARNING "perfmon: " f "\n", ## x)
+#define PFM_LOG(f, x...) printk(KERN_NOTICE "perfmon: " f "\n", ## x)
+#define PFM_INFO(f, x...) printk(KERN_INFO "perfmon: " f "\n", ## x)
+
+/*
+ * debugging
+ *
+ * Printk rate limiting is enforced to avoid getting flooded with too many
+ * error messages on the console (which could render the machine unresponsive).
+ * To get full debug output (turn off ratelimit):
+ * $ echo 0 >/proc/sys/kernel/printk_ratelimit
+ *
+ * debug is a bitmask where bits are defined as follows:
+ * bit 0: enable non-interrupt code degbug messages
+ * bit 1: enable interrupt code debug messages
+ */
+#ifdef CONFIG_PERFMON_DEBUG
+#define _PFM_DBG(lm, f, x...) \
+ do { \
+ if (unlikely((pfm_controls.debug & lm) && printk_ratelimit())) { \
+ printk("perfmon: %s.%d: CPU%d [%d]: " f "\n", \
+ __func__, __LINE__, \
+ smp_processor_id(), current->pid , ## x); \
+ } \
+ } while (0)
+
+#define PFM_DBG(f, x...) _PFM_DBG(0x1, f, ##x)
+#define PFM_DBG_ovfl(f, x...) _PFM_DBG(0x2, f, ##x)
+#else
+#define PFM_DBG(f, x...) do {} while (0)
+#define PFM_DBG_ovfl(f, x...) do {} while (0)
+#endif
+
+extern struct pfm_pmu_config *pfm_pmu_conf;
+extern int perfmon_disabled;
+
+static inline struct pfm_arch_context *pfm_ctx_arch(struct pfm_context *c)
+{
+ return (struct pfm_arch_context *)(c+1);
+}
+
+#include <linux/perfmon_pmu.h>
+
+extern const struct file_operations pfm_file_ops;
+
+#define cast_ulp(_x) ((unsigned long *)_x)
+
+void pfm_handle_work(struct pt_regs *regs);
+void __pfm_exit_thread(void);
+void __pfm_init_percpu(void *dummy);
+
+static inline void pfm_exit_thread(void)
+{
+ if (current->pfm_context)
+ __pfm_exit_thread();
+}
+
+/*
+ * include arch-specific kernel level definitions
+ */
+#include <asm/perfmon_kern.h>
+
+static inline void pfm_copy_thread(struct task_struct *task)
+{
+ /*
+ * context or perfmon TIF state is NEVER inherited
+ * in child task. Holds for per-thread and system-wide
+ */
+ task->pfm_context = NULL;
+ clear_tsk_thread_flag(task, TIF_PERFMON_CTXSW);
+}
+
+/*
+ * read a single PMD register.
+ */
+static inline u64 pfm_read_pmd(struct pfm_context *ctx, unsigned int cnum)
+{
+ return pfm_arch_read_pmd(ctx, cnum);
+}
+/*
+ * write a single PMD register.
+ */
+static inline void pfm_write_pmd(struct pfm_context *ctx, unsigned int cnum,
+ u64 value)
+{
+ /*
+ * PMD writes are ignored for read-only registers
+ */
+ if (pfm_pmu_conf->pmd_desc[cnum].type & PFM_REG_RO)
+ return;
+
+ /*
+ * clear unimplemented bits
+ */
+ value &= ~pfm_pmu_conf->pmd_desc[cnum].rsvd_msk;
+
+ pfm_arch_write_pmd(ctx, cnum, value);
+}
+
+DECLARE_PER_CPU(struct pfm_context *, pmu_ctx);
+DECLARE_PER_CPU(struct task_struct *, pmu_owner);
+
+/*
+ * max vector argument elements for local storage (no kmalloc/kfree)
+ * The PFM_ARCH_PM*_ARG should be defined in perfmon_kern.h.
+ * If not, default (conservative) values are used
+ */
+#ifndef PFM_ARCH_PMC_STK_ARG
+#define PFM_ARCH_PMC_STK_ARG 1
+#endif
+
+#ifndef PFM_ARCH_PMD_STK_ARG
+#define PFM_ARCH_PMD_STK_ARG 1
+#endif
+
+#define PFM_PMC_STK_ARG PFM_ARCH_PMC_STK_ARG
+#define PFM_PMD_STK_ARG PFM_ARCH_PMD_STK_ARG
+
+#else /* !CONFIG_PERFMON */
+/*
+ * perfmon hooks are nops when CONFIG_PERFMON is undefined
+ */
+#define pfm_exit_thread(_t) do { } while (0)
+#define pfm_handle_work(_t) do { } while (0)
+#define pfm_copy_thread(_t) do { } while (0)
+
+#endif /* CONFIG_PERFMON */
+
+#endif /* __KERNEL__*/
+#endif /* __LINUX_PERFMON_KERN_H__ */
Index: o/include/linux/perfmon_pmu.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ o/include/linux/perfmon_pmu.h 2008-06-04 21:31:01.000000000 +0200
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2006 Hewlett-Packard Development Company, L.P.
+ * Contributed by Stephane Eranian <[email protected]>
+ *
+ * Interface for PMU description modules
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+ */
+#ifndef __PERFMON_PMU_H__
+#define __PERFMON_PMU_H__ 1
+
+/*
+ * generic information about a PMC or PMD register
+ */
+struct pfm_regmap_desc {
+ u16 type; /* register infos */
+ u16 reserved1; /* for future use */
+ u32 reserved2; /* for future use */
+ u64 dfl_val; /* power-on default value (quiescent) */
+ u64 rsvd_msk; /* reserved bits: 1 means reserved */
+ u64 no_emul64_msk; /* bits to clear for PFM_REGFL_NO_EMUL64 */
+ unsigned long hw_addr; /* HW register address or index */
+ struct kobject kobj; /* for internal use only */
+ char *desc; /* HW register description string */
+};
+#define to_reg(n) container_of(n, struct pfm_regmap_desc, kobj)
+
+/*
+ * pfm_reg_desc helper macros
+ */
+#define PMC_D(t, d, v, r, n, h) \
+ { .type = t, \
+ .desc = d, \
+ .dfl_val = v, \
+ .rsvd_msk = r, \
+ .no_emul64_msk = n, \
+ .hw_addr = h \
+ }
+
+#define PMD_D(t, d, h) \
+ { .type = t, \
+ .desc = d, \
+ .rsvd_msk = 0, \
+ .no_emul64_msk = 0, \
+ .hw_addr = h \
+ }
+
+#define PMD_DR(t, d, h, r) \
+ { .type = t, \
+ .desc = d, \
+ .rsvd_msk = r, \
+ .no_emul64_msk = 0, \
+ .hw_addr = h \
+ }
+
+#define PMX_NA \
+ { .type = PFM_REG_NA }
+
+/*
+ * type of a PMU register (16-bit bitmask) for use with pfm_reg_desc.type
+ */
+#define PFM_REG_NA 0x00 /* not avail. (not impl.,no access) must be 0 */
+#define PFM_REG_I 0x01 /* PMC/PMD: implemented */
+#define PFM_REG_WC 0x02 /* PMC: has write_checker */
+#define PFM_REG_C64 0x04 /* PMD: 64-bit virtualization */
+#define PFM_REG_RO 0x08 /* PMD: read-only (writes ignored) */
+#define PFM_REG_INTR 0x20 /* PMD: register can generate interrupt */
+#define PFM_REG_NO64 0x100 /* PMC: supports PFM_REGFL_NO_EMUL64 */
+
+/*
+ * define some shortcuts for common types
+ */
+#define PFM_REG_W (PFM_REG_WC|PFM_REG_I)
+#define PFM_REG_W64 (PFM_REG_WC|PFM_REG_NO64|PFM_REG_I)
+#define PFM_REG_C (PFM_REG_C64|PFM_REG_INTR|PFM_REG_I)
+#define PFM_REG_I64 (PFM_REG_NO64|PFM_REG_I)
+#define PFM_REG_IRO (PFM_REG_I|PFM_REG_RO)
+
+typedef int (*pfm_pmc_check_t)(struct pfm_context *ctx,
+ struct pfm_event_set *set,
+ struct pfarg_pmc *req);
+
+typedef int (*pfm_pmd_check_t)(struct pfm_context *ctx,
+ struct pfm_event_set *set,
+ struct pfarg_pmd *req);
+
+/*
+ * registers description
+ */
+struct pfm_regdesc {
+ u64 pmcs[PFM_PMC_BV]; /* available PMC */
+ u64 pmds[PFM_PMD_BV]; /* available PMD */
+ u64 rw_pmds[PFM_PMD_BV]; /* available RW PMD */
+ u64 intr_pmds[PFM_PMD_BV]; /* PMD generating intr */
+ u64 cnt_pmds[PFM_PMD_BV]; /* PMD counters */
+ u16 max_pmc; /* highest+1 avail PMC */
+ u16 max_pmd; /* highest+1 avail PMD */
+ u16 max_rw_pmd; /* highest+1 avail RW PMD */
+ u16 max_intr_pmd; /* highest+1 intr PMD */
+ u16 num_rw_pmd; /* number of avail RW PMD */
+ u16 num_pmcs; /* number of logical PMCS */
+ u16 num_pmds; /* number of logical PMDS */
+ u16 num_counters; /* number of counting PMD */
+};
+
+/*
+ * structure used by pmu description modules
+ *
+ * probe_pmu() routine return value:
+ * - 1 means recognized PMU
+ * - 0 means not recognized PMU
+ */
+struct pfm_pmu_config {
+ char *pmu_name; /* PMU family name */
+ char *version; /* config module version */
+
+ int counter_width; /* width of hardware counter */
+
+ struct pfm_regmap_desc *pmc_desc; /* PMC register descriptions */
+ struct pfm_regmap_desc *pmd_desc; /* PMD register descriptions */
+
+ pfm_pmc_check_t pmc_write_check;/* write checker (optional) */
+ pfm_pmd_check_t pmd_write_check;/* write checker (optional) */
+ pfm_pmd_check_t pmd_read_check; /* read checker (optional) */
+ u16 num_pmc_entries;/* #entries in pmc_desc */
+ u16 num_pmd_entries;/* #entries in pmd_desc */
+ void *pmu_info; /* model-specific infos */
+ /*
+ * fields computed internally, do not set in module
+ */
+ struct pfm_regdesc regs; /* registers available */
+ u64 ovfl_mask; /* overflow mask */
+ struct kobject kobj; /* for internal use only */
+};
+#define to_pmu(n) container_of(n, struct pfm_pmu_config, kobj)
+
+static inline void *pfm_pmu_info(void)
+{
+ return pfm_pmu_conf->pmu_info;
+}
+
+int pfm_pmu_register(struct pfm_pmu_config *cfg);
+
+int pfm_sysfs_add_pmu(struct pfm_pmu_config *pmu);
+
+#endif /* __PERFMON_PMU_H__ */
--
On Mon, 09 Jun 2008 15:33:40 -0700 (PDT)
[email protected] wrote:
> +#ifndef __LINUX_PERFMON_H__
> +#define __LINUX_PERFMON_H__
> +
> +/*
> + * This file contains all the user visible generic definitions for
> the
> + * interface. Model-specific user-visible definitions are located in
> + * the asm/perfmon.h file.
> + */
> + */
> +#define PFM_BVSIZE(x) (((x)+(sizeof(u64)<<3)-1) /
> (sizeof(u64)<<3)) +#define PFM_PMD_BV PFM_BVSIZE(PFM_MAX_PMDS)
can't use u64 in userspace headers; must use __u64
> + * default value for the user and group security parameters in
> + * /proc/sys/kernel/perfmon/sys_group
> + * /proc/sys/kernel/perfmon/task_group
hmmm that smells funky.
> +/*
> + * perfmon version number
> + */
> +#define PFM_VERSION_MAJ 2U
> +#define PFM_VERSION_MIN 99U
> +#define PFM_VERSION (((PFM_VERSION_MAJ&0xffff)<<16)|\
> + (PFM_VERSION_MIN & 0xffff))
> +#define PFM_VERSION_MAJOR(x) (((x)>>16) & 0xffff)
> +#define PFM_VERSION_MINOR(x) ((x) & 0xffff)
I'm very nervous when seeing something like this in userspace headers;
you need to assume that the app has been compiled with a very different
version of the headers than the currently running kernel.... either the
version of perfmon doesn't matter, in which case these don't belong
here, or it does and it should be a runtime query.
> +#ifndef __LINUX_PERFMON_KERN_H__
> +#define __LINUX_PERFMON_KERN_H__
> +/*
> + * This file contains all the definitions of data structures,
> variables, macros
> + * that are to be shared between generic code and arch-specific code
> + *
> + * For generic only definitions, use perfmon/perfmon_priv.h
> + */
> +#ifdef __KERNEL__
no need for #ifdef __KERNEL__, just don't expose the header to
userspace.
> +/*
> + * logging
> + */
> +#define PFM_ERR(f, x...) printk(KERN_ERR "perfmon: " f "\n", ##
> x) +#define PFM_WARN(f, x...) printk(KERN_WARNING "perfmon: " f "\n",
> ## x) +#define PFM_LOG(f, x...) printk(KERN_NOTICE "perfmon: " f
> "\n", ## x) +#define PFM_INFO(f, x...) printk(KERN_INFO "perfmon:
> " f "\n", ## x) +
hmmm what's wrong with the current set of macros the kernel has for
these?
Arjan,
On Tue, Jun 10, 2008 at 4:29 PM, Arjan van de Ven <[email protected]> wrote:
> On Mon, 09 Jun 2008 15:33:40 -0700 (PDT)
> [email protected] wrote:
>
>> +#ifndef __LINUX_PERFMON_H__
>> +#define __LINUX_PERFMON_H__
>> +
>> +/*
>> + * This file contains all the user visible generic definitions for
>> the
>> + * interface. Model-specific user-visible definitions are located in
>> + * the asm/perfmon.h file.
>> + */
>> + */
>> +#define PFM_BVSIZE(x) (((x)+(sizeof(u64)<<3)-1) /
>> (sizeof(u64)<<3)) +#define PFM_PMD_BV PFM_BVSIZE(PFM_MAX_PMDS)
>
> can't use u64 in userspace headers; must use __u64
>
>
Will fix that.
>> + * default value for the user and group security parameters in
>> + * /proc/sys/kernel/perfmon/sys_group
>> + * /proc/sys/kernel/perfmon/task_group
>
> hmmm that smells funky.
>
Will clarify this.
>> +/*
>> + * perfmon version number
>> + */
>> +#define PFM_VERSION_MAJ 2U
>> +#define PFM_VERSION_MIN 99U
>> +#define PFM_VERSION (((PFM_VERSION_MAJ&0xffff)<<16)|\
>> + (PFM_VERSION_MIN & 0xffff))
>> +#define PFM_VERSION_MAJOR(x) (((x)>>16) & 0xffff)
>> +#define PFM_VERSION_MINOR(x) ((x) & 0xffff)
>
> I'm very nervous when seeing something like this in userspace headers;
> you need to assume that the app has been compiled with a very different
> version of the headers than the currently running kernel.... either the
> version of perfmon doesn't matter, in which case these don't belong
> here, or it does and it should be a runtime query.
>
I think you bring up a good point. There is indeed a way of querying the version
via /sysfs.
However the question is how does an application know which API version
it was compiled
for, so it can compare with what it finds in /sysfs? That ought to be
somewhere in the
public headers that the application was compiled with.
>
>
>> +#ifndef __LINUX_PERFMON_KERN_H__
>> +#define __LINUX_PERFMON_KERN_H__
>> +/*
>> + * This file contains all the definitions of data structures,
>> variables, macros
>> + * that are to be shared between generic code and arch-specific code
>> + *
>> + * For generic only definitions, use perfmon/perfmon_priv.h
>> + */
>> +#ifdef __KERNEL__
>
> no need for #ifdef __KERNEL__, just don't expose the header to
> userspace.
>
You are right. Will remove that.
>> +/*
>> + * logging
>> + */
>> +#define PFM_ERR(f, x...) printk(KERN_ERR "perfmon: " f "\n", ##
>> x) +#define PFM_WARN(f, x...) printk(KERN_WARNING "perfmon: " f "\n",
>> ## x) +#define PFM_LOG(f, x...) printk(KERN_NOTICE "perfmon: " f
>> "\n", ## x) +#define PFM_INFO(f, x...) printk(KERN_INFO "perfmon:
>> " f "\n", ## x) +
>
> hmmm what's wrong with the current set of macros the kernel has for
> these?
>
I think these simply prefix the message with "perfmon:" so you know
which subsystems the messages are from.
You do it in one place instead of duplicating the "perfmon: " string everywhere.
On Wednesday 11 June 2008, stephane eranian wrote:
> > I'm very nervous when seeing something like this in userspace headers;
> > you need to assume that the app has been compiled with a very different
> > version of the headers than the currently running kernel.... either the
> > version of perfmon doesn't matter, in which case these don't belong
> > here, or it does and it should be a runtime query.
> >
> I think you bring up a good point. There is indeed a way of querying the version
> via /sysfs.
>
> However the question is how does an application know which API version
> it was compiled
> for, so it can compare with what it finds in /sysfs? That ought to be
> somewhere in the
> public headers that the application was compiled with.
>
The normal way for an application is to just use a syscall or file
interface, and check for -ENOENT or -ENOSYS error codes in order to
find kernels that are too old. If older kernels had a different way
of doing things, the application can fall back on that mechanism.
An example for this would be pselect() which you can replace with
select(), but only in a racy way that the user should avoid.
When the kernel changes an interface, it must only do that in a
backwards compatible way, so that old binaries do not break. Ever.
Arnd <><