Module: xenomai-3
Branch: stable-3.0.x
Commit: e6cd9610215b06ee85272f57702354a7e38b5f7c
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=e6cd9610215b06ee85272f57702354a7e38b5f7c

Author: Philippe Gerum <r...@xenomai.org>
Date:   Fri Nov  4 16:25:15 2016 +0100

cobalt/posix/timer: allow usage with external clocks

There is no reason to restrict usage of POSIX timers to the standard
POSIX clocks, given that Cobalt allows registering user-defined
clocks, and nothing in the implementation assumes a specific clock
driving such timers.

---

 kernel/cobalt/posix/clock.c |   23 +++++++++++++++++++++++
 kernel/cobalt/posix/clock.h |   22 +++++++++-------------
 kernel/cobalt/posix/timer.c |   19 +++++++------------
 3 files changed, 39 insertions(+), 25 deletions(-)

diff --git a/kernel/cobalt/posix/clock.c b/kernel/cobalt/posix/clock.c
index b51cb4c..8dab55b 100644
--- a/kernel/cobalt/posix/clock.c
+++ b/kernel/cobalt/posix/clock.c
@@ -349,3 +349,26 @@ void cobalt_clock_deregister(struct xnclock *clock)
        xnclock_deregister(clock);
 }
 EXPORT_SYMBOL_GPL(cobalt_clock_deregister);
+
+struct xnclock *cobalt_clock_find(clockid_t clock_id)
+{
+       struct xnclock *clock = ERR_PTR(-EINVAL);
+       spl_t s;
+       int nr;
+
+       if (clock_id == CLOCK_MONOTONIC ||
+           clock_id == CLOCK_MONOTONIC_RAW ||
+           clock_id == CLOCK_REALTIME)
+               return &nkclock;
+       
+       if (__COBALT_CLOCK_EXT_P(clock_id)) {
+               nr = __COBALT_CLOCK_EXT_INDEX(clock_id);
+               xnlock_get_irqsave(&nklock, s);
+               if (test_bit(nr, cobalt_clock_extids))
+                       clock = external_clocks[nr];
+               xnlock_put_irqrestore(&nklock, s);
+       }
+
+       return clock;
+}
+EXPORT_SYMBOL_GPL(cobalt_clock_find);
diff --git a/kernel/cobalt/posix/clock.h b/kernel/cobalt/posix/clock.h
index 82cb0b6..c77c3a5 100644
--- a/kernel/cobalt/posix/clock.h
+++ b/kernel/cobalt/posix/clock.h
@@ -26,6 +26,8 @@
 
 #define ONE_BILLION             1000000000
 
+struct xnclock;
+
 static inline void ns2ts(struct timespec *ts, xnticks_t nsecs)
 {
        ts->tv_sec = xnclock_divrem_billion(nsecs, &ts->tv_nsec);
@@ -68,21 +70,13 @@ static inline xnticks_t clock_get_ticks(clockid_t clock_id)
 
 static inline int clock_flag(int flag, clockid_t clock_id)
 {
-       switch(flag & TIMER_ABSTIME) {
-       case 0:
+       if ((flag & TIMER_ABSTIME) == 0)
                return XN_RELATIVE;
 
-       case TIMER_ABSTIME:
-               switch(clock_id) {
-               case CLOCK_MONOTONIC:
-               case CLOCK_MONOTONIC_RAW:
-                       return XN_ABSOLUTE;
-
-               case CLOCK_REALTIME:
-                       return XN_REALTIME;
-               }
-       }
-       return -EINVAL;
+       if (clock_id == CLOCK_REALTIME)
+               return XN_REALTIME;
+
+       return XN_ABSOLUTE;
 }
 
 int __cobalt_clock_getres(clockid_t clock_id,
@@ -118,6 +112,8 @@ int cobalt_clock_register(struct xnclock *clock,
 
 void cobalt_clock_deregister(struct xnclock *clock);
 
+struct xnclock *cobalt_clock_find(clockid_t clock_id);
+
 extern DECLARE_BITMAP(cobalt_clock_extids, COBALT_MAX_EXTCLOCKS);
 
 #endif /* !_COBALT_POSIX_CLOCK_H */
diff --git a/kernel/cobalt/posix/timer.c b/kernel/cobalt/posix/timer.c
index cf1c919..c6190d1 100644
--- a/kernel/cobalt/posix/timer.c
+++ b/kernel/cobalt/posix/timer.c
@@ -47,6 +47,7 @@ timer_init(struct cobalt_timer *timer,
           const struct sigevent *__restrict__ evp) /* nklocked, IRQs off. */
 {
        struct cobalt_thread *owner = cobalt_current_thread(), *target = NULL;
+       struct xnclock *clock;
 
        /*
         * First, try to offload this operation to the extended
@@ -59,14 +60,8 @@ timer_init(struct cobalt_timer *timer,
        /*
         * Ok, we have no extension available, or we do but it does
         * not want to overload the standard behavior: handle this
-        * timer the pure Cobalt way then. We only know about standard
-        * clocks in this case.
+        * timer the pure Cobalt way then.
         */
-       if (timer->clockid != CLOCK_MONOTONIC &&
-           timer->clockid != CLOCK_MONOTONIC_RAW &&
-           timer->clockid != CLOCK_REALTIME)
-               return ERR_PTR(-EINVAL);
-
        if (evp == NULL || evp->sigev_notify == SIGEV_NONE) {
                target = owner; /* Assume SIGEV_THREAD_ID. */
                goto init;
@@ -83,11 +78,11 @@ timer_init(struct cobalt_timer *timer,
        if (target == NULL)
                return ERR_PTR(-EINVAL);
 init:
-       /*
-        * All standard clocks are based on the core clock, and we
-        * want to deliver a signal when a timer elapses.
-        */
-       xntimer_init(&timer->timerbase, &nkclock, cobalt_timer_handler,
+       clock = cobalt_clock_find(timer->clockid);
+       if (IS_ERR(clock))
+               return ERR_PTR(PTR_ERR(clock));
+
+       xntimer_init(&timer->timerbase, clock, cobalt_timer_handler,
                     target->threadbase.sched, XNTIMER_UGRAVITY);
 
        return target;


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

Reply via email to