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

Submitted by Andrey Ryabinin on Nov. 3, 2020, 3:02 p.m.

Details

Message ID 20201103150247.23486-1-aryabinin@virtuozzo.com
State New
Series "x86_64, vclock_gettime: Use standart division instead of __iter_div_u64_rem()"
Headers show

Commit Message

Andrey Ryabinin Nov. 3, 2020, 3:02 p.m.
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.

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;