diff options
Diffstat (limited to 'kernel/events/core.c')
-rw-r--r-- | kernel/events/core.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index f1cf0edeb39a..b7935fcec7d9 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
@@ -4039,7 +4039,7 @@ void perf_prepare_sample(struct perf_event_header *header, | |||
4039 | if (sample_type & PERF_SAMPLE_CALLCHAIN) { | 4039 | if (sample_type & PERF_SAMPLE_CALLCHAIN) { |
4040 | int size = 1; | 4040 | int size = 1; |
4041 | 4041 | ||
4042 | data->callchain = perf_callchain(regs); | 4042 | data->callchain = perf_callchain(event, regs); |
4043 | 4043 | ||
4044 | if (data->callchain) | 4044 | if (data->callchain) |
4045 | size += data->callchain->nr; | 4045 | size += data->callchain->nr; |
@@ -5209,7 +5209,8 @@ static int perf_tp_event_match(struct perf_event *event, | |||
5209 | } | 5209 | } |
5210 | 5210 | ||
5211 | void perf_tp_event(u64 addr, u64 count, void *record, int entry_size, | 5211 | void perf_tp_event(u64 addr, u64 count, void *record, int entry_size, |
5212 | struct pt_regs *regs, struct hlist_head *head, int rctx) | 5212 | struct pt_regs *regs, struct hlist_head *head, int rctx, |
5213 | struct task_struct *task) | ||
5213 | { | 5214 | { |
5214 | struct perf_sample_data data; | 5215 | struct perf_sample_data data; |
5215 | struct perf_event *event; | 5216 | struct perf_event *event; |
@@ -5228,6 +5229,31 @@ void perf_tp_event(u64 addr, u64 count, void *record, int entry_size, | |||
5228 | perf_swevent_event(event, count, &data, regs); | 5229 | perf_swevent_event(event, count, &data, regs); |
5229 | } | 5230 | } |
5230 | 5231 | ||
5232 | /* | ||
5233 | * If we got specified a target task, also iterate its context and | ||
5234 | * deliver this event there too. | ||
5235 | */ | ||
5236 | if (task && task != current) { | ||
5237 | struct perf_event_context *ctx; | ||
5238 | struct trace_entry *entry = record; | ||
5239 | |||
5240 | rcu_read_lock(); | ||
5241 | ctx = rcu_dereference(task->perf_event_ctxp[perf_sw_context]); | ||
5242 | if (!ctx) | ||
5243 | goto unlock; | ||
5244 | |||
5245 | list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { | ||
5246 | if (event->attr.type != PERF_TYPE_TRACEPOINT) | ||
5247 | continue; | ||
5248 | if (event->attr.config != entry->type) | ||
5249 | continue; | ||
5250 | if (perf_tp_event_match(event, &data, regs)) | ||
5251 | perf_swevent_event(event, count, &data, regs); | ||
5252 | } | ||
5253 | unlock: | ||
5254 | rcu_read_unlock(); | ||
5255 | } | ||
5256 | |||
5231 | perf_swevent_put_recursion_context(rctx); | 5257 | perf_swevent_put_recursion_context(rctx); |
5232 | } | 5258 | } |
5233 | EXPORT_SYMBOL_GPL(perf_tp_event); | 5259 | EXPORT_SYMBOL_GPL(perf_tp_event); |