[RHEL8,COMMIT] x86_64, vclock_gettime: Use standart division instead of __iter_div_u64_rem()

Submitted by Konstantin Khorenko on Nov. 6, 2020, 2:31 p.m.

Details

Message ID 202011061431.0A6EVDMU2053434@finist-co8.sw.ru
State New
Series "x86_64, vclock_gettime: Use standart division instead of __iter_div_u64_rem()"
Headers show

Commit Message

Konstantin Khorenko Nov. 6, 2020, 2:31 p.m.
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@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@virtuozzo.com>
---
 arch/x86/entry/vdso/vclock_gettime.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

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;