Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 147350
b: refs/heads/master
c: 8d1b2d9
h: refs/heads/master
v: v3
  • Loading branch information
Peter Zijlstra authored and Ingo Molnar committed Apr 8, 2009
1 parent cef020a commit 92b8348
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8740f9418c78dcad694b46ab25d1645d5aef1f5e
refs/heads/master: 8d1b2d9361b494bfc761700c348c65ebbe3deb5b
1 change: 1 addition & 0 deletions trunk/fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,7 @@ void set_task_comm(struct task_struct *tsk, char *buf)
task_lock(tsk);
strlcpy(tsk->comm, buf, sizeof(tsk->comm));
task_unlock(tsk);
perf_counter_comm(tsk);
}

int flush_old_exec(struct linux_binprm * bprm)
Expand Down
16 changes: 15 additions & 1 deletion trunk/include/linux/perf_counter.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,9 @@ struct perf_counter_hw_event {
exclude_idle : 1, /* don't count when idle */
mmap : 1, /* include mmap data */
munmap : 1, /* include munmap data */
comm : 1, /* include comm data */

__reserved_1 : 53;
__reserved_1 : 52;

__u32 extra_config_len;
__u32 wakeup_events; /* wakeup every n events */
Expand Down Expand Up @@ -230,6 +231,16 @@ enum perf_event_type {
PERF_EVENT_MMAP = 1,
PERF_EVENT_MUNMAP = 2,

/*
* struct {
* struct perf_event_header header;
*
* u32 pid, tid;
* char comm[];
* };
*/
PERF_EVENT_COMM = 3,

/*
* When header.misc & PERF_EVENT_MISC_OVERFLOW the event_type field
* will be PERF_RECORD_*
Expand Down Expand Up @@ -545,6 +556,8 @@ extern void perf_counter_mmap(unsigned long addr, unsigned long len,
extern void perf_counter_munmap(unsigned long addr, unsigned long len,
unsigned long pgoff, struct file *file);

extern void perf_counter_comm(struct task_struct *tsk);

#define MAX_STACK_DEPTH 255

struct perf_callchain_entry {
Expand Down Expand Up @@ -583,6 +596,7 @@ static inline void
perf_counter_munmap(unsigned long addr, unsigned long len,
unsigned long pgoff, struct file *file) { }

static inline void perf_counter_comm(struct task_struct *tsk) { }
#endif

#endif /* __KERNEL__ */
Expand Down
93 changes: 93 additions & 0 deletions trunk/kernel/perf_counter.c
Original file line number Diff line number Diff line change
Expand Up @@ -1916,6 +1916,99 @@ static void perf_counter_output(struct perf_counter *counter,
perf_output_end(&handle);
}

/*
* comm tracking
*/

struct perf_comm_event {
struct task_struct *task;
char *comm;
int comm_size;

struct {
struct perf_event_header header;

u32 pid;
u32 tid;
} event;
};

static void perf_counter_comm_output(struct perf_counter *counter,
struct perf_comm_event *comm_event)
{
struct perf_output_handle handle;
int size = comm_event->event.header.size;
int ret = perf_output_begin(&handle, counter, size, 0, 0);

if (ret)
return;

perf_output_put(&handle, comm_event->event);
perf_output_copy(&handle, comm_event->comm,
comm_event->comm_size);
perf_output_end(&handle);
}

static int perf_counter_comm_match(struct perf_counter *counter,
struct perf_comm_event *comm_event)
{
if (counter->hw_event.comm &&
comm_event->event.header.type == PERF_EVENT_COMM)
return 1;

return 0;
}

static void perf_counter_comm_ctx(struct perf_counter_context *ctx,
struct perf_comm_event *comm_event)
{
struct perf_counter *counter;

if (system_state != SYSTEM_RUNNING || list_empty(&ctx->event_list))
return;

rcu_read_lock();
list_for_each_entry_rcu(counter, &ctx->event_list, event_entry) {
if (perf_counter_comm_match(counter, comm_event))
perf_counter_comm_output(counter, comm_event);
}
rcu_read_unlock();
}

static void perf_counter_comm_event(struct perf_comm_event *comm_event)
{
struct perf_cpu_context *cpuctx;
unsigned int size;
char *comm = comm_event->task->comm;

size = ALIGN(strlen(comm), sizeof(u64));

comm_event->comm = comm;
comm_event->comm_size = size;

comm_event->event.header.size = sizeof(comm_event->event) + size;

cpuctx = &get_cpu_var(perf_cpu_context);
perf_counter_comm_ctx(&cpuctx->ctx, comm_event);
put_cpu_var(perf_cpu_context);

perf_counter_comm_ctx(&current->perf_counter_ctx, comm_event);
}

void perf_counter_comm(struct task_struct *task)
{
struct perf_comm_event comm_event = {
.task = task,
.event = {
.header = { .type = PERF_EVENT_COMM, },
.pid = task->group_leader->pid,
.tid = task->pid,
},
};

perf_counter_comm_event(&comm_event);
}

/*
* mmap tracking
*/
Expand Down

0 comments on commit 92b8348

Please sign in to comment.