[Xenomai-git] Philippe Gerum : cobalt/timer: consider clock event affinity when pinning timers

2016-11-14 Thread git repository hosting
Module: xenomai-3
Branch: stable-3.0.x
Commit: b9642fc43473d91d11a16baee1ce0b1aaa1ec1f1
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=b9642fc43473d91d11a16baee1ce0b1aaa1ec1f1

Author: Philippe Gerum 
Date:   Mon Nov 14 11:49:09 2016 +0100

cobalt/timer: consider clock event affinity when pinning timers

Pinning a timer to the same CPU than the caller is affine to must take
into account the affinity of the clock device backing the timer.

When an affinity mismatch is detected by xntimer_set_sched(), the
timer affinity is left unchanged, which will certainly cause
additional overhead due to the requirement of waking up a thread on a
remote CPU from the timer's handler, but will also keep the situation
sane.

---

 include/cobalt/kernel/timer.h |7 ++-
 kernel/cobalt/timer.c |   17 +
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/include/cobalt/kernel/timer.h b/include/cobalt/kernel/timer.h
index 6cb2bb3..700392e 100644
--- a/include/cobalt/kernel/timer.h
+++ b/include/cobalt/kernel/timer.h
@@ -546,11 +546,8 @@ static inline void xntimer_release_ipi(void) { }
 
 #endif /* CONFIG_SMP */
 
-static inline void xntimer_set_sched(struct xntimer *timer,
-struct xnsched *sched)
-{
-   xntimer_migrate(timer, sched);
-}
+bool xntimer_set_sched(struct xntimer *timer,
+  struct xnsched *sched);
 
 char *xntimer_format_time(xnticks_t ns,
  char *buf, size_t bufsz);
diff --git a/kernel/cobalt/timer.c b/kernel/cobalt/timer.c
index dd78c38..6263f5b 100644
--- a/kernel/cobalt/timer.c
+++ b/kernel/cobalt/timer.c
@@ -541,6 +541,23 @@ void __xntimer_migrate(struct xntimer *timer, struct 
xnsched *sched)
 }
 EXPORT_SYMBOL_GPL(__xntimer_migrate);
 
