]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] Fix problem introduced by do_div() patch
authorBernardo Innocenti <bernie@develer.com>
Tue, 8 Jul 2003 09:19:51 +0000 (02:19 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Tue, 8 Jul 2003 09:19:51 +0000 (02:19 -0700)
 - 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.

include/asm-generic/div64.h
include/linux/compiler.h
lib/div64.c

index 292b5a8404315484e43142482833154175949e05..b0b1805a74191631b5157c3c36d695d31bc2acce 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/compiler.h>
 
 #if BITS_PER_LONG == 64
 
 
 #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                                          \
index 4ef20f517d27f3d47f07f49f600f98a80e49d7a4..95baf96090d993100419fa2846924ee78e5c1a6d 100644 (file)
 #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)                                   \
index eab47437f18252d9ea06aacdf0ba62d8c4ec30a8..d8c699e1f70ec76236227677af5b886ac4e6c7f6 100644 (file)
  * 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 @@ uint32_t __div64_32(uint64_t *n, uint32_t base)
        return rem;
 }
 
+EXPORT_SYMBOL(__div64_32);
+
+#endif /* BITS_PER_LONG == 32 */