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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Thu Nov 10 16:31:56 2011 +0100

cobalt: generalize support for extended scheduling attributes

We provide the necessary bits to create threads from userland within
Cobalt-specific scheduling classes, like SCHED_COBALT, SCHED_SPORADIC
or SCHED_TP.

To this end, we introduce pthread_create_ex(), which accepts an
extended thread attribute structure to hold the class-specific
parameters. In addition, a set of attribute accessors for this
structure is also provided, as a collection of pthread_attr_*_ex()
calls.

pthread_create() is internally rebased on pthread_create_ex(), and the
kernel support for creating Cobalt shadows is changed to accept the
extended attribute set.

---

 include/cobalt/pthread.h |  141 +++++++++++++++++--------
 kernel/cobalt/syscall.c  |   39 ++++---
 lib/cobalt/Makefile.am   |    1 +
 lib/cobalt/Makefile.in   |   28 ++++--
 lib/cobalt/attr.c        |  121 +++++++++++++++++++++
 lib/cobalt/thread.c      |  261 +++++++++++++++++++++++++--------------------
 6 files changed, 408 insertions(+), 183 deletions(-)

diff --git a/include/cobalt/pthread.h b/include/cobalt/pthread.h
index 955a6b4..acfda12 100644
--- a/include/cobalt/pthread.h
+++ b/include/cobalt/pthread.h
@@ -258,11 +258,11 @@ int pthread_attr_getfp_np(const pthread_attr_t *attr,
 int pthread_attr_setfp_np(pthread_attr_t *attr,
                          int use_fp);
 
-int pthread_attr_getaffinity_np (const pthread_attr_t *attr,
-                                xnarch_cpumask_t *mask);
+int pthread_attr_getaffinity_np(const pthread_attr_t *attr,
+                               xnarch_cpumask_t *mask);
 
-int pthread_attr_setaffinity_np (pthread_attr_t *attr,
-                                xnarch_cpumask_t mask);
+int pthread_attr_setaffinity_np(pthread_attr_t *attr,
+                               xnarch_cpumask_t mask);
 
 int pthread_create(pthread_t *tid,
                   const pthread_attr_t *attr,
@@ -408,49 +408,18 @@ int pthread_set_name_np(pthread_t thread,
 
 #else /* !(__KERNEL__ || __XENO_SIM__) */
 
+typedef struct {
+       pthread_attr_t std;
+       struct {
+               int sched_policy;
+               struct sched_param_ex sched_param;
+       } nonstd;
+} pthread_attr_ex_t;
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#ifndef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL
-int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr,
-                                 int *proto);
-
-int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr,
-                                 int proto);
-#endif
-
-#ifndef HAVE_PTHREAD_CONDATTR_SETCLOCK
-int pthread_condattr_getclock(const pthread_condattr_t *attr,
-                             clockid_t *clk_id);
-
-int pthread_condattr_setclock(pthread_condattr_t *attr,
-                             clockid_t clk_id);
-#endif
-
-int pthread_make_periodic_np(pthread_t thread,
-                            clockid_t clk_id,
-                            struct timespec *starttp,
-                            struct timespec *periodtp);
-
-int pthread_wait_np(unsigned long *overruns_r);
-
-int pthread_set_mode_np(int clrmask, int setmask,
-                       int *mask_r);
-
-int pthread_set_name_np(pthread_t thread,
-                       const char *name);
-
-int pthread_probe_np(pid_t tid);
-
-int pthread_getschedparam_ex(pthread_t tid,
-                            int *pol,
-                            struct sched_param_ex *par);
-
-int pthread_setschedparam_ex(pthread_t tid,
-                            int pol,
-                            const struct sched_param_ex *par);
-
 COBALT_DECL(int, pthread_attr_setschedpolicy(pthread_attr_t *attr,
                                             int policy));
 
@@ -545,6 +514,92 @@ COBALT_DECL(int, pthread_cond_broadcast(pthread_cond_t 
*cond));
 
 COBALT_DECL(int, pthread_kill(pthread_t tid, int sig));
 
+#ifndef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL
+COBALT_DECL(int, pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr,
+                                              int *proto));
+
+COBALT_DECL(int, pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr,
+                                              int proto));
+#endif
+
+#ifndef HAVE_PTHREAD_CONDATTR_SETCLOCK
+COBALT_DECL(int, pthread_condattr_getclock(const pthread_condattr_t *attr,
+                                          clockid_t *clk_id));
+
+COBALT_DECL(int pthread_condattr_setclock(pthread_condattr_t *attr,
+                                         clockid_t clk_id));
+#endif
+
+int pthread_make_periodic_np(pthread_t thread,
+                            clockid_t clk_id,
+                            struct timespec *starttp,
+                            struct timespec *periodtp);
+
+int pthread_wait_np(unsigned long *overruns_r);
+
+int pthread_set_mode_np(int clrmask, int setmask,
+                       int *mask_r);
+
+int pthread_set_name_np(pthread_t thread,
+                       const char *name);
+
+int pthread_probe_np(pid_t tid);
+
+int pthread_create_ex(pthread_t *tid,
+                     const pthread_attr_ex_t *attr_ex,
+                     void *(*start)(void *),
+                     void *arg);
+
+int pthread_getschedparam_ex(pthread_t tid,
+                            int *pol,
+                            struct sched_param_ex *par);
+
+int pthread_setschedparam_ex(pthread_t tid,
+                            int pol,
+                            const struct sched_param_ex *par);
+
+int pthread_attr_init_ex(pthread_attr_ex_t *attr_ex);
+
+int pthread_attr_destroy_ex(pthread_attr_ex_t *attr_ex);
+
+int pthread_attr_setschedpolicy_ex(pthread_attr_ex_t *attr_ex,
+                                  int policy);
+
+int pthread_attr_getschedpolicy_ex(const pthread_attr_ex_t *attr_ex,
+                                  int *policy);
+
+int pthread_attr_setschedparam_ex(pthread_attr_ex_t *attr_ex,
+                                 const struct sched_param_ex *param_ex);
+
+int pthread_attr_getschedparam_ex(const pthread_attr_ex_t *attr_ex,
+                                 struct sched_param_ex *param_ex);
+
+int pthread_attr_getinheritsched_ex(const pthread_attr_ex_t *attr_ex,
+                                   int *inheritsched);
+
+int pthread_attr_setinheritsched_ex(pthread_attr_ex_t *attr_ex,
+                                   int inheritsched);
+
+int pthread_attr_getdetachstate_ex(const pthread_attr_ex_t *attr_ex,
+                                  int *detachstate);
+
+int pthread_attr_setdetachstate_ex(pthread_attr_ex_t *attr_ex,
+                                  int detachstate);
+
+int pthread_attr_setdetachstate_ex(pthread_attr_ex_t *attr_ex,
+                                  int detachstate);
+
+int pthread_attr_getstacksize_ex(const pthread_attr_ex_t *attr_ex,
+                                size_t *stacksize);
+
+int pthread_attr_setstacksize_ex(pthread_attr_ex_t *attr_ex,
+                                size_t stacksize);
+
+int pthread_attr_getscope_ex(const pthread_attr_ex_t *attr_ex,
+                            int *scope);
+
+int pthread_attr_setscope_ex(pthread_attr_ex_t *attr_ex,
+                            int scope);
 #ifdef __cplusplus
 }
 #endif
