Module: xenomai-gch Branch: for-forge Commit: 1d5f60351dd45a19acc7942d8efa1c22567ba885 URL: http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=1d5f60351dd45a19acc7942d8efa1c22567ba885
Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org> Date: Tue Mar 24 20:40:13 2015 +0100 cobalt/mutex,cond: allow static initializer By initializing the mutex or condvar on first access --- lib/cobalt/cond.c | 58 +++++++++++++++++++++++++++++++++++++++++++----- lib/cobalt/mutex.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 109 insertions(+), 11 deletions(-) diff --git a/lib/cobalt/cond.c b/lib/cobalt/cond.c index 70a97fd..ba1fada 100644 --- a/lib/cobalt/cond.c +++ b/lib/cobalt/cond.c @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include <errno.h> +#include <string.h> #include <pthread.h> #include <asm/xenomai/syscall.h> #include "current.h" @@ -189,6 +190,17 @@ static void __pthread_cond_cleanup(void *data) c->mutex->lockcnt = c->count; } +static int __attribute__((cold)) cobalt_cond_autoinit(pthread_cond_t *cond) +{ + static pthread_cond_t uninit_cond = PTHREAD_COND_INITIALIZER; + + if (memcmp(cond, &uninit_cond, sizeof(*cond))) + return EINVAL; + + return __COBALT(pthread_cond_init(cond, NULL)); +} + + /** * Wait on a condition variable. * @@ -248,10 +260,13 @@ COBALT_IMPL(int, pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mute int err, oldtype; unsigned count; - if (_mx->magic != COBALT_MUTEX_MAGIC - || _cnd->magic != COBALT_COND_MAGIC) + if (_mx->magic != COBALT_MUTEX_MAGIC) return EINVAL; + if (_cnd->magic != COBALT_COND_MAGIC) + goto autoinit; + + cont: if (_mx->attr.type == PTHREAD_MUTEX_ERRORCHECK) { xnhandle_t cur = cobalt_get_current(); @@ -283,6 +298,12 @@ COBALT_IMPL(int, pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mute pthread_testcancel(); return -err ?: -c.err; + + autoinit: + err = cobalt_cond_autoinit(cond); + if (err) + return err; + goto cont; } /** @@ -333,10 +354,13 @@ COBALT_IMPL(int, pthread_cond_timedwait, (pthread_cond_t *cond, int err, oldtype; unsigned count; - if (_mx->magic != COBALT_MUTEX_MAGIC - || _cnd->magic != COBALT_COND_MAGIC) + if (_mx->magic != COBALT_MUTEX_MAGIC) return EINVAL; + if (_cnd->magic != COBALT_COND_MAGIC) + goto autoinit; + + cont: if (_mx->attr.type == PTHREAD_MUTEX_ERRORCHECK) { xnhandle_t cur = cobalt_get_current(); @@ -367,6 +391,12 @@ COBALT_IMPL(int, pthread_cond_timedwait, (pthread_cond_t *cond, pthread_testcancel(); return -err ?: -c.err; + + autoinit: + err = cobalt_cond_autoinit(cond); + if (err) + return err; + goto cont; } /** @@ -398,10 +428,12 @@ COBALT_IMPL(int, pthread_cond_signal, (pthread_cond_t *cond)) __u32 pending_signals; xnhandle_t cur; __u32 flags; + int err; if (_cnd->magic != COBALT_COND_MAGIC) - return EINVAL; + goto autoinit; + cont: mutex_state = get_mutex_state(_cnd); if (mutex_state == NULL) return 0; /* Fast path, no waiter. */ @@ -422,6 +454,12 @@ COBALT_IMPL(int, pthread_cond_signal, (pthread_cond_t *cond)) cond_state->pending_signals = pending_signals + 1; return 0; + + autoinit: + err = cobalt_cond_autoinit(cond); + if (err) + return err; + goto cont; } /** @@ -449,10 +487,12 @@ COBALT_IMPL(int, pthread_cond_broadcast, (pthread_cond_t *cond)) struct cobalt_cond_state *cond_state; xnhandle_t cur; __u32 flags; + int err; if (_cnd->magic != COBALT_COND_MAGIC) - return EINVAL; + goto autoinit; + cont: mutex_state = get_mutex_state(_cnd); if (mutex_state == NULL) return 0; @@ -471,6 +511,12 @@ COBALT_IMPL(int, pthread_cond_broadcast, (pthread_cond_t *cond)) cond_state->pending_signals = ~0U; return 0; + + autoinit: + err = cobalt_cond_autoinit(cond); + if (err) + return err; + goto cont; } /** diff --git a/lib/cobalt/mutex.c b/lib/cobalt/mutex.c index 93a9bbc..b84a582 100644 --- a/lib/cobalt/mutex.c +++ b/lib/cobalt/mutex.c @@ -16,8 +16,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include <errno.h> -#include <pthread.h> +#include <string.h> #include <limits.h> +#include <pthread.h> #include <asm/xenomai/syscall.h> #include "current.h" #include "internal.h" @@ -170,6 +171,29 @@ COBALT_IMPL(int, pthread_mutex_destroy, (pthread_mutex_t *mutex)) return -err; } +static int __attribute__((cold)) cobalt_mutex_autoinit(pthread_mutex_t *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; + pthread_mutexattr_t mattr; + int err; + + if (memcmp(mutex, &uninit_normal_mutex, sizeof(*mutex)) + && memcmp(mutex, &uninit_recursive_mutex, sizeof(*mutex)) + && memcmp(mutex, &uninit_errorcheck_mutex, sizeof(*mutex))) + return EINVAL; + + pthread_mutexattr_init(&mattr); + pthread_mutexattr_settype(&mattr, mutex->__data.__kind); + err = __COBALT(pthread_mutex_init(mutex, &mattr)); + pthread_mutexattr_destroy(&mattr); + + return err; +} + /** * Lock a mutex. * @@ -214,13 +238,14 @@ COBALT_IMPL(int, pthread_mutex_lock, (pthread_mutex_t *mutex)) return EPERM; if (_mutex->magic != COBALT_MUTEX_MAGIC) - return EINVAL; + goto autoinit; /* * We track resource ownership for non real-time shadows in * order to handle the auto-relax feature, so we must always * obtain them via a syscall. */ + cont: status = cobalt_get_current_mode(); if ((status & (XNRELAX|XNWEAK)) == 0) { ret = xnsynch_fast_acquire(mutex_get_ownerp(_mutex), cur); @@ -257,6 +282,12 @@ COBALT_IMPL(int, pthread_mutex_lock, (pthread_mutex_t *mutex)) _mutex->lockcnt = 1; return -ret; + + autoinit: + ret = cobalt_mutex_autoinit(mutex); + if (ret) + return ret; + goto cont; } /** @@ -302,9 +333,10 @@ COBALT_IMPL(int, pthread_mutex_timedlock, (pthread_mutex_t *mutex, return EPERM; if (_mutex->magic != COBALT_MUTEX_MAGIC) - return EINVAL; + goto autoinit; /* See __cobalt_pthread_mutex_lock() */ + cont: status = cobalt_get_current_mode(); if ((status & (XNRELAX|XNWEAK)) == 0) { ret = xnsynch_fast_acquire(mutex_get_ownerp(_mutex), cur); @@ -341,6 +373,12 @@ COBALT_IMPL(int, pthread_mutex_timedlock, (pthread_mutex_t *mutex, if (ret == 0) _mutex->lockcnt = 1; return -ret; + + autoinit: + ret = cobalt_mutex_autoinit(mutex); + if (ret) + return ret; + goto cont; } /** @@ -379,8 +417,9 @@ COBALT_IMPL(int, pthread_mutex_trylock, (pthread_mutex_t *mutex)) return EPERM; if (_mutex->magic != COBALT_MUTEX_MAGIC) - return EINVAL; + goto autoinit; + cont: status = cobalt_get_current_mode(); if ((status & (XNRELAX|XNWEAK)) == 0) { err = xnsynch_fast_acquire(mutex_get_ownerp(_mutex), cur); @@ -416,6 +455,12 @@ do_syscall: _mutex->lockcnt = 1; return -err; + + autoinit: + err = cobalt_mutex_autoinit(mutex); + if (err) + return err; + goto cont; } /** @@ -452,8 +497,9 @@ COBALT_IMPL(int, pthread_mutex_unlock, (pthread_mutex_t *mutex)) int err; if (_mutex->magic != COBALT_MUTEX_MAGIC) - return EINVAL; + goto autoinit; + cont: cur = cobalt_get_current(); if (cur == XN_NO_HANDLE) return EPERM; @@ -482,6 +528,12 @@ do_syscall: } while (err == -EINTR); return -err; + + autoinit: + err = cobalt_mutex_autoinit(mutex); + if (err) + return err; + goto cont; } /** _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git