diff options
| -rw-r--r-- | include/linux/perf_counter.h | 4 | ||||
| -rw-r--r-- | kernel/perf_counter.c | 74 | ||||
| -rw-r--r-- | kernel/sched.c | 1 |
3 files changed, 26 insertions, 53 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 0e57d8cc5a3d..deb9acf9ad2a 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h | |||
| @@ -615,6 +615,8 @@ extern void perf_counter_munmap(unsigned long addr, unsigned long len, | |||
| 615 | 615 | ||
| 616 | extern void perf_counter_comm(struct task_struct *tsk); | 616 | extern void perf_counter_comm(struct task_struct *tsk); |
| 617 | 617 | ||
| 618 | extern void perf_counter_task_migration(struct task_struct *task, int cpu); | ||
| 619 | |||
| 618 | #define MAX_STACK_DEPTH 255 | 620 | #define MAX_STACK_DEPTH 255 |
| 619 | 621 | ||
| 620 | struct perf_callchain_entry { | 622 | struct perf_callchain_entry { |
| @@ -668,6 +670,8 @@ perf_counter_munmap(unsigned long addr, unsigned long len, | |||
| 668 | 670 | ||
| 669 | static inline void perf_counter_comm(struct task_struct *tsk) { } | 671 | static inline void perf_counter_comm(struct task_struct *tsk) { } |
| 670 | static inline void perf_counter_init(void) { } | 672 | static inline void perf_counter_init(void) { } |
| 673 | static inline void perf_counter_task_migration(struct task_struct *task, | ||
| 674 | int cpu) { } | ||
| 671 | #endif | 675 | #endif |
| 672 | 676 | ||
| 673 | #endif /* __KERNEL__ */ | 677 | #endif /* __KERNEL__ */ |
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 8d2653f137e9..cd94cf3bf9e2 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c | |||
| @@ -2921,11 +2921,13 @@ static int perf_swcounter_match(struct perf_counter *counter, | |||
| 2921 | if (counter->hw_event.config != event_config) | 2921 | if (counter->hw_event.config != event_config) |
| 2922 | return 0; | 2922 | return 0; |
| 2923 | 2923 | ||
| 2924 | if (counter->hw_event.exclude_user && user_mode(regs)) | 2924 | if (regs) { |
| 2925 | return 0; | 2925 | if (counter->hw_event.exclude_user && user_mode(regs)) |
| 2926 | return 0; | ||
| 2926 | 2927 | ||
| 2927 | if (counter->hw_event.exclude_kernel && !user_mode(regs)) | 2928 | if (counter->hw_event.exclude_kernel && !user_mode(regs)) |
| 2928 | return 0; | 2929 | return 0; |
| 2930 | } | ||
| 2929 | 2931 | ||
| 2930 | return 1; | 2932 | return 1; |
| 2931 | } | 2933 | } |
| @@ -2935,7 +2937,7 @@ static void perf_swcounter_add(struct perf_counter *counter, u64 nr, | |||
| 2935 | { | 2937 | { |
| 2936 | int neg = atomic64_add_negative(nr, &counter->hw.count); | 2938 | int neg = atomic64_add_negative(nr, &counter->hw.count); |
| 2937 | 2939 | ||
| 2938 | if (counter->hw.irq_period && !neg) | 2940 | if (counter->hw.irq_period && !neg && regs) |
| 2939 | perf_swcounter_overflow(counter, nmi, regs, addr); | 2941 | perf_swcounter_overflow(counter, nmi, regs, addr); |
| 2940 | } | 2942 | } |
| 2941 | 2943 | ||
| @@ -3151,55 +3153,24 @@ static const struct pmu perf_ops_task_clock = { | |||
| 3151 | /* | 3153 | /* |
| 3152 | * Software counter: cpu migrations | 3154 | * Software counter: cpu migrations |
| 3153 | */ | 3155 | */ |
| 3154 | 3156 | void perf_counter_task_migration(struct task_struct *task, int cpu) | |
| 3155 | static inline u64 get_cpu_migrations(struct perf_counter *counter) | ||
| 3156 | { | ||
| 3157 | struct task_struct *curr = counter->ctx->task; | ||
| 3158 | |||
| 3159 | if (curr) | ||
| 3160 | return curr->se.nr_migrations; | ||
| 3161 | return cpu_nr_migrations(smp_processor_id()); | ||
| 3162 | } | ||
| 3163 | |||
| 3164 | static void cpu_migrations_perf_counter_update(struct perf_counter *counter) | ||
| 3165 | { | ||
| 3166 | u64 prev, now; | ||
| 3167 | s64 delta; | ||
| 3168 | |||
| 3169 | prev = atomic64_read(&counter->hw.prev_count); | ||
| 3170 | now = get_cpu_migrations(counter); | ||
| 3171 | |||
| 3172 | atomic64_set(&counter->hw.prev_count, now); | ||
| 3173 | |||
| 3174 | delta = now - prev; | ||
| 3175 | |||
| 3176 | atomic64_add(delta, &counter->count); | ||
| 3177 | } | ||
| 3178 | |||
| 3179 | static void cpu_migrations_perf_counter_read(struct perf_counter *counter) | ||
| 3180 | { | 3157 | { |
| 3181 | cpu_migrations_perf_counter_update(counter); | 3158 | struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu); |
| 3182 | } | 3159 | struct perf_counter_context *ctx; |
| 3183 | 3160 | ||
| 3184 | static int cpu_migrations_perf_counter_enable(struct perf_counter *counter) | 3161 | perf_swcounter_ctx_event(&cpuctx->ctx, PERF_TYPE_SOFTWARE, |
| 3185 | { | 3162 | PERF_COUNT_CPU_MIGRATIONS, |
| 3186 | if (counter->prev_state <= PERF_COUNTER_STATE_OFF) | 3163 | 1, 1, NULL, 0); |
| 3187 | atomic64_set(&counter->hw.prev_count, | ||
| 3188 | get_cpu_migrations(counter)); | ||
| 3189 | return 0; | ||
| 3190 | } | ||
| 3191 | 3164 | ||
| 3192 | static void cpu_migrations_perf_counter_disable(struct perf_counter *counter) | 3165 | ctx = perf_pin_task_context(task); |
| 3193 | { | 3166 | if (ctx) { |
| 3194 | cpu_migrations_perf_counter_update(counter); | 3167 | perf_swcounter_ctx_event(ctx, PERF_TYPE_SOFTWARE, |
| 3168 | PERF_COUNT_CPU_MIGRATIONS, | ||
| 3169 | 1, 1, NULL, 0); | ||
| 3170 | perf_unpin_context(ctx); | ||
| 3171 | } | ||
| 3195 | } | 3172 | } |
| 3196 | 3173 | ||
| 3197 | static const struct pmu perf_ops_cpu_migrations = { | ||
| 3198 | .enable = cpu_migrations_perf_counter_enable, | ||
| 3199 | .disable = cpu_migrations_perf_counter_disable, | ||
| 3200 | .read = cpu_migrations_perf_counter_read, | ||
| 3201 | }; | ||
| 3202 | |||
| 3203 | #ifdef CONFIG_EVENT_PROFILE | 3174 | #ifdef CONFIG_EVENT_PROFILE |
| 3204 | void perf_tpcounter_event(int event_id) | 3175 | void perf_tpcounter_event(int event_id) |
| 3205 | { | 3176 | { |
| @@ -3272,11 +3243,8 @@ static const struct pmu *sw_perf_counter_init(struct perf_counter *counter) | |||
| 3272 | case PERF_COUNT_PAGE_FAULTS_MIN: | 3243 | case PERF_COUNT_PAGE_FAULTS_MIN: |
| 3273 | case PERF_COUNT_PAGE_FAULTS_MAJ: | 3244 | case PERF_COUNT_PAGE_FAULTS_MAJ: |
| 3274 | case PERF_COUNT_CONTEXT_SWITCHES: | 3245 | case PERF_COUNT_CONTEXT_SWITCHES: |
| 3275 | pmu = &perf_ops_generic; | ||
| 3276 | break; | ||
| 3277 | case PERF_COUNT_CPU_MIGRATIONS: | 3246 | case PERF_COUNT_CPU_MIGRATIONS: |
| 3278 | if (!counter->hw_event.exclude_kernel) | 3247 | pmu = &perf_ops_generic; |
| 3279 | pmu = &perf_ops_cpu_migrations; | ||
| 3280 | break; | 3248 | break; |
| 3281 | } | 3249 | } |
| 3282 | 3250 | ||
diff --git a/kernel/sched.c b/kernel/sched.c index 3226cc132e9f..8d43347a0c0d 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -1977,6 +1977,7 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu) | |||
| 1977 | if (task_hot(p, old_rq->clock, NULL)) | 1977 | if (task_hot(p, old_rq->clock, NULL)) |
| 1978 | schedstat_inc(p, se.nr_forced2_migrations); | 1978 | schedstat_inc(p, se.nr_forced2_migrations); |
| 1979 | #endif | 1979 | #endif |
| 1980 | perf_counter_task_migration(p, new_cpu); | ||
| 1980 | } | 1981 | } |
| 1981 | p->se.vruntime -= old_cfsrq->min_vruntime - | 1982 | p->se.vruntime -= old_cfsrq->min_vruntime - |
| 1982 | new_cfsrq->min_vruntime; | 1983 | new_cfsrq->min_vruntime; |
