Module: xenomai-2.6
Branch: master
Commit: 79892f2e9f2a82791df49a93103b04be5ce3099d
URL:    
http://git.xenomai.org/?p=xenomai-2.6.git;a=commit;h=79892f2e9f2a82791df49a93103b04be5ce3099d

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Thu Jul  7 11:27:57 2016 +0200

posix/mutex,cond: allow static initializer

By initializing the mutex or condvar on first access.

Backport from Xenomai 3.0 commits:
77a0e7eb6cb7573bd5baf253429346595a797b86
83b0f18930290ae1aacf561a25b0daf224b6e00b
dfa9ad71e481c70069cce539b462806ab2abee6c
e55f70bc55ea8f408eabaa9aee635a4b0547294d
67ae83b2f26ff7550e3390781bf9fe10b3aef41b
3f0934d7a6ebcfbd2c0954cdf2a7630c278e8867

---

 doc/txt/pse51-skin.txt   |    7 ---
 ksrc/skins/posix/cond.c  |    4 --
 ksrc/skins/posix/mutex.c |    3 --
 src/skins/posix/cond.c   |   51 +++++++++++++++++++++
 src/skins/posix/init.c   |    3 ++
 src/skins/posix/mutex.c  |  114 ++++++++++++++++++++++++++++++++++++++++++++--
 6 files changed, 164 insertions(+), 18 deletions(-)

diff --git a/doc/txt/pse51-skin.txt b/doc/txt/pse51-skin.txt
index fade9ac..54ceb59 100644
--- a/doc/txt/pse51-skin.txt
+++ b/doc/txt/pse51-skin.txt
@@ -124,13 +124,6 @@ their vanilla names.
 
 Caveats:
 
-- Use of the static initializers PTHREAD_MUTEX_INITIALIZER and
-PTHREAD_COND_INITIALIZER in setting up mutex and condition variable
-replacements is invalid; dynamic initialization through the
-pthread_mutex_init() and pthread_cond_init() routines must be used
-instead, otherwise, mutex and condition variable-related calls would
-always return an error status (EINVAL).
-
 - Real-time signals sent to user-space threads cause migration to secondary
   mode.
 
diff --git a/ksrc/skins/posix/cond.c b/ksrc/skins/posix/cond.c
index e32a06f..371996a 100644
--- a/ksrc/skins/posix/cond.c
+++ b/ksrc/skins/posix/cond.c
@@ -41,10 +41,6 @@
  * several processes (it may not be shared by default, see
  * pthread_condattr_setpshared()).
  *
