Module: xenomai-3
Branch: master
Commit: 113867b0ece6f836fad7c45c2dc10ce4ada54c48
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=113867b0ece6f836fad7c45c2dc10ce4ada54c48

Author: Philippe Gerum <r...@xenomai.org>
Date:   Wed Oct  1 11:35:00 2014 +0200

cobalt/timer: anticipate on the expiry date

The gravity is directly substracted from the timer expiry date,
instead of applying gravity on the timer shot date and/or within the
timer processing loop. This prevents the overhead that may be caused
by the need for rescheduling early shots.

However, this does NOT prevent early shots in case the clock gravity
value for the target context is over-pessimistic.

---

 include/cobalt/kernel/timer.h |   32 +++++++++++++++++++++++---------
 kernel/cobalt/clock.c         |   32 +++++---------------------------
 kernel/cobalt/timer.c         |   30 ++++++++++++++++++++----------
 3 files changed, 48 insertions(+), 46 deletions(-)

diff --git a/include/cobalt/kernel/timer.h b/include/cobalt/kernel/timer.h
index dcb6927..e633945 100644
--- a/include/cobalt/kernel/timer.h
+++ b/include/cobalt/kernel/timer.h
@@ -268,12 +268,25 @@ static inline xntimerq_t *xntimer_this_queue(struct 
xntimer *timer)
        return &tmd->q;
 }
 
-static inline void xntimer_update_date(struct xntimer *timer)
+static inline unsigned long xntimer_gravity(struct xntimer *timer)
 {
-       xntimerh_date(&timer->aplink) = timer->start_date +
-               xnclock_ns_to_ticks(xntimer_clock(timer),
-                               timer->periodic_ticks * timer->interval_ns);
+       struct xnclock *clock = xntimer_clock(timer);
+
+       if (timer->status & XNTIMER_KGRAVITY)
+               return clock->gravity.kernel;
+
+       if (timer->status & XNTIMER_UGRAVITY)
+               return clock->gravity.user;
 
+       return clock->gravity.irq;
+}
+
+static inline void xntimer_update_date(struct xntimer *timer)
+{
+       xntimerh_date(&timer->aplink) = timer->start_date
+               + xnclock_ns_to_ticks(xntimer_clock(timer),
+                       timer->periodic_ticks * timer->interval_ns)
+               - xntimer_gravity(timer);
 }
 
 static inline xnticks_t xntimer_pexpect(struct xntimer *timer)
@@ -392,6 +405,12 @@ static inline xnticks_t xntimer_interval(struct xntimer 
*timer)
        return timer->interval_ns;
 }
 
+static inline xnticks_t xntimer_expiry(struct xntimer *timer)
+{
+       /* Real expiry date in ticks without anticipation (no gravity) */
+       return xntimerh_date(&timer->aplink) + xntimer_gravity(timer);
+}
+
 int xntimer_start(struct xntimer *timer,
                xnticks_t value,
                xnticks_t interval,
@@ -418,11 +437,6 @@ static inline xnticks_t xntimer_get_timeout_stopped(struct 
xntimer *timer)
        return xntimer_get_timeout(timer);
 }
 
-static inline xnticks_t xntimer_get_expiry(struct xntimer *timer)
-{
-       return xntimerh_date(&timer->aplink);
-}
-
 static inline void xntimer_enqueue(struct xntimer *timer,
                                   xntimerq_t *q)
 {
diff --git a/kernel/cobalt/clock.c b/kernel/cobalt/clock.c
index 962e1f9..2c1219b 100644
--- a/kernel/cobalt/clock.c
+++ b/kernel/cobalt/clock.c
@@ -121,17 +121,6 @@ EXPORT_SYMBOL_GPL(xnclock_core_ticks_to_ns_rounded);
 EXPORT_SYMBOL_GPL(xnclock_core_ns_to_ticks);
 EXPORT_SYMBOL_GPL(xnclock_divrem_billion);
 
-static inline unsigned long get_timer_gravity(struct xntimer *timer)
-{
-       if (timer->status & XNTIMER_KGRAVITY)
-               return nkclock.gravity.kernel;
-
-       if (timer->status & XNTIMER_UGRAVITY)
-               return nkclock.gravity.user;
-
-       return nkclock.gravity.irq;
-}
-
 void xnclock_core_local_shot(struct xnsched *sched)
 {
        struct xntimerdata *tmd;
@@ -186,16 +175,7 @@ void xnclock_core_local_shot(struct xnsched *sched)
                }
        }
 
-       /*
-        * The gravity value gives the amount of time expressed in
-        * clock ticks, by which we should anticipate the next shot
-        * for the given timer, to account for the typical system
-        * latency when delivering the event to an irq handler, or a
-        * kernel/user thread.
-        */
-       delay = xntimerh_date(&timer->aplink) -
-               (xnclock_core_read_raw() + get_timer_gravity(timer));
-
+       delay = xntimerh_date(&timer->aplink) - xnclock_core_read_raw();
        if (delay < 0)
                delay = 0;
        else if (delay > ULONG_MAX)
