[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Possible timing problems



> From: Mikael Starvik <starvik@xxxxxxx.com>
> Date: Tue, 20 Feb 2001 08:32:30 +0100

> The for-loop is not removed by the comiler. The compiler generates
> the following assembler code for the for loop:
> 
> a:
> cmpq -1,r9
> bne a
> subq 1,r9 ; Delay slot
> 
> This means that each iteration is 3 clock cycles so the loop
> actually delays usec * 1.5 microseconds.

Mr Aaberg is right to be concerned about the empty loop.  Let me
urge people *not* to write code like that:

>     for(i = 50 * (usec); i--;) /* nothing */ ; 

The compiler might (read: will) remove those loops in a future
release.  There's nothing holy about empty loops (anymore; for
those of you with old gcc manuals).

Also, the timing of such loops is definitely dependent upon the
current speed of the chip.  When code is compiled for a faster
chip, the code will need to be tweaked.  Having said that, the
Linux kernel *does* count the number of such iterations per
clock tick, so perhaps it be validly used in code such as
udelay.  But then you should use udelay, not your own code.  I
know udelay is unnecessarily bloated right now, but it's the
right thing to use for loops such as the one below.

For code *other* than in the Linux kernel, where you know the
count is right (because it is calculated as in the Linux
kernel), you still shouldn't have an empty loop.  Put an
assembly instruction in it:

 for (i = 50 * usec; i--;)
   asm ("nop");

Note that asm:s without inputs and outputs are automatically
also "volatile"; they must not be "hoisted" out of the loop or
moved in another way.  Also, you must not have a "" instead of
the "nop", because the loop might be partially unrolled for
obscure reasons.

End of lecture. :-)
brgds, H-P