Prev: [RFC][PATCH v1 00/15] perf: export events in a structured way via sysfs
Next: perf: export tracepoint events via sysfs: iwlwifi and iwlwifi_io
From: Lin Ming on 22 Jul 2010 07:20 perf: core, add functions to export events via sysfs --- include/linux/perf_event.h | 13 +++++ kernel/perf_event.c | 110 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 0 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 0ed315e..5e9f5c6 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1057,6 +1057,9 @@ extern int perf_swevent_get_recursion_context(void); extern void perf_swevent_put_recursion_context(int rctx); extern void perf_event_enable(struct perf_event *event); extern void perf_event_disable(struct perf_event *event); + +extern struct kobject *perf_sys_create_events_dir(struct kobject *parent); +extern int perf_sys_add_event(struct kobject *parent, char *name, u64 config, int type); #else static inline void perf_event_task_sched_in(struct task_struct *task) { } @@ -1092,6 +1095,16 @@ static inline int perf_swevent_get_recursion_context(void) { return -1; } static inline void perf_swevent_put_recursion_context(int rctx) { } static inline void perf_event_enable(struct perf_event *event) { } static inline void perf_event_disable(struct perf_event *event) { } + +static inline int perf_sys_add_event(struct kobject *parent, char *name, u64 config, int type) +{ + return 0; +} + +static inline struct kobject *perf_sys_create_events_dir(struct kobject *parent) +{ + return NULL; +} #endif #define perf_output_put(handle, x) \ diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 10945db..26c15a0 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -5888,3 +5888,113 @@ static int __init perf_event_sysfs_init(void) &perfclass_attr_group); } device_initcall(perf_event_sysfs_init); + +struct event_kobject { + struct kobject *kobj; + + u64 config; + int type; + + struct event_kobject *next; +}; + +static struct event_kobject *event_kobject_list; + +static struct event_kobject *perf_sys_find_event_kobj(struct kobject *kobj) +{ + struct event_kobject *event_kobj; + + event_kobj = event_kobject_list; + + while (event_kobj) { + if (kobj == event_kobj->kobj) + return event_kobj; + + event_kobj = event_kobj->next; + } + + return NULL; +} + +#define EVENT_ATTR_RO(_name) \ + static struct kobj_attribute _name##_attr = __ATTR_RO(_name) + +static ssize_t config_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct event_kobject *event_kobj; + + event_kobj = perf_sys_find_event_kobj(kobj); + + return sprintf(buf, "%llx\n", event_kobj->config); +} +EVENT_ATTR_RO(config); + +static ssize_t type_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct event_kobject *event_kobj; + + event_kobj = perf_sys_find_event_kobj(kobj); + + return sprintf(buf, "%d\n", event_kobj->type); +} +EVENT_ATTR_RO(type); + +static struct attribute *event_attrs[] = { + &config_attr.attr, + &type_attr.attr, + NULL, +}; + +static struct attribute_group event_attr_group = { + .attrs = event_attrs, +}; + +#define EVENTS_DIR "events" +struct kobject *perf_sys_create_events_dir(struct kobject *parent) +{ + if (!parent) + return NULL; + + return kobject_create_and_add(EVENTS_DIR, parent); +} + +static DEFINE_SPINLOCK(sys_events_lock); + +int perf_sys_add_event(struct kobject *parent, char *name, u64 config, int type) +{ + struct event_kobject *event_kobj; + struct kobject *kobj; + int err; + + if (!name) + return -1; + + kobj = kobject_create_and_add(name, parent); + if (!kobj) + return -ENOMEM; + err = sysfs_create_group(kobj, &event_attr_group); + if (err) { + kobject_put(kobj); + return -ENOMEM; + } + + event_kobj = kmalloc(sizeof(*event_kobj), GFP_KERNEL); + if (!event_kobj) { + kobject_put(kobj); + return -ENOMEM; + } + + spin_lock(&sys_events_lock); + + event_kobj->kobj = kobj; + event_kobj->config = config; + event_kobj->type = type; + event_kobj->next = event_kobject_list; + event_kobject_list = event_kobj; + + spin_unlock(&sys_events_lock); + + return 0; +} -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ |