gettimeofday seconds rollover problem?

Pavel Pisa ppisa4lists at
Thu Feb 23 23:12:25 UTC 2006

Hello all,

I have only some dumb notices to this subject.

I remember, that exactly similar discussion
has been running over Linux kernel mailing list.

If I remember well, final Linus's remarks and
guideline was, that even volatile for variables
is not big win. It affects only ordering for
CPU as virtual machine => it has no guarantee
for real memory state even on non-cached regions
and really right way to solve these is to use
memory barriers and volatile asm macros (inb/outb/readl/...)
for IO. IO macros has to include barriers instructions
for architectures which do not declare precise ordering
of instructions and has delayed data writing 
(for example PPC requires eieio or other variants there
or you see not change on pine even if you toggle it in
the loop and have declared peripheral/pointer as volatile).

Volatile could lead to significantly worse performance
in some situations. So if you want busyloop to wait
for some physical memory change the addition of barrier
is only solution to take. If it is only UP interprocess
case, then explicit atomic read/write variant could be
better. It can be build as *(volatile long/int/char*)x
or better as volatile asm instruction wrapper.
Volatile doesnot guarantee consistent state for structures
and more complex types (for example packed could allow
misaligned access for long on some architectures, but
breaks consisten access for sure)

Back to IRQ enable/disable. If you use "memory","cc" clobbered
in the exact volatile asm block which changes IRQ mask,
than you have guaranteed, that compiler doesnot move
accesses to the global memory/variables around it.
This doesnot affect caching or other optimization of local
variables arrangements between stack and registers. This ensures
expected behavior for UP as virtual machine. To guarantee
something between physical memory, IO or more CPUs barriers are still

If you use external functions for IRQ mask handling, than C compiler
interprets that as point, where global memory/variables can change
and does not cache them locally in registers. It has exactly same effect
as listing "memory". But because functions call is considered
as destruction of values in the clobberable registers, it imposes
not only performance lost on real call overhead but even on reload/lost
of values in the clobberable registers. The register pressure is bigger,
for architectures with link register concept this imposes to add instruction
to save this register in the non-clobbered one or onto stack and possibly leaf
node optimized function becomes heavy one.

So my personal preference is to use "memory","cc". We use this solution
on our systemless H8S, M68K, ARM and PPC targets and i have never
noticed problem caused by this. It can only have impact to somethink like
work with global variable do IRQ masking work with variable again, if this
is really critical, you can guide GCC by explicit addition of local variable
to hold copy of global one. That is right, that the degree of freedom
of GCC to hold copy of variable in register or reload value again
from memory is lost and you cannot say, hey GCC, I do not care about
this one.

Only other reasonable solution (according to my knowledge) is to not
use barriers at all and use carefully one of the following options
to mark variables which access order (mutual or relative to IRQ masking)
is important
  - readl/writel 
  - work_var=*(volatile xxx*)&global_one
  - volatile asm ("" : : "g" (&x))
  - volatile asm ("" : "=m" (x): "0" (x))
       this has some disadvantage that GCC has to provide address which
       could possibly lead to computation of the value in the register

Best wishes and excuse foe e-mail length,
I have impulsion for short notice,
but my problem description is more complex
than I want

                Pavel Pisa


> Notice that the compiler is quite happy to use after the enable/ disable 
> the value which was saved in d0 before the enable/disable.   How has 
> adding the "memory" hurt anything?

If the state is stored into local variable, than "memory"
has no effect. If in global one, it is forced then.

More information about the users mailing list