- * Note that only pthread_cond_init() may be used to initialize a condition
- * variable, using the static initializer @a PTHREAD_COND_INITIALIZER is
- * not supported.
- *
  *@{*/
 
 #include <posix/mutex.h>
diff --git a/ksrc/skins/posix/mutex.c b/ksrc/skins/posix/mutex.c
index c38b04b..9e81bab 100644
--- a/ksrc/skins/posix/mutex.c
+++ b/ksrc/skins/posix/mutex.c
@@ -42,9 +42,6 @@
  * By default, Xenomai POSIX skin mutexes are of the normal type, use no
  * priority protocol and may not be shared between several processes.
  *
- * Note that only pthread_mutex_init() may be used to initialize a mutex, using
- * the static initializer @a PTHREAD_MUTEX_INITIALIZER is not supported.
- *
  *@{*/
 
 #include <nucleus/sys_ppd.h>
diff --git a/src/skins/posix/cond.c b/src/skins/posix/cond.c
index 7884836..ba63c70 100644
--- a/src/skins/posix/cond.c
+++ b/src/skins/posix/cond.c
@@ -22,8 +22,12 @@
 #include <posix/mutex.h>
 #include <posix/cb_lock.h>
 
+#define PSE51_COND_MAGIC (0x86860505)
+
 extern int __pse51_muxid;
 
+static int cond_autoinit(pthread_cond_t *cond);
+
 int __wrap_pthread_condattr_init(pthread_condattr_t *attr)
 {
        return -XENOMAI_SKINCALL1(__pse51_muxid, __pse51_condattr_init, attr);
@@ -109,6 +113,10 @@ int __wrap_pthread_cond_wait(pthread_cond_t *cond, 
pthread_mutex_t *mutex)
        };
        int err, oldtype;
 
+       if (unlikely(c.cond->shadow_cond.magic != PSE51_COND_MAGIC))
+               goto autoinit;
+
+  start:
        if (cb_try_read_lock(&c.mutex->shadow_mutex.lock, s))
                return EINVAL;
 
@@ -137,6 +145,12 @@ int __wrap_pthread_cond_wait(pthread_cond_t *cond, 
pthread_mutex_t *mutex)
        pthread_testcancel();
 
        return err ?: c.err;
+
+  autoinit:
+       err = cond_autoinit(cond);
+       if (err)
+               return err;
+       goto start;
 }
 
 int __wrap_pthread_cond_timedwait(pthread_cond_t * cond,
@@ -149,6 +163,10 @@ int __wrap_pthread_cond_timedwait(pthread_cond_t * cond,
        };
        int err, oldtype;
 
+       if (unlikely(c.cond->shadow_cond.magic != PSE51_COND_MAGIC))
+               goto autoinit;
+
+  start:
        if (cb_try_read_lock(&c.mutex->shadow_mutex.lock, s))
                return EINVAL;
 
@@ -176,20 +194,53 @@ int __wrap_pthread_cond_timedwait(pthread_cond_t * cond,
        pthread_testcancel();
 
        return err ?: c.err;
+
+  autoinit:
+       err = cond_autoinit(cond);
+       if (err)
+               return err;
+       goto start;
 }
 
 int __wrap_pthread_cond_signal(pthread_cond_t * cond)
 {
        union __xeno_cond *_cond = (union __xeno_cond *)cond;
+       int err;
+
+       if (unlikely(_cond->shadow_cond.magic != PSE51_COND_MAGIC))
+               goto autoinit;
 
+  start:
        return -XENOMAI_SKINCALL1(__pse51_muxid,
                                  __pse51_cond_signal, &_cond->shadow_cond);
+
+  autoinit:
+       err = cond_autoinit(cond);
+       if (err)
+               return err;
+       goto start;
 }
 
 int __wrap_pthread_cond_broadcast(pthread_cond_t * cond)
 {
        union __xeno_cond *_cond = (union __xeno_cond *)cond;
+       int err;
 
+       if (unlikely(_cond->shadow_cond.magic != PSE51_COND_MAGIC))
+               goto autoinit;
+
+  start:
        return -XENOMAI_SKINCALL1(__pse51_muxid,
                                  __pse51_cond_broadcast, &_cond->shadow_cond);
+
+  autoinit:
+       err = cond_autoinit(cond);
+       if (err)
+               return err;
+       goto start;
+}
+
+static int __attribute__((cold)) cond_autoinit(pthread_cond_t *cond)
+{
+       return __wrap_pthread_cond_init(cond, NULL);
 }
diff --git a/src/skins/posix/init.c b/src/skins/posix/init.c
index ca1d9e1..bdac5f7 100644
--- a/src/skins/posix/init.c
+++ b/src/skins/posix/init.c
@@ -40,6 +40,7 @@ static int fork_handler_registered;
 
 int __wrap_pthread_setschedparam(pthread_t, int, const struct sched_param *);
 void pse51_clock_init(int);
+void pse51_mutex_init(void);
 
 static __constructor__ void __init_posix_interface(void)
 {
@@ -67,6 +68,8 @@ static __constructor__ void __init_posix_interface(void)
                                                                 
__rtdm_fdcount);
        }
 
+       pse51_mutex_init();
+
        noshadow = getenv("XENO_NOSHADOW");
        if ((!noshadow || !*noshadow) && xeno_get_current() == XN_NO_HANDLE) {
                err = __real_pthread_getschedparam(pthread_self(), &policy,
diff --git a/src/skins/posix/mutex.c b/src/skins/posix/mutex.c
index ed4dfdd..2f3c1ce 100644
--- a/src/skins/posix/mutex.c
+++ b/src/skins/posix/mutex.c
@@ -19,6 +19,9 @@
 #include <errno.h>
 #include <pthread.h>
 #include <limits.h>
+#include <assert.h>
+#include <unistd.h>
+
 #include <nucleus/synch.h>
 #include <posix/mutex.h>
 #include <posix/syscall.h>
@@ -27,10 +30,13 @@
 #include <asm-generic/sem_heap.h>
 
 extern int __pse51_muxid;
+static union __xeno_mutex autoinit_mutex_union;
+static pthread_mutex_t *const autoinit_mutex =
+       &autoinit_mutex_union.native_mutex;
 
-#ifdef CONFIG_XENO_FASTSYNCH
 #define PSE51_MUTEX_MAGIC (0x86860303)
 
+#ifdef CONFIG_XENO_FASTSYNCH
 static xnarch_atomic_t *get_ownerp(struct __shadow_mutex *shadow)
 {
        if (likely(!shadow->attr.pshared))
@@ -40,6 +46,8 @@ static xnarch_atomic_t *get_ownerp(struct __shadow_mutex 
*shadow)
 }
 #endif /* CONFIG_XENO_FASTSYNCH */
 
+static int mutex_autoinit(pthread_mutex_t *mutex);
+
 int __wrap_pthread_mutexattr_init(pthread_mutexattr_t *attr)
 {
        return -XENOMAI_SKINCALL1(__pse51_muxid, __pse51_mutexattr_init, attr);
@@ -103,7 +111,6 @@ int __wrap_pthread_mutex_init(pthread_mutex_t *mutex,
                goto checked;
 
        err = -XENOMAI_SKINCALL2(__pse51_muxid,__pse51_check_init,shadow,attr);
-
        if (err) {
                cb_read_unlock(&shadow->lock, s);
                return err;
@@ -156,6 +163,10 @@ int __wrap_pthread_mutex_lock(pthread_mutex_t *mutex)
        if (unlikely(cur == XN_NO_HANDLE))
                return EPERM;
 
+       if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC))
+               goto autoinit;
+
+  start:
        if (unlikely(cb_try_read_lock(&shadow->lock, s)))
                return EINVAL;
 
@@ -201,8 +212,12 @@ int __wrap_pthread_mutex_lock(pthread_mutex_t *mutex)
                        err = 0;
                        goto out;
                }
+#else /* !CONFIG_XENO_FASTSYNCH */
+       if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC))
+               goto autoinit;
 
-#endif /* CONFIG_XENO_FASTSYNCH */
+  start:
+#endif /* !CONFIG_XENO_FASTSYNCH */
 
        do {
                err = 
XENOMAI_SKINCALL1(__pse51_muxid,__pse51_mutex_lock,shadow);
@@ -214,6 +229,12 @@ int __wrap_pthread_mutex_lock(pthread_mutex_t *mutex)
 #endif /* CONFIG_XENO_FASTSYNCH */
 
        return -err;
+
+  autoinit:
+       err = mutex_autoinit(mutex);
+       if (err)
+               return err;
+       goto start;
 }
 
 int __wrap_pthread_mutex_timedlock(pthread_mutex_t *mutex,
@@ -231,6 +252,10 @@ int __wrap_pthread_mutex_timedlock(pthread_mutex_t *mutex,
        if (unlikely(cur == XN_NO_HANDLE))
                return EPERM;
 
+       if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC))
+               goto autoinit;
+
+  start:
        if (unlikely(cb_try_read_lock(&shadow->lock, s)))
                return EINVAL;
 
@@ -273,7 +298,12 @@ int __wrap_pthread_mutex_timedlock(pthread_mutex_t *mutex,
                        goto out;
                }
 
-#endif /* CONFIG_XENO_FASTSYNCH */
+#else /* !CONFIG_XENO_FASTSYNCH */
+       if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC))
+               goto autoinit;
+
+  start:
+#endif /* !CONFIG_XENO_FASTSYNCH */
 
        do {
                err = XENOMAI_SKINCALL2(__pse51_muxid,
@@ -286,6 +316,12 @@ int __wrap_pthread_mutex_timedlock(pthread_mutex_t *mutex,
 #endif /* CONFIG_XENO_FASTSYNCH */
 
        return -err;
+
+  autoinit:
+       err = mutex_autoinit(mutex);
+       if (err)
+               return err;
+       goto start;
 }
 
 int __wrap_pthread_mutex_trylock(pthread_mutex_t *mutex)
@@ -304,6 +340,10 @@ int __wrap_pthread_mutex_trylock(pthread_mutex_t *mutex)
        if (unlikely(cur == XN_NO_HANDLE))
                return EPERM;
 
+       if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC))
+               goto autoinit;
+
+  start:
        if (unlikely(cb_try_read_lock(&shadow->lock, s)))
                return EINVAL;
 
