With this patch applied, the Xenomai skin libraries are able to obtain
the execution mode the current thread without issuing a syscall. The
kernel-user interface looks as follows:

 - On thread creation (which triggers xnshadow_map), user space passes a
   pointer to an unsigned long.

 - Before going primary and after completing the switch to secondary
   mode, the nucleus writes 0 or XNRELAX to that unsigned long. The mode
   updates use __xn_put_user, so they are fail-safe (write errors are
   ignored, only an initial access_wok check is reported back).

 - User space can check its state by calling xeno_get_current_mode().
   An optional light-weight version based on __thread is also provided.

Signed-off-by: Jan Kiszka <[EMAIL PROTECTED]>
---
 include/asm-generic/bits/bind.h    |   22 +++++++++++++++++++++-
 include/asm-generic/bits/current.h |   20 ++++++++++++++++++++
 include/native/syscall.h           |    1 +
 include/nucleus/shadow.h           |    3 ++-
 include/nucleus/thread.h           |    4 ++++
 include/psos+/syscall.h            |    8 ++++++++
 include/vrtx/syscall.h             |    1 +
 include/vxworks/syscall.h          |    1 +
 ksrc/nucleus/shadow.c              |   22 ++++++++++++++++++++--
 ksrc/skins/native/syscall.c        |    3 ++-
 ksrc/skins/posix/syscall.c         |   14 +++++++++-----
 ksrc/skins/psos+/syscall.c         |   34 +++++++++++++++++++++-------------
 ksrc/skins/uitron/syscall.c        |    8 ++++++--
 ksrc/skins/vrtx/syscall.c          |    4 +++-
 ksrc/skins/vxworks/syscall.c       |    4 +++-
 src/skins/native/task.c            |   10 ++++++++++
 src/skins/posix/thread.c           |   33 +++++++++++++++++++++++++++++++--
 src/skins/psos+/task.c             |   16 +++++++++++++---
 src/skins/uitron/task.c            |   11 +++++++++--
 src/skins/vrtx/task.c              |    6 ++++++
 src/skins/vxworks/taskLib.c        |    6 ++++++
 21 files changed, 197 insertions(+), 34 deletions(-)

Index: b/include/native/syscall.h
===================================================================
--- a/include/native/syscall.h
+++ b/include/native/syscall.h
@@ -134,6 +134,7 @@ struct rt_arg_bulk {
        u_long a3;
        u_long a4;
        u_long a5;
+       u_long a6;
 };
 
 #ifdef __KERNEL__
Index: b/include/nucleus/shadow.h
===================================================================
--- a/include/nucleus/shadow.h
+++ b/include/nucleus/shadow.h
@@ -69,7 +69,8 @@ void xnshadow_grab_events(void);
 void xnshadow_release_events(void);
 
 int xnshadow_map(struct xnthread *thread,
-                xncompletion_t __user *u_completion);
+                xncompletion_t __user *u_completion,
+                unsigned long __user *u_mode);
 
 void xnshadow_unmap(struct xnthread *thread);
 
Index: b/include/nucleus/thread.h
===================================================================
--- a/include/nucleus/thread.h
+++ b/include/nucleus/thread.h
@@ -248,6 +248,10 @@ typedef struct xnthread {
 
        void *cookie;           /* Cookie to pass to the entry routine */
 
+#ifdef CONFIG_XENO_OPT_PERVASIVE
+       unsigned long __user *u_mode;   /* Thread mode variable in userland. */
+#endif /* CONFIG_XENO_OPT_PERVASIVE */
+
     XNARCH_DECL_DISPLAY_CONTEXT();
 
 } xnthread_t;
Index: b/ksrc/nucleus/shadow.c
===================================================================
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -1079,6 +1079,8 @@ redo:
                /* Grab the request token. */
                return -ERESTARTSYS;
 
+       __xn_put_user(0, thread->u_mode);
+
        preempt_disable();
 
        /* Assume that we might have been migrated while waiting for
@@ -1250,6 +1252,8 @@ void xnshadow_relax(int notify)
        /* "current" is now running into the Linux domain on behalf of the
           root thread. */
 
