Page MenuHomeFreeBSD

D40120.id122012.diff
No OneTemporary

D40120.id122012.diff

diff --git a/sys/compat/linuxkpi/common/include/linux/math64.h b/sys/compat/linuxkpi/common/include/linux/math64.h
--- a/sys/compat/linuxkpi/common/include/linux/math64.h
+++ b/sys/compat/linuxkpi/common/include/linux/math64.h
@@ -31,6 +31,7 @@
#define _LINUXKPI_LINUX_MATH64_H
#include <sys/stdint.h>
+#include <linux/log2.h>
#define do_div(n, base) ({ \
uint32_t __base = (base); \
@@ -108,6 +109,41 @@
return ((x / div) * y + (rem * y) / div);
}
+static inline uint64_t
+mul_u64_u64_div_u64(uint64_t x, uint64_t y, uint64_t z)
+{
+ uint64_t res;
+
+ res = 0;
+ /* Overflow on x * y possible? */
+ if ((ilog2(x) + ilog2(y)) > 62) {
+ uint64_t remainder;
+ int d;
+
+ /*
+ * Do: (y / z) * x; y = y % z.
+ * If we overflow the result will never fit. Otherwise the final
+ * div64_u64() will do the x * y / z missing we already prepared
+ * for the final result of (y % z) * x / z in addition to res.
+ */
+ res = div64_u64_rem(y, z, &remainder);
+ res *= x;
+ y = remainder;
+
+ /* Re-check with new y. */
+ d = ilog2(x) + ilog2(y) - 62;
+ if (d > 0) {
+ /* We cannot help anymore. Reduce precision. */
+ y >>= d;
+ z >>= d;
+ /* Avoid div0. */
+ if (z == 0)
+ return (res);
+ }
+ }
+ return (res + div64_u64(x * y, z));
+}
+
static inline uint64_t
mul_u64_u32_shr(uint64_t x, uint32_t y, unsigned int shift)
{

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 31, 4:40 AM (15 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28108428
Default Alt Text
D40120.id122012.diff (1 KB)

Event Timeline