+bool xntimer_set_sched(struct xntimer *timer,
+  struct xnsched *sched)
+{
+   /*
+* We may deny the request if the target CPU does not receive
+* any event from the clock device backing the timer.
+*/
+   if (cpumask_test_cpu(xnsched_cpu(sched),
+&xntimer_clock(timer)->affinity)) {
+   xntimer_migrate(timer, sched);
+   return true;
+   }
+
+   return false;
+}
+EXPORT_SYMBOL_GPL(xntimer_set_sched);
+
 int xntimer_setup_ipi(void)
 {
return ipipe_request_irq(&xnsched_realtime_domain,


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


[Xenomai-git] Philippe Gerum : cobalt/timer: fixup CPU affinity mismatch at init

2016-11-14 Thread git repository hosting
Module: xenomai-3
Branch: stable-3.0.x
Commit: 9b8d7c947089dfb0b3ca4b6f1e17a989ddc9a3e4
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=9b8d7c947089dfb0b3ca4b6f1e17a989ddc9a3e4

Author: Philippe Gerum 
Date:   Sat Nov 12 11:56:09 2016 +0100

cobalt/timer: fixup CPU affinity mismatch at init

Since recently, POSIX timers can be backed by external clock
devices. Unlike the core clock, some of those devices may be ticking
only on a restricted set of CPUs, compared to the broader real-time
CPU set. This may lead to an affinity mismatch between a thread
creating a timer, and the CPU set that can receive timer events from
the backing device.

When this happens, warning on detecting such issue while initializing
the timer without fixing up the situation is not of a great help.

It is better to pick a CPU which is a member of the clock affinity set
and make such timer affine to it instead. In such a case, the overhead
induced by rescheduling a remote thread upon timer expiry is
acceptable compared to leaving a thread waiting indefinitely for timer
events that will never come.

---

 include/cobalt/kernel/timer.h |2 --
 kernel/cobalt/sched.c |6 +++---
 kernel/cobalt/thread.c|2 --
 kernel/cobalt/timer.c |   30 --
 4 files changed, 11 insertions(+), 29 deletions(-)

diff --git a/include/cobalt/kernel/timer.h b/include/cobalt/kernel/timer.h
index d92c8c8..6cb2bb3 100644
--- a/include/cobalt/kernel/timer.h
+++ b/include/cobalt/kernel/timer.h
@@ -56,8 +56,6 @@ typedef enum xntmode {
 #define XNTIMER_GRAVITY_MASK   (XNTIMER_KGRAVITY|XNTIMER_UGRAVITY)
 #define XNTIMER_INIT_MASK  (XNTIMER_GRAVITY_MASK|XNTIMER_NOBLCK)
 
-#define __XNTIMER_CORE0x1000
-
 /* These flags are available to the real-time interfaces */
 #define XNTIMER_SPARE0  0x0100
 #define XNTIMER_SPARE1  0x0200
diff --git a/kernel/cobalt/sched.c b/kernel/cobalt/sched.c
index 7cb91a5..cbe14bd 100644
--- a/kernel/cobalt/sched.c
+++ b/kernel/cobalt/sched.c
@@ -194,11 +194,11 @@ void xnsched_init(struct xnsched *sched, int cpu)
 * exit code.
 */
xntimer_init(&sched->htimer, &nkclock, NULL,
-sched, XNTIMER_IGRAVITY|__XNTIMER_CORE);
+sched, XNTIMER_IGRAVITY);
xntimer_set_priority(&sched->htimer, XNTIMER_LOPRIO);
xntimer_set_name(&sched->htimer, htimer_name);
xntimer_init(&sched->rrbtimer, &nkclock, roundrobin_handler,
-sched, XNTIMER_IGRAVITY|__XNTIMER_CORE);
+sched, XNTIMER_IGRAVITY);
xntimer_set_name(&sched->rrbtimer, rrbtimer_name);
xntimer_set_priority(&sched->rrbtimer, XNTIMER_LOPRIO);
 
@@ -213,7 +213,7 @@ void xnsched_init(struct xnsched *sched, int cpu)
 
 #ifdef CONFIG_XENO_OPT_WATCHDOG
xntimer_init(&sched->wdtimer, &nkclock, watchdog_handler,
-sched, XNTIMER_NOBLCK|XNTIMER_IGRAVITY|__XNTIMER_CORE);
+sched, XNTIMER_NOBLCK|XNTIMER_IGRAVITY);
xntimer_set_name(&sched->wdtimer, "[watchdog]");
xntimer_set_priority(&sched->wdtimer, XNTIMER_LOPRIO);
 #endif /* CONFIG_XENO_OPT_WATCHDOG */
diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
index fb856a4..34eca35 100644
--- a/kernel/cobalt/thread.c
+++ b/kernel/cobalt/thread.c
@@ -209,8 +209,6 @@ int __xnthread_init(struct xnthread *thread,
init_completion(&thread->exited);
 
gravity = flags & XNUSER ? XNTIMER_UGRAVITY : XNTIMER_KGRAVITY;
-   if (flags & XNROOT)
-   gravity |= __XNTIMER_CORE;
xntimer_init(&thread->rtimer, &nkclock, timeout_handler,
 sched, gravity);
xntimer_set_name(&thread->rtimer, thread->name);
diff --git a/kernel/cobalt/timer.c b/kernel/cobalt/timer.c
index 3563636..dd78c38 100644
--- a/kernel/cobalt/timer.c
+++ b/kernel/cobalt/timer.c
@@ -349,29 +349,15 @@ void __xntimer_init(struct xntimer *timer,
timer->handler = handler;
timer->interval_ns = 0;
/*
-* Timers are affine to a real-time CPU. If no affinity was
-* specified, assign the timer to the first possible CPU which
-* can receive interrupt events from the clock device attached
-* to the reference clock for this timer.
+* Unlike common IRQs, timer events are per-CPU by design. If
+* the CPU the caller is affine to does not receive timer
+* events, or no affinity was specified (i.e. sched == NULL),
+* assign the timer to the first possible CPU which can
+* receive interrupt events from the clock device backing this
+* timer.
 */
-   if (sched) {
-   /*
-* Complain loudly if no tick is expected from the
-* clock device on the CPU served by the specified
-* scheduler slot. This reveals a CPU affinity
-* mismatch between the clock hardware and the client
-* code init