linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* do_div vs sector_t
@ 2003-07-11 22:33 Matthew Wilcox
  2003-07-11 22:34 ` Andrew Morton
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Matthew Wilcox @ 2003-07-11 22:33 UTC (permalink / raw)
  To: Bernardo Innocenti; +Cc: Andrew Morton, linux-kernel


# define do_div(n,base) ({                              \
        uint32_t __base = (base);                       \
        uint32_t __rem;                                 \
        if (likely(((n) >> 32) == 0)) {                 \

so if we call do_div() on a u32, the compiler emits nasal daemons.
and we do this -- in the antcipatory scheduler:

                if (aic->seek_samples) {
                        aic->seek_mean = aic->seek_total + 128;
                        do_div(aic->seek_mean, aic->seek_samples);
                }

seek_mean is a sector_t so sometimes it's 64-bit on a 32-bit platform.
so we can't avoid calling do_div().

This almost works (the warning is harmless since gcc optimises away the call)

# define do_div(n,base) ({                                              \
        uint32_t __base = (base);                                       \
        uint32_t __rem;                                                 \
        if ((sizeof(n) < 8) || (likely(((n) >> 32) == 0))) {            \
                __rem = (uint32_t)(n) % __base;                         \
                (n) = (uint32_t)(n) / __base;                           \
        } else                                                          \
                __rem = __div64_32(&(n), __base);                       \
        __rem;                                                          \
 })

Better ideas?

-- 
"It's not Hollywood.  War is real, war is primarily not about defeat or
victory, it is about death.  I've seen thousands and thousands of dead bodies.
Do you think I want to have an academic debate on this subject?" -- Robert Fisk

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: do_div vs sector_t
  2003-07-11 22:33 do_div vs sector_t Matthew Wilcox
@ 2003-07-11 22:34 ` Andrew Morton
  2003-07-11 22:42 ` Neil Brown
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Andrew Morton @ 2003-07-11 22:34 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: bernie, akpm, linux-kernel

Matthew Wilcox <willy@debian.org> wrote:
>
> This almost works (the warning is harmless since gcc optimises away the call)
> 
> # define do_div(n,base) ({                                              \
>         uint32_t __base = (base);                                       \
>         uint32_t __rem;                                                 \
>         if ((sizeof(n) < 8) || (likely(((n) >> 32) == 0))) {            \
>                 __rem = (uint32_t)(n) % __base;                         \
>                 (n) = (uint32_t)(n) / __base;                           \
>         } else                                                          \
>                 __rem = __div64_32(&(n), __base);                       \
>         __rem;                                                          \
>  })

Could we just do:

diff -puN include/asm-generic/div64.h~do_div-fix-43 include/asm-generic/div64.h
--- 25/include/asm-generic/div64.h~do_div-fix-43	Fri Jul 11 15:32:33 2003
+++ 25-akpm/include/asm-generic/div64.h	Fri Jul 11 15:33:26 2003
@@ -34,7 +34,8 @@
 
 extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
 
-# define do_div(n,base) ({				\
+# define do_div(_n,base) ({				\
+	uint64_t n = _n;				\
 	uint32_t __base = (base);			\
 	uint32_t __rem;					\
 	if (likely(((n) >> 32) == 0)) {			\
@@ -42,6 +43,7 @@ extern uint32_t __div64_32(uint64_t *div
 		(n) = (uint32_t)(n) / __base;		\
 	} else 						\
 		__rem = __div64_32(&(n), __base);	\
+	_n = n;						\
 	__rem;						\
  })
 

_




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: do_div vs sector_t
  2003-07-11 22:33 do_div vs sector_t Matthew Wilcox
  2003-07-11 22:34 ` Andrew Morton
