diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/Makefile | 1 | ||||
-rw-r--r-- | kernel/exit.c | 14 | ||||
-rw-r--r-- | kernel/perf_event.c | 82 | ||||
-rw-r--r-- | kernel/trace/Makefile | 2 | ||||
-rw-r--r-- | kernel/trace/trace.c | 6 |
5 files changed, 62 insertions, 43 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index 33e0a39cf359..5669f71dfdd5 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -100,6 +100,7 @@ obj-$(CONFIG_FUNCTION_TRACER) += trace/ | |||
100 | obj-$(CONFIG_TRACING) += trace/ | 100 | obj-$(CONFIG_TRACING) += trace/ |
101 | obj-$(CONFIG_X86_DS) += trace/ | 101 | obj-$(CONFIG_X86_DS) += trace/ |
102 | obj-$(CONFIG_RING_BUFFER) += trace/ | 102 | obj-$(CONFIG_RING_BUFFER) += trace/ |
103 | obj-$(CONFIG_TRACEPOINTS) += trace/ | ||
103 | obj-$(CONFIG_SMP) += sched_cpupri.o | 104 | obj-$(CONFIG_SMP) += sched_cpupri.o |
104 | obj-$(CONFIG_IRQ_WORK) += irq_work.o | 105 | obj-$(CONFIG_IRQ_WORK) += irq_work.o |
105 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o | 106 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o |
diff --git a/kernel/exit.c b/kernel/exit.c index 89c74861a3da..f9a45ebcc7b1 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -994,6 +994,15 @@ NORET_TYPE void do_exit(long code) | |||
994 | exit_fs(tsk); | 994 | exit_fs(tsk); |
995 | check_stack_usage(); | 995 | check_stack_usage(); |
996 | exit_thread(); | 996 | exit_thread(); |
997 | |||
998 | /* | ||
999 | * Flush inherited counters to the parent - before the parent | ||
1000 | * gets woken up by child-exit notifications. | ||
1001 | * | ||
1002 | * because of cgroup mode, must be called before cgroup_exit() | ||
1003 | */ | ||
1004 | perf_event_exit_task(tsk); | ||
1005 | |||
997 | cgroup_exit(tsk, 1); | 1006 | cgroup_exit(tsk, 1); |
998 | 1007 | ||
999 | if (group_dead) | 1008 | if (group_dead) |
@@ -1007,11 +1016,6 @@ NORET_TYPE void do_exit(long code) | |||
1007 | * FIXME: do that only when needed, using sched_exit tracepoint | 1016 | * FIXME: do that only when needed, using sched_exit tracepoint |
1008 | */ | 1017 | */ |
1009 | flush_ptrace_hw_breakpoint(tsk); | 1018 | flush_ptrace_hw_breakpoint(tsk); |
1010 | /* | ||
1011 | * Flush inherited counters to the parent - before the parent | ||
1012 | * gets woken up by child-exit notifications. | ||
1013 | */ | ||
1014 | perf_event_exit_task(tsk); | ||
1015 | 1019 | ||
1016 | exit_notify(tsk, group_dead); | 1020 | exit_notify(tsk, group_dead); |
1017 | #ifdef CONFIG_NUMA | 1021 | #ifdef CONFIG_NUMA |
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 11847bf1e8cc..b782b7a79f00 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -38,6 +38,12 @@ | |||
38 | 38 | ||
39 | #include <asm/irq_regs.h> | 39 | #include <asm/irq_regs.h> |
40 | 40 | ||
41 | enum event_type_t { | ||
42 | EVENT_FLEXIBLE = 0x1, | ||
43 | EVENT_PINNED = 0x2, | ||
44 | EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED, | ||
45 | }; | ||
46 | |||
41 | atomic_t perf_task_events __read_mostly; | 47 | atomic_t perf_task_events __read_mostly; |
42 | static atomic_t nr_mmap_events __read_mostly; | 48 | static atomic_t nr_mmap_events __read_mostly; |
43 | static atomic_t nr_comm_events __read_mostly; | 49 | static atomic_t nr_comm_events __read_mostly; |
@@ -65,6 +71,12 @@ int sysctl_perf_event_sample_rate __read_mostly = 100000; | |||
65 | 71 | ||
66 | static atomic64_t perf_event_id; | 72 | static atomic64_t perf_event_id; |
67 | 73 | ||
74 | static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx, | ||
75 | enum event_type_t event_type); | ||
76 | |||
77 | static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx, | ||
78 | enum event_type_t event_type); | ||
79 | |||
68 | void __weak perf_event_print_debug(void) { } | 80 | void __weak perf_event_print_debug(void) { } |
69 | 81 | ||
70 | extern __weak const char *perf_pmu_name(void) | 82 | extern __weak const char *perf_pmu_name(void) |
@@ -72,6 +84,11 @@ extern __weak const char *perf_pmu_name(void) | |||
72 | return "pmu"; | 84 | return "pmu"; |
73 | } | 85 | } |
74 | 86 | ||
87 | static inline u64 perf_clock(void) | ||
88 | { | ||
89 | return local_clock(); | ||
90 | } | ||
91 | |||
75 | void perf_pmu_disable(struct pmu *pmu) | 92 | void perf_pmu_disable(struct pmu *pmu) |
76 | { | 93 | { |
77 | int *count = this_cpu_ptr(pmu->pmu_disable_count); | 94 | int *count = this_cpu_ptr(pmu->pmu_disable_count); |
@@ -240,11 +257,6 @@ static void perf_unpin_context(struct perf_event_context *ctx) | |||
240 | put_ctx(ctx); | 257 | put_ctx(ctx); |
241 | } | 258 | } |
242 | 259 | ||
243 | static inline u64 perf_clock(void) | ||
244 | { | ||
245 | return local_clock(); | ||
246 | } | ||
247 | |||
248 | /* | 260 | /* |
249 | * Update the record of the current time in a context. | 261 | * Update the record of the current time in a context. |
250 | */ | 262 | */ |
@@ -256,6 +268,12 @@ static void update_context_time(struct perf_event_context *ctx) | |||
256 | ctx->timestamp = now; | 268 | ctx->timestamp = now; |
257 | } | 269 | } |
258 | 270 | ||
271 | static u64 perf_event_time(struct perf_event *event) | ||
272 | { | ||
273 | struct perf_event_context *ctx = event->ctx; | ||
274 | return ctx ? ctx->time : 0; | ||
275 | } | ||
276 | |||
259 | /* | 277 | /* |
260 | * Update the total_time_enabled and total_time_running fields for a event. | 278 | * Update the total_time_enabled and total_time_running fields for a event. |
261 | */ | 279 | */ |
@@ -269,7 +287,7 @@ static void update_event_times(struct perf_event *event) | |||
269 | return; | 287 | return; |
270 | 288 | ||
271 | if (ctx->is_active) | 289 | if (ctx->is_active) |
272 | run_end = ctx->time; | 290 | run_end = perf_event_time(event); |
273 | else | 291 | else |
274 | run_end = event->tstamp_stopped; | 292 | run_end = event->tstamp_stopped; |
275 | 293 | ||
@@ -278,7 +296,7 @@ static void update_event_times(struct perf_event *event) | |||
278 | if (event->state == PERF_EVENT_STATE_INACTIVE) | 296 | if (event->state == PERF_EVENT_STATE_INACTIVE) |
279 | run_end = event->tstamp_stopped; | 297 | run_end = event->tstamp_stopped; |
280 | else | 298 | else |
281 | run_end = ctx->time; | 299 | run_end = perf_event_time(event); |
282 | 300 | ||
283 | event->total_time_running = run_end - event->tstamp_running; | 301 | event->total_time_running = run_end - event->tstamp_running; |
284 | } | 302 | } |
@@ -534,6 +552,7 @@ event_sched_out(struct perf_event *event, | |||
534 | struct perf_cpu_context *cpuctx, | 552 | struct perf_cpu_context *cpuctx, |
535 | struct perf_event_context *ctx) | 553 | struct perf_event_context *ctx) |
536 | { | 554 | { |
555 | u64 tstamp = perf_event_time(event); | ||
537 | u64 delta; | 556 | u64 delta; |
538 | /* | 557 | /* |
539 | * An event which could not be activated because of | 558 | * An event which could not be activated because of |
@@ -545,7 +564,7 @@ event_sched_out(struct perf_event *event, | |||
545 | && !event_filter_match(event)) { | 564 | && !event_filter_match(event)) { |
546 | delta = ctx->time - event->tstamp_stopped; | 565 | delta = ctx->time - event->tstamp_stopped; |
547 | event->tstamp_running += delta; | 566 | event->tstamp_running += delta; |
548 | event->tstamp_stopped = ctx->time; | 567 | event->tstamp_stopped = tstamp; |
549 | } | 568 | } |
550 | 569 | ||
551 | if (event->state != PERF_EVENT_STATE_ACTIVE) | 570 | if (event->state != PERF_EVENT_STATE_ACTIVE) |
@@ -556,7 +575,7 @@ event_sched_out(struct perf_event *event, | |||
556 | event->pending_disable = 0; | 575 | event->pending_disable = 0; |
557 | event->state = PERF_EVENT_STATE_OFF; | 576 | event->state = PERF_EVENT_STATE_OFF; |
558 | } | 577 | } |
559 | event->tstamp_stopped = ctx->time; | 578 | event->tstamp_stopped = tstamp; |
560 | event->pmu->del(event, 0); | 579 | event->pmu->del(event, 0); |
561 | event->oncpu = -1; | 580 | event->oncpu = -1; |
562 | 581 | ||
@@ -768,6 +787,8 @@ event_sched_in(struct perf_event *event, | |||
768 | struct perf_cpu_context *cpuctx, | 787 | struct perf_cpu_context *cpuctx, |
769 | struct perf_event_context *ctx) | 788 | struct perf_event_context *ctx) |
770 | { | 789 | { |
790 | u64 tstamp = perf_event_time(event); | ||
791 | |||
771 | if (event->state <= PERF_EVENT_STATE_OFF) | 792 | if (event->state <= PERF_EVENT_STATE_OFF) |
772 | return 0; | 793 | return 0; |
773 | 794 | ||
@@ -784,9 +805,9 @@ event_sched_in(struct perf_event *event, | |||
784 | return -EAGAIN; | 805 | return -EAGAIN; |
785 | } | 806 | } |
786 | 807 | ||
787 | event->tstamp_running += ctx->time - event->tstamp_stopped; | 808 | event->tstamp_running += tstamp - event->tstamp_stopped; |
788 | 809 | ||
789 | event->shadow_ctx_time = ctx->time - ctx->timestamp; | 810 | event->shadow_ctx_time = tstamp - ctx->timestamp; |
790 | 811 | ||
791 | if (!is_software_event(event)) | 812 | if (!is_software_event(event)) |
792 | cpuctx->active_oncpu++; | 813 | cpuctx->active_oncpu++; |
@@ -898,11 +919,13 @@ static int group_can_go_on(struct perf_event *event, | |||
898 | static void add_event_to_ctx(struct perf_event *event, | 919 | static void add_event_to_ctx(struct perf_event *event, |
899 | struct perf_event_context *ctx) | 920 | struct perf_event_context *ctx) |
900 | { | 921 | { |
922 | u64 tstamp = perf_event_time(event); | ||
923 | |||
901 | list_add_event(event, ctx); | 924 | list_add_event(event, ctx); |
902 | perf_group_attach(event); | 925 | perf_group_attach(event); |
903 | event->tstamp_enabled = ctx->time; | 926 | event->tstamp_enabled = tstamp; |
904 | event->tstamp_running = ctx->time; | 927 | event->tstamp_running = tstamp; |
905 | event->tstamp_stopped = ctx->time; | 928 | event->tstamp_stopped = tstamp; |
906 | } | 929 | } |
907 | 930 | ||
908 | /* | 931 | /* |
@@ -937,7 +960,7 @@ static void __perf_install_in_context(void *info) | |||
937 | 960 | ||
938 | add_event_to_ctx(event, ctx); | 961 | add_event_to_ctx(event, ctx); |
939 | 962 | ||
940 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | 963 | if (!event_filter_match(event)) |
941 | goto unlock; | 964 | goto unlock; |
942 | 965 | ||
943 | /* | 966 | /* |
@@ -1042,14 +1065,13 @@ static void __perf_event_mark_enabled(struct perf_event *event, | |||
1042 | struct perf_event_context *ctx) | 1065 | struct perf_event_context *ctx) |
1043 | { | 1066 | { |
1044 | struct perf_event *sub; | 1067 | struct perf_event *sub; |
1068 | u64 tstamp = perf_event_time(event); | ||
1045 | 1069 | ||
1046 | event->state = PERF_EVENT_STATE_INACTIVE; | 1070 | event->state = PERF_EVENT_STATE_INACTIVE; |
1047 | event->tstamp_enabled = ctx->time - event->total_time_enabled; | 1071 | event->tstamp_enabled = tstamp - event->total_time_enabled; |
1048 | list_for_each_entry(sub, &event->sibling_list, group_entry) { | 1072 | list_for_each_entry(sub, &event->sibling_list, group_entry) { |
1049 | if (sub->state >= PERF_EVENT_STATE_INACTIVE) { | 1073 | if (sub->state >= PERF_EVENT_STATE_INACTIVE) |
1050 | sub->tstamp_enabled = | 1074 | sub->tstamp_enabled = tstamp - sub->total_time_enabled; |
1051 | ctx->time - sub->total_time_enabled; | ||
1052 | } | ||
1053 | } | 1075 | } |
1054 | } | 1076 | } |
1055 | 1077 | ||
@@ -1082,7 +1104,7 @@ static void __perf_event_enable(void *info) | |||
1082 | goto unlock; | 1104 | goto unlock; |
1083 | __perf_event_mark_enabled(event, ctx); | 1105 | __perf_event_mark_enabled(event, ctx); |
1084 | 1106 | ||
1085 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | 1107 | if (!event_filter_match(event)) |
1086 | goto unlock; | 1108 | goto unlock; |
1087 | 1109 | ||
1088 | /* | 1110 | /* |
@@ -1193,12 +1215,6 @@ static int perf_event_refresh(struct perf_event *event, int refresh) | |||
1193 | return 0; | 1215 | return 0; |
1194 | } | 1216 | } |
1195 | 1217 | ||
1196 | enum event_type_t { | ||
1197 | EVENT_FLEXIBLE = 0x1, | ||
1198 | EVENT_PINNED = 0x2, | ||
1199 | EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED, | ||
1200 | }; | ||
1201 | |||
1202 | static void ctx_sched_out(struct perf_event_context *ctx, | 1218 | static void ctx_sched_out(struct perf_event_context *ctx, |
1203 | struct perf_cpu_context *cpuctx, | 1219 | struct perf_cpu_context *cpuctx, |
1204 | enum event_type_t event_type) | 1220 | enum event_type_t event_type) |
@@ -1435,7 +1451,7 @@ ctx_pinned_sched_in(struct perf_event_context *ctx, | |||
1435 | list_for_each_entry(event, &ctx->pinned_groups, group_entry) { | 1451 | list_for_each_entry(event, &ctx->pinned_groups, group_entry) { |
1436 | if (event->state <= PERF_EVENT_STATE_OFF) | 1452 | if (event->state <= PERF_EVENT_STATE_OFF) |
1437 | continue; | 1453 | continue; |
1438 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | 1454 | if (!event_filter_match(event)) |
1439 | continue; | 1455 | continue; |
1440 | 1456 | ||
1441 | if (group_can_go_on(event, cpuctx, 1)) | 1457 | if (group_can_go_on(event, cpuctx, 1)) |
@@ -1467,7 +1483,7 @@ ctx_flexible_sched_in(struct perf_event_context *ctx, | |||
1467 | * Listen to the 'cpu' scheduling filter constraint | 1483 | * Listen to the 'cpu' scheduling filter constraint |
1468 | * of events: | 1484 | * of events: |
1469 | */ | 1485 | */ |
1470 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | 1486 | if (!event_filter_match(event)) |
1471 | continue; | 1487 | continue; |
1472 | 1488 | ||
1473 | if (group_can_go_on(event, cpuctx, can_add_hw)) { | 1489 | if (group_can_go_on(event, cpuctx, can_add_hw)) { |
@@ -1694,7 +1710,7 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period) | |||
1694 | if (event->state != PERF_EVENT_STATE_ACTIVE) | 1710 | if (event->state != PERF_EVENT_STATE_ACTIVE) |
1695 | continue; | 1711 | continue; |
1696 | 1712 | ||
1697 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | 1713 | if (!event_filter_match(event)) |
1698 | continue; | 1714 | continue; |
1699 | 1715 | ||
1700 | hwc = &event->hw; | 1716 | hwc = &event->hw; |
@@ -3893,7 +3909,7 @@ static int perf_event_task_match(struct perf_event *event) | |||
3893 | if (event->state < PERF_EVENT_STATE_INACTIVE) | 3909 | if (event->state < PERF_EVENT_STATE_INACTIVE) |
3894 | return 0; | 3910 | return 0; |
3895 | 3911 | ||
3896 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | 3912 | if (!event_filter_match(event)) |
3897 | return 0; | 3913 | return 0; |
3898 | 3914 | ||
3899 | if (event->attr.comm || event->attr.mmap || | 3915 | if (event->attr.comm || event->attr.mmap || |
@@ -4030,7 +4046,7 @@ static int perf_event_comm_match(struct perf_event *event) | |||
4030 | if (event->state < PERF_EVENT_STATE_INACTIVE) | 4046 | if (event->state < PERF_EVENT_STATE_INACTIVE) |
4031 | return 0; | 4047 | return 0; |
4032 | 4048 | ||
4033 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | 4049 | if (!event_filter_match(event)) |
4034 | return 0; | 4050 | return 0; |
4035 | 4051 | ||
4036 | if (event->attr.comm) | 4052 | if (event->attr.comm) |
@@ -4178,7 +4194,7 @@ static int perf_event_mmap_match(struct perf_event *event, | |||
4178 | if (event->state < PERF_EVENT_STATE_INACTIVE) | 4194 | if (event->state < PERF_EVENT_STATE_INACTIVE) |
4179 | return 0; | 4195 | return 0; |
4180 | 4196 | ||
4181 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | 4197 | if (!event_filter_match(event)) |
4182 | return 0; | 4198 | return 0; |
4183 | 4199 | ||
4184 | if ((!executable && event->attr.mmap_data) || | 4200 | if ((!executable && event->attr.mmap_data) || |
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index 53f338190b26..761c510a06c5 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile | |||
@@ -52,7 +52,7 @@ obj-$(CONFIG_EVENT_TRACING) += trace_event_perf.o | |||
52 | endif | 52 | endif |
53 | obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o | 53 | obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o |
54 | obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o | 54 | obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o |
55 | obj-$(CONFIG_EVENT_TRACING) += power-traces.o | 55 | obj-$(CONFIG_TRACEPOINTS) += power-traces.o |
56 | ifeq ($(CONFIG_TRACING),y) | 56 | ifeq ($(CONFIG_TRACING),y) |
57 | obj-$(CONFIG_KGDB_KDB) += trace_kdb.o | 57 | obj-$(CONFIG_KGDB_KDB) += trace_kdb.o |
58 | endif | 58 | endif |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index f8cf959bad45..dc53ecb80589 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -1313,12 +1313,10 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc) | |||
1313 | 1313 | ||
1314 | __this_cpu_inc(user_stack_count); | 1314 | __this_cpu_inc(user_stack_count); |
1315 | 1315 | ||
1316 | |||
1317 | |||
1318 | event = trace_buffer_lock_reserve(buffer, TRACE_USER_STACK, | 1316 | event = trace_buffer_lock_reserve(buffer, TRACE_USER_STACK, |
1319 | sizeof(*entry), flags, pc); | 1317 | sizeof(*entry), flags, pc); |
1320 | if (!event) | 1318 | if (!event) |
1321 | return; | 1319 | goto out_drop_count; |
1322 | entry = ring_buffer_event_data(event); | 1320 | entry = ring_buffer_event_data(event); |
1323 | 1321 | ||
1324 | entry->tgid = current->tgid; | 1322 | entry->tgid = current->tgid; |
@@ -1333,8 +1331,8 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc) | |||
1333 | if (!filter_check_discard(call, entry, buffer, event)) | 1331 | if (!filter_check_discard(call, entry, buffer, event)) |
1334 | ring_buffer_unlock_commit(buffer, event); | 1332 | ring_buffer_unlock_commit(buffer, event); |
1335 | 1333 | ||
1334 | out_drop_count: | ||
1336 | __this_cpu_dec(user_stack_count); | 1335 | __this_cpu_dec(user_stack_count); |
1337 | |||
1338 | out: | 1336 | out: |
1339 | preempt_enable(); | 1337 | preempt_enable(); |
1340 | } | 1338 | } |