mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-12 13:34:10 +08:00
9d2dcc8fc6
It is useful to get the running time of a thread. Doing so in an efficient manner can be important for performance of user applications. Avoiding system calls in `clock_gettime` when handling CLOCK_THREAD_CPUTIME_ID is important. Other clocks are handled in the VDSO, but CLOCK_THREAD_CPUTIME_ID falls back on the system call. CLOCK_THREAD_CPUTIME_ID is not handled in the VDSO since it would have costs associated with maintaining updated user space accessible time offsets. These offsets have to be updated everytime the a thread is scheduled/descheduled. However, for programs regularly checking the running time of a thread, this is a performance improvement. This patch takes a middle ground, and adds support for cap_user_time an optional feature of the perf_event API. This way costs are only incurred when the perf_event api is enabled. This is done the same way as it is in x86. Ultimately this allows calculating the thread running time in userspace on aarch64 as follows (adapted from perf_event_open manpage): u32 seq, time_mult, time_shift; u64 running, count, time_offset, quot, rem, delta; struct perf_event_mmap_page *pc; pc = buf; // buf is the perf event mmaped page as documented in the API. if (pc->cap_usr_time) { do { seq = pc->lock; barrier(); running = pc->time_running; count = readCNTVCT_EL0(); // Read ARM hardware clock. time_offset = pc->time_offset; time_mult = pc->time_mult; time_shift = pc->time_shift; barrier(); } while (pc->lock != seq); quot = (count >> time_shift); rem = count & (((u64)1 << time_shift) - 1); delta = time_offset + quot * time_mult + ((rem * time_mult) >> time_shift); running += delta; // running now has the current nanosecond level thread time. } Summary of changes in the patch: For aarch64 systems, make arch_perf_update_userpage update the timing information stored in the perf_event page. Requiring the following calculations: - Calculate the appropriate time_mult, and time_shift factors to convert ticks to nano seconds for the current clock frequency. - Adjust the mult and shift factors to avoid shift factors of 32 bits. (possibly unnecessary) - The time_offset userspace should apply when doing calculations: negative the current sched time (now), because time_running and time_enabled fields of the perf_event page have just been updated. Toggle bits to appropriate values: - Enable cap_user_time Signed-off-by: Michael O'Farrell <micpof@gmail.com> Signed-off-by: Will Deacon <will.deacon@arm.com> |
||
---|---|---|
.. | ||
probes | ||
vdso | ||
.gitignore | ||
acpi_numa.c | ||
acpi_parking_protocol.c | ||
acpi.c | ||
alternative.c | ||
arm64ksyms.c | ||
armv8_deprecated.c | ||
asm-offsets.c | ||
cacheinfo.c | ||
cpu_errata.c | ||
cpu_ops.c | ||
cpu-reset.h | ||
cpu-reset.S | ||
cpufeature.c | ||
cpuidle.c | ||
cpuinfo.c | ||
crash_dump.c | ||
debug-monitors.c | ||
efi-entry.S | ||
efi-header.S | ||
efi-rt-wrapper.S | ||
efi.c | ||
entry-fpsimd.S | ||
entry-ftrace.S | ||
entry.S | ||
fpsimd.c | ||
ftrace.c | ||
head.S | ||
hibernate-asm.S | ||
hibernate.c | ||
hw_breakpoint.c | ||
hyp-stub.S | ||
image.h | ||
insn.c | ||
io.c | ||
irq.c | ||
jump_label.c | ||
kaslr.c | ||
kgdb.c | ||
kuser32.S | ||
machine_kexec.c | ||
Makefile | ||
module-plts.c | ||
module.c | ||
module.lds | ||
paravirt.c | ||
pci.c | ||
perf_callchain.c | ||
perf_event.c | ||
perf_regs.c | ||
process.c | ||
psci.c | ||
ptrace.c | ||
reloc_test_core.c | ||
reloc_test_syms.S | ||
relocate_kernel.S | ||
return_address.c | ||
sdei.c | ||
setup.c | ||
signal32.c | ||
signal.c | ||
sleep.S | ||
smccc-call.S | ||
smp_spin_table.c | ||
smp.c | ||
ssbd.c | ||
stacktrace.c | ||
suspend.c | ||
sys32.c | ||
sys_compat.c | ||
sys.c | ||
syscall.c | ||
time.c | ||
topology.c | ||
trace-events-emulation.h | ||
traps.c | ||
vdso.c | ||
vmlinux.lds.S |