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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sat Nov 26 16:07:24 2011 +0100

copperplate/clockobj, lib: assume fixed clock resolution during runtime

For performance reason, we want to run locklessly for common time unit
conversions, so the clockobj implementation now assumes that the clock
resolution will not be updated on-the-fly.

This means that clockobj_set_resolution() shall be called from init
- or known to be safe - context only.

COPPERPLATE_PROTECT sections have been removed around client API calls
which do not involve locking anymore.

---

 include/copperplate/clockobj.h |   29 +---------------
 lib/alchemy/internal.c         |    3 --
 lib/alchemy/task.c             |    7 +---
 lib/alchemy/timer.c            |    9 -----
 lib/copperplate/clockobj.c     |   72 ++++++++++++++++++++++++++-------------
 lib/psos/tm.c                  |    4 +-
 lib/vxworks/tickLib.c          |    2 +-
 7 files changed, 54 insertions(+), 72 deletions(-)

diff --git a/include/copperplate/clockobj.h b/include/copperplate/clockobj.h
index 8e07946..7537c01 100644
--- a/include/copperplate/clockobj.h
+++ b/include/copperplate/clockobj.h
@@ -22,7 +22,6 @@
 #include <pthread.h>
 #include <time.h>
 #include <xeno_config.h>
-#include <copperplate/init.h>
 #include <copperplate/list.h>
 #include <copperplate/debug.h>
 #include <copperplate/lock.h>
