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