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

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Fri Oct  2 23:07:16 2015 +0200

posix/mutex: fix autoinit

If several threads call simultaneously pthread_mutex_lock() on a mutex
initialized with PTHREAD_MUTEX_INITIALIZER, the current automatic
intialization may result in several initializations of the mutex.
Serialize the automatic initialization with a global mutex to avoid
that.

This can be done only for automatic initialization, as
pthread_mutex_init() may be called from a non Xenomai thread, which
could not sleep on a cobalt mutex, and serializing with a plain Linux
mutex would cause a switch to secondary mode for pthread_mutex_lock() in
case of automatic initialization.

Using a condition variable would create a cancellation point, whereas
pthread_mutex_lock() and pthread_mutex_unlock() can not be cancellation
points.

---

 lib/cobalt/init.c     |    2 +-
 lib/cobalt/internal.h |    2 +-
 lib/cobalt/mutex.c    |   26 +++++++++++++++++++++++---
 3 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/lib/cobalt/init.c b/lib/cobalt/init.c
index 2910f6e..9d1674d 100644
--- a/lib/cobalt/init.c
+++ b/lib/cobalt/init.c
@@ -172,6 +172,7 @@ static void __cobalt_init(void)
                            sizeof(sem_t),
                            sizeof(struct cobalt_sem_shadow));
 
+       cobalt_mutex_init();
        cobalt_thread_init();
        cobalt_print_init();
 }
@@ -189,7 +190,6 @@ int cobalt_init(void)
        int policy, ret;
 
        commit_stack_memory();  /* We only need this for the main thread */
-       cobalt_default_mutexattr_init();
        cobalt_default_condattr_init();
        __cobalt_init();
 
diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
index 540c286..4f03cf0 100644
--- a/lib/cobalt/internal.h
+++ b/lib/cobalt/internal.h
@@ -51,7 +51,7 @@ void cobalt_print_init_atfork(void);
 
 void cobalt_ticks_init(unsigned long long freq);
 
-void cobalt_default_mutexattr_init(void);
+void cobalt_mutex_init(void);
 
 void cobalt_default_condattr_init(void);
 
diff --git a/lib/cobalt/mutex.c b/lib/cobalt/mutex.c
index e4024e3..f613478 100644
--- a/lib/cobalt/mutex.c
+++ b/lib/cobalt/mutex.c
@@ -56,10 +56,21 @@
  */
 
 static pthread_mutexattr_t cobalt_default_mutexattr;
+static pthread_mutex_t cobalt_autoinit_mutex;
 
-void cobalt_default_mutexattr_init(void)
+void cobalt_mutex_init(void)
 {
+       pthread_mutexattr_t rt_init_mattr;
+       int err __attribute__((unused));
+
        pthread_mutexattr_init(&cobalt_default_mutexattr);
+
+       pthread_mutexattr_init(&rt_init_mattr);
+       pthread_mutexattr_setprotocol(&rt_init_mattr, PTHREAD_PRIO_INHERIT);
+       err = __COBALT(pthread_mutex_init(&cobalt_autoinit_mutex,
+                                               &rt_init_mattr));
+       assert(err == 0);
+       pthread_mutexattr_destroy(&rt_init_mattr);
 }
 
 /**
@@ -176,12 +187,15 @@ COBALT_IMPL(int, pthread_mutex_destroy, (pthread_mutex_t 
*mutex))
 static int __attribute__((cold)) cobalt_mutex_autoinit(pthread_mutex_t *mutex)
 {
        static pthread_mutex_t uninit_normal_mutex = PTHREAD_MUTEX_INITIALIZER;
+       struct cobalt_mutex_shadow *_mutex =
+               &((union cobalt_mutex_union *)mutex)->shadow_mutex;
        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, type;
+       int ret = 0, type;
 
        if (memcmp(mutex, &uninit_normal_mutex, sizeof(*mutex)) == 0)
                type = PTHREAD_MUTEX_DEFAULT;
@@ -194,7 +208,13 @@ static int __attribute__((cold)) 
cobalt_mutex_autoinit(pthread_mutex_t *mutex)
 
        pthread_mutexattr_init(&mattr);
        pthread_mutexattr_settype(&mattr, type);
-       ret = __COBALT(pthread_mutex_init(mutex, &mattr));
+       err = __COBALT(pthread_mutex_lock(&cobalt_autoinit_mutex));
+       assert(err = 0);
+       if (_mutex->magic != COBALT_MUTEX_MAGIC)
+               ret = __COBALT(pthread_mutex_init(mutex, &mattr));
+       err = __COBALT(pthread_mutex_unlock(&cobalt_autoinit_mutex));
+       assert(err == 0);
+
        pthread_mutexattr_destroy(&mattr);
 
        return ret;


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

Reply via email to