diff --git a/kernel/cobalt/syscall.c b/kernel/cobalt/syscall.c
index d5c2ff8..9574eeb 100644
--- a/kernel/cobalt/syscall.c
+++ b/kernel/cobalt/syscall.c
@@ -207,16 +207,19 @@ static int __tid_probe(pid_t h_tid)
        return ret;
 }
 
-static int __pthread_create(unsigned long tid,
-                           int policy, int sched_prio,
+static int __pthread_create(unsigned long tid, int policy,
+                           struct sched_param_ex __user *u_param,
                            unsigned long __user *u_mode)
 {
        struct task_struct *p = current;
+       struct sched_param_ex param;
        struct cobalt_hkey hkey;
        pthread_attr_t attr;
        pthread_t k_tid;
-       int err;
+       int ret;
 
+       if (__xn_safe_copy_from_user(&param, u_param, sizeof(param)))
+               return -EFAULT;
        /*
         * We have been passed the pthread_t identifier the user-space
         * POSIX library has assigned to our caller; we'll index our
@@ -233,25 +236,31 @@ static int __pthread_create(unsigned long tid,
        pthread_attr_init(&attr);
        attr.policy = policy;
        attr.detachstate = PTHREAD_CREATE_DETACHED;
-       attr.schedparam_ex.sched_priority = sched_prio;
+       attr.schedparam_ex = param;
        attr.fp = 1;
        attr.name = p->comm;
 
-       err = pthread_create(&k_tid, &attr, NULL, NULL);
+       ret = pthread_create(&k_tid, &attr, NULL, NULL);
+       if (ret)
+               return -ret;
 
-       if (err)
-               return -err;    /* Conventionally, our error codes are 
negative. */
+       ret = xnshadow_map(&k_tid->threadbase, NULL, u_mode);
+       if (ret)
+               goto fail;
 
-       err = xnshadow_map(&k_tid->threadbase, NULL, u_mode);
-       if (err == 0 && !__pthread_hash(&hkey, k_tid, task_pid_vnr(p)))
-               err = -ENOMEM;
+       if (!__pthread_hash(&hkey, k_tid, task_pid_vnr(p))) {
+               ret = -ENOMEM;
+               goto fail;
+       }
 
-       if (err)
-               cobalt_thread_abort(k_tid, NULL);
-       else
-               k_tid->hkey = hkey;
+       k_tid->hkey = hkey;
 
-       return err;
+       return 0;
+
+fail:
+       cobalt_thread_abort(k_tid, NULL);
+
+       return ret;
 }
 
 #define __pthread_detach  __cobalt_call_not_available
diff --git a/lib/cobalt/Makefile.am b/lib/cobalt/Makefile.am
index 6e5942f..28d8453 100644
--- a/lib/cobalt/Makefile.am
+++ b/lib/cobalt/Makefile.am
@@ -12,6 +12,7 @@ libcobalt_la_LDFLAGS = @XENO_DLOPEN_CONSTRAINT@ -version-info 
2:0:0 -lpthread -l
 
 libcobalt_la_SOURCES = \
        assert_context.c \
+       attr.c \
        bind.c \
        current.c \
        sem_heap.c \
diff --git a/lib/cobalt/Makefile.in b/lib/cobalt/Makefile.in
index 38b0342..127e993 100644
--- a/lib/cobalt/Makefile.in
+++ b/lib/cobalt/Makefile.in
@@ -79,15 +79,16 @@ am__installdirs = "$(DESTDIR)$(libdir)"
 LTLIBRARIES = $(lib_LTLIBRARIES)
 libcobalt_la_LIBADD =
 am_libcobalt_la_OBJECTS = libcobalt_la-assert_context.lo \
-       libcobalt_la-bind.lo libcobalt_la-current.lo \
-       libcobalt_la-sem_heap.lo libcobalt_la-sigshadow.lo \
-       libcobalt_la-timeconv.lo libcobalt_la-init.lo \
-       libcobalt_la-internal.lo libcobalt_la-thread.lo \
-       libcobalt_la-timer.lo libcobalt_la-semaphore.lo \
-       libcobalt_la-clock.lo libcobalt_la-cond.lo libcobalt_la-mq.lo \
-       libcobalt_la-mutex.lo libcobalt_la-shm.lo \
-       libcobalt_la-select.lo libcobalt_la-rtdm.lo \
-       libcobalt_la-printf.lo libcobalt_la-wrappers.lo
+       libcobalt_la-attr.lo libcobalt_la-bind.lo \
+       libcobalt_la-current.lo libcobalt_la-sem_heap.lo \
+       libcobalt_la-sigshadow.lo libcobalt_la-timeconv.lo \
+       libcobalt_la-init.lo libcobalt_la-internal.lo \
+       libcobalt_la-thread.lo libcobalt_la-timer.lo \
+       libcobalt_la-semaphore.lo libcobalt_la-clock.lo \
+       libcobalt_la-cond.lo libcobalt_la-mq.lo libcobalt_la-mutex.lo \
+       libcobalt_la-shm.lo libcobalt_la-select.lo \
+       libcobalt_la-rtdm.lo libcobalt_la-printf.lo \
+       libcobalt_la-wrappers.lo
 libcobalt_la_OBJECTS = $(am_libcobalt_la_OBJECTS)
 libcobalt_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
        $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -277,6 +278,7 @@ lib_LTLIBRARIES = libcobalt.la
 libcobalt_la_LDFLAGS = @XENO_DLOPEN_CONSTRAINT@ -version-info 2:0:0 -lpthread 
-lrt
 libcobalt_la_SOURCES = \
        assert_context.c \
+       attr.c \
        bind.c \
        current.c \
        sem_heap.c \
@@ -378,6 +380,7 @@ distclean-compile:
        -rm -f *.tab.c
 
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libcobalt_la-assert_context.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libcobalt_la-attr.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libcobalt_la-bind.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libcobalt_la-clock.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libcobalt_la-cond.Plo@am__quote@
@@ -426,6 +429,13 @@ libcobalt_la-assert_context.lo: assert_context.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) 
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(libcobalt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o 
libcobalt_la-assert_context.lo `test -f 'assert_context.c' || echo 
'$(srcdir)/'`assert_context.c
 
+libcobalt_la-attr.lo: attr.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) 
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(libcobalt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT 
libcobalt_la-attr.lo -MD -MP -MF $(DEPDIR)/libcobalt_la-attr.Tpo -c -o 
libcobalt_la-attr.lo `test -f 'attr.c' || echo '$(srcdir)/'`attr.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/libcobalt_la-attr.Tpo 
$(DEPDIR)/libcobalt_la-attr.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='attr.c' 
object='libcobalt_la-attr.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) 
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(libcobalt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o 
libcobalt_la-attr.lo `test -f 'attr.c' || echo '$(srcdir)/'`attr.c
+
 libcobalt_la-bind.lo: bind.c
 @am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) 
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(libcobalt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT 
libcobalt_la-bind.lo -MD -MP -MF $(DEPDIR)/libcobalt_la-bind.Tpo -c -o 
libcobalt_la-bind.lo `test -f 'bind.c' || echo '$(srcdir)/'`bind.c
 @am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/libcobalt_la-bind.Tpo 
$(DEPDIR)/libcobalt_la-bind.Plo
diff --git a/lib/cobalt/attr.c b/lib/cobalt/attr.c
new file mode 100644
index 0000000..5c8f8d7
--- /dev/null
+++ b/lib/cobalt/attr.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 Philippe Gerum <r...@xenomai.org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+ */
+
+#include <stddef.h>
+#include <errno.h>
+#include <pthread.h>
+
+int pthread_attr_init_ex(pthread_attr_ex_t *attr_ex)
+{
+       struct sched_param param;
+       int policy;
+
+       /* We start with the default standard attribute set. */
+       pthread_attr_init(&attr_ex->std);
+       pthread_attr_getschedpolicy(&attr_ex->std, &policy);
+       attr_ex->nonstd.sched_policy = policy;
+       pthread_attr_getschedparam(&attr_ex->std, &param);
+       attr_ex->nonstd.sched_param.sched_priority = param.sched_priority;
+
+       return 0;
+}
+
+int pthread_attr_destroy_ex(pthread_attr_ex_t *attr_ex)
+{
+       return pthread_attr_destroy(&attr_ex->std);
+}
+
+int pthread_attr_setschedpolicy_ex(pthread_attr_ex_t *attr_ex,
+                                  int policy)
+{
+       attr_ex->nonstd.sched_policy = policy;
+
+       return 0;
+}
+
+int pthread_attr_getschedpolicy_ex(const pthread_attr_ex_t *attr_ex,
+                                  int *policy)
+{
+       *policy = attr_ex->nonstd.sched_policy;
+
+       return 0;
+}
+
+int pthread_attr_setschedparam_ex(pthread_attr_ex_t *attr_ex,
+                                 const struct sched_param_ex *param_ex)
+{
+       attr_ex->nonstd.sched_param = *param_ex;
+
+       return 0;
+}
+
+int pthread_attr_getschedparam_ex(const pthread_attr_ex_t *attr_ex,
+                                 struct sched_param_ex *param_ex)
+{
+       *param_ex = attr_ex->nonstd.sched_param;
+
+       return 0;
+}
+
+int pthread_attr_setinheritsched_ex(pthread_attr_ex_t *attr_ex,
+                                   int inheritsched)
+{
+       return pthread_attr_setinheritsched(&attr_ex->std, inheritsched);
+}
+
+int pthread_attr_getinheritsched_ex(const pthread_attr_ex_t *attr_ex,
+                                   int *inheritsched)
+{
+       return pthread_attr_getinheritsched(&attr_ex->std, inheritsched);
+}
+
+int pthread_attr_getdetachstate_ex(const pthread_attr_ex_t *attr_ex,
+                                  int *detachstate)
+{
+       return pthread_attr_getdetachstate(&attr_ex->std, detachstate);
+}
+
+int pthread_attr_setdetachstate_ex(pthread_attr_ex_t *attr_ex,
+                                  int detachstate)
+{
+       return pthread_attr_setdetachstate(&attr_ex->std, detachstate);
+}
+
+int pthread_attr_getstacksize_ex(const pthread_attr_ex_t *attr_ex,
+                                size_t *stacksize)
+{
+       return pthread_attr_getstacksize(&attr_ex->std, stacksize);
+}
+
+int pthread_attr_setstacksize_ex(pthread_attr_ex_t *attr_ex,
+                                size_t stacksize)
+{
+       return pthread_attr_setstacksize(&attr_ex->std, stacksize);
+}
+
+int pthread_attr_getscope_ex(const pthread_attr_ex_t *attr_ex,
+                            int *scope)
+{
+       return pthread_attr_getscope(&attr_ex->std, scope);
+}
+
+int pthread_attr_setscope_ex(pthread_attr_ex_t *attr_ex,
+                            int scope)
+{
+       return pthread_attr_setscope(&attr_ex->std, scope);
+}
diff --git a/lib/cobalt/thread.c b/lib/cobalt/thread.c
index e4a2ca2..dd23587 100644
--- a/lib/cobalt/thread.c
+++ b/lib/cobalt/thread.c
@@ -32,28 +32,29 @@
 
 extern int __cobalt_muxid;
 
-static pthread_attr_t default_attr;
+static pthread_attr_ex_t default_attr_ex;
+
 static int linuxthreads;
 
 int __wrap_pthread_setschedparam(pthread_t thread,
                                 int policy, const struct sched_param *param)
 {
-       pthread_t myself = pthread_self();
+       volatile pthread_t myself = pthread_self();
        unsigned long mode_offset;
-       int err, promoted;
+       int ret, promoted;
 
        if (thread == myself)
                xeno_fault_stack();
 
-       err = -XENOMAI_SKINCALL5(__cobalt_muxid,
+       ret = -XENOMAI_SKINCALL5(__cobalt_muxid,
                                 __cobalt_thread_setschedparam,
                                 thread, policy, param,
                                 &mode_offset, &promoted);
 
-       if (err == EPERM)
+       if (ret == EPERM)
                return __STD(pthread_setschedparam(thread, policy, param));
 
-       if (!err && promoted) {
+       if (ret == 0 && promoted) {
                xeno_sigshadow_install_once();
                xeno_set_current();
                xeno_set_current_mode(mode_offset);
@@ -61,31 +62,30 @@ int __wrap_pthread_setschedparam(pthread_t thread,
                        XENOMAI_SYSCALL1(__xn_sys_migrate, XENOMAI_XENO_DOMAIN);
        }
 
-       return err;
+       return ret;
 }
 
 int pthread_setschedparam_ex(pthread_t thread,
                             int policy, const struct sched_param_ex *param)
 {
-       pthread_t myself = pthread_self();
+       volatile pthread_t myself = pthread_self();
        struct sched_param short_param;
        unsigned long mode_offset;
-       int err, promoted;
+       int ret, promoted;
 
        if (thread == myself)
                xeno_fault_stack();
 
-       err = -XENOMAI_SKINCALL5(__cobalt_muxid,
+       ret = -XENOMAI_SKINCALL5(__cobalt_muxid,
                                 __cobalt_thread_setschedparam_ex,
                                 thread, policy, param,
                                 &mode_offset, &promoted);
-
-       if (err == EPERM) {
+       if (ret == EPERM) {
                short_param.sched_priority = param->sched_priority;
                return __STD(pthread_setschedparam(thread, policy, 
&short_param));
        }
 
-       if (!err && promoted) {
+       if (ret == 0 && promoted) {
                xeno_sigshadow_install_once();
                xeno_set_current();
                xeno_set_current_mode(mode_offset);
@@ -93,23 +93,22 @@ int pthread_setschedparam_ex(pthread_t thread,
                        XENOMAI_SYSCALL1(__xn_sys_migrate, XENOMAI_XENO_DOMAIN);
        }
 
-       return err;
+       return ret;
 }
 
 int __wrap_pthread_getschedparam(pthread_t thread,
                                 int *__restrict__ policy,
                                 struct sched_param *__restrict__ param)
 {
-       int err;
+       int ret;
 
-       err = -XENOMAI_SKINCALL3(__cobalt_muxid,
+       ret = -XENOMAI_SKINCALL3(__cobalt_muxid,
                                 __cobalt_thread_getschedparam,
                                 thread, policy, param);
-
-       if (err == ESRCH)
+       if (ret == ESRCH)
                return __STD(pthread_getschedparam(thread, policy, param));
 
-       return err;
+       return ret;
 }
 
 int pthread_getschedparam_ex(pthread_t thread,
@@ -117,29 +116,29 @@ int pthread_getschedparam_ex(pthread_t thread,
                             struct sched_param_ex *__restrict__ param)
 {
        struct sched_param short_param;
-       int err;
+       int ret;
 
-       err = -XENOMAI_SKINCALL3(__cobalt_muxid,
+       ret = -XENOMAI_SKINCALL3(__cobalt_muxid,
                                 __cobalt_thread_getschedparam_ex,
                                 thread, policy, param);
-
-       if (err == ESRCH) {
-               err = __STD(pthread_getschedparam(thread, policy, 
&short_param));
-               if (err == 0)
+       if (ret == ESRCH) {
+               ret = __STD(pthread_getschedparam(thread, policy, 
&short_param));
+               if (ret == 0)
                        param->sched_priority = short_param.sched_priority;
        }
 
-       return err;
+       return ret;
 }
 
 int __wrap_sched_yield(void)
 {
-       int err = -XENOMAI_SKINCALL0(__cobalt_muxid, __cobalt_sched_yield);
+       int ret;
 
-       if (err == -1)
-               err = __STD(sched_yield());
+       ret = -XENOMAI_SKINCALL0(__cobalt_muxid, __cobalt_sched_yield);
+       if (ret == -1)
+               ret = __STD(sched_yield());
 
-       return err;
+       return ret;
 }
 
 int __wrap_sched_get_priority_min(int policy)
@@ -178,131 +177,161 @@ int __wrap_pthread_yield(void)
 }
 
 struct pthread_iargs {
-       void *(*start) (void *);
-       void *arg;
+       struct sched_param_ex param_ex;
        int policy;
-       int parent_prio, prio;
+       void *(*start)(void *);
+       void *arg;
+       int parent_prio;
        sem_t sync;
        int ret;
 };
 
-static void *__pthread_trampoline(void *arg)
+static void *__pthread_trampoline(void *p)
 {
-       struct pthread_iargs *iargs = (struct pthread_iargs *)arg;
-       /* Avoid smart versions of gcc to trashes the syscall
-          registers (again, see later comment). */
+       /*
+        * Volatile is to prevent (too) smart gcc releases from
+        * trashing the syscall registers (see later comment).
+        */
        volatile pthread_t tid = pthread_self();
-       void *(*start) (void *), *cookie;
+       struct pthread_iargs *iargs = p;
+       struct sched_param_ex param_ex;
+       void *(*start)(void *), *arg;
        unsigned long mode_offset;
-       struct sched_param param;
-       void *status = NULL;
        int parent_prio, policy;
-       long err;
+       long ret;
 
        xeno_sigshadow_install_once();
 
-       param.sched_priority = iargs->prio;
+       param_ex = iargs->param_ex;
        policy = iargs->policy;
        parent_prio = iargs->parent_prio;
-
-       /* Do _not_ inline the call to pthread_self() in the syscall
-          macro: this trashes the syscall regs on some archs. */
-       err = XENOMAI_SKINCALL4(__cobalt_muxid, __cobalt_thread_create, tid,
-                               iargs->policy, iargs->prio, &mode_offset);
-       iargs->ret = -err;
-
-       /* We must save anything we'll need to use from *iargs on our own
-          stack now before posting the sync sema4, since our released
-          parent could unwind the stack space onto which the iargs struct
-          is laid on before we actually get the CPU back. */
-
        start = iargs->start;
-       cookie = iargs->arg;
-
-       if (!err) {
+       arg = iargs->arg;
+
+       /*
+        * Do _not_ inline the call to pthread_self() in the syscall
+        * macro: this trashes the syscall regs on some archs.
+        */
+       ret = XENOMAI_SKINCALL4(__cobalt_muxid, __cobalt_thread_create, tid,
+                               policy, &param_ex, &mode_offset);
+       if (ret == 0) {
                xeno_set_current();
                xeno_set_current_mode(mode_offset);
        }
 
+       /*
+        * We must access anything we'll need from *iargs before
+        * posting the sync semaphore, since our released parent could
+        * unwind the stack space onto which the iargs struct is laid
+        * on before we actually get the CPU back.
+        */
+       iargs->ret = -ret;
        __STD(sem_post(&iargs->sync));
+       if (ret)
+               return (void *)-ret;
 
-       if (!err) {
-               /* If the thread running pthread_create runs with the same
-                  priority as us, we should leave it running, as if there never
-                  was a synchronization with a semaphore. */
-               if (param.sched_priority == parent_prio)
-                       __wrap_sched_yield();
+       /*
+        * If the parent thread runs with the same priority as we do,
+        * then we should yield the CPU to it, to preserve the
+        * scheduling order.
+        */
+       if (param_ex.sched_priority == parent_prio)
+               __wrap_sched_yield();
 
-               if (policy != SCHED_OTHER)
-                       XENOMAI_SYSCALL1(__xn_sys_migrate, XENOMAI_XENO_DOMAIN);
-               status = start(cookie);
-       } else
-               status = (void *)-err;
+       if (policy != SCHED_OTHER)
+               XENOMAI_SYSCALL1(__xn_sys_migrate, XENOMAI_XENO_DOMAIN);
 
-       return status;
+       return start(arg);
 }
 
-int __wrap_pthread_create(pthread_t *tid,
-                         const pthread_attr_t * attr,
-                         void *(*start) (void *), void *arg)
+int pthread_create_ex(pthread_t *tid,
+                     const pthread_attr_ex_t *attr_ex,
+                     void *(*start) (void *), void *arg)
 {
        struct pthread_iargs iargs;
        struct sched_param param;
-       pthread_attr_t iattr;
-       int inherit, err;
+       pthread_attr_t attr;
+       int inherit, ret;
        pthread_t ltid;
        size_t stksz;
 
-       if (!attr)
-               attr = &default_attr;
+       if (attr_ex == NULL)
+               attr_ex = &default_attr_ex;
+
+       pthread_getschedparam_ex(pthread_self(), &iargs.policy, 
&iargs.param_ex);
+       iargs.parent_prio = iargs.param_ex.sched_priority;
+       memcpy(&attr, &attr_ex->std, sizeof(attr));
 
-       pthread_attr_getinheritsched(attr, &inherit);
-       __wrap_pthread_getschedparam(pthread_self(), &iargs.policy, &param);
-       iargs.parent_prio = param.sched_priority;
+       pthread_attr_getinheritsched(&attr, &inherit);
        if (inherit == PTHREAD_EXPLICIT_SCHED) {
-               pthread_attr_getschedpolicy(attr, &iargs.policy);
-               pthread_attr_getschedparam(attr, &param);
+               pthread_attr_getschedpolicy_ex(attr_ex, &iargs.policy);
+               pthread_attr_getschedparam_ex(attr_ex, &iargs.param_ex);
        }
-       iargs.prio = param.sched_priority;
 
-       memcpy(&iattr, attr, sizeof(pthread_attr_t));
        if (linuxthreads && geteuid()) {
-               /* Work around linuxthreads shortcoming: it doesn't believe
-                  that it could have RT power as non-root and fails the
-                  thread creation overeagerly. */
-               pthread_attr_setinheritsched(&iattr, PTHREAD_EXPLICIT_SCHED);
+               /*
+                * Work around linuxthreads shortcoming: it doesn't
+                * believe that it could have RT power as non-root and
+                * fails the thread creation overeagerly.
+                */
+               pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
                param.sched_priority = 0;
-               pthread_attr_setschedpolicy(&iattr, SCHED_OTHER);
-               pthread_attr_setschedparam(&iattr, &param);
+               pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
+               pthread_attr_setschedparam(&attr, &param);
        } else
-               /* Get the created thread to temporarily inherit pthread_create
-                  caller priority */
-               pthread_attr_setinheritsched(&iattr, PTHREAD_INHERIT_SCHED);
-       pthread_attr_getstacksize(&iattr, &stksz);
-       pthread_attr_setstacksize(&iattr, xeno_stacksize(stksz));
-       attr = &iattr;
-
-       /* First start a native POSIX thread, then associate a Xenomai shadow to
-          it. */
-
+               /*
+                * Get the created thread to temporarily inherit the
+                * caller priority (we mean linux/libc priority here,
+                * as we use a libc call to create the thread).
+                */
+               pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
+
+       pthread_attr_getstacksize(&attr, &stksz);
+       pthread_attr_setstacksize(&attr, xeno_stacksize(stksz));
+
+       /*
+        * First start a native POSIX thread, then mate a Xenomai
+        * shadow to it.
+        */
        iargs.start = start;
        iargs.arg = arg;
        iargs.ret = EAGAIN;
        __STD(sem_init(&iargs.sync, 0, 0));
 
-       err = __STD(pthread_create(&ltid, attr,
-                                  &__pthread_trampoline, &iargs));
+       ret = __STD(pthread_create(&ltid, &attr, &__pthread_trampoline, 
&iargs));
+       if (ret)
+               goto fail;
+
+       while (__STD(sem_wait(&iargs.sync)) && errno == EINTR)
+               ;
 
-       if (!err)
-               while (__STD(sem_wait(&iargs.sync)) && errno == EINTR) ;
+       ret = iargs.ret;
+       if (ret == 0)
+               *tid = ltid;
+fail:
        __STD(sem_destroy(&iargs.sync));
 
-       err = err ?: iargs.ret;
+       return ret;
+}
 
-       if (!err)
-               *tid = ltid;
+int __wrap_pthread_create(pthread_t *tid,
+                         const pthread_attr_t *attr,
+                         void *(*start) (void *), void *arg)
+{
+       pthread_attr_ex_t attr_ex;
+       struct sched_param param;
+       int policy;
+
+       if (attr == NULL)
+               attr = &default_attr_ex.std;
+
+       memcpy(&attr_ex.std, attr, sizeof(*attr));
+       pthread_attr_getschedpolicy(attr, &policy);
+       attr_ex.nonstd.sched_policy = policy;
+       pthread_attr_getschedparam(attr, &param);
+       attr_ex.nonstd.sched_param.sched_priority = param.sched_priority;
 
-       return err;
+       return pthread_create_ex(tid, &attr_ex, start, arg);
 }
 
 int pthread_make_periodic_np(pthread_t thread,
@@ -317,16 +346,16 @@ int pthread_make_periodic_np(pthread_t thread,
 
 int pthread_wait_np(unsigned long *overruns_r)
 {
-       int err, oldtype;
+       int ret, oldtype;
 
        pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
 
-       err = -XENOMAI_SKINCALL1(__cobalt_muxid,
+       ret = -XENOMAI_SKINCALL1(__cobalt_muxid,
                                 __cobalt_thread_wait, overruns_r);
 
        pthread_setcanceltype(oldtype, NULL);
 
-       return err;
+       return ret;
 }
 
 int pthread_set_mode_np(int clrmask, int setmask, int *mode_r)
@@ -350,19 +379,19 @@ int pthread_probe_np(pid_t tid)
 
 int __wrap_pthread_kill(pthread_t thread, int sig)
 {
-       int err;
-       err = -XENOMAI_SKINCALL2(__cobalt_muxid,
-                                __cobalt_thread_kill, thread, sig);
+       int ret;
 
-       if (err == ESRCH)
+       ret = -XENOMAI_SKINCALL2(__cobalt_muxid,
+                                __cobalt_thread_kill, thread, sig);
+       if (ret == ESRCH)
                return __STD(pthread_kill(thread, sig));
 
-       return err;
+       return ret;
 }
 
 static __attribute__((constructor)) void cobalt_thread_init(void)
 {
-       pthread_attr_init(&default_attr);
+       pthread_attr_init_ex(&default_attr_ex);
 #ifdef _CS_GNU_LIBPTHREAD_VERSION
        {
                char vers[128];


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

Reply via email to