this seems identical to an issue I have. I wanted to start a millisecond tick, 
aligned to seconds, but used the POSIX timerfd_settime.
Under Linux this works as intendent, under cobalt it doesn't.

I  expect that the first timeout would be somewhat close to the call, on a 
"whole" millisecond.

What happens is that the timer-function convert the (Nano-)seconds to the 
internal resolution. This has a small error, which normally won't matter for 
short timespans.
The problem here is, that the absolute time will get converted with a big 
(absolute) error - growing bigger the longer your system is up.

What you could do, is reading the current time and fixing it up to a whole tick 
close to it, name this prev_secondtime, then use this as initial value.
Now the driver will have to fixup nothing or only a small amount, keeping the 
error low.

You can also try fixing this at driver level, but I haven't dissected this 
carefully yet.
Basically the driver should calculate in the "source time" for as long as 
possible and only use the converted internal value for close events to keep 
conversion errors bounded.


Highly experimental patch for ./kernel/cobalt/timer.c

--- timer.c.org 2017-12-18 10:09:37.283116000 +0100
+++ timer.c     2017-12-18 10:39:36.085302719 +0100
@@ -116,7 +116,7 @@
        struct xnclock *clock = xntimer_clock(timer);
        xntimerq_t *q = xntimer_percpu_queue(timer);
-       xnticks_t date, now, delay, period;
+       xnticks_t date, now, delay, period, expired = 0;
        unsigned long gravity;
        int ret = 0;

@@ -141,6 +141,7 @@
        default: /* XN_ABSOLUTE || XN_REALTIME */
                date = xnclock_ns_to_ticks(clock, value);
                if ((xnsticks_t)(date - now) <= 0) {
+                       _ xnticks t nextvalue;
                        if (interval == XN_INFINITE)
                                return -ETIMEDOUT;
@@ -148,9 +149,17 @@
                         * delivery, wait for the next shot on the
                         * periodic time line.
-                       delay = now - date;
+                       expired = xnarch_div64(xnclock_ticks_to_ns(now - date), 
+                       nextvalue = value + interval * (expired + 1);
+                       /*
+                        * Note: need to think about errors for big offsets,
+                        * iteration of the correction is likely necessary,
+                        * until the value is within the boundaries [now, now + 
+                        */
+                       date = xnclock_ns_to_ticks(clock, nextvalue);
                        period = xnclock_ns_to_ticks(clock, interval);
-                       date += period * (xnarch_div64(delay, period) + 1);

 >-----Original Message-----
 >From: Xenomai [mailto:xenomai-boun...@xenomai.org] On Behalf Of Lowell
 >Sent: Montag, 12. Februar 2018 14:41
 >To: xenomai@xenomai.org
 >Subject: Re: [Xenomai] rtdm_timer_start latency?
 >Lowell Gilbert <klu...@be-well.ilk.org> writes:
 >> Philippe Gerum <r...@xenomai.org> writes:
 >>> On 02/09/2018 11:02 AM, Philippe Gerum wrote:
 >>>> On 02/09/2018 12:45 AM, Lowell Gilbert wrote:
 >>>>> Am I correct in assuming that when calling rtdm_timer_start(), I should
 >>>>> not be getting multi-second latencies before the first call to the timer
 >>>>> routine? Just checking before I dig in too far.
 >>>> Of course not. I suspect an absolute expiry time is given with a
 >>>> relative mode spec.
 >>> More generally, an absolute expiry time which is not based on the right
 >>> clock specified by the mode argument.
 >>> i.e.
 >>> expiry = rtdm_clock_monotonic(), mode = RTDM_TIMERMODE_REALTIME
 >=> BAD
 >>> expiry = rtdm_clock_realtime(), mode = RTDM_TIMERMODE_ABSOLUTE =>
 >>> expiry = rtdm_clock_realtime() or _monotonic(), mode =
 >> Okay, that makes sense.
 >> I was using 0 for expiry, because I really just wanted the periodic
 >> wakeup. I don't remember why I didn't create a periodic task instead of
 >> using a timer.
 >> What clock do I want to use to get the timer started? Once it starts, it
 >> runs fine; but it often takes two or three seconds before the first call
 >> into the handler.
 >> To put it another way, I'm trying to figure out what am I doing wrong in:
 >>               ret = rtdm_timer_start(&pstate.collect.timer, 1,
 >>                                      pstate.collect.period,
 >>                                      RTDM_TIMERMODE_RELATIVE);
 >I could just rewrite the code to use a periodic task, but I'd prefer to
 >understand what is actually wrong with my current code first, to be sure
 >that refactoring will really solve my problem.
 >Or I could have the timer run constantly, but that is just hacking
 >around the problem, not really solving it.
 >Thanks for all help, past and future.
 >Xenomai mailing list

This message and any attachments are solely for the use of the intended 
recipients. They may contain privileged and/or confidential information or 
other information protected from disclosure. If you are not an intended 
recipient, you are hereby notified that you received this email in error and 
that any review, dissemination, distribution or copying of this email and any 
attachment is strictly prohibited. If you have received this email in error, 
please contact the sender and delete the message and any attachment from your 


Rechtsform/ Legal form: Gesellschaft mit beschränkter Haftung / Corporation

Firmensitz/ Registered seat: Wien

Firmenbuchgericht/ Court of registry: Handelsgericht Wien

Firmenbuchnummer/ Company registration: FN 61833 g

DVR: 0605077

UID-Nr.: ATU14756806

Thank You

Xenomai mailing list

Reply via email to