All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arjan van de Ven <arjan@infradead.org>
To: linux-kernel@vger.kernel.org
Cc: mingo@elte.hu, peterz@infradead.org,
	Frederic Weisbecker <fweisbec@gmail.com>
Subject: [RFC PATCH] perf_core: provide a kernel-internal interface to get to performance counters
Date: Fri, 25 Sep 2009 12:25:56 +0200	[thread overview]
Message-ID: <20090925122556.2f8bd939@infradead.org> (raw)

>From 5db5cd76f3c16c9f6093f54d1ccfb97d04b9a1ca Mon Sep 17 00:00:00 2001
From: Arjan van de Ven <arjan@linux.intel.com>
Date: Fri, 25 Sep 2009 12:20:57 +0200
Subject: [PATCH] perf_core: provide a kernel-internal interface to get to performance counters

There are reasons for kernel code to ask for, and use, performance counters.
For example, in CPU freq governors this tends to be a good idea, but there
are other examples possible as well of course.

This patch adds the needed bits to do enable this functionality; they have been
tested in an experimental cpufreq driver that I'm working on, and the changes
are all that I needed to access counters properly.

Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
---
 include/linux/perf_event.h |    3 ++
 kernel/perf_event.c        |   71 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 73 insertions(+), 1 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 3a9d36d..5890330 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -733,6 +733,9 @@ extern int hw_perf_group_sched_in(struct perf_event *group_leader,
 	       struct perf_cpu_context *cpuctx,
 	       struct perf_event_context *ctx, int cpu);
 extern void perf_event_update_userpage(struct perf_event *event);
+extern int perf_event_release_kernel(struct perf_event *event);
+extern struct perf_event *perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu);
+extern u64 perf_event_read_value(struct perf_event *event);
 
 struct perf_sample_data {
 	u64				type;
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 76ac4db..185f45a 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -1734,6 +1734,26 @@ static int perf_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
+int perf_event_release_kernel(struct perf_event *event)
+{
+	struct perf_event_context *ctx = event->ctx;
+
+	WARN_ON_ONCE(ctx->parent_ctx);
+	mutex_lock(&ctx->mutex);
+	perf_event_remove_from_context(event);
+	mutex_unlock(&ctx->mutex);
+
+	mutex_lock(&event->owner->perf_event_mutex);
+	list_del_init(&event->owner_entry);
+	mutex_unlock(&event->owner->perf_event_mutex);
+	put_task_struct(event->owner);
+
+	free_event(event);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(perf_event_release_kernel);
+
 static int perf_event_read_size(struct perf_event *event)
 {
 	int entry = sizeof(u64); /* value */
@@ -1759,7 +1779,7 @@ static int perf_event_read_size(struct perf_event *event)
 	return size;
 }
 
-static u64 perf_event_read_value(struct perf_event *event)
+u64 perf_event_read_value(struct perf_event *event)
 {
 	struct perf_event *child;
 	u64 total = 0;
@@ -1770,6 +1790,7 @@ static u64 perf_event_read_value(struct perf_event *event)
 
 	return total;
 }
+EXPORT_SYMBOL_GPL(perf_event_read_value);
 
 static int perf_event_read_entry(struct perf_event *event,
 				   u64 read_format, char __user *buf)
@@ -4463,6 +4484,54 @@ err_put_context:
 }
 
 /*
+ * perf_event_create_kernel_counter
+ * MUST be called from a kernel thread.
+ */
+struct perf_event *
+perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu)
+{
+	struct perf_event *event;
+	struct perf_event_context *ctx;
+	int err;
+
+	/*
+	 * Get the target context (task or percpu):
+	 */
+
+	ctx = find_get_context(0, cpu);
+	if (IS_ERR(ctx))
+		return NULL ;
+
+	event = perf_event_alloc(attr, cpu, ctx, NULL,
+				     NULL, GFP_KERNEL);
+	err = PTR_ERR(event);
+	if (IS_ERR(event))
+		goto err_put_context;
+
+	event->filp = NULL;
+	WARN_ON_ONCE(ctx->parent_ctx);
+	mutex_lock(&ctx->mutex);
+	perf_install_in_context(ctx, event, cpu);
+	++ctx->generation;
+	mutex_unlock(&ctx->mutex);
+
+	event->owner = current;
+	get_task_struct(current);
+	mutex_lock(&current->perf_event_mutex);
+	list_add_tail(&event->owner_entry, &current->perf_event_list);
+	mutex_unlock(&current->perf_event_mutex);
+
+	return event;
+
+err_put_context:
+	if (err < 0)
+		put_ctx(ctx);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter);
+
+/*
  * inherit a event from parent task to child task:
  */
 static struct perf_event *
-- 
1.6.0.6



-- 
Arjan van de Ven 	Intel Open Source Technology Centre
For development, discussion and tips for power savings, 
visit http://www.lesswatts.org

             reply	other threads:[~2009-09-25 10:25 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-09-25 10:25 Arjan van de Ven [this message]
2009-09-25 10:44 ` [RFC PATCH] perf_core: provide a kernel-internal interface to get to performance counters Frederic Weisbecker
2009-09-25 11:42 ` Peter Zijlstra
2009-09-26 16:03 ` Frank Ch. Eigler
2009-09-26 16:11   ` Arjan van de Ven
2009-09-26 16:20     ` Frank Ch. Eigler
2009-09-26 18:32   ` K.Prasad
2009-09-26 18:48     ` Arjan van de Ven
2009-10-01  7:25       ` Ingo Molnar
2009-10-01  8:16         ` K.Prasad
2009-10-01  8:53           ` Ingo Molnar
2009-10-01 10:01             ` K.Prasad
2009-10-01 10:28               ` Ingo Molnar
2009-10-04 22:28             ` Frederic Weisbecker
2009-10-05  9:55               ` Ingo Molnar
2009-10-05 10:13                 ` Frédéric Weisbecker
2009-10-05  7:53             ` Peter Zijlstra
2009-10-05  8:55               ` Ingo Molnar
2009-10-05  9:24                 ` Frédéric Weisbecker
2009-10-05  9:48                   ` Ingo Molnar
2009-10-05 10:08                     ` Frédéric Weisbecker
2009-11-21 13:36 ` [tip:perf/core] perf/core: Provide " tip-bot for Arjan van de Ven
2010-02-05 15:47 ` [RFC PATCH] perf_core: provide " Christoph Hellwig
2010-02-05 17:59   ` john smith
2010-02-06  6:24   ` Arjan van de Ven
2010-02-06 11:46     ` Frederic Weisbecker
2010-02-06 14:18       ` Peter Zijlstra
2010-02-06 16:08         ` Frederic Weisbecker
2010-02-07 17:01   ` Ingo Molnar
2010-01-25  5:10 john smith

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090925122556.2f8bd939@infradead.org \
    --to=arjan@infradead.org \
    --cc=fweisbec@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=peterz@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.