aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/perf_counter.c
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-04-08 09:01:30 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-08 13:05:47 -0400
commit8d1b2d9361b494bfc761700c348c65ebbe3deb5b (patch)
tree284706b328133063bf530cb47c52a827b523b65a /kernel/perf_counter.c
parent8740f9418c78dcad694b46ab25d1645d5aef1f5e (diff)
perf_counter: track task-comm data
Similar to the mmap data stream, add one that tracks the task COMM field, so that the userspace reporting knows what to call a task. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> LKML-Reference: <20090408130409.127422406@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/perf_counter.c')
-rw-r--r--kernel/perf_counter.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index bf12df6f3538..2d4aebb2982b 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -1917,6 +1917,99 @@ static void perf_counter_output(struct perf_counter *counter,
1917} 1917}
1918 1918
1919/* 1919/*
1920 * comm tracking
1921 */
1922
1923struct perf_comm_event {
1924 struct task_struct *task;
1925 char *comm;
1926 int comm_size;
1927
1928 struct {
1929 struct perf_event_header header;
1930
1931 u32 pid;
1932 u32 tid;
1933 } event;
1934};
1935
1936static void perf_counter_comm_output(struct perf_counter *counter,
1937 struct perf_comm_event *comm_event)
1938{
1939 struct perf_output_handle handle;
1940 int size = comm_event->event.header.size;
1941 int ret = perf_output_begin(&handle, counter, size, 0, 0);
1942
1943 if (ret)
1944 return;
1945
1946 perf_output_put(&handle, comm_event->event);
1947 perf_output_copy(&handle, comm_event->comm,
1948 comm_event->comm_size);
1949 perf_output_end(&handle);
1950}
1951
1952static int perf_counter_comm_match(struct perf_counter *counter,
1953 struct perf_comm_event *comm_event)
1954{
1955 if (counter->hw_event.comm &&
1956 comm_event->event.header.type == PERF_EVENT_COMM)
1957 return 1;
1958
1959 return 0;
1960}
1961
1962static void perf_counter_comm_ctx(struct perf_counter_context *ctx,
1963 struct perf_comm_event *comm_event)
1964{
1965 struct perf_counter *counter;
1966
1967 if (system_state != SYSTEM_RUNNING || list_empty(&ctx->event_list))
1968 return;
1969
1970 rcu_read_lock();
1971 list_for_each_entry_rcu(counter, &ctx->event_list, event_entry) {
1972 if (perf_counter_comm_match(counter, comm_event))
1973 perf_counter_comm_output(counter, comm_event);
1974 }
1975 rcu_read_unlock();
1976}
1977
1978static void perf_counter_comm_event(struct perf_comm_event *comm_event)
1979{
1980 struct perf_cpu_context *cpuctx;
1981 unsigned int size;
1982 char *comm = comm_event->task->comm;
1983
1984 size = ALIGN(strlen(comm), sizeof(u64));
1985
1986 comm_event->comm = comm;
1987 comm_event->comm_size = size;
1988
1989 comm_event->event.header.size = sizeof(comm_event->event) + size;
1990
1991 cpuctx = &get_cpu_var(perf_cpu_context);
1992 perf_counter_comm_ctx(&cpuctx->ctx, comm_event);
1993 put_cpu_var(perf_cpu_context);
1994
1995 perf_counter_comm_ctx(&current->perf_counter_ctx, comm_event);
1996}
1997
1998void perf_counter_comm(struct task_struct *task)
1999{
2000 struct perf_comm_event comm_event = {
2001 .task = task,
2002 .event = {
2003 .header = { .type = PERF_EVENT_COMM, },
2004 .pid = task->group_leader->pid,
2005 .tid = task->pid,
2006 },
2007 };
2008
2009 perf_counter_comm_event(&comm_event);
2010}
2011
2012/*
1920 * mmap tracking 2013 * mmap tracking
1921 */ 2014 */
1922 2015