diff options
-rw-r--r-- | include/linux/perf_counter.h | 11 | ||||
-rw-r--r-- | kernel/perf_counter.c | 18 |
2 files changed, 25 insertions, 4 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 89698d8aba5c..e7213e46cf9c 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h | |||
@@ -669,7 +669,16 @@ static inline int is_software_counter(struct perf_counter *counter) | |||
669 | (counter->attr.type != PERF_TYPE_HW_CACHE); | 669 | (counter->attr.type != PERF_TYPE_HW_CACHE); |
670 | } | 670 | } |
671 | 671 | ||
672 | extern void perf_swcounter_event(u32, u64, int, struct pt_regs *, u64); | 672 | extern atomic_t perf_swcounter_enabled[PERF_COUNT_SW_MAX]; |
673 | |||
674 | extern void __perf_swcounter_event(u32, u64, int, struct pt_regs *, u64); | ||
675 | |||
676 | static inline void | ||
677 | perf_swcounter_event(u32 event, u64 nr, int nmi, struct pt_regs *regs, u64 addr) | ||
678 | { | ||
679 | if (atomic_read(&perf_swcounter_enabled[event])) | ||
680 | __perf_swcounter_event(event, nr, nmi, regs, addr); | ||
681 | } | ||
673 | 682 | ||
674 | extern void __perf_counter_mmap(struct vm_area_struct *vma); | 683 | extern void __perf_counter_mmap(struct vm_area_struct *vma); |
675 | 684 | ||
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 1a933a221ea4..7515c7695428 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c | |||
@@ -3317,8 +3317,8 @@ out: | |||
3317 | put_cpu_var(perf_cpu_context); | 3317 | put_cpu_var(perf_cpu_context); |
3318 | } | 3318 | } |
3319 | 3319 | ||
3320 | void | 3320 | void __perf_swcounter_event(u32 event, u64 nr, int nmi, |
3321 | perf_swcounter_event(u32 event, u64 nr, int nmi, struct pt_regs *regs, u64 addr) | 3321 | struct pt_regs *regs, u64 addr) |
3322 | { | 3322 | { |
3323 | struct perf_sample_data data = { | 3323 | struct perf_sample_data data = { |
3324 | .regs = regs, | 3324 | .regs = regs, |
@@ -3509,9 +3509,19 @@ static const struct pmu *tp_perf_counter_init(struct perf_counter *counter) | |||
3509 | } | 3509 | } |
3510 | #endif | 3510 | #endif |
3511 | 3511 | ||
3512 | atomic_t perf_swcounter_enabled[PERF_COUNT_SW_MAX]; | ||
3513 | |||
3514 | static void sw_perf_counter_destroy(struct perf_counter *counter) | ||
3515 | { | ||
3516 | u64 event = counter->attr.config; | ||
3517 | |||
3518 | atomic_dec(&perf_swcounter_enabled[event]); | ||
3519 | } | ||
3520 | |||
3512 | static const struct pmu *sw_perf_counter_init(struct perf_counter *counter) | 3521 | static const struct pmu *sw_perf_counter_init(struct perf_counter *counter) |
3513 | { | 3522 | { |
3514 | const struct pmu *pmu = NULL; | 3523 | const struct pmu *pmu = NULL; |
3524 | u64 event = counter->attr.config; | ||
3515 | 3525 | ||
3516 | /* | 3526 | /* |
3517 | * Software counters (currently) can't in general distinguish | 3527 | * Software counters (currently) can't in general distinguish |
@@ -3520,7 +3530,7 @@ static const struct pmu *sw_perf_counter_init(struct perf_counter *counter) | |||
3520 | * to be kernel events, and page faults are never hypervisor | 3530 | * to be kernel events, and page faults are never hypervisor |
3521 | * events. | 3531 | * events. |
3522 | */ | 3532 | */ |
3523 | switch (counter->attr.config) { | 3533 | switch (event) { |
3524 | case PERF_COUNT_SW_CPU_CLOCK: | 3534 | case PERF_COUNT_SW_CPU_CLOCK: |
3525 | pmu = &perf_ops_cpu_clock; | 3535 | pmu = &perf_ops_cpu_clock; |
3526 | 3536 | ||
@@ -3541,6 +3551,8 @@ static const struct pmu *sw_perf_counter_init(struct perf_counter *counter) | |||
3541 | case PERF_COUNT_SW_PAGE_FAULTS_MAJ: | 3551 | case PERF_COUNT_SW_PAGE_FAULTS_MAJ: |
3542 | case PERF_COUNT_SW_CONTEXT_SWITCHES: | 3552 | case PERF_COUNT_SW_CONTEXT_SWITCHES: |
3543 | case PERF_COUNT_SW_CPU_MIGRATIONS: | 3553 | case PERF_COUNT_SW_CPU_MIGRATIONS: |
3554 | atomic_inc(&perf_swcounter_enabled[event]); | ||
3555 | counter->destroy = sw_perf_counter_destroy; | ||
3544 | pmu = &perf_ops_generic; | 3556 | pmu = &perf_ops_generic; |
3545 | break; | 3557 | break; |
3546 | } | 3558 | } |