Module: xenomai-gch
Branch: for-forge
Commit: c93a544914bde1ff24c83e2cb8076e73590a2abf
URL:    
http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=c93a544914bde1ff24c83e2cb8076e73590a2abf

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Mon Nov 14 23:40:28 2011 +0100

cobalt: move mutex services to kernel/cobalt/mutex.c

---

 kernel/cobalt/cond.c    |    3 +-
 kernel/cobalt/mutex.c   |  552 ++++++++++++++++-------------------------------
 kernel/cobalt/mutex.h   |   58 ++---
 kernel/cobalt/syscall.c |  257 +---------------------
 lib/cobalt/mutex.c      |  197 ++++++++---------
 5 files changed, 317 insertions(+), 750 deletions(-)

diff --git a/kernel/cobalt/cond.c b/kernel/cobalt/cond.c
index e9bfe51..d398afb 100644
--- a/kernel/cobalt/cond.c
+++ b/kernel/cobalt/cond.c
@@ -329,8 +329,7 @@ static int cobalt_cond_timedwait_epilogue(xnthread_t *cur,
 
        xnlock_get_irqsave(&nklock, s);
 
-       err = cobalt_mutex_timedlock_internal(cur, mutex, 0, XN_INFINITE);
-
+       err = cobalt_mutex_acquire_unchecked(cur, mutex, 0, XN_INFINITE);
        if (err == -EINTR)
                goto unlock_and_return;
 
diff --git a/kernel/cobalt/mutex.c b/kernel/cobalt/mutex.c
index b204b31..d8f13d2 100644
--- a/kernel/cobalt/mutex.c
+++ b/kernel/cobalt/mutex.c
@@ -53,38 +53,10 @@
 
 pthread_mutexattr_t cobalt_default_mutex_attr;
 
-int cobalt_mutex_check_init(struct __shadow_mutex *shadow,
-                          const pthread_mutexattr_t *attr)
-{
-       xnqueue_t *mutexq;
-
-       if (!attr)
-               attr = &cobalt_default_mutex_attr;
-
-       mutexq = &cobalt_kqueues(attr->pshared)->mutexq;
-
-       if (shadow->magic == COBALT_MUTEX_MAGIC) {
-               xnholder_t *holder;
-               spl_t s;
-
-               xnlock_get_irqsave(&nklock, s);
-               for (holder = getheadq(mutexq); holder;
-                    holder = nextq(mutexq, holder))
-                       if (holder == &shadow->mutex->link) {
-                               xnlock_put_irqrestore(&nklock, s);
-                               /* mutex is already in the queue. */
-                               return -EBUSY;
-                       }
-               xnlock_put_irqrestore(&nklock, s);
-       }
-
-       return 0;
-}
-
-int cobalt_mutex_init_internal(struct __shadow_mutex *shadow,
-                             cobalt_mutex_t *mutex,
-                             xnarch_atomic_t *ownerp,
-                             const pthread_mutexattr_t *attr)
+static int cobalt_mutex_init_inner(struct __shadow_mutex *shadow,
+                                  cobalt_mutex_t *mutex,
+                                  xnarch_atomic_t *ownerp,
+                                  const pthread_mutexattr_t *attr)
 {
        xnflags_t synch_flags = XNSYNCH_PRIO | XNSYNCH_OWNER;
        struct xnsys_ppd *sys_ppd;
@@ -124,69 +96,8 @@ int cobalt_mutex_init_internal(struct __shadow_mutex 
*shadow,
        return 0;
 }
 
-/**
- * Initialize a mutex.
- *
- * This services initializes the mutex @a mx, using the mutex attributes object
- * @a attr. If @a attr is @a NULL, default attributes are used (see
- * pthread_mutexattr_init()).
- *
- * @param mx the mutex to be initialized;
- *
- * @param attr the mutex attributes object.
- *
- * @return 0 on success,
- * @return an error number if:
- * - EINVAL, the mutex attributes object @a attr is invalid or uninitialized;
- * - EBUSY, the mutex @a mx was already initialized;
- * - ENOMEM, insufficient memory exists in the system heap to initialize the
- *   mutex, increase CONFIG_XENO_OPT_SYS_HEAPSZ.
- * - EAGAIN, insufficient memory exists in the semaphore heap to initialize the
- *   mutex, increase CONFIG_XENO_OPT_GLOBAL_SEM_HEAPSZ for a process-shared
- *   mutex, or CONFG_XENO_OPT_SEM_HEAPSZ for a process-private mutex.
- *
- * @see
- * <a 
href="http://www.opengroup.org/onlinepubs/000095399/functions/pthread_mutex_init.html";>
- * Specification.</a>
- *
- */
-int pthread_mutex_init(pthread_mutex_t *mx, const pthread_mutexattr_t *attr)
-{
-       struct __shadow_mutex *shadow =
-           &((union __xeno_mutex *)mx)->shadow_mutex;
-       cobalt_mutex_t *mutex;
-       xnarch_atomic_t *ownerp = NULL;
-       int err;
-
-       if (!attr)
-               attr = &cobalt_default_mutex_attr;
-
-       err = cobalt_mutex_check_init(shadow, attr);
-       if (err)
-               return -err;
-
-       mutex = (cobalt_mutex_t *) xnmalloc(sizeof(*mutex));
-       if (!mutex)
-               return ENOMEM;
-
-       ownerp = (xnarch_atomic_t *)
-               xnheap_alloc(&xnsys_ppd_get(attr->pshared)->sem_heap,
-                            sizeof(xnarch_atomic_t));
-       if (!ownerp) {
-               xnfree(mutex);
-               return EAGAIN;
-       }
-
-       err = cobalt_mutex_init_internal(shadow, mutex, ownerp, attr);
-       if (err) {
-               xnfree(mutex);
-               xnheap_free(&xnsys_ppd_get(attr->pshared)->sem_heap, ownerp);
-       }
-       return -err;
-}
-
-void cobalt_mutex_destroy_internal(cobalt_mutex_t *mutex,
-                                 cobalt_kqueues_t *q)
+static void cobalt_mutex_destroy_inner(cobalt_mutex_t *mutex,
+                                      cobalt_kqueues_t *q)
 {
        spl_t s;
 
@@ -202,58 +113,29 @@ void cobalt_mutex_destroy_internal(cobalt_mutex_t *mutex,
        xnfree(mutex);
 }
 
-/**
- * Destroy a mutex.
- *
- * This service destroys the mutex @a mx, if it is unlocked and not referenced
- * by any condition variable. The mutex becomes invalid for all mutex services
- * (they all return the EINVAL error) except pthread_mutex_init().
- *
- * @param mx the mutex to be destroyed.
- *
- * @return 0 on success,
- * @return an error number if:
- * - EINVAL, the mutex @a mx is invalid;
- * - EPERM, the mutex is not process-shared and does not belong to the current
- *   process;
- * - EBUSY, the mutex is locked, or used by a condition variable.
- *
- * @see
- * <a 
href="http://www.opengroup.org/onlinepubs/000095399/functions/pthread_mutex_destroy.html";>
- * Specification.</a>
- *
- */
-int pthread_mutex_destroy(pthread_mutex_t * mx)
+static int cobalt_mutex_acquire(xnthread_t *cur,
+                               cobalt_mutex_t *mutex,
+                               int timed,
+                               xnticks_t abs_to)
 {
-       struct __shadow_mutex *shadow =
-           &((union __xeno_mutex *)mx)->shadow_mutex;
-       cobalt_mutex_t *mutex;
-
-       mutex = shadow->mutex;
-       if (!cobalt_obj_active(shadow, COBALT_MUTEX_MAGIC, struct 
__shadow_mutex)
-           || !cobalt_obj_active(mutex, COBALT_MUTEX_MAGIC, struct 
cobalt_mutex))
-               return EINVAL;
-
-       if (cobalt_kqueues(mutex->attr.pshared) != mutex->owningq)
-               return EPERM;
-
-       if (xnsynch_fast_owner_check(mutex->synchbase.fastlock,
-                                    XN_NO_HANDLE) != 0)
-               return EBUSY;
+       if (xnpod_unblockable_p())
+               return -EPERM;
 
-       cobalt_mark_deleted(shadow);
-       cobalt_mark_deleted(mutex);
+       if (!cobalt_obj_active(mutex, COBALT_MUTEX_MAGIC, struct cobalt_mutex))
+               return -EINVAL;
 
-       cobalt_mutex_destroy_internal(mutex, 
cobalt_kqueues(mutex->attr.pshared));
+#if XENO_DEBUG(POSIX)
+       if (mutex->owningq != cobalt_kqueues(mutex->attr.pshared))
+               return -EPERM;
+#endif /* XENO_DEBUG(POSIX) */
 
-       return 0;
+       return cobalt_mutex_acquire_unchecked(cur, mutex, timed, abs_to);
 }
 
-int cobalt_mutex_timedlock_break(struct __shadow_mutex *shadow,
-                               int timed, xnticks_t abs_to)
+static int cobalt_mutex_timedlock_break(cobalt_mutex_t *mutex,
+                                       int timed, xnticks_t abs_to)
 {
        xnthread_t *cur = xnpod_current_thread();
-       cobalt_mutex_t *mutex;
        spl_t s;
        int err;
 
@@ -261,15 +143,11 @@ int cobalt_mutex_timedlock_break(struct __shadow_mutex 
*shadow,
        if (xnthread_handle(cur) == XN_NO_HANDLE)
                return -EPERM;
 
-       err = cobalt_mutex_timedlock_internal(cur, shadow->mutex, timed, 
abs_to);
-       if (!err)
-               shadow->lockcnt = 1;
+       err = cobalt_mutex_acquire(cur, mutex, timed, abs_to);
 
        if (err != -EBUSY)
                goto out;
 
-       mutex = shadow->mutex;
-
        switch(mutex->attr.type) {
        case PTHREAD_MUTEX_NORMAL:
                /* Attempting to relock a normal mutex, deadlock. */
@@ -305,18 +183,15 @@ int cobalt_mutex_timedlock_break(struct __shadow_mutex 
*shadow,
 
                break;
 
+               /* Recursive mutexes are handled in user-space, so
+                  these cases can not happen */
        case PTHREAD_MUTEX_ERRORCHECK:
-               err = -EDEADLK;
+               err = -EINVAL;
                break;
 
        case PTHREAD_MUTEX_RECURSIVE:
-               if (shadow->lockcnt == UINT_MAX) {
-                       err = -EAGAIN;
-                       break;
-               }
-
-               ++shadow->lockcnt;
-               err = 0;
+               err = -EINVAL;
+               break;
        }
 
   out:
@@ -324,243 +199,203 @@ int cobalt_mutex_timedlock_break(struct __shadow_mutex 
*shadow,
 
 }
 
-/**
- * Attempt to lock a mutex.
- *
- * This service is equivalent to pthread_mutex_lock(), except that if the mutex
- * @a mx is locked by another thread than the current one, this service returns
- * immediately.
- *
- * @param mx the mutex to be locked.
- *
- * @return 0 on success;
- * @return an error number if:
- * - EPERM, the caller context is invalid;
- * - EINVAL, the mutex is invalid;
- * - EPERM, the mutex is not process-shared and does not belong to the current
- *   process;
- * - EBUSY, the mutex was locked by another thread than the current one;
- * - EAGAIN, the mutex is recursive, and the maximum number of recursive locks
- *   has been exceeded.
- *
- * @par Valid contexts:
- * - Xenomai kernel-space thread,
- * - Xenomai user-space thread (switches to primary mode).
- *
- * @see
- * <a 
href="http://www.opengroup.org/onlinepubs/000095399/functions/pthread_mutex_trylock.html";>
- * Specification.</a>
- *
- */
-int pthread_mutex_trylock(pthread_mutex_t *mx)
+int cobalt_mutex_check_init(union __xeno_mutex __user *u_mx)
 {
-       struct __shadow_mutex *shadow =
-           &((union __xeno_mutex *)mx)->shadow_mutex;
-       xnthread_t *cur = xnpod_current_thread();
-       cobalt_mutex_t *mutex = shadow->mutex;
+       cobalt_mutex_t *mutex;
+       xnholder_t *holder;
+       xnqueue_t *mutexq;
+       spl_t s;
+
+       __xn_get_user(mutex, &u_mx->shadow_mutex.mutex);
+
+       mutexq = &cobalt_kqueues(0)->mutexq;
+
+       xnlock_get_irqsave(&nklock, s);
+       for (holder = getheadq(mutexq);
+            holder; holder = nextq(mutexq, holder))
+               if (holder == &mutex->link)
+                       goto busy;
+       xnlock_put_irqrestore(&nklock, s);
+
+       mutexq = &cobalt_kqueues(1)->mutexq;
+
+       xnlock_get_irqsave(&nklock, s);
+       for (holder = getheadq(mutexq);
+            holder; holder = nextq(mutexq, holder))
+               if (holder == &mutex->link)
+                       goto busy;
+       xnlock_put_irqrestore(&nklock, s);
+
+       return 0;
+
+  busy:
+       xnlock_put_irqrestore(&nklock, s);
+       /* mutex is already in the queue. */
+       return -EBUSY;
+}
+
+int cobalt_mutex_init(union __xeno_mutex __user *u_mx,
+                     const pthread_mutexattr_t __user *u_attr)
+{
+       pthread_mutexattr_t locattr, *attr;
+       xnarch_atomic_t *ownerp;
+       union __xeno_mutex mx;
+       cobalt_mutex_t *mutex;
        int err;
 
-       if (xnpod_unblockable_p())
-               return EPERM;
+       if (__xn_safe_copy_from_user(&mx.shadow_mutex,
+                                    &u_mx->shadow_mutex,
+                                    sizeof(mx.shadow_mutex)))
+               return -EFAULT;
 
-       if (!cobalt_obj_active(shadow, COBALT_MUTEX_MAGIC,
-                             struct __shadow_mutex)
-           || !cobalt_obj_active(mutex, COBALT_MUTEX_MAGIC,
-                                struct cobalt_mutex)) {
-               err = EINVAL;
-               goto out;
+       if (u_attr) {
+               if (__xn_safe_copy_from_user(&locattr, u_attr,
+                                            sizeof(locattr)))
+                       return -EFAULT;
+
+               attr = &locattr;
+       } else
+               attr = &cobalt_default_mutex_attr;
+
+       mutex = xnmalloc(sizeof(*mutex));
+       if (mutex == NULL)
+               return -ENOMEM;
+
+       ownerp = xnheap_alloc(&xnsys_ppd_get(attr->pshared)->sem_heap,
+                             sizeof(xnarch_atomic_t));
+       if (ownerp == NULL) {
+               xnfree(mutex);
+               return -EAGAIN;
        }
 
-#if XENO_DEBUG(POSIX)
-       if (mutex->owningq != cobalt_kqueues(mutex->attr.pshared)) {
-               err = EPERM;
-               goto out;
+       err = cobalt_mutex_init_inner(&mx.shadow_mutex, mutex, ownerp, attr);
+       if (err) {
+               xnfree(mutex);
+               xnheap_free(&xnsys_ppd_get(attr->pshared)->sem_heap, ownerp);
+               return err;
        }
-#endif /* XENO_DEBUG(POSIX) */
 
-       err = -xnsynch_fast_acquire(mutex->synchbase.fastlock,
-                                   xnthread_handle(cur));
-       if (likely(!err))
-               shadow->lockcnt = 1;
-       else if (err == EBUSY) {
-               cobalt_mutex_t *mutex = shadow->mutex;
-
-               if (mutex->attr.type == PTHREAD_MUTEX_RECURSIVE) {
-                       if (shadow->lockcnt == UINT_MAX)
-                               err = EAGAIN;
-                       else {
-                               ++shadow->lockcnt;
-                               err = 0;
-                       }
-               }
+       return __xn_safe_copy_to_user(&u_mx->shadow_mutex,
+                                     &mx.shadow_mutex, 
sizeof(u_mx->shadow_mutex));
+}
+
+int cobalt_mutex_destroy(union __xeno_mutex __user *u_mx)
+{
+       struct __shadow_mutex *shadow;
+       union __xeno_mutex mx;
+       cobalt_mutex_t *mutex;
+
+       shadow = &mx.shadow_mutex;
+
+       if (__xn_safe_copy_from_user(shadow,
+                                    &u_mx->shadow_mutex,
+                                    sizeof(*shadow)))
+               return -EFAULT;
+
+       mutex = shadow->mutex;
+       if (cobalt_kqueues(mutex->attr.pshared) != mutex->owningq)
+               return -EPERM;
+
+       if (xnsynch_fast_owner_check(mutex->synchbase.fastlock,
+                                    XN_NO_HANDLE) != 0)
+               return -EBUSY;
+
+       if (countq(&mutex->conds))
+               return -EBUSY;
+
+       cobalt_mark_deleted(shadow);
+       cobalt_mutex_destroy_inner(mutex, mutex->owningq);
+
+       return __xn_safe_copy_to_user(&u_mx->shadow_mutex,
+                                     shadow, sizeof(u_mx->shadow_mutex));
+}
+
+int cobalt_mutex_trylock(union __xeno_mutex __user *u_mx)
+{
+       xnthread_t *cur = xnpod_current_thread();
+       cobalt_mutex_t *mutex;
+       int err;
+
+       __xn_get_user(mutex, &u_mx->shadow_mutex.mutex);
+
+       if (!cobalt_obj_active(mutex, COBALT_MUTEX_MAGIC,
+                              struct cobalt_mutex))
+               return -EINVAL;
+
+       err = xnsynch_fast_acquire(mutex->synchbase.fastlock,
+                                  xnthread_handle(cur));
+       switch(err) {
+       case 0:
+               if (xnthread_test_state(cur, XNOTHER))
+                       xnthread_inc_rescnt(cur);
+               break;
+
+/* This should not happen, as recursive mutexes are handled in
+   user-space */
+       case -EBUSY:
+               err = -EINVAL;
+               break;
+
+       case -EAGAIN:
+               err = -EBUSY;
+               break;
        }
 
-  out:
        return err;
 }
 
-/**
- * Lock a mutex.
- *
- * This service attempts to lock the mutex @a mx. If the mutex is free, it
- * becomes locked. If it was locked by another thread than the current one, the
- * current thread is suspended until the mutex is unlocked. If it was already
- * locked by the current mutex, the behaviour of this service depends on the
- * mutex type :
- * - for mutexes of the @a PTHREAD_MUTEX_NORMAL type, this service deadlocks;
- * - for mutexes of the @a PTHREAD_MUTEX_ERRORCHECK type, this service returns
- *   the EDEADLK error number;
- * - for mutexes of the @a PTHREAD_MUTEX_RECURSIVE type, this service 
increments
- *   the lock recursion count and returns 0.
- *
- * @param mx the mutex to be locked.
- *
- * @return 0 on success
- * @return an error number if:
- * - EPERM, the caller context is invalid;
- * - EINVAL, the mutex @a mx is invalid;
- * - EPERM, the mutex is not process-shared and does not belong to the current
- *   process;
- * - EDEADLK, the mutex is of the @a PTHREAD_MUTEX_ERRORCHECK type and was
- *   already locked by the current thread;
- * - EAGAIN, the mutex is of the @a PTHREAD_MUTEX_RECURSIVE type and the 
maximum
- *   number of recursive locks has been exceeded.
- *
- * @par Valid contexts:
- * - Xenomai kernel-space thread;
- * - Xenomai user-space thread (switches to primary mode).
- *
- * @see
- * <a 
href="http://www.opengroup.org/onlinepubs/000095399/functions/pthread_mutex_lock.html";>
- * Specification.</a>
- *
- */
-int pthread_mutex_lock(pthread_mutex_t * mx)
+int cobalt_mutex_lock(union __xeno_mutex __user *u_mx)
 {
-       struct __shadow_mutex *shadow =
-           &((union __xeno_mutex *)mx)->shadow_mutex;
+       cobalt_mutex_t *mutex;
        int err;
 
-       do {
-               err = cobalt_mutex_timedlock_break(shadow, 0, XN_INFINITE);
-       } while (err == -EINTR);
+       __xn_get_user(mutex, &u_mx->shadow_mutex.mutex);
+
+       err = cobalt_mutex_timedlock_break(mutex, 0, XN_INFINITE);
 
-       return -err;
+       return err;
 }
 
-/**
- * Attempt, during a bounded time, to lock a mutex.
- *
- * This service is equivalent to pthread_mutex_lock(), except that if the mutex
- * @a mx is locked by another thread than the current one, this service only
- * suspends the current thread until the timeout specified by @a to expires.
- *
- * @param mx the mutex to be locked;
- *
- * @param to the timeout, expressed as an absolute value of the CLOCK_REALTIME
- * clock.
- *
- * @return 0 on success;
- * @return an error number if:
- * - EPERM, the caller context is invalid;
- * - EINVAL, the mutex @a mx is invalid;
- * - EPERM, the mutex is not process-shared and does not belong to the current
- *   process;
- * - ETIMEDOUT, the mutex could not be locked and the specified timeout
- *   expired;
- * - EDEADLK, the mutex is of the @a PTHREAD_MUTEX_ERRORCHECK type and the 
mutex
- *   was already locked by the current thread;
- * - EAGAIN, the mutex is of the @a PTHREAD_MUTEX_RECURSIVE type and the 
maximum
- *   number of recursive locks has been exceeded.
- *
- * @par Valid contexts:
- * - Xenomai kernel-space thread;
- * - Xenomai user-space thread (switches to primary mode).
- *
- * @see
- * <a 
href="http://www.opengroup.org/onlinepubs/000095399/functions/pthread_mutex_timedlock.html";>
- * Specification.</a>
- *
- */
-int pthread_mutex_timedlock(pthread_mutex_t * mx, const struct timespec *to)
+int cobalt_mutex_timedlock(union __xeno_mutex __user *u_mx,
+                          const struct timespec __user *u_ts)
 {
-       struct __shadow_mutex *shadow =
-           &((union __xeno_mutex *)mx)->shadow_mutex;
+       cobalt_mutex_t *mutex;
+       struct timespec ts;
        int err;
 
-       do {
-               err = cobalt_mutex_timedlock_break(shadow, 1,
-                                                  ts2ns(to) + 1);
-       } while (err == -EINTR);
+       __xn_get_user(mutex, &u_mx->shadow_mutex.mutex);
+
+       if (__xn_safe_copy_from_user(&ts, u_ts, sizeof(ts)))
+               return -EFAULT;
 
-       return -err;
+       err = cobalt_mutex_timedlock_break(mutex, 1, ts2ns(&ts) + 1);
+
+       return err;
 }
 
-/**
- * Unlock a mutex.
- *
- * This service unlocks the mutex @a mx. If the mutex is of the @a
- * PTHREAD_MUTEX_RECURSIVE @a type and the locking recursion count is greater
- * than one, the lock recursion count is decremented and the mutex remains
- * locked.
- *
- * Attempting to unlock a mutex which is not locked or which is locked by
- * another thread than the current one yields the EPERM error, whatever the
- * mutex @a type attribute.
- *
- * @param mx the mutex to be released.
- *
- * @return 0 on success;
- * @return an error number if:
- * - EPERM, the caller context is invalid;
- * - EINVAL, the mutex @a mx is invalid;
- * - EPERM, the mutex was not locked by the current thread.
- *
- * @par Valid contexts:
- * - Xenomai kernel-space thread,
- * - kernel-space cancellation cleanup routine,
- * - Xenomai user-space thread (switches to primary mode),
- * - user-space cancellation cleanup routine.
- *
- * @see
- * <a 
href="http://www.opengroup.org/onlinepubs/000095399/functions/pthread_mutex_unlock.html";>
- * Specification.</a>
- *
- */
-int pthread_mutex_unlock(pthread_mutex_t * mx)
+int cobalt_mutex_unlock(union __xeno_mutex __user *u_mx)
 {
-       struct __shadow_mutex *shadow =
-           &((union __xeno_mutex *)mx)->shadow_mutex;
-       xnthread_t *cur = xnpod_current_thread();
        cobalt_mutex_t *mutex;
        int err;
+       spl_t s;
 
-       if (xnpod_root_p() || xnpod_interrupt_p())
-               return EPERM;
+       if (xnpod_root_p())
+               return -EPERM;
 
-       mutex = shadow->mutex;
+       __xn_get_user(mutex, &u_mx->shadow_mutex.mutex);
 
-       if (!cobalt_obj_active(shadow,
-                             COBALT_MUTEX_MAGIC, struct __shadow_mutex)
-           || !cobalt_obj_active(mutex, COBALT_MUTEX_MAGIC, struct 
cobalt_mutex)) {
-               err = EINVAL;
-               goto out;
-       }
-
-       err = -xnsynch_owner_check(&mutex->synchbase, cur);
-       if (err)
+       xnlock_get_irqsave(&nklock, s);
+       err = cobalt_mutex_release(xnpod_current_thread(), mutex);
+       if (err < 0)
                goto out;
 
-       if (shadow->lockcnt > 1) {
-               /* Mutex is recursive */
-               --shadow->lockcnt;
-               return 0;
-       }
-
-       if (xnsynch_release(&mutex->synchbase))
+       if (err) {
                xnpod_schedule();
-
+               err = 0;
+       }
   out:
+       xnlock_put_irqrestore(&nklock, s);
+
        return err;
 }
 
@@ -573,7 +408,7 @@ void cobalt_mutexq_cleanup(cobalt_kqueues_t *q)
 
        while ((holder = getheadq(&q->mutexq)) != NULL) {
                xnlock_put_irqrestore(&nklock, s);
-               cobalt_mutex_destroy_internal(link2mutex(holder), q);
+               cobalt_mutex_destroy_inner(link2mutex(holder), q);
 #if XENO_DEBUG(POSIX)
                xnprintf("Posix: destroying mutex %p.\n", link2mutex(holder));
 #endif /* XENO_DEBUG(POSIX) */
@@ -595,10 +430,3 @@ void cobalt_mutex_pkg_cleanup(void)
 }
 
 /*@}*/
-
-EXPORT_SYMBOL_GPL(pthread_mutex_init);
-EXPORT_SYMBOL_GPL(pthread_mutex_destroy);
-EXPORT_SYMBOL_GPL(pthread_mutex_trylock);
-EXPORT_SYMBOL_GPL(pthread_mutex_lock);
-EXPORT_SYMBOL_GPL(pthread_mutex_timedlock);
-EXPORT_SYMBOL_GPL(pthread_mutex_unlock);
diff --git a/kernel/cobalt/mutex.h b/kernel/cobalt/mutex.h
index 5f523ab..6b6d360 100644
--- a/kernel/cobalt/mutex.h
+++ b/kernel/cobalt/mutex.h
@@ -62,45 +62,13 @@ typedef struct cobalt_mutex {
 
 extern pthread_mutexattr_t cobalt_default_mutex_attr;
 
-void cobalt_mutexq_cleanup(cobalt_kqueues_t *q);
-
-void cobalt_mutex_pkg_init(void);
-
-void cobalt_mutex_pkg_cleanup(void);
-
-/* Internal mutex functions, exposed for use by syscall.c. */
-int cobalt_mutex_timedlock_break(struct __shadow_mutex *shadow,
-                               int timed, xnticks_t to);
-
-int cobalt_mutex_check_init(struct __shadow_mutex *shadow,
-                          const pthread_mutexattr_t *attr);
-
-int cobalt_mutex_init_internal(struct __shadow_mutex *shadow,
-                             cobalt_mutex_t *mutex,
-                             xnarch_atomic_t *ownerp,
-                             const pthread_mutexattr_t *attr);
-
-void cobalt_mutex_destroy_internal(cobalt_mutex_t *mutex,
-                                 cobalt_kqueues_t *q);
-
 /* must be called with nklock locked, interrupts off. */
-static inline int cobalt_mutex_timedlock_internal(xnthread_t *cur,
+static inline int cobalt_mutex_acquire_unchecked(xnthread_t *cur,
                                                 cobalt_mutex_t *mutex,
                                                 int timed,
                                                 xnticks_t abs_to)
 
 {
-       if (xnpod_unblockable_p())
-               return -EPERM;
-
-       if (!cobalt_obj_active(mutex, COBALT_MUTEX_MAGIC, struct cobalt_mutex))
-               return -EINVAL;
-
-#if XENO_DEBUG(POSIX)
-       if (mutex->owningq != cobalt_kqueues(mutex->attr.pshared))
-               return -EPERM;
-#endif /* XENO_DEBUG(POSIX) */
-
        if (xnsynch_owner_check(&mutex->synchbase, cur) == 0)
                return -EBUSY;
 
@@ -121,8 +89,7 @@ static inline int cobalt_mutex_timedlock_internal(xnthread_t 
*cur,
        return 0;
 }
 
-static inline int cobalt_mutex_release(xnthread_t *cur,
-                                      cobalt_mutex_t *mutex)
+static inline int cobalt_mutex_release(xnthread_t *cur, cobalt_mutex_t *mutex)
 {
        xnholder_t *holder;
        int need_resched;
@@ -160,6 +127,27 @@ static inline int cobalt_mutex_release(xnthread_t *cur,
           done atomically in pthread_cond_*wait. */
 }
 
+int cobalt_mutex_check_init(union __xeno_mutex __user *u_mx);
+
+int cobalt_mutex_init(union __xeno_mutex __user *u_mx,
+                     const pthread_mutexattr_t __user *u_attr);
+
+int cobalt_mutex_destroy(union __xeno_mutex __user *u_mx);
+
+int cobalt_mutex_trylock(union __xeno_mutex __user *u_mx);
+
+int cobalt_mutex_lock(union __xeno_mutex __user *u_mx);
+
+int cobalt_mutex_timedlock(union __xeno_mutex __user *u_mx,
+                          const struct timespec __user *u_ts);
+
+int cobalt_mutex_unlock(union __xeno_mutex __user *u_mx);
+
+void cobalt_mutexq_cleanup(cobalt_kqueues_t *q);
+
+void cobalt_mutex_pkg_init(void);
+
+void cobalt_mutex_pkg_cleanup(void);
 #endif /* __KERNEL__ */
 
 #endif /* !_POSIX_MUTEX_H */
diff --git a/kernel/cobalt/syscall.c b/kernel/cobalt/syscall.c
index 7664ece..0233d8a 100644
--- a/kernel/cobalt/syscall.c
+++ b/kernel/cobalt/syscall.c
@@ -1048,249 +1048,6 @@ static int 
__pthread_mutexattr_setpshared(pthread_mutexattr_t __user *u_attr,
        return __xn_safe_copy_to_user(u_attr, &attr, sizeof(*u_attr));
 }
 
-static int __pthread_mutex_check_init(union __xeno_mutex __user *u_mx,
-                                     const pthread_mutexattr_t __user *u_attr)
-{
-       pthread_mutexattr_t locattr, *attr;
-       union __xeno_mutex mx;
-
-       if (__xn_safe_copy_from_user(&mx.shadow_mutex,
-                                    &u_mx->shadow_mutex,
-                                    sizeof(mx.shadow_mutex)))
-               return -EFAULT;
-
-       if (u_attr) {
-               if (__xn_safe_copy_from_user(&locattr, u_attr,
-                                            sizeof(locattr)))
-                       return -EFAULT;
-
-               attr = &locattr;
-       } else
-               attr = NULL;
-
-       return cobalt_mutex_check_init(&u_mx->shadow_mutex, attr);
-}
-
-static int __pthread_mutex_init(union __xeno_mutex __user *u_mx,
-                               const pthread_mutexattr_t __user *u_attr)
-{
-       pthread_mutexattr_t locattr, *attr;
-       xnarch_atomic_t *ownerp;
-       union __xeno_mutex mx;
-       cobalt_mutex_t *mutex;
-       int err;
-
-       if (__xn_safe_copy_from_user(&mx.shadow_mutex,
-                                    &u_mx->shadow_mutex,
-                                    sizeof(mx.shadow_mutex)))
-               return -EFAULT;
-
-       if (u_attr) {
-               if (__xn_safe_copy_from_user(&locattr, u_attr,
-                                            sizeof(locattr)))
-                       return -EFAULT;
-
-               attr = &locattr;
-       } else
-               attr = &cobalt_default_mutex_attr;
-
-       mutex = xnmalloc(sizeof(*mutex));
-       if (mutex == NULL)
-               return -ENOMEM;
-
-       ownerp = xnheap_alloc(&xnsys_ppd_get(attr->pshared)->sem_heap,
-                             sizeof(xnarch_atomic_t));
-       if (ownerp == NULL) {
-               xnfree(mutex);
-               return -EAGAIN;
-       }
-
-       err = cobalt_mutex_init_internal(&mx.shadow_mutex, mutex, ownerp, attr);
-       if (err) {
-               xnfree(mutex);
-               xnheap_free(&xnsys_ppd_get(attr->pshared)->sem_heap, ownerp);
-               return err;
-       }
-
-       return __xn_safe_copy_to_user(&u_mx->shadow_mutex,
-                                     &mx.shadow_mutex, 
sizeof(u_mx->shadow_mutex));
-}
-
-static int __pthread_mutex_destroy(union __xeno_mutex __user *u_mx)
-{
-       struct __shadow_mutex *shadow;
-       union __xeno_mutex mx;
-       cobalt_mutex_t *mutex;
-
-       shadow = &mx.shadow_mutex;
-
-       if (__xn_safe_copy_from_user(shadow,
-                                    &u_mx->shadow_mutex,
-                                    sizeof(*shadow)))
-               return -EFAULT;
-
-       if (!cobalt_obj_active(shadow, COBALT_MUTEX_MAGIC, struct 
__shadow_mutex))
-               return -EINVAL;
-
-       mutex = shadow->mutex;
-       if (cobalt_kqueues(mutex->attr.pshared) != mutex->owningq)
-               return -EPERM;
-
-       if (xnsynch_fast_owner_check(mutex->synchbase.fastlock,
-                                    XN_NO_HANDLE) != 0)
-               return -EBUSY;
-
-       if (countq(&mutex->conds))
-               return -EBUSY;
-
-       cobalt_mark_deleted(shadow);
-       cobalt_mutex_destroy_internal(mutex, mutex->owningq);
-
-       return __xn_safe_copy_to_user(&u_mx->shadow_mutex,
-                                     shadow, sizeof(u_mx->shadow_mutex));
-}
-
-static int __pthread_mutex_trylock(union __xeno_mutex __user *u_mx)
-{
-       xnthread_t *cur = xnpod_current_thread();
-       struct __shadow_mutex *shadow;
-       cobalt_mutex_t *mutex;
-       union __xeno_mutex mx;
-       int err;
-
-       if (__xn_safe_copy_from_user(&mx.shadow_mutex,
-                                    &u_mx->shadow_mutex,
-                                    offsetof(struct __shadow_mutex, owner)))
-               return -EFAULT;
-
-       shadow = &mx.shadow_mutex;
-       mutex = shadow->mutex;
-
-       if (!cobalt_obj_active(shadow, COBALT_MUTEX_MAGIC,
-                             struct __shadow_mutex)
-           || !cobalt_obj_active(mutex, COBALT_MUTEX_MAGIC,
-                                struct cobalt_mutex)) {
-               return -EINVAL;
-       }
-
-       err = xnsynch_fast_acquire(mutex->synchbase.fastlock,
-                                  xnthread_handle(cur));
-       switch(err) {
-       case 0:
-               if (xnthread_test_state(cur, XNOTHER))
-                       xnthread_inc_rescnt(cur);
-               shadow->lockcnt = 1;
-               break;
-
-       case -EBUSY:
-/* This should not happen, as recursive mutexes are handled in
-   user-space */
-               if (mutex->attr.type == PTHREAD_MUTEX_RECURSIVE) {
-                       if (shadow->lockcnt == UINT_MAX)
-                               err = -EAGAIN;
-                       else {
-                               ++shadow->lockcnt;
-                               err = 0;
-                       }
-               }
-               break;
-
-       case -EAGAIN:
-               err = -EBUSY;
-               break;
-       }
-
-       if (err == 0 &&
-           __xn_safe_copy_to_user(&u_mx->shadow_mutex.lockcnt,
-                                  &shadow->lockcnt,
-                                  sizeof(u_mx->shadow_mutex.lockcnt)))
-               return -EFAULT;
-
-       return err;
-}
-
-static int __pthread_mutex_lock(union __xeno_mutex __user *u_mx)
-{
-       struct __shadow_mutex *shadow;
-       union __xeno_mutex mx;
-       int err;
-
-       if (__xn_safe_copy_from_user(&mx.shadow_mutex,
-                                    &u_mx->shadow_mutex,
-                                    offsetof(struct __shadow_mutex, owner)))
-               return -EFAULT;
-
-       shadow = &mx.shadow_mutex;
-
-       err = cobalt_mutex_timedlock_break(&mx.shadow_mutex, 0, XN_INFINITE);
-       if (err == 0 &&
-           __xn_safe_copy_to_user(&u_mx->shadow_mutex.lockcnt,
-                                  &shadow->lockcnt,
-                                  sizeof(u_mx->shadow_mutex.lockcnt)))
-               return -EFAULT;
-
-       return err;
-}
-
-static int __pthread_mutex_timedlock(union __xeno_mutex __user *u_mx,
-                                    const struct timespec __user *u_ts)
-{
-       struct __shadow_mutex *shadow;
-       union __xeno_mutex mx;
-       struct timespec ts;
-       int err;
-
-       if (__xn_safe_copy_from_user(&mx.shadow_mutex,
-                                    &u_mx->shadow_mutex,
-                                    sizeof(mx.shadow_mutex)))
-               return -EFAULT;
-
-       if (__xn_safe_copy_from_user(&ts, u_ts, sizeof(ts)))
-               return -EFAULT;
-
-       shadow = &mx.shadow_mutex;
-
-       err = cobalt_mutex_timedlock_break(&mx.shadow_mutex,
-                                         1, ts2ns(&ts) + 1);
-       if (err == 0 &&
-           __xn_safe_copy_to_user(&u_mx->shadow_mutex.lockcnt,
-                                  &shadow->lockcnt,
-                                  sizeof(u_mx->shadow_mutex.lockcnt)))
-               return -EFAULT;
-
-       return err;
-}
-
-static int __pthread_mutex_unlock(union __xeno_mutex __user *u_mx)
-{
-       union __xeno_mutex mx;
-       int err;
-       spl_t s;
-
-       if (xnpod_root_p())
-               return -EPERM;
-
-       if (__xn_safe_copy_from_user(&mx.shadow_mutex,
-                                    &u_mx->shadow_mutex,
-                                    offsetof(struct __shadow_mutex, owner)))
-               return -EFAULT;
-
-       xnlock_get_irqsave(&nklock, s);
-       err = cobalt_mutex_release(xnpod_current_thread(),
-                                  mx.shadow_mutex.mutex);
-       if (err < 0)
-               goto out;
-
-       if (err) {
-               xnpod_schedule();
-               err = 0;
-       }
-  out:
-       xnlock_put_irqrestore(&nklock, s);
-
-       return err;
-}
-
 static int __pthread_condattr_init(pthread_condattr_t __user *u_attr)
 {
        pthread_condattr_t attr;
@@ -2288,13 +2045,13 @@ static struct xnsysent __systab[] = {
        SKINCALL_DEF(__cobalt_clock_gettime, __clock_gettime, any),
        SKINCALL_DEF(__cobalt_clock_settime, __clock_settime, any),
        SKINCALL_DEF(__cobalt_clock_nanosleep, __clock_nanosleep, 
nonrestartable),
-       SKINCALL_DEF(__cobalt_mutex_init, __pthread_mutex_init, any),
-       SKINCALL_DEF(__cobalt_check_init, __pthread_mutex_check_init, any),
-       SKINCALL_DEF(__cobalt_mutex_destroy, __pthread_mutex_destroy, any),
-       SKINCALL_DEF(__cobalt_mutex_lock, __pthread_mutex_lock, primary),
-       SKINCALL_DEF(__cobalt_mutex_timedlock, __pthread_mutex_timedlock, 
primary),
-       SKINCALL_DEF(__cobalt_mutex_trylock, __pthread_mutex_trylock, primary),
-       SKINCALL_DEF(__cobalt_mutex_unlock, __pthread_mutex_unlock, 
nonrestartable),
+       SKINCALL_DEF(__cobalt_mutex_init, cobalt_mutex_init, any),
+       SKINCALL_DEF(__cobalt_check_init, cobalt_mutex_check_init, any),
+       SKINCALL_DEF(__cobalt_mutex_destroy, cobalt_mutex_destroy, any),
+       SKINCALL_DEF(__cobalt_mutex_lock, cobalt_mutex_lock, primary),
+       SKINCALL_DEF(__cobalt_mutex_timedlock, cobalt_mutex_timedlock, primary),
+       SKINCALL_DEF(__cobalt_mutex_trylock, cobalt_mutex_trylock, primary),
+       SKINCALL_DEF(__cobalt_mutex_unlock, cobalt_mutex_unlock, 
nonrestartable),
        SKINCALL_DEF(__cobalt_cond_init, cobalt_cond_init, any),
        SKINCALL_DEF(__cobalt_cond_destroy, cobalt_cond_destroy, any),
        SKINCALL_DEF(__cobalt_cond_wait_prologue, cobalt_cond_wait_prologue, 
nonrestartable),
diff --git a/lib/cobalt/mutex.c b/lib/cobalt/mutex.c
index 908bdeb..e8d0bca 100644
--- a/lib/cobalt/mutex.c
+++ b/lib/cobalt/mutex.c
@@ -96,10 +96,13 @@ int __wrap_pthread_mutex_init(pthread_mutex_t *mutex,
        struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
        int err;
 
-       err = 
-XENOMAI_SKINCALL2(__cobalt_muxid,__cobalt_check_init,shadow,attr);
+       if (shadow->magic == COBALT_MUTEX_MAGIC) {
+               err = -XENOMAI_SKINCALL1(__cobalt_muxid,
+                                        __cobalt_check_init,shadow);
 
-       if (err)
-               return err;
+               if (err)
+                       return err;
+       }
 
        err = 
-XENOMAI_SKINCALL2(__cobalt_muxid,__cobalt_mutex_init,shadow,attr);
 
@@ -116,9 +119,12 @@ int __wrap_pthread_mutex_destroy(pthread_mutex_t *mutex)
        struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
        int err;
 
-       err = -XENOMAI_SKINCALL1(__cobalt_muxid, __cobalt_mutex_destroy, 
shadow);
+       if (shadow->magic != COBALT_MUTEX_MAGIC)
+               return EINVAL;
 
-       return err;
+       err = XENOMAI_SKINCALL1(__cobalt_muxid, __cobalt_mutex_destroy, shadow);
+
+       return -err;
 }
 
 int __wrap_pthread_mutex_lock(pthread_mutex_t *mutex)
@@ -134,51 +140,49 @@ int __wrap_pthread_mutex_lock(pthread_mutex_t *mutex)
        if (cur == XN_NO_HANDLE)
                return EPERM;
 
-       status = xeno_get_current_mode();
-
-       if (shadow->magic != COBALT_MUTEX_MAGIC) {
-               err = -EINVAL;
-               goto out;
-       }
+       if (shadow->magic != COBALT_MUTEX_MAGIC)
+               return EINVAL;
 
        /*
         * 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.
         */
+       status = xeno_get_current_mode();
        if (likely(!(status & (XNRELAX|XNOTHER)))) {
                err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
-
                if (likely(!err)) {
                        shadow->lockcnt = 1;
                        return 0;
                }
+       } else {
+               err = xnsynch_fast_owner_check(get_ownerp(shadow), cur);
+               if (!err)
+                       err = -EBUSY;
+       }
+
+       if (err == -EBUSY)
+               switch(shadow->attr.type) {
+               case PTHREAD_MUTEX_NORMAL:
+                       break;
 
-               if (err == -EBUSY)
-                       switch(shadow->attr.type) {
-                       case PTHREAD_MUTEX_NORMAL:
-                               break;
-
-                       case PTHREAD_MUTEX_ERRORCHECK:
-                               err = -EDEADLK;
-                               goto out;
-
-                       case PTHREAD_MUTEX_RECURSIVE:
-                               if (shadow->lockcnt == UINT_MAX) {
-                                       err = -EAGAIN;
-                                       goto out;
-                               }
-                               ++shadow->lockcnt;
-                               err = 0;
-                               goto out;
-                       }
+               case PTHREAD_MUTEX_ERRORCHECK:
+                       return EDEADLK;
+
+               case PTHREAD_MUTEX_RECURSIVE:
+                       if (shadow->lockcnt == UINT_MAX)
+                               return EAGAIN;
+                       ++shadow->lockcnt;
+                       return 0;
                }
 
        do {
                err = 
XENOMAI_SKINCALL1(__cobalt_muxid,__cobalt_mutex_lock,shadow);
        } while (err == -EINTR);
 
-  out:
+       if (!err)
+               shadow->lockcnt = 1;
+
        return -err;
 }
 
@@ -195,48 +199,46 @@ int __wrap_pthread_mutex_timedlock(pthread_mutex_t *mutex,
        if (cur == XN_NO_HANDLE)
                return EPERM;
 
-       status = xeno_get_current_mode();
-
-       if (shadow->magic != COBALT_MUTEX_MAGIC) {
-               err = -EINVAL;
-               goto out;
-       }
+       if (shadow->magic != COBALT_MUTEX_MAGIC)
+               return EINVAL;
 
        /* See __wrap_pthread_mutex_lock() */
+       status = xeno_get_current_mode();
        if (likely(!(status & (XNRELAX|XNOTHER)))) {
                err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
-
                if (likely(!err)) {
                        shadow->lockcnt = 1;
                        return 0;
                }
+       } else {
+               err = xnsynch_fast_owner_check(get_ownerp(shadow), cur);
+               if (!err)
+                       err = -EBUSY;
+       }
 
-               if (err == -EBUSY)
-                       switch(shadow->attr.type) {
-                       case PTHREAD_MUTEX_NORMAL:
-                               break;
+       if (err == -EBUSY)
+               switch(shadow->attr.type) {
+               case PTHREAD_MUTEX_NORMAL:
+                       break;
 
-                       case PTHREAD_MUTEX_ERRORCHECK:
-                               err = -EDEADLK;
-                               goto out;
+               case PTHREAD_MUTEX_ERRORCHECK:
+                       return EDEADLK;
 
-                       case PTHREAD_MUTEX_RECURSIVE:
-                               if (shadow->lockcnt == UINT_MAX) {
-                                       err = -EAGAIN;
-                                       goto out;
-                               }
+               case PTHREAD_MUTEX_RECURSIVE:
+                       if (shadow->lockcnt == UINT_MAX)
+                               return EAGAIN;
 
-                               ++shadow->lockcnt;
-                               goto out;
-                       }
-       }
+                       ++shadow->lockcnt;
+                       return 0;
+               }
 
        do {
                err = XENOMAI_SKINCALL2(__cobalt_muxid,
                                        __cobalt_mutex_timedlock, shadow, to);
        } while (err == -EINTR);
 
-  out:
+       if (!err)
+               shadow->lockcnt = 1;
        return -err;
 }
 
@@ -244,7 +246,7 @@ int __wrap_pthread_mutex_trylock(pthread_mutex_t *mutex)
 {
        union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
        struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
-       xnarch_atomic_t *ownerp;
+       unsigned long status;
        xnhandle_t cur;
        int err;
 
@@ -252,48 +254,46 @@ int __wrap_pthread_mutex_trylock(pthread_mutex_t *mutex)
        if (cur == XN_NO_HANDLE)
                return EPERM;
 
-       if (unlikely(shadow->magic != COBALT_MUTEX_MAGIC)) {
-               err = EINVAL;
-               goto out;
-       }
+       if (unlikely(shadow->magic != COBALT_MUTEX_MAGIC))
+               return EINVAL;
 
-       ownerp = get_ownerp(shadow);
-       err = xnsynch_fast_owner_check(ownerp, cur);
-       if (err == 0) {
-               if (shadow->attr.type == PTHREAD_MUTEX_RECURSIVE) {
-                       if (shadow->lockcnt == UINT_MAX)
-                               err = EAGAIN;
-                       else {
-                               ++shadow->lockcnt;
-                               err = 0;
-                       }
-               } else
-                       err = EBUSY;
-               goto out;
-       }
+       status = xeno_get_current_mode();
+       if (likely(!(status & (XNRELAX|XNOTHER)))) {
+               err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
+               if (likely(!err)) {
+                       shadow->lockcnt = 1;
+                       return 0;
+               }
+       } else {
+               err = xnsynch_fast_owner_check(get_ownerp(shadow), cur);
+               if (err < 0)
+                       goto do_syscall;
 
-       if (unlikely(xeno_get_current_mode() & (XNOTHER | XNRELAX)))
-               goto do_syscall;
+               err = -EBUSY;
+       }
 
-       err = xnsynch_fast_acquire(ownerp, cur);
+       if (err == -EBUSY && shadow->attr.type == PTHREAD_MUTEX_RECURSIVE) {
+               if (shadow->lockcnt == UINT_MAX)
+                       return EAGAIN;
 
-       if (likely(!err)) {
-               shadow->lockcnt = 1;
+               ++shadow->lockcnt;
                return 0;
-       }
-
-       err = EBUSY;
+       } else
+               err = -EBUSY;
        goto out;
 
 do_syscall:
 
        do {
-               err = -XENOMAI_SKINCALL1(__cobalt_muxid,
-                                        __cobalt_mutex_trylock, shadow);
-       } while (err == EINTR);
+               err = XENOMAI_SKINCALL1(__cobalt_muxid,
+                                       __cobalt_mutex_trylock, shadow);
+       } while (err == -EINTR);
+
+       if (!err)
+               shadow->lockcnt = 1;
 
   out:
-       return err;
+       return -err;
 }
 
 int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex)
@@ -301,37 +301,33 @@ int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex)
        union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
        struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
        xnarch_atomic_t *ownerp;
-       xnhandle_t cur;
+       xnhandle_t cur, owner;
        int err;
 
+       if (unlikely(shadow->magic != COBALT_MUTEX_MAGIC))
+               return EINVAL;
+
        cur = xeno_get_current();
        if (cur == XN_NO_HANDLE)
                return EPERM;
 
-       if (unlikely(shadow->magic != COBALT_MUTEX_MAGIC)) {
-               err = -EINVAL;
-               goto out_err;
-       }
-
        ownerp = get_ownerp(shadow);
-
-       err = xnsynch_fast_owner_check(ownerp, cur);
-       if (unlikely(err))
-               goto out_err;
+       owner = xnarch_atomic_get(ownerp);
+       if (xnhandle_mask_spares(owner) != cur)
+               return EPERM;
 
        if (shadow->lockcnt > 1) {
                --shadow->lockcnt;
-               goto out;
+               return 0;
        }
 
-       if (unlikely(xeno_get_current_mode() & XNOTHER))
+       if ((owner & COBALT_MUTEX_COND_SIGNAL))
                goto do_syscall;
 
-       if (unlikely(xnsynch_fast_check_spares(ownerp, 
COBALT_MUTEX_COND_SIGNAL)))
+       if (unlikely(xeno_get_current_mode() & XNOTHER))
                goto do_syscall;
 
        if (likely(xnsynch_fast_release(ownerp, cur)))
-         out:
                return 0;
 
 do_syscall:
@@ -341,6 +337,5 @@ do_syscall:
                                        __cobalt_mutex_unlock, shadow);
        } while (err == -EINTR);
 
-  out_err:
        return -err;
 }


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

Reply via email to