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

Bug with clock nanoseconds



Manuel Coutinho wrote:
>
> Hi
>
>  
>
> We have discovered a bug of RTEMS relating to the clock. Even though 
> we only tested it for the ERC32 board (for now), we believe it is 
> common throughout all the targets.
>

No you have discovered a bug in the ERC32's get nanoseconds since last 
tick handler. 
Apparently it doesn't recognize that is has been longer than a tick 
since the last clock
tick.  It should determine that is has overflowed and return 1 clock 
tick + partial clock
tick. 

It is returning the wrong answer.

>  
>
> The test consists in checking if the time given by rtems_clock_get is 
> always increasing. The code is as follows:
>
>  
>
> .....


....
>
> As you can see, the problem is raised when a clock tick occurs: the 
> time read in ?new? is older than ?old?. This cannot happen since ?new? 
> is updated AFTER ?old?! This problem occurs if a clock interrupt is 
> triggered after the number of clock ticks have been read but BEFORE 
> the nanosecond field has been read. The resulting number of clock 
> ticks is ?small? (should be plus one).
>
>  
>
> We can use the interrupt pending CPU registers info to determine if, 
> while we are reading the number of clock ticks that occurred and the 
> nanoseconds, a clock interrupt could be pending.
>
>  
>
> We do not have enough knowledge to say that this solution can be used 
> for all boards (determining if an interrupt is pending). In the SPARC 
> architecture, at least, it is possible. If it is possible in all 
> architectures, then a solution to RTEMS would be to change the code of 
> the _TOD_Get_uptime function to:
>
>  
>
>  
>
> void _TOD_Get_uptime(struct timespec *uptime) {
>
>     ISR_Level level;
>
>     struct timespec offset;
>
>     volatile uint32_t pending;
>
>  
>
>     /* assume uptime checked by caller */
>
>  
>
>     offset.tv_sec = 0;
>
>     offset.tv_nsec = 0;
>
>  
>
>     _ISR_Disable(level);
>
>     *uptime = _TOD_Uptime;
>
>     if (_Watchdog_Nanoseconds_since_tick_handler)
>
>         offset.tv_nsec = (*_Watchdog_Nanoseconds_since_tick_handler)();
>
>  
>
>     /* code added: */
>
>     pending = isClockInterruptPending();
>
>  
>
>     _ISR_Enable(level);
>
>  
>
>     /* code added */
>
>     /* if an interrupt occurred while interrupts were disabled and the 
> nanoseconds is too little */
>
>     /* means that a clock interrupt occurred BEFORE the nanoseconds 
> were read */
>
>     if (pending && offset.tv_nsec < 
> rtems_configuration_get_microseconds_per_tick() / 2) {
>
>         struct timespec clockTick = {0, 
> rtems_configuration_get_microseconds_per_tick()*1000};
>
>         _Timespec_Add_to(&offset, &clockTick); /* so add one clock 
> tick to the offset */
>
>     }
>
>  
>
>     /* else, the clock tick occurred AFTER the nanoseconds were read, 
> so no problem */
>
>  
>
>     _Timespec_Add_to(uptime, &offset);
>
> }
>
>  
>
>  
>
> At least, with these modifications, the test passes :)!
>
>  
>
> Kind regards
>
> Manuel Coutinho
>


-- 
Joel Sherrill, Ph.D.             Director of Research & Development
joel.sherrill at OARcorp.com        On-Line Applications Research
Ask me about RTEMS: a free RTOS  Huntsville AL 35805
   Support Available             (256) 722-9985