@ 2003-07-11 22:42 ` Neil Brown
  2003-07-12  0:14   ` do_div vs sector_t (patch) Nick Piggin
  2003-07-12  6:52 ` do_div vs sector_t Christoph Hellwig
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Neil Brown @ 2003-07-11 22:42 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: Bernardo Innocenti, Andrew Morton, linux-kernel

On Friday July 11, willy@debian.org wrote:
> 
> # define do_div(n,base) ({                              \
>         uint32_t __base = (base);                       \
>         uint32_t __rem;                                 \
>         if (likely(((n) >> 32) == 0)) {                 \
> 
> so if we call do_div() on a u32, the compiler emits nasal daemons.
> and we do this -- in the antcipatory scheduler:
> 
>                 if (aic->seek_samples) {
>                         aic->seek_mean = aic->seek_total + 128;
>                         do_div(aic->seek_mean, aic->seek_samples);
>                 }
> 
> seek_mean is a sector_t so sometimes it's 64-bit on a 32-bit platform.
> so we can't avoid calling do_div().
> 
> This almost works (the warning is harmless since gcc optimises away the call)
> 
> # define do_div(n,base) ({                                              \
>         uint32_t __base = (base);                                       \
>         uint32_t __rem;                                                 \
>         if ((sizeof(n) < 8) || (likely(((n) >> 32) == 0))) {            \
>                 __rem = (uint32_t)(n) % __base;                         \
>                 (n) = (uint32_t)(n) / __base;                           \
>         } else                                                          \
>                 __rem = __div64_32(&(n), __base);                       \
>         __rem;                                                          \
>  })
> 
> Better ideas?

sector_div, defined in blkdev.h, is probably what you want.

NeilBrown

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: do_div vs sector_t (patch)
  2003-07-11 22:42 ` Neil Brown
@ 2003-07-12  0:14   ` Nick Piggin
  0 siblings, 0 replies; 12+ messages in thread
From: Nick Piggin @ 2003-07-12  0:14 UTC (permalink / raw)
  To: Neil Brown, Andrew Morton
  Cc: Matthew Wilcox, Bernardo Innocenti, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1647 bytes --]



Neil Brown wrote:

>On Friday July 11, willy@debian.org wrote:
>
>># define do_div(n,base) ({                              \
>>        uint32_t __base = (base);                       \
>>        uint32_t __rem;                                 \
>>        if (likely(((n) >> 32) == 0)) {                 \
>>
>>so if we call do_div() on a u32, the compiler emits nasal daemons.
>>and we do this -- in the antcipatory scheduler:
>>
>>                if (aic->seek_samples) {
>>                        aic->seek_mean = aic->seek_total + 128;
>>                        do_div(aic->seek_mean, aic->seek_samples);
>>                }
>>
>>seek_mean is a sector_t so sometimes it's 64-bit on a 32-bit platform.
>>so we can't avoid calling do_div().
>>
>>This almost works (the warning is harmless since gcc optimises away the call)
>>
>># define do_div(n,base) ({                                              \
>>        uint32_t __base = (base);                                       \
>>        uint32_t __rem;                                                 \
>>        if ((sizeof(n) < 8) || (likely(((n) >> 32) == 0))) {            \
>>                __rem = (uint32_t)(n) % __base;                         \
>>                (n) = (uint32_t)(n) / __base;                           \
>>        } else                                                          \
>>                __rem = __div64_32(&(n), __base);                       \
>>        __rem;                                                          \
>> })
>>
>>Better ideas?
>>
>
>sector_div, defined in blkdev.h, is probably what you want.
>

Looks right. Following patch alright?


[-- Attachment #2: as-do-div --]
[-- Type: text/plain, Size: 510 bytes --]

--- linux-2.5/drivers/block/as-iosched.c.orig	2003-07-12 10:12:20.000000000 +1000
+++ linux-2.5/drivers/block/as-iosched.c	2003-07-12 10:12:28.000000000 +1000
@@ -837,7 +837,7 @@ static void as_update_iohist(struct as_i
 		aic->seek_total += 256*seek_dist;
 		if (aic->seek_samples) {
 			aic->seek_mean = aic->seek_total + 128;
-			do_div(aic->seek_mean, aic->seek_samples);
+			sector_div(aic->seek_mean, aic->seek_samples);
 		}
 		aic->seek_samples = (aic->seek_samples>>1)
 					+ (aic->seek_samples>>2);

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: do_div vs sector_t
  2003-07-11 22:33 do_div vs sector_t Matthew Wilcox
  2003-07-11 22:34 ` Andrew Morton
  2003-07-11 22:42 ` Neil Brown
@ 2003-07-12  6:52 ` Christoph Hellwig
  2003-07-12  6:58   ` Andrew Morton
  2003-07-13 17:26 ` Richard Henderson
  2003-07-14  4:07 ` Peter Chubb
  4 siblings, 1 reply; 12+ messages in thread
From: Christoph Hellwig @ 2003-07-12  6:52 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: Bernardo Innocenti, Andrew Morton, linux-kernel

On Fri, Jul 11, 2003 at 11:33:59PM +0100, Matthew Wilcox wrote:
>                         aic->seek_mean = aic->seek_total + 128;
>                         do_div(aic->seek_mean, aic->seek_samples);
>                 }
> 
> seek_mean is a sector_t so sometimes it's 64-bit on a 32-bit platform.
> so we can't avoid calling do_div().

That's why we have sector_div, never use do_div on a sector_t.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: do_div vs sector_t
  2003-07-12  6:52 ` do_div vs sector_t Christoph Hellwig