+       __xn_put_user(XNRELAX, thread->u_mode);
+
        trace_mark(xn_nucleus_shadow_relaxed,
                  "thread %p thread_name %s comm %s",
                  thread, xnthread_name(thread), current->comm);
@@ -1264,7 +1268,9 @@ void xnshadow_exit(void)
 }
 
 /*!
- * \fn int xnshadow_map(xnthread_t *thread, xncompletion_t __user 
*u_completion)
+ * \fn int xnshadow_map(xnthread_t *thread,
+ *                      xncompletion_t __user *u_completion,
+ *                      unsigned long __user *u_mode)
  * @internal
  * \brief Create a shadow thread context.
  *
@@ -1288,6 +1294,11 @@ void xnshadow_exit(void)
  * immediately started and "current" immediately resumes in the Xenomai
  * domain from this service.
  *
+ * @param: u_mode is the address of a mode variable in user space that
+ * will reflect the current thread mode (primary or secondary). The
+ * nucleus will try to update the variable before switching to secondary
+ * or after switching from primary mode.
+ *
  * @return 0 is returned on success. Otherwise:
  *
  * - -ERESTARTSYS is returned if the current Linux task has received a
@@ -1313,7 +1324,8 @@ void xnshadow_exit(void)
  *
  */
 
-int xnshadow_map(xnthread_t *thread, xncompletion_t __user *u_completion)
+int xnshadow_map(xnthread_t *thread, xncompletion_t __user *u_completion,
+                unsigned long __user *u_mode)
 {
        xnarch_cpumask_t affinity;
        unsigned muxid, magic;
@@ -1325,6 +1337,9 @@ int xnshadow_map(xnthread_t *thread, xnc
        if (xnthread_test_state(thread, XNMAPPED))
                return -EINVAL;
 
+       if (!access_wok(u_mode, sizeof(*u_mode)))
+               return -EFAULT;
+
 #ifdef CONFIG_MMU
        if (!(current->mm->def_flags & VM_LOCKED))
                send_sig(SIGXCPU, current, 1);
@@ -1385,6 +1400,9 @@ int xnshadow_map(xnthread_t *thread, xnc
        if (err)
                return err;
 
+       thread->u_mode = u_mode;
+       __xn_put_user(XNRELAX, u_mode);
+
        err = xnshadow_harden();
 
        xnarch_trace_pid(xnarch_user_pid(xnthread_archtcb(thread)),
Index: b/ksrc/skins/native/syscall.c
===================================================================
--- a/ksrc/skins/native/syscall.c
+++ b/ksrc/skins/native/syscall.c
@@ -191,7 +191,8 @@ static int __rt_task_create(struct pt_re
                if (__xn_safe_copy_to_user((void __user *)bulk.a1, &ph, 
sizeof(ph)))
                        err = -EFAULT;
                else {
-                       err = xnshadow_map(&task->thread_base, u_completion);
+                       err = xnshadow_map(&task->thread_base, u_completion,
+                                          (unsigned long __user *)bulk.a6);
                        if (!err)
                                goto out;
                }
Index: b/ksrc/skins/posix/syscall.c
===================================================================
--- a/ksrc/skins/posix/syscall.c
+++ b/ksrc/skins/posix/syscall.c
@@ -180,7 +180,8 @@ static int __pthread_create(struct pt_re
        if (err)
                return -err;    /* Conventionally, our error codes are 
negative. */
 
-       err = xnshadow_map(&k_tid->threadbase, NULL);
+       err = xnshadow_map(&k_tid->threadbase, NULL,
+                          (unsigned long __user *)__xn_reg_arg2(regs));
 
        if (!err && !__pthread_hash(&hkey, k_tid))
                err = -ENOMEM;
@@ -196,7 +197,8 @@ static int __pthread_create(struct pt_re
 #define __pthread_detach  __pse51_call_not_available
 
 static pthread_t __pthread_shadow(struct task_struct *p,
-                                 struct pse51_hkey *hkey)
+                                 struct pse51_hkey *hkey,
+                                 unsigned long __user *u_mode)
 {
        pthread_attr_t attr;
        pthread_t k_tid;
@@ -211,7 +213,7 @@ static pthread_t __pthread_shadow(struct
        if (err)
                return ERR_PTR(-err);
 
-       err = xnshadow_map(&k_tid->threadbase, NULL);
+       err = xnshadow_map(&k_tid->threadbase, NULL, u_mode);
 
        if (!err && !__pthread_hash(hkey, k_tid))
                err = -EAGAIN;
@@ -227,11 +229,13 @@ static pthread_t __pthread_shadow(struct
 static int __pthread_setschedparam(struct pt_regs *regs)
 {
        int policy, err, promoted = 0;
+       unsigned long __user *u_mode;
        struct sched_param param;
        struct pse51_hkey hkey;
        pthread_t k_tid;
 
        policy = __xn_reg_arg2(regs);
+       u_mode = (unsigned long __user *)__xn_reg_arg4(regs);
 
        if (__xn_safe_copy_from_user(&param,
                                     (void __user *)__xn_reg_arg3(regs), 
sizeof(param)))
@@ -241,10 +245,10 @@ static int __pthread_setschedparam(struc
        hkey.mm = current->mm;
        k_tid = __pthread_find(&hkey);
 
-       if (!k_tid && __xn_reg_arg1(regs) == __xn_reg_arg4(regs)) {
+       if (!k_tid && u_mode) {
                /* If the syscall applies to "current", and the latter is not
                   a Xenomai thread already, then shadow it. */
-               k_tid = __pthread_shadow(current, &hkey);
+               k_tid = __pthread_shadow(current, &hkey, u_mode);
                if (IS_ERR(k_tid))
                        return PTR_ERR(k_tid);
 
Index: b/ksrc/skins/psos+/syscall.c
===================================================================
--- a/ksrc/skins/psos+/syscall.c
+++ b/ksrc/skins/psos+/syscall.c
@@ -60,11 +60,14 @@ static psostask_t *__psos_task_current(s
 }
 
 /*
- * int __t_create(const char *name,
- *                u_long prio,
- *                u_long flags,
+ * int __t_create(struct psos_arg_bulk *bulk,
  *                u_long *tid_r,
  *                xncompletion_t *completion)
+ * bulk = {
+ * a1: const char *name;
+ * a2: u_long prio;
+ * a3: u_long flags;
+ * a4: unsigned long *mode;
  */
 
 static int __t_create(struct pt_regs *regs)
@@ -73,10 +76,15 @@ static int __t_create(struct pt_regs *re
        struct task_struct *p = current;
        u_long prio, flags, tid, err;
        char name[XNOBJECT_NAME_LEN];
+       struct psos_arg_bulk bulk;
        psostask_t *task;
 
+       if (__xn_safe_copy_from_user(&bulk, (void __user *)__xn_reg_arg1(regs),
+                                    sizeof(bulk)))
+               return -EFAULT;
+
        /* Get task name. */
-       if (__xn_safe_strncpy_from_user(name, (const char __user 
*)__xn_reg_arg1(regs),
+       if (__xn_safe_strncpy_from_user(name, (const char __user *)bulk.a1,
                                        sizeof(name) - 1) < 0)
                return -EFAULT;
 
@@ -85,12 +93,12 @@ static int __t_create(struct pt_regs *re
        p->comm[sizeof(p->comm) - 1] = '\0';
 
        /* Task priority. */
-       prio = __xn_reg_arg2(regs);
+       prio = bulk.a2;
        /* Task flags. Force FPU support in user-space. This will lead
           to a no-op if the platform does not support it. */
-       flags = __xn_reg_arg3(regs) | T_SHADOW | T_FPU;
+       flags = bulk.a3 | T_SHADOW | T_FPU;
        /* Completion descriptor our parent thread is pending on. */
-       u_completion = (xncompletion_t __user *)__xn_reg_arg5(regs);
+       u_completion = (xncompletion_t __user *)__xn_reg_arg3(regs);
 
        err = t_create(name, prio, 0, 0, flags, &tid);
 
@@ -100,14 +108,14 @@ static int __t_create(struct pt_regs *re
                 * about the new thread id, so we can manipulate its
                 * TCB pointer freely. */
                tid = xnthread_handle(&task->threadbase);
-               if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg4(regs), 
&tid,
+               if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg2(regs), 
&tid,
                                           sizeof(tid)))
                        return -EFAULT;
-               else {
-                       err = xnshadow_map(&task->threadbase, u_completion);    
/* May be NULL */
-                       if (!err)
-                               goto out;
-               }
+
+               err = xnshadow_map(&task->threadbase, u_completion,
+                                  (unsigned long __user *)bulk.a4);
+               if (!err)
+                       goto out;
 
                t_delete((u_long)task);
        }
Index: b/ksrc/skins/vrtx/syscall.c
===================================================================
--- a/ksrc/skins/vrtx/syscall.c
+++ b/ksrc/skins/vrtx/syscall.c
@@ -48,6 +48,7 @@ static int __muxid;
  * a1: int tid;
  * a2: int prio;
  * a3: int mode;
+ * a4: unsigned long *shadow_mode;
  * }
  */
 
@@ -89,7 +90,8 @@ static int __sc_tecreate(struct pt_regs
                                           &tid, sizeof(tid)))
                        err = -EFAULT;
                else {
-                       err = xnshadow_map(&task->threadbase, u_completion);
+                       err = xnshadow_map(&task->threadbase, u_completion,
+                                          (unsigned long __user *)bulk.a4);
                        if (!err)
                                goto done;
                }
Index: b/ksrc/skins/vxworks/syscall.c
===================================================================
--- a/ksrc/skins/vxworks/syscall.c
+++ b/ksrc/skins/vxworks/syscall.c
@@ -66,6 +66,7 @@ static WIND_TCB *__wind_task_current(str
  * a2: int prio;
  * a3: int flags;
  * a4: pthread_self();
+ * a5: unsigned long *mode;
  * }
  */
 
@@ -124,7 +125,8 @@ static int __wind_task_init(struct pt_re
                                           sizeof(ph)))
                        err = -EFAULT;
                else {
-                       err = xnshadow_map(&task->threadbase, u_completion);
+                       err = xnshadow_map(&task->threadbase, u_completion,
+                                          (unsigned long __user *)bulk.a5);
                        if (!err)
                                goto out;
                }
Index: b/ksrc/skins/uitron/syscall.c
===================================================================
--- a/ksrc/skins/uitron/syscall.c
+++ b/ksrc/skins/uitron/syscall.c
@@ -31,13 +31,15 @@
 int __ui_muxid;
 
 /*
- * int __uitron_cre_tsk(ID tskid, T_CTSK *pk_ctsk, xncompletion_t *completion)
+ * int __uitron_cre_tsk(ID tskid, T_CTSK *pk_ctsk, xncompletion_t *completion,
+ *                      unsigned long *mode)
  */
 
 static int __ui_cre_tsk(struct pt_regs *regs)
 {
        xncompletion_t __user *u_completion;
        struct task_struct *p = current;
+       unsigned long __user *u_mode;
        uitask_t *task;
        T_CTSK pk_ctsk;
        ID tskid;
@@ -54,6 +56,8 @@ static int __ui_cre_tsk(struct pt_regs *
        /* Completion descriptor our parent thread is pending on. */
        u_completion = (xncompletion_t __user *)__xn_reg_arg3(regs);
 
+       u_mode = (unsigned long __user *)__xn_reg_arg4(regs);
+
        err = cre_tsk(tskid, &pk_ctsk);
 
        if (likely(err == E_OK)) {
@@ -74,7 +78,7 @@ static int __ui_cre_tsk(struct pt_regs *
                 * recycled before we could map it; however, the risk
                 * is mitigated by consistency checks performed in
                 * xnshadow_map(). */
-               return xnshadow_map(&task->threadbase, u_completion);   /* May 
be NULL */
+               return xnshadow_map(&task->threadbase, u_completion, u_mode);
        }
 
       fail:
Index: b/include/asm-generic/bits/bind.h
===================================================================
--- a/include/asm-generic/bits/bind.h
+++ b/include/asm-generic/bits/bind.h
@@ -17,6 +17,8 @@
 #ifdef HAVE___THREAD
 __thread xnhandle_t xeno_current __attribute__ ((tls_model ("initial-exec"))) =
        XN_NO_HANDLE;
+__thread unsigned long
+xeno_current_mode __attribute__ ((tls_model ("initial-exec")));
 
 static inline void __xeno_set_current(xnhandle_t current)
 {
@@ -24,17 +26,35 @@ static inline void __xeno_set_current(xn
 }
 #else /* !HAVE___THREAD */
 pthread_key_t xeno_current_key;
+pthread_key_t xeno_current_mode_key;
 
 static inline void __xeno_set_current(xnhandle_t current)
 {
        pthread_setspecific(xeno_current_key, (void *)current);
 }
 
+unsigned long *xeno_init_current_mode(void)
+{
+       unsigned long *mode = malloc(sizeof(unsigned long));
+       pthread_setspecific(xeno_current_mode_key, mode);
+       return mode;
+}
+
+static void cleanup_current_mode(void *ptr)
+{
+       free(ptr);
+}
+
 static __attribute__ ((constructor))
-void init_current_key(void)
+void init_current_keys(void)
 {
        int err = pthread_key_create(&xeno_current_key, NULL);
+       if (err)
+               goto error_exit;
+
+       err = pthread_key_create(&xeno_current_mode_key, cleanup_current_mode);
        if (err) {
+         error_exit:
                fprintf(stderr, "Xenomai: error creating TSD key: %s\n",
                        strerror(err));
                exit(1);
Index: b/include/asm-generic/bits/current.h
===================================================================
--- a/include/asm-generic/bits/current.h
+++ b/include/asm-generic/bits/current.h
@@ -6,14 +6,27 @@
 
 #ifdef HAVE___THREAD
 extern __thread xnhandle_t xeno_current __attribute__ ((tls_model 
("initial-exec")));
+extern __thread unsigned long
+xeno_current_mode __attribute__ ((tls_model ("initial-exec")));
 
 static inline xnhandle_t xeno_get_current(void)
 {
        return xeno_current;
 }
 
+static inline unsigned long xeno_get_current_mode(void)
+{
+       return xeno_current_mode;
+}
+
+static inline unsigned long *xeno_init_current_mode(void)
+{
+       return &xeno_current_mode;
+}
+
 #else /* ! HAVE___THREAD */
 extern pthread_key_t xeno_current_key;
+extern pthread_key_t xeno_current_mode_key;
 
 static inline xnhandle_t xeno_get_current(void)
 {
@@ -24,6 +37,13 @@ static inline xnhandle_t xeno_get_curren
 
        return (xnhandle_t)val;
 }
+
+static inline unsigned long xeno_get_current_mode(void)
+{
+       return *(unsigned long *)pthread_getspecific(xeno_current_mode_key);
+}
+
+unsigned long *xeno_init_current_mode(void);
 #endif /* ! HAVE___THREAD */
 
 void xeno_set_current(void);
Index: b/src/skins/native/task.c
===================================================================
--- a/src/skins/native/task.c
+++ b/src/skins/native/task.c
@@ -89,6 +89,12 @@ static void *rt_task_trampoline(void *co
        bulk.a3 = (u_long)iargs->prio;
        bulk.a4 = (u_long)iargs->mode;
        bulk.a5 = (u_long)pthread_self();
+       bulk.a6 = (u_long)xeno_init_current_mode();
+
+       if (!bulk.a6) {
+               err = -ENOMEM;
+               goto fail;
+       }
 
        err = XENOMAI_SKINCALL2(__native_muxid,
                                __native_task_create, &bulk,
@@ -205,6 +211,10 @@ int rt_task_shadow(RT_TASK *task, const
        bulk.a3 = (u_long)prio;
        bulk.a4 = (u_long)mode;
        bulk.a5 = (u_long)pthread_self();
+       bulk.a6 = (u_long)xeno_init_current_mode();
+
+       if (!bulk.a6)
+               return -ENOMEM;
 
        err = XENOMAI_SKINCALL2(__native_muxid, __native_task_create, &bulk,
                                NULL);
Index: b/src/skins/posix/thread.c
===================================================================
--- a/src/skins/posix/thread.c
+++ b/src/skins/posix/thread.c
@@ -47,11 +47,23 @@ int __wrap_pthread_setschedparam(pthread
                                 int policy, const struct sched_param *param)
 {
        pthread_t myself = pthread_self();
+       unsigned long *mode_buf = NULL;
        int err, promoted;
 
+       if (thread == myself) {
+#ifdef HAVE___THREAD
+               mode_buf = xeno_init_current_mode();
+#else /* !HAVE___THREAD */
+               mode_buf = malloc(sizeof(*mode_buf));
+
+               if (!mode_buf)
+                       return ENOMEM;
+#endif /* !HAVE___THREAD */
+       }
+
        err = -XENOMAI_SKINCALL5(__pse51_muxid,
                                 __pse51_thread_setschedparam,
-                                thread, policy, param, myself, &promoted);
+                                thread, policy, param, mode_buf, &promoted);
 
        if (err == EPERM)
                return __real_pthread_setschedparam(thread, policy, param);
@@ -60,10 +72,17 @@ int __wrap_pthread_setschedparam(pthread
 
        if (!err && promoted) {
                old_sigharden_handler = signal(SIGHARDEN, 
&__pthread_sigharden_handler);
+#ifndef HAVE___THREAD
+               pthread_setspecific(xeno_current_mode_key, mode_buf);
+#endif /* !HAVE___THREAD */
                xeno_set_current();
                if (policy != SCHED_OTHER)
                        XENOMAI_SYSCALL1(__xn_sys_migrate, XENOMAI_XENO_DOMAIN);
        }
+#ifndef HAVE___THREAD
+       else
+               free(mode_buf);
+#endif /* !HAVE___THREAD */
 
        return err;
 }
@@ -116,6 +135,7 @@ static void *__pthread_trampoline(void *
        struct sched_param param;
        void *status = NULL;
        int parent_prio, policy;
+       unsigned long *mode_buf;
        long err;
 
        old_sigharden_handler = signal(SIGHARDEN, &__pthread_sigharden_handler);
@@ -123,10 +143,18 @@ static void *__pthread_trampoline(void *
        param.sched_priority = iargs->prio;
        policy = iargs->policy;
        parent_prio = iargs->parent_prio;
+       mode_buf = xeno_init_current_mode();
+
+       if (!mode_buf) {
+               status = (void *)ENOMEM;
+               iargs->ret = ENOMEM;
+               goto out;
+       }
 
        /* Do _not_ inline the call to pthread_self() in the syscall
           macro: this trashes the syscall regs on some archs. */
-       err = XENOMAI_SKINCALL1(__pse51_muxid, __pse51_thread_create, tid);
+       err = XENOMAI_SKINCALL2(__pse51_muxid, __pse51_thread_create, tid,
+                               mode_buf);
        iargs->ret = -err;
 
        /* We must save anything we'll need to use from *iargs on our own
@@ -159,6 +187,7 @@ static void *__pthread_trampoline(void *
        } else
                status = (void *)-err;
 
+out:
        pthread_exit(status);
 }
 
Index: b/include/vrtx/syscall.h
===================================================================
--- a/include/vrtx/syscall.h
+++ b/include/vrtx/syscall.h
@@ -85,6 +85,7 @@ struct vrtx_arg_bulk {
     u_long a1;
     u_long a2;
     u_long a3;
+    u_long a4;
 };
 
 #ifdef __KERNEL__
Index: b/include/vxworks/syscall.h
===================================================================
--- a/include/vxworks/syscall.h
+++ b/include/vxworks/syscall.h
@@ -77,6 +77,7 @@ struct wind_arg_bulk {
     u_long a2;
     u_long a3;
     u_long a4;
+    u_long a5;
 };
 
 #ifdef __KERNEL__
Index: b/src/skins/vrtx/task.c
===================================================================
--- a/src/skins/vrtx/task.c
+++ b/src/skins/vrtx/task.c
@@ -118,6 +118,12 @@ static void *vrtx_task_trampoline(void *
        bulk.a1 = (u_long)iargs->tid;
        bulk.a2 = (u_long)iargs->prio;
        bulk.a3 = (u_long)iargs->mode;
+       bulk.a4 = (u_long)xeno_init_current_mode();
+
+       if (!bulk.a4) {
+               err = -ENOMEM;
+               goto fail;
+       }
 
        err = XENOMAI_SKINCALL3(__vrtx_muxid,
                                __vrtx_tecreate,
Index: b/src/skins/vxworks/taskLib.c
===================================================================
--- a/src/skins/vxworks/taskLib.c
+++ b/src/skins/vxworks/taskLib.c
@@ -118,6 +118,12 @@ static void *wind_task_trampoline(void *
        bulk.a2 = (u_long)iargs->prio;
        bulk.a3 = (u_long)iargs->flags;
        bulk.a4 = (u_long)pthread_self();
+       bulk.a5 = (u_long)xeno_init_current_mode();
+
+       if (!bulk.a5) {
+               err = -ENOMEM;
+               goto fail;
+       }
 
        err = XENOMAI_SKINCALL3(__vxworks_muxid,
                                __vxworks_task_init,
Index: b/include/psos+/syscall.h
===================================================================
--- a/include/psos+/syscall.h
+++ b/include/psos+/syscall.h
@@ -74,6 +74,14 @@
 /* Xenomai extension: get raw count of jiffies */
 #define __psos_tm_getc      46
 
+struct psos_arg_bulk {
+
+    u_long a1;
+    u_long a2;
+    u_long a3;
+    u_long a4;
+};
+
 #ifdef __KERNEL__
 
 #ifdef __cplusplus
Index: b/src/skins/psos+/task.c
===================================================================
--- a/src/skins/psos+/task.c
+++ b/src/skins/psos+/task.c
@@ -72,6 +72,7 @@ static void *psos_task_trampoline(void *
        struct psos_task_iargs *iargs = (struct psos_task_iargs *)cookie;
        void (*entry)(u_long, u_long, u_long, u_long);
        u_long dummy_args[4] = { 0, 0, 0, 0 }, *targs;
+       struct psos_arg_bulk bulk;
        struct sched_param param;
        int policy;
        long err;
@@ -83,10 +84,19 @@ static void *psos_task_trampoline(void *
 
        old_sigharden_handler = signal(SIGHARDEN, &psos_task_sigharden);
 
-       err = XENOMAI_SKINCALL5(__psos_muxid,
+       bulk.a1 = (u_long)iargs->name;
+       bulk.a2 = (u_long)iargs->prio;
+       bulk.a3 = (u_long)iargs->flags;
+       bulk.a4 = (u_long)xeno_init_current_mode();
+
+       if (!bulk.a4) {
+               err = -ENOMEM;
+               goto fail;
+       }
+
+       err = XENOMAI_SKINCALL3(__psos_muxid,
                                __psos_t_create,
-                               iargs->name, iargs->prio, iargs->flags,
-                               iargs->tid_r, iargs->completionp);
+                               &bulk, iargs->tid_r, iargs->completionp);
        if (err)
                goto fail;
 
Index: b/src/skins/uitron/task.c
===================================================================
--- a/src/skins/uitron/task.c
+++ b/src/skins/uitron/task.c
@@ -68,6 +68,7 @@ static void *uitron_task_trampoline(void
 {
        struct uitron_task_iargs *iargs = (struct uitron_task_iargs *)cookie;
        struct sched_param param;
+       unsigned long *mode;
        void (*entry)(INT);
        int policy;
        long err;
@@ -83,10 +84,16 @@ static void *uitron_task_trampoline(void
        pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
        old_sigharden_handler = signal(SIGHARDEN, &uitron_task_sigharden);
 
-       err = XENOMAI_SKINCALL3(__uitron_muxid,
+       mode = xeno_init_current_mode();
+       if (!mode) {
+               err = -ENOMEM;
+               goto fail;
+       }
+
+       err = XENOMAI_SKINCALL4(__uitron_muxid,
                                __uitron_cre_tsk,
                                iargs->tskid, iargs->pk_ctsk,
-                               iargs->completionp);
+                               iargs->completionp, mode);
        if (err)
                goto fail;
 


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

Reply via email to