diff options
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r-- | kernel/perf_event.c | 64 |
1 files changed, 52 insertions, 12 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 5ed0c06765bb..8ef4ba3bcb1f 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -674,21 +674,14 @@ group_sched_in(struct perf_event *group_event, | |||
674 | { | 674 | { |
675 | struct perf_event *event, *partial_group = NULL; | 675 | struct perf_event *event, *partial_group = NULL; |
676 | struct pmu *pmu = group_event->pmu; | 676 | struct pmu *pmu = group_event->pmu; |
677 | bool txn = false; | ||
678 | 677 | ||
679 | if (group_event->state == PERF_EVENT_STATE_OFF) | 678 | if (group_event->state == PERF_EVENT_STATE_OFF) |
680 | return 0; | 679 | return 0; |
681 | 680 | ||
682 | /* Check if group transaction availabe */ | 681 | pmu->start_txn(pmu); |
683 | if (pmu->start_txn) | ||
684 | txn = true; | ||
685 | |||
686 | if (txn) | ||
687 | pmu->start_txn(pmu); | ||
688 | 682 | ||
689 | if (event_sched_in(group_event, cpuctx, ctx)) { | 683 | if (event_sched_in(group_event, cpuctx, ctx)) { |
690 | if (txn) | 684 | pmu->cancel_txn(pmu); |
691 | pmu->cancel_txn(pmu); | ||
692 | return -EAGAIN; | 685 | return -EAGAIN; |
693 | } | 686 | } |
694 | 687 | ||
@@ -702,7 +695,7 @@ group_sched_in(struct perf_event *group_event, | |||
702 | } | 695 | } |
703 | } | 696 | } |
704 | 697 | ||
705 | if (!txn || !pmu->commit_txn(pmu)) | 698 | if (!pmu->commit_txn(pmu)) |
706 | return 0; | 699 | return 0; |
707 | 700 | ||
708 | group_error: | 701 | group_error: |
@@ -717,8 +710,7 @@ group_error: | |||
717 | } | 710 | } |
718 | event_sched_out(group_event, cpuctx, ctx); | 711 | event_sched_out(group_event, cpuctx, ctx); |
719 | 712 | ||
720 | if (txn) | 713 | pmu->cancel_txn(pmu); |
721 | pmu->cancel_txn(pmu); | ||
722 | 714 | ||
723 | return -EAGAIN; | 715 | return -EAGAIN; |
724 | } | 716 | } |
@@ -4965,6 +4957,31 @@ static LIST_HEAD(pmus); | |||
4965 | static DEFINE_MUTEX(pmus_lock); | 4957 | static DEFINE_MUTEX(pmus_lock); |
4966 | static struct srcu_struct pmus_srcu; | 4958 | static struct srcu_struct pmus_srcu; |
4967 | 4959 | ||
4960 | static void perf_pmu_nop_void(struct pmu *pmu) | ||
4961 | { | ||
4962 | } | ||
4963 | |||
4964 | static int perf_pmu_nop_int(struct pmu *pmu) | ||
4965 | { | ||
4966 | return 0; | ||
4967 | } | ||
4968 | |||
4969 | static void perf_pmu_start_txn(struct pmu *pmu) | ||
4970 | { | ||
4971 | perf_pmu_disable(pmu); | ||
4972 | } | ||
4973 | |||
4974 | static int perf_pmu_commit_txn(struct pmu *pmu) | ||
4975 | { | ||
4976 | perf_pmu_enable(pmu); | ||
4977 | return 0; | ||
4978 | } | ||
4979 | |||
4980 | static void perf_pmu_cancel_txn(struct pmu *pmu) | ||
4981 | { | ||
4982 | perf_pmu_enable(pmu); | ||
4983 | } | ||
4984 | |||
4968 | int perf_pmu_register(struct pmu *pmu) | 4985 | int perf_pmu_register(struct pmu *pmu) |
4969 | { | 4986 | { |
4970 | int ret; | 4987 | int ret; |
@@ -4974,6 +4991,29 @@ int perf_pmu_register(struct pmu *pmu) | |||
4974 | pmu->pmu_disable_count = alloc_percpu(int); | 4991 | pmu->pmu_disable_count = alloc_percpu(int); |
4975 | if (!pmu->pmu_disable_count) | 4992 | if (!pmu->pmu_disable_count) |
4976 | goto unlock; | 4993 | goto unlock; |
4994 | |||
4995 | if (!pmu->start_txn) { | ||
4996 | if (pmu->pmu_enable) { | ||
4997 | /* | ||
4998 | * If we have pmu_enable/pmu_disable calls, install | ||
4999 | * transaction stubs that use that to try and batch | ||
5000 | * hardware accesses. | ||
5001 | */ | ||
5002 | pmu->start_txn = perf_pmu_start_txn; | ||
5003 | pmu->commit_txn = perf_pmu_commit_txn; | ||
5004 | pmu->cancel_txn = perf_pmu_cancel_txn; | ||
5005 | } else { | ||
5006 | pmu->start_txn = perf_pmu_nop_void; | ||
5007 | pmu->commit_txn = perf_pmu_nop_int; | ||
5008 | pmu->cancel_txn = perf_pmu_nop_void; | ||
5009 | } | ||
5010 | } | ||
5011 | |||
5012 | if (!pmu->pmu_enable) { | ||
5013 | pmu->pmu_enable = perf_pmu_nop_void; | ||
5014 | pmu->pmu_disable = perf_pmu_nop_void; | ||
5015 | } | ||
5016 | |||
4977 | list_add_rcu(&pmu->entry, &pmus); | 5017 | list_add_rcu(&pmu->entry, &pmus); |
4978 | ret = 0; | 5018 | ret = 0; |
4979 | unlock: | 5019 | unlock: |