@ 2003-07-12  6:58   ` Andrew Morton
  0 siblings, 0 replies; 12+ messages in thread
From: Andrew Morton @ 2003-07-12  6:58 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: willy, bernie, akpm, linux-kernel

Christoph Hellwig <hch@infradead.org> wrote:
>
> On Fri, Jul 11, 2003 at 11:33:59PM +0100, Matthew Wilcox wrote:
> >                         aic->seek_mean = aic->seek_total + 128;
> >                         do_div(aic->seek_mean, aic->seek_samples);
> >                 }
> > 
> > seek_mean is a sector_t so sometimes it's 64-bit on a 32-bit platform.
> > so we can't avoid calling do_div().
> 
> That's why we have sector_div, never use do_div on a sector_t.

Thing is, the arith in there can overflow with 32-bit sector_t anyway, so
we need 64-bit quantities regardless of the CONFIG_LBD setting.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: do_div vs sector_t
  2003-07-11 22:33 do_div vs sector_t Matthew Wilcox
                   ` (2 preceding siblings ...)
  2003-07-12  6:52 ` do_div vs sector_t Christoph Hellwig
@ 2003-07-13 17:26 ` Richard Henderson
  2003-07-13 17:39   ` Russell King
  2003-07-13 19:14   ` Bernardo Innocenti
  2003-07-14  4:07 ` Peter Chubb
  4 siblings, 2 replies; 12+ messages in thread
From: Richard Henderson @ 2003-07-13 17:26 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: Bernardo Innocenti, Andrew Morton, linux-kernel

On Fri, Jul 11, 2003 at 11:33:59PM +0100, Matthew Wilcox wrote:
> Better ideas?

          if (likely(((n) >> 31 >> 1) == 0)) {


r~

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: do_div vs sector_t
  2003-07-13 17:26 ` Richard Henderson
@ 2003-07-13 17:39   ` Russell King
  2003-07-13 19:14   ` Bernardo Innocenti
  1 sibling, 0 replies; 12+ messages in thread
From: Russell King @ 2003-07-13 17:39 UTC (permalink / raw)
  To: Matthew Wilcox, Bernardo Innocenti, Andrew Morton, linux-kernel

On Sun, Jul 13, 2003 at 10:26:23AM -0700, Richard Henderson wrote:
> On Fri, Jul 11, 2003 at 11:33:59PM +0100, Matthew Wilcox wrote:
> > Better ideas?
> 
>           if (likely(((n) >> 31 >> 1) == 0)) {
> 

Beware - luckily I don't have to worry about that on ARM (we do our own
thing.)  However, with this code:

int foo(unsigned long long n)
{
        if (((n) >> 31 >> 1) == 0) {
                return 1;
        } else {
                return 0;
        }
}

gcc 3.2.2 on ARM (32-bit) produces some not-very-nice code, consisting of
6 shifts and including placing one register on the stack and completely
ignoring a register which it could freely use instead.

-- 
Russell King (rmk@arm.linux.org.uk)                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: do_div vs sector_t
  2003-07-13 17:26 ` Richard Henderson
  2003-07-13 17:39   ` Russell King
@ 2003-07-13 19:14   ` Bernardo Innocenti
  2003-07-13 20:04     ` Matthew Wilcox
  1 sibling, 1 reply; 12+ messages in thread
