gettimeofday seconds rollover problem?

Joel Sherrill joel.sherrill at oarcorp.com
Thu Feb 23 12:20:07 UTC 2006


Chris Johns wrote:

> Joel Sherrill wrote:
>
>>
>> The seconds and nanoseconds values are grabbed/computed with interrupts
>> disabled so I don't think that would be the problem.
>
>
> No they are not and it is the problem. The interrupts are being enable 
> just after they are being disabled. Here is the code:
>
> 00000000 <gettimeofday>:
> gettimeofday():
> ../../../../../head/cpukit/libcsupport/src/__gettod.c:50
>    0:   4e56 0000       linkw %fp,#0
>    4:   206e 0008       moveal %fp@(8),%a0
> ../../../../../head/cpukit/libcsupport/src/__gettod.c:55
>    8:   4a88            tstl %a0
>    a:   6736            beqs 42 <gettimeofday+0x42>
> ../../../../../head/cpukit/libcsupport/src/__gettod.c:67
>    c:   203c 0000 0700  movel #1792,%d0
>   12:   2200            movel %d0,%d1
>   14:   40c0            movew %sr,%d0
>   16:   8280            orl %d0,%d1
>   18:   46c1            movew %d1,%sr
>                         ^^^^^^^^^^^^^ DISABLED
> ../../../../../head/cpukit/libcsupport/src/__gettod.c:70
>   1a:   46c0            movew %d0,%sr
>                         ^^^^^^^^^^^^^ ENABLED
>
> The remainder of the code is the reading of the time:
>
> ../../../../../head/cpukit/libcsupport/src/__gettod.c:72
>   1c:   2039 0000 0000  movel 0 <gettimeofday>,%d0
>   22:   0680 21da e500  addil #567993600,%d0
>   28:   2080            movel %d0,%a0@
> ../../../../../head/cpukit/libcsupport/src/__gettod.c:73
>   2a:   2239 0000 0000  movel 0 <gettimeofday>,%d1
>   30:   2039 0000 0000  movel 0 <gettimeofday>,%d0
>   36:   4c00 1800       mulsl %d0,%d1
>   3a:   2141 0004       movel %d1,%a0@(4)
>   3e:   4280            clrl %d0
>   40:   6010            bras 52 <gettimeofday+0x52>
> ../../../../../head/cpukit/libcsupport/src/__gettod.c:56
>   42:   4eb9 0000 0000  jsr 0 <gettimeofday>
>   48:   2040            moveal %d0,%a0
>   4a:   20bc 0000 000e  movel #14,%a0@
>   50:   70ff            moveq #-1,%d0
>   52:   4e5e            unlk %fp
>   54:   4e75            rts
>
> I wonder where else in the kernel this is happening and to which other 
> targets. I see the i386 also has problems. In the i386 only one value 
> is being read with interrupts masked:
>
>   rtems_interrupt_disable(level);
>    c:   9c                      pushf
>    d:   fa                      cli
>    e:   58                      pop    %eax
>  cpukit/libcsupport/src/__gettod.c:69
>     seconds      = _TOD_Seconds_since_epoch;
>     microseconds = _TOD_Current.ticks;
>    f:   8b 15 18 00 00 00       mov    0x18,%edx
>                                 ^^^^^^^^^^^^^^^^ ONLY ONE READ
> cpukit/libcsupport/src/__gettod.c:70
>   rtems_interrupt_enable(level);
>   15:   50                      push   %eax
>   16:   9d                      popf
> cpukit/libcsupport/src/__gettod.c:72
>   tp->tv_sec  = seconds + POSIX_TIME_SECONDS_1970_THROUGH_1988;
>   17:   a1 00 00 00 00          mov    0x0,%eax
>                                 ^^^^^^^^^^^^^^^ THE OTHER READ
>   1c:   05 00 e5 da 21          add    $0x21dae500,%eax
>   21:   89 01                   mov    %eax,(%ecx)
>
>> The asm volatile statements
>> should provide sync points for the compiler if a partial read of 
>> memory were
>> an issue. 
>
>
> If this is the case it would seem we have a problem with our asm 
> statements or the compiler has a bug.
>

This is the C code we are looking at the assembly for, correct?

  rtems_interrupt_disable(level);
    seconds      = _TOD_Seconds_since_epoch;
    microseconds = _TOD_Current.ticks;
  rtems_interrupt_enable(level);

and the assembly inlines for that are:

#define m68k_disable_interrupts( _level ) \
   do { register uint32_t   _tmpsr = 0x0700; \
        asm volatile ( "move.w %%sr,%0\n\t" \
                       "or.l   %0,%1\n\t" \
                       "move.w %1,%%sr" \
                       : "=d" (_level), "=d"(_tmpsr) : "1"(_tmpsr) ); \
   } while( 0 )
#define m68k_enable_interrupts( _level ) \
  asm volatile ( "move.w  %0,%%sr " : : "d" (_level));

Which compiler did you check that with? 

> Regards
> Chris





More information about the users mailing list