Module: xenomai-3
Branch: next
Commit: 350f327863fe17e5b2fe76a4a086aa472bcacf6d
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=350f327863fe17e5b2fe76a4a086aa472bcacf6d

Author: Philippe Gerum <r...@xenomai.org>
Date:   Fri Mar 18 12:12:27 2016 +0100

lib/cobalt: use lazy schedparam propagation

Do not switch to secondary mode upon schedparam updates for
propagating changes to the regular kernel, if the caller runs in
primary mode when entering pthread_setschedparam*() or
sched_setscheduler(). In such a case, the update request to the
regular kernel is left pending until the target thread resumes
execution in relaxed mode, at which point it is committed.

CAUTION: This mechanism won't update the schedparams cached by the
glibc for the caller in user-space, but this is the deal: we don't
relax threads which issue pthread_setschedparam[_ex]() from primary
mode anymore, but then only the kernel side (Cobalt and the host
kernel) will be aware of the change, and glibc might cache obsolete
information.

If the caller already runs in relaxed mode on entry to these services,
the update request takes place immediately, via the regular (g)libc
calls.

In any case, the new scheduling parameters for the target thread are
immediately applied by Cobalt, regardless of the update path followed
for the regular kernel.

---

 lib/cobalt/internal.c  |   44 ++++++++++++++++++++++++++
 lib/cobalt/sched.c     |   13 ++++----
 lib/cobalt/sigshadow.c |    8 +++++
 lib/cobalt/thread.c    |   80 +++++++++++++++++-------------------------------
 4 files changed, 87 insertions(+), 58 deletions(-)

