Oops. He didn't remove it, he just picked up my older version
which also missed an important bug fix.
Here's an incremental patch against 2.5.74-bk4. Please apply.
---------------------------------------------------------------------
Fix problem introduced by previous do_div() patch:
- export the __div64_32 symbol for modules;
- add likely() to the fast path (divisor>>32 == 0);
- add __attribute__((pure)) to __div64_32() prototype so
the compiler knows global memory isn't clobbered;
- avoid building __div64_32() on 64bit architectures.
diff -Nru linux-2.5.74-bk4.orig/include/asm-generic/div64.h linux-2.5.74-bk4/include/asm-generic/div64.h
--- linux-2.5.74-bk4.orig/include/asm-generic/div64.h 2003-07-08 22:29:32.000000000 +0200
+++ linux-2.5.74-bk4/include/asm-generic/div64.h 2003-07-08 22:45:21.000000000 +0200
@@ -18,6 +18,7 @@
*/
#include <linux/types.h>
+#include <linux/compiler.h>
#if BITS_PER_LONG == 64
@@ -31,12 +32,12 @@
#elif BITS_PER_LONG == 32
-extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
+extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor) __attribute_pure__;
# define do_div(n,base) ({ \
uint32_t __base = (base); \
uint32_t __rem; \
- if (((n) >> 32) == 0) { \
+ if (likely(((n) >> 32) == 0)) { \
__rem = (uint32_t)(n) % __base; \
(n) = (uint32_t)(n) / __base; \
} else \
diff -Nru linux-2.5.74-bk4.orig/include/linux/compiler.h linux-2.5.74-bk4/include/linux/compiler.h
--- linux-2.5.74-bk4.orig/include/linux/compiler.h 2003-07-08 22:23:25.000000000 +0200
+++ linux-2.5.74-bk4/include/linux/compiler.h 2003-07-08 22:45:21.000000000 +0200
@@ -56,6 +56,24 @@
#define __attribute_used__ __attribute__((__unused__))
#endif
+/*
+ * From the GCC manual:
+ *
+ * Many functions have no effects except the return value and their
+ * return value depends only on the parameters and/or global
+ * variables. Such a function can be subject to common subexpression
+ * elimination and loop optimization just as an arithmetic operator
+ * would be.
+ * [...]
+ * The attribute `pure' is not implemented in GCC versions earlier
+ * than 2.96.
+ */
+#if (__GNUC__ == 2 && __GNUC_MINOR >= 96) || __GNUC__ > 2
+#define __attribute_pure__ __attribute__((pure))
+#else
+#define __attribute_pure__ /* unimplemented */
+#endif
+
/* This macro obfuscates arithmetic on a variable address so that gcc
shouldn't recognize the original var, and make assumptions about it */
#define RELOC_HIDE(ptr, off) \
diff -Nru linux-2.5.74-bk4.orig/lib/div64.c linux-2.5.74-bk4/lib/div64.c
--- linux-2.5.74-bk4.orig/lib/div64.c 2003-07-08 22:29:32.000000000 +0200
+++ linux-2.5.74-bk4/lib/div64.c 2003-07-08 22:45:21.000000000 +0200
@@ -12,13 +12,17 @@
* The fast case for (n>>32 == 0) is handled inline by do_div().
*
* Code generated for this function might be very inefficient
- * for some CPUs. div64_32() can be overridden by linking arch-specific
+ * for some CPUs. __div64_32() can be overridden by linking arch-specific
* assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S.
*/
#include <linux/types.h>
+#include <linux/module.h>
#include <asm/div64.h>
+/* Not needed on 64bit architectures */
+#if BITS_PER_LONG == 32
+
uint32_t __div64_32(uint64_t *n, uint32_t base)
{
uint32_t low, low2, high, rem;
@@ -43,3 +47,6 @@
return rem;
}
+EXPORT_SYMBOL(__div64_32);
+
+#endif /* BITS_PER_LONG == 32 */
-- // Bernardo Innocenti - Develer S.r.l., R&D dept. \X/ http://www.develer.com/Please don't send Word attachments - http://www.gnu.org/philosophy/no-word-attachments.html
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/