Commit 19665252 authored by Bernardo Innocenti's avatar Bernardo Innocenti Committed by Linus Torvalds

[PATCH] Fix problem introduced by 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.
parent 6761d095
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/compiler.h>
#if BITS_PER_LONG == 64 #if BITS_PER_LONG == 64
...@@ -31,12 +32,12 @@ ...@@ -31,12 +32,12 @@
#elif BITS_PER_LONG == 32 #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) ({ \ # define do_div(n,base) ({ \
uint32_t __base = (base); \ uint32_t __base = (base); \
uint32_t __rem; \ uint32_t __rem; \
if (((n) >> 32) == 0) { \ if (likely(((n) >> 32) == 0)) { \
__rem = (uint32_t)(n) % __base; \ __rem = (uint32_t)(n) % __base; \
(n) = (uint32_t)(n) / __base; \ (n) = (uint32_t)(n) / __base; \
} else \ } else \
......
...@@ -56,6 +56,24 @@ ...@@ -56,6 +56,24 @@
#define __attribute_used__ __attribute__((__unused__)) #define __attribute_used__ __attribute__((__unused__))
#endif #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 /* This macro obfuscates arithmetic on a variable address so that gcc
shouldn't recognize the original var, and make assumptions about it */ shouldn't recognize the original var, and make assumptions about it */
#define RELOC_HIDE(ptr, off) \ #define RELOC_HIDE(ptr, off) \
......
...@@ -12,13 +12,17 @@ ...@@ -12,13 +12,17 @@
* The fast case for (n>>32 == 0) is handled inline by do_div(). * The fast case for (n>>32 == 0) is handled inline by do_div().
* *
* Code generated for this function might be very inefficient * 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. * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S.
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/module.h>
#include <asm/div64.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 __div64_32(uint64_t *n, uint32_t base)
{ {
uint32_t low, low2, high, rem; uint32_t low, low2, high, rem;
...@@ -43,3 +47,6 @@ uint32_t __div64_32(uint64_t *n, uint32_t base) ...@@ -43,3 +47,6 @@ uint32_t __div64_32(uint64_t *n, uint32_t base)
return rem; return rem;
} }
EXPORT_SYMBOL(__div64_32);
#endif /* BITS_PER_LONG == 32 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment