linux/compat/include/linux/poison.h \
linux/compat/include/linux/rculist.h \
linux/compat/include/linux/rcupdate.h \
+ linux/compat/include/linux/reciprocal_div.h \
linux/compat/include/linux/rtnetlink.h \
linux/compat/include/linux/sctp.h \
linux/compat/include/linux/skbuff.h \
--- /dev/null
+#ifndef _LINUX_RECIPROCAL_DIV_WRAPPER_H
+#define _LINUX_RECIPROCAL_DIV_WRAPPER_H 1
+
+#include <linux/types.h>
+
+/*
+ * This algorithm is based on the paper "Division by Invariant
+ * Integers Using Multiplication" by Torbjörn Granlund and Peter
+ * L. Montgomery.
+ *
+ * The assembler implementation from Agner Fog, which this code is
+ * based on, can be found here:
+ * http://www.agner.org/optimize/asmlib.zip
+ *
+ * This optimization for A/B is helpful if the divisor B is mostly
+ * runtime invariant. The reciprocal of B is calculated in the
+ * slow-path with reciprocal_value(). The fast-path can then just use
+ * a much faster multiplication operation with a variable dividend A
+ * to calculate the division A/B.
+ */
+
+#define reciprocal_value rpl_reciprocal_value
+struct reciprocal_value {
+ u32 m;
+ u8 sh1, sh2;
+};
+
+struct reciprocal_value reciprocal_value(u32 d);
+
+#define reciprocal_divide rpl_reciprocal_divide
+static inline u32 reciprocal_divide(u32 a, struct reciprocal_value R)
+{
+ u32 t = (u32)(((u64)a * R.m) >> 32);
+ return (t + ((a - t) >> R.sh1)) >> R.sh2;
+}
+
+#endif /* _LINUX_RECIPROCAL_DIV_WRAPPER_H */
+#include <linux/kernel.h>
#include <asm/div64.h>
#include <linux/reciprocal_div.h>
-#include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
-/* definition is required since reciprocal_value() is not exported */
-u32 reciprocal_value(u32 k)
+/*
+ * For a description of the algorithm please have a look at
+ * include/linux/reciprocal_div.h
+ */
+
+struct reciprocal_value reciprocal_value(u32 d)
{
- u64 val = (1LL << 32) + (k - 1);
- do_div(val, k);
- return (u32)val;
+ struct reciprocal_value R;
+ u64 m;
+ int l;
+
+ l = fls(d - 1);
+ m = ((1ULL << 32) * ((1ULL << l) - d));
+ do_div(m, d);
+ ++m;
+ R.m = (u32)m;
+ R.sh1 = min(l, 1);
+ R.sh2 = max(l - 1, 0);
+
+ return R;
}
-#endif