This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: periodic threads with kapi?


>>>>> "Ryan" == Ryan Boder <icanoop@bitwiser.org> writes:

    Ryan> On Mon, Aug 18, 2003 at 09:53:18AM +0100, Bart Veer wrote:
    >> >> void
    >> >> my_thread_delay_absolute(cyg_tick_count_t abs_time)
    >> >> {
    >> >>     cyg_tick_count_t delay = abs_time - cyg_current_time();
    >> >>     if (delay > 0) {
    >> >>         cyg_thread_delay(delay);
    >> >>     }
    >> >> }

    >> There is no drift. The calling code should calculate the new
    >> value of abs_time by adding the appropriate number of ticks to
    >> the previous value of abs_time, thus moving from one absolute
    >> time to the next. For example adding 100 each time will give
    >> absolute intervals of 1 second (assuming the usual 10ms clock).

    Ryan> What if a timer interrupt happens between the delay
    Ryan> calculation and the time the timer is actually set? I think
    Ryan> that would cause drift. Am I wrong? The delay would be one
    Ryan> tick off in the same direction every time that happens.

A timer interrupt will not cause drift. Suppose the arguments to
successive calls to this function are 100, 200, 300, 400, ... The
thread gets woken up at time 100, does a bit of processing, then calls
this delay function before the next timer interrupt occurs. The
calculated delay will be 100, so the delay now takes us to time 200.

At time 200 the thread takes rather longer to do its processing
because there is a higher priority thread, so the delay call will not
happen until time 202. This time the calculated delay will be 98
ticks, taking us to 300.

At time 300 the thread just manages to do its processing before the
next clock interrupt and calls the delay function, giving a calculated
delay of 100. However the clock interrupt occurs in the small window
between the calculation and the cyg_thread_delay() call, so this will
actually take us to time 401 rather than 400.

At time 401 the thread will call my_thread_delay_absolute(500), giving
a calculated delay of 99. Assume we don't hit the window again, then
the next wake up will occur at the desired time of 500. The code has
compensated for the temporary drift and we are back to the desired
periodic behaviour.

So there is no systematic drift, only occasional jitter.


The jitter can be caused by three separate problems, not just by clock
interrupts: 

1) there is a clock interrupt between calculating the delay and the
   call to cyg_thread_delay(), but control returns to this thread
   after the interrupt. The next wakeup will be off by one, but
   this will be compensated for in the next delay calculation.

2) there is some other interrupt between calculating the delay and the
   call to cyg_thread_delay(), causing a higher priority thread to run
   for an unknown amount of time. Say that other thread uses all cpu
   time for the next 5 ticks. The next wakeup will be off by 5, but
   again this will be compensated for in the next delay calculation.

3) the thread is woken up exactly when it is supposed to, but there is
   a higher priority runnable thread. Hence the wakeup does not really
   take effect until later. Again there are no long-term consequences.

In case (3) everything is behaving exactly as it is supposed to:
higher priority threads get to run first. If the resulting jitter is
unacceptable then you'll need to rethink the thread priorities.

Case (2) is similar to (3). It can be avoided either by running this
thread at a suitably high priority, or by temporarily boosting the
priority around the calculation and the cyg_thread_delay() call.
An alternative is locking the scheduler around these operations,
so that no other thread can get in.

Case (1) is the least harmful in that the next wakeup will be off by
only one tick, rather than by an arbitrary time interval. If that is
not acceptable then the scheduler must be locked. That will cause the
timer DSR to be postponed, and it is the timer DSR that manipulates
the timer queue and increments the value returned by
cyg_current_time().

In the end it all depends on the application. Some applications can
tolerate the occasional variation, and the original code will work
just fine. Other applications need more accurate intervals, but
achieving that accuracy requires extra code, affecting both code size
and cpu cycles.

Bart

-- 
Bart Veer                       eCos Configuration Architect
http://www.ecoscentric.com/     The eCos and RedBoot experts

-- 
Before posting, please read the FAQ: http://sources.redhat.com/fom/ecos
and search the list archive: http://sources.redhat.com/ml/ecos-discuss


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]