@@ -229,10 +209,9 @@ static void adjust_timer(struct xntimer *timer, xntimerq_t 
*q,
        timer->start_date -= delta;
        period = xntimer_interval(timer);
        diff = xnclock_ticks_to_ns(clock,
-                               xnclock_read_raw(clock) -
-                               xntimerh_date(&timer->aplink));
+               xnclock_read_raw(clock) - xntimer_expiry(timer));
 
-       if ((xnsticks_t) (diff - period) >= 0) {
+       if ((xnsticks_t)(diff - period) >= 0) {
                /*
                 * Timer should tick several times before now, instead
                 * of calling timer->handler several times, we change
@@ -695,9 +674,9 @@ void xnclock_tick(struct xnclock *clock)
 {
        xntimerq_t *timerq = &xnclock_this_timerdata(clock)->q;
        struct xnsched *sched = xnsched_current();
-       xnticks_t now, interval_ticks;
        struct xntimer *timer;
        xnsticks_t delta;
+       xnticks_t now;
        xntimerh_t *h;
 
        /*
@@ -767,9 +746,8 @@ void xnclock_tick(struct xnclock *clock)
                    (XNTIMER_PERIODIC|XNTIMER_DEQUEUED|XNTIMER_RUNNING))
                        continue;
        advance:
-               interval_ticks = 1;
                do {
-                       timer->periodic_ticks += interval_ticks;
+                       timer->periodic_ticks++;
                        xntimer_update_date(timer);
                } while (xntimerh_date(&timer->aplink) < now);
        requeue:
diff --git a/kernel/cobalt/timer.c b/kernel/cobalt/timer.c
index 9e6f8e5..ae4e5c9 100644
--- a/kernel/cobalt/timer.c
+++ b/kernel/cobalt/timer.c
@@ -105,6 +105,7 @@ int xntimer_start(struct xntimer *timer,
        struct xnclock *clock = xntimer_clock(timer);
        xntimerq_t *q = xntimer_percpu_queue(timer);
        xnticks_t date, now, delay, period;
+       unsigned long gravity;
        struct xnsched *sched;
        int ret = 0;
 
@@ -144,7 +145,18 @@ int xntimer_start(struct xntimer *timer,
                break;
        }
 
-       xntimerh_date(&timer->aplink) = date;
+       /*
+        * To cope with the basic system latency, we apply a clock
+        * gravity value, which is the amount of time expressed in
+        * clock ticks by which we should anticipate the shot for any
+        * outstanding timer. The gravity value varies with the type
+        * of context the timer wakes up, i.e. irq handler, kernel or
+        * user thread.
+        */
+       gravity = xntimer_gravity(timer);
+       xntimerh_date(&timer->aplink) = date - gravity;
+       if (now >= xntimerh_date(&timer->aplink))
+               xntimerh_date(&timer->aplink) += gravity / 2;
 
        timer->interval_ns = XN_INFINITE;
        timer->interval = XN_INFINITE;
@@ -229,8 +241,7 @@ xnticks_t xntimer_get_date(struct xntimer *timer)
        if (!xntimer_running_p(timer))
                return XN_INFINITE;
 
-       return xnclock_ticks_to_ns(xntimer_clock(timer),
-                                  xntimerh_date(&timer->aplink));
+       return xnclock_ticks_to_ns(xntimer_clock(timer), xntimer_expiry(timer));
 }
 EXPORT_SYMBOL_GPL(xntimer_get_date);
 
@@ -254,20 +265,19 @@ EXPORT_SYMBOL_GPL(xntimer_get_date);
  */
 xnticks_t xntimer_get_timeout(struct xntimer *timer)
 {
-       xnticks_t ticks, delta;
        struct xnclock *clock;
+       xnticks_t expiry, now;
 
        if (!xntimer_running_p(timer))
                return XN_INFINITE;
 
        clock = xntimer_clock(timer);
-       ticks = xnclock_read_raw(clock);
-       if (xntimerh_date(&timer->aplink) < ticks)
-               return 1;       /* Will elapse shortly. */
-
-       delta = xntimerh_date(&timer->aplink) - ticks;
+       now = xnclock_read_raw(clock);
+       expiry = xntimer_expiry(timer);
+       if (expiry < now)
+               return 1;  /* Will elapse shortly. */
 
-       return xnclock_ticks_to_ns(clock, delta);
+       return xnclock_ticks_to_ns(clock, expiry - now);
 }
 EXPORT_SYMBOL_GPL(xntimer_get_timeout);
 


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to