@@ -353,7 +393,10 @@ do_syscall:
        cb_read_unlock(&shadow->lock, s);
 
 #else /* !CONFIG_XENO_FASTSYNCH */
+       if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC))
+               goto autoinit;
 
+  start:
        do {
                err = XENOMAI_SKINCALL1(__pse51_muxid,
                                        __pse51_mutex_trylock, shadow);
@@ -362,6 +405,12 @@ do_syscall:
 #endif /* !CONFIG_XENO_FASTSYNCH */
 
        return -err;
+
+  autoinit:
+       err = mutex_autoinit(mutex);
+       if (err)
+               return err;
+       goto start;
 }
 
 int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex)
@@ -418,3 +467,60 @@ do_syscall:
 
        return -err;
 }
+
+void pse51_mutex_init(void)
+{
+       struct __shadow_mutex *_mutex = &autoinit_mutex_union.shadow_mutex;
+       pthread_mutexattr_t rt_init_mattr;
+       int err __attribute__((unused));
+
+       __wrap_pthread_mutexattr_init(&rt_init_mattr);
+       __wrap_pthread_mutexattr_setprotocol(&rt_init_mattr, 
PTHREAD_PRIO_INHERIT);
+       _mutex->magic = ~PSE51_MUTEX_MAGIC;
+       err = __wrap_pthread_mutex_init(autoinit_mutex, &rt_init_mattr);
+       assert(err == 0);
+       __wrap_pthread_mutexattr_destroy(&rt_init_mattr);
+}
+
+static int __attribute__((cold)) mutex_autoinit(pthread_mutex_t *mutex)
+{
+       struct __shadow_mutex *_mutex =
+               &((union __xeno_mutex *)mutex)->shadow_mutex;
+       static pthread_mutex_t uninit_normal_mutex = PTHREAD_MUTEX_INITIALIZER;
+       static pthread_mutex_t uninit_recursive_mutex =
+               PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+       static pthread_mutex_t uninit_errorcheck_mutex =
+               PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+       int err __attribute__((unused));
+       pthread_mutexattr_t mattr;
+       int ret = 0, type;
+
+       if (memcmp(mutex, &uninit_normal_mutex, sizeof(*mutex)) == 0)
+               type = PTHREAD_MUTEX_DEFAULT;
+       else if (memcmp(mutex, &uninit_recursive_mutex, sizeof(*mutex)) == 0)
+               type = PTHREAD_MUTEX_RECURSIVE_NP;
+       else if (memcmp(mutex, &uninit_errorcheck_mutex, sizeof(*mutex)) == 0)
+               type = PTHREAD_MUTEX_ERRORCHECK_NP;
+       else
+               return EINVAL;
+
+       __wrap_pthread_mutexattr_init(&mattr);
+       __wrap_pthread_mutexattr_settype(&mattr, type);
+       err = __wrap_pthread_mutex_lock(autoinit_mutex);
+       if (err) {
+               ret = err;
+               goto out;
+       }
+       if (_mutex->magic != PSE51_MUTEX_MAGIC)
+               ret = __wrap_pthread_mutex_init(mutex, &mattr);
+       err = __wrap_pthread_mutex_unlock(autoinit_mutex);
+       if (err) {
+               if (ret == 0)
+                       ret = err;
+       }
+
+  out:
+       __wrap_pthread_mutexattr_destroy(&mattr);
+
+       return ret;
+}


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

Reply via email to