@@ -96,11 +95,9 @@ timespec_after(const struct timespec *t1, const struct 
timespec *t2)
 extern "C" {
 #endif
 
-void clockobj_set_date(struct clockobj *clkobj,
-                      ticks_t ticks, unsigned int resolution_ns);
+void clockobj_set_date(struct clockobj *clkobj, ticks_t ticks);
 
-void clockobj_get_date(struct clockobj *clkobj,
-                      ticks_t *pticks);
+void clockobj_get_date(struct clockobj *clkobj, ticks_t *pticks);
 
 void clockobj_get_time(struct clockobj *clkobj,
                       ticks_t *pticks, ticks_t *ptsc);
@@ -220,18 +217,6 @@ void clockobj_ticks_to_timespec(struct clockobj *clkobj,
 }
 
 static inline
-int __clockobj_set_resolution(struct clockobj *clkobj,
-                             unsigned int resolution_ns)
-{
-       if (resolution_ns > 1) {
-               warning("support for low resolution clock disabled");
-               return __bt(-EINVAL);
-       }
-
-       return 0;
-}
-
-static inline
 unsigned int clockobj_get_resolution(struct clockobj *clkobj)
 {
        return 1;
@@ -273,16 +258,6 @@ void clockobj_ticks_to_timespec(struct clockobj *clkobj,
 }
 
 static inline
-int __clockobj_set_resolution(struct clockobj *clkobj,
-                             unsigned int resolution_ns)
-{
-       clkobj->resolution = resolution_ns;
-       clkobj->frequency = 1000000000 / resolution_ns;
-
-       return 0;
-}
-
-static inline
 unsigned int clockobj_get_resolution(struct clockobj *clkobj)
 {
        return clkobj->resolution;
diff --git a/lib/alchemy/internal.c b/lib/alchemy/internal.c
index fd2479c..445d50e 100644
--- a/lib/alchemy/internal.c
+++ b/lib/alchemy/internal.c
@@ -42,13 +42,10 @@ char *alchemy_build_name(char *buf, const char *name,
 
 RTIME alchemy_rel2abs_timeout(RTIME timeout)
 {
-       struct service svc;
        ticks_t now;
 
        if (timeout != TM_INFINITE && timeout != TM_NONBLOCK) {
-               COPPERPLATE_PROTECT(svc);
                clockobj_get_time(&alchemy_clock, &now, NULL);
-               COPPERPLATE_UNPROTECT(svc);
                timeout += now;
        }
 
diff --git a/lib/alchemy/task.c b/lib/alchemy/task.c
index e52e14c..5cfd1d0 100644
--- a/lib/alchemy/task.c
+++ b/lib/alchemy/task.c
@@ -475,7 +475,6 @@ int rt_task_sleep(RTIME delay)
 int rt_task_sleep_until(RTIME date)
 {
        struct timespec ts;
-       struct service svc;
        ticks_t now;
 
        if (!threadobj_current_p())
@@ -485,14 +484,10 @@ int rt_task_sleep_until(RTIME date)
                ts.tv_sec = (time_t)-1 >> 1;
                ts.tv_nsec = 999999999;
        } else {
-               COPPERPLATE_PROTECT(svc);
                clockobj_get_time(&alchemy_clock, &now, NULL);
-               if (date <= now) {
-                       COPPERPLATE_UNPROTECT(svc);
+               if (date <= now)
                        return -ETIMEDOUT;
-               }
                clockobj_ticks_to_timespec(&alchemy_clock, date, &ts);
-               COPPERPLATE_UNPROTECT(svc);
        }
 
        return threadobj_sleep(&ts);
diff --git a/lib/alchemy/timer.c b/lib/alchemy/timer.c
index 447d7dd..28c5989 100644
--- a/lib/alchemy/timer.c
+++ b/lib/alchemy/timer.c
@@ -23,12 +23,9 @@ struct clockobj alchemy_clock;
 
 RTIME rt_timer_read(void)
 {
-       struct service svc;
        ticks_t ticks;
 
-       COPPERPLATE_PROTECT(svc);
        clockobj_get_time(&alchemy_clock, &ticks, NULL);
-       COPPERPLATE_UNPROTECT(svc);
 
        return ticks;
 }
@@ -45,18 +42,12 @@ SRTIME rt_timer_ticks2ns(SRTIME ticks)
 
 int rt_timer_inquire(RT_TIMER_INFO *info)
 {
-       struct service svc;
-
-       COPPERPLATE_PROTECT(svc);
-
        info->period = clockobj_get_resolution(&alchemy_clock);
        if (info->period == 1)
                info->period = TM_ONESHOT;
 
        clockobj_get_time(&alchemy_clock, &info->date, &info->tsc);
 
-       COPPERPLATE_UNPROTECT(svc);
-
        return 0;
 }
 
diff --git a/lib/copperplate/clockobj.c b/lib/copperplate/clockobj.c
index 4cc4a63..d40a79c 100644
--- a/lib/copperplate/clockobj.c
+++ b/lib/copperplate/clockobj.c
@@ -27,6 +27,7 @@
 #include "copperplate/lock.h"
 #include "copperplate/clockobj.h"
 #include "copperplate/debug.h"
+#include "internal.h"
 
 void timespec_sub(struct timespec *r,
                  const struct timespec *t1, const struct timespec *t2)
@@ -80,7 +81,21 @@ void timespec_adds(struct timespec *r,
        }
 }
 
-#ifndef CONFIG_XENO_LORES_CLOCK_DISABLED
+#ifdef CONFIG_XENO_LORES_CLOCK_DISABLED
+
+static inline
+int __clockobj_set_resolution(struct clockobj *clkobj,
+                             unsigned int resolution_ns)
+{
+       if (resolution_ns > 1) {
+               warning("support for low resolution clock disabled");
+               return __bt(-EINVAL);
+       }
+
+       return 0;
+}
+
+#else  /* !CONFIG_XENO_LORES_CLOCK_DISABLED */
 
 void __clockobj_ticks_to_timespec(struct clockobj *clkobj,
                                  ticks_t ticks,
@@ -103,13 +118,21 @@ void __clockobj_ticks_to_timeout(struct clockobj *clkobj,
 {
        struct timespec delta;
 
-       read_lock_nocancel(&clkobj->lock);
        __RT(clock_gettime(clk_id, ts));
        __clockobj_ticks_to_timespec(clkobj, ticks, &delta);
-       read_unlock(&clkobj->lock);
        timespec_add(ts, ts, &delta);
 }
 
+static inline
+int __clockobj_set_resolution(struct clockobj *clkobj,
+                             unsigned int resolution_ns)
+{
+       clkobj->resolution = resolution_ns;
+       clkobj->frequency = 1000000000 / resolution_ns;
+
+       return 0;
+}
+
 #endif /* !CONFIG_XENO_LORES_CLOCK_DISABLED */
 
 static const int mdays[] = {
@@ -164,11 +187,9 @@ void clockobj_ticks_to_caltime(struct clockobj *clkobj,
        unsigned int freq;
        time_t nsecs;
 
-       read_lock_nocancel(&clkobj->lock);
        freq = clockobj_get_frequency(clkobj);
        nsecs = ticks / freq;
        *rticks = ticks % freq;
-       read_unlock(&clkobj->lock);
 
        for (year = 1970;; year++) { /* Years since 1970. */
                int ysecs = ((year % 4) ? 365 : 366) * SECBYDAY;
@@ -209,39 +230,47 @@ void clockobj_caltime_to_timeout(struct clockobj *clkobj, 
const struct tm *tm,
 {
        ticks_t ticks;
 
-       read_lock_nocancel(&clkobj->lock);
        clockobj_caltime_to_ticks(clkobj, tm, rticks, &ticks);
        __clockobj_ticks_to_timespec(clkobj, ticks, ts);
        timespec_sub(ts, ts, &clkobj->offset);
-       read_unlock(&clkobj->lock);
 }
 
-void clockobj_set_date(struct clockobj *clkobj,
-                      ticks_t ticks, unsigned int resolution_ns)
+void clockobj_set_date(struct clockobj *clkobj, ticks_t ticks)
 {
        struct timespec now;
 
+       /*
+        * XXX: we grab the lock to exclude other threads from reading
+        * the clock offset while we update it, so that they either
+        * compute against the old value, or the new one, but always
+        * see a valid offset.
+        */
        read_lock_nocancel(&clkobj->lock);
 
        __RT(clock_gettime(CLOCK_COPPERPLATE, &now));
 
-       /* Change the resolution on-the-fly if given. */
-       if (resolution_ns)
-               __clockobj_set_resolution(clkobj, resolution_ns);
-
        __clockobj_ticks_to_timespec(clkobj, ticks, &clkobj->epoch);
        timespec_sub(&clkobj->offset, &clkobj->epoch, &now);
 
        read_unlock(&clkobj->lock);
 }
 
+/*
+ * XXX: clockobj_set_resolution() should be called during the init
+ * phase, not after. For performance reason, we want to run locklessly
+ * for common time unit conversions, so the clockobj implementation
+ * does assume that the clock resolution will not be updated
+ * on-the-fly.
+ */
 int clockobj_set_resolution(struct clockobj *clkobj, unsigned int 
resolution_ns)
 {
 #ifdef CONFIG_XENO_LORES_CLOCK_DISABLED
        assert(resolution_ns == 1);
 #else
+       __clockobj_set_resolution(clkobj, resolution_ns);
+
        /* Changing the resolution implies resetting the epoch. */
-       clockobj_set_date(clkobj, 0, resolution_ns);
+       clockobj_set_date(clkobj, 0);
 #endif
        return 0;
 }
@@ -265,8 +294,6 @@ void clockobj_get_time(struct clockobj *clkobj,
 {
        unsigned long long ns, tsc;
 
-       read_lock_nocancel(&clkobj->lock);
-
        tsc = __xn_rdtsc();
        ns = xnarch_tsc_to_ns(tsc);
        if (clockobj_get_resolution(clkobj) > 1)
@@ -275,8 +302,6 @@ void clockobj_get_time(struct clockobj *clkobj,
 
        if (ptsc)
                *ptsc = tsc;
-
-       read_unlock(&clkobj->lock);
 }
 
 void clockobj_get_date(struct clockobj *clkobj, ticks_t *pticks)
@@ -310,8 +335,6 @@ void clockobj_get_time(struct clockobj *clkobj, ticks_t 
*pticks,
 
        __RT(clock_gettime(CLOCK_COPPERPLATE, &now));
 
-       read_lock_nocancel(&clkobj->lock);
-
        /* Convert the time value to ticks, with no offset. */
        if (clockobj_get_resolution(clkobj) > 1)
                *pticks = (ticks_t)now.tv_sec * clockobj_get_frequency(clkobj)
@@ -325,8 +348,6 @@ void clockobj_get_time(struct clockobj *clkobj, ticks_t 
*pticks,
         */
        if (ptsc)
                *ptsc = *pticks;
-
-       read_unlock(&clkobj->lock);
 }
 
 void clockobj_get_date(struct clockobj *clkobj, ticks_t *pticks)
@@ -356,11 +377,9 @@ void clockobj_ticks_to_clock(struct clockobj *clkobj,
 {
        struct timespec ts, now;
 
-       read_lock_nocancel(&clkobj->lock);
        __RT(clock_gettime(CLOCK_COPPERPLATE, &now));
        /* Absolute timeout, CLOCK_COPPERPLATE-based. */
        __clockobj_ticks_to_timespec(clkobj, ticks, &ts);
-       read_unlock(&clkobj->lock);
        /* Offset from CLOCK_COPPERPLATE epoch. */
        timespec_sub(timeout, &ts, &now);
        /* Current time for clk_id. */
@@ -384,6 +403,11 @@ int clockobj_init(struct clockobj *clkobj,
        if (ret)
                return __bt(ret);
 
+       /*
+        * FIXME: this lock is only used to protect the wallclock
+        * offset readings from updates. We should replace this by a
+        * confirmed reading loop.
+        */
        __RT(pthread_mutexattr_init(&mattr));
        __RT(pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT));
        __RT(pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_PRIVATE));
diff --git a/lib/psos/tm.c b/lib/psos/tm.c
index a4d7ccd..acc79b7 100644
--- a/lib/psos/tm.c
+++ b/lib/psos/tm.c
@@ -302,7 +302,7 @@ u_long tm_set(u_long date, u_long time, u_long ticks)
                goto out;
 
        clockobj_caltime_to_ticks(&psos_clock, &tm, ticks, &t);
-       clockobj_set_date(&psos_clock, t, 0);
+       clockobj_set_date(&psos_clock, t);
 out:
        COPPERPLATE_UNPROTECT(svc);
 
@@ -317,8 +317,8 @@ u_long tm_get(u_long *date_r, u_long *time_r, u_long 
*ticks_r)
 
        COPPERPLATE_PROTECT(svc);
        clockobj_get_date(&psos_clock, &t);
-       clockobj_ticks_to_caltime(&psos_clock, t, &tm, ticks_r);
        COPPERPLATE_UNPROTECT(svc);
+       clockobj_ticks_to_caltime(&psos_clock, t, &tm, ticks_r);
        *date_r = ((tm.tm_year + 1900) << 16) | ((tm.tm_mon + 1) << 8) | 
tm.tm_mday;
        *time_r = (tm.tm_hour << 16) | (tm.tm_min << 8) | tm.tm_sec;
 
diff --git a/lib/vxworks/tickLib.c b/lib/vxworks/tickLib.c
index 9fe5730..effb68b 100644
--- a/lib/vxworks/tickLib.c
+++ b/lib/vxworks/tickLib.c
@@ -42,5 +42,5 @@ ULONG tickGet(void)
 
 void tickSet(ULONG ticks)
 {
-       clockobj_set_date(&wind_clock, ticks, 0);
+       clockobj_set_date(&wind_clock, ticks);
 }


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to