[Devel,RHEL7,COMMIT] ms/math64: add function to multiply and then divide u64 to u32-s

Submitted by Konstantin Khorenko on Oct. 24, 2016, 12:07 p.m.

Details

Message ID 201610241207.u9OC7AuM023194@finist_cl7.x64_64.work.ct
State New
Series "ms/math64: add function to multiply and then divide u64 to u32-s"
Headers show

Commit Message

Konstantin Khorenko Oct. 24, 2016, 12:07 p.m.
The commit is pushed to "branch-rh7-3.10.0-327.36.1.vz7.19.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.36.1.vz7.19.3
------>
commit 6a37864fdce506e5d6c409450e7615f78efb6719
Author: Denis Plotnikov <dplotnikov@virtuozzo.com>
Date:   Mon Oct 24 16:07:10 2016 +0400

    ms/math64: add function to multiply and then divide u64 to u32-s
    
    The function returns 64 lowest digits of the operation result with
    loss of the higher than 64 orders of magnitude.
    
    The function added as a part of Hyper-V TSC reference page clock porting
    https://jira.sw.ru/browse/PSBM-46245
    
    It was initially introduced in commit 381d585c80e34988269bd7901ad910981e900be1
    by Haozhong Zhang <haozhong.zhang@intel.com>
    
    Signed-off-by: Denis Plotnikov <dplotnikov@virtuozzo.com>
    Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
    Signed-off-by: "Denis V. Lunev" <den@openvz.org>
---
 include/linux/math64.h | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

Patch hide | download patch | download mbox

diff --git a/include/linux/math64.h b/include/linux/math64.h
index 44282ec..0264dbb 100644
--- a/include/linux/math64.h
+++ b/include/linux/math64.h
@@ -214,4 +214,33 @@  static inline u64 mul_u64_u64_shr(u64 a, u64 b, unsigned int shift)
 
 #endif
 
+#ifndef mul_u64_u32_div
+static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
+{
+	union {
+		u64 ll;
+		struct {
+#ifdef __BIG_ENDIAN
+			u32 high, low;
+#else
+			u32 low, high;
+#endif
+		} l;
+	} u, rl, rh;
+
+	u.ll = a;
+	rl.ll = (u64)u.l.low * mul;
+	rh.ll = (u64)u.l.high * mul + rl.l.high;
+
+	/* Bits 32-63 of the result will be in rh.l.low. */
+	rl.l.high = do_div(rh.ll, divisor);
+
+	/* Bits 0-31 of the result will be in rl.l.low. */
+	do_div(rl.ll, divisor);
+
+	rl.l.high = rh.l.low;
+	return rl.ll;
+}
+#endif /* mul_u64_u32_div */
+
 #endif /* _LINUX_MATH64_H */