diff options
author | Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | 2013-12-12 11:26:51 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-12-16 08:37:57 -0500 |
commit | fcc77f507333776eaa336ab4ff49c23422f53703 (patch) | |
tree | 5b1e158fc3da9b865d1bdbb89b7cb23936e6cb57 /arch/s390/kernel | |
parent | 69f239ed335a4b03265cae3ca930f3f166e42e35 (diff) |
s390/cpum_sf: Atomically reset trailer entry fields of sample-data-blocks
Ensure to reset the sample-data-block full indicator and the overflow counter
at the same time. This must be done atomically because the sampling hardware
is still active while full sample-data-block is processed.
Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/perf_cpum_sf.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c index ea1656073dac..9202f2858894 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c | |||
@@ -953,7 +953,7 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all) | |||
953 | struct hw_perf_event *hwc = &event->hw; | 953 | struct hw_perf_event *hwc = &event->hw; |
954 | struct hws_trailer_entry *te; | 954 | struct hws_trailer_entry *te; |
955 | unsigned long *sdbt; | 955 | unsigned long *sdbt; |
956 | unsigned long long event_overflow, sampl_overflow, num_sdb; | 956 | unsigned long long event_overflow, sampl_overflow, num_sdb, te_flags; |
957 | int done; | 957 | int done; |
958 | 958 | ||
959 | sdbt = (unsigned long *) TEAR_REG(hwc); | 959 | sdbt = (unsigned long *) TEAR_REG(hwc); |
@@ -990,9 +990,13 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all) | |||
990 | hw_collect_samples(event, sdbt, &event_overflow); | 990 | hw_collect_samples(event, sdbt, &event_overflow); |
991 | num_sdb++; | 991 | num_sdb++; |
992 | 992 | ||
993 | /* Reset trailer */ | 993 | /* Reset trailer (using compare-double-and-swap) */ |
994 | xchg(&te->overflow, 0); | 994 | do { |
995 | xchg((unsigned char *) te, 0x40); | 995 | te_flags = te->flags & ~SDB_TE_BUFFER_FULL_MASK; |
996 | te_flags |= SDB_TE_ALERT_REQ_MASK; | ||
997 | } while (!cmpxchg_double(&te->flags, &te->overflow, | ||
998 | te->flags, te->overflow, | ||
999 | te_flags, 0ULL)); | ||
996 | 1000 | ||
997 | /* Advance to next sample-data-block */ | 1001 | /* Advance to next sample-data-block */ |
998 | sdbt++; | 1002 | sdbt++; |