[Devel] [PATCH RHEL8 COMMIT] x86_64, vclock_gettime: Use standart division instead of __iter_div_u64_rem()
Konstantin Khorenko
khorenko at virtuozzo.com
Fri Nov 6 17:31:13 MSK 2020
The commit is pushed to "work" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-193.6.3.vz8.4.16
------>
commit b2c945177c8f0933ed37ad7f181a5be71458111a
Author: Andrey Ryabinin <aryabinin at virtuozzo.com>
Date: Fri Nov 6 17:31:13 2020 +0300
x86_64, vclock_gettime: Use standart division instead of __iter_div_u64_rem()
timespec_sub_ns() historically uses __iter_div_u64_rem() for division.
Probably it's supposed to be faster
/*
* Iterative div/mod for use when dividend is not expected to be much
* bigger than divisor.
*/
u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
However in our case ve_start_time may make dividend much bigger than divisor.
So let's use standard "/" instead of iterative one. With 0 ve_start_time
I wasn't able to see measurable difference, however with big ve_start_time
the difference is rather significant:
# time ./clock_iter_div
real 1m30.224s
user 1m30.343s
sys 0m0.008s
# time taskset ./clock_div
real 0m2.757s
user 0m1.730s
sys 0m0.066s
32-bit vdso doesn't like 64-bit division and doesn't link.
I think it needs __udivsi3(). So just fallback to __iter_div_u64_rem()
on 32-bit.
Fixes: af2c78f571e6 ("ve: add per-ve CLOCK_MONOTONIC time via __vdso_gettimeofday()")
https://jira.sw.ru/browse/PSBM-121856
Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
---
arch/x86/entry/vdso/vclock_gettime.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/arch/x86/entry/vdso/vclock_gettime.c b/arch/x86/entry/vdso/vclock_gettime.c
index be1de6c4cafa..224dbe80da66 100644
--- a/arch/x86/entry/vdso/vclock_gettime.c
+++ b/arch/x86/entry/vdso/vclock_gettime.c
@@ -229,13 +229,27 @@ notrace static int __always_inline do_realtime(struct timespec *ts)
return mode;
}
+static inline u64 divu64(u64 dividend, u32 divisor, u64 *remainder)
+{
+ /* 32-bit wants __udivsi3() and fails to link, so fallback to iter */
+#ifndef BUILD_VDSO32
+ u64 res;
+
+ res = dividend/divisor;
+ *remainder = dividend % divisor;
+ return res;
+#else
+ return __iter_div_u64_rem(dividend, divisor, remainder);
+#endif
+}
+
static inline void timespec_sub_ns(struct timespec *ts, u64 ns)
{
if ((s64)ns <= 0) {
- ts->tv_sec += __iter_div_u64_rem(-ns, NSEC_PER_SEC, &ns);
+ ts->tv_sec += divu64(-ns, NSEC_PER_SEC, &ns);
ts->tv_nsec = ns;
} else {
- ts->tv_sec -= __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
+ ts->tv_sec -= divu64(ns, NSEC_PER_SEC, &ns);
if (ns) {
ts->tv_sec--;
ns = NSEC_PER_SEC - ns;
More information about the Devel
mailing list