diff options
author | Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | 2013-12-12 17:26:51 +0100 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-12-16 14:37:57 +0100 |
commit | fcc77f507333776eaa336ab4ff49c23422f53703 (patch) | |
tree | 5b1e158fc3da9b865d1bdbb89b7cb23936e6cb57 /arch/s390/kernel | |
parent | 69f239ed335a4b03265cae3ca930f3f166e42e35 (diff) | |
download | talos-obmc-linux-fcc77f507333776eaa336ab4ff49c23422f53703.tar.gz talos-obmc-linux-fcc77f507333776eaa336ab4ff49c23422f53703.zip |
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) struct hw_perf_event *hwc = &event->hw; struct hws_trailer_entry *te; unsigned long *sdbt; - unsigned long long event_overflow, sampl_overflow, num_sdb; + unsigned long long event_overflow, sampl_overflow, num_sdb, te_flags; int done; sdbt = (unsigned long *) TEAR_REG(hwc); @@ -990,9 +990,13 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all) hw_collect_samples(event, sdbt, &event_overflow); num_sdb++; - /* Reset trailer */ - xchg(&te->overflow, 0); - xchg((unsigned char *) te, 0x40); + /* Reset trailer (using compare-double-and-swap) */ + do { + te_flags = te->flags & ~SDB_TE_BUFFER_FULL_MASK; + te_flags |= SDB_TE_ALERT_REQ_MASK; + } while (!cmpxchg_double(&te->flags, &te->overflow, + te->flags, te->overflow, + te_flags, 0ULL)); /* Advance to next sample-data-block */ sdbt++; |