Page 1 of 2

Virtual timer overflow  Topic is solved

Posted: Wed May 22, 2019 6:37 pm
by steved
Not sure if this is a bug or a constraint.

ChibiOs 19.1.2
Using 32L071, so 16-bit SYSTICK at 1kHz.
CH_CFG_INTERVALS_SIZE 32
CH_CFG_TIME_TYPES_SIZE 32
All diagnostics enabled

I have a virtual timer started for a 5-minute interval (so multiple cycles of SYSTICK).
It appears that this can be handled as long as there are other virtual timers active - the outstanding tick count is clearly being reduced progressively.
Occasionally this 5-minute timer is the only one active; I then get a halt triggered by overflow in chTimeAddX() in line 134 of chvt.c.

Re: Virtual timer overflow

Posted: Wed May 22, 2019 7:04 pm
by Giovanni
Hi,

Interesting corner case, I need to verify. It is possible that flashing leds in the various demos hid this.

Giovanni

Re: Virtual timer overflow

Posted: Thu May 23, 2019 9:34 am
by Giovanni
Confirmed, there is a problem under those conditions, will be fixed over weekend.

Giovanni

Re: Virtual timer overflow

Posted: Sun May 26, 2019 7:48 am
by Giovanni
Hi,

The fix is to replace line 453 in chvt.h:

Code: Select all

  delta = chTimeDiffX(now, chTimeAddX(ch.vtlist.lasttime, vtp->delta));


with this:

Code: Select all

  delta = vtp->delta - chTimeDiffX(ch.vtlist.lasttime, now);


which calculates the delta in the "intervals domain" instead of "absolute time domain" like the previous expression. The two things are not equivalent because the different type size.

Opening a ticket about this, thanks for finding.

Giovanni

Re: Virtual timer overflow

Posted: Mon May 27, 2019 5:00 pm
by faisal
Will a test case be added to test for this?

Re: Virtual timer overflow

Posted: Mon May 27, 2019 6:28 pm
by Giovanni
Probably but it will be "conditional", executed only when the kernel is configured in the right mode: tickless and (sizeof(interval) > sizeof(time)) and no other timers active and systick frequency high enough to not take ages to complete.

So you will not see it executed in default demos, it requires a special run.

Giovanni

Re: Virtual timer overflow

Posted: Tue May 28, 2019 11:07 am
by faisal
Giovanni wrote:Probably but it will be "conditional", executed only when the kernel is configured in the right mode: tickless and (sizeof(interval) > sizeof(time)) and no other timers active and systick frequency high enough to not take ages to complete.

So you will not see it executed in default demos, it requires a special run.

Giovanni


That works. Just as long as it's part of the standard regression test of the kernel. I'm interested in the bug being fixed, and also that the process doesn't allow it to happen again in the future.

Re: Virtual timer overflow

Posted: Wed May 29, 2019 8:37 am
by steved
Not sure that the fix covers all situations; I saw the problem elsewhere.There are two cases to consider:
a) No virtual timers active; start one with a long delay
b) Multiple virtual timers active; shorter ones expire, until the long delay timer is the only one left.

I think the fix just covers the second case.
The first case brings you to line 134 of chvt.c:

Code: Select all

      port_timer_start_alarm(chTimeAddX(ch.vtlist.lasttime, delay));
, which is where I noticed the problem.

Re: Virtual timer overflow

Posted: Wed May 29, 2019 8:44 am
by Giovanni
This must be a different issue with the same root cause, I will inspect all chTimeAddX() call instances.

Note that I tested your case A, it fixes it.

Giovanni

Re: Virtual timer overflow

Posted: Wed May 29, 2019 9:19 am
by Giovanni
Hi,

Are you sure it happens in the above code?

Because:

Code: Select all


#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
      /* The delta could be too large for the physical timer to handle.*/
      if (delay > (sysinterval_t)TIME_MAX_SYSTIME) {
        delay = (sysinterval_t)TIME_MAX_SYSTIME;
      }
#endif

      /* Being the first element in the list the alarm timer is started.*/
      port_timer_start_alarm(chTimeAddX(ch.vtlist.lasttime, delay));


the "if" part seems to make the assertion in chTimeAddX() impossible. Could you make a stack trace after the assertion is triggered?

The only problem I found was in function chVTGetTimersStateI():

Code: Select all

    *timep = chTimeDiffX(chVTGetSystemTimeX(),
                         chTimeAddX(ch.vtlist.lasttime,
                                    ch.vtlist.next->delta +
                                    (sysinterval_t)CH_CFG_ST_TIMEDELTA));


has been changed in:

Code: Select all

    *timep = (ch.vtlist.next->delta + (sysinterval_t)CH_CFG_ST_TIMEDELTA) -
             chTimeDiffX(ch.vtlist.lasttime, chVTGetSystemTimeX());


All other calls to chTimeAddX() have similar "if" guards.

Giovanni