Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

math64: New separate div64_u64_rem helper

Commit f792685006274a850e6cc0ea9ade275ccdfc90bc ("math64: New
div64_u64_rem helper") implemented div64_u64 in terms of div64_u64_rem.
But div64_u64_rem was removed because it slowed down div64_u64 (and
there were no other users of div64_u64_rem).

Device Mapper's I/O statistics support has a need for div64_u64_rem;
reintroduce this helper as a separate method that doesn't slow down
div64_u64, especially on 32-bit systems.

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Cc: Stanislaw Gruszka <sgruszka@redhat.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

+53
+13
include/linux/math64.h
··· 31 31 } 32 32 33 33 /** 34 + * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder 35 + */ 36 + static inline u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder) 37 + { 38 + *remainder = dividend % divisor; 39 + return dividend / divisor; 40 + } 41 + 42 + /** 34 43 * div64_u64 - unsigned 64bit divide with 64bit divisor 35 44 */ 36 45 static inline u64 div64_u64(u64 dividend, u64 divisor) ··· 70 61 71 62 #ifndef div_s64_rem 72 63 extern s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder); 64 + #endif 65 + 66 + #ifndef div64_u64_rem 67 + extern u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder); 73 68 #endif 74 69 75 70 #ifndef div64_u64
+40
lib/div64.c
··· 79 79 #endif 80 80 81 81 /** 82 + * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder 83 + * @dividend: 64bit dividend 84 + * @divisor: 64bit divisor 85 + * @remainder: 64bit remainder 86 + * 87 + * This implementation is a comparable to algorithm used by div64_u64. 88 + * But this operation, which includes math for calculating the remainder, 89 + * is kept distinct to avoid slowing down the div64_u64 operation on 32bit 90 + * systems. 91 + */ 92 + #ifndef div64_u64_rem 93 + u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder) 94 + { 95 + u32 high = divisor >> 32; 96 + u64 quot; 97 + 98 + if (high == 0) { 99 + u32 rem32; 100 + quot = div_u64_rem(dividend, divisor, &rem32); 101 + *remainder = rem32; 102 + } else { 103 + int n = 1 + fls(high); 104 + quot = div_u64(dividend >> n, divisor >> n); 105 + 106 + if (quot != 0) 107 + quot--; 108 + 109 + *remainder = dividend - quot * divisor; 110 + if (*remainder >= divisor) { 111 + quot++; 112 + *remainder -= divisor; 113 + } 114 + } 115 + 116 + return quot; 117 + } 118 + EXPORT_SYMBOL(div64_u64_rem); 119 + #endif 120 + 121 + /** 82 122 * div64_u64 - unsigned 64bit divide with 64bit divisor 83 123 * @dividend: 64bit dividend 84 124 * @divisor: 64bit divisor