From: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
To: xenomai@xenomai.org
Subject: [Xenomai-core] [9/9] Re-implementation of mutex, user-space support.
Date: Thu, 24 Apr 2008 08:33:10 +0200 [thread overview]
Message-ID: <18448.10662.83570.781983@domain.hid> (raw)
In-Reply-To: <18448.10594.876717.762863@domain.hid>
The new implementation. In user-space, without syscall in the common case when a
mutex is free when locking it, and was not claimed when unlocking it.
Note that this change entails a change in behaviour of the mutexes: before this
change locking a mutex caused the calling thread to switch to primary mode. Now,
the thread locking a mutex without syscall remains in the same mode.
---
Makefile.am | 2
cond.c | 21 ++++
mutex.c | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
3 files changed, 260 insertions(+), 25 deletions(-)
Index: src/skins/posix/mutex.c
===================================================================
--- src/skins/posix/mutex.c (revision 3718)
+++ src/skins/posix/mutex.c (working copy)
@@ -18,9 +18,14 @@
#include <errno.h>
#include <posix/syscall.h>
+#include <posix/cb_lock.h>
#include <pthread.h>
+#define PSE51_MUTEX_MAGIC (0x86860303)
+
extern int __pse51_muxid;
+extern pthread_key_t pse51_cur_key;
+extern unsigned long pse51_shared_map[2];
int __wrap_pthread_mutexattr_init(pthread_mutexattr_t *attr)
{
@@ -73,66 +78,279 @@ int __wrap_pthread_mutexattr_setpshared(
__pse51_mutexattr_setpshared, attr, pshared);
}
-int __wrap_pthread_mutex_init(pthread_mutex_t * mutex,
- const pthread_mutexattr_t * attr)
+static atomic_ptr_t *get_ownerp(struct __shadow_mutex *shadow)
+{
+ if (likely(!shadow->attr.pshared))
+ return shadow->owner;
+
+ return (atomic_ptr_t *) (pse51_shared_map[1] + shadow->owner_offset);
+}
+
+int __wrap_pthread_mutex_init(pthread_mutex_t *mutex,
+ const pthread_mutexattr_t *attr)
{
union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
+ struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
int err;
- err = -XENOMAI_SKINCALL2(__pse51_muxid,
- __pse51_mutex_init,&_mutex->shadow_mutex,attr);
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+ if (unlikely(cb_try_read_lock(&shadow->lock, s)))
+ goto checked;
+
+ err = -XENOMAI_SKINCALL2(__pse51_muxid,__pse51_check_init,shadow,attr);
+
+ if (err) {
+ cb_read_unlock(&shadow->lock, s);
+ return err;
+ }
+
+ checked:
+ cb_force_write_lock(&shadow->lock, s);
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
+
+ err = -XENOMAI_SKINCALL2(__pse51_muxid,__pse51_mutex_init,shadow,attr);
+
+ if (!shadow->attr.pshared)
+ shadow->owner = (atomic_ptr_t *)
+ (pse51_shared_map[0] + shadow->owner_offset);
+
+ cb_write_unlock(&shadow->lock, s);
+
return err;
}
-int __wrap_pthread_mutex_destroy(pthread_mutex_t * mutex)
+int __wrap_pthread_mutex_destroy(pthread_mutex_t *mutex)
{
union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
+ struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
+ int err;
- return -XENOMAI_SKINCALL1(__pse51_muxid,
- __pse51_mutex_destroy, &_mutex->shadow_mutex);
+ if (unlikely(cb_try_write_lock(&shadow->lock, s)))
+ return EINVAL;
+
+ err = -XENOMAI_SKINCALL1(__pse51_muxid, __pse51_mutex_destroy, shadow);
+
+ cb_write_unlock(&shadow->lock, s);
+
+ return err;
}
-int __wrap_pthread_mutex_lock(pthread_mutex_t * mutex)
+int __wrap_pthread_mutex_lock(pthread_mutex_t *mutex)
{
union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
- int err;
+ struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
+ xnthread_t *cur, *owner;
+ int err = 0;
+
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+ cur = pthread_getspecific(pse51_cur_key);
+ if (!cur)
+ return EPERM;
+
+ if (unlikely(cb_try_read_lock(&shadow->lock, s)))
+ return EINVAL;
+
+ if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ owner = atomic_ptr_cmpxchg(get_ownerp(shadow), NULL, cur);
+ if (likely(!owner)) {
+ shadow->lockcnt = 1;
+ cb_read_unlock(&shadow->lock, s);
+ return 0;
+ }
+
+ if (clear_claimed(owner) == cur)
+ 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;
+ goto out;
+ }
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
do {
- err = XENOMAI_SKINCALL1(__pse51_muxid,
- __pse51_mutex_lock,
- &_mutex->shadow_mutex);
+ err = XENOMAI_SKINCALL1(__pse51_muxid,__pse51_mutex_lock,shadow);
} while (err == -EINTR);
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+ out:
+ cb_read_unlock(&shadow->lock, s);
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
+
return -err;
}
-int __wrap_pthread_mutex_timedlock(pthread_mutex_t * mutex,
+int __wrap_pthread_mutex_timedlock(pthread_mutex_t *mutex,
const struct timespec *to)
{
union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
- int err;
+ struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
+ xnthread_t *cur, *owner;
+ int err = 0;
+
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+ cur = pthread_getspecific(pse51_cur_key);
+ if (!cur)
+ return EPERM;
+
+ if (unlikely(cb_try_read_lock(&shadow->lock, s)))
+ return EINVAL;
+
+ if (shadow->magic != PSE51_MUTEX_MAGIC) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ owner = atomic_ptr_cmpxchg(get_ownerp(shadow), NULL, cur);
+ if (likely(!owner)) {
+ shadow->lockcnt = 1;
+ cb_read_unlock(&shadow->lock, s);
+ return 0;
+ }
+
+ if (clear_claimed(owner) == cur)
+ 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;
+ goto out;
+ }
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
do {
err = XENOMAI_SKINCALL2(__pse51_muxid,
- __pse51_mutex_timedlock,
- &_mutex->shadow_mutex, to);
+ __pse51_mutex_timedlock, shadow, to);
} while (err == -EINTR);
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+ out:
+ cb_read_unlock(&shadow->lock, s);
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
+
return -err;
}
-int __wrap_pthread_mutex_trylock(pthread_mutex_t * mutex)
+int __wrap_pthread_mutex_trylock(pthread_mutex_t *mutex)
{
union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
+ struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
+ xnthread_t *cur, *owner;
+ int err = 0;
+
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+ cur = pthread_getspecific(pse51_cur_key);
+ if (!cur)
+ return EPERM;
+
+ if (unlikely(cb_try_read_lock(&shadow->lock, s)))
+ return EINVAL;
+
+ if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ owner = atomic_ptr_cmpxchg(get_ownerp(shadow), NULL, cur);
+ if (likely(!owner)) {
+ shadow->lockcnt = 1;
+ cb_read_unlock(&shadow->lock, s);
+ return 0;
+ }
+
+ err = -EBUSY;
+ if (clear_claimed(owner) == cur
+ && shadow->attr.type == PTHREAD_MUTEX_RECURSIVE)
+ if (shadow->lockcnt == UINT_MAX)
+ err = -EAGAIN;
+ else {
+ ++shadow->lockcnt;
+ err = 0;
+ }
+
+ out:
+ cb_read_unlock(&shadow->lock, s);
+
+ return -err;
+
+#else /* !XNARCH_HAVE_US_ATOMIC_CMPXCHG */
+
+ return -XENOMAI_SKINCALL1(__pse51_muxid, __pse51_mutex_trylock, shadow);
- return -XENOMAI_SKINCALL1(__pse51_muxid,
- __pse51_mutex_trylock, &_mutex->shadow_mutex);
+#endif /* !XNARCH_HAVE_US_ATOMIC_CMPXCHG */
}
-int __wrap_pthread_mutex_unlock(pthread_mutex_t * mutex)
+int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex)
{
union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
+ struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
- return -XENOMAI_SKINCALL1(__pse51_muxid,
- __pse51_mutex_unlock, &_mutex->shadow_mutex);
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+ atomic_ptr_t *ownerp;
+ xnthread_t *cur;
+ int err = 0;
+
+ cur = pthread_getspecific(pse51_cur_key);
+ if (!cur)
+ return EPERM;
+
+ if (unlikely(cb_try_read_lock(&shadow->lock, s)))
+ return EINVAL;
+
+ if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC)) {
+ err = -EINVAL;
+ goto out_err;
+ }
+
+ ownerp = get_ownerp(shadow);
+ if (unlikely(clear_claimed(atomic_ptr_read(ownerp)) != cur)) {
+ err = -EPERM;
+ goto out_err;
+ }
+
+ err = 0;
+ if (shadow->lockcnt > 1) {
+ --shadow->lockcnt;
+ goto out;
+ }
+
+ if (likely(atomic_ptr_cmpxchg(ownerp, cur, NULL) == cur)) {
+ out:
+ cb_read_unlock(&shadow->lock, s);
+ return 0;
+ }
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
+
+ err = XENOMAI_SKINCALL1(__pse51_muxid, __pse51_mutex_unlock, shadow);
+
+#ifdef XNARCH_HAVE_US_ATOMIC_CMPXCHG
+ out_err:
+ cb_read_unlock(&shadow->lock, s);
+#endif /* XNARCH_HAVE_US_ATOMIC_CMPXCHG */
+
+ return -err;
}
Index: src/skins/posix/cond.c
===================================================================
--- src/skins/posix/cond.c (revision 3718)
+++ src/skins/posix/cond.c (working copy)
@@ -19,6 +19,7 @@
#include <errno.h>
#include <posix/syscall.h>
#include <pthread.h>
+#include <posix/cb_lock.h>
extern int __pse51_muxid;
@@ -95,7 +96,7 @@ static void __pthread_cond_cleanup(void
c->count);
}
-int __wrap_pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
+int __wrap_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
{
struct pse51_cond_cleanup_t c = {
.cond = (union __xeno_cond *)cond,
@@ -103,6 +104,9 @@ int __wrap_pthread_cond_wait(pthread_con
};
int err, oldtype;
+ if (cb_try_read_lock(&c.mutex->shadow_mutex.lock, s))
+ return EINVAL;
+
pthread_cleanup_push(&__pthread_cond_cleanup, &c);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
@@ -118,11 +122,15 @@ int __wrap_pthread_cond_wait(pthread_con
pthread_cleanup_pop(0);
- if (err)
+ if (err) {
+ cb_read_unlock(&c.mutex->shadow_mutex.lock, s);
return err;
+ }
__pthread_cond_cleanup(&c);
+ cb_read_unlock(&c.mutex->shadow_mutex.lock, s);
+
pthread_testcancel();
return 0;
@@ -138,6 +146,9 @@ int __wrap_pthread_cond_timedwait(pthrea
};
int err, oldtype;
+ if (cb_try_read_lock(&c.mutex->shadow_mutex.lock, s))
+ return EINVAL;
+
pthread_cleanup_push(&__pthread_cond_cleanup, &c);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
@@ -153,11 +164,15 @@ int __wrap_pthread_cond_timedwait(pthrea
pthread_cleanup_pop(0);
- if (err && err != ETIMEDOUT)
+ if (err && err != ETIMEDOUT) {
+ cb_read_unlock(&c.mutex->shadow_mutex.lock, s);
return err;
+ }
__pthread_cond_cleanup(&c);
+ cb_read_unlock(&c.mutex->shadow_mutex.lock, s);
+
pthread_testcancel();
return err;
Index: src/skins/posix/Makefile.am
===================================================================
--- src/skins/posix/Makefile.am (revision 3718)
+++ src/skins/posix/Makefile.am (working copy)
@@ -2,6 +2,8 @@ includedir = $(prefix)/include/posix
lib_LTLIBRARIES = libpthread_rt.la
+CPPFLAGS+=-I$(top_srcdir)/ksrc/skins
+
libpthread_rt_la_LDFLAGS = -version-info 1:0:0 -lpthread
libpthread_rt_la_SOURCES = \
--
Gilles.
next prev parent reply other threads:[~2008-04-24 6:33 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-04-24 6:16 [Xenomai-core] [0/9] Posix skin user-space mutexes Gilles Chanteperdrix
2008-04-24 6:20 ` [Xenomai-core] [1/9] Support for non cached memory mappings Gilles Chanteperdrix
2008-04-24 6:21 ` [Xenomai-core] [2/9] Define XNARCH_SHARED_HEAP_FLAGS Gilles Chanteperdrix
2008-04-24 6:22 ` [Xenomai-core] [3/9] Define more atomic operations in user-space Gilles Chanteperdrix
2008-04-24 6:24 ` [Xenomai-core] [4/9] Define ARM " Gilles Chanteperdrix
2008-04-24 6:25 ` [Xenomai-core] [5/9] Define new syscalls for the posix skin Gilles Chanteperdrix
2008-04-24 6:27 ` [Xenomai-core] [6/9] Rework posix skin shared heaps support, add per-process shared heap Gilles Chanteperdrix
2008-04-24 6:30 ` [Xenomai-core] [7/9] Poor man's object control block read-write lock Gilles Chanteperdrix
2008-04-24 6:32 ` [Xenomai-core] [8/9] Re-implementation of mutexes, kernel-space support Gilles Chanteperdrix
2008-04-24 6:33 ` Gilles Chanteperdrix [this message]
2008-04-25 8:03 ` [Xenomai-core] [6/9] Rework posix skin shared heaps support, add per-process shared heap Philippe Gerum
2008-04-25 7:59 ` [Xenomai-core] [5/9] Define new syscalls for the posix skin Philippe Gerum
2008-04-25 7:51 ` [Xenomai-core] [4/9] Define ARM atomic operations in user-space Philippe Gerum
2008-04-25 7:48 ` [Xenomai-core] [3/9] Define more " Philippe Gerum
2008-04-25 13:26 ` Gilles Chanteperdrix
2008-04-25 13:42 ` Philippe Gerum
2008-04-25 13:50 ` Gilles Chanteperdrix
2008-04-25 14:01 ` Philippe Gerum
2008-04-25 14:13 ` Gilles Chanteperdrix
2008-04-25 14:20 ` Philippe Gerum
2008-04-25 22:09 ` Gilles Chanteperdrix
2008-04-26 7:02 ` Philippe Gerum
2008-04-24 7:09 ` [Xenomai-core] [0/9] Posix skin user-space mutexes Jan Kiszka
2008-04-24 7:37 ` Gilles Chanteperdrix
2008-04-24 8:23 ` Gilles Chanteperdrix
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=18448.10662.83570.781983@domain.hid \
--to=gilles.chanteperdrix@xenomai.org \
--cc=xenomai@xenomai.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.