From: Bernardo Innocenti @ 2003-07-13 19:14 UTC (permalink / raw)
  To: Richard Henderson, Matthew Wilcox; +Cc: Andrew Morton, linux-kernel

On Sunday 13 July 2003 19:26, Richard Henderson wrote:
> On Fri, Jul 11, 2003 at 11:33:59PM +0100, Matthew Wilcox wrote:
> > Better ideas?
>
>           if (likely(((n) >> 31 >> 1) == 0)) {

Do we still need to fix this? I've already posted a patch to disallow
calling do_div() with any divisor that doesn't look like an unsigned
64bit interger.

-- 
  // 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



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: do_div vs sector_t
  2003-07-13 19:14   ` Bernardo Innocenti
@ 2003-07-13 20:04     ` Matthew Wilcox
  0 siblings, 0 replies; 12+ messages in thread
From: Matthew Wilcox @ 2003-07-13 20:04 UTC (permalink / raw)
  To: Bernardo Innocenti
  Cc: Richard Henderson, Matthew Wilcox, Andrew Morton, linux-kernel

On Sun, Jul 13, 2003 at 09:14:35PM +0200, Bernardo Innocenti wrote:
> On Sunday 13 July 2003 19:26, Richard Henderson wrote:
> > On Fri, Jul 11, 2003 at 11:33:59PM +0100, Matthew Wilcox wrote:
> > > Better ideas?
> >
> >           if (likely(((n) >> 31 >> 1) == 0)) {
> 
> Do we still need to fix this? I've already posted a patch to disallow
> calling do_div() with any divisor that doesn't look like an unsigned
> 64bit interger.

No, I think the combination of sector_div() and your patch makes everything
happy-happy.  Thanks!

-- 
"It's not Hollywood.  War is real, war is primarily not about defeat or
victory, it is about death.  I've seen thousands and thousands of dead bodies.
Do you think I want to have an academic debate on this subject?" -- Robert Fisk

^ permalink raw reply	[flat|nested] 12+ messages in thread

* do_div vs sector_t
  2003-07-11 22:33 do_div vs sector_t Matthew Wilcox
                   ` (3 preceding siblings ...)
  2003-07-13 17:26 ` Richard Henderson
@ 2003-07-14  4:07 ` Peter Chubb
  4 siblings, 0 replies; 12+ messages in thread
From: Peter Chubb @ 2003-07-14  4:07 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: Bernardo Innocenti, Andrew Morton, linux-kernel

>>>>> "Matthew" == Matthew Wilcox <willy@debian.org> writes:


Matthew>                         do_div(aic->seek_mean, aic->seek_samples); }

Matthew> seek_mean is a sector_t so sometimes it's 64-bit on a 32-bit
Matthew> platform.  so we can't avoid calling do_div().

Use sector_div() instead! -- it uses a 63/32 bit divide/remainder if
sector_t is 64-bit, and 32/32 if it's 32-bit.

--
Dr Peter Chubb  http://www.gelato.unsw.edu.au  peterc AT gelato.unsw.edu.au
You are lost in a maze of BitKeeper repositories,   all slightly different.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: do_div vs sector_t
@ 2003-07-13 18:40 linux
  0 siblings, 0 replies; 12+ messages in thread
From: linux @ 2003-07-13 18:40 UTC (permalink / raw)
  To: willy; +Cc: linux-kernel

>        if (likely(((n) >> 32) == 0)) {                 \

if (likely((n) <= 0xffffffff)) {

will work with any unsigned type for n.


GCC knows to only look at the high word to make this test.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2003-07-14  3:53 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-11 22:33 do_div vs sector_t Matthew Wilcox
2003-07-11 22:34 ` Andrew Morton
2003-07-11 22:42 ` Neil Brown
2003-07-12  0:14   ` do_div vs sector_t (patch) Nick Piggin
2003-07-12  6:52 ` do_div vs sector_t Christoph Hellwig
2003-07-12  6:58   ` Andrew Morton
2003-07-13 17:26 ` Richard Henderson
2003-07-13 17:39   ` Russell King
2003-07-13 19:14   ` Bernardo Innocenti
2003-07-13 20:04     ` Matthew Wilcox
2003-07-14  4:07 ` Peter Chubb
2003-07-13 18:40 linux

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).