Messages in this thread | | | Date | Mon, 1 Aug 2022 09:17:55 -0300 | From | Arnaldo Carvalho de Melo <> | Subject | Re: [PATCH v3 1/3] perf: Align user space counter reading with code |
| |
Em Tue, Jul 19, 2022 at 03:39:44PM -0700, Ian Rogers escreveu: > Align the user space counter reading documentation with the code in > perf_mmap__read_self. Previously the documentation was based on the perf > rdpmc test, but now general purpose code is provided by libperf.
Peter, can you merge this so as not to make Linus raise eyebrows with me processing things outside tools/perf/ when asking him to pull perf userspace?
- Arnaldo
> Signed-off-by: Ian Rogers <irogers@google.com> > --- > include/uapi/linux/perf_event.h | 35 +++++++++++++++++---------- > tools/include/uapi/linux/perf_event.h | 35 +++++++++++++++++---------- > 2 files changed, 44 insertions(+), 26 deletions(-) > > diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h > index d37629dbad72..6826dabb7e03 100644 > --- a/include/uapi/linux/perf_event.h > +++ b/include/uapi/linux/perf_event.h > @@ -538,9 +538,13 @@ struct perf_event_mmap_page { > * > * if (pc->cap_usr_time && enabled != running) { > * cyc = rdtsc(); > - * time_offset = pc->time_offset; > * time_mult = pc->time_mult; > * time_shift = pc->time_shift; > + * time_offset = pc->time_offset; > + * if (pc->cap_user_time_short) { > + * time_cycles = pc->time_cycles; > + * time_mask = pc->time_mask; > + * } > * } > * > * index = pc->index; > @@ -548,6 +552,9 @@ struct perf_event_mmap_page { > * if (pc->cap_user_rdpmc && index) { > * width = pc->pmc_width; > * pmc = rdpmc(index - 1); > + * pmc <<= 64 - width; > + * pmc >>= 64 - width; > + * count += pmc; > * } > * > * barrier(); > @@ -590,25 +597,27 @@ struct perf_event_mmap_page { > * If cap_usr_time the below fields can be used to compute the time > * delta since time_enabled (in ns) using rdtsc or similar. > * > - * u64 quot, rem; > - * u64 delta; > - * > - * quot = (cyc >> time_shift); > - * rem = cyc & (((u64)1 << time_shift) - 1); > - * delta = time_offset + quot * time_mult + > - * ((rem * time_mult) >> time_shift); > + * cyc = time_cycles + ((cyc - time_cycles) & time_mask); > + * delta = time_offset + mul_u64_u32_shr(cyc, time_mult, time_shift); > * > * Where time_offset,time_mult,time_shift and cyc are read in the > - * seqcount loop described above. This delta can then be added to > - * enabled and possible running (if index), improving the scaling: > + * seqcount loop described above. mul_u64_u32_shr will compute: > + * > + * (u64)(((unsigned __int128)cyc * time_mult) >> time_shift) > + * > + * This delta can then be added to enabled and possible running (if > + * index) to improve the scaling. Due to event multiplexing, running > + * may be zero and so care is needed to avoid division by zero. > * > * enabled += delta; > * if (index) > * running += delta; > * > - * quot = count / running; > - * rem = count % running; > - * count = quot * enabled + (rem * enabled) / running; > + * if (running != 0) { > + * quot = count / running; > + * rem = count % running; > + * count = quot * enabled + (rem * enabled) / running; > + * } > */ > __u16 time_shift; > __u32 time_mult; > diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h > index d37629dbad72..6826dabb7e03 100644 > --- a/tools/include/uapi/linux/perf_event.h > +++ b/tools/include/uapi/linux/perf_event.h > @@ -538,9 +538,13 @@ struct perf_event_mmap_page { > * > * if (pc->cap_usr_time && enabled != running) { > * cyc = rdtsc(); > - * time_offset = pc->time_offset; > * time_mult = pc->time_mult; > * time_shift = pc->time_shift; > + * time_offset = pc->time_offset; > + * if (pc->cap_user_time_short) { > + * time_cycles = pc->time_cycles; > + * time_mask = pc->time_mask; > + * } > * } > * > * index = pc->index; > @@ -548,6 +552,9 @@ struct perf_event_mmap_page { > * if (pc->cap_user_rdpmc && index) { > * width = pc->pmc_width; > * pmc = rdpmc(index - 1); > + * pmc <<= 64 - width; > + * pmc >>= 64 - width; > + * count += pmc; > * } > * > * barrier(); > @@ -590,25 +597,27 @@ struct perf_event_mmap_page { > * If cap_usr_time the below fields can be used to compute the time > * delta since time_enabled (in ns) using rdtsc or similar. > * > - * u64 quot, rem; > - * u64 delta; > - * > - * quot = (cyc >> time_shift); > - * rem = cyc & (((u64)1 << time_shift) - 1); > - * delta = time_offset + quot * time_mult + > - * ((rem * time_mult) >> time_shift); > + * cyc = time_cycles + ((cyc - time_cycles) & time_mask); > + * delta = time_offset + mul_u64_u32_shr(cyc, time_mult, time_shift); > * > * Where time_offset,time_mult,time_shift and cyc are read in the > - * seqcount loop described above. This delta can then be added to > - * enabled and possible running (if index), improving the scaling: > + * seqcount loop described above. mul_u64_u32_shr will compute: > + * > + * (u64)(((unsigned __int128)cyc * time_mult) >> time_shift) > + * > + * This delta can then be added to enabled and possible running (if > + * index) to improve the scaling. Due to event multiplexing, running > + * may be zero and so care is needed to avoid division by zero. > * > * enabled += delta; > * if (index) > * running += delta; > * > - * quot = count / running; > - * rem = count % running; > - * count = quot * enabled + (rem * enabled) / running; > + * if (running != 0) { > + * quot = count / running; > + * rem = count % running; > + * count = quot * enabled + (rem * enabled) / running; > + * } > */ > __u16 time_shift; > __u32 time_mult; > -- > 2.37.0.170.g444d1eabd0-goog
--
- Arnaldo
| |