diff --git a/lib/cobalt/internal.c b/lib/cobalt/internal.c
index 5b89db5..cb1d53b 100644
--- a/lib/cobalt/internal.c
+++ b/lib/cobalt/internal.c
@@ -514,3 +514,47 @@ int cobalt_sched_weighted_prio(int policy,
 {
        return XENOMAI_SYSCALL2(sc_cobalt_sched_weightprio, policy, param_ex);
 }
+
+int cobalt_xlate_schedparam(int policy,
+                           const struct sched_param_ex *param_ex,
+                           struct sched_param *param)
+{
+       int std_policy, priority;
+
+       /*
+        * Translates Cobalt scheduling parameters to native ones,
+        * based on a best approximation for Cobalt policies which are
+        * not available from the host kernel.
+        */
+       std_policy = policy;
+       priority = param_ex->sched_priority;
+
+       switch (policy) {
+       case SCHED_WEAK:
+               std_policy = priority ? SCHED_FIFO : SCHED_OTHER;
+               break;
+       default:
+               std_policy = SCHED_FIFO;
+               /* falldown wanted. */
+       case SCHED_OTHER:
+       case SCHED_FIFO:
+       case SCHED_RR:
+               /*
+                * The Cobalt priority range is larger than those of
+                * the native SCHED_FIFO/RR classes, so we have to cap
+                * the priority value accordingly.  We also remap
+                * "weak" (negative) priorities - which are only
+                * meaningful for the Cobalt core - to regular values.
+                */
+               if (priority > __cobalt_std_fifo_maxpri)
+                       priority = __cobalt_std_fifo_maxpri;
+       }
+
+       if (priority < 0)
+               priority = -priority;
+       
+       memset(param, 0, sizeof(*param));
+       param->sched_priority = priority;
+
+       return std_policy;
+}
diff --git a/lib/cobalt/sched.c b/lib/cobalt/sched.c
index b0292b5..87b9235 100644
--- a/lib/cobalt/sched.c
+++ b/lib/cobalt/sched.c
@@ -26,7 +26,6 @@
 #include <sys/types.h>
 #include <semaphore.h>
 #include <asm/xenomai/syscall.h>
-#include "current.h"
 #include "internal.h"
 
 /**
@@ -297,11 +296,13 @@ int sched_setscheduler_ex(pid_t pid,
                return EINVAL;
 
        /* See pthread_setschedparam_ex(). */
-       
-       std_policy = cobalt_xlate_schedparam(policy, param_ex, &std_param);
-       ret = __STD(sched_setscheduler(pid, std_policy, &std_param));
-       if (ret)
-               return errno;
+
+       if (cobalt_is_relaxed()) {
+               std_policy = cobalt_xlate_schedparam(policy, param_ex, 
&std_param);
+               ret = __STD(sched_setscheduler(pid, std_policy, &std_param));
+               if (ret)
+                       return errno;
+       }
 
        ret = -XENOMAI_SYSCALL5(sc_cobalt_sched_setscheduler_ex,
                                pid, policy, param_ex,
diff --git a/lib/cobalt/sigshadow.c b/lib/cobalt/sigshadow.c
index 3f4e9c5..48d5a81 100644
--- a/lib/cobalt/sigshadow.c
+++ b/lib/cobalt/sigshadow.c
@@ -59,6 +59,14 @@ int cobalt_sigshadow_handler(int sig, siginfo_t *si, void 
*ctxt)
                skip = nr > 3 ? 3 : 0;
                XENOMAI_SYSCALL3(sc_cobalt_backtrace, nr - skip, frames + skip, 
arg);
                break;
+       case SIGSHADOW_ACTION_HOME:
+               /*
+                * We have been asked to call home from the current
+                * context: sending a query for retrieving our handle
+                * will just do this.
+                */
+               cobalt_get_current_slow();
+               break;
        default:
                return 0;
        }
diff --git a/lib/cobalt/thread.c b/lib/cobalt/thread.c
index e6b3eae..8b4568d 100644
--- a/lib/cobalt/thread.c
+++ b/lib/cobalt/thread.c
@@ -26,7 +26,6 @@
 #include <sys/types.h>
 #include <semaphore.h>
 #include <asm/xenomai/syscall.h>
-#include "current.h"
 #include "internal.h"
 
 /**
@@ -46,50 +45,6 @@ static pthread_attr_ex_t default_attr_ex;
 
 static int linuxthreads;
 
-int cobalt_xlate_schedparam(int policy,
-                           const struct sched_param_ex *param_ex,
-                           struct sched_param *param)
-{
-       int std_policy, priority;
-
-       /*
-        * Translates Cobalt scheduling parameters to native ones,
-        * based on a best approximation for Cobalt policies which are
-        * not available from the host kernel.
-        */
-       std_policy = policy;
-       priority = param_ex->sched_priority;
-
-       switch (policy) {
-       case SCHED_WEAK:
-               std_policy = priority ? SCHED_FIFO : SCHED_OTHER;
-               break;
-       default:
-               std_policy = SCHED_FIFO;
-               /* falldown wanted. */
-       case SCHED_OTHER:
-       case SCHED_FIFO:
-       case SCHED_RR:
-               /*
-                * The Cobalt priority range is larger than those of
-                * the native SCHED_FIFO/RR classes, so we have to cap
-                * the priority value accordingly.  We also remap
-                * "weak" (negative) priorities - which are only
-                * meaningful for the Cobalt core - to regular values.
-                */
-               if (priority > __cobalt_std_fifo_maxpri)
-                       priority = __cobalt_std_fifo_maxpri;
-       }
-
-       if (priority < 0)
-               priority = -priority;
-       
-       memset(param, 0, sizeof(*param));
-       param->sched_priority = priority;
-
-       return std_policy;
-}
-
 struct pthread_iargs {
        struct sched_param_ex param_ex;
        int policy;
@@ -125,7 +80,10 @@ static void *cobalt_thread_trampoline(void *p)
        start = iargs->start;
        arg = iargs->arg;
 
-       /* Set our scheduling parameters for the host kernel first. */
+       /*
+        * We don't have any Xenomai extension yet, set our base
+        * scheduling parameters for the host kernel first.
+        */
        std_policy = cobalt_xlate_schedparam(policy, &param_ex, &std_param);
        ret = __STD(pthread_setschedparam(ptid, std_policy, &std_param));
        if (ret)
@@ -652,13 +610,31 @@ int pthread_setschedparam_ex(pthread_t thread,
        __u32 u_winoff;
 
        /*
-        * First we tell the libc and the regular kernel about the
-        * policy/param change, then we tell Xenomai.
+        * If we enter this call over a relaxed context, take the
+        * opportunity to tell the host kernel via the regular libc
+        * about the new schedparams right now, then tell Xenomai
+        * next.  Otherwise, send the request to Xenomai only, which
+        * will propagate the change to the host kernel asap,
+        * i.e. almost immediately if the target thread is already
+        * relaxed, or when it relaxes otherwise.
+        *
+        * CAUTION: when lazy propagation has to take place
+        * (i.e. calling pthread_setschedparam_ex() from primary
+        * mode), glibc's cached idea of the current schedparams of
+        * the target thread will be out of sync. This is part of the
+        * trade-off to keep the caller running in primary mode
+        * throughout this service.
+        *
+        * Application which are sensitive to this issue with Xenomai
+        * threads should refrain from mixing APIs for managing
+        * scheduling parameters, and only rely on libcobalt for this.
         */
-       std_policy = cobalt_xlate_schedparam(policy, param_ex, &std_param);
-       ret = __STD(pthread_setschedparam(thread, std_policy, &std_param));
-       if (ret)
-               return ret;
+       if (cobalt_is_relaxed()) { /* True if shadow not mapped yet. */
+               std_policy = cobalt_xlate_schedparam(policy, param_ex, 
&std_param);
+               ret = __STD(pthread_setschedparam(thread, std_policy, 
&std_param));
+               if (ret)
+                       return ret;
+       }
 
        ret = -XENOMAI_SYSCALL5(sc_cobalt_thread_setschedparam_ex,
                                thread, policy, param_ex,


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

Reply via email to