gettimeofday seconds rollover problem?
Joel Sherrill
joel.sherrill at oarcorp.com
Thu Feb 23 20:33:10 UTC 2006
Till Straumann wrote:
> One moment, folks -- I'm not sure the "memory" approach is best
> for all architectures. On CPUs with many registers, making
> rtems_interrupt_enable()/disable a real subroutine might be cheaper.
>
> In any case, I believe that declaring the relevant global variables
> 'volatile' is the correct way to deal with this problem.
>
> The standard says:
>
> "An object that has volatile-qualified type may be modified in ways
> unknown to the
> implementation or have other unknown side effects. Therefore any
> expression referring
> to such an object shall be evaluated strictly according to the rules
> of the abstract machine,
> as described in 5.1.2.3. Furthermore, at every sequence point the
> value last stored in the
> object shall agree with that prescribed by the abstract machine,
> except as modified by the
> unknown factors mentioned previously.114) What constitutes an access
> to an object that
> has volatile-qualified type is implementation-defined.
>
> -----114) A volatile declaration may be used to describe an object
> corresponding to a memory-mapped
> input/output port or an object accessed by an asynchronously
> interrupting function. Actions on
> objects so declared shall not be ‘‘optimized out’’ by an
> implementation or reordered except as
> permitted by the rules for evaluating expressions."
>
> Seems exactly what we want and indeed, while the powerpc port
> (gcc-4.0.2) currently
> also exhibits the problem, when recompiled with both _TOD_Current and
> _TOD_Seconts_since_epoch
> declared 'volatile' the respective read operations are not moved out
> of the protected
> section anymore.
>
> -- Till
>
> BTW: I also checked m68k/coldfire/gcc-4.0.2 -- declaring the relevant
> globals 'volatile' produces
> correctly protected code.
>
Does anyone object to this solution?
Is there any other variable inside RTEMS that should be volatile. I
have a sick feeling that there are
a handful that may need it. At the top of my list would be
_Thread_Executing and _Thread_Heir and
a few others that are related.
Till, can you check the generated code for this code from the top of
_Thread_Dispatch? It may hint
that more volatiles are needed.
_ISR_Disable( level );
while ( _Context_Switch_necessary == TRUE ) {
heir = _Thread_Heir;
_Thread_Dispatch_disable_level = 1;
_Context_Switch_necessary = FALSE;
_Thread_Executing = heir;
executing->rtems_ada_self = rtems_ada_self;
rtems_ada_self = heir->rtems_ada_self;
if ( heir->budget_algorithm ==
THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE )
heir->cpu_time_budget = _Thread_Ticks_per_timeslice;
_ISR_Enable( level );
BTW: I also checked m68k/coldfire/gcc-4.0.2 -- declaring the relevant
globals 'volatile' produces
correctly protected code.
Once this gets settled, it needs a patch. :)
--joel
> Eric Norum wrote:
>
>> Ack!
>> Looks like gcc really is getting aggressive.
>>
>> Here's the code for a ColdFire MCF5282:
>>
>> (gdb) disassem gettimeofday
>> Dump of assembler code for function gettimeofday:
>> 0x00127d8c <gettimeofday+0>: moveal %sp@(4),%a0
>> 0x00127d90 <gettimeofday+4>: tstl %a0
>> 0x00127d92 <gettimeofday+6>: beqs 0x127dca <gettimeofday+62>
>> 0x00127d94 <gettimeofday+8>: movel #1792,%d0
>> 0x00127d9a <gettimeofday+14>: movel %d0,%d1
>> 0x00127d9c <gettimeofday+16>: movew %sr,%d0
>> 0x00127d9e <gettimeofday+18>: orl %d0,%d1
>> 0x00127da0 <gettimeofday+20>: movew %d1,%sr
>> 0x00127da2 <gettimeofday+22>: movel 0x219f22 <_TOD_Current+24>,%d1
>> 0x00127da8 <gettimeofday+28>: movew %d0,%sr
>> 0x00127daa <gettimeofday+30>: movel 0x219e46
>> <_TOD_Seconds_since_epoch>,%d0
>> 0x00127db0 <gettimeofday+36>: addil #567993600,%d0
>> 0x00127db6 <gettimeofday+42>: movel %d0,%a0@
>> 0x00127db8 <gettimeofday+44>: movel 0x219f72
>> <_TOD_Microseconds_per_tick>,%d0
>> 0x00127dbe <gettimeofday+50>: mulsl %d1,%d0
>> 0x00127dc2 <gettimeofday+54>: movel %d0,%a0@(4)
>> 0x00127dc6 <gettimeofday+58>: clrl %d0
>> 0x00127dc8 <gettimeofday+60>: rts
>>
>>
>> As you can see, the 'ticks' value is read with interrupts disabled,
>> but the 'seconds since epoch' is not.
>>
>>
>> norume at pyramidion 221> m68k-rtems4.7-gcc --version
>> m68k-rtems4.7-gcc (GCC) 4.0.2
>>
>>
>>
>> I made the following change:
>> Index: cpukit/score/cpu/m68k/rtems/score/m68k.h
>> ===================================================================
>> RCS file: /usr1/CVS/rtems/cpukit/score/cpu/m68k/rtems/score/m68k.h,v
>> retrieving revision 1.24
>> diff -u -r1.24 m68k.h
>> --- cpukit/score/cpu/m68k/rtems/score/m68k.h 7 Jun 2005 16:44:18
>> -0000 1.24
>> +++ cpukit/score/cpu/m68k/rtems/score/m68k.h 23 Feb 2006 16:29:19 -0000
>> @@ -280,17 +280,19 @@
>> asm volatile ( "move.w %%sr,%0\n\t" \
>> "or.l %0,%1\n\t" \
>> "move.w %1,%%sr" \
>> - : "=d" (_level), "=d"(_tmpsr) : "1"(_tmpsr) ); \
>> + : "=d" (_level), "=d"(_tmpsr) : "1"(_tmpsr) \
>> + : "memory", "cc" ); \
>> } while( 0 )
>> #else
>> #define m68k_disable_interrupts( _level ) \
>> asm volatile ( "move.w %%sr,%0\n\t" \
>> "or.w #0x0700,%%sr" \
>> - : "=d" (_level))
>> + : "=d" (_level) \
>> + : : "memory", "cc" )
>> #endif
>> #define m68k_enable_interrupts( _level ) \
>> - asm volatile ( "move.w %0,%%sr " : : "d" (_level));
>> + asm volatile ( "move.w %0,%%sr " : : "d" (_level) : "memory", "cc");
>> #if ( M68K_COLDFIRE_ARCH == 1 )
>> #define m68k_flash_interrupts( _level ) \
>> @@ -298,13 +300,15 @@
>> asm volatile ( "move.w %2,%%sr\n\t" \
>> "or.l %2,%1\n\t" \
>> "move.w %1,%%sr" \
>> - : "=d"(_tmpsr) : "0"(_tmpsr), "d"(_level) ); \
>> + : "=d"(_tmpsr) : "0"(_tmpsr), "d"(_level) \
>> + : "memory", "cc"); \
>> } while( 0 )
>> #else
>> #define m68k_flash_interrupts( _level ) \
>> asm volatile ( "move.w %0,%%sr\n\t" \
>> "or.w #0x0700,%%sr" \
>> - : : "d" (_level))
>> + : : "d" (_level) \
>> + : "memory", "cc" )
>> #endif
>> #define m68k_get_interrupt_level( _level ) \
>>
>>
>>
>> Now the code looks good:
>>
>> (gdb) disassem gettimeofday
>> Dump of assembler code for function gettimeofday:
>> 0x00127d8c <gettimeofday+0>: movel %d2,%sp at -
>> 0x00127d8e <gettimeofday+2>: moveal %sp@(8),%a0
>> 0x00127d92 <gettimeofday+6>: tstl %a0
>> 0x00127d94 <gettimeofday+8>: beqs 0x127dcc <gettimeofday+64>
>> 0x00127d96 <gettimeofday+10>: movel #1792,%d0
>> 0x00127d9c <gettimeofday+16>: movel %d0,%d1
>> 0x00127d9e <gettimeofday+18>: movew %sr,%d0
>> 0x00127da0 <gettimeofday+20>: orl %d0,%d1
>> 0x00127da2 <gettimeofday+22>: movew %d1,%sr
>> 0x00127da4 <gettimeofday+24>: movel 0x219e06
>> <_TOD_Seconds_since_epoch>,%d1
>> 0x00127daa <gettimeofday+30>: movel 0x219ee2 <_TOD_Current+24>,%d2
>> 0x00127db0 <gettimeofday+36>: movew %d0,%sr
>> 0x00127db2 <gettimeofday+38>: addil #567993600,%d1
>> 0x00127db8 <gettimeofday+44>: movel %d1,%a0@
>> 0x00127dba <gettimeofday+46>: movel 0x219f32
>> <_TOD_Microseconds_per_tick>,%d0
>> 0x00127dc0 <gettimeofday+52>: mulsl %d2,%d0
>> 0x00127dc4 <gettimeofday+56>: movel %d0,%a0@(4)
>> 0x00127dc8 <gettimeofday+60>: clrl %d0
>> 0x00127dca <gettimeofday+62>: bras 0x127ddc <gettimeofday+80>
>> 0x00127dcc <gettimeofday+64>: jsr 0x185270 <__errno>
>> 0x00127dd2 <gettimeofday+70>: moveal %d0,%a0
>> 0x00127dd4 <gettimeofday+72>: movel #14,%a0@
>> 0x00127dda <gettimeofday+78>: moveq #-1,%d0
>> 0x00127ddc <gettimeofday+80>: movel %sp at +,%d2
>> 0x00127dde <gettimeofday+82>: rts
>>
>>
>
More information about the users
mailing list