aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/perf_counter.h22
-rw-r--r--kernel/perf_counter.c4
2 files changed, 12 insertions, 14 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index 90cce0c74a03..f2b914de3f0c 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -167,30 +167,28 @@ struct perf_counter_mmap_page {
167 /* 167 /*
168 * Bits needed to read the hw counters in user-space. 168 * Bits needed to read the hw counters in user-space.
169 * 169 *
170 * The index and offset should be read atomically using the seqlock: 170 * u32 seq;
171 * 171 * s64 count;
172 * __u32 seq, index;
173 * __s64 offset;
174 * 172 *
175 * again: 173 * again:
176 * rmb();
177 * seq = pc->lock; 174 * seq = pc->lock;
178 *
179 * if (unlikely(seq & 1)) { 175 * if (unlikely(seq & 1)) {
180 * cpu_relax(); 176 * cpu_relax();
181 * goto again; 177 * goto again;
182 * } 178 * }
183 * 179 *
184 * index = pc->index; 180 * if (pc->index) {
185 * offset = pc->offset; 181 * count = pmc_read(pc->index - 1);
182 * count += pc->offset;
183 * } else
184 * goto regular_read;
186 * 185 *
187 * rmb(); 186 * barrier();
188 * if (pc->lock != seq) 187 * if (pc->lock != seq)
189 * goto again; 188 * goto again;
190 * 189 *
191 * After this, index contains architecture specific counter index + 1, 190 * NOTE: for obvious reason this only works on self-monitoring
192 * so that 0 means unavailable, offset contains the value to be added 191 * processes.
193 * to the result of the raw timer read to obtain this counter's value.
194 */ 192 */
195 __u32 lock; /* seqlock for synchronization */ 193 __u32 lock; /* seqlock for synchronization */
196 __u32 index; /* hardware counter identifier */ 194 __u32 index; /* hardware counter identifier */
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index f105a6e696c2..2a5d4f525567 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -1340,13 +1340,13 @@ void perf_counter_update_userpage(struct perf_counter *counter)
1340 */ 1340 */
1341 preempt_disable(); 1341 preempt_disable();
1342 ++userpg->lock; 1342 ++userpg->lock;
1343 smp_wmb(); 1343 barrier();
1344 userpg->index = counter->hw.idx; 1344 userpg->index = counter->hw.idx;
1345 userpg->offset = atomic64_read(&counter->count); 1345 userpg->offset = atomic64_read(&counter->count);
1346 if (counter->state == PERF_COUNTER_STATE_ACTIVE) 1346 if (counter->state == PERF_COUNTER_STATE_ACTIVE)
1347 userpg->offset -= atomic64_read(&counter->hw.prev_count); 1347 userpg->offset -= atomic64_read(&counter->hw.prev_count);
1348 1348
1349 smp_wmb(); 1349 barrier();
1350 ++userpg->lock; 1350 ++userpg->lock;
1351 preempt_enable(); 1351 preempt_enable();
1352unlock: 1352unlock: