Messages in this thread Patch in this message | | | Date | Thu, 23 Oct 2003 21:20:03 -0700 | From | Randolph Chung <> | Subject | [patch] fix __div64_32 to do division properly |
| |
The generic __div64_32 in lib/div64.c only handles "small" divisors. If the divisor is full 32-bits, it returns invalid results. This patch fixes it. (this is used e.g. in nanosleep)
thanks randolph
Index: lib/div64.c =================================================================== RCS file: /var/cvs/linux-2.6/lib/div64.c,v retrieving revision 1.1 diff -u -p -r1.1 div64.c --- lib/div64.c 29 Jul 2003 17:02:19 -0000 1.1 +++ lib/div64.c 24 Oct 2003 04:10:59 -0000 @@ -25,25 +25,27 @@ uint32_t __div64_32(uint64_t *n, uint32_t base) { - uint32_t low, low2, high, rem; + uint64_t rem = *n; + uint64_t b = base; + uint64_t res = 0, d = 1; - low = *n & 0xffffffff; - high = *n >> 32; - rem = high % (uint32_t)base; - high = high / (uint32_t)base; - low2 = low >> 16; - low2 += rem << 16; - rem = low2 % (uint32_t)base; - low2 = low2 / (uint32_t)base; - low = low & 0xffff; - low += rem << 16; - rem = low % (uint32_t)base; - low = low / (uint32_t)base; + if (b > 0) { + while (b < rem) { + b <<= 1; + d <<= 1; + } + } - *n = low + - ((uint64_t)low2 << 16) + - ((uint64_t)high << 32); + do { + if (rem >= b) { + rem -= b; + res += d; + } + b >>= 1; + d >>= 1; + } while (d); + *n = res; return rem; } -- Randolph Chung Debian GNU/Linux Developer, hppa/ia64 ports http://www.tausq.org/ - 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/
| |