diff options
-rw-r--r-- | include/linux/perf_counter.h | 22 | ||||
-rw-r--r-- | kernel/perf_counter.c | 4 |
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(); |
1352 | unlock: | 1352 | unlock: |