All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more
@ 2008-10-16 15:46 Jan Kiszka
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 01/12] Generic thread registration Jan Kiszka
                   ` (13 more replies)
  0 siblings, 14 replies; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 15:46 UTC (permalink / raw)
  To: xenomai

Here comes a significantly reworked patch series to improve fast mutex
support of Xenomai.

This approach now introduces a generic fast xnsynch core and converts
the existing POSIX implementation over. It also comes with a second
user, the Native skin. Additionally, it improves xeno_get_current via
a TLS variable and addresses the issue that threads in secondary mode
acquiring an uncontended mutex need to be migrated first.

At this chance, the TLS optimization is also applied on self-lookups of
task handles (Native, VRTX and VxWorks). And I included my
SMP-by-default patch for user libs which is highly recommended to reduce
the risk of accidental code breakage on SMP with the new mutex code.

Jan

---
 include/asm-generic/atomic.h               |   24 -
 xenomai/README.INSTALL                     |    2 
 xenomai/configure.in                       |   45 +-
 xenomai/include/asm-arm/atomic.h           |    3 
 xenomai/include/asm-blackfin/atomic.h      |    2 
 xenomai/include/asm-generic/Makefile.am    |    2 
 xenomai/include/asm-generic/Makefile.in    |    2 
 xenomai/include/asm-generic/bits/bind.h    |   82 +++-
 xenomai/include/asm-generic/bits/current.h |   36 +
 xenomai/include/asm-generic/features.h     |   24 -
 xenomai/include/asm-ia64/atomic.h          |    2 
 xenomai/include/asm-powerpc/atomic.h       |    2 
 xenomai/include/asm-x86/atomic.h           |    2 
 xenomai/include/native/mutex.h             |   23 -
 xenomai/include/native/syscall.h           |    1 
 xenomai/include/nucleus/registry.h         |    1 
 xenomai/include/nucleus/shadow.h           |    3 
 xenomai/include/nucleus/synch.h            |   70 +++
 xenomai/include/nucleus/thread.h           |   29 +
 xenomai/include/nucleus/types.h            |   13 
 xenomai/include/psos+/syscall.h            |    8 
 xenomai/include/rtdm/rtdm_driver.h         |    2 
 xenomai/include/vrtx/syscall.h             |    1 
 xenomai/include/vxworks/syscall.h          |    1 
 xenomai/ksrc/arch/arm/Kconfig              |    2 
 xenomai/ksrc/arch/powerpc/Kconfig          |    2 
 xenomai/ksrc/arch/x86/Kconfig              |    2 
 xenomai/ksrc/drivers/testing/switchtest.c  |    2 
 xenomai/ksrc/nucleus/pipe.c                |    2 
 xenomai/ksrc/nucleus/registry.c            |    4 
 xenomai/ksrc/nucleus/select.c              |    2 
 xenomai/ksrc/nucleus/shadow.c              |   38 +-
 xenomai/ksrc/nucleus/synch.c               |  534 ++++++++++++++++++++---------
 xenomai/ksrc/nucleus/thread.c              |    2 
 xenomai/ksrc/skins/native/Kconfig          |    1 
 xenomai/ksrc/skins/native/alarm.c          |    2 
 xenomai/ksrc/skins/native/buffer.c         |    4 
 xenomai/ksrc/skins/native/cond.c           |   18 
 xenomai/ksrc/skins/native/event.c          |    2 
 xenomai/ksrc/skins/native/heap.c           |    2 
 xenomai/ksrc/skins/native/intr.c           |    2 
 xenomai/ksrc/skins/native/mutex.c          |  327 ++++++++++-------
 xenomai/ksrc/skins/native/queue.c          |    2 
 xenomai/ksrc/skins/native/sem.c            |    2 
 xenomai/ksrc/skins/native/syscall.c        |  132 +++++--
 xenomai/ksrc/skins/native/task.c           |   28 -
 xenomai/ksrc/skins/posix/Kconfig           |    1 
 xenomai/ksrc/skins/posix/cb_lock.h         |   21 -
 xenomai/ksrc/skins/posix/cond.c            |   34 -
 xenomai/ksrc/skins/posix/intr.c            |    2 
 xenomai/ksrc/skins/posix/mq.c              |    4 
 xenomai/ksrc/skins/posix/mutex.c           |  121 ++++--
 xenomai/ksrc/skins/posix/mutex.h           |  136 +------
 xenomai/ksrc/skins/posix/sem.c             |    2 
 xenomai/ksrc/skins/posix/syscall.c         |   61 +--
 xenomai/ksrc/skins/posix/thread.c          |   14 
 xenomai/ksrc/skins/psos+/Kconfig           |    2 
 xenomai/ksrc/skins/psos+/event.c           |    2 
 xenomai/ksrc/skins/psos+/queue.c           |    2 
 xenomai/ksrc/skins/psos+/rn.c              |    2 
 xenomai/ksrc/skins/psos+/sem.c             |    2 
 xenomai/ksrc/skins/psos+/syscall.c         |   53 +-
 xenomai/ksrc/skins/psos+/task.c            |   20 -
 xenomai/ksrc/skins/rtai/Kconfig            |    1 
 xenomai/ksrc/skins/rtai/sem.c              |   12 
 xenomai/ksrc/skins/rtai/task.c             |   10 
 xenomai/ksrc/skins/rtdm/drvlib.c           |   27 -
 xenomai/ksrc/skins/uitron/Kconfig          |    1 
 xenomai/ksrc/skins/uitron/flag.c           |    2 
 xenomai/ksrc/skins/uitron/mbx.c            |    3 
 xenomai/ksrc/skins/uitron/sem.c            |    3 
 xenomai/ksrc/skins/uitron/syscall.c        |    8 
 xenomai/ksrc/skins/uitron/task.c           |   11 
 xenomai/ksrc/skins/vrtx/Kconfig            |    2 
 xenomai/ksrc/skins/vrtx/event.c            |    2 
 xenomai/ksrc/skins/vrtx/mb.c               |    2 
 xenomai/ksrc/skins/vrtx/mx.c               |    7 
 xenomai/ksrc/skins/vrtx/queue.c            |    2 
 xenomai/ksrc/skins/vrtx/sem.c              |    2 
 xenomai/ksrc/skins/vrtx/syscall.c          |    4 
 xenomai/ksrc/skins/vrtx/task.c             |   17 
 xenomai/ksrc/skins/vxworks/Kconfig         |    2 
 xenomai/ksrc/skins/vxworks/module.c        |    2 
 xenomai/ksrc/skins/vxworks/msgQLib.c       |    2 
 xenomai/ksrc/skins/vxworks/semLib.c        |    8 
 xenomai/ksrc/skins/vxworks/syscall.c       |   37 +-
 xenomai/ksrc/skins/vxworks/taskLib.c       |   12 
 xenomai/src/skins/native/cond.c            |   30 +
 xenomai/src/skins/native/init.c            |    8 
 xenomai/src/skins/native/mutex.c           |  105 +++++
 xenomai/src/skins/native/task.c            |   44 ++
 xenomai/src/skins/posix/mutex.c            |  192 +++++-----
 xenomai/src/skins/posix/thread.c           |   33 +
 xenomai/src/skins/psos+/task.c             |   34 +
 xenomai/src/skins/uitron/task.c            |   29 +
 xenomai/src/skins/vrtx/init.c              |   19 -
 xenomai/src/skins/vrtx/task.c              |   37 +-
 xenomai/src/skins/vxworks/init.c           |    8 
 xenomai/src/skins/vxworks/taskLib.c        |   29 +
 99 files changed, 1809 insertions(+), 909 deletions(-)

--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux



^ permalink raw reply	[flat|nested] 50+ messages in thread

* [Xenomai-core] [PATCH 01/12] Generic thread registration
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
@ 2008-10-16 15:46 ` Jan Kiszka
  2008-10-16 19:26   ` Gilles Chanteperdrix
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 02/12] Handle-based xeno_get_current service Jan Kiszka
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 15:46 UTC (permalink / raw)
  To: xenomai; +Cc: Jan Kiszka

[-- Attachment #1: generic-thread-registration.patch --]
[-- Type: text/plain, Size: 18484 bytes --]

Lay groundwork for registering every thread at least anonymously with
the Xenomai registry when required (e.g. handle-based fast xnsynch
support). Wrap the operations appropriately, also saving a few #ifdefs.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/nucleus/registry.h   |    1 
 include/nucleus/thread.h     |   25 +++++++++++++++++
 ksrc/nucleus/thread.c        |    2 +
 ksrc/skins/native/syscall.c  |   61 ++++++++++++++++++++++++++-----------------
 ksrc/skins/native/task.c     |   13 ---------
 ksrc/skins/psos+/syscall.c   |   19 ++++++++-----
 ksrc/skins/psos+/task.c      |   20 +++-----------
 ksrc/skins/vxworks/syscall.c |   31 ++++++++++++---------
 ksrc/skins/vxworks/taskLib.c |   10 -------
 9 files changed, 102 insertions(+), 80 deletions(-)

Index: b/ksrc/skins/native/syscall.c
===================================================================
--- a/ksrc/skins/native/syscall.c
+++ b/ksrc/skins/native/syscall.c
@@ -52,7 +52,8 @@ int __native_muxid;
 static int __rt_bind_helper(struct task_struct *p,
 			    struct pt_regs *regs,
 			    xnhandle_t *handlep,
-			    unsigned magic, void **objaddrp)
+			    unsigned magic, void **objaddrp,
+			    unsigned long objoffs)
 {
 	char name[XNOBJECT_NAME_LEN];
 	RTIME timeout;
@@ -82,7 +83,7 @@ static int __rt_bind_helper(struct task_
 
 	/* Also validate the type of the bound object. */
 
-	if (xeno_test_magic(objaddr, magic)) {
+	if (xeno_test_magic(objaddr + objoffs, magic)) {
 		if (objaddrp)
 			*objaddrp = objaddr;
 	} else
@@ -93,6 +94,11 @@ static int __rt_bind_helper(struct task_
 	return err;
 }
 
+static RT_TASK *__rt_task_lookup(xnhandle_t threadh)
+{
+	return thread2rtask(xnthread_lookup(threadh));
+}
+
 static RT_TASK *__rt_task_current(struct task_struct *p)
 {
 	xnthread_t *thread = xnshadow_thread(p);
@@ -223,7 +229,9 @@ static int __rt_task_bind(struct pt_regs
 	RT_TASK_PLACEHOLDER ph;
 	int err;
 
-	err = __rt_bind_helper(p, regs, &ph.opaque, XENO_TASK_MAGIC, NULL);
+	err =
+	    __rt_bind_helper(p, regs, &ph.opaque, XENO_TASK_MAGIC, NULL,
+			     -offsetof(RT_TASK, thread_base));
 
 	if (err)
 		return err;
@@ -253,7 +261,7 @@ static int __rt_task_start(struct pt_reg
 				     sizeof(ph)))
 		return -EFAULT;
 
-	task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+	task = __rt_task_lookup(ph.opaque);
 
 	if (!task)
 		return -ESRCH;
@@ -279,7 +287,7 @@ static int __rt_task_suspend(struct pt_r
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = __rt_task_lookup(ph.opaque);
 	} else
 		task = __rt_task_current(p);
 
@@ -302,7 +310,7 @@ static int __rt_task_resume(struct pt_re
 				     sizeof(ph)))
 		return -EFAULT;
 
-	task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+	task = __rt_task_lookup(ph.opaque);
 
 	if (!task)
 		return -ESRCH;
@@ -326,7 +334,7 @@ static int __rt_task_delete(struct pt_re
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = __rt_task_lookup(ph.opaque);
 	} else
 		task = __rt_task_current(p);
 
@@ -364,7 +372,7 @@ static int __rt_task_set_periodic(struct
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = __rt_task_lookup(ph.opaque);
 	} else
 		task = __rt_task_current(p);
 
@@ -418,7 +426,7 @@ static int __rt_task_set_priority(struct
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = __rt_task_lookup(ph.opaque);
 	} else
 		task = __rt_task_current(p);
 
@@ -473,7 +481,7 @@ static int __rt_task_unblock(struct pt_r
 				     sizeof(ph)))
 		return -EFAULT;
 
-	task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+	task = __rt_task_lookup(ph.opaque);
 
 	if (!task)
 		return -ESRCH;
@@ -500,7 +508,7 @@ static int __rt_task_inquire(struct pt_r
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = __rt_task_lookup(ph.opaque);
 	} else
 		task = __rt_task_current(p);
 
@@ -541,7 +549,7 @@ static int __rt_task_notify(struct pt_re
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = __rt_task_lookup(ph.opaque);
 	} else
 		task = __rt_task_current(p);
 
@@ -627,7 +635,7 @@ static int __rt_task_slice(struct pt_reg
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = __rt_task_lookup(ph.opaque);
 	} else
 		task = __rt_task_current(current);
 
@@ -667,7 +675,7 @@ static int __rt_task_send(struct pt_regs
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = __rt_task_lookup(ph.opaque);
 	} else
 		task = __rt_task_current(current);
 
@@ -1104,7 +1112,9 @@ static int __rt_sem_bind(struct pt_regs
 	RT_SEM_PLACEHOLDER ph;
 	int err;
 
-	err = __rt_bind_helper(current, regs, &ph.opaque, XENO_SEM_MAGIC, NULL);
+	err =
+	    __rt_bind_helper(current, regs, &ph.opaque, XENO_SEM_MAGIC,
+			     NULL, 0);
 
 	if (err)
 		return err;
@@ -1324,7 +1334,8 @@ static int __rt_event_bind(struct pt_reg
 	int err;
 
 	err =
-	    __rt_bind_helper(current, regs, &ph.opaque, XENO_EVENT_MAGIC, NULL);
+	    __rt_bind_helper(current, regs, &ph.opaque, XENO_EVENT_MAGIC,
+			     NULL, 0);
 
 	if (err)
 		return err;
@@ -1567,7 +1578,8 @@ static int __rt_mutex_bind(struct pt_reg
 	int err;
 
 	err =
-	    __rt_bind_helper(current, regs, &ph.opaque, XENO_MUTEX_MAGIC, NULL);
+	    __rt_bind_helper(current, regs, &ph.opaque, XENO_MUTEX_MAGIC,
+			     NULL, 0);
 
 	if (err)
 		return err;
@@ -1758,7 +1770,8 @@ static int __rt_cond_bind(struct pt_regs
 	int err;
 
 	err =
-	    __rt_bind_helper(current, regs, &ph.opaque, XENO_COND_MAGIC, NULL);
+	    __rt_bind_helper(current, regs, &ph.opaque, XENO_COND_MAGIC,
+			     NULL, 0);
 
 	if (err)
 		return err;
@@ -2008,7 +2021,7 @@ static int __rt_queue_bind(struct pt_reg
 
 	err =
 	    __rt_bind_helper(p, regs, &ph.opaque, XENO_QUEUE_MAGIC,
-			     (void **)&q);
+			     (void **)&q, 0);
 
 	if (err)
 		goto unlock_and_exit;
@@ -2507,7 +2520,7 @@ static int __rt_heap_bind(struct pt_regs
 
 	err =
 	    __rt_bind_helper(p, regs, &ph.opaque, XENO_HEAP_MAGIC,
-			     (void **)&heap);
+			     (void **)&heap, 0);
 
 	if (err)
 		goto unlock_and_exit;
@@ -3018,7 +3031,7 @@ static int __rt_intr_bind(struct pt_regs
 	RT_INTR_PLACEHOLDER ph;
 	int err;
 
-	err = __rt_bind_helper(p, regs, &ph.opaque, XENO_INTR_MAGIC, NULL);
+	err = __rt_bind_helper(p, regs, &ph.opaque, XENO_INTR_MAGIC, NULL, 0);
 
 	if (err)
 		return err;
@@ -3275,7 +3288,7 @@ static int __rt_pipe_bind(struct pt_regs
 	RT_PIPE_PLACEHOLDER ph;
 	int err;
 
-	err = __rt_bind_helper(p, regs, &ph.opaque, XENO_PIPE_MAGIC, NULL);
+	err = __rt_bind_helper(p, regs, &ph.opaque, XENO_PIPE_MAGIC, NULL, 0);
 
 	if (err)
 		return err;
@@ -3551,7 +3564,9 @@ static int __rt_buffer_bind(struct pt_re
 	RT_BUFFER_PLACEHOLDER ph;
 	int ret;
 
-	ret = __rt_bind_helper(current, regs, &ph.opaque, XENO_BUFFER_MAGIC, NULL);
+	ret =
+	    __rt_bind_helper(current, regs, &ph.opaque, XENO_BUFFER_MAGIC,
+			     NULL, 0);
 	if (ret)
 		return ret;
 
Index: b/ksrc/skins/native/task.c
===================================================================
--- a/ksrc/skins/native/task.c
+++ b/ksrc/skins/native/task.c
@@ -46,7 +46,6 @@
 
 #include <nucleus/pod.h>
 #include <nucleus/heap.h>
-#include <nucleus/registry.h>
 #include <native/task.h>
 #include <native/timer.h>
 
@@ -80,11 +79,6 @@ static void __task_delete_hook(xnthread_
 	xnsynch_destroy(&task->msendq);
 #endif /* CONFIG_XENO_OPT_NATIVE_MPS */
 
-#ifdef CONFIG_XENO_OPT_REGISTRY
-	if (xnthread_handle(&task->thread_base) != XN_NO_HANDLE)
-		xnregistry_remove(xnthread_handle(&task->thread_base));
-#endif /* CONFIG_XENO_OPT_REGISTRY */
-
 	xnsynch_destroy(&task->safesynch);
 
 	removeq(&__xeno_task_q, &task->link);
@@ -285,20 +279,15 @@ int rt_task_create(RT_TASK *task,
 	appendq(&__xeno_task_q, &task->link);
 	xnlock_put_irqrestore(&nklock, s);
 
-#ifdef CONFIG_XENO_OPT_REGISTRY
 	/* <!> Since xnregister_enter() may reschedule, only register
 	   complete objects, so that the registry cannot return handles to
 	   half-baked objects... */
 
 	if (name) {
-		err = xnregistry_enter(task->rname,
-				       task,
-				       &xnthread_handle(&task->thread_base),
-				       NULL);
+		err = xnthread_register(&task->thread_base, task->rname);
 		if (err)
 			xnpod_delete_thread(&task->thread_base);
 	}
-#endif /* CONFIG_XENO_OPT_REGISTRY */
 
 	return err;
 }
Index: b/ksrc/skins/psos+/syscall.c
===================================================================
--- a/ksrc/skins/psos+/syscall.c
+++ b/ksrc/skins/psos+/syscall.c
@@ -44,6 +44,11 @@
 
 int __psos_muxid;
 
+static inline psostask_t *__psos_task_lookup(xnhandle_t taskh)
+{
+	return thread2psostask(xnthread_lookup(taskh));
+}
+
 static psostask_t *__psos_task_current(struct task_struct *p)
 {
 	xnthread_t *thread = xnshadow_thread(p);
@@ -131,7 +136,7 @@ static int __t_start(struct pt_regs *reg
 	psostask_t *task;
 
 	handle = __xn_reg_arg1(regs);
-	task = (psostask_t *)xnregistry_fetch(handle);
+	task = __psos_task_lookup(handle);
 
 	if (!task)
 		return ERR_OBJID;
@@ -162,7 +167,7 @@ static int __t_delete(struct pt_regs *re
 	handle = __xn_reg_arg1(regs);
 
 	if (handle)
-		task = (psostask_t *)xnregistry_fetch(handle);
+		task = __psos_task_lookup(handle);
 	else
 		task = __psos_task_current(current);
 
@@ -182,7 +187,7 @@ static int __t_suspend(struct pt_regs *r
 	psostask_t *task;
 
 	if (handle)
-		task = (psostask_t *)xnregistry_fetch(handle);
+		task = __psos_task_lookup(handle);
 	else
 		task = __psos_task_current(current);
 
@@ -202,7 +207,7 @@ static int __t_resume(struct pt_regs *re
 	psostask_t *task;
 
 	if (handle)
-		task = (psostask_t *)xnregistry_fetch(handle);
+		task = __psos_task_lookup(handle);
 	else
 		task = __psos_task_current(current);
 
@@ -284,7 +289,7 @@ static int __t_setpri(struct pt_regs *re
 	psostask_t *task;
 
 	if (handle)
-		task = (psostask_t *)xnregistry_fetch(handle);
+		task = __psos_task_lookup(handle);
 	else
 		task = __psos_task_current(current);
 
@@ -314,7 +319,7 @@ static int __ev_send(struct pt_regs *reg
 	u_long events;
 
 	if (handle)
-		task = (psostask_t *)xnregistry_fetch(handle);
+		task = __psos_task_lookup(handle);
 	else
 		task = __psos_task_current(current);
 
@@ -1317,7 +1322,7 @@ static int __as_send(struct pt_regs *reg
 	psostask_t *task;
 
 	if (handle)
-		task = (psostask_t *)xnregistry_fetch(handle);
+		task = __psos_task_lookup(handle);
 	else
 		task = __psos_task_current(current);
 
Index: b/ksrc/skins/psos+/task.c
===================================================================
--- a/ksrc/skins/psos+/task.c
+++ b/ksrc/skins/psos+/task.c
@@ -17,7 +17,6 @@
  * 02111-1307, USA.
  */
 
-#include <nucleus/registry.h>
 #include <psos+/task.h>
 #include <psos+/tm.h>
 
@@ -45,11 +44,6 @@ static void psostask_delete_hook(xnthrea
 	if (xnthread_get_magic(thread) != PSOS_SKIN_MAGIC)
 		return;
 
-#ifdef CONFIG_XENO_OPT_REGISTRY
-	if (xnthread_handle(thread) != XN_NO_HANDLE)
-		xnregistry_remove(xnthread_handle(thread));
-#endif /* CONFIG_XENO_OPT_REGISTRY */
-
 	task = thread2psostask(thread);
 
 	removeq(&psostaskq, &task->link);
@@ -95,6 +89,7 @@ u_long t_create(const char *name,
 {
 	xnflags_t bflags = 0;
 	psostask_t *task;
+	u_long err;
 	spl_t s;
 	int n;
 
@@ -159,16 +154,11 @@ u_long t_create(const char *name,
 	*tid_r = (u_long)task;
 	xnlock_put_irqrestore(&nklock, s);
 
-#ifdef CONFIG_XENO_OPT_REGISTRY
-	{
-		u_long err = xnregistry_enter(task->name,
-					      task, &xnthread_handle(&task->threadbase), NULL);
-		if (err) {
-			t_delete((u_long)task);
-			return err;
-		}
+	err = xnthread_register(&task->threadbase, task->name);
+	if (err) {
+		t_delete((u_long)task);
+		return err;
 	}
-#endif /* CONFIG_XENO_OPT_REGISTRY */
 
 	xnarch_create_display(&task->threadbase, task->name, psostask);
 
Index: b/ksrc/skins/vxworks/syscall.c
===================================================================
--- a/ksrc/skins/vxworks/syscall.c
+++ b/ksrc/skins/vxworks/syscall.c
@@ -42,6 +42,11 @@
 
 int __wind_muxid;
 
+static inline WIND_TCB *__wind_lookup_task(xnhandle_t threadh)
+{
+	return thread2wind_task(xnthread_lookup(threadh));
+}
+
 static WIND_TCB *__wind_task_current(struct task_struct *p)
 {
 	xnthread_t *thread = xnshadow_thread(p);
@@ -146,7 +151,7 @@ out:
 
 static int __wind_task_activate(struct pt_regs *regs)
 {
-	WIND_TCB *pTcb = (WIND_TCB *)xnregistry_fetch(__xn_reg_arg1(regs));
+	WIND_TCB *pTcb = __wind_lookup_task(__xn_reg_arg1(regs));
 
 	if (!pTcb)
 		return S_objLib_OBJ_ID_ERROR;
@@ -167,7 +172,7 @@ static int __wind_task_deleteforce(struc
 	WIND_TCB *pTcb;
 
 	if (handle)
-		pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+		pTcb = __wind_lookup_task(handle);
 	else
 		pTcb = __wind_task_current(current);
 
@@ -190,7 +195,7 @@ static int __wind_task_delete(struct pt_
 	WIND_TCB *pTcb;
 
 	if (handle)
-		pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+		pTcb = __wind_lookup_task(handle);
 	else
 		pTcb = __wind_task_current(current);
 
@@ -213,7 +218,7 @@ static int __wind_task_suspend(struct pt
 	WIND_TCB *pTcb;
 
 	if (handle)
-		pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+		pTcb = __wind_lookup_task(handle);
 	else
 		pTcb = __wind_task_current(current);
 
@@ -232,7 +237,7 @@ static int __wind_task_suspend(struct pt
 
 static int __wind_task_resume(struct pt_regs *regs)
 {
-	WIND_TCB *pTcb = (WIND_TCB *)xnregistry_fetch(__xn_reg_arg1(regs));
+	WIND_TCB *pTcb = __wind_lookup_task(__xn_reg_arg1(regs));
 
 	if (!pTcb)
 		return S_objLib_OBJ_ID_ERROR;
@@ -275,7 +280,7 @@ static int __wind_task_priorityset(struc
 	WIND_TCB *pTcb;
 
 	if (handle)
-		pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+		pTcb = __wind_lookup_task(handle);
 	else
 		pTcb = __wind_task_current(current);
 
@@ -299,7 +304,7 @@ static int __wind_task_priorityget(struc
 	int prio;
 
 	if (handle)
-		pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+		pTcb = __wind_lookup_task(handle);
 	else
 		pTcb = __wind_task_current(current);
 
@@ -374,7 +379,7 @@ static int __wind_task_verifyid(struct p
 	xnhandle_t handle = __xn_reg_arg1(regs);
 	WIND_TCB *pTcb;
 
-	pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+	pTcb = __wind_lookup_task(handle);
 
 	if (!pTcb)
 		return S_objLib_OBJ_ID_ERROR;
@@ -574,7 +579,7 @@ static int __wind_taskinfo_name(struct p
 	const char *name;
 	WIND_TCB *pTcb;
 
-	pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+	pTcb = __wind_lookup_task(handle);
 
 	if (!pTcb)
 		return S_objLib_OBJ_ID_ERROR;
@@ -618,7 +623,7 @@ static int __wind_taskinfo_status(struct
 
 	xnlock_get_irqsave(&nklock, s);
 
-	pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+	pTcb = __wind_lookup_task(handle);
 
 	if (!pTcb || pTcb->magic != WIND_TASK_MAGIC) {
 		xnlock_put_irqrestore(&nklock, s);
@@ -643,7 +648,7 @@ static int __wind_taskinfo_get(struct pt
 	WIND_TCB *pTcb;
 	int err;
 
-	pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+	pTcb = __wind_lookup_task(handle);
 	if (!pTcb)
 		return S_objLib_OBJ_ID_ERROR;
 
@@ -673,7 +678,7 @@ static int __wind_errno_taskset(struct p
  		return 0;
  	}
  
- 	pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ 	pTcb = __wind_lookup_task(handle);
 	if (!pTcb)
 		return S_objLib_OBJ_ID_ERROR;
 
@@ -696,7 +701,7 @@ static int __wind_errno_taskget(struct p
  	if (!handle)
  		errcode = wind_errnoget();
  	else {
- 		pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ 		pTcb = __wind_lookup_task(handle);
  		if (!pTcb)
  			return S_objLib_OBJ_ID_ERROR;
  
Index: b/ksrc/skins/vxworks/taskLib.c
===================================================================
--- a/ksrc/skins/vxworks/taskLib.c
+++ b/ksrc/skins/vxworks/taskLib.c
@@ -170,14 +170,11 @@ STATUS taskInit(WIND_TCB *pTcb,
 	appendq(&wind_tasks_q, &pTcb->link);
 	xnlock_put_irqrestore(&nklock, s);
 
-#ifdef CONFIG_XENO_OPT_REGISTRY
-	if (xnregistry_enter(pTcb->name,
-			     pTcb, &xnthread_handle(&pTcb->threadbase), NULL)) {
+	if (xnthread_register(&pTcb->threadbase, pTcb->name)) {
 		wind_errnoset(S_objLib_OBJ_ID_ERROR);
 		taskDeleteForce((TASK_ID) pTcb);
 		return ERROR;
 	}
-#endif /* CONFIG_XENO_OPT_REGISTRY */
 
 	return OK;
 }
@@ -618,11 +615,6 @@ static void wind_task_delete_hook(xnthre
 	if (xnthread_get_magic(thread) != VXWORKS_SKIN_MAGIC)
 		return;
 
-#ifdef CONFIG_XENO_OPT_REGISTRY
-	if (xnthread_handle(thread) != XN_NO_HANDLE)
-	    xnregistry_remove(xnthread_handle(thread));
-#endif /* CONFIG_XENO_OPT_REGISTRY */
-
 	task = thread2wind_task(thread);
 
 	xnsynch_destroy(&task->safesync);
Index: b/include/nucleus/registry.h
===================================================================
--- a/include/nucleus/registry.h
+++ b/include/nucleus/registry.h
@@ -35,7 +35,6 @@
 #if defined(__KERNEL__) || defined(__XENO_SIM__)
 
 #include <nucleus/synch.h>
-#include <nucleus/thread.h>
 
 struct xnpnode;
 
Index: b/include/nucleus/thread.h
===================================================================
--- a/include/nucleus/thread.h
+++ b/include/nucleus/thread.h
@@ -130,6 +130,7 @@
 
 #include <nucleus/stat.h>
 #include <nucleus/timer.h>
+#include <nucleus/registry.h>
 
 #ifdef __XENO_SIM__
 /* Pseudo-status (must not conflict with other bits) */
@@ -392,6 +393,30 @@ static inline xnticks_t xnthread_get_per
 	return period;
 }
 
+#ifdef CONFIG_XENO_OPT_REGISTRY
+static inline int xnthread_register(xnthread_t *thread, const char *name)
+{
+	return xnregistry_enter(name, thread, &xnthread_handle(thread), NULL);
+}
+
+static inline xnthread_t *xnthread_lookup(xnhandle_t threadh)
+{
+	xnthread_t *thread = xnregistry_fetch(threadh);
+
+	return (thread && xnthread_handle(thread) == threadh) ? thread : NULL;
+}
+#else /* !CONFIG_XENO_OPT_REGISTRY */
+static inline int xnthread_register(xnthread_t *thread, const char *name)
+{
+	return 0;
+}
+
+static inline xnthread_t *xnthread_lookup(xnhandle_t threadh)
+{
+	return NULL;
+}
+#endif /* !CONFIG_XENO_OPT_REGISTRY */
+
 #ifdef __cplusplus
 }
 #endif
Index: b/ksrc/nucleus/thread.c
===================================================================
--- a/ksrc/nucleus/thread.c
+++ b/ksrc/nucleus/thread.c
@@ -136,6 +136,8 @@ void xnthread_cleanup_tcb(xnthread_t *th
 #endif
 
 #ifdef CONFIG_XENO_OPT_REGISTRY
+	if (thread->registry.handle != XN_NO_HANDLE)
+		xnregistry_remove(thread->registry.handle);
 	thread->registry.handle = XN_NO_HANDLE;
 #endif /* CONFIG_XENO_OPT_REGISTRY */
 }



^ permalink raw reply	[flat|nested] 50+ messages in thread

* [Xenomai-core] [PATCH 02/12] Handle-based xeno_get_current service
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 01/12] Generic thread registration Jan Kiszka
@ 2008-10-16 15:46 ` Jan Kiszka
  2008-10-16 19:36   ` Gilles Chanteperdrix
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 03/12] Remove xnarch_atomic_intptr Jan Kiszka
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 15:46 UTC (permalink / raw)
  To: xenomai; +Cc: Jan Kiszka

[-- Attachment #1: handle-based-xeno_get_current.patch --]
[-- Type: text/plain, Size: 26845 bytes --]

To avoid sharing kernel object pointers with user space, a handle-based
approach is installed by this patch. It also reserves a few bits of the
handle value for special use (like the claimed bit of fast xnsynch).
Furthermore, the patch ensures that threads are registered at least
anonymously to allow them being used with fast xnsynch objects.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/asm-generic/bits/bind.h    |    9 ++++-
 include/asm-generic/bits/current.h |    5 +--
 include/nucleus/types.h            |   13 +++++++
 ksrc/nucleus/shadow.c              |   16 +++++++--
 ksrc/skins/native/Kconfig          |    1 
 ksrc/skins/native/task.c           |    8 +---
 ksrc/skins/posix/Kconfig           |    1 
 ksrc/skins/posix/cb_lock.h         |   15 ++++++---
 ksrc/skins/posix/cond.c            |   12 ++++---
 ksrc/skins/posix/mutex.c           |   21 +++++++-----
 ksrc/skins/posix/mutex.h           |   61 +++++++++++++++++++++++--------------
 ksrc/skins/posix/syscall.c         |   11 +++---
 ksrc/skins/posix/thread.c          |   12 +++++++
 ksrc/skins/psos+/Kconfig           |    2 -
 ksrc/skins/rtai/Kconfig            |    1 
 ksrc/skins/rtai/task.c             |   10 ++++++
 ksrc/skins/rtdm/drvlib.c           |    8 ++++
 ksrc/skins/uitron/Kconfig          |    1 
 ksrc/skins/uitron/task.c           |   11 ++++++
 ksrc/skins/vrtx/Kconfig            |    2 -
 ksrc/skins/vrtx/task.c             |   17 +++++++++-
 ksrc/skins/vxworks/Kconfig         |    2 -
 src/skins/posix/mutex.c            |   41 ++++++++++++------------
 23 files changed, 199 insertions(+), 81 deletions(-)

Index: b/include/asm-generic/bits/current.h
===================================================================
--- a/include/asm-generic/bits/current.h
+++ b/include/asm-generic/bits/current.h
@@ -2,14 +2,15 @@
 #define _XENO_ASM_GENERIC_CURRENT_H
 
 #include <pthread.h>
+#include <nucleus/types.h>
 
 extern pthread_key_t xeno_current_key;
 
 extern void xeno_set_current(void);
 
-static inline void *xeno_get_current(void)
+static inline xnhandle_t xeno_get_current(void)
 {
-	return pthread_getspecific(xeno_current_key);
+	return (xnhandle_t)pthread_getspecific(xeno_current_key);
 }
 
 #endif /* _XENO_ASM_GENERIC_CURRENT_H */
Index: b/include/nucleus/types.h
===================================================================
--- a/include/nucleus/types.h
+++ b/include/nucleus/types.h
@@ -61,6 +61,19 @@ typedef unsigned long xnhandle_t;
 
 #define XN_NO_HANDLE ((xnhandle_t)0)
 
+#define XN_HANDLE_SPARE0	((xnhandle_t)0x10000000)
+#define XN_HANDLE_SPARE1	((xnhandle_t)0x20000000)
+#define XN_HANDLE_SPARE2	((xnhandle_t)0x40000000)
+#define XN_HANDLE_SPARE3	((xnhandle_t)0x80000000)
+#define XN_HANDLE_SPARE_MASK	((xnhandle_t)0xf0000000)
+
+#define xnhandle_mask_spare(handle)  ((handle) & ~XN_HANDLE_SPARE_MASK)
+#define xnhandle_test_spare(handle, bits)  (!!((handle) & (bits)))
+#define xnhandle_set_spare(handle, bits) \
+	do { (handle) |= (bits); } while (0)
+#define xnhandle_clear_spare(handle, bits) \
+	do { (handle) &= ~(bits); } while (0)
+
 struct xnintr;
 
 typedef int (*xnisr_t)(struct xnintr *intr);
Index: b/ksrc/nucleus/shadow.c
===================================================================
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -1908,13 +1908,21 @@ static int xnshadow_sys_sem_heap(struct
 	return __xn_safe_copy_to_user(us_hinfo, &hinfo, sizeof(*us_hinfo));
 }
 
+#ifdef CONFIG_XENO_OPT_REGISTRY
 static int xnshadow_sys_current(struct pt_regs *regs)
 {
-	xnthread_t * __user *us_current, *cur = xnshadow_thread(current);
-	us_current = (xnthread_t *__user *) __xn_reg_arg1(regs);
+	xnthread_t *cur = xnshadow_thread(current);
+	xnhandle_t __user *us_handle;
 
-	return __xn_safe_copy_to_user(us_current, &cur, sizeof(*us_current));
+	if (!cur)
+		return -EPERM;
+
+	us_handle = (xnhandle_t __user *) __xn_reg_arg1(regs);
+
+	return __xn_safe_copy_to_user(us_handle, &xnthread_handle(cur),
+				      sizeof(*us_handle));
 }
+#endif /* CONFIG_XENO_OPT_REGISTRY */
 
 static xnsysent_t __systab[] = {
 	[__xn_sys_migrate] = {&xnshadow_sys_migrate, __xn_exec_current},
@@ -1925,7 +1933,9 @@ static xnsysent_t __systab[] = {
 	[__xn_sys_barrier] = {&xnshadow_sys_barrier, __xn_exec_lostage},
 	[__xn_sys_trace] = {&xnshadow_sys_trace, __xn_exec_any},
 	[__xn_sys_sem_heap] = {&xnshadow_sys_sem_heap, __xn_exec_any},
+#ifdef CONFIG_XENO_OPT_REGISTRY
 	[__xn_sys_current] = {&xnshadow_sys_current, __xn_exec_any},
+#endif /* CONFIG_XENO_OPT_REGISTRY */
 };
 
 static void *xnshadow_sys_event(int event, void *data)
Index: b/ksrc/skins/posix/cb_lock.h
===================================================================
--- a/ksrc/skins/posix/cb_lock.h
+++ b/ksrc/skins/posix/cb_lock.h
@@ -3,15 +3,22 @@
 
 #include <asm/xenomai/atomic.h>
 #include <nucleus/compiler.h>
+#include <nucleus/types.h>
 
 #ifndef __KERNEL__
 typedef void xnthread_t;
 #endif /* __KERNEL__ */
 
-#define test_claimed(owner) ((long) (owner) & 1)
-#define clear_claimed(owner) ((xnthread_t *) ((long) (owner) & ~1))
-#define set_claimed(owner, bit) \
-        ((xnthread_t *) ((long) clear_claimed(owner) | !!(bit)))
+#define __CLAIMED_BIT		XN_HANDLE_SPARE3
+
+#define test_claimed(owner)	xnhandle_test_spare(owner, __CLAIMED_BIT)
+#define clear_claimed(owner)	xnhandle_mask_spare(owner)
+#define set_claimed(owner, bit) ({ \
+	xnhandle_t __tmp = xnhandle_mask_spare(owner); \
+	if (bit) \
+		xnhandle_set_spare(__tmp, __CLAIMED_BIT); \
+	__tmp; \
+})
 
 #ifdef CONFIG_XENO_FASTSEM
 
Index: b/ksrc/skins/posix/cond.c
===================================================================
--- a/ksrc/skins/posix/cond.c
+++ b/ksrc/skins/posix/cond.c
@@ -230,18 +230,20 @@ static inline int mutex_save_count(xnthr
 
 	mutex = shadow->mutex;
 
-	if (clear_claimed(xnarch_atomic_intptr_get(mutex->owner)) != cur)
+	if (clear_claimed(xnarch_atomic_get(mutex->owner)) !=
+	    xnthread_handle(cur))
 		return EPERM;
 
 	*count_ptr = shadow->lockcnt;
 
-	if (likely(xnarch_atomic_intptr_cmpxchg(mutex->owner, cur, NULL) == cur))
+	if (likely(xnarch_atomic_cmpxchg(mutex->owner, cur, XN_NO_HANDLE) ==
+		   xnthread_handle(cur)))
 		return 0;
 
 	owner = xnsynch_wakeup_one_sleeper(&mutex->synchbase);
-	xnarch_atomic_intptr_set
-		(mutex->owner,
-		 set_claimed(owner,xnsynch_nsleepers(&mutex->synchbase)));
+	xnarch_atomic_set(mutex->owner,
+			  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));
 
 	/* Do not reschedule here, releasing the mutex and suspension must be
 	   done atomically in pthread_cond_*wait. */
Index: b/ksrc/skins/posix/mutex.c
===================================================================
--- a/ksrc/skins/posix/mutex.c
+++ b/ksrc/skins/posix/mutex.c
@@ -82,7 +82,7 @@ int pse51_mutex_check_init(struct __shad
 
 int pse51_mutex_init_internal(struct __shadow_mutex *shadow,
 			      pse51_mutex_t *mutex,
-			      xnarch_atomic_intptr_t *ownerp,
+			      xnarch_atomic_t *ownerp,
 			      const pthread_mutexattr_t *attr)
 {
 	xnflags_t synch_flags = XNSYNCH_PRIO | XNSYNCH_NOPIP;
@@ -118,7 +118,7 @@ int pse51_mutex_init_internal(struct __s
 	mutex->owner = ownerp;
 	mutex->owningq = kq;
 	mutex->sleepers = 0;
-	xnarch_atomic_intptr_set(ownerp, NULL);
+	xnarch_atomic_set(ownerp, XN_NO_HANDLE);
 
 	xnlock_get_irqsave(&nklock, s);
 	appendq(&kq->mutexq, &mutex->link);
@@ -159,7 +159,7 @@ int pthread_mutex_init(pthread_mutex_t *
 	    &((union __xeno_mutex *)mx)->shadow_mutex;
 	DECLARE_CB_LOCK_FLAGS(s);
 	pse51_mutex_t *mutex;
-	xnarch_atomic_intptr_t *ownerp;
+	xnarch_atomic_t *ownerp;
 	int err;
 
 	if (!attr)
@@ -185,9 +185,9 @@ int pthread_mutex_init(pthread_mutex_t *
 	if (!mutex)
 		return ENOMEM;
 
-	ownerp = (xnarch_atomic_intptr_t *)
+	ownerp = (xnarch_atomic_t *)
 		xnheap_alloc(&xnsys_ppd_get(attr->pshared)->sem_heap,
-			     sizeof(xnarch_atomic_intptr_t));
+			     sizeof(xnarch_atomic_t));
 	if (!ownerp) {
 		xnfree(mutex);
 		return EAGAIN;
@@ -266,7 +266,7 @@ int pthread_mutex_destroy(pthread_mutex_
 		return EPERM;
 	}
 
-	if (xnarch_atomic_intptr_get(mutex->owner)) {
+	if (xnarch_atomic_get(mutex->owner) != XN_NO_HANDLE) {
 		cb_write_unlock(&shadow->lock, s);
 		return EBUSY;
 	}
@@ -290,6 +290,10 @@ int pse51_mutex_timedlock_break(struct _
 	spl_t s;
 	int err;
 
+	/* We need a valid thread handle for the fast lock. */
+	if (xnthread_handle(cur) == XN_NO_HANDLE)
+		return -EPERM;
+
 	err = pse51_mutex_timedlock_internal(cur, shadow, 1, timed, abs_to);
 	if (err != -EBUSY)
 		goto unlock_and_return;
@@ -392,7 +396,7 @@ int pthread_mutex_trylock(pthread_mutex_
 		return -PTR_ERR(owner);
 
 	err = EBUSY;
-	if (clear_claimed(owner) == cur) {
+	if (owner == cur) {
 		pse51_mutex_t *mutex = shadow->mutex;
 
 		if (mutex->attr.type == PTHREAD_MUTEX_RECURSIVE) {
@@ -573,7 +577,8 @@ int pthread_mutex_unlock(pthread_mutex_t
 
 	mutex = shadow->mutex;
 	
-	if (clear_claimed(xnarch_atomic_intptr_get(mutex->owner)) != cur) {
+	if (clear_claimed(xnarch_atomic_get(mutex->owner)) !=
+	    xnthread_handle(cur)) {
 		err = EPERM;
 		goto out;
 	}
Index: b/ksrc/skins/posix/mutex.h
===================================================================
--- a/ksrc/skins/posix/mutex.h
+++ b/ksrc/skins/posix/mutex.h
@@ -34,7 +34,7 @@ union __xeno_mutex {
 		xnarch_atomic_t lock;
 		union {
 			unsigned owner_offset;
-			xnarch_atomic_intptr_t *owner;
+			xnarch_atomic_t *owner;
 		};
 		struct pse51_mutexattr attr;
 #endif /* CONFIG_XENO_FASTSEM */
@@ -54,7 +54,7 @@ typedef struct pse51_mutex {
 #define link2mutex(laddr)                                               \
 	((pse51_mutex_t *)(((char *)laddr) - offsetof(pse51_mutex_t, link)))
 
-	xnarch_atomic_intptr_t *owner;
+	xnarch_atomic_t *owner;
 	pthread_mutexattr_t attr;
 	unsigned sleepers;
 	pse51_kqueues_t *owningq;
@@ -77,7 +77,7 @@ int pse51_mutex_check_init(struct __shad
 
 int pse51_mutex_init_internal(struct __shadow_mutex *shadow,
 			      pse51_mutex_t *mutex,
-			      xnarch_atomic_intptr_t *ownerp,
+			      xnarch_atomic_t *ownerp,
 			      const pthread_mutexattr_t *attr);
 
 void pse51_mutex_destroy_internal(pse51_mutex_t *mutex,
@@ -88,6 +88,7 @@ pse51_mutex_trylock_internal(xnthread_t
 			     struct __shadow_mutex *shadow, unsigned count)
 {
 	pse51_mutex_t *mutex = shadow->mutex;
+	xnhandle_t ownerh;
 	xnthread_t *owner;
 
 	if (xnpod_unblockable_p())
@@ -101,9 +102,14 @@ pse51_mutex_trylock_internal(xnthread_t
 		return ERR_PTR(-EPERM);
 #endif /* XENO_DEBUG(POSIX) */
 
-	owner = xnarch_atomic_intptr_cmpxchg(mutex->owner, NULL, cur);
-	if (unlikely(owner != NULL))
+	ownerh = xnarch_atomic_cmpxchg(mutex->owner, XN_NO_HANDLE,
+				       xnthread_handle(cur));
+	if (unlikely(ownerh != XN_NO_HANDLE)) {
+		owner = xnthread_lookup(clear_claimed(ownerh));
+		if (!owner)
+			return ERR_PTR(-EINVAL);
 		return owner;
+	}
 
 	shadow->lockcnt = count;
 	return NULL;
@@ -118,7 +124,8 @@ static inline int pse51_mutex_timedlock_
 
 {
 	pse51_mutex_t *mutex;
-	xnthread_t *owner, *old;
+	xnthread_t *owner;
+	xnhandle_t ownerh, old;
 	spl_t s;
 	int err;
 
@@ -128,32 +135,39 @@ static inline int pse51_mutex_timedlock_
 		return PTR_ERR(owner);
 
 	mutex = shadow->mutex;
-	if (clear_claimed(owner) == cur)
+	if (owner == cur)
 		return -EBUSY;
 
 	/* Set bit 0, so that mutex_unlock will know that the mutex is claimed.
 	   Hold the nklock, for mutual exclusion with slow mutex_unlock. */
 	xnlock_get_irqsave(&nklock, s);
-	if (test_claimed(owner)) {
-		old = xnarch_atomic_intptr_get(mutex->owner);
+	if (test_claimed(ownerh)) {
+		old = xnarch_atomic_get(mutex->owner);
 		goto test_no_owner;
 	}
 	do {
-		old = xnarch_atomic_intptr_cmpxchg(mutex->owner,
-						   owner, set_claimed(owner, 1));
-		if (likely(old == owner))
+		old = xnarch_atomic_cmpxchg(mutex->owner, ownerh,
+					    set_claimed(ownerh, 1));
+		if (likely(old == ownerh))
 			break;
 	  test_no_owner:
-		if (old == NULL) {
+		if (old == XN_NO_HANDLE) {
 			/* Owner called fast mutex_unlock
 			   (on another cpu) */
 			xnlock_put_irqrestore(&nklock, s);
 			goto retry_lock;
 		}
-		owner = old;
-	} while (!test_claimed(owner));
+		ownerh = old;
+	} while (!test_claimed(ownerh));
+
+	owner = xnthread_lookup(clear_claimed(ownerh));
+
+	if (unlikely(!owner)) {
+		err = -EINVAL;
+		goto error;
+	}
 
-	xnsynch_set_owner(&mutex->synchbase, clear_claimed(owner));
+	xnsynch_set_owner(&mutex->synchbase, owner);
 	++mutex->sleepers;
 	if (timed)
 		xnsynch_sleep_on(&mutex->synchbase, abs_to, XN_REALTIME);
@@ -174,7 +188,8 @@ static inline int pse51_mutex_timedlock_
 		goto error;
 	}
 
-	xnarch_atomic_intptr_set(mutex->owner,set_claimed(cur, mutex->sleepers));
+	ownerh = set_claimed(xnthread_handle(cur), mutex->sleepers);
+	xnarch_atomic_set(mutex->owner, ownerh);
 	shadow->lockcnt = count;
 	xnlock_put_irqrestore(&nklock, s);
 
@@ -182,9 +197,9 @@ static inline int pse51_mutex_timedlock_
 
   error:
 	if (!mutex->sleepers)
-		xnarch_atomic_intptr_set
+		xnarch_atomic_set
 			(mutex->owner,
-			 clear_claimed(xnarch_atomic_intptr_get(mutex->owner)));
+			 clear_claimed(xnarch_atomic_get(mutex->owner)));
 	xnlock_put_irqrestore(&nklock, s);
 	return err;
 }
@@ -192,16 +207,18 @@ static inline int pse51_mutex_timedlock_
 static inline void pse51_mutex_unlock_internal(xnthread_t *cur,
 					       pse51_mutex_t *mutex)
 {
+	xnhandle_t ownerh;
 	xnthread_t *owner;
 	spl_t s;
 
-	if (likely(xnarch_atomic_intptr_cmpxchg(mutex->owner, cur, NULL) == cur))
+	if (likely(xnarch_atomic_cmpxchg(mutex->owner, cur, XN_NO_HANDLE) ==
+		   xnthread_handle(cur)))
 		return;
 
 	xnlock_get_irqsave(&nklock, s);
 	owner = xnsynch_wakeup_one_sleeper(&mutex->synchbase);
-	xnarch_atomic_intptr_set(mutex->owner,
-				 set_claimed(owner, mutex->sleepers));
+	ownerh = set_claimed(xnthread_handle(owner), mutex->sleepers);
+	xnarch_atomic_set(mutex->owner, ownerh);
 	if (owner)
 		xnpod_schedule();
 	xnlock_put_irqrestore(&nklock, s);
Index: b/ksrc/skins/posix/syscall.c
===================================================================
--- a/ksrc/skins/posix/syscall.c
+++ b/ksrc/skins/posix/syscall.c
@@ -1060,7 +1060,8 @@ static int __pthread_mutex_unlock(struct
 
 	mutex = shadow->mutex;
 
-	if (clear_claimed(xnarch_atomic_intptr_get(mutex->owner)) != cur) {
+	if (clear_claimed(xnarch_atomic_get(mutex->owner)) !=
+	    xnthread_handle(cur)) {
 		err = -EPERM;
 		goto out;
 	}
@@ -1119,7 +1120,7 @@ static int __pthread_mutex_init(struct p
 	pthread_mutexattr_t locattr, *attr, *uattrp;
 	union __xeno_mutex mx, *umx;
 	pse51_mutex_t *mutex;
-	xnarch_atomic_intptr_t *ownerp;
+	xnarch_atomic_t *ownerp;
 	int err;
 
 	umx = (union __xeno_mutex *)__xn_reg_arg1(regs);
@@ -1144,9 +1145,9 @@ static int __pthread_mutex_init(struct p
 	if (!mutex)
 		return -ENOMEM;
 
-	ownerp = (xnarch_atomic_intptr_t *)
+	ownerp = (xnarch_atomic_t *)
 		xnheap_alloc(&xnsys_ppd_get(attr->pshared)->sem_heap,
-			     sizeof(xnarch_atomic_intptr_t));
+			     sizeof(xnarch_atomic_t));
 	if (!ownerp) {
 		xnfree(mutex);
 		return -EAGAIN;
@@ -1185,7 +1186,7 @@ static int __pthread_mutex_destroy(struc
 	if (pse51_kqueues(mutex->attr.pshared) != mutex->owningq)
 		return -EPERM;
 
-	if (xnarch_atomic_intptr_get(mutex->owner))
+	if (xnarch_atomic_get(mutex->owner) != XN_NO_HANDLE)
 		return -EBUSY;
 
 	pse51_mark_deleted(shadow);
Index: b/src/skins/posix/mutex.c
===================================================================
--- a/src/skins/posix/mutex.c
+++ b/src/skins/posix/mutex.c
@@ -31,12 +31,12 @@ extern int __pse51_muxid;
 
 extern unsigned long xeno_sem_heap[2];
 
-static xnarch_atomic_intptr_t *get_ownerp(struct __shadow_mutex *shadow)
+static xnarch_atomic_t *get_ownerp(struct __shadow_mutex *shadow)
 {
 	if (likely(!shadow->attr.pshared))
 		return shadow->owner;
 	
-	return (xnarch_atomic_intptr_t *) (xeno_sem_heap[1] + shadow->owner_offset);
+	return (xnarch_atomic_t *) (xeno_sem_heap[1] + shadow->owner_offset);
 }
 #endif /* CONFIG_XENO_FASTSEM */
 
@@ -117,7 +117,7 @@ int __wrap_pthread_mutex_init(pthread_mu
 
 #ifdef CONFIG_XENO_FASTSEM
 	if (!shadow->attr.pshared)
-		shadow->owner = (xnarch_atomic_intptr_t *)
+		shadow->owner = (xnarch_atomic_t *)
 			(xeno_sem_heap[0] + shadow->owner_offset);
 	
 	cb_write_unlock(&shadow->lock, s);
@@ -149,10 +149,10 @@ int __wrap_pthread_mutex_lock(pthread_mu
 	int err = 0;
 
 #ifdef CONFIG_XENO_FASTSEM
-	xnthread_t *cur, *owner;
+	xnhandle_t cur, owner;
 
 	cur = xeno_get_current();
-	if (!cur)
+	if (cur == XN_NO_HANDLE)
 		return EPERM;
 
 	if (unlikely(cb_try_read_lock(&shadow->lock, s)))
@@ -163,8 +163,8 @@ int __wrap_pthread_mutex_lock(pthread_mu
 		goto out;
 	}
 
-	owner = xnarch_atomic_intptr_cmpxchg(get_ownerp(shadow), NULL, cur);
-	if (likely(!owner)) {
+	owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
+	if (likely(owner == XN_NO_HANDLE)) {
 		shadow->lockcnt = 1;
 		cb_read_unlock(&shadow->lock, s);
 		return 0;
@@ -210,10 +210,10 @@ int __wrap_pthread_mutex_timedlock(pthre
 	int err = 0;
 
 #ifdef CONFIG_XENO_FASTSEM
-	xnthread_t *cur, *owner;
+	xnhandle_t cur, owner;
 
 	cur = xeno_get_current();
-	if (!cur)
+	if (cur == XN_NO_HANDLE)
 		return EPERM;
 
 	if (unlikely(cb_try_read_lock(&shadow->lock, s)))
@@ -224,8 +224,8 @@ int __wrap_pthread_mutex_timedlock(pthre
 		goto out;
 	}	
 
-	owner = xnarch_atomic_intptr_cmpxchg(get_ownerp(shadow), NULL, cur);
-	if (likely(!owner)) {
+	owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
+	if (likely(owner == XN_NO_HANDLE)) {
 		shadow->lockcnt = 1;
 		cb_read_unlock(&shadow->lock, s);
 		return 0;
@@ -271,10 +271,10 @@ int __wrap_pthread_mutex_trylock(pthread
 	int err = 0;
 
 #ifdef CONFIG_XENO_FASTSEM
-	xnthread_t *cur, *owner;
+	xnhandle_t cur, owner;
 
 	cur = xeno_get_current();
-	if (!cur)
+	if (cur == XN_NO_HANDLE)
 		return EPERM;
 
 	if (unlikely(cb_try_read_lock(&shadow->lock, s)))
@@ -285,8 +285,8 @@ int __wrap_pthread_mutex_trylock(pthread
 		goto out;
 	}	
 
-	owner = xnarch_atomic_intptr_cmpxchg(get_ownerp(shadow), NULL, cur);
-	if (likely(!owner)) {
+	owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
+	if (likely(owner == XN_NO_HANDLE)) {
 		shadow->lockcnt = 1;
 		cb_read_unlock(&shadow->lock, s);
 		return 0;
@@ -325,11 +325,11 @@ int __wrap_pthread_mutex_unlock(pthread_
 	int err = 0;
 
 #ifdef CONFIG_XENO_FASTSEM
-	xnarch_atomic_intptr_t *ownerp;
-	xnthread_t *cur;
+	xnarch_atomic_t *ownerp;
+	xnhandle_t cur, owner;
 
 	cur = xeno_get_current();
-	if (!cur)
+	if (cur == XN_NO_HANDLE)
 		return EPERM;
 
 	if (unlikely(cb_try_read_lock(&shadow->lock, s)))
@@ -341,7 +341,8 @@ int __wrap_pthread_mutex_unlock(pthread_
 	}
 
 	ownerp = get_ownerp(shadow);
-	if (unlikely(clear_claimed(xnarch_atomic_intptr_get(ownerp)) != cur)) {
+	owner = clear_claimed(xnarch_atomic_get(ownerp));
+	if (unlikely(owner != cur)) {
 		err = -EPERM;
 		goto out_err;
 	}
@@ -352,7 +353,7 @@ int __wrap_pthread_mutex_unlock(pthread_
 		goto out;
 	}
 
-	if (likely(xnarch_atomic_intptr_cmpxchg(ownerp, cur, NULL) == cur)) {
+	if (likely(xnarch_atomic_cmpxchg(ownerp, cur, XN_NO_HANDLE) == cur)) {
 	  out:
 		cb_read_unlock(&shadow->lock, s);
 		return 0;
Index: b/ksrc/skins/posix/thread.c
===================================================================
--- a/ksrc/skins/posix/thread.c
+++ b/ksrc/skins/posix/thread.c
@@ -234,6 +234,18 @@ int pthread_create(pthread_t *tid,
 	thread->hkey.mm = NULL;
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
 
+#ifdef CONFIG_XENO_FASTSEM
+	/* We need an anonymous registry entry to obtain a handle for fast
+	   mutex locking. */
+	{
+		int err = xnthread_register(&thread->threadbase, "");
+		if (err) {
+			thread_destroy(thread);
+			return err;
+		}
+	}
+#endif /* CONFIG_XENO_FASTSEM */
+
 	*tid = thread;		/* Must be done before the thread is started. */
 
 	if (start)		/* Do not start shadow threads (i.e. start == NULL). */
Index: b/ksrc/skins/posix/Kconfig
===================================================================
--- a/ksrc/skins/posix/Kconfig
+++ b/ksrc/skins/posix/Kconfig
@@ -1,5 +1,6 @@
 menuconfig XENO_SKIN_POSIX
 	depends on XENO_OPT_NUCLEUS 
+	select XENO_OPT_REGISTRY if XENO_FASTSEM
 	tristate "POSIX API"
 	default y
 	help
Index: b/include/asm-generic/bits/bind.h
===================================================================
--- a/include/asm-generic/bits/bind.h
+++ b/include/asm-generic/bits/bind.h
@@ -22,7 +22,14 @@ __attribute__ ((weak))
 void xeno_set_current(void)
 {
 	void *kthread_cb;
-	XENOMAI_SYSCALL1(__xn_sys_current, &kthread_cb);
+	int err;
+
+	err = XENOMAI_SYSCALL1(__xn_sys_current, &kthread_cb);
+	if (err) {
+		fprintf(stderr, "Xenomai: error obtaining handle for current "
+			"thread: %s\n", strerror(err));
+		exit(1);
+	}
 	pthread_setspecific(xeno_current_key, kthread_cb);
 }
 
Index: b/ksrc/skins/native/Kconfig
===================================================================
--- a/ksrc/skins/native/Kconfig
+++ b/ksrc/skins/native/Kconfig
@@ -1,5 +1,6 @@
 menuconfig XENO_SKIN_NATIVE
 	depends on XENO_OPT_NUCLEUS
+	select XENO_OPT_REGISTRY if XENO_FASTSEM
 	tristate "Native API"
 	default y
 	help
Index: b/ksrc/skins/native/task.c
===================================================================
--- a/ksrc/skins/native/task.c
+++ b/ksrc/skins/native/task.c
@@ -283,11 +283,9 @@ int rt_task_create(RT_TASK *task,
 	   complete objects, so that the registry cannot return handles to
 	   half-baked objects... */
 
-	if (name) {
-		err = xnthread_register(&task->thread_base, task->rname);
-		if (err)
-			xnpod_delete_thread(&task->thread_base);
-	}
+	err = xnthread_register(&task->thread_base, name ? task->rname : "");
+	if (err)
+		xnpod_delete_thread(&task->thread_base);
 
 	return err;
 }
Index: b/ksrc/skins/psos+/Kconfig
===================================================================
--- a/ksrc/skins/psos+/Kconfig
+++ b/ksrc/skins/psos+/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_PSOS
 	depends on XENO_OPT_NUCLEUS
 	select XENO_OPT_TIMING_PERIODIC
 	tristate "pSOS+ emulator"
-	select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE
+	select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSEM
 	help
 
 	This API skin emulates WindRiver's pSOS+ operating system.
Index: b/ksrc/skins/uitron/Kconfig
===================================================================
--- a/ksrc/skins/uitron/Kconfig
+++ b/ksrc/skins/uitron/Kconfig
@@ -2,6 +2,7 @@ menuconfig XENO_SKIN_UITRON
 	depends on XENO_OPT_NUCLEUS
 	select XENO_OPT_TIMING_PERIODIC
 	select XENO_OPT_MAP
+	select XENO_OPT_REGISTRY if XENO_FASTSEM
 	tristate "uITRON API"
 	help
 
Index: b/ksrc/skins/uitron/task.c
===================================================================
--- a/ksrc/skins/uitron/task.c
+++ b/ksrc/skins/uitron/task.c
@@ -16,7 +16,6 @@
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#include <nucleus/registry.h>
 #include <nucleus/pod.h>
 #include <nucleus/heap.h>
 #include <uitron/task.h>
@@ -151,6 +150,16 @@ ER cre_tsk(ID tskid, T_CTSK *pk_ctsk)
 	xnlock_put_irqrestore(&nklock, s);
 	task->magic = uITRON_TASK_MAGIC;
 
+#ifdef CONFIG_XENO_FASTSEM
+	/* We need an anonymous registry entry to obtain a handle for fast
+	   mutex locking. */
+	if (xnthread_register(&task->threadbase, "")) {
+		xnmap_remove(ui_task_idmap, tskid);
+		xnpod_abort_thread(&task->threadbase);
+		return E_NOMEM;
+	}
+#endif /* CONFIG_XENO_FASTSEM */
+
 	return E_OK;
 }
 
Index: b/ksrc/skins/rtai/Kconfig
===================================================================
--- a/ksrc/skins/rtai/Kconfig
+++ b/ksrc/skins/rtai/Kconfig
@@ -1,5 +1,6 @@
 menuconfig XENO_SKIN_RTAI
 	depends on XENO_OPT_NUCLEUS
+	select XENO_OPT_REGISTRY if XENO_FASTSEM
 	tristate "RTAI emulator"
 	help
 
Index: b/ksrc/skins/rtai/task.c
===================================================================
--- a/ksrc/skins/rtai/task.c
+++ b/ksrc/skins/rtai/task.c
@@ -152,6 +152,16 @@ int rt_task_init(RT_TASK *task,
 	task->magic = RTAI_TASK_MAGIC;
 	appendq(&__rtai_task_q, &task->link);
 
+#ifdef CONFIG_XENO_FASTSEM
+	/* We need an anonymous registry entry to obtain a handle for fast
+	   mutex locking. */
+	err = xnthread_register(&task->thread_base, "");
+	if (err) {
+		xnpod_abort_thread(&task->thread_base);
+		goto unlock_and_exit;
+	}
+#endif /* CONFIG_XENO_FASTSEM */
+
 	/* Add a switch hook only if a signal function has been declared
 	   at least once for some created task. */
 
Index: b/ksrc/skins/vrtx/Kconfig
===================================================================
--- a/ksrc/skins/vrtx/Kconfig
+++ b/ksrc/skins/vrtx/Kconfig
@@ -3,7 +3,7 @@ menuconfig XENO_SKIN_VRTX
 	select XENO_OPT_TIMING_PERIODIC
 	select XENO_OPT_MAP
 	tristate "VRTX emulator"
-	select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE
+	select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || CONFIG_XENO_FASTSEM
 	help
 
 	This API skin emulates Mentor Graphics's VRTX operating
Index: b/ksrc/skins/vrtx/task.c
===================================================================
--- a/ksrc/skins/vrtx/task.c
+++ b/ksrc/skins/vrtx/task.c
@@ -188,12 +188,25 @@ int sc_tecreate_inner(vrtxtask_t *task,
 	if (mode & 0x10)
 		bmode |= XNRRB;
 
-	*errp = RET_OK;
-
 	xnlock_get_irqsave(&nklock, s);
 	appendq(&vrtx_task_q, &task->link);
 	xnlock_put_irqrestore(&nklock, s);
 
+#ifdef CONFIG_XENO_FASTSEM
+	/* We need an anonymous registry entry to obtain a handle for fast
+	   mutex locking. */
+	{
+		int err = xnthread_register(&task->threadbase, "");
+		if (err) {
+			xnpod_abort_thread(&task->threadbase);
+			*errp = ER_MEM;
+			return -1;
+		}
+	}
+#endif /* CONFIG_XENO_FASTSEM */
+
+	*errp = RET_OK;
+
 	xnpod_start_thread(&task->threadbase,
 			   bmode, 0, XNPOD_ALL_CPUS, &vrtxtask_trampoline,
 			   task);
Index: b/ksrc/skins/vxworks/Kconfig
===================================================================
--- a/ksrc/skins/vxworks/Kconfig
+++ b/ksrc/skins/vxworks/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_VXWORKS
 	depends on XENO_OPT_NUCLEUS
 	select XENO_OPT_TIMING_PERIODIC
 	tristate "VxWorks emulator"
-	select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE
+	select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSEM
 	help
 
 	This API skin emulates WindRiver's VxWorks operating system.
Index: b/ksrc/skins/rtdm/drvlib.c
===================================================================
--- a/ksrc/skins/rtdm/drvlib.c
+++ b/ksrc/skins/rtdm/drvlib.c
@@ -145,6 +145,14 @@ int rtdm_task_init(rtdm_task_t *task, co
 	if (err)
 		return err;
 
+#ifdef CONFIG_XENO_FASTSEM
+	/* We need an anonymous registry entry to obtain a handle for fast
+	   mutex locking. */
+	err = xnthread_register(task, "");
+	if (err)
+		goto cleanup_out;
+#endif /* CONFIG_XENO_FASTSEM */
+
 	if (period > 0) {
 		err = xnpod_set_thread_periodic(task, XN_INFINITE,
 						xntbase_ns2ticks_ceil



^ permalink raw reply	[flat|nested] 50+ messages in thread

* [Xenomai-core] [PATCH 03/12] Remove xnarch_atomic_intptr
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 01/12] Generic thread registration Jan Kiszka
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 02/12] Handle-based xeno_get_current service Jan Kiszka
@ 2008-10-16 15:46 ` Jan Kiszka
  2008-10-16 19:37   ` Gilles Chanteperdrix
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 04/12] Spread xeno_set_current under all skins Jan Kiszka
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 15:46 UTC (permalink / raw)
  To: xenomai; +Cc: Jan Kiszka

[-- Attachment #1: remove-xnarch_atomic_intptr.patch --]
[-- Type: text/plain, Size: 4306 bytes --]

No more users, no more use cases in sight, let's get rid of it.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/asm-arm/atomic.h        |    3 ---
 include/asm-blackfin/atomic.h   |    2 --
 include/asm-generic/Makefile.am |    2 +-
 include/asm-generic/Makefile.in |    2 +-
 include/asm-generic/atomic.h    |   24 ------------------------
 include/asm-ia64/atomic.h       |    2 --
 include/asm-powerpc/atomic.h    |    2 --
 include/asm-x86/atomic.h        |    2 --
 8 files changed, 2 insertions(+), 37 deletions(-)

Index: b/include/asm-arm/atomic.h
===================================================================
--- a/include/asm-arm/atomic.h
+++ b/include/asm-arm/atomic.h
@@ -412,9 +412,6 @@ static __inline__ void xnarch_atomic_cle
 
 typedef unsigned long atomic_flags_t;
 
-/* Add support for xnarch_atomic_intptr_t */
-#include <asm-generic/xenomai/atomic.h>
-
 #endif /* !_XENO_ASM_ARM_ATOMIC_H */
 
 // vim: ts=4 et sw=4 sts=4
Index: b/include/asm-blackfin/atomic.h
===================================================================
--- a/include/asm-blackfin/atomic.h
+++ b/include/asm-blackfin/atomic.h
@@ -42,8 +42,6 @@
 typedef atomic_t atomic_counter_t;
 typedef atomic_t xnarch_atomic_t;
 
-#include <asm-generic/xenomai/atomic.h>
-
 #else /* !__KERNEL__ */
 
 #include <asm/xenomai/syscall.h>
Index: b/include/asm-generic/Makefile.am
===================================================================
--- a/include/asm-generic/Makefile.am
+++ b/include/asm-generic/Makefile.am
@@ -1,5 +1,5 @@
 includesubdir = $(includedir)/asm-generic
 
-includesub_HEADERS = arith.h atomic.h features.h hal.h syscall.h system.h wrappers.h
+includesub_HEADERS = arith.h features.h hal.h syscall.h system.h wrappers.h
 
 SUBDIRS = bits
Index: b/include/asm-generic/Makefile.in
===================================================================
--- a/include/asm-generic/Makefile.in
+++ b/include/asm-generic/Makefile.in
@@ -226,7 +226,7 @@ target_vendor = @target_vendor@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 includesubdir = $(includedir)/asm-generic
-includesub_HEADERS = arith.h atomic.h features.h hal.h syscall.h system.h wrappers.h
+includesub_HEADERS = arith.h features.h hal.h syscall.h system.h wrappers.h
 SUBDIRS = bits
 all: all-recursive
 
Index: b/include/asm-generic/atomic.h
===================================================================
--- a/include/asm-generic/atomic.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _XENO_ASM_GENERIC_ATOMIC_H
-#define _XENO_ASM_GENERIC_ATOMIC_H
-
-typedef xnarch_atomic_t xnarch_atomic_intptr_t;
-
-static inline void *xnarch_atomic_intptr_get(xnarch_atomic_intptr_t *l)
-{
-        xnarch_atomic_t *v = (xnarch_atomic_t *)l;
-
-        return (void *)xnarch_atomic_get(v);
-}
-
-static inline void xnarch_atomic_intptr_set(xnarch_atomic_intptr_t *l, void *i)
-{
-        xnarch_atomic_t *v = (xnarch_atomic_t *)l;
-
-        xnarch_atomic_set(v, (long)i);
-}
-
-#define xnarch_atomic_intptr_cmpxchg(l, old, newval) \
-        (void *)(xnarch_atomic_cmpxchg((xnarch_atomic_t *)(l), \
-				       (long)(old), (long)(newval)))
-
-#endif /* _XENO_ASM_GENERIC_ATOMIC_H */
Index: b/include/asm-ia64/atomic.h
===================================================================
--- a/include/asm-ia64/atomic.h
+++ b/include/asm-ia64/atomic.h
@@ -71,8 +71,6 @@ static inline void atomic_clear_mask(uns
 #define xnarch_atomic_cmpxchg(pcounter,old,new) \
 	cmpxchg((&(pcounter)->counter),(old),(new))
 
-#include <asm-generic/xenomai/atomic.h>
-
 #else /* !__KERNEL__ */
 
 #include <asm/xenomai/features.h>
Index: b/include/asm-powerpc/atomic.h
===================================================================
--- a/include/asm-powerpc/atomic.h
+++ b/include/asm-powerpc/atomic.h
@@ -262,6 +262,4 @@ xnarch_atomic_cmpxchg(xnarch_atomic_t *p
 
 typedef unsigned long atomic_flags_t;
 
-#include <asm-generic/xenomai/atomic.h>
-
 #endif /* !_XENO_ASM_POWERPC_ATOMIC_H */
Index: b/include/asm-x86/atomic.h
===================================================================
--- a/include/asm-x86/atomic.h
+++ b/include/asm-x86/atomic.h
@@ -136,6 +136,4 @@ xnarch_atomic_cmpxchg(xnarch_atomic_t *v
 
 #endif /* __KERNEL__ */
 
-#include <asm-generic/xenomai/atomic.h>
-
 #endif /* !_XENO_ASM_X86_ATOMIC_64_H */



^ permalink raw reply	[flat|nested] 50+ messages in thread

* [Xenomai-core] [PATCH 04/12] Spread xeno_set_current under all skins
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
                   ` (2 preceding siblings ...)
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 03/12] Remove xnarch_atomic_intptr Jan Kiszka
@ 2008-10-16 15:46 ` Jan Kiszka
  2008-10-16 19:38   ` Gilles Chanteperdrix
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 05/12] Factor out xnsynch_acquire/release Jan Kiszka
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 15:46 UTC (permalink / raw)
  To: xenomai; +Cc: Jan Kiszka

[-- Attachment #1: spread-xeno_set_current.patch --]
[-- Type: text/plain, Size: 5518 bytes --]

Spread xeno_set_current under all user space supporting skins.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 src/skins/native/task.c     |   13 +++++++++++--
 src/skins/psos+/task.c      |   18 ++++++++++++++----
 src/skins/uitron/task.c     |   18 +++++++++++++-----
 src/skins/vrtx/task.c       |    3 +++
 src/skins/vxworks/taskLib.c |    3 +++
 5 files changed, 44 insertions(+), 11 deletions(-)

Index: b/src/skins/native/task.c
===================================================================
--- a/src/skins/native/task.c
+++ b/src/skins/native/task.c
@@ -26,6 +26,7 @@
 #include <limits.h>
 #include <native/syscall.h>
 #include <native/task.h>
+#include <asm-generic/bits/current.h>
 #include "wrappers.h"
 
 extern pthread_key_t __native_tskey;
@@ -88,6 +89,8 @@ static void *rt_task_trampoline(void *co
 	if (err)
 		goto fail;
 
+	xeno_set_current();
+
 	/* Wait on the barrier for the task to be started. The barrier
 	   could be released in order to process Linux signals while the
 	   Xenomai shadow is still dormant; in such a case, resume wait. */
@@ -169,6 +172,7 @@ int rt_task_shadow(RT_TASK *task, const
 	struct sched_param param;
 	struct rt_arg_bulk bulk;
 	RT_TASK task_desc;
+	int err;
 
 	if (task == NULL)
 		task = &task_desc; /* Discarded. */
@@ -191,8 +195,13 @@ int rt_task_shadow(RT_TASK *task, const
 	bulk.a4 = (u_long)mode;
 	bulk.a5 = (u_long)pthread_self();
 
-	return XENOMAI_SKINCALL2(__native_muxid, __native_task_create, &bulk,
-				 NULL);
+	err = XENOMAI_SKINCALL2(__native_muxid, __native_task_create, &bulk,
+				NULL);
+
+	if (!err)
+		xeno_set_current();
+
+	return err;
 }
 
 int rt_task_bind(RT_TASK *task, const char *name, RTIME timeout)
Index: b/src/skins/psos+/task.c
===================================================================
--- a/src/skins/psos+/task.c
+++ b/src/skins/psos+/task.c
@@ -26,6 +26,7 @@
 #include <memory.h>
 #include <string.h>
 #include <psos+/psos.h>
+#include <asm-generic/bits/current.h>
 
 extern int __psos_muxid;
 
@@ -89,6 +90,8 @@ static void *psos_task_trampoline(void *
 	if (err)
 		goto fail;
 
+	xeno_set_current();
+
 	/* Wait on the barrier for the task to be started. The barrier
 	   could be released in order to process Linux signals while the
 	   Xenomai shadow is still dormant; in such a case, resume wait. */
@@ -173,14 +176,21 @@ u_long t_shadow(const char *name, /* Xen
 		u_long flags,
 		u_long *tid_r)
 {
+	int err;
+
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
 
 	old_sigharden_handler = signal(SIGHARDEN, &psos_task_sigharden);
 
-	return XENOMAI_SKINCALL5(__psos_muxid,
-				 __psos_t_create,
-				 name, prio, flags,
-				 tid_r, NULL);
+	err = XENOMAI_SKINCALL5(__psos_muxid,
+				__psos_t_create,
+				name, prio, flags,
+				tid_r, NULL);
+
+	if (!err)
+		xeno_set_current();
+
+	return err;
 }
 
 u_long t_start(u_long tid,
Index: b/src/skins/uitron/task.c
===================================================================
--- a/src/skins/uitron/task.c
+++ b/src/skins/uitron/task.c
@@ -25,6 +25,7 @@
 #include <limits.h>
 #include <asm/xenomai/system.h>
 #include <uitron/uitron.h>
+#include <asm-generic/bits/current.h>
 
 extern int __uitron_muxid;
 
@@ -89,6 +90,8 @@ static void *uitron_task_trampoline(void
 	if (err)
 		goto fail;
 
+	xeno_set_current();
+
 	/* iargs->pk_ctsk might not be valid anymore, after our parent
 	   was released from the completion sync, so do not
 	   dereference this pointer. */
@@ -150,7 +153,7 @@ ER cre_tsk(ID tskid, T_CTSK *pk_ctsk)
 ER shd_tsk(ID tskid, T_CTSK *pk_ctsk) /* Xenomai extension. */
 {
 	struct sched_param param;
-	int policy;
+	int policy, err;
 	
 	/* Make sure the POSIX library caches the right priority. */
 	policy = uitron_task_set_posix_priority(pk_ctsk->itskpri, &param);
@@ -160,10 +163,15 @@ ER shd_tsk(ID tskid, T_CTSK *pk_ctsk) /*
 
 	old_sigharden_handler = signal(SIGHARDEN, &uitron_task_sigharden);
 
-	return XENOMAI_SKINCALL3(__uitron_muxid,
-				 __uitron_cre_tsk,
-				 tskid, pk_ctsk,
-				 NULL);
+	err = XENOMAI_SKINCALL3(__uitron_muxid,
+				__uitron_cre_tsk,
+				tskid, pk_ctsk,
+				NULL);
+
+	if (!err)
+		xeno_set_current();
+
+	return err;
 }
 
 ER del_tsk(ID tskid)
Index: b/src/skins/vrtx/task.c
===================================================================
--- a/src/skins/vrtx/task.c
+++ b/src/skins/vrtx/task.c
@@ -27,6 +27,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <vrtx/vrtx.h>
+#include <asm-generic/bits/current.h>
 
 extern pthread_key_t __vrtx_tskey;
 
@@ -116,6 +117,8 @@ static void *vrtx_task_trampoline(void *
 	if (err)
 		goto fail;
 
+	xeno_set_current();
+
 	/* Wait on the barrier for the task to be started. The barrier
 	   could be released in order to process Linux signals while the
 	   Xenomai shadow is still dormant; in such a case, resume wait. */
Index: b/src/skins/vxworks/taskLib.c
===================================================================
--- a/src/skins/vxworks/taskLib.c
+++ b/src/skins/vxworks/taskLib.c
@@ -27,6 +27,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <vxworks/vxworks.h>
+#include <asm-generic/bits/current.h>
 #include "wrappers.h"
 
 extern pthread_key_t __vxworks_tskey;
@@ -117,6 +118,8 @@ static void *wind_task_trampoline(void *
 	if (err)
 		goto fail;
 
+	xeno_set_current();
+
 	/* Wait on the barrier for the task to be started. The barrier
 	   could be released in order to process Linux signals while the
 	   Xenomai shadow is still dormant; in such a case, resume wait. */



^ permalink raw reply	[flat|nested] 50+ messages in thread

* [Xenomai-core] [PATCH 05/12] Factor out xnsynch_acquire/release
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
                   ` (3 preceding siblings ...)
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 04/12] Spread xeno_set_current under all skins Jan Kiszka
@ 2008-10-16 15:46 ` Jan Kiszka
  2008-10-16 19:46   ` Gilles Chanteperdrix
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 06/12] Lockless fast path for xnsynch_acquire/release Jan Kiszka
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 15:46 UTC (permalink / raw)
  To: xenomai; +Cc: Jan Kiszka

[-- Attachment #1: factor-out-xnsynch_acquire-release.patch --]
[-- Type: text/plain, Size: 30505 bytes --]

This patch addresses the increasing divergence of owner-tracking vs.
owner-less xnsynch objects.

Services dealing with the former will include the new, lockless xnsynch
prologue for optimizing its fastpath. At the the same time, this
additional code should not disturb too much in those cases where we do
not track ownership (condition variables, events, semaphores etc.).
Moreover, I noticed that some of the existing code assumes XNSYNCH_NOPIP
means no ownership, which is surely not true. The already visible effect
is that lock stealing is needlessly restricted to XNSYNCH_PIP.

Going through the API, I dug out three diverging services and replaced
them with two new ones:

Owner-less xnsynch objects:
 - xnsynch_sleep_on
 - xnsynch_wakeup_one_sleeper
 - xnsynch_wakeup_this_sleeper

Owner-tracking xnsynch objects:
 - xnsynch_acquire
 - xnsynch_release

The latter type of objects are marked with the new flag XNSYNCH_OWNER,
used only for debugging and code documentation purposes in the current
implementation.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/nucleus/synch.h     |   16 +
 include/rtdm/rtdm_driver.h  |    2 
 ksrc/nucleus/synch.c        |  418 +++++++++++++++++++++++++++++---------------
 ksrc/skins/native/cond.c    |    2 
 ksrc/skins/native/mutex.c   |    7 
 ksrc/skins/native/task.c    |    5 
 ksrc/skins/posix/cond.c     |    2 
 ksrc/skins/posix/mutex.c    |   10 -
 ksrc/skins/posix/mutex.h    |    6 
 ksrc/skins/rtai/sem.c       |   10 -
 ksrc/skins/rtdm/drvlib.c    |   15 -
 ksrc/skins/vrtx/mx.c        |    6 
 ksrc/skins/vxworks/semLib.c |    6 
 13 files changed, 326 insertions(+), 179 deletions(-)

Index: b/include/nucleus/synch.h
===================================================================
--- a/include/nucleus/synch.h
+++ b/include/nucleus/synch.h
@@ -30,10 +30,11 @@
 #define XNSYNCH_NOPIP   0x0
 #define XNSYNCH_PIP     0x2
 #define XNSYNCH_DREORD  0x4
+#define XNSYNCH_OWNER   0x8
 
 #if defined(__KERNEL__) || defined(__XENO_SIM__)
 
-#define XNSYNCH_CLAIMED 0x8	/* Claimed by other thread(s) w/ PIP */
+#define XNSYNCH_CLAIMED 0x10	/* Claimed by other thread(s) w/ PIP */
 
 /* Spare flags usable by upper interfaces */
 #define XNSYNCH_SPARE0  0x01000000
@@ -105,13 +106,18 @@ void xnsynch_sleep_on(xnsynch_t *synch,
 
 struct xnthread *xnsynch_wakeup_one_sleeper(xnsynch_t *synch);
 
-struct xnthread *xnsynch_peek_pendq(xnsynch_t *synch);
-
 xnpholder_t *xnsynch_wakeup_this_sleeper(xnsynch_t *synch,
 					 xnpholder_t *holder);
 
-int xnsynch_flush(xnsynch_t *synch,
-		  xnflags_t reason);
+void xnsynch_acquire(xnsynch_t *synch,
+		     xnticks_t timeout,
+		     xntmode_t timeout_mode);
+
+struct xnthread *xnsynch_release(xnsynch_t *synch);
+
+struct xnthread *xnsynch_peek_pendq(xnsynch_t *synch);
+
+int xnsynch_flush(xnsynch_t *synch, xnflags_t reason);
 
 void xnsynch_release_all_ownerships(struct xnthread *thread);
 
Index: b/ksrc/nucleus/synch.c
===================================================================
--- a/ksrc/nucleus/synch.c
+++ b/ksrc/nucleus/synch.c
@@ -59,6 +59,12 @@
  * - XNSYNCH_PRIO causes the threads waiting for the resource to pend
  * in priority order. Otherwise, FIFO ordering is used (XNSYNCH_FIFO).
  *
+ * - XNSYNCH_OWNER indicates that the synchronization object shall
+ * track its owning thread (required if XNSYNCH_PIP is selected). Note
+ * that setting this flag implies the use xnsynch_acquire and
+ * xnsynch_release instead of xnsynch_sleep_on and
+ * xnsynch_wakeup_one_sleeper/xnsynch_wakeup_this_sleeper.
+ *
  * - XNSYNCH_PIP causes the priority inheritance mechanism to be
  * automatically activated when a priority inversion is detected among
  * threads using this object. Otherwise, no priority inheritance takes
@@ -89,7 +95,7 @@ void xnsynch_init(xnsynch_t *synch, xnfl
 	initph(&synch->link);
 
 	if (flags & XNSYNCH_PIP)
-		flags |= XNSYNCH_PRIO;	/* Obviously... */
+		flags |= XNSYNCH_PRIO | XNSYNCH_OWNER;	/* Obviously... */
 
 	synch->status = flags & ~XNSYNCH_CLAIMED;
 	synch->owner = NULL;
@@ -98,6 +104,209 @@ void xnsynch_init(xnsynch_t *synch, xnfl
 	xnarch_init_display_context(synch);
 }
 
+/*!
+ * \fn void xnsynch_sleep_on(xnsynch_t *synch, xnticks_t timeout,
+ *                           xntmode_t timeout_mode);
+ * \brief Sleep on an ownerless synchronization object.
+ *
+ * Makes the calling thread sleep on the specified synchronization
+ * object, waiting for it to be signaled.
+ *
+ * This service should be called by upper interfaces wanting the
+ * current thread to pend on the given resource. It must not be used
+ * with synchronization objects that are supposed to track ownership
+ * (XNSYNCH_OWNER).
+ *
+ * @param synch The descriptor address of the synchronization object
+ * to sleep on.
+ *
+ * @param timeout The timeout which may be used to limit the time the
+ * thread pends on the resource. This value is a wait time given in
+ * ticks (see note). It can either be relative, absolute monotonic, or
+ * absolute adjustable depending on @a timeout_mode. Passing XN_INFINITE
+ * @b and setting @a mode to XN_RELATIVE specifies an unbounded wait. All
+ * other values are used to initialize a watchdog timer.
+ *
+ * @param timeout_mode The mode of the @a timeout parameter. It can
+ * either be set to XN_RELATIVE, XN_ABSOLUTE, or XN_REALTIME (see also
+ * xntimer_start()).
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Kernel-based task
+ * - User-space task
+ *
+ * Rescheduling: always.
+ *
+ * @note The @a timeout value will be interpreted as jiffies if the
+ * current thread is bound to a periodic time base (see
+ * xnpod_init_thread), or nanoseconds otherwise.
+ */
+
+void xnsynch_sleep_on(xnsynch_t *synch, xnticks_t timeout,
+		      xntmode_t timeout_mode)
+{
+	xnthread_t *thread = xnpod_current_thread();
+	spl_t s;
+
+	XENO_BUGON(NUCLEUS, testbits(synch->status, XNSYNCH_OWNER));
+
+	xnlock_get_irqsave(&nklock, s);
+
+	trace_mark(xn_nucleus_synch_sleepon,
+		   "thread %p thread_name %s synch %p",
+		   thread, xnthread_name(thread), synch);
+
+	if (!testbits(synch->status, XNSYNCH_PRIO)) /* i.e. FIFO */
+		appendpq(&synch->pendq, &thread->plink);
+	else /* i.e. priority-sorted */
+		insertpqf(&synch->pendq, &thread->plink, thread->cprio);
+
+	xnpod_suspend_thread(thread, XNPEND, timeout, timeout_mode, synch);
+
+	xnlock_put_irqrestore(&nklock, s);
+}
+
+/*!
+ * \fn xnthread_t *xnsynch_wakeup_one_sleeper(xnsynch_t *synch);
+ * \brief Give the resource ownership to the next waiting thread.
+ *
+ * This service wakes up the thread which is currently leading the
+ * synchronization object's pending list. The sleeping thread is
+ * unblocked from its pending state, but no reschedule is performed.
+ *
+ * This service should be called by upper interfaces wanting to signal
+ * the given resource so that a single waiter is resumed. It must not
+ * be used with synchronization objects that are supposed to track
+ * ownership (XNSYNCH_OWNER not set).
+ *
+ * @param synch The descriptor address of the synchronization object
+ * whose ownership is changed.
+ *
+ * @return The descriptor address of the unblocked thread.
+ *
+ * Side-effects:
+ *
+ * - The effective priority of the previous resource owner might be
+ * lowered to its base priority value as a consequence of the priority
+ * inheritance boost being cleared.
+ *
+ * - The synchronization object ownership is transfered to the
+ * unblocked thread.
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Interrupt service routine
+ * - Kernel-based task
+ * - User-space task
+ *
+ * Rescheduling: never.
+ */
+
+xnthread_t *xnsynch_wakeup_one_sleeper(xnsynch_t *synch)
+{
+	xnthread_t *thread = NULL;
+	xnpholder_t *holder;
+	spl_t s;
+
+	XENO_BUGON(NUCLEUS, testbits(synch->status, XNSYNCH_OWNER));
+
+	xnlock_get_irqsave(&nklock, s);
+
+	holder = getpq(&synch->pendq);
+
+	if (holder) {
+		thread = link2thread(holder, plink);
+		thread->wchan = NULL;
+		trace_mark(xn_nucleus_synch_wakeup_one,
+			   "thread %p thread_name %s synch %p",
+			   thread, xnthread_name(thread), synch);
+		xnpod_resume_thread(thread, XNPEND);
+	}
+
+	xnlock_put_irqrestore(&nklock, s);
+
+	xnarch_post_graph_if(synch, 0, emptypq_p(&synch->pendq));
+
+	return thread;
+}
+
+/*!
+ * \fn void xnsynch_wakeup_this_sleeper(xnsynch_t *synch, xnpholder_t *holder);
+ * \brief Give the resource ownership to a given waiting thread.
+ *
+ * This service wakes up a specific thread which is currently pending on
+ * the given synchronization object. The sleeping thread is unblocked
+ * from its pending state, but no reschedule is performed.
+ *
+ * This service should be called by upper interfaces wanting to signal
+ * the given resource so that a specific waiter is resumed. It must not
+ * be used with synchronization objects that are supposed to track
+ * ownership (XNSYNCH_OWNER not set).
+ *
+ * @param synch The descriptor address of the synchronization object
+ * whose ownership is changed.
+ *
+ * @param holder The link holder address of the thread to unblock
+ * (&thread->plink) which MUST be currently linked to the
+ * synchronization object's pending queue (i.e. synch->pendq).
+ *
+ * @return The link address of the unblocked thread in the
+ * synchronization object's pending queue.
+ *
+ * Side-effects:
+ *
+ * - The effective priority of the previous resource owner might be
+ * lowered to its base priority value as a consequence of the priority
+ * inheritance boost being cleared.
+ *
+ * - The synchronization object ownership is transfered to the
+ * unblocked thread.
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Interrupt service routine
+ * - Kernel-based task
+ * - User-space task
+ *
+ * Rescheduling: never.
+ */
+
+xnpholder_t *xnsynch_wakeup_this_sleeper(xnsynch_t *synch, xnpholder_t *holder)
+{
+	xnthread_t *thread;
+	xnpholder_t *nholder;
+	spl_t s;
+
+	XENO_BUGON(NUCLEUS, testbits(synch->status, XNSYNCH_OWNER));
+
+	xnlock_get_irqsave(&nklock, s);
+
+	nholder = poppq(&synch->pendq, holder);
+
+	thread = link2thread(holder, plink);
+	thread->wchan = NULL;
+	trace_mark(xn_nucleus_synch_wakeup_this,
+		   "thread %p thread_name %s synch %p",
+		   thread, xnthread_name(thread), synch);
+	xnpod_resume_thread(thread, XNPEND);
+
+	xnlock_put_irqrestore(&nklock, s);
+
+	xnarch_post_graph_if(synch, 0, emptypq_p(&synch->pendq));
+
+	return nholder;
+}
+
 /*
  * xnsynch_renice_thread() -- This service is used by the PIP code to
  * raise/lower a thread's priority. The thread's base priority value
@@ -125,19 +334,20 @@ static void xnsynch_renice_thread(xnthre
 }
 
 /*! 
- * \fn void xnsynch_sleep_on(xnsynch_t *synch, xnticks_t timeout,
- *                           xntmode_t timeout_mode)
- *
- * \brief Sleep on a synchronization object.
- *
- * Makes the calling thread sleep on the specified synchronization
- * object, waiting for it to be signaled.
+ * \fn void xnsynch_acquire(xnsynch_t *synch, xnticks_t timeout,
+ *                          xntmode_t timeout_mode);
+ * \brief Acquire the ownership of a synchronization object.
  *
  * This service should be called by upper interfaces wanting the
- * current thread to pend on the given resource.
+ * current thread to acquire the ownership of the given resource. If
+ * the resource is already assigned to a thread, the caller is
+ * suspended.
+ *
+ * This service must be used only with synchronization objects that
+ * track ownership (XNSYNCH_OWNER set.
  *
  * @param synch The descriptor address of the synchronization object
- * to sleep on.
+ * to acquire.
  *
  * @param timeout The timeout which may be used to limit the time the
  * thread pends on the resource. This value is a wait time given in
@@ -158,36 +368,24 @@ static void xnsynch_renice_thread(xnthre
  * - Kernel-based task
  * - User-space task
  *
- * Rescheduling: always.
+ * Rescheduling: possible.
  *
  * @note The @a timeout value will be interpreted as jiffies if the
  * current thread is bound to a periodic time base (see
  * xnpod_init_thread), or nanoseconds otherwise.
  */
 
-void xnsynch_sleep_on(xnsynch_t *synch, xnticks_t timeout,
-		      xntmode_t timeout_mode)
+void xnsynch_acquire(xnsynch_t *synch, xnticks_t timeout,
+		     xntmode_t timeout_mode)
 {
 	xnthread_t *thread = xnpod_current_thread(), *owner;
 	spl_t s;
 
-	xnlock_get_irqsave(&nklock, s);
+	XENO_BUGON(NUCLEUS, !testbits(synch->status, XNSYNCH_OWNER));
 
-	trace_mark(xn_nucleus_synch_sleepon,
-		   "thread %p thread_name %s synch %p",
-		   thread, xnthread_name(thread), synch);
+	xnlock_get_irqsave(&nklock, s);
 
-	if (!testbits(synch->status, XNSYNCH_PRIO)) { /* i.e. FIFO */
-		appendpq(&synch->pendq, &thread->plink);
-		xnpod_suspend_thread(thread, XNPEND, timeout, timeout_mode, synch);
-		goto unlock_and_exit;
-	}
-
-	if (!testbits(synch->status, XNSYNCH_PIP)) { /* i.e. no ownership */
-		insertpqf(&synch->pendq, &thread->plink, thread->cprio);
-		xnpod_suspend_thread(thread, XNPEND, timeout, timeout_mode, synch);
-		goto unlock_and_exit;
-	}
+	trace_mark(xn_nucleus_synch_acquire, "synch %p", synch);
 
 redo:
 	owner = synch->owner;
@@ -198,6 +396,12 @@ redo:
 		goto unlock_and_exit;
 	}
 
+	if (!testbits(synch->status, XNSYNCH_PRIO)) { /* i.e. FIFO */
+		appendpq(&synch->pendq, &thread->plink);
+		xnpod_suspend_thread(thread, XNPEND, timeout, timeout_mode, synch);
+		goto unlock_and_exit;
+	}
+
 	if (thread->cprio > owner->cprio) {
 		if (xnthread_test_info(owner, XNWAKEN) && owner->wwake == synch) {
 			/* Ownership is still pending, steal the resource. */
@@ -207,19 +411,22 @@ redo:
 			goto unlock_and_exit;
 		}
 
-		if (!xnthread_test_state(owner, XNBOOST)) {
-			owner->bprio = owner->cprio;
-			xnthread_set_state(owner, XNBOOST);
-		}
+		insertpqf(&synch->pendq, &thread->plink, thread->cprio);
 
-		if (testbits(synch->status, XNSYNCH_CLAIMED))
-			removepq(&owner->claimq, &synch->link);
-		else
-			__setbits(synch->status, XNSYNCH_CLAIMED);
+		if (testbits(synch->status, XNSYNCH_PIP)) {
+			if (!xnthread_test_state(owner, XNBOOST)) {
+				owner->bprio = owner->cprio;
+				xnthread_set_state(owner, XNBOOST);
+			}
+
+			if (testbits(synch->status, XNSYNCH_CLAIMED))
+				removepq(&owner->claimq, &synch->link);
+			else
+				__setbits(synch->status, XNSYNCH_CLAIMED);
 
-		insertpqf(&owner->claimq, &synch->link, thread->cprio);
-		insertpqf(&synch->pendq, &thread->plink, thread->cprio);
-		xnsynch_renice_thread(owner, thread->cprio);
+			insertpqf(&owner->claimq, &synch->link, thread->cprio);
+			xnsynch_renice_thread(owner, thread->cprio);
+		}
 	} else
 		insertpqf(&synch->pendq, &thread->plink, thread->cprio);
 
@@ -335,17 +542,17 @@ void xnsynch_renice_sleeper(xnthread_t *
 	}
 }
 
-/*! 
- * \fn xnthread_t *xnsynch_wakeup_one_sleeper(xnsynch_t *synch);
+/*!
+ * \fn xnthread_t *xnsynch_release(xnsynch_t *synch);
  * \brief Give the resource ownership to the next waiting thread.
  *
- * This service gives the ownership of a synchronization object to the
- * thread which is currently leading the object's pending list. The
- * sleeping thread is unblocked, but no action is taken regarding the
- * previous owner of the resource.
+ * This service releases the ownership of the given synchronization
+ * object. The thread which is currently leading the object's pending
+ * list, if any, is unblocked from its pending state. However, no
+ * reschedule is performed.
  *
- * This service should be called by upper interfaces wanting to signal
- * the given resource so that a single waiter is resumed.
+ * This service must be used only with synchronization objects that
+ * track ownership (XNSYNCH_OWNER set.
  *
  * @param synch The descriptor address of the synchronization object
  * whose ownership is changed.
@@ -373,38 +580,41 @@ void xnsynch_renice_sleeper(xnthread_t *
  * Rescheduling: never.
  */
 
-xnthread_t *xnsynch_wakeup_one_sleeper(xnsynch_t *synch)
+struct xnthread *xnsynch_release(xnsynch_t *synch)
 {
-	xnthread_t *thread = NULL, *lastowner;
+	xnthread_t *newowner, *lastowner;
 	xnpholder_t *holder;
 	spl_t s;
 
+	XENO_BUGON(NUCLEUS, !testbits(synch->status, XNSYNCH_OWNER));
+
 	xnlock_get_irqsave(&nklock, s);
 
-	lastowner = synch->owner;
+	trace_mark(xn_nucleus_synch_release, "synch %p", synch);
+
 	holder = getpq(&synch->pendq);
 
 	if (holder) {
-		thread = link2thread(holder, plink);
-		thread->wchan = NULL;
-		thread->wwake = synch;
-		synch->owner = thread;
-		xnthread_set_info(thread, XNWAKEN);
-		trace_mark(xn_nucleus_synch_wakeup_one,
-			   "thread %p thread_name %s synch %p",
-			   thread, xnthread_name(thread), synch);
-		xnpod_resume_thread(thread, XNPEND);
-	} else
-		synch->owner = NULL;
+		newowner = link2thread(holder, plink);
+		newowner->wchan = NULL;
+		newowner->wwake = synch;
+		lastowner = synch->owner;
+		synch->owner = newowner;
+		xnthread_set_info(newowner, XNWAKEN);
+		xnpod_resume_thread(newowner, XNPEND);
 
-	if (testbits(synch->status, XNSYNCH_CLAIMED))
-		xnsynch_clear_boost(synch, lastowner);
+		if (testbits(synch->status, XNSYNCH_CLAIMED))
+			xnsynch_clear_boost(synch, lastowner);
+	} else {
+		newowner = NULL;
+		synch->owner = NULL;
+	}
 
 	xnlock_put_irqrestore(&nklock, s);
 
 	xnarch_post_graph_if(synch, 0, emptypq_p(&synch->pendq));
 
-	return thread;
+	return newowner;
 }
 
 /*! 
@@ -446,80 +656,6 @@ xnthread_t *xnsynch_peek_pendq(xnsynch_t
 }
 
 /*! 
- * \fn void xnsynch_wakeup_this_sleeper(xnsynch_t *synch, xnpholder_t *holder);
- * \brief Give the resource ownership to a given waiting thread.
- *
- * This service gives the ownership of a given synchronization object
- * to a specific thread which is currently pending on it. The sleeping
- * thread is unblocked from its pending state. No action is taken
- * regarding the previous resource owner.
- *
- * This service should be called by upper interfaces wanting to signal
- * the given resource so that a specific waiter is resumed.
- *
- * @param synch The descriptor address of the synchronization object
- * whose ownership is changed.
- *
- * @param holder The link holder address of the thread to unblock
- * (&thread->plink) which MUST be currently linked to the
- * synchronization object's pending queue (i.e. synch->pendq).
- *
- * @return The link address of the unblocked thread in the
- * synchronization object's pending queue.
- *
- * Side-effects:
- *
- * - The effective priority of the previous resource owner might be
- * lowered to its base priority value as a consequence of the priority
- * inheritance boost being cleared.
- *
- * - The synchronization object ownership is transfered to the
- * unblocked thread.
- *
- * Environments:
- *
- * This service can be called from:
- *
- * - Kernel module initialization/cleanup code
- * - Interrupt service routine
- * - Kernel-based task
- * - User-space task
- *
- * Rescheduling: never.
- */
-
-xnpholder_t *xnsynch_wakeup_this_sleeper(xnsynch_t *synch, xnpholder_t *holder)
-{
-	xnthread_t *thread, *lastowner;
-	xnpholder_t *nholder;
-	spl_t s;
-
-	xnlock_get_irqsave(&nklock, s);
-
-	lastowner = synch->owner;
-	nholder = poppq(&synch->pendq, holder);
-
-	thread = link2thread(holder, plink);
-	thread->wchan = NULL;
-	thread->wwake = synch;
-	synch->owner = thread;
-	xnthread_set_info(thread, XNWAKEN);
-	trace_mark(xn_nucleus_synch_wakeup_all,
-		   "thread %p thread_name %s synch %p",
-		   thread, xnthread_name(thread), synch);
-	xnpod_resume_thread(thread, XNPEND);
-
-	if (testbits(synch->status, XNSYNCH_CLAIMED))
-		xnsynch_clear_boost(synch, lastowner);
-
-	xnlock_put_irqrestore(&nklock, s);
-
-	xnarch_post_graph_if(synch, 0, emptypq_p(&synch->pendq));
-
-	return nholder;
-}
-
-/*! 
  * \fn void xnsynch_flush(xnsynch_t *synch, xnflags_t reason);
  * \brief Unblock all waiters pending on a resource.
  *
@@ -679,12 +815,12 @@ void xnsynch_release_all_ownerships(xnth
 
 	for (holder = getheadpq(&thread->claimq); holder != NULL;
 	     holder = nholder) {
-		/* Since xnsynch_wakeup_one_sleeper() alters the claim
+		/* Since xnsynch_release() alters the claim
 		   queue, we need to be conservative while scanning
 		   it. */
 		xnsynch_t *synch = link2synch(holder);
 		nholder = nextpq(&thread->claimq, holder);
-		xnsynch_wakeup_one_sleeper(synch);
+		xnsynch_release(synch);
 		if (synch->cleanup)
 			synch->cleanup(synch);
 	}
@@ -701,3 +837,5 @@ EXPORT_SYMBOL(xnsynch_sleep_on);
 EXPORT_SYMBOL(xnsynch_wakeup_one_sleeper);
 EXPORT_SYMBOL(xnsynch_wakeup_this_sleeper);
 EXPORT_SYMBOL(xnsynch_peek_pendq);
+EXPORT_SYMBOL(xnsynch_acquire);
+EXPORT_SYMBOL(xnsynch_release);
Index: b/include/rtdm/rtdm_driver.h
===================================================================
--- a/include/rtdm/rtdm_driver.h
+++ b/include/rtdm/rtdm_driver.h
@@ -1134,7 +1134,7 @@ static inline void rtdm_mutex_unlock(rtd
 
 	trace_mark(xn_rtdm_mutex_unlock, "mutex %p", mutex);
 
-	if (unlikely(xnsynch_wakeup_one_sleeper(&mutex->synch_base) != NULL))
+	if (unlikely(xnsynch_release(&mutex->synch_base) != NULL))
 		xnpod_schedule();
 }
 
Index: b/ksrc/skins/native/cond.c
===================================================================
--- a/ksrc/skins/native/cond.c
+++ b/ksrc/skins/native/cond.c
@@ -421,7 +421,7 @@ int rt_cond_wait_inner(RT_COND *cond, RT
 
 	mutex->lockcnt = 0;
 
-	if (xnsynch_wakeup_one_sleeper(&mutex->synch_base)) {
+	if (xnsynch_release(&mutex->synch_base)) {
 		mutex->lockcnt = 1;
 		/* Scheduling deferred */
 	}
Index: b/ksrc/skins/native/mutex.c
===================================================================
--- a/ksrc/skins/native/mutex.c
+++ b/ksrc/skins/native/mutex.c
@@ -170,7 +170,8 @@ int rt_mutex_create(RT_MUTEX *mutex, con
 	if (xnpod_asynch_p())
 		return -EPERM;
 
-	xnsynch_init(&mutex->synch_base, XNSYNCH_PRIO | XNSYNCH_PIP);
+	xnsynch_init(&mutex->synch_base,
+		     XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER);
 	mutex->handle = 0;	/* i.e. (still) unregistered mutex. */
 	mutex->magic = XENO_MUTEX_MAGIC;
 	mutex->lockcnt = 0;
@@ -309,7 +310,7 @@ int rt_mutex_acquire_inner(RT_MUTEX *mut
 		goto unlock_and_exit;
 	}
 
-	xnsynch_sleep_on(&mutex->synch_base, timeout, timeout_mode);
+	xnsynch_acquire(&mutex->synch_base, timeout, timeout_mode);
 
 	if (xnthread_test_info(thread, XNRMID))
 		err = -EIDRM;	/* Mutex deleted while pending. */
@@ -523,7 +524,7 @@ int rt_mutex_release(RT_MUTEX *mutex)
 	if (--mutex->lockcnt > 0)
 		goto unlock_and_exit;
 
-	if (xnsynch_wakeup_one_sleeper(&mutex->synch_base)) {
+	if (xnsynch_release(&mutex->synch_base)) {
 		mutex->lockcnt = 1;
 		xnpod_schedule();
 	}
Index: b/ksrc/skins/native/task.c
===================================================================
--- a/ksrc/skins/native/task.c
+++ b/ksrc/skins/native/task.c
@@ -269,7 +269,8 @@ int rt_task_create(RT_TASK *task,
 
 #ifdef CONFIG_XENO_OPT_NATIVE_MPS
 	xnsynch_init(&task->mrecv, XNSYNCH_FIFO);
-	xnsynch_init(&task->msendq, XNSYNCH_PRIO | XNSYNCH_PIP);
+	xnsynch_init(&task->msendq,
+		     XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER);
 	xnsynch_set_owner(&task->msendq, &task->thread_base);
 	task->flowgen = 0;
 #endif /* CONFIG_XENO_OPT_NATIVE_MPS */
@@ -1773,7 +1774,7 @@ ssize_t rt_task_send(RT_TASK *task,
 	   client in the case required by the priority inheritance
 	   protocol (i.e. prio(client) > prio(server)). */
 
-	xnsynch_sleep_on(&task->msendq, timeout, XN_RELATIVE);
+	xnsynch_acquire(&task->msendq, timeout, XN_RELATIVE);
 
 	/* At this point, the server task might have exited right
 	 * after having replied to us, so do not make optimistic
Index: b/ksrc/skins/posix/cond.c
===================================================================
--- a/ksrc/skins/posix/cond.c
+++ b/ksrc/skins/posix/cond.c
@@ -240,7 +240,7 @@ static inline int mutex_save_count(xnthr
 		   xnthread_handle(cur)))
 		return 0;
 
-	owner = xnsynch_wakeup_one_sleeper(&mutex->synchbase);
+	owner = xnsynch_release(&mutex->synchbase);
 	xnarch_atomic_set(mutex->owner,
 			  set_claimed(xnthread_handle(owner),
 				      xnsynch_nsleepers(&mutex->synchbase)));
Index: b/ksrc/skins/posix/mutex.c
===================================================================
--- a/ksrc/skins/posix/mutex.c
+++ b/ksrc/skins/posix/mutex.c
@@ -85,7 +85,7 @@ int pse51_mutex_init_internal(struct __s
 			      xnarch_atomic_t *ownerp,
 			      const pthread_mutexattr_t *attr)
 {
-	xnflags_t synch_flags = XNSYNCH_PRIO | XNSYNCH_NOPIP;
+	xnflags_t synch_flags = XNSYNCH_PRIO | XNSYNCH_OWNER;
 	struct xnsys_ppd *sys_ppd;
 	pse51_kqueues_t *kq;
 	spl_t s;
@@ -307,11 +307,11 @@ int pse51_mutex_timedlock_break(struct _
 		for (;;) {
 			++mutex->sleepers;
 			if (timed)
-				xnsynch_sleep_on(&mutex->synchbase,
-						 abs_to, XN_REALTIME);
+				xnsynch_acquire(&mutex->synchbase,
+						abs_to, XN_REALTIME);
 			else
-				xnsynch_sleep_on(&mutex->synchbase,
-						 XN_INFINITE, XN_RELATIVE);
+				xnsynch_acquire(&mutex->synchbase,
+						XN_INFINITE, XN_RELATIVE);
 			--mutex->sleepers;
 
 			if (xnthread_test_info(cur, XNBREAK)) {
Index: b/ksrc/skins/posix/mutex.h
===================================================================
--- a/ksrc/skins/posix/mutex.h
+++ b/ksrc/skins/posix/mutex.h
@@ -170,9 +170,9 @@ static inline int pse51_mutex_timedlock_
 	xnsynch_set_owner(&mutex->synchbase, owner);
 	++mutex->sleepers;
 	if (timed)
-		xnsynch_sleep_on(&mutex->synchbase, abs_to, XN_REALTIME);
+		xnsynch_acquire(&mutex->synchbase, abs_to, XN_REALTIME);
 	else
-		xnsynch_sleep_on(&mutex->synchbase, XN_INFINITE, XN_RELATIVE);
+		xnsynch_acquire(&mutex->synchbase, XN_INFINITE, XN_RELATIVE);
 	--mutex->sleepers;
 
 	if (xnthread_test_info(cur, XNBREAK)) {
@@ -216,7 +216,7 @@ static inline void pse51_mutex_unlock_in
 		return;
 
 	xnlock_get_irqsave(&nklock, s);
-	owner = xnsynch_wakeup_one_sleeper(&mutex->synchbase);
+	owner = xnsynch_release(&mutex->synchbase);
 	ownerh = set_claimed(xnthread_handle(owner), mutex->sleepers);
 	xnarch_atomic_set(mutex->owner, ownerh);
 	if (owner)
Index: b/ksrc/skins/rtai/sem.c
===================================================================
--- a/ksrc/skins/rtai/sem.c
+++ b/ksrc/skins/rtai/sem.c
@@ -28,7 +28,7 @@ void rt_typed_sem_init(SEM * sem, int va
 	int mode = XNSYNCH_PRIO;
 
 	if ((type & RES_SEM) == RES_SEM) {
-		mode |= XNSYNCH_PIP;
+		mode |= XNSYNCH_PIP | XNSYNCH_OWNER;
 		value = 0;	/* We will use this as a lock count. */
 	} else {
 		if ((type & BIN_SEM) && value > 1)
@@ -98,7 +98,7 @@ int rt_sem_signal(SEM * sem)
 			goto unlock_and_exit;
 
 		sem->owner =
-		    thread2rtask(xnsynch_wakeup_one_sleeper(&sem->synch_base));
+		    thread2rtask(xnsynch_release(&sem->synch_base));
 
 		if (sem->owner != NULL)
 			xnpod_schedule();
@@ -141,12 +141,12 @@ int rt_sem_wait(SEM * sem)
 			err = ++sem->count;
 			goto unlock_and_exit;
 		}
+		xnsynch_acquire(&sem->synch_base, XN_INFINITE, XN_RELATIVE);
 	} else if (sem->count > 0) {
 		err = sem->count--;
 		goto unlock_and_exit;
-	}
-
-	xnsynch_sleep_on(&sem->synch_base, XN_INFINITE, XN_RELATIVE);
+	} else
+		xnsynch_sleep_on(&sem->synch_base, XN_INFINITE, XN_RELATIVE);
 
 	if (xnthread_test_info(&task->thread_base, XNRMID))
 		err = SEM_ERR;	/* Semaphore deleted while pending. */
Index: b/ksrc/skins/rtdm/drvlib.c
===================================================================
--- a/ksrc/skins/rtdm/drvlib.c
+++ b/ksrc/skins/rtdm/drvlib.c
@@ -1390,7 +1390,8 @@ void rtdm_mutex_init(rtdm_mutex_t *mutex
 	/* Make atomic for re-initialisation support */
 	xnlock_get_irqsave(&nklock, s);
 
-	xnsynch_init(&mutex->synch_base, XNSYNCH_PRIO | XNSYNCH_PIP);
+	xnsynch_init(&mutex->synch_base,
+		     XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER);
 
 	xnlock_put_irqrestore(&nklock, s);
 }
@@ -1534,14 +1535,14 @@ int rtdm_mutex_timedlock(rtdm_mutex_t *m
 restart:
 		if (timeout_seq && (timeout > 0)) {
 			/* timeout sequence */
-			xnsynch_sleep_on(&mutex->synch_base, *timeout_seq,
-					 XN_ABSOLUTE);
+			xnsynch_acquire(&mutex->synch_base, *timeout_seq,
+					XN_ABSOLUTE);
 		} else {
 			/* infinite or relative timeout */
-			xnsynch_sleep_on(&mutex->synch_base,
-					 xntbase_ns2ticks_ceil
-					 (xnthread_time_base(curr_thread),
-					  timeout), XN_RELATIVE);
+			xnsynch_acquire(&mutex->synch_base,
+					xntbase_ns2ticks_ceil
+					(xnthread_time_base(curr_thread),
+					 timeout), XN_RELATIVE);
 		}
 
 		if (unlikely(xnthread_test_info(curr_thread,
Index: b/ksrc/skins/vrtx/mx.c
===================================================================
--- a/ksrc/skins/vrtx/mx.c
+++ b/ksrc/skins/vrtx/mx.c
@@ -161,7 +161,7 @@ int sc_mcreate(unsigned int opt, int *er
 	inith(&mx->link);
 	mx->mid = mid;
 	mx->owner = NULL;
-	xnsynch_init(&mx->synchbase, bflags | XNSYNCH_DREORD);
+	xnsynch_init(&mx->synchbase, bflags | XNSYNCH_DREORD | XNSYNCH_OWNER);
 
 	xnlock_get_irqsave(&nklock, s);
 	appendq(&vrtx_mx_q, &mx->link);
@@ -192,7 +192,7 @@ void sc_mpost(int mid, int *errp)
 	}
 
 	/* Undefined behaviour if the poster does not own the mutex. */
-	mx->owner = xnsynch_wakeup_one_sleeper(&mx->synchbase);
+	mx->owner = xnsynch_release(&mx->synchbase);
 
 	*errp = RET_OK;
 
@@ -267,7 +267,7 @@ void sc_mpend(int mid, unsigned long tim
 		if (timeout)
 			task->vrtxtcb.TCBSTAT |= TBSDELAY;
 
-		xnsynch_sleep_on(&mx->synchbase, timeout, XN_RELATIVE);
+		xnsynch_acquire(&mx->synchbase, timeout, XN_RELATIVE);
 
 		if (xnthread_test_info(&task->threadbase, XNBREAK))
 			*errp = -EINTR;
Index: b/ksrc/skins/vxworks/semLib.c
===================================================================
--- a/ksrc/skins/vxworks/semLib.c
+++ b/ksrc/skins/vxworks/semLib.c
@@ -138,7 +138,7 @@ SEM_ID semCCreate(int flags, int count)
 
 SEM_ID semMCreate(int flags)
 {
-	int bflags = 0;
+	int bflags = XNSYNCH_OWNER;
 
 	error_check(flags & ~WIND_SEMM_OPTION_MASK, S_semLib_INVALID_QUEUE_TYPE,
 		    return 0);
@@ -346,7 +346,7 @@ static STATUS semm_take(wind_sem_t *sem,
 	error_check(to == XN_NONBLOCK, S_objLib_OBJ_UNAVAILABLE,
 		    return ERROR);
 
-	xnsynch_sleep_on(&sem->synchbase, to, XN_RELATIVE);
+	xnsynch_acquire(&sem->synchbase, to, XN_RELATIVE);
 
 	error_check(xnthread_test_info(cur, XNBREAK),
 		    -EINTR, return ERROR);
@@ -385,7 +385,7 @@ static STATUS semm_give(wind_sem_t *sem)
 	if (--sem->count > 0)
 		return OK;
 
-	if (xnsynch_wakeup_one_sleeper(&sem->synchbase)) {
+	if (xnsynch_release(&sem->synchbase)) {
 		sem->count = 1;
 		resched = 1;
 	}



^ permalink raw reply	[flat|nested] 50+ messages in thread

* [Xenomai-core] [PATCH 06/12] Lockless fast path for xnsynch_acquire/release
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
                   ` (4 preceding siblings ...)
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 05/12] Factor out xnsynch_acquire/release Jan Kiszka
@ 2008-10-16 15:46 ` Jan Kiszka
  2008-10-16 19:57   ` Gilles Chanteperdrix
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 07/12] Convert POSIX skin to fast xnsynch Jan Kiszka
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 15:46 UTC (permalink / raw)
  To: xenomai; +Cc: Jan Kiszka

[-- Attachment #1: fast-xnsynch.patch --]
[-- Type: text/plain, Size: 54837 bytes --]

This patch adds optional lockless fast paths to xnsynch_acquire and
xnsynch_release. Those paths are considered if CONFIG_XENO_FASTSYNC
is defined and the owner-tracking xnsynch object is given a non-NULL
reference to an atomic fastlock variable on initialization. This allows
for a smooth migration of existing mutex implementations in Xenomai
skins to a fast xnsynch scheme.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 configure.in                      |   16 ++--
 include/asm-generic/bits/bind.h   |   16 ++--
 include/asm-generic/features.h    |   24 +++---
 include/nucleus/synch.h           |   54 ++++++++++++++-
 ksrc/arch/arm/Kconfig             |    2 
 ksrc/arch/powerpc/Kconfig         |    2 
 ksrc/arch/x86/Kconfig             |    2 
 ksrc/drivers/testing/switchtest.c |    2 
 ksrc/nucleus/pipe.c               |    2 
 ksrc/nucleus/registry.c           |    4 -
 ksrc/nucleus/select.c             |    2 
 ksrc/nucleus/synch.c              |  132 ++++++++++++++++++++++++++++++++------
 ksrc/skins/native/Kconfig         |    2 
 ksrc/skins/native/alarm.c         |    2 
 ksrc/skins/native/buffer.c        |    4 -
 ksrc/skins/native/cond.c          |    2 
 ksrc/skins/native/event.c         |    2 
 ksrc/skins/native/heap.c          |    2 
 ksrc/skins/native/intr.c          |    2 
 ksrc/skins/native/mutex.c         |    2 
 ksrc/skins/native/queue.c         |    2 
 ksrc/skins/native/sem.c           |    2 
 ksrc/skins/native/task.c          |    6 -
 ksrc/skins/posix/Kconfig          |    2 
 ksrc/skins/posix/cb_lock.h        |    6 -
 ksrc/skins/posix/cond.c           |   18 ++---
 ksrc/skins/posix/intr.c           |    2 
 ksrc/skins/posix/mq.c             |    4 -
 ksrc/skins/posix/mutex.c          |   12 +--
 ksrc/skins/posix/mutex.h          |    4 -
 ksrc/skins/posix/sem.c            |    2 
 ksrc/skins/posix/syscall.c        |   20 ++---
 ksrc/skins/posix/thread.c         |    6 -
 ksrc/skins/psos+/Kconfig          |    2 
 ksrc/skins/psos+/event.c          |    2 
 ksrc/skins/psos+/queue.c          |    2 
 ksrc/skins/psos+/rn.c             |    2 
 ksrc/skins/psos+/sem.c            |    2 
 ksrc/skins/rtai/Kconfig           |    2 
 ksrc/skins/rtai/sem.c             |    2 
 ksrc/skins/rtai/task.c            |    4 -
 ksrc/skins/rtdm/drvlib.c          |   10 +-
 ksrc/skins/uitron/Kconfig         |    2 
 ksrc/skins/uitron/flag.c          |    2 
 ksrc/skins/uitron/mbx.c           |    3 
 ksrc/skins/uitron/sem.c           |    3 
 ksrc/skins/uitron/task.c          |    4 -
 ksrc/skins/vrtx/Kconfig           |    2 
 ksrc/skins/vrtx/event.c           |    2 
 ksrc/skins/vrtx/mb.c              |    2 
 ksrc/skins/vrtx/mx.c              |    3 
 ksrc/skins/vrtx/queue.c           |    2 
 ksrc/skins/vrtx/sem.c             |    2 
 ksrc/skins/vxworks/Kconfig        |    2 
 ksrc/skins/vxworks/module.c       |    2 
 ksrc/skins/vxworks/msgQLib.c      |    2 
 ksrc/skins/vxworks/semLib.c       |    2 
 ksrc/skins/vxworks/syscall.c      |    2 
 ksrc/skins/vxworks/taskLib.c      |    2 
 src/skins/posix/mutex.c           |   42 ++++++------
 60 files changed, 309 insertions(+), 162 deletions(-)

Index: b/configure.in
===================================================================
--- a/configure.in
+++ b/configure.in
@@ -59,27 +59,27 @@ AM_PROG_LEX
 
 AC_MSG_CHECKING([for target architecture])
 
-CONFIG_XENO_FASTSEM=
+CONFIG_XENO_FASTSYNCH=
 case "$host" in
  i*86*-*)
 	XENO_TARGET_ARCH=x86
         XENO_LINUX_ARCH=i386
 	XENO_LINUX_INSTALL_TARGET=install
-	CONFIG_XENO_FASTSEM=y
+	CONFIG_XENO_FASTSYNCH=y
         ;;
  powerpc-*|ppc-*)
 	XENO_TARGET_ARCH=powerpc
         XENO_LINUX_ARCH=ppc
 	XENO_LINUX_INSTALL_TARGET=install_image
 	XENO_LINUX_IMAGE=arch/ppc/boot/images/zImage.elf
-	CONFIG_XENO_FASTSEM=y
+	CONFIG_XENO_FASTSYNCH=y
         ;;
  powerpc64-*|ppc64-*)
 	XENO_TARGET_ARCH=powerpc
         XENO_LINUX_ARCH=ppc64
 	XENO_LINUX_INSTALL_TARGET=install_image
 	XENO_LINUX_IMAGE=arch/ppc64/boot/images/zImage
-	CONFIG_XENO_FASTSEM=y
+	CONFIG_XENO_FASTSYNCH=y
         ;;
  ia64-*)
 	XENO_TARGET_ARCH=ia64
@@ -96,14 +96,14 @@ case "$host" in
  	XENO_LINUX_ARCH=arm
 	XENO_LINUX_INSTALL_TARGET=install_image
 	XENO_LINUX_IMAGE=arch/arm/boot/zImage
-	# We set CONFIG_XENO_FASTSEM later, when we know what architecture we
+	# We set CONFIG_XENO_FASTSYNCH later, when we know what architecture we
 	# are running
 	;;
  x86_64-*|amd64-*)
 	XENO_TARGET_ARCH=x86
         XENO_LINUX_ARCH=x86_64
 	XENO_LINUX_INSTALL_TARGET=install
-	CONFIG_XENO_FASTSEM=y
+	CONFIG_XENO_FASTSYNCH=y
         ;;
  *) echo ""
    echo "*******************************************"
@@ -288,7 +288,7 @@ user-space]),
   AC_MSG_RESULT(${CONFIG_XENO_ARM_EABI:-no})
 
   if test $CONFIG_XENO_ARM_ARCH -ge 6 || test x$CONFIG_SMP != xy; then
-	CONFIG_XENO_FASTSEM=y
+	CONFIG_XENO_FASTSYNCH=y
   fi
 fi
 
@@ -570,7 +570,7 @@ dnl
 
 test x$CONFIG_XENO_X86_SEP = xy && AC_DEFINE(CONFIG_XENO_X86_SEP,1,[config])
 test x$CONFIG_SMP = xy && AC_DEFINE(CONFIG_SMP,1,[config])
-test x$CONFIG_XENO_FASTSEM = xy && AC_DEFINE(CONFIG_XENO_FASTSEM,1,[config])
+test x$CONFIG_XENO_FASTSYNCH = xy && AC_DEFINE(CONFIG_XENO_FASTSYNCH,1,[config])
 test x$CONFIG_X86_TSC = xy && AC_DEFINE(CONFIG_X86_TSC,1,[config])
 test -n "$CONFIG_XENO_ARM_ARCH" && AC_DEFINE_UNQUOTED(CONFIG_XENO_ARM_ARCH,$CONFIG_XENO_ARM_ARCH,[config])
 
Index: b/include/asm-generic/bits/bind.h
===================================================================
--- a/include/asm-generic/bits/bind.h
+++ b/include/asm-generic/bits/bind.h
@@ -43,14 +43,14 @@ static void init_current_key(void)
 	}
 }
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 __attribute__ ((weak))
 unsigned long xeno_sem_heap[2] = { 0, 0 };
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 void xeno_handle_mlock_alert(int sig);
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 static void *map_sem_heap(unsigned shared)
 {
 	struct heap_info {
@@ -104,7 +104,7 @@ static void unmap_sem_heap(unsigned long
 
 	munmap((void *) heap_addr, hinfo.size);
 }
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 void __attribute__((weak)) xeno_sigill_handler(int sig)
 {
@@ -177,7 +177,7 @@ xeno_bind_skin(unsigned skin_magic, cons
 
 	pthread_once(&xeno_init_current_key_once, &init_current_key);
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	/* In case we forked, we need to map the new local semaphore heap */
 	if (xeno_sem_heap[0])
 		unmap_sem_heap(xeno_sem_heap[0], 0);
@@ -196,7 +196,7 @@ xeno_bind_skin(unsigned skin_magic, cons
 			exit(EXIT_FAILURE);
 		}
 	}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	return muxid;
 }
@@ -253,7 +253,7 @@ xeno_bind_skin_opt(unsigned skin_magic,
 
 	pthread_once(&xeno_init_current_key_once, &init_current_key);
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	/* In case we forked, we need to map the new local semaphore heap */
 	if (xeno_sem_heap[0])
 		unmap_sem_heap(xeno_sem_heap[0], 0);
@@ -272,7 +272,7 @@ xeno_bind_skin_opt(unsigned skin_magic,
 			exit(EXIT_FAILURE);
 		}
 	}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	return muxid;
 }
Index: b/include/asm-generic/features.h
===================================================================
--- a/include/asm-generic/features.h
+++ b/include/asm-generic/features.h
@@ -25,9 +25,9 @@
 #include <xeno_config.h>
 #endif /* __KERNEL__ */
 
-#define __xn_feat_smp       0x80000000
-#define __xn_feat_fastsem   0x40000000
-#define __xn_feat_nofastsem 0x20000000
+#define __xn_feat_smp         0x80000000
+#define __xn_feat_fastsynch   0x40000000
+#define __xn_feat_nofastsynch 0x20000000
 
 #ifdef CONFIG_SMP
 #define __xn_feat_smp_mask __xn_feat_smp
@@ -35,25 +35,25 @@
 #define __xn_feat_smp_mask 0
 #endif
 
-#ifdef CONFIG_XENO_FASTSEM
-#define __xn_feat_fastsem_mask __xn_feat_fastsem
+#ifdef CONFIG_XENO_FASTSYNCH
+#define __xn_feat_fastsynch_mask __xn_feat_fastsynch
 #else
-#define __xn_feat_fastsem_mask __xn_feat_nofastsem
+#define __xn_feat_fastsynch_mask __xn_feat_nofastsynch
 #endif
 
-#define __xn_feat_generic_mask     (__xn_feat_smp_mask | __xn_feat_fastsem_mask)
+#define __xn_feat_generic_mask     (__xn_feat_smp_mask | __xn_feat_fastsynch_mask)
 
-#define __xn_feat_generic_man_mask (__xn_feat_fastsem | __xn_feat_nofastsem)
+#define __xn_feat_generic_man_mask (__xn_feat_fastsynch | __xn_feat_nofastsynch)
 
 static inline const char *get_generic_feature_label (unsigned feature)
 {
     switch (feature) {
     	case __xn_feat_smp:
 	    return "smp";
-        case __xn_feat_fastsem:
-	    return "fastsem";
-        case __xn_feat_nofastsem:
-	    return "nofastsem";
+        case __xn_feat_fastsynch:
+	    return "fastsynch";
+        case __xn_feat_nofastsynch:
+	    return "nofastsynch";
     	default:
 	    return 0;
     }
Index: b/include/nucleus/synch.h
===================================================================
--- a/include/nucleus/synch.h
+++ b/include/nucleus/synch.h
@@ -32,10 +32,42 @@
 #define XNSYNCH_DREORD  0x4
 #define XNSYNCH_OWNER   0x8
 
+/* Fast lock API */
+static inline int xnsynch_fast_owner_check(xnarch_atomic_t *fastlock,
+					   xnhandle_t ownerh)
+{
+	return (xnhandle_mask_spare(xnarch_atomic_get(fastlock)) == ownerh) ?
+		0 : -EPERM;
+}
+
+static inline int xnsynch_fast_acquire(xnarch_atomic_t *fastlock,
+				       xnhandle_t new_ownerh)
+{
+	xnhandle_t lock_state =
+	    xnarch_atomic_cmpxchg(fastlock, XN_NO_HANDLE, new_ownerh);
+
+	if (likely(lock_state == XN_NO_HANDLE))
+		return 0;
+
+	if (xnhandle_mask_spare(lock_state) == new_ownerh)
+		return -EBUSY;
+
+	return -EAGAIN;
+}
+
+static inline int xnsynch_fast_release(xnarch_atomic_t *fastlock,
+				       xnhandle_t cur_ownerh)
+{
+	return (xnarch_atomic_cmpxchg(fastlock, cur_ownerh, XN_NO_HANDLE) ==
+		cur_ownerh);
+}
+
 #if defined(__KERNEL__) || defined(__XENO_SIM__)
 
 #define XNSYNCH_CLAIMED 0x10	/* Claimed by other thread(s) w/ PIP */
 
+#define XNSYNCH_FLCLAIM XN_HANDLE_SPARE3 /* Corresponding bit in fast lock */
+
 /* Spare flags usable by upper interfaces */
 #define XNSYNCH_SPARE0  0x01000000
 #define XNSYNCH_SPARE1  0x02000000
@@ -67,6 +99,10 @@ typedef struct xnsynch {
 
     struct xnthread *owner; /* Thread which owns the resource */
 
+#ifdef CONFIG_XENO_FASTSYNCH
+    xnarch_atomic_t *fastlock; /* Pointer to fast lock word */
+#endif /* CONFIG_XENO_FASTSYNCH */
+
     void (*cleanup)(struct xnsynch *synch); /* Cleanup handler */
 
     XNARCH_DECL_DISPLAY_CONTEXT();
@@ -81,12 +117,26 @@ typedef struct xnsynch {
 #define xnsynch_pended_p(synch)		(!emptypq_p(&((synch)->pendq)))
 #define xnsynch_owner(synch)		((synch)->owner)
 
+#ifdef CONFIG_XENO_FASTSYNCH
+#define xnsynch_fastlock(synch)		((synch)->fastlock)
+#define xnsynch_fastlock_p(synch)	((synch)->fastlock != NULL)
+#else /* !CONFIG_XENO_FASTSYNCH */
+#define xnsynch_fastlock(synch)		NULL
+#define xnsynch_fastlock_p(synch)	0
+#endif /* !CONFIG_XENO_FASTSYNCH */
+
+#define xnsynch_fast_is_claimed(fastlock) \
+	xnhandle_test_spare(fastlock, XNSYNCH_FLCLAIM)
+#define xnsynch_fast_set_claimed(fastlock, enable) \
+	(((fastlock) & ~XNSYNCH_FLCLAIM) | ((enable) ? XNSYNCH_FLCLAIM : 0))
+#define xnsynch_fast_mask_claimed(fastlock) ((fastlock) & ~XNSYNCH_FLCLAIM)
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-void xnsynch_init(xnsynch_t *synch,
-		  xnflags_t flags);
+void xnsynch_init(xnsynch_t *synch, xnflags_t flags,
+		  xnarch_atomic_t *fastlock);
 
 #define xnsynch_destroy(synch) xnsynch_flush(synch,XNRMID)
 
Index: b/ksrc/arch/arm/Kconfig
===================================================================
--- a/ksrc/arch/arm/Kconfig
+++ b/ksrc/arch/arm/Kconfig
@@ -2,7 +2,7 @@ config XENO_GENERIC_STACKPOOL
 	bool
 	default y
 
-config XENO_FASTSEM
+config XENO_FASTSYNCH
 	bool
 	default y if (CPU_32v3 || CPU_32v4T || CPU_32v5) && !SMP || CPU_32v6 || CPU_32v7
 
Index: b/ksrc/arch/powerpc/Kconfig
===================================================================
--- a/ksrc/arch/powerpc/Kconfig
+++ b/ksrc/arch/powerpc/Kconfig
@@ -2,7 +2,7 @@ config XENO_GENERIC_STACKPOOL
 	bool
 	default y
 
-config XENO_FASTSEM
+config XENO_FASTSYNCH
 	bool
 	default y
 
Index: b/ksrc/arch/x86/Kconfig
===================================================================
--- a/ksrc/arch/x86/Kconfig
+++ b/ksrc/arch/x86/Kconfig
@@ -2,7 +2,7 @@ config XENO_GENERIC_STACKPOOL
 	bool
 	default y
 
-config XENO_FASTSEM
+config XENO_FASTSYNCH
 	bool
 	default y
 
Index: b/ksrc/skins/native/Kconfig
===================================================================
--- a/ksrc/skins/native/Kconfig
+++ b/ksrc/skins/native/Kconfig
@@ -1,6 +1,6 @@
 menuconfig XENO_SKIN_NATIVE
 	depends on XENO_OPT_NUCLEUS
-	select XENO_OPT_REGISTRY if XENO_FASTSEM
+	select XENO_OPT_REGISTRY if XENO_FASTSYNCH
 	tristate "Native API"
 	default y
 	help
Index: b/ksrc/skins/posix/Kconfig
===================================================================
--- a/ksrc/skins/posix/Kconfig
+++ b/ksrc/skins/posix/Kconfig
@@ -1,6 +1,6 @@
 menuconfig XENO_SKIN_POSIX
 	depends on XENO_OPT_NUCLEUS 
-	select XENO_OPT_REGISTRY if XENO_FASTSEM
+	select XENO_OPT_REGISTRY if XENO_FASTSYNCH
 	tristate "POSIX API"
 	default y
 	help
Index: b/ksrc/skins/posix/cb_lock.h
===================================================================
--- a/ksrc/skins/posix/cb_lock.h
+++ b/ksrc/skins/posix/cb_lock.h
@@ -20,7 +20,7 @@ typedef void xnthread_t;
 	__tmp; \
 })
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 
 static  __inline__ int __cb_try_read_lock(xnarch_atomic_t *lock)
 {
@@ -68,7 +68,7 @@ static __inline__ void __cb_write_unlock
 #define cb_try_write_lock(lock, flags) __cb_try_write_lock(lock)
 #define cb_force_write_lock(lock, flags) __cb_force_write_lock(lock)
 #define cb_write_unlock(lock, flags) __cb_write_unlock(lock)
-#else /* !CONFIG_XENO_FASTSEM */
+#else /* !CONFIG_XENO_FASTSYNCH */
 #ifdef __KERNEL__
 #define DECLARE_CB_LOCK_FLAGS(name) spl_t name
 #define cb_try_read_lock(lock, flags) \
@@ -87,6 +87,6 @@ static __inline__ void __cb_write_unlock
 #define cb_force_write_lock(lock, flags) do { } while (0)
 #define cb_write_unlock(lock, flags) do { } while (0)
 #endif /* !__KERNEL__ */
-#endif /* !CONFIG_XENO_FASTSEM */
+#endif /* !CONFIG_XENO_FASTSYNCH */
 
 #endif /* CB_LOCK_H */
Index: b/ksrc/skins/posix/cond.c
===================================================================
--- a/ksrc/skins/posix/cond.c
+++ b/ksrc/skins/posix/cond.c
@@ -142,7 +142,7 @@ int pthread_cond_init(pthread_cond_t * c
 	shadow->magic = PSE51_COND_MAGIC;
 	shadow->cond = cond;
 
-	xnsynch_init(&cond->synchbase, synch_flags);
+	xnsynch_init(&cond->synchbase, synch_flags, NULL);
 	inith(&cond->link);
 	cond->attr = *attr;
 	cond->mutex = NULL;
@@ -424,10 +424,10 @@ int pthread_cond_wait(pthread_cond_t * c
 	unsigned count;
 	int err;
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	if (unlikely(cb_try_read_lock(&mutex->lock, s)))
 		return EINVAL;
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	err = pse51_cond_timedwait_prologue(cur, cond, mutex,
 					    &count, 0, XN_INFINITE);
@@ -437,9 +437,9 @@ int pthread_cond_wait(pthread_cond_t * c
 							      mutex, count))
 			;
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	cb_read_unlock(&mutex->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	return err != EINTR ? err : 0;
 }
@@ -492,10 +492,10 @@ int pthread_cond_timedwait(pthread_cond_
 	unsigned count;
 	int err;
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	if (unlikely(cb_try_read_lock(&mutex->lock, s)))
 		return EINVAL;
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	err = pse51_cond_timedwait_prologue(cur, cond, mutex, &count, 1,
 					    ts2ticks_ceil(abstime) + 1);
@@ -505,9 +505,9 @@ int pthread_cond_timedwait(pthread_cond_
 							      mutex, count))
 			;
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	cb_read_unlock(&mutex->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	return err != EINTR ? err : 0;
 }
Index: b/ksrc/skins/posix/mutex.c
===================================================================
--- a/ksrc/skins/posix/mutex.c
+++ b/ksrc/skins/posix/mutex.c
@@ -103,16 +103,16 @@ int pse51_mutex_init_internal(struct __s
 	shadow->mutex = mutex;
 	shadow->lockcnt = 0;
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	xnarch_atomic_set(&shadow->lock, -1);
 	shadow->attr = *attr;
 	shadow->owner_offset = xnheap_mapped_offset(&sys_ppd->sem_heap, ownerp);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	if (attr->protocol == PTHREAD_PRIO_INHERIT)
 		synch_flags |= XNSYNCH_PIP;
 
-	xnsynch_init(&mutex->synchbase, synch_flags);
+	xnsynch_init(&mutex->synchbase, synch_flags, NULL);
 	inith(&mutex->link);
 	mutex->attr = *attr;
 	mutex->owner = ownerp;
@@ -169,16 +169,16 @@ int pthread_mutex_init(pthread_mutex_t *
 		goto checked;
 
 	err = pse51_mutex_check_init(shadow, attr);
-#ifndef CONFIG_XENO_FASTSEM
+#ifndef CONFIG_XENO_FASTSYNCH
 	cb_read_unlock(&shadow->lock, s);
 	if (err)
 		return -err;
-#else /* CONFIG_XENO_FASTSEM */
+#else /* CONFIG_XENO_FASTSYNCH */
 	if (err) {
 		cb_read_unlock(&shadow->lock, s);
 		return -err;
 	}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
   checked:
 	mutex = (pse51_mutex_t *) xnmalloc(sizeof(*mutex));
Index: b/ksrc/skins/posix/mutex.h
===================================================================
--- a/ksrc/skins/posix/mutex.h
+++ b/ksrc/skins/posix/mutex.h
@@ -30,14 +30,14 @@ union __xeno_mutex {
 		unsigned magic;
 		unsigned lockcnt;
 		struct pse51_mutex *mutex;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 		xnarch_atomic_t lock;
 		union {
 			unsigned owner_offset;
 			xnarch_atomic_t *owner;
 		};
 		struct pse51_mutexattr attr;
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 	} shadow_mutex;
 };
 
Index: b/ksrc/skins/posix/syscall.c
===================================================================
--- a/ksrc/skins/posix/syscall.c
+++ b/ksrc/skins/posix/syscall.c
@@ -886,7 +886,7 @@ static int __pthread_mutexattr_setpshare
 	return __xn_safe_copy_to_user((void __user *)uattrp, &attr, sizeof(*uattrp));
 }
 
-#ifndef CONFIG_XENO_FASTSEM
+#ifndef CONFIG_XENO_FASTSYNCH
 static int __pthread_mutex_init(struct pt_regs *regs)
 {
 	pthread_mutexattr_t locattr, *attr, *uattrp;
@@ -1088,7 +1088,7 @@ static int __pthread_mutex_unlock(struct
 
 	return err;
 }
-#else /* !CONFIG_XENO_FASTSEM */
+#else /* !CONFIG_XENO_FASTSYNCH */
 static int __pthread_mutex_check_init(struct pt_regs *regs)
 {
 	pthread_mutexattr_t locattr, *attr, *uattrp;
@@ -1279,7 +1279,7 @@ static int __pthread_mutex_unlock(struct
 
 	return 0;
 }
-#endif /* !CONFIG_XENO_FASTSEM */
+#endif /* !CONFIG_XENO_FASTSYNCH */
 
 static int __pthread_condattr_init(struct pt_regs *regs)
 {
@@ -1469,11 +1469,11 @@ static int __pthread_cond_wait_prologue(
 
 	if (__xn_safe_copy_from_user(&mx.shadow_mutex,
 				     (void __user *)&umx->shadow_mutex,
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 				     offsetof(struct __shadow_mutex, lock)
-#else /* !CONFIG_XENO_FASTSEM */
+#else /* !CONFIG_XENO_FASTSYNCH */
 				     sizeof(mx.shadow_mutex)
-#endif /* !CONFIG_XENO_FASTSEM */
+#endif /* !CONFIG_XENO_FASTSYNCH */
 				     ))
 		return -EFAULT;
 
@@ -1537,11 +1537,11 @@ static int __pthread_cond_wait_epilogue(
 
 	if (__xn_safe_copy_from_user(&mx.shadow_mutex,
 				     (void __user *)&umx->shadow_mutex,
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 				     offsetof(struct __shadow_mutex, lock)
-#else /* !CONFIG_XENO_FASTSEM */
+#else /* !CONFIG_XENO_FASTSYNCH */
 				     sizeof(mx.shadow_mutex)
-#endif /* !CONFIG_XENO_FASTSEM */
+#endif /* !CONFIG_XENO_FASTSYNCH */
 				     ))
 		return -EFAULT;
 
@@ -2695,7 +2695,7 @@ static xnsysent_t __systab[] = {
 	[__pse51_mutex_lock] = {&__pthread_mutex_lock, __xn_exec_primary},
 	[__pse51_mutex_timedlock] =
 	    {&__pthread_mutex_timedlock, __xn_exec_primary},
-#ifndef CONFIG_XENO_FASTSEM
+#ifndef CONFIG_XENO_FASTSYNCH
 	[__pse51_mutex_trylock] = {&__pthread_mutex_trylock, __xn_exec_primary},
 #else
         [__pse51_check_init] = {&__pthread_mutex_check_init, __xn_exec_any},
Index: b/ksrc/skins/posix/thread.c
===================================================================
--- a/ksrc/skins/posix/thread.c
+++ b/ksrc/skins/posix/thread.c
@@ -209,7 +209,7 @@ int pthread_create(pthread_t *tid,
 	thread->magic = PSE51_THREAD_MAGIC;
 	thread->entry = start;
 	thread->arg = arg;
-	xnsynch_init(&thread->join_synch, XNSYNCH_PRIO);
+	xnsynch_init(&thread->join_synch, XNSYNCH_PRIO, NULL);
 	thread->nrt_joiners = 0;
 
 	pse51_cancel_init_thread(thread);
@@ -234,7 +234,7 @@ int pthread_create(pthread_t *tid,
 	thread->hkey.mm = NULL;
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	/* We need an anonymous registry entry to obtain a handle for fast
 	   mutex locking. */
 	{
@@ -244,7 +244,7 @@ int pthread_create(pthread_t *tid,
 			return err;
 		}
 	}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	*tid = thread;		/* Must be done before the thread is started. */
 
Index: b/ksrc/skins/psos+/Kconfig
===================================================================
--- a/ksrc/skins/psos+/Kconfig
+++ b/ksrc/skins/psos+/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_PSOS
 	depends on XENO_OPT_NUCLEUS
 	select XENO_OPT_TIMING_PERIODIC
 	tristate "pSOS+ emulator"
-	select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSEM
+	select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSYNCH
 	help
 
 	This API skin emulates WindRiver's pSOS+ operating system.
Index: b/ksrc/skins/rtai/Kconfig
===================================================================
--- a/ksrc/skins/rtai/Kconfig
+++ b/ksrc/skins/rtai/Kconfig
@@ -1,6 +1,6 @@
 menuconfig XENO_SKIN_RTAI
 	depends on XENO_OPT_NUCLEUS
-	select XENO_OPT_REGISTRY if XENO_FASTSEM
+	select XENO_OPT_REGISTRY if XENO_FASTSYNCH
 	tristate "RTAI emulator"
 	help
 
Index: b/ksrc/skins/rtai/task.c
===================================================================
--- a/ksrc/skins/rtai/task.c
+++ b/ksrc/skins/rtai/task.c
@@ -152,7 +152,7 @@ int rt_task_init(RT_TASK *task,
 	task->magic = RTAI_TASK_MAGIC;
 	appendq(&__rtai_task_q, &task->link);
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	/* We need an anonymous registry entry to obtain a handle for fast
 	   mutex locking. */
 	err = xnthread_register(&task->thread_base, "");
@@ -160,7 +160,7 @@ int rt_task_init(RT_TASK *task,
 		xnpod_abort_thread(&task->thread_base);
 		goto unlock_and_exit;
 	}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	/* Add a switch hook only if a signal function has been declared
 	   at least once for some created task. */
Index: b/ksrc/skins/uitron/Kconfig
===================================================================
--- a/ksrc/skins/uitron/Kconfig
+++ b/ksrc/skins/uitron/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_UITRON
 	depends on XENO_OPT_NUCLEUS
 	select XENO_OPT_TIMING_PERIODIC
 	select XENO_OPT_MAP
-	select XENO_OPT_REGISTRY if XENO_FASTSEM
+	select XENO_OPT_REGISTRY if XENO_FASTSYNCH
 	tristate "uITRON API"
 	help
 
Index: b/ksrc/skins/uitron/task.c
===================================================================
--- a/ksrc/skins/uitron/task.c
+++ b/ksrc/skins/uitron/task.c
@@ -150,7 +150,7 @@ ER cre_tsk(ID tskid, T_CTSK *pk_ctsk)
 	xnlock_put_irqrestore(&nklock, s);
 	task->magic = uITRON_TASK_MAGIC;
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	/* We need an anonymous registry entry to obtain a handle for fast
 	   mutex locking. */
 	if (xnthread_register(&task->threadbase, "")) {
@@ -158,7 +158,7 @@ ER cre_tsk(ID tskid, T_CTSK *pk_ctsk)
 		xnpod_abort_thread(&task->threadbase);
 		return E_NOMEM;
 	}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	return E_OK;
 }
Index: b/ksrc/skins/vrtx/Kconfig
===================================================================
--- a/ksrc/skins/vrtx/Kconfig
+++ b/ksrc/skins/vrtx/Kconfig
@@ -3,7 +3,7 @@ menuconfig XENO_SKIN_VRTX
 	select XENO_OPT_TIMING_PERIODIC
 	select XENO_OPT_MAP
 	tristate "VRTX emulator"
-	select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || CONFIG_XENO_FASTSEM
+	select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || CONFIG_XENO_FASTSYNCH
 	help
 
 	This API skin emulates Mentor Graphics's VRTX operating
Index: b/ksrc/skins/vxworks/Kconfig
===================================================================
--- a/ksrc/skins/vxworks/Kconfig
+++ b/ksrc/skins/vxworks/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_VXWORKS
 	depends on XENO_OPT_NUCLEUS
 	select XENO_OPT_TIMING_PERIODIC
 	tristate "VxWorks emulator"
-	select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSEM
+	select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSYNCH
 	help
 
 	This API skin emulates WindRiver's VxWorks operating system.
Index: b/src/skins/posix/mutex.c
===================================================================
--- a/src/skins/posix/mutex.c
+++ b/src/skins/posix/mutex.c
@@ -26,7 +26,7 @@
 
 extern int __pse51_muxid;
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 #define PSE51_MUTEX_MAGIC (0x86860303)
 
 extern unsigned long xeno_sem_heap[2];
@@ -38,7 +38,7 @@ static xnarch_atomic_t *get_ownerp(struc
 	
 	return (xnarch_atomic_t *) (xeno_sem_heap[1] + shadow->owner_offset);
 }
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 int __wrap_pthread_mutexattr_init(pthread_mutexattr_t *attr)
 {
@@ -98,7 +98,7 @@ int __wrap_pthread_mutex_init(pthread_mu
 	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
 	int err;
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	if (unlikely(cb_try_read_lock(&shadow->lock, s)))
 		goto checked;
 
@@ -111,17 +111,17 @@ int __wrap_pthread_mutex_init(pthread_mu
 
   checked:
 	cb_force_write_lock(&shadow->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	err = -XENOMAI_SKINCALL2(__pse51_muxid,__pse51_mutex_init,shadow,attr);
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	if (!shadow->attr.pshared)
 		shadow->owner = (xnarch_atomic_t *)
 			(xeno_sem_heap[0] + shadow->owner_offset);
 	
 	cb_write_unlock(&shadow->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	return err;
 }
@@ -148,7 +148,7 @@ int __wrap_pthread_mutex_lock(pthread_mu
 	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
 	int err = 0;
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	xnhandle_t cur, owner;
 
 	cur = xeno_get_current();
@@ -188,16 +188,16 @@ int __wrap_pthread_mutex_lock(pthread_mu
 			++shadow->lockcnt;
 			goto out;
 		}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	do {
 		err = XENOMAI_SKINCALL1(__pse51_muxid,__pse51_mutex_lock,shadow);
 	} while (err == -EINTR);
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
   out:
 	cb_read_unlock(&shadow->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	return -err;
 }
@@ -209,7 +209,7 @@ int __wrap_pthread_mutex_timedlock(pthre
 	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
 	int err = 0;
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	xnhandle_t cur, owner;
 
 	cur = xeno_get_current();
@@ -249,17 +249,17 @@ int __wrap_pthread_mutex_timedlock(pthre
 			++shadow->lockcnt;
 			goto out;
 		}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	do {
 		err = XENOMAI_SKINCALL2(__pse51_muxid,
 					__pse51_mutex_timedlock, shadow, to);
 	} while (err == -EINTR);
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
   out:
 	cb_read_unlock(&shadow->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	return -err;
 }
@@ -270,7 +270,7 @@ int __wrap_pthread_mutex_trylock(pthread
 	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
 	int err = 0;
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	xnhandle_t cur, owner;
 
 	cur = xeno_get_current();
@@ -306,14 +306,14 @@ int __wrap_pthread_mutex_trylock(pthread
   out:
 	cb_read_unlock(&shadow->lock, s);
 
-#else /* !CONFIG_XENO_FASTSEM */
+#else /* !CONFIG_XENO_FASTSYNCH */
 
 	do {
 		err = XENOMAI_SKINCALL1(__pse51_muxid,
 					__pse51_mutex_trylock, shadow);
 	} while (err == -EINTR);
 
-#endif /* !CONFIG_XENO_FASTSEM */
+#endif /* !CONFIG_XENO_FASTSYNCH */
 
 	return -err;
 }
@@ -324,7 +324,7 @@ int __wrap_pthread_mutex_unlock(pthread_
 	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
 	int err = 0;
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	xnarch_atomic_t *ownerp;
 	xnhandle_t cur, owner;
 
@@ -358,17 +358,17 @@ int __wrap_pthread_mutex_unlock(pthread_
 		cb_read_unlock(&shadow->lock, s);
 		return 0;
 	}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	do {
 		err = XENOMAI_SKINCALL1(__pse51_muxid,
 					__pse51_mutex_unlock, shadow);
 	} while (err == -EINTR);
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
   out_err:
 	cb_read_unlock(&shadow->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	return -err;
 }
Index: b/ksrc/nucleus/pipe.c
===================================================================
--- a/ksrc/nucleus/pipe.c
+++ b/ksrc/nucleus/pipe.c
@@ -235,7 +235,7 @@ int xnpipe_connect(int minor,
 
 	__setbits(state->status, XNPIPE_KERN_CONN);
 
-	xnsynch_init(&state->synchbase, XNSYNCH_FIFO);
+	xnsynch_init(&state->synchbase, XNSYNCH_FIFO, NULL);
 	state->output_handler = output_handler;
 	state->input_handler = input_handler;
 	state->alloc_handler = alloc_handler;
Index: b/ksrc/nucleus/registry.c
===================================================================
--- a/ksrc/nucleus/registry.c
+++ b/ksrc/nucleus/registry.c
@@ -186,7 +186,7 @@ int xnregistry_init(void)
 	for (n = 0; n < registry_hash_entries; n++)
 		registry_hash_table[n] = NULL;
 
-	xnsynch_init(&registry_hash_synch, XNSYNCH_FIFO);
+	xnsynch_init(&registry_hash_synch, XNSYNCH_FIFO, NULL);
 
 	return 0;
 }
@@ -615,7 +615,7 @@ int xnregistry_enter(const char *key,
 
 	object = link2xnobj(holder);
 
-	xnsynch_init(&object->safesynch, XNSYNCH_FIFO);
+	xnsynch_init(&object->safesynch, XNSYNCH_FIFO, NULL);
 	object->objaddr = objaddr;
 	object->cstamp = ++registry_obj_stamp;
 	object->safelock = 0;
Index: b/ksrc/nucleus/select.c
===================================================================
--- a/ksrc/nucleus/select.c
+++ b/ksrc/nucleus/select.c
@@ -274,7 +274,7 @@ int xnselector_init(struct xnselector *s
 {
 	unsigned i;
 
-	xnsynch_init(&selector->synchbase, XNSYNCH_FIFO | XNSYNCH_NOPIP);
+	xnsynch_init(&selector->synchbase, XNSYNCH_FIFO, NULL);
 	for (i = 0; i < XNSELECT_MAX_TYPES; i++) {
 		__FD_ZERO(&selector->fds[i].expected);
 		__FD_ZERO(&selector->fds[i].pending);
Index: b/ksrc/nucleus/synch.c
===================================================================
--- a/ksrc/nucleus/synch.c
+++ b/ksrc/nucleus/synch.c
@@ -37,7 +37,9 @@
 #include <nucleus/module.h>
 
 /*! 
- * \fn void xnsynch_init(xnsynch_t *synch, xnflags_t flags);
+ * \fn void xnsynch_init(xnsynch_t *synch, xnflags_t flags,
+ *                       xnarch_atomic_t *fastlock)
+ *
  * \brief Initialize a synchronization object.
  *
  * Initializes a new specialized object which can subsequently be used
@@ -79,6 +81,10 @@
  * synchronization object makes the waiters wait by priority order on
  * the awaited resource (XNSYNCH_PRIO).
  *
+ * @param fastlock Address of the fast lock word to be associated with
+ * the synchronization object. If NULL is passed or XNSYNCH_OWNER is not
+ * set, fast-lock support is disabled.
+ *
  * Environments:
  *
  * This service can be called from:
@@ -90,7 +96,7 @@
  * Rescheduling: never.
  */
 
-void xnsynch_init(xnsynch_t *synch, xnflags_t flags)
+void xnsynch_init(xnsynch_t *synch, xnflags_t flags, xnarch_atomic_t *fastlock)
 {
 	initph(&synch->link);
 
@@ -100,6 +106,13 @@ void xnsynch_init(xnsynch_t *synch, xnfl
 	synch->status = flags & ~XNSYNCH_CLAIMED;
 	synch->owner = NULL;
 	synch->cleanup = NULL;	/* Only works for PIP-enabled objects. */
+#ifdef CONFIG_XENO_FASTSYNCH
+	if ((flags & XNSYNCH_OWNER) && fastlock) {
+		synch->fastlock = fastlock;
+		xnarch_atomic_set(fastlock, XN_NO_HANDLE);
+	} else
+		synch->fastlock = NULL;
+#endif /* CONFIG_XENO_FASTSYNCH */
 	initpq(&synch->pendq);
 	xnarch_init_display_context(synch);
 }
@@ -379,36 +392,87 @@ void xnsynch_acquire(xnsynch_t *synch, x
 		     xntmode_t timeout_mode)
 {
 	xnthread_t *thread = xnpod_current_thread(), *owner;
+	xnhandle_t threadh = xnthread_handle(thread), fastlock, old;
+	const int use_fastlock = xnsynch_fastlock_p(synch);
 	spl_t s;
 
 	XENO_BUGON(NUCLEUS, !testbits(synch->status, XNSYNCH_OWNER));
 
-	xnlock_get_irqsave(&nklock, s);
-
 	trace_mark(xn_nucleus_synch_acquire, "synch %p", synch);
 
-redo:
-	owner = synch->owner;
+      redo:
 
-	if (!owner) {
-		synch->owner = thread;
-		xnthread_clear_info(thread, XNRMID | XNTIMEO | XNBREAK);
-		goto unlock_and_exit;
-	}
+	if (use_fastlock) {
+		fastlock = xnarch_atomic_cmpxchg(xnsynch_fastlock(synch),
+						 XN_NO_HANDLE, threadh);
+
+		if (likely(fastlock == XN_NO_HANDLE)) {
+			xnthread_clear_info(thread,
+					    XNRMID | XNTIMEO | XNBREAK);
+			return;
+		}
 
-	if (!testbits(synch->status, XNSYNCH_PRIO)) { /* i.e. FIFO */
-		appendpq(&synch->pendq, &thread->plink);
-		xnpod_suspend_thread(thread, XNPEND, timeout, timeout_mode, synch);
-		goto unlock_and_exit;
+		xnlock_get_irqsave(&nklock, s);
+
+		/* Set claimed bit.
+		   In case it appears to be set already, re-read its state
+		   under nklock so that we don't miss any change between the
+		   lock-less read and here. But also try to avoid cmpxchg
+		   where possible. Only if it appears not to be set, start
+		   with cmpxchg directly. */
+		if (xnsynch_fast_is_claimed(fastlock)) {
+			old = xnarch_atomic_get(xnsynch_fastlock(synch));
+			goto test_no_owner;
+		}
+		do {
+			old = xnarch_atomic_cmpxchg
+				(xnsynch_fastlock(synch), fastlock,
+				 xnsynch_fast_set_claimed(fastlock, 1));
+			if (likely(old == fastlock))
+				break;
+
+		  test_no_owner:
+			if (old == XN_NO_HANDLE) {
+				/* Owner called xnsynch_release
+				   (on another cpu) */
+				xnlock_put_irqrestore(&nklock, s);
+				goto redo;
+			}
+			fastlock = old;
+		} while (!xnsynch_fast_is_claimed(fastlock));
+
+		owner = xnthread_lookup(xnsynch_fast_mask_claimed(fastlock));
+
+		if (!owner) {
+			/* The handle is broken, therefore pretend that the synch
+			   object was deleted to signal an error. */
+			xnthread_set_info(thread, XNRMID);
+			goto unlock_and_exit;
+		}
+
+		xnsynch_set_owner(synch, owner);
+	} else {
+		xnlock_get_irqsave(&nklock, s);
+
+		owner = synch->owner;
+
+		if (!owner) {
+			synch->owner = thread;
+			xnthread_clear_info(thread,
+					    XNRMID | XNTIMEO | XNBREAK);
+			goto unlock_and_exit;
+		}
 	}
 
-	if (thread->cprio > owner->cprio) {
+	if (!testbits(synch->status, XNSYNCH_PRIO)) /* i.e. FIFO */
+		appendpq(&synch->pendq, &thread->plink);
+	else if (thread->cprio > owner->cprio) {
 		if (xnthread_test_info(owner, XNWAKEN) && owner->wwake == synch) {
 			/* Ownership is still pending, steal the resource. */
 			synch->owner = thread;
 			xnthread_clear_info(thread, XNRMID | XNTIMEO | XNBREAK);
 			xnthread_set_info(owner, XNROBBED);
-			goto unlock_and_exit;
+			goto grab_and_exit;
 		}
 
 		insertpqf(&synch->pendq, &thread->plink, thread->cprio);
@@ -439,12 +503,28 @@ redo:
 		/* Somebody stole us the ownership while we were ready
 		   to run, waiting for the CPU: we need to wait again
 		   for the resource. */
-		if (timeout_mode != XN_RELATIVE || timeout == XN_INFINITE)
+		if (timeout_mode != XN_RELATIVE || timeout == XN_INFINITE) {
+			xnlock_put_irqrestore(&nklock, s);
 			goto redo;
+		}
 		timeout = xntimer_get_timeout_stopped(&thread->rtimer);
-		if (timeout > 1) /* Otherwise, it's too late. */
+		if (timeout > 1) { /* Otherwise, it's too late. */
+			xnlock_put_irqrestore(&nklock, s);
 			goto redo;
+		}
 		xnthread_set_info(thread, XNTIMEO);
+	} else {
+
+	      grab_and_exit:
+
+		if (use_fastlock) {
+			/* We are the new owner, update the fastlock
+			   accordingly. */
+			if (xnsynch_pended_p(synch))
+				threadh =
+				    xnsynch_fast_set_claimed(threadh, 1);
+			xnarch_atomic_set(xnsynch_fastlock(synch), threadh);
+		}
 	}
 
       unlock_and_exit:
@@ -582,12 +662,20 @@ void xnsynch_renice_sleeper(xnthread_t *
 
 struct xnthread *xnsynch_release(xnsynch_t *synch)
 {
+	const int use_fastlock = xnsynch_fastlock_p(synch);
 	xnthread_t *newowner, *lastowner;
+	xnhandle_t lastownerh, newownerh;
 	xnpholder_t *holder;
 	spl_t s;
 
 	XENO_BUGON(NUCLEUS, !testbits(synch->status, XNSYNCH_OWNER));
 
+	lastownerh = xnthread_handle(xnpod_current_thread());
+
+	if (use_fastlock &&
+	    likely(xnsynch_fast_release(xnsynch_fastlock(synch), lastownerh)))
+		return NULL;
+
 	xnlock_get_irqsave(&nklock, s);
 
 	trace_mark(xn_nucleus_synch_release, "synch %p", synch);
@@ -605,10 +693,16 @@ struct xnthread *xnsynch_release(xnsynch
 
 		if (testbits(synch->status, XNSYNCH_CLAIMED))
 			xnsynch_clear_boost(synch, lastowner);
+
+		newownerh = xnsynch_fast_set_claimed(xnthread_handle(newowner),
+						     xnsynch_pended_p(synch));
 	} else {
 		newowner = NULL;
 		synch->owner = NULL;
+		newownerh = XN_NO_HANDLE;
 	}
+	if (use_fastlock)
+		xnarch_atomic_set(xnsynch_fastlock(synch), newownerh);
 
 	xnlock_put_irqrestore(&nklock, s);
 
Index: b/ksrc/drivers/testing/switchtest.c
===================================================================
--- a/ksrc/drivers/testing/switchtest.c
+++ b/ksrc/drivers/testing/switchtest.c
@@ -219,7 +219,7 @@ static int rtswitch_register_task(rtswit
 	ctx->next_index++;
 	t->base = *arg;
 	sema_init(&t->nrt_synch, 0);
-	xnsynch_init(&t->rt_synch, XNSYNCH_FIFO);
+	xnsynch_init(&t->rt_synch, XNSYNCH_FIFO, NULL);
 
 	up(&ctx->lock);
 
Index: b/ksrc/skins/native/alarm.c
===================================================================
--- a/ksrc/skins/native/alarm.c
+++ b/ksrc/skins/native/alarm.c
@@ -207,7 +207,7 @@ int rt_alarm_create(RT_ALARM *alarm,
 	xnlock_put_irqrestore(&nklock, s);
 
 #ifdef CONFIG_XENO_OPT_PERVASIVE
-	xnsynch_init(&alarm->synch_base, XNSYNCH_PRIO);
+	xnsynch_init(&alarm->synch_base, XNSYNCH_PRIO, NULL);
 	alarm->cpid = 0;
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
 
Index: b/ksrc/skins/native/buffer.c
===================================================================
--- a/ksrc/skins/native/buffer.c
+++ b/ksrc/skins/native/buffer.c
@@ -192,8 +192,8 @@ int rt_buffer_create(RT_BUFFER *bf, cons
 	if (bf->bufmem == NULL)
 		return -ENOMEM;
 
-	xnsynch_init(&bf->isynch_base, mode & B_PRIO);
-	xnsynch_init(&bf->osynch_base, mode & B_PRIO);
+	xnsynch_init(&bf->isynch_base, mode & B_PRIO, NULL);
+	xnsynch_init(&bf->osynch_base, mode & B_PRIO, NULL);
 
 	bf->handle = 0;	/* i.e. (still) unregistered buffer. */
 	xnobject_copy_name(bf->name, name);
Index: b/ksrc/skins/native/cond.c
===================================================================
--- a/ksrc/skins/native/cond.c
+++ b/ksrc/skins/native/cond.c
@@ -160,7 +160,7 @@ int rt_cond_create(RT_COND *cond, const
 	if (xnpod_asynch_p())
 		return -EPERM;
 
-	xnsynch_init(&cond->synch_base, XNSYNCH_PRIO);
+	xnsynch_init(&cond->synch_base, XNSYNCH_PRIO, NULL);
 	cond->handle = 0;	/* i.e. (still) unregistered cond. */
 	cond->magic = XENO_COND_MAGIC;
 	xnobject_copy_name(cond->name, name);
Index: b/ksrc/skins/native/event.c
===================================================================
--- a/ksrc/skins/native/event.c
+++ b/ksrc/skins/native/event.c
@@ -183,7 +183,7 @@ int rt_event_create(RT_EVENT *event,
 	if (xnpod_asynch_p())
 		return -EPERM;
 
-	xnsynch_init(&event->synch_base, mode & EV_PRIO);
+	xnsynch_init(&event->synch_base, mode & EV_PRIO, NULL);
 	event->value = ivalue;
 	event->handle = 0;	/* i.e. (still) unregistered event. */
 	event->magic = XENO_EVENT_MAGIC;
Index: b/ksrc/skins/native/heap.c
===================================================================
--- a/ksrc/skins/native/heap.c
+++ b/ksrc/skins/native/heap.c
@@ -292,7 +292,7 @@ int rt_heap_create(RT_HEAP *heap, const
 		}
 	}
 
-	xnsynch_init(&heap->synch_base, mode & (H_PRIO | H_FIFO));
+	xnsynch_init(&heap->synch_base, mode & (H_PRIO | H_FIFO), NULL);
 	heap->handle = 0;	/* i.e. (still) unregistered heap. */
 	heap->magic = XENO_HEAP_MAGIC;
 	heap->mode = mode;
Index: b/ksrc/skins/native/intr.c
===================================================================
--- a/ksrc/skins/native/intr.c
+++ b/ksrc/skins/native/intr.c
@@ -266,7 +266,7 @@ int rt_intr_create(RT_INTR *intr,
 
 	xnintr_init(&intr->intr_base, intr->name, irq, isr, iack, mode);
 #ifdef CONFIG_XENO_OPT_PERVASIVE
-	xnsynch_init(&intr->synch_base, XNSYNCH_PRIO);
+	xnsynch_init(&intr->synch_base, XNSYNCH_PRIO, NULL);
 	intr->pending = 0;
 	intr->cpid = 0;
 	intr->mode = 0;
Index: b/ksrc/skins/native/mutex.c
===================================================================
--- a/ksrc/skins/native/mutex.c
+++ b/ksrc/skins/native/mutex.c
@@ -171,7 +171,7 @@ int rt_mutex_create(RT_MUTEX *mutex, con
 		return -EPERM;
 
 	xnsynch_init(&mutex->synch_base,
-		     XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER);
+		     XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER, NULL);
 	mutex->handle = 0;	/* i.e. (still) unregistered mutex. */
 	mutex->magic = XENO_MUTEX_MAGIC;
 	mutex->lockcnt = 0;
Index: b/ksrc/skins/native/queue.c
===================================================================
--- a/ksrc/skins/native/queue.c
+++ b/ksrc/skins/native/queue.c
@@ -255,7 +255,7 @@ int rt_queue_create(RT_QUEUE *q,
 		}
 	}
 
-	xnsynch_init(&q->synch_base, mode & (Q_PRIO | Q_FIFO));
+	xnsynch_init(&q->synch_base, mode & (Q_PRIO | Q_FIFO), NULL);
 	initq(&q->pendq);
 	q->handle = 0;		/* i.e. (still) unregistered queue. */
 	q->magic = XENO_QUEUE_MAGIC;
Index: b/ksrc/skins/native/sem.c
===================================================================
--- a/ksrc/skins/native/sem.c
+++ b/ksrc/skins/native/sem.c
@@ -181,7 +181,7 @@ int rt_sem_create(RT_SEM *sem, const cha
 	if ((mode & S_PULSE) && icount > 0)
 		return -EINVAL;
 
-	xnsynch_init(&sem->synch_base, mode & S_PRIO);
+	xnsynch_init(&sem->synch_base, mode & S_PRIO, NULL);
 	sem->count = icount;
 	sem->mode = mode;
 	sem->handle = 0;	/* i.e. (still) unregistered semaphore. */
Index: b/ksrc/skins/native/task.c
===================================================================
--- a/ksrc/skins/native/task.c
+++ b/ksrc/skins/native/task.c
@@ -255,7 +255,7 @@ int rt_task_create(RT_TASK *task,
 	task->overrun = -1;
 	task->cstamp = ++__xeno_task_stamp;
 	task->safelock = 0;
-	xnsynch_init(&task->safesynch, XNSYNCH_FIFO);
+	xnsynch_init(&task->safesynch, XNSYNCH_FIFO, NULL);
 
 	xnarch_cpus_clear(task->affinity);
 
@@ -268,9 +268,9 @@ int rt_task_create(RT_TASK *task,
 		task->affinity = XNPOD_ALL_CPUS;
 
 #ifdef CONFIG_XENO_OPT_NATIVE_MPS
-	xnsynch_init(&task->mrecv, XNSYNCH_FIFO);
+	xnsynch_init(&task->mrecv, XNSYNCH_FIFO, NULL);
 	xnsynch_init(&task->msendq,
-		     XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER);
+		     XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER, NULL);
 	xnsynch_set_owner(&task->msendq, &task->thread_base);
 	task->flowgen = 0;
 #endif /* CONFIG_XENO_OPT_NATIVE_MPS */
Index: b/ksrc/skins/posix/intr.c
===================================================================
--- a/ksrc/skins/posix/intr.c
+++ b/ksrc/skins/posix/intr.c
@@ -116,7 +116,7 @@ int pthread_intr_attach_np(pthread_intr_
 	xnintr_init(&intr->intr_base, NULL, irq, isr, iack, 0);
 
 #ifdef CONFIG_XENO_OPT_PERVASIVE
-	xnsynch_init(&intr->synch_base, XNSYNCH_PRIO);
+	xnsynch_init(&intr->synch_base, XNSYNCH_PRIO, NULL);
 	intr->pending = 0;
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
 	intr->magic = PSE51_INTR_MAGIC;
Index: b/ksrc/skins/posix/mq.c
===================================================================
--- a/ksrc/skins/posix/mq.c
+++ b/ksrc/skins/posix/mq.c
@@ -129,8 +129,8 @@ static int pse51_mq_init(pse51_mq_t * mq
 
 	mq->memsize = memsize;
 	initpq(&mq->queued);
-	xnsynch_init(&mq->receivers, XNSYNCH_PRIO | XNSYNCH_NOPIP);
-	xnsynch_init(&mq->senders, XNSYNCH_PRIO | XNSYNCH_NOPIP);
+	xnsynch_init(&mq->receivers, XNSYNCH_PRIO | XNSYNCH_NOPIP, NULL);
+	xnsynch_init(&mq->senders, XNSYNCH_PRIO | XNSYNCH_NOPIP, NULL);
 	mq->mem = mem;
 
 	/* Fill the pool. */
Index: b/ksrc/skins/posix/sem.c
===================================================================
--- a/ksrc/skins/posix/sem.c
+++ b/ksrc/skins/posix/sem.c
@@ -99,7 +99,7 @@ static int pse51_sem_init_inner(pse51_se
 
 	inith(&sem->link);
 	appendq(&pse51_kqueues(pshared)->semq, &sem->link);
-	xnsynch_init(&sem->synchbase, XNSYNCH_PRIO);
+	xnsynch_init(&sem->synchbase, XNSYNCH_PRIO, NULL);
 	sem->value = value;
 	sem->pshared = pshared;
 	sem->is_named = 0;
Index: b/ksrc/skins/psos+/event.c
===================================================================
--- a/ksrc/skins/psos+/event.c
+++ b/ksrc/skins/psos+/event.c
@@ -21,7 +21,7 @@
 
 void taskev_init(psosevent_t *evgroup)
 {
-	xnsynch_init(&evgroup->synchbase, XNSYNCH_FIFO);
+	xnsynch_init(&evgroup->synchbase, XNSYNCH_FIFO, NULL);
 	evgroup->events = 0;
 }
 
Index: b/ksrc/skins/psos+/queue.c
===================================================================
--- a/ksrc/skins/psos+/queue.c
+++ b/ksrc/skins/psos+/queue.c
@@ -259,7 +259,7 @@ static u_long q_create_internal(const ch
 		}
 	}
 
-	xnsynch_init(&queue->synchbase, bflags);
+	xnsynch_init(&queue->synchbase, bflags, NULL);
 
 	queue->magic = PSOS_QUEUE_MAGIC;
 	xnobject_copy_name(queue->name, name);
Index: b/ksrc/skins/psos+/rn.c
===================================================================
--- a/ksrc/skins/psos+/rn.c
+++ b/ksrc/skins/psos+/rn.c
@@ -214,7 +214,7 @@ u_long rn_create(const char *name,
 	rn->usize = usize;
 	xnobject_copy_name(rn->name, name);
 
-	xnsynch_init(&rn->synchbase, bflags);
+	xnsynch_init(&rn->synchbase, bflags, NULL);
 	rn->magic = PSOS_RN_MAGIC;
 
 	inith(&rn->rlink);
Index: b/ksrc/skins/psos+/sem.c
===================================================================
--- a/ksrc/skins/psos+/sem.c
+++ b/ksrc/skins/psos+/sem.c
@@ -114,7 +114,7 @@ u_long sm_create(const char *name, u_lon
 	if (flags & SM_PRIOR)
 		bflags |= XNSYNCH_PRIO;
 
-	xnsynch_init(&sem->synchbase, bflags);
+	xnsynch_init(&sem->synchbase, bflags, NULL);
 
 	inith(&sem->link);
 	sem->count = icount;
Index: b/ksrc/skins/rtai/sem.c
===================================================================
--- a/ksrc/skins/rtai/sem.c
+++ b/ksrc/skins/rtai/sem.c
@@ -38,7 +38,7 @@ void rt_typed_sem_init(SEM * sem, int va
 			mode = XNSYNCH_FIFO;
 	}
 
-	xnsynch_init(&sem->synch_base, mode);
+	xnsynch_init(&sem->synch_base, mode, NULL);
 	sem->count = value;
 	sem->type = type & 0x3;
 	sem->owner = NULL;
Index: b/ksrc/skins/rtdm/drvlib.c
===================================================================
--- a/ksrc/skins/rtdm/drvlib.c
+++ b/ksrc/skins/rtdm/drvlib.c
@@ -145,13 +145,13 @@ int rtdm_task_init(rtdm_task_t *task, co
 	if (err)
 		return err;
 
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
 	/* We need an anonymous registry entry to obtain a handle for fast
 	   mutex locking. */
 	err = xnthread_register(task, "");
 	if (err)
 		goto cleanup_out;
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	if (period > 0) {
 		err = xnpod_set_thread_periodic(task, XN_INFINITE,
@@ -761,7 +761,7 @@ void rtdm_event_init(rtdm_event_t *event
 	/* Make atomic for re-initialisation support */
 	xnlock_get_irqsave(&nklock, s);
 
-	xnsynch_init(&event->synch_base, XNSYNCH_PRIO);
+	xnsynch_init(&event->synch_base, XNSYNCH_PRIO, NULL);
 	if (pending)
 		xnsynch_set_flags(&event->synch_base, RTDM_EVENT_PENDING);
 	xnselect_init(&event->select_block);
@@ -1109,7 +1109,7 @@ void rtdm_sem_init(rtdm_sem_t *sem, unsi
 	xnlock_get_irqsave(&nklock, s);
 
 	sem->value = value;
-	xnsynch_init(&sem->synch_base, XNSYNCH_PRIO);
+	xnsynch_init(&sem->synch_base, XNSYNCH_PRIO, NULL);
 	xnselect_init(&sem->select_block);
 
 	xnlock_put_irqrestore(&nklock, s);
@@ -1391,7 +1391,7 @@ void rtdm_mutex_init(rtdm_mutex_t *mutex
 	xnlock_get_irqsave(&nklock, s);
 
 	xnsynch_init(&mutex->synch_base,
-		     XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER);
+		     XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER, NULL);
 
 	xnlock_put_irqrestore(&nklock, s);
 }
Index: b/ksrc/skins/uitron/flag.c
===================================================================
--- a/ksrc/skins/uitron/flag.c
+++ b/ksrc/skins/uitron/flag.c
@@ -122,7 +122,7 @@ ER cre_flg(ID flgid, T_CFLG *pk_cflg)
 		return E_OBJ;
 	}
 
-	xnsynch_init(&flag->synchbase, XNSYNCH_FIFO);
+	xnsynch_init(&flag->synchbase, XNSYNCH_FIFO, NULL);
 	flag->id = flgid;
 	flag->exinf = pk_cflg->exinf;
 	flag->flgatr = pk_cflg->flgatr;
Index: b/ksrc/skins/uitron/mbx.c
===================================================================
--- a/ksrc/skins/uitron/mbx.c
+++ b/ksrc/skins/uitron/mbx.c
@@ -138,7 +138,8 @@ ER cre_mbx(ID mbxid, T_CMBX *pk_cmbx)
 	}
 
 	xnsynch_init(&mbx->synchbase,
-		     (pk_cmbx->mbxatr & TA_TPRI) ? XNSYNCH_PRIO : XNSYNCH_FIFO);
+		     (pk_cmbx->mbxatr & TA_TPRI) ? XNSYNCH_PRIO : XNSYNCH_FIFO,
+		     NULL);
 
 	mbx->id = mbxid;
 	mbx->exinf = pk_cmbx->exinf;
Index: b/ksrc/skins/uitron/sem.c
===================================================================
--- a/ksrc/skins/uitron/sem.c
+++ b/ksrc/skins/uitron/sem.c
@@ -127,7 +127,8 @@ ER cre_sem(ID semid, T_CSEM *pk_csem)
 	}
 
 	xnsynch_init(&sem->synchbase,
-		     (pk_csem->sematr & TA_TPRI) ? XNSYNCH_PRIO : XNSYNCH_FIFO);
+		     (pk_csem->sematr & TA_TPRI) ? XNSYNCH_PRIO : XNSYNCH_FIFO,
+		     NULL);
 
 	sem->id = semid;
 	sem->exinf = pk_csem->exinf;
Index: b/ksrc/skins/vrtx/event.c
===================================================================
--- a/ksrc/skins/vrtx/event.c
+++ b/ksrc/skins/vrtx/event.c
@@ -151,7 +151,7 @@ int sc_fcreate(int *errp)
 		goto nocb;
 	}
 
-	xnsynch_init(&evgroup->synchbase, XNSYNCH_PRIO | XNSYNCH_DREORD);
+	xnsynch_init(&evgroup->synchbase, XNSYNCH_PRIO | XNSYNCH_DREORD, NULL);
 	inith(&evgroup->link);
 	evgroup->evid = evid;
 	evgroup->magic = VRTX_EVENT_MAGIC;
Index: b/ksrc/skins/vrtx/mb.c
===================================================================
--- a/ksrc/skins/vrtx/mb.c
+++ b/ksrc/skins/vrtx/mb.c
@@ -210,7 +210,7 @@ vrtxmb_t *mb_map(char **mboxp)
 	mb->mboxp = mboxp;
 	mb->msg = NULL;
 	mb->hnext = NULL;
-	xnsynch_init(&mb->synchbase, XNSYNCH_PRIO | XNSYNCH_DREORD);
+	xnsynch_init(&mb->synchbase, XNSYNCH_PRIO | XNSYNCH_DREORD, NULL);
 	appendq(&vrtx_mbox_q, &mb->link);
 	mb_hash(mboxp, mb);
 
Index: b/ksrc/skins/vrtx/mx.c
===================================================================
--- a/ksrc/skins/vrtx/mx.c
+++ b/ksrc/skins/vrtx/mx.c
@@ -161,7 +161,8 @@ int sc_mcreate(unsigned int opt, int *er
 	inith(&mx->link);
 	mx->mid = mid;
 	mx->owner = NULL;
-	xnsynch_init(&mx->synchbase, bflags | XNSYNCH_DREORD | XNSYNCH_OWNER);
+	xnsynch_init(&mx->synchbase, bflags | XNSYNCH_DREORD | XNSYNCH_OWNER,
+		     NULL);
 
 	xnlock_get_irqsave(&nklock, s);
 	appendq(&vrtx_mx_q, &mx->link);
Index: b/ksrc/skins/vrtx/queue.c
===================================================================
--- a/ksrc/skins/vrtx/queue.c
+++ b/ksrc/skins/vrtx/queue.c
@@ -165,7 +165,7 @@ int sc_qecreate(int qid, int qsize, int
 		bflags = XNSYNCH_PRIO;
 
 	inith(&queue->link);
-	xnsynch_init(&queue->synchbase, bflags | XNSYNCH_DREORD);
+	xnsynch_init(&queue->synchbase, bflags | XNSYNCH_DREORD, NULL);
 	queue->magic = VRTX_QUEUE_MAGIC;
 	queue->qid = qid;
 	queue->qsize = qsize;
Index: b/ksrc/skins/vrtx/sem.c
===================================================================
--- a/ksrc/skins/vrtx/sem.c
+++ b/ksrc/skins/vrtx/sem.c
@@ -155,7 +155,7 @@ int sc_screate(unsigned initval, int opt
 	else
 		bflags = XNSYNCH_FIFO;
 
-	xnsynch_init(&sem->synchbase, bflags | XNSYNCH_DREORD);
+	xnsynch_init(&sem->synchbase, bflags | XNSYNCH_DREORD, NULL);
 	inith(&sem->link);
 	sem->semid = semid;
 	sem->magic = VRTX_SEM_MAGIC;
Index: b/ksrc/skins/vxworks/module.c
===================================================================
--- a/ksrc/skins/vxworks/module.c
+++ b/ksrc/skins/vxworks/module.c
@@ -59,7 +59,7 @@ int SKIN_INIT(vxworks)
 	/* The following fields are unused in the global holder;
 	   still, we initialize them not to leave such data in an
 	   invalid state. */
-	xnsynch_init(&__wind_global_rholder.wdsynch, XNSYNCH_FIFO);
+	xnsynch_init(&__wind_global_rholder.wdsynch, XNSYNCH_FIFO, NULL);
 	initq(&__wind_global_rholder.wdpending);
 	__wind_global_rholder.wdcount = 0;
 
Index: b/ksrc/skins/vxworks/msgQLib.c
===================================================================
--- a/ksrc/skins/vxworks/msgQLib.c
+++ b/ksrc/skins/vxworks/msgQLib.c
@@ -174,7 +174,7 @@ MSG_Q_ID msgQCreate(int nb_msgs, int len
 	if (flags & MSG_Q_PRIORITY)
 		bflags |= XNSYNCH_PRIO;
 
-	xnsynch_init(&queue->synchbase, bflags);
+	xnsynch_init(&queue->synchbase, bflags, NULL);
 
 	msg_size = sizeof(wind_msg_t) + length;
 
Index: b/ksrc/skins/vxworks/semLib.c
===================================================================
--- a/ksrc/skins/vxworks/semLib.c
+++ b/ksrc/skins/vxworks/semLib.c
@@ -423,7 +423,7 @@ static SEM_ID sem_create_internal(int fl
 
 	check_alloc(wind_sem_t, sem, return 0);
 
-	xnsynch_init(&sem->synchbase, (xnflags_t)flags);
+	xnsynch_init(&sem->synchbase, (xnflags_t)flags, NULL);
 	sem->magic = WIND_SEM_MAGIC;
 	sem->count = count;
 	sem->vtbl = vtbl;
Index: b/ksrc/skins/vxworks/syscall.c
===================================================================
--- a/ksrc/skins/vxworks/syscall.c
+++ b/ksrc/skins/vxworks/syscall.c
@@ -1171,7 +1171,7 @@ static void *__wind_shadow_eventcb(int e
 
 		initq(&rh->wdq);
 		/* A single server thread pends on this. */
-		xnsynch_init(&rh->wdsynch, XNSYNCH_FIFO);
+		xnsynch_init(&rh->wdsynch, XNSYNCH_FIFO, NULL);
 		initq(&rh->wdpending);
 		rh->wdcount = 0;
 		initq(&rh->msgQq);
Index: b/ksrc/skins/vxworks/taskLib.c
===================================================================
--- a/ksrc/skins/vxworks/taskLib.c
+++ b/ksrc/skins/vxworks/taskLib.c
@@ -146,7 +146,7 @@ STATUS taskInit(WIND_TCB *pTcb,
 	xnthread_time_slice(&pTcb->threadbase) = rrperiod;
 
 	pTcb->safecnt = 0;
-	xnsynch_init(&pTcb->safesync, 0);
+	xnsynch_init(&pTcb->safesync, 0, NULL);
 
 	/* TODO: fill in attributes of wind_task_t:
 	   pTcb->status



^ permalink raw reply	[flat|nested] 50+ messages in thread

* [Xenomai-core] [PATCH 07/12] Convert POSIX skin to fast xnsynch
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
                   ` (5 preceding siblings ...)
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 06/12] Lockless fast path for xnsynch_acquire/release Jan Kiszka
@ 2008-10-16 15:46 ` Jan Kiszka
  2008-10-16 20:05   ` Gilles Chanteperdrix
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin Jan Kiszka
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 15:46 UTC (permalink / raw)
  To: xenomai; +Cc: Jan Kiszka

[-- Attachment #1: switch-posix-to-fast-xnsynch.patch --]
[-- Type: text/plain, Size: 19656 bytes --]

Migrates the existing fast mutex implementation of the POSIX skin to
fast xnsynch services, also fixing the build for arch that do not
support fast mutexes.

Lock stealing via pthread_trylock is not considered by this patch,
keeping this services lockless and syscall-less until we identify the
need for using the steal mechanism also for this case.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 ksrc/skins/posix/cond.c    |   18 ++---
 ksrc/skins/posix/mutex.c   |   92 ++++++++++++++++++++--------
 ksrc/skins/posix/mutex.h   |  143 +++++++--------------------------------------
 ksrc/skins/posix/syscall.c |   22 ++----
 src/skins/posix/mutex.c    |   55 ++++++++---------
 5 files changed, 132 insertions(+), 198 deletions(-)

Index: b/ksrc/skins/posix/cond.c
===================================================================
--- a/ksrc/skins/posix/cond.c
+++ b/ksrc/skins/posix/cond.c
@@ -223,27 +223,23 @@ static inline int mutex_save_count(xnthr
 				   unsigned *count_ptr)
 {
 	pse51_mutex_t *mutex;
-	xnthread_t *owner;
 
 	if (!pse51_obj_active(shadow, PSE51_MUTEX_MAGIC, struct __shadow_mutex))
 		 return EINVAL;
 
 	mutex = shadow->mutex;
 
-	if (clear_claimed(xnarch_atomic_get(mutex->owner)) !=
-	    xnthread_handle(cur))
+#ifdef CONFIG_XENO_FASTSYNCH
+	if (xnsynch_fast_owner_check(mutex->synchbase.fastlock,
+				     xnthread_handle(cur)) != 0)
+#else /* !CONFIG_XENO_FASTSYNCH */
+	if (xnsynch_owner(&mutex->synchbase) != cur)
+#endif /* !CONFIG_XENO_FASTSYNCH */
 		return EPERM;
 
 	*count_ptr = shadow->lockcnt;
 
-	if (likely(xnarch_atomic_cmpxchg(mutex->owner, cur, XN_NO_HANDLE) ==
-		   xnthread_handle(cur)))
-		return 0;
-
-	owner = xnsynch_release(&mutex->synchbase);
-	xnarch_atomic_set(mutex->owner,
-			  set_claimed(xnthread_handle(owner),
-				      xnsynch_nsleepers(&mutex->synchbase)));
+	xnsynch_release(&mutex->synchbase);
 
 	/* Do not reschedule here, releasing the mutex and suspension must be
 	   done atomically in pthread_cond_*wait. */
Index: b/ksrc/skins/posix/mutex.c
===================================================================
--- a/ksrc/skins/posix/mutex.c
+++ b/ksrc/skins/posix/mutex.c
@@ -102,9 +102,9 @@ int pse51_mutex_init_internal(struct __s
 	shadow->magic = PSE51_MUTEX_MAGIC;
 	shadow->mutex = mutex;
 	shadow->lockcnt = 0;
+	xnarch_atomic_set(&shadow->lock, -1);
 
 #ifdef CONFIG_XENO_FASTSYNCH
-	xnarch_atomic_set(&shadow->lock, -1);
 	shadow->attr = *attr;
 	shadow->owner_offset = xnheap_mapped_offset(&sys_ppd->sem_heap, ownerp);
 #endif /* CONFIG_XENO_FASTSYNCH */
@@ -112,13 +112,10 @@ int pse51_mutex_init_internal(struct __s
 	if (attr->protocol == PTHREAD_PRIO_INHERIT)
 		synch_flags |= XNSYNCH_PIP;
 
-	xnsynch_init(&mutex->synchbase, synch_flags, NULL);
+	xnsynch_init(&mutex->synchbase, synch_flags, ownerp);
 	inith(&mutex->link);
 	mutex->attr = *attr;
-	mutex->owner = ownerp;
 	mutex->owningq = kq;
-	mutex->sleepers = 0;
-	xnarch_atomic_set(ownerp, XN_NO_HANDLE);
 
 	xnlock_get_irqsave(&nklock, s);
 	appendq(&kq->mutexq, &mutex->link);
@@ -159,7 +156,7 @@ int pthread_mutex_init(pthread_mutex_t *
 	    &((union __xeno_mutex *)mx)->shadow_mutex;
 	DECLARE_CB_LOCK_FLAGS(s);
 	pse51_mutex_t *mutex;
-	xnarch_atomic_t *ownerp;
+	xnarch_atomic_t *ownerp = NULL;
 	int err;
 
 	if (!attr)
@@ -185,6 +182,7 @@ int pthread_mutex_init(pthread_mutex_t *
 	if (!mutex)
 		return ENOMEM;
 
+#ifdef CONFIG_XENO_FASTSYNCH
 	ownerp = (xnarch_atomic_t *)
 		xnheap_alloc(&xnsys_ppd_get(attr->pshared)->sem_heap,
 			     sizeof(xnarch_atomic_t));
@@ -192,6 +190,7 @@ int pthread_mutex_init(pthread_mutex_t *
 		xnfree(mutex);
 		return EAGAIN;
 	}
+#endif /* CONFIG_XENO_FASTSYNCH */
 
 	cb_force_write_lock(&shadow->lock, s);
 	err = pse51_mutex_init_internal(shadow, mutex, ownerp, attr);
@@ -199,7 +198,9 @@ int pthread_mutex_init(pthread_mutex_t *
 
 	if (err) {
 		xnfree(mutex);
+#ifdef CONFIG_XENO_FASTSYNCH
 		xnheap_free(&xnsys_ppd_get(attr->pshared)->sem_heap, ownerp);
+#endif /* CONFIG_XENO_FASTSYNCH */
 	}
 	return -err;
 }
@@ -216,8 +217,10 @@ void pse51_mutex_destroy_internal(pse51_
 	xnsynch_destroy(&mutex->synchbase);
 	xnlock_put_irqrestore(&nklock, s);
 
-	if (mutex->attr.pshared)
-		xnheap_free(&xnsys_ppd_get(1)->sem_heap, mutex->owner);
+#ifdef CONFIG_XENO_FASTSYNCH
+	xnheap_free(&xnsys_ppd_get(mutex->attr.pshared)->sem_heap,
+		    mutex->synchbase.fastlock);
+#endif /* CONFIG_XENO_FASTSYNCH */
 	/* We do not free the owner if the mutex is not pshared, because when
 	   this function is called from pse51_mutexq_cleanup, the sem_heap has
 	   been destroyed, and we have no way to find it back. */
@@ -266,7 +269,12 @@ int pthread_mutex_destroy(pthread_mutex_
 		return EPERM;
 	}
 
-	if (xnarch_atomic_get(mutex->owner) != XN_NO_HANDLE) {
+#ifdef CONFIG_XENO_FASTSYNCH
+	if (xnsynch_fast_owner_check(mutex->synchbase.fastlock,
+				     XN_NO_HANDLE) != 0) {
+#else /* CONFIG_XENO_FASTSYNCH */
+	if (shadow->lockcnt) {
+#endif
 		cb_write_unlock(&shadow->lock, s);
 		return EBUSY;
 	}
@@ -274,9 +282,6 @@ int pthread_mutex_destroy(pthread_mutex_
 	pse51_mark_deleted(shadow);
 	cb_write_unlock(&shadow->lock, s);
 
-	if (!mutex->attr.pshared)
-		xnheap_free(&xnsys_ppd_get(mutex->attr.pshared)->sem_heap,
-			    mutex->owner);
 	pse51_mutex_destroy_internal(mutex, pse51_kqueues(mutex->attr.pshared));
 	
 	return 0;
@@ -305,14 +310,12 @@ int pse51_mutex_timedlock_break(struct _
 		/* Attempting to relock a normal mutex, deadlock. */
 		xnlock_get_irqsave(&nklock, s);
 		for (;;) {
-			++mutex->sleepers;
 			if (timed)
 				xnsynch_acquire(&mutex->synchbase,
 						abs_to, XN_REALTIME);
 			else
 				xnsynch_acquire(&mutex->synchbase,
 						XN_INFINITE, XN_RELATIVE);
-			--mutex->sleepers;
 
 			if (xnthread_test_info(cur, XNBREAK)) {
 				err = -EINTR;
@@ -384,19 +387,48 @@ int pthread_mutex_trylock(pthread_mutex_
 {
 	struct __shadow_mutex *shadow =
 	    &((union __xeno_mutex *)mx)->shadow_mutex;
-	xnthread_t *owner, *cur = xnpod_current_thread();
+	xnthread_t *cur = xnpod_current_thread();
+	pse51_mutex_t *mutex = shadow->mutex;
 	DECLARE_CB_LOCK_FLAGS(s);
 	int err;
 
+	if (xnpod_unblockable_p())
+		return EPERM;
+
 	if (unlikely(cb_try_read_lock(&shadow->lock, s)))
 		return EINVAL;
 
-	owner = pse51_mutex_trylock_internal(cur, shadow, 1);
-	if (likely(!owner) || IS_ERR(owner))
-		return -PTR_ERR(owner);
+	if (!pse51_obj_active(shadow, PSE51_MUTEX_MAGIC,
+			      struct __shadow_mutex)) {
+		err = EINVAL;
+		goto unlock_and_return;
+	}
+
+#if XENO_DEBUG(POSIX)
+	if (mutex->owningq != pse51_kqueues(mutex->attr.pshared)) {
+		err = EPERM;
+		goto unlock_and_return;
+	}
+#endif /* XENO_DEBUG(POSIX) */
 
-	err = EBUSY;
-	if (owner == cur) {
+#ifdef CONFIG_XENO_FASTSYNCH
+	err = -xnsynch_fast_acquire(mutex->synchbase.fastlock,
+				    xnthread_handle(cur));
+#else /* !CONFIG_XENO_FASTSYNCH */
+	{
+		xnthread_t *owner = xnsynch_owner(&mutex->synchbase);
+		if (!owner)
+			err = 0;
+		else if (owner == cur)
+			err = EBUSY;
+		else
+			err = EAGAIN;
+	}
+#endif /* !CONFIG_XENO_FASTSYNCH */
+
+	if (likely(!err))
+		shadow->lockcnt = 1;
+	else if (err == EBUSY) {
 		pse51_mutex_t *mutex = shadow->mutex;
 
 		if (mutex->attr.type == PTHREAD_MUTEX_RECURSIVE) {
@@ -409,6 +441,7 @@ int pthread_mutex_trylock(pthread_mutex_
 		}
 	}
 
+  unlock_and_return:
 	cb_read_unlock(&shadow->lock, s);
 
 	return err;
@@ -564,7 +597,7 @@ int pthread_mutex_unlock(pthread_mutex_t
 	int err;
 
 	if (xnpod_root_p() || xnpod_interrupt_p())
-		return -EPERM;
+		return EPERM;
 
 	if (unlikely(cb_try_read_lock(&shadow->lock, s)))
 		return EINVAL;
@@ -576,14 +609,16 @@ int pthread_mutex_unlock(pthread_mutex_t
 	}
 
 	mutex = shadow->mutex;
-	
-	if (clear_claimed(xnarch_atomic_get(mutex->owner)) !=
-	    xnthread_handle(cur)) {
-		err = EPERM;
+
+#ifdef CONFIG_XENO_FASTSYNCH
+	err = -xnsynch_fast_owner_check(mutex->synchbase.fastlock,
+					xnthread_handle(cur));
+#else /* !CONFIG_XENO_FASTSYNCH */
+	err = (xnsynch_owner(&mutex->synchbase) == cur) ? 0 : EPERM;
+#endif /* !CONFIG_XENO_FASTSYNCH */
+	if (err)
 		goto out;
-	}
 
-	err = 0;
 	if (shadow->lockcnt > 1) {
 		/* Mutex is recursive */
 		--shadow->lockcnt;
@@ -591,7 +626,8 @@ int pthread_mutex_unlock(pthread_mutex_t
 		return 0;
 	}
 
-	pse51_mutex_unlock_internal(cur, mutex);
+	if (xnsynch_release(&mutex->synchbase))
+		xnpod_schedule();
 
   out:
 	cb_read_unlock(&shadow->lock, s);
Index: b/ksrc/skins/posix/mutex.h
===================================================================
--- a/ksrc/skins/posix/mutex.h
+++ b/ksrc/skins/posix/mutex.h
@@ -30,8 +30,8 @@ union __xeno_mutex {
 		unsigned magic;
 		unsigned lockcnt;
 		struct pse51_mutex *mutex;
-#ifdef CONFIG_XENO_FASTSYNCH
 		xnarch_atomic_t lock;
+#ifdef CONFIG_XENO_FASTSYNCH
 		union {
 			unsigned owner_offset;
 			xnarch_atomic_t *owner;
@@ -54,9 +54,7 @@ typedef struct pse51_mutex {
 #define link2mutex(laddr)                                               \
 	((pse51_mutex_t *)(((char *)laddr) - offsetof(pse51_mutex_t, link)))
 
-	xnarch_atomic_t *owner;
 	pthread_mutexattr_t attr;
-	unsigned sleepers;
 	pse51_kqueues_t *owningq;
 } pse51_mutex_t;
 
@@ -83,145 +81,52 @@ int pse51_mutex_init_internal(struct __s
 void pse51_mutex_destroy_internal(pse51_mutex_t *mutex,
 				  pse51_kqueues_t *q);
 
-static inline xnthread_t *
-pse51_mutex_trylock_internal(xnthread_t *cur,
-			     struct __shadow_mutex *shadow, unsigned count)
+/* must be called with nklock locked, interrupts off. */
+static inline int pse51_mutex_timedlock_internal(xnthread_t *cur,
+						 struct __shadow_mutex *shadow,
+						 unsigned count,
+						 int timed,
+						 xnticks_t abs_to)
+
 {
 	pse51_mutex_t *mutex = shadow->mutex;
-	xnhandle_t ownerh;
-	xnthread_t *owner;
 
 	if (xnpod_unblockable_p())
-		return ERR_PTR(-EPERM);
+		return -EPERM;
 
 	if (!pse51_obj_active(shadow, PSE51_MUTEX_MAGIC, struct __shadow_mutex))
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
 #if XENO_DEBUG(POSIX)
 	if (mutex->owningq != pse51_kqueues(mutex->attr.pshared))
-		return ERR_PTR(-EPERM);
+		return -EPERM;
 #endif /* XENO_DEBUG(POSIX) */
 
-	ownerh = xnarch_atomic_cmpxchg(mutex->owner, XN_NO_HANDLE,
-				       xnthread_handle(cur));
-	if (unlikely(ownerh != XN_NO_HANDLE)) {
-		owner = xnthread_lookup(clear_claimed(ownerh));
-		if (!owner)
-			return ERR_PTR(-EINVAL);
-		return owner;
-	}
-
-	shadow->lockcnt = count;
-	return NULL;
-}
-
-/* must be called with nklock locked, interrupts off. */
-static inline int pse51_mutex_timedlock_internal(xnthread_t *cur,
-						 struct __shadow_mutex *shadow,
-						 unsigned count,
-						 int timed,
-						 xnticks_t abs_to)
-
-{
-	pse51_mutex_t *mutex;
-	xnthread_t *owner;
-	xnhandle_t ownerh, old;
-	spl_t s;
-	int err;
-
-  retry_lock:
-	owner = pse51_mutex_trylock_internal(cur, shadow, count);
-	if (likely(!owner) || IS_ERR(owner))
-		return PTR_ERR(owner);
-
-	mutex = shadow->mutex;
-	if (owner == cur)
+#ifdef CONFIG_XENO_FASTSYNCH
+	if (xnsynch_fast_owner_check(mutex->synchbase.fastlock,
+				     xnthread_handle(cur)) == 0)
+#else /* !CONFIG_XENO_FASTSYNCH */
+	if (xnsynch_owner(&mutex->synchbase) == cur)
+#endif /* !CONFIG_XENO_FASTSYNCH */
 		return -EBUSY;
 
-	/* Set bit 0, so that mutex_unlock will know that the mutex is claimed.
-	   Hold the nklock, for mutual exclusion with slow mutex_unlock. */
-	xnlock_get_irqsave(&nklock, s);
-	if (test_claimed(ownerh)) {
-		old = xnarch_atomic_get(mutex->owner);
-		goto test_no_owner;
-	}
-	do {
-		old = xnarch_atomic_cmpxchg(mutex->owner, ownerh,
-					    set_claimed(ownerh, 1));
-		if (likely(old == ownerh))
-			break;
-	  test_no_owner:
-		if (old == XN_NO_HANDLE) {
-			/* Owner called fast mutex_unlock
-			   (on another cpu) */
-			xnlock_put_irqrestore(&nklock, s);
-			goto retry_lock;
-		}
-		ownerh = old;
-	} while (!test_claimed(ownerh));
-
-	owner = xnthread_lookup(clear_claimed(ownerh));
-
-	if (unlikely(!owner)) {
-		err = -EINVAL;
-		goto error;
-	}
-
-	xnsynch_set_owner(&mutex->synchbase, owner);
-	++mutex->sleepers;
 	if (timed)
 		xnsynch_acquire(&mutex->synchbase, abs_to, XN_REALTIME);
 	else
 		xnsynch_acquire(&mutex->synchbase, XN_INFINITE, XN_RELATIVE);
-	--mutex->sleepers;
 
-	if (xnthread_test_info(cur, XNBREAK)) {
-		err = -EINTR;
-		goto error;
-	}
-	if (xnthread_test_info(cur, XNRMID)) {
-		err = -EINVAL;
-		goto error;
-	}
-	if (xnthread_test_info(cur, XNTIMEO)) {
-		err = -ETIMEDOUT;
-		goto error;
+	if (unlikely(xnthread_test_info(cur, XNBREAK | XNRMID | XNTIMEO))) {
+		if (xnthread_test_info(cur, XNBREAK))
+			return -EINTR;
+		else if (xnthread_test_info(cur, XNTIMEO))
+			return -ETIMEDOUT;
+		else /* XNRMID */
+			return -EINVAL;
 	}
 
-	ownerh = set_claimed(xnthread_handle(cur), mutex->sleepers);
-	xnarch_atomic_set(mutex->owner, ownerh);
 	shadow->lockcnt = count;
-	xnlock_put_irqrestore(&nklock, s);
 
 	return 0;
-
-  error:
-	if (!mutex->sleepers)
-		xnarch_atomic_set
-			(mutex->owner,
-			 clear_claimed(xnarch_atomic_get(mutex->owner)));
-	xnlock_put_irqrestore(&nklock, s);
-	return err;
-}
-
-static inline void pse51_mutex_unlock_internal(xnthread_t *cur,
-					       pse51_mutex_t *mutex)
-{
-	xnhandle_t ownerh;
-	xnthread_t *owner;
-	spl_t s;
-
-	if (likely(xnarch_atomic_cmpxchg(mutex->owner, cur, XN_NO_HANDLE) ==
-		   xnthread_handle(cur)))
-		return;
-
-	xnlock_get_irqsave(&nklock, s);
-	owner = xnsynch_release(&mutex->synchbase);
-	ownerh = set_claimed(xnthread_handle(owner), mutex->sleepers);
-	xnarch_atomic_set(mutex->owner, ownerh);
-	if (owner)
-		xnpod_schedule();
-	xnlock_put_irqrestore(&nklock, s);
 }
 
 #endif /* __KERNEL__ */
Index: b/ksrc/skins/posix/syscall.c
===================================================================
--- a/ksrc/skins/posix/syscall.c
+++ b/ksrc/skins/posix/syscall.c
@@ -1060,13 +1060,10 @@ static int __pthread_mutex_unlock(struct
 
 	mutex = shadow->mutex;
 
-	if (clear_claimed(xnarch_atomic_get(mutex->owner)) !=
-	    xnthread_handle(cur)) {
-		err = -EPERM;
+	err = (xnsynch_owner(&mutex->synchbase) == cur) ? 0 : -EPERM;
+	if (err)
 		goto out;
-	}
 
-	err = 0;
 	if (shadow->lockcnt > 1) {
 		/* Mutex is recursive */
 		--shadow->lockcnt;
@@ -1080,8 +1077,9 @@ static int __pthread_mutex_unlock(struct
 
 		return 0;
 	}
-	
-	pse51_mutex_unlock_internal(cur, mutex);
+
+	if (xnsynch_release(&mutex->synchbase))
+		xnpod_schedule();
 
   out:
 	cb_read_unlock(&shadow->lock, s);
@@ -1186,13 +1184,11 @@ static int __pthread_mutex_destroy(struc
 	if (pse51_kqueues(mutex->attr.pshared) != mutex->owningq)
 		return -EPERM;
 
-	if (xnarch_atomic_get(mutex->owner) != XN_NO_HANDLE)
+	if (xnsynch_fast_owner_check(mutex->synchbase.fastlock,
+				     XN_NO_HANDLE) != 0)
 		return -EBUSY;
 
 	pse51_mark_deleted(shadow);
-	if (!mutex->attr.pshared)
-		xnheap_free(&xnsys_ppd_get(mutex->attr.pshared)->sem_heap,
-			    mutex->owner);
 	pse51_mutex_destroy_internal(mutex, mutex->owningq);
 
 	return __xn_safe_copy_to_user((void __user *)&umx->shadow_mutex,
@@ -1262,7 +1258,6 @@ static int __pthread_mutex_timedlock(str
 
 static int __pthread_mutex_unlock(struct pt_regs *regs)
 {
-	xnthread_t *cur = xnpod_current_thread();
 	union __xeno_mutex mx, *umx;
 
 	if (xnpod_root_p())
@@ -1275,7 +1270,8 @@ static int __pthread_mutex_unlock(struct
 				     offsetof(struct __shadow_mutex, lock)))
 		return -EFAULT;
 
-	pse51_mutex_unlock_internal(cur, mx.shadow_mutex.mutex);
+	if (xnsynch_release(&mx.shadow_mutex.mutex->synchbase))
+		xnpod_schedule();
 
 	return 0;
 }
Index: b/src/skins/posix/mutex.c
===================================================================
--- a/src/skins/posix/mutex.c
+++ b/src/skins/posix/mutex.c
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <pthread.h>
 #include <limits.h>
+#include <nucleus/synch.h>
 #include <posix/mutex.h>
 #include <posix/syscall.h>
 #include <posix/cb_lock.h>
@@ -146,10 +147,10 @@ int __wrap_pthread_mutex_lock(pthread_mu
 {
 	union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
 	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
-	int err = 0;
+	int err;
 
 #ifdef CONFIG_XENO_FASTSYNCH
-	xnhandle_t cur, owner;
+	xnhandle_t cur;
 
 	cur = xeno_get_current();
 	if (cur == XN_NO_HANDLE)
@@ -163,14 +164,15 @@ int __wrap_pthread_mutex_lock(pthread_mu
 		goto out;
 	}
 
-	owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
-	if (likely(owner == XN_NO_HANDLE)) {
+	err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
+
+	if (likely(!err)) {
 		shadow->lockcnt = 1;
 		cb_read_unlock(&shadow->lock, s);
 		return 0;
 	}
 
-	if (clear_claimed(owner) == cur)
+	if (err == -EBUSY)
 		switch(shadow->attr.type) {
 		case PTHREAD_MUTEX_NORMAL:
 			break;
@@ -184,8 +186,8 @@ int __wrap_pthread_mutex_lock(pthread_mu
 				err = -EAGAIN;
 				goto out;
 			}
-
 			++shadow->lockcnt;
+			err = 0;
 			goto out;
 		}
 #endif /* CONFIG_XENO_FASTSYNCH */
@@ -207,10 +209,10 @@ int __wrap_pthread_mutex_timedlock(pthre
 {
 	union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
 	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
-	int err = 0;
+	int err;
 
 #ifdef CONFIG_XENO_FASTSYNCH
-	xnhandle_t cur, owner;
+	xnhandle_t cur;
 
 	cur = xeno_get_current();
 	if (cur == XN_NO_HANDLE)
@@ -224,14 +226,15 @@ int __wrap_pthread_mutex_timedlock(pthre
 		goto out;
 	}	
 
-	owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
-	if (likely(owner == XN_NO_HANDLE)) {
+	err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
+
+	if (likely(!err)) {
 		shadow->lockcnt = 1;
 		cb_read_unlock(&shadow->lock, s);
 		return 0;
 	}
 
-	if (clear_claimed(owner) == cur)
+	if (err == -EBUSY)
 		switch(shadow->attr.type) {
 		case PTHREAD_MUTEX_NORMAL:
 			break;
@@ -268,10 +271,10 @@ int __wrap_pthread_mutex_trylock(pthread
 {
 	union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
 	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
-	int err = 0;
+	int err;
 
 #ifdef CONFIG_XENO_FASTSYNCH
-	xnhandle_t cur, owner;
+	xnhandle_t cur;
 
 	cur = xeno_get_current();
 	if (cur == XN_NO_HANDLE)
@@ -285,23 +288,23 @@ int __wrap_pthread_mutex_trylock(pthread
 		goto out;
 	}	
 
-	owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
-	if (likely(owner == XN_NO_HANDLE)) {
+	err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
+
+	if (likely(!err)) {
 		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 (err == -EBUSY && shadow->attr.type == PTHREAD_MUTEX_RECURSIVE) {
 		if (shadow->lockcnt == UINT_MAX)
 			err = -EAGAIN;
 		else {
 			++shadow->lockcnt;
 			err = 0;
 		}
-	}
+	} else
+		err = -EBUSY;
 
   out:
 	cb_read_unlock(&shadow->lock, s);
@@ -322,11 +325,11 @@ int __wrap_pthread_mutex_unlock(pthread_
 {
 	union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
 	struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
-	int err = 0;
+	int err;
 
 #ifdef CONFIG_XENO_FASTSYNCH
 	xnarch_atomic_t *ownerp;
-	xnhandle_t cur, owner;
+	xnhandle_t cur;
 
 	cur = xeno_get_current();
 	if (cur == XN_NO_HANDLE)
@@ -341,19 +344,17 @@ int __wrap_pthread_mutex_unlock(pthread_
 	}
 
 	ownerp = get_ownerp(shadow);
-	owner = clear_claimed(xnarch_atomic_get(ownerp));
-	if (unlikely(owner != cur)) {
-		err = -EPERM;
+
+	err = xnsynch_fast_owner_check(ownerp, cur);
+	if (unlikely(err))
 		goto out_err;
-	}
 
-	err = 0;
 	if (shadow->lockcnt > 1) {
 		--shadow->lockcnt;
 		goto out;
 	}
 
-	if (likely(xnarch_atomic_cmpxchg(ownerp, cur, XN_NO_HANDLE) == cur)) {
+	if (likely(xnsynch_fast_release(ownerp, cur))) {
 	  out:
 		cb_read_unlock(&shadow->lock, s);
 		return 0;



^ permalink raw reply	[flat|nested] 50+ messages in thread

* [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
                   ` (6 preceding siblings ...)
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 07/12] Convert POSIX skin to fast xnsynch Jan Kiszka
@ 2008-10-16 15:46 ` Jan Kiszka
  2008-10-16 20:13   ` Gilles Chanteperdrix
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 09/12] Optionally replace pthread_getspecific with TLS variables Jan Kiszka
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 15:46 UTC (permalink / raw)
  To: xenomai; +Cc: Jan Kiszka

[-- Attachment #1: switch-native-to-fast-xnsynch.patch --]
[-- Type: text/plain, Size: 25949 bytes --]

Implement a fast path for rt_mutex_acquire/release, making use of fast
xnsynch services. Just as for the POSIX skin, lock stealing via trylock
is sacrificed for a syscall-less user space implementation.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/native/mutex.h      |   23 ++-
 ksrc/skins/native/cond.c    |   16 +-
 ksrc/skins/native/mutex.c   |  314 ++++++++++++++++++++++++++------------------
 ksrc/skins/native/syscall.c |   70 +++++++--
 src/skins/native/cond.c     |   30 ++++
 src/skins/native/mutex.c    |  102 +++++++++++++-
 6 files changed, 398 insertions(+), 157 deletions(-)

Index: b/include/native/mutex.h
===================================================================
--- a/include/native/mutex.h
+++ b/include/native/mutex.h
@@ -32,7 +32,7 @@ struct rt_task;
  */
 typedef struct rt_mutex_info {
 
-	int lockcnt;		/**< Lock nesting level (> 0 means "locked"). */
+	int locked;		/**< > 0 if mutex is locked. */
 
 	int nwaiters;		/**< Number of pending tasks. */
 
@@ -44,7 +44,15 @@ typedef struct rt_mutex_info {
 } RT_MUTEX_INFO;
 
 typedef struct rt_mutex_placeholder {
+
 	xnhandle_t opaque;
+
+#ifdef CONFIG_XENO_FASTSYNCH
+	xnarch_atomic_t *fastlock;
+
+	int lockcnt;
+#endif /* CONFIG_XENO_FASTSYNCH */
+
 } RT_MUTEX_PLACEHOLDER;
 
 #if (defined(__KERNEL__) || defined(__XENO_SIM__)) && !defined(DOXYGEN_CPP)
@@ -54,6 +62,8 @@ typedef struct rt_mutex_placeholder {
 
 #define XENO_MUTEX_MAGIC 0x55550505
 
+#define RT_MUTEX_EXPORTED	XNSYNCH_SPARE0	/* Mutex registered by name */
+
 typedef struct __rt_mutex {
 
 	unsigned magic;		/* !< Magic code - must be first */
@@ -74,7 +84,7 @@ typedef struct __rt_mutex {
 
 #define rlink2mutex(ln)		container_of(ln, RT_MUTEX, rlink)
 
-    xnqueue_t *rqueue;		/* !< Backpointer to resource queue. */
+	xnqueue_t *rqueue;	/* !< Backpointer to resource queue. */
 
 } RT_MUTEX;
 
@@ -93,9 +103,8 @@ static inline void __native_mutex_flush_
 	xeno_flush_rq(RT_MUTEX, rq, mutex);
 }
 
-int rt_mutex_acquire_inner(RT_MUTEX *mutex,
-			   xntmode_t timeout_mode,
-			   RTIME timeout);
+int rt_mutex_acquire_inner(RT_MUTEX *mutex, RTIME timeout,
+			   xntmode_t timeout_mode);
 
 #else /* !CONFIG_XENO_OPT_NATIVE_MUTEX */
 
@@ -138,6 +147,10 @@ static inline int rt_mutex_unbind (RT_MU
 extern "C" {
 #endif
 
+int rt_mutex_create_inner(RT_MUTEX *mutex, const char *name,
+			  xnarch_atomic_t *fastlock);
+int rt_mutex_delete_inner(RT_MUTEX *mutex);
+
 /* Public interface. */
 
 int rt_mutex_create(RT_MUTEX *mutex,
Index: b/ksrc/skins/native/cond.c
===================================================================
--- a/ksrc/skins/native/cond.c
+++ b/ksrc/skins/native/cond.c
@@ -407,24 +407,26 @@ int rt_cond_wait_inner(RT_COND *cond, RT
 
 	thread = xnpod_current_thread();
 
-	if (thread != xnsynch_owner(&mutex->synch_base)) {
+#ifdef CONFIG_XENO_FASTSYNCH
+	if (xnsynch_fast_owner_check(mutex->synch_base.fastlock,
+				     xnthread_handle(thread)) != 0) {
+#else /* !CONFIG_XENO_FASTSYNCH */
+	if (xnsynch_owner(&mutex->synch_base) != thread) {
+#endif /* !CONFIG_XENO_FASTSYNCH */
 		err = -EPERM;
 		goto unlock_and_exit;
 	}
 
 	/*
 	 * We can't use rt_mutex_release since that might reschedule
-	 * before enter xnsynch_sleep_on, hence most of the code is
-	 * duplicated here.
+	 * before enter xnsynch_sleep_on.
 	 */
 	lockcnt = mutex->lockcnt; /* Leave even if mutex is nested */
 
 	mutex->lockcnt = 0;
 
-	if (xnsynch_release(&mutex->synch_base)) {
-		mutex->lockcnt = 1;
-		/* Scheduling deferred */
-	}
+	xnsynch_release(&mutex->synch_base);
+	/* Scheduling deferred */
 
 	xnsynch_sleep_on(&cond->synch_base, timeout, timeout_mode);
 
Index: b/ksrc/skins/native/mutex.c
===================================================================
--- a/ksrc/skins/native/mutex.c
+++ b/ksrc/skins/native/mutex.c
@@ -57,29 +57,42 @@ static int __mutex_read_proc(char *page,
 			     off_t off, int count, int *eof, void *data)
 {
 	RT_MUTEX *mutex = (RT_MUTEX *)data;
+#ifdef CONFIG_XENO_FASTSYNCH
+	xnhandle_t lock_state;
+#endif /* CONFIG_XENO_FASTSYNCH */
+	xnthread_t *owner;
 	char *p = page;
 	int len;
 	spl_t s;
 
 	xnlock_get_irqsave(&nklock, s);
 
-	if (xnsynch_owner(&mutex->synch_base) != NULL) {
-		xnpholder_t *holder;
+#ifndef CONFIG_XENO_FASTSYNCH
+	owner = xnsynch_owner(&mutex->synch_base);
+#else /* CONFIG_XENO_FASTSYNCH */
+	lock_state = xnarch_atomic_get(mutex->synch_base.fastlock);
+
+	owner = (lock_state == XN_NO_HANDLE) ? NULL :
+		xnthread_lookup(xnsynch_fast_mask_claimed(lock_state));
 
+	if (!owner && lock_state != XN_NO_HANDLE)
+		p += sprintf(p, "=<DAMAGED HANDLE!>");
+	else
+#endif /* CONFIG_XENO_FASTSYNCH */
+	if (owner) {
 		/* Locked mutex -- dump owner and waiters, if any. */
+		xnpholder_t *holder;
 
-		p += sprintf(p, "=locked by %s depth=%d\n",
-			     xnthread_name(xnsynch_owner(&mutex->synch_base)),
-			     mutex->lockcnt);
+		p += sprintf(p, "=locked by %s\n", xnthread_name(owner));
 
 		holder = getheadpq(xnsynch_wait_queue(&mutex->synch_base));
 
 		while (holder) {
 			xnthread_t *sleeper = link2thread(holder, plink);
+
 			p += sprintf(p, "+%s\n", xnthread_name(sleeper));
-			holder =
-			    nextpq(xnsynch_wait_queue(&mutex->synch_base),
-				   holder);
+			holder = nextpq(xnsynch_wait_queue(&mutex->synch_base),
+					holder);
 		}
 	} else
 		/* Mutex unlocked. */
@@ -120,49 +133,8 @@ static xnpnode_t __mutex_pnode = {
 
 #endif /* CONFIG_XENO_EXPORT_REGISTRY */
 
-/**
- * @fn int rt_mutex_create(RT_MUTEX *mutex,const char *name)
- *
- * @brief Create a mutex.
- *
- * Create a mutual exclusion object that allows multiple tasks to
- * synchronize access to a shared resource. A mutex is left in an
- * unlocked state after creation.
- *
- * @param mutex The address of a mutex descriptor Xenomai will use to
- * store the mutex-related data.  This descriptor must always be valid
- * while the mutex is active therefore it must be allocated in
- * permanent memory.
- *
- * @param name An ASCII string standing for the symbolic name of the
- * mutex. When non-NULL and non-empty, this string is copied to a safe
- * place into the descriptor, and passed to the registry package if
- * enabled for indexing the created mutex.
- *
- * @return 0 is returned upon success. Otherwise:
- *
- * - -ENOMEM is returned if the system fails to get enough dynamic
- * memory from the global real-time heap in order to register the
- * mutex.
- *
- * - -EEXIST is returned if the @a name is already in use by some
- * registered object.
- *
- * - -EPERM is returned if this service was called from an
- * asynchronous context.
- *
- * Environments:
- *
- * This service can be called from:
- *
- * - Kernel module initialization/cleanup code
- * - Kernel-based task
- * - User-space task
- *
- * Rescheduling: possible.
- */
-
-int rt_mutex_create(RT_MUTEX *mutex, const char *name)
+int rt_mutex_create_inner(RT_MUTEX *mutex, const char *name,
+			  xnarch_atomic_t *fastlock)
 {
 	int err = 0;
 	spl_t s;
@@ -171,7 +143,7 @@ int rt_mutex_create(RT_MUTEX *mutex, con
 		return -EPERM;
 
 	xnsynch_init(&mutex->synch_base,
-		     XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER, NULL);
+		     XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER, fastlock);
 	mutex->handle = 0;	/* i.e. (still) unregistered mutex. */
 	mutex->magic = XENO_MUTEX_MAGIC;
 	mutex->lockcnt = 0;
@@ -196,7 +168,7 @@ int rt_mutex_create(RT_MUTEX *mutex, con
 				       &__mutex_pnode);
 
 		if (err)
-			rt_mutex_delete(mutex);
+			rt_mutex_delete_inner(mutex);
 	}
 #endif /* CONFIG_XENO_OPT_REGISTRY */
 
@@ -204,22 +176,32 @@ int rt_mutex_create(RT_MUTEX *mutex, con
 }
 
 /**
- * @fn int rt_mutex_delete(RT_MUTEX *mutex)
+ * @fn int rt_mutex_create(RT_MUTEX *mutex,const char *name)
  *
- * @brief Delete a mutex.
+ * @brief Create a mutex.
  *
- * Destroy a mutex and release all the tasks currently pending on it.
- * A mutex exists in the system since rt_mutex_create() has been
- * called to create it, so this service must be called in order to
- * destroy it afterwards.
+ * Create a mutual exclusion object that allows multiple tasks to
+ * synchronize access to a shared resource. A mutex is left in an
+ * unlocked state after creation.
  *
- * @param mutex The descriptor address of the affected mutex.
+ * @param mutex The address of a mutex descriptor Xenomai will use to
+ * store the mutex-related data.  This descriptor must always be valid
+ * while the mutex is active therefore it must be allocated in
+ * permanent memory.
+ *
+ * @param name An ASCII string standing for the symbolic name of the
+ * mutex. When non-NULL and non-empty, this string is copied to a safe
+ * place into the descriptor, and passed to the registry package if
+ * enabled for indexing the created mutex.
  *
  * @return 0 is returned upon success. Otherwise:
  *
- * - -EINVAL is returned if @a mutex is not a mutex descriptor.
+ * - -ENOMEM is returned if the system fails to get enough dynamic
+ * memory from the global real-time heap in order to register the
+ * mutex.
  *
- * - -EIDRM is returned if @a mutex is a deleted mutex descriptor.
+ * - -EEXIST is returned if the @a name is already in use by some
+ * registered object.
  *
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
@@ -235,7 +217,30 @@ int rt_mutex_create(RT_MUTEX *mutex, con
  * Rescheduling: possible.
  */
 
-int rt_mutex_delete(RT_MUTEX *mutex)
+int rt_mutex_create(RT_MUTEX *mutex, const char *name)
+{
+	xnarch_atomic_t *fastlock = NULL;
+	int err;
+
+#ifdef CONFIG_XENO_FASTSYNCH
+	/* Allocate lock memory for in-kernel use */
+	fastlock = xnmalloc(sizeof(xnarch_atomic_t));
+
+	if (!fastlock)
+		return -ENOMEM;
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+	err = rt_mutex_create_inner(mutex, name, fastlock);
+
+#ifdef CONFIG_XENO_FASTSYNCH
+	if (err)
+		xnfree(fastlock);
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+	return err;
+}
+
+int rt_mutex_delete_inner(RT_MUTEX *mutex)
 {
 	int err = 0, rc;
 	spl_t s;
@@ -275,61 +280,116 @@ int rt_mutex_delete(RT_MUTEX *mutex)
 	return err;
 }
 
-int rt_mutex_acquire_inner(RT_MUTEX *mutex, xntmode_t timeout_mode, RTIME timeout)
+/**
+ * @fn int rt_mutex_delete(RT_MUTEX *mutex)
+ *
+ * @brief Delete a mutex.
+ *
+ * Destroy a mutex and release all the tasks currently pending on it.
+ * A mutex exists in the system since rt_mutex_create() has been
+ * called to create it, so this service must be called in order to
+ * destroy it afterwards.
+ *
+ * @param mutex The descriptor address of the affected mutex.
+ *
+ * @return 0 is returned upon success. Otherwise:
+ *
+ * - -EINVAL is returned if @a mutex is not a mutex descriptor.
+ *
+ * - -EIDRM is returned if @a mutex is a deleted mutex descriptor.
+ *
+ * - -EPERM is returned if this service was called from an
+ * asynchronous context.
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Kernel-based task
+ * - User-space task
+ *
+ * Rescheduling: possible.
+ */
+
+int rt_mutex_delete(RT_MUTEX *mutex)
+{
+	int err;
+
+	err = rt_mutex_delete_inner(mutex);
+
+#ifdef CONFIG_XENO_FASTSYNCH
+	if (!err)
+		xnfree(mutex->synch_base.fastlock);
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+	return err;
+}
+
+int rt_mutex_acquire_inner(RT_MUTEX *mutex, RTIME timeout,
+			   xntmode_t timeout_mode)
 {
 	xnthread_t *thread;
-	int err = 0;
-	spl_t s;
 
 	if (xnpod_unblockable_p())
 		return -EPERM;
 
-	xnlock_get_irqsave(&nklock, s);
-
 	mutex = xeno_h2obj_validate(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
 
-	if (!mutex) {
-		err = xeno_handle_error(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
-		goto unlock_and_exit;
-	}
+	if (!mutex)
+		return xeno_handle_error(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
 
 	thread = xnpod_current_thread();
 
-	if (xnsynch_owner(&mutex->synch_base) == NULL) {
-		xnsynch_set_owner(&mutex->synch_base, thread);
-		goto grab_mutex;
-	}
-
+#ifdef CONFIG_XENO_FASTSYNCH
+	if (xnsynch_fast_owner_check(mutex->synch_base.fastlock,
+				     xnthread_handle(thread)) == 0) {
+#else /* !CONFIG_XENO_FASTSYNCH */
 	if (xnsynch_owner(&mutex->synch_base) == thread) {
+#endif /* !CONFIG_XENO_FASTSYNCH */
 		mutex->lockcnt++;
-		goto unlock_and_exit;
+		return 0;
 	}
 
-	if (timeout == TM_NONBLOCK) {
-		err = -EWOULDBLOCK;
-		goto unlock_and_exit;
+	if (timeout == TM_NONBLOCK && timeout_mode == XN_RELATIVE) {
+#ifdef CONFIG_XENO_FASTSYNCH
+		if (xnsynch_fast_acquire(mutex->synch_base.fastlock,
+					 xnthread_handle(thread)) == 0) {
+			mutex->lockcnt = 1;
+			return 0;
+		} else
+			return -EWOULDBLOCK;
+
+#else /* !CONFIG_XENO_FASTSYNCH */
+		int err = 0;
+		spl_t s;
+
+		xnlock_get_irqsave(&nklock, s);
+		if (xnsynch_owner(&mutex->synch_base) == NULL)
+			mutex->lockcnt = 1;
+		else
+			err = -EWOULDBLOCK;
+		xnlock_put_irqrestore(&nklock, s);
+		return err;
+#endif /* !CONFIG_XENO_FASTSYNCH */
 	}
 
 	xnsynch_acquire(&mutex->synch_base, timeout, timeout_mode);
 
-	if (xnthread_test_info(thread, XNRMID))
-		err = -EIDRM;	/* Mutex deleted while pending. */
-	else if (xnthread_test_info(thread, XNTIMEO))
-		err = -ETIMEDOUT;	/* Timeout. */
-	else if (xnthread_test_info(thread, XNBREAK))
-		err = -EINTR;	/* Unblocked. */
-	else {
-	      grab_mutex:
-		/* xnsynch_sleep_on() might have stolen the resource,
-		   so we need to put our internal data in sync. */
-		mutex->lockcnt = 1;
+	if (unlikely(xnthread_test_info(thread, XNBREAK | XNRMID | XNTIMEO))) {
+		if (xnthread_test_info(thread, XNBREAK))
+			return -EINTR;
+		else if (xnthread_test_info(thread, XNTIMEO))
+			return -ETIMEDOUT;
+		else /* XNRMID */
+			return -EIDRM;
 	}
 
-      unlock_and_exit:
+	/* xnsynch_sleep_on() might have stolen the resource,
+	   so we need to put our internal data in sync. */
+	mutex->lockcnt = 1;
 
-	xnlock_put_irqrestore(&nklock, s);
-
-	return err;
+	return 0;
 }
 
 /**
@@ -398,7 +458,7 @@ int rt_mutex_acquire_inner(RT_MUTEX *mut
 
 int rt_mutex_acquire(RT_MUTEX *mutex, RTIME timeout)
 {
-	return rt_mutex_acquire_inner(mutex, XN_RELATIVE, timeout);
+	return rt_mutex_acquire_inner(mutex, timeout, XN_RELATIVE);
 }
 
 /**
@@ -464,7 +524,7 @@ int rt_mutex_acquire(RT_MUTEX *mutex, RT
 
 int rt_mutex_acquire_until(RT_MUTEX *mutex, RTIME timeout)
 {
-	return rt_mutex_acquire_inner(mutex, XN_REALTIME, timeout);
+	return rt_mutex_acquire_inner(mutex, timeout, XN_REALTIME);
 }
 
 /**
@@ -501,39 +561,33 @@ int rt_mutex_acquire_until(RT_MUTEX *mut
 
 int rt_mutex_release(RT_MUTEX *mutex)
 {
-	int err = 0;
-	spl_t s;
+	xnthread_t *thread = xnpod_current_thread();
+	int err;
 
 	if (xnpod_unblockable_p())
 		return -EPERM;
 
-	xnlock_get_irqsave(&nklock, s);
-
 	mutex = xeno_h2obj_validate(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
 
-	if (!mutex) {
-		err = xeno_handle_error(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
-		goto unlock_and_exit;
-	}
+	if (!mutex)
+		return xeno_handle_error(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
 
-	if (xnpod_current_thread() != xnsynch_owner(&mutex->synch_base)) {
-		err = -EPERM;
-		goto unlock_and_exit;
-	}
+#ifdef CONFIG_XENO_FASTSYNCH
+	err = xnsynch_fast_owner_check(mutex->synch_base.fastlock,
+					xnthread_handle(thread));
+#else /* !CONFIG_XENO_FASTSYNCH */
+	err = (xnsynch_owner(&mutex->synch_base) == thread) ? 0 : -EPERM;
+#endif /* !CONFIG_XENO_FASTSYNCH */
+	if (err)
+		return err;
 
 	if (--mutex->lockcnt > 0)
-		goto unlock_and_exit;
+		return 0;
 
-	if (xnsynch_release(&mutex->synch_base)) {
-		mutex->lockcnt = 1;
+	if (xnsynch_release(&mutex->synch_base))
 		xnpod_schedule();
-	}
 
-      unlock_and_exit:
-
-	xnlock_put_irqrestore(&nklock, s);
-
-	return err;
+	return 0;
 }
 
 /**
@@ -569,6 +623,10 @@ int rt_mutex_release(RT_MUTEX *mutex)
 
 int rt_mutex_inquire(RT_MUTEX *mutex, RT_MUTEX_INFO *info)
 {
+#ifdef CONFIG_XENO_FASTSYNCH
+	xnhandle_t lock_state;
+#endif /* CONFIG_XENO_FASTSYNCH */
+	xnthread_t *owner;
 	int err = 0;
 	spl_t s;
 
@@ -582,11 +640,21 @@ int rt_mutex_inquire(RT_MUTEX *mutex, RT
 	}
 
 	strcpy(info->name, mutex->name);
-	info->lockcnt = mutex->lockcnt;
 	info->nwaiters = xnsynch_nsleepers(&mutex->synch_base);
-	if (mutex->lockcnt)
-		strcpy(info->owner,
-		       xnthread_name(xnsynch_owner(&mutex->synch_base)));
+
+#ifndef CONFIG_XENO_FASTSYNCH
+	owner = xnsynch_owner(&mutex->synch_base);
+#else /* CONFIG_XENO_FASTSYNCH */
+	lock_state = xnarch_atomic_get(mutex->synch_base.fastlock);
+	info->locked = (lock_state != XN_NO_HANDLE);
+	owner = (info->locked) ?
+		xnthread_lookup(xnsynch_fast_mask_claimed(lock_state)) : NULL;
+	if (!owner && info->locked)
+		strcpy(info->owner, "<DAMAGED HANDLE!>");
+	else
+#endif /* CONFIG_XENO_FASTSYNCH */
+	if (owner)
+		strcpy(info->owner, xnthread_name(owner));
 	else
 		info->owner[0] = 0;
 
Index: b/ksrc/skins/native/syscall.c
===================================================================
--- a/ksrc/skins/native/syscall.c
+++ b/ksrc/skins/native/syscall.c
@@ -24,6 +24,7 @@
 #include <nucleus/heap.h>
 #include <nucleus/shadow.h>
 #include <nucleus/registry.h>
+#include <nucleus/sys_ppd.h>
 #include <native/syscall.h>
 #include <native/task.h>
 #include <native/timer.h>
@@ -1532,6 +1533,8 @@ static int __rt_event_inquire(struct pt_
 static int __rt_mutex_create(struct pt_regs *regs)
 {
 	char name[XNOBJECT_NAME_LEN];
+	xnarch_atomic_t *fastlock = NULL;
+	xnheap_t *sem_heap;
 	RT_MUTEX_PLACEHOLDER ph;
 	RT_MUTEX *mutex;
 	int err;
@@ -1546,22 +1549,45 @@ static int __rt_mutex_create(struct pt_r
 	} else
 		*name = '\0';
 
+	sem_heap = &xnsys_ppd_get(*name != '\0')->sem_heap;
+
 	mutex = (RT_MUTEX *)xnmalloc(sizeof(*mutex));
 
 	if (!mutex)
 		return -ENOMEM;
 
-	err = rt_mutex_create(mutex, name);
+#ifdef CONFIG_XENO_FASTSYNCH
+	fastlock = xnheap_alloc(sem_heap, sizeof(xnarch_atomic_t));
+
+	if (!fastlock) {
+		xnfree(mutex);
+		return -ENOMEM;
+	}
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+	err = rt_mutex_create_inner(mutex, name, fastlock);
 
 	if (err == 0) {
 		mutex->cpid = current->pid;
 		/* Copy back the registry handle to the ph struct. */
 		ph.opaque = mutex->handle;
+#ifdef CONFIG_XENO_FASTSYNCH
+		/* The lock address will be finished in user space. */
+		ph.fastlock =
+			(void *)xnheap_mapped_offset(sem_heap, fastlock);
+		if (*name != '\0')
+			xnsynch_set_flags(&mutex->synch_base,
+					  RT_MUTEX_EXPORTED);
+#endif /* CONFIG_XENO_FASTSYNCH */
 		if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg1(regs), &ph,
 					   sizeof(ph)))
 			err = -EFAULT;
-	} else
+	} else {
+#ifdef CONFIG_XENO_FASTSYNCH
+		xnheap_free(&xnsys_ppd_get(*name != '\0')->sem_heap, fastlock);
+#endif /* CONFIG_XENO_FASTSYNCH */
 		xnfree(mutex);
+	}
 
 	return err;
 }
@@ -1575,15 +1601,22 @@ static int __rt_mutex_create(struct pt_r
 static int __rt_mutex_bind(struct pt_regs *regs)
 {
 	RT_MUTEX_PLACEHOLDER ph;
+	RT_MUTEX *mutex;
 	int err;
 
 	err =
 	    __rt_bind_helper(current, regs, &ph.opaque, XENO_MUTEX_MAGIC,
-			     NULL, 0);
+			     (void **)&mutex, 0);
 
 	if (err)
 		return err;
 
+#ifdef CONFIG_XENO_FASTSYNCH
+	ph.fastlock =
+		(void *)xnheap_mapped_offset(&xnsys_ppd_get(1)->sem_heap,
+					     mutex->synch_base.fastlock);
+#endif /* CONFIG_XENO_FASTSYNCH */
+
 	if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg1(regs), &ph,
 			      sizeof(ph)))
 		return -EFAULT;
@@ -1610,10 +1643,17 @@ static int __rt_mutex_delete(struct pt_r
 	if (!mutex)
 		return -ESRCH;
 
-	err = rt_mutex_delete(mutex);
+	err = rt_mutex_delete_inner(mutex);
 
-	if (!err && mutex->cpid)
+	if (!err && mutex->cpid) {
+#ifdef CONFIG_XENO_FASTSYNCH
+		int global = xnsynch_test_flags(&mutex->synch_base,
+						RT_MUTEX_EXPORTED);
+		xnheap_free(&xnsys_ppd_get(global)->sem_heap,
+			    mutex->synch_base.fastlock);
+#endif /* CONFIG_XENO_FASTSYNCH */
 		xnfree(mutex);
+	}
 
 	return err;
 }
@@ -1626,13 +1666,14 @@ static int __rt_mutex_delete(struct pt_r
 
 static int __rt_mutex_acquire(struct pt_regs *regs)
 {
-	RT_MUTEX_PLACEHOLDER ph;
+	RT_MUTEX_PLACEHOLDER __user *ph;
 	xntmode_t timeout_mode;
+	xnhandle_t mutexh;
 	RT_MUTEX *mutex;
 	RTIME timeout;
 
-	if (__xn_safe_copy_from_user(&ph, (void __user *)__xn_reg_arg1(regs),
-				     sizeof(ph)))
+	ph = (RT_MUTEX_PLACEHOLDER __user *)__xn_reg_arg1(regs);
+	if (__xn_safe_copy_from_user(&mutexh, &ph->opaque, sizeof(mutexh)))
 		return -EFAULT;
 
 	timeout_mode = __xn_reg_arg2(regs);
@@ -1641,12 +1682,12 @@ static int __rt_mutex_acquire(struct pt_
 				     sizeof(timeout)))
 		return -EFAULT;
 
-	mutex = (RT_MUTEX *)xnregistry_fetch(ph.opaque);
+	mutex = (RT_MUTEX *)xnregistry_fetch(mutexh);
 
 	if (!mutex)
 		return -ESRCH;
 
-	return rt_mutex_acquire_inner(mutex, timeout_mode, timeout);
+	return rt_mutex_acquire_inner(mutex, timeout, timeout_mode);
 }
 
 /*
@@ -1655,14 +1696,15 @@ static int __rt_mutex_acquire(struct pt_
 
 static int __rt_mutex_release(struct pt_regs *regs)
 {
-	RT_MUTEX_PLACEHOLDER ph;
+	RT_MUTEX_PLACEHOLDER __user *ph;
+	xnhandle_t mutexh;
 	RT_MUTEX *mutex;
 
-	if (__xn_safe_copy_from_user(&ph, (void __user *)__xn_reg_arg1(regs),
-				     sizeof(ph)))
+	ph = (RT_MUTEX_PLACEHOLDER __user *)__xn_reg_arg1(regs);
+	if (__xn_safe_copy_from_user(&mutexh, &ph->opaque, sizeof(mutexh)))
 		return -EFAULT;
 
-	mutex = (RT_MUTEX *)xnregistry_fetch(ph.opaque);
+	mutex = (RT_MUTEX *)xnregistry_fetch(mutexh);
 
 	if (!mutex)
 		return -ESRCH;
Index: b/src/skins/native/cond.c
===================================================================
--- a/src/skins/native/cond.c
+++ b/src/skins/native/cond.c
@@ -41,16 +41,46 @@ int rt_cond_delete(RT_COND *cond)
 
 int rt_cond_wait(RT_COND *cond, RT_MUTEX *mutex, RTIME timeout)
 {
+#ifdef CONFIG_XENO_FASTSYNCH
+	int saved_lockcnt, err;
+
+	saved_lockcnt = mutex->lockcnt;
+
+	err = XENOMAI_SKINCALL4(__native_muxid,
+				__native_cond_wait, cond, mutex,
+				XN_RELATIVE, &timeout);
+
+	mutex->lockcnt = saved_lockcnt;
+
+	return err;
+
+#else /* !CONFIG_XENO_FASTSYNCH */
 	return XENOMAI_SKINCALL4(__native_muxid,
 				 __native_cond_wait, cond, mutex,
 				 XN_RELATIVE, &timeout);
+#endif /* !CONFIG_XENO_FASTSYNCH */
 }
 
 int rt_cond_wait_until(RT_COND *cond, RT_MUTEX *mutex, RTIME timeout)
 {
+#ifdef CONFIG_XENO_FASTSYNCH
+	int saved_lockcnt, err;
+
+	saved_lockcnt = mutex->lockcnt;
+
+	err = XENOMAI_SKINCALL4(__native_muxid,
+				__native_cond_wait, cond, mutex,
+				XN_REALTIME, &timeout);
+
+	mutex->lockcnt = saved_lockcnt;
+
+	return err;
+
+#else /* !CONFIG_XENO_FASTSYNCH */
 	return XENOMAI_SKINCALL4(__native_muxid,
 				 __native_cond_wait, cond, mutex,
 				 XN_REALTIME, &timeout);
+#endif /* !CONFIG_XENO_FASTSYNCH */
 }
 
 int rt_cond_signal(RT_COND *cond)
Index: b/src/skins/native/mutex.c
===================================================================
--- a/src/skins/native/mutex.c
+++ b/src/skins/native/mutex.c
@@ -16,21 +16,51 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
 
+#include <limits.h>
+#include <nucleus/synch.h>
 #include <native/syscall.h>
 #include <native/mutex.h>
+#include <asm-generic/bits/current.h>
 
 extern int __native_muxid;
+extern unsigned long xeno_sem_heap[2];
 
 int rt_mutex_create(RT_MUTEX *mutex, const char *name)
 {
-	return XENOMAI_SKINCALL2(__native_muxid,
-				 __native_mutex_create, mutex, name);
+	int err;
+
+	err = XENOMAI_SKINCALL2(__native_muxid,
+				__native_mutex_create, mutex, name);
+
+#ifdef CONFIG_XENO_FASTSYNCH
+	if (!err) {
+		mutex->fastlock = (xnarch_atomic_t *)
+			(xeno_sem_heap[(name && *name) ? 1 : 0] +
+			 (unsigned long)mutex->fastlock);
+		mutex->lockcnt = 0;
+	}
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+	return err;
 }
 
 int rt_mutex_bind(RT_MUTEX *mutex, const char *name, RTIME timeout)
 {
-	return XENOMAI_SKINCALL3(__native_muxid,
-				 __native_mutex_bind, mutex, name, &timeout);
+	int err;
+
+	err = XENOMAI_SKINCALL3(__native_muxid,
+				__native_mutex_bind, mutex, name, &timeout);
+
+#ifdef CONFIG_XENO_FASTSYNCH
+	if (!err) {
+		mutex->fastlock = (xnarch_atomic_t *)
+			(xeno_sem_heap[(name && *name) ? 1 : 0] +
+			 (unsigned long)mutex->fastlock);
+		mutex->lockcnt = 0;
+	}
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+	return err;
 }
 
 int rt_mutex_delete(RT_MUTEX *mutex)
@@ -38,20 +68,76 @@ int rt_mutex_delete(RT_MUTEX *mutex)
 	return XENOMAI_SKINCALL1(__native_muxid, __native_mutex_delete, mutex);
 }
 
+static int rt_mutex_acquire_inner(RT_MUTEX *mutex, RTIME timeout, xntmode_t mode)
+{
+	int err;
+#ifdef CONFIG_XENO_FASTSYNCH
+	xnhandle_t cur;
+
+	cur = xeno_get_current();
+	if (!cur)
+		return -EPERM;
+
+	err = xnsynch_fast_acquire(mutex->fastlock, cur);
+	if (likely(!err)) {
+		mutex->lockcnt = 1;
+		return 0;
+	}
+
+	if (err == -EBUSY) {
+		if (mutex->lockcnt == UINT_MAX)
+			return -EAGAIN;
+
+		mutex->lockcnt++;
+		return 0;
+	}
+
+	if (timeout == TM_NONBLOCK && mode == XN_RELATIVE)
+		return -EWOULDBLOCK;
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+	err = XENOMAI_SKINCALL3(__native_muxid,
+				__native_mutex_acquire, mutex, mode, &timeout);
+
+#ifdef CONFIG_XENO_FASTSYNCH
+	if (!err)
+		mutex->lockcnt = 1;
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+	return err;
+}
+
 int rt_mutex_acquire(RT_MUTEX *mutex, RTIME timeout)
 {
-	return XENOMAI_SKINCALL3(__native_muxid,
-				 __native_mutex_acquire, mutex, XN_RELATIVE, &timeout);
+	return rt_mutex_acquire_inner(mutex, timeout, XN_RELATIVE);
 }
 
 int rt_mutex_acquire_until(RT_MUTEX *mutex, RTIME timeout)
 {
-	return XENOMAI_SKINCALL3(__native_muxid,
-				 __native_mutex_acquire, mutex, XN_REALTIME, &timeout);
+	return rt_mutex_acquire_inner(mutex, timeout, XN_REALTIME);
 }
 
 int rt_mutex_release(RT_MUTEX *mutex)
 {
+#ifdef CONFIG_XENO_FASTSYNCH
+	xnhandle_t cur;
+
+	cur = xeno_get_current();
+	if (!cur)
+		return -EPERM;
+
+	if (unlikely(xnsynch_fast_owner_check(mutex->fastlock, cur) != 0))
+		return -EPERM;
+
+	if (mutex->lockcnt > 1) {
+		mutex->lockcnt--;
+		return 0;
+	}
+
+	if (likely(xnsynch_fast_release(mutex->fastlock, cur)))
+		return 0;
+#endif /* CONFIG_XENO_FASTSYNCH */
+
 	return XENOMAI_SKINCALL1(__native_muxid, __native_mutex_release, mutex);
 }
 



^ permalink raw reply	[flat|nested] 50+ messages in thread

* [Xenomai-core] [PATCH 09/12] Optionally replace pthread_getspecific with TLS variables
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
                   ` (7 preceding siblings ...)
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin Jan Kiszka
@ 2008-10-16 15:46 ` Jan Kiszka
  2008-10-16 20:18   ` Gilles Chanteperdrix
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 10/12] Report current shadow thread mode to user space Jan Kiszka
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 15:46 UTC (permalink / raw)
  To: xenomai; +Cc: Jan Kiszka

[-- Attachment #1: optionally-replace-pthread_getspecific-with-tls.patch --]
[-- Type: text/plain, Size: 13153 bytes --]

On architectures that support the __thread storage class and the
initial-exec TLS model, several use cases of pthread_get/setspecific can
be optimized. On x86, e.g., we are able to implement xeno_get_current()
via just two instructions instead of a call into glibc and all the
included pthread_key lookup. The minor downside of initial-exec TLS is
that libraries using such variables are excluded from dlopen.

This patch adds the required check to configure, also installing a
switch (--without-__thread) in order to disable the support if dlopen
compatibility should be required. It adds a __thread-variant for
xeno_get_current and self-references of the current Native, VRTX and
VxWorks tasks.

RTDK's rt_printf services are intentionally not converted as they are
heavy-weighted anyway and depend on the pthread_key destructor
mechanism.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 configure.in                       |   23 +++++++++++++++++++
 include/asm-generic/bits/bind.h    |   44 ++++++++++++++++++++++++++-----------
 include/asm-generic/bits/current.h |   13 +++++++++-
 src/skins/native/init.c            |    8 +++++-
 src/skins/native/task.c            |   21 +++++++++++++++++
 src/skins/vrtx/init.c              |    8 +++++-
 src/skins/vrtx/task.c              |   14 ++++++++++-
 src/skins/vxworks/init.c           |    8 +++++-
 src/skins/vxworks/taskLib.c        |   20 +++++++++++++++-
 9 files changed, 137 insertions(+), 22 deletions(-)

Index: b/configure.in
===================================================================
--- a/configure.in
+++ b/configure.in
@@ -762,6 +762,29 @@ LIBS="$LIBS -lrt"
 AC_CHECK_FUNCS([shm_open shm_unlink])
 LIBS="$save_LIBS"
 
+AC_ARG_WITH([__thread],
+	    AC_HELP_STRING([--without-__thread],
+			   [do not use TLS features (allows for dlopen'ing Xenomai libs)]),
+	    [use__thread=$withval],
+	    [use__thread=yes])
+
+dnl Check whether the compiler supports the __thread keyword.
+if test "x$use__thread" != xno; then
+	AC_CACHE_CHECK([for __thread], libc_cv_gcc___thread,
+	[cat > conftest.c <<\EOF
+__thread int a __attribute__ ((tls_model ("initial-exec"))) = 42;
+EOF
+	if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -c -Werror conftest.c >&AS_MESSAGE_LOG_FD]); then
+		libc_cv_gcc___thread=yes
+	else
+		libc_cv_gcc___thread=no
+	fi
+	rm -f conftest*])
+	if test "$libc_cv_gcc___thread" = yes; then
+		AC_DEFINE(HAVE___THREAD,1,[config])
+	fi
+fi
+
 dnl
 dnl Build the Makefiles
 dnl
Index: b/include/asm-generic/bits/bind.h
===================================================================
--- a/include/asm-generic/bits/bind.h
+++ b/include/asm-generic/bits/bind.h
@@ -11,26 +11,26 @@
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
+#include <nucleus/types.h>
 #include <asm/xenomai/syscall.h>
 
+#ifdef HAVE___THREAD
+__thread xnhandle_t xeno_current __attribute__ ((tls_model ("initial-exec"))) =
+	XN_NO_HANDLE;
+
+static inline void __xeno_set_current(xnhandle_t current)
+{
+	xeno_current = current;
+}
+#else /* !HAVE___THREAD */
 __attribute__ ((weak))
 pthread_key_t xeno_current_key;
 __attribute__ ((weak))
 pthread_once_t xeno_init_current_key_once = PTHREAD_ONCE_INIT;
 
-__attribute__ ((weak))
-void xeno_set_current(void)
+static inline void __xeno_set_current(xnhandle_t current)
 {
-	void *kthread_cb;
-	int err;
-
-	err = XENOMAI_SYSCALL1(__xn_sys_current, &kthread_cb);
-	if (err) {
-		fprintf(stderr, "Xenomai: error obtaining handle for current "
-			"thread: %s\n", strerror(err));
-		exit(1);
-	}
-	pthread_setspecific(xeno_current_key, kthread_cb);
+	pthread_setspecific(xeno_current_key, (void *)current);
 }
 
 static void init_current_key(void)
@@ -42,6 +42,22 @@ static void init_current_key(void)
 		exit(1);
 	}
 }
+#endif /* !HAVE___THREAD */
+
+__attribute__ ((weak))
+void xeno_set_current(void)
+{
+	xnhandle_t current;
+	int err;
+
+	err = XENOMAI_SYSCALL1(__xn_sys_current, &current);
+	if (err) {
+		fprintf(stderr, "Xenomai: error obtaining handle for current "
+			"thread: %s\n", strerror(err));
+		exit(1);
+	}
+	__xeno_set_current(current);
+}
 
 #ifdef CONFIG_XENO_FASTSYNCH
 __attribute__ ((weak))
@@ -175,7 +191,9 @@ xeno_bind_skin(unsigned skin_magic, cons
 	sa.sa_flags = 0;
 	sigaction(SIGXCPU, &sa, NULL);
 
+#ifndef HAVE___THREAD
 	pthread_once(&xeno_init_current_key_once, &init_current_key);
+#endif /* !HAVE___THREAD */
 
 #ifdef CONFIG_XENO_FASTSYNCH
 	/* In case we forked, we need to map the new local semaphore heap */
@@ -251,7 +269,9 @@ xeno_bind_skin_opt(unsigned skin_magic,
 	xeno_arch_features_check();
 #endif /* xeno_arch_features_check */
 
+#ifndef HAVE___THREAD
 	pthread_once(&xeno_init_current_key_once, &init_current_key);
+#endif /* !HAVE___THREAD */
 
 #ifdef CONFIG_XENO_FASTSYNCH
 	/* In case we forked, we need to map the new local semaphore heap */
Index: b/include/asm-generic/bits/current.h
===================================================================
--- a/include/asm-generic/bits/current.h
+++ b/include/asm-generic/bits/current.h
@@ -4,13 +4,22 @@
 #include <pthread.h>
 #include <nucleus/types.h>
 
-extern pthread_key_t xeno_current_key;
+#ifdef HAVE___THREAD
+extern __thread xnhandle_t xeno_current __attribute__ ((tls_model ("initial-exec")));
 
-extern void xeno_set_current(void);
+static inline xnhandle_t xeno_get_current(void)
+{
+	return xeno_current;
+}
+#else /* ! HAVE___THREAD */
+extern pthread_key_t xeno_current_key;
 
 static inline xnhandle_t xeno_get_current(void)
 {
 	return (xnhandle_t)pthread_getspecific(xeno_current_key);
 }
+#endif /* ! HAVE___THREAD */
+
+extern void xeno_set_current(void);
 
 #endif /* _XENO_ASM_GENERIC_CURRENT_H */
Index: b/src/skins/native/init.c
===================================================================
--- a/src/skins/native/init.c
+++ b/src/skins/native/init.c
@@ -27,16 +27,18 @@
 #include <asm-generic/bits/bind.h>
 #include <asm-generic/bits/mlock_alert.h>
 
-pthread_key_t __native_tskey;
-
 int __native_muxid = -1;
 void native_timer_init(int);
 
+#ifndef HAVE___THREAD
+pthread_key_t __native_tskey;
+
 static void __flush_tsd(void *tsd)
 {
 	/* Free the task descriptor allocated by rt_task_self(). */
 	free(tsd);
 }
+#endif /* !HAVE___THREAD */
 
 static __attribute__ ((constructor))
 void __init_xeno_interface(void)
@@ -50,10 +52,12 @@ void __init_xeno_interface(void)
 	
 	__native_muxid = __xn_mux_shifted_id(__native_muxid);
 
+#ifndef HAVE___THREAD
 	/* Allocate a TSD key for indexing self task pointers. */
 
 	if (pthread_key_create(&__native_tskey, &__flush_tsd) != 0) {
 		fprintf(stderr, "Xenomai: failed to allocate new TSD key?!\n");
 		exit(1);
 	}
+#endif /* !HAVE___THREAD */
 }
Index: b/src/skins/native/task.c
===================================================================
--- a/src/skins/native/task.c
+++ b/src/skins/native/task.c
@@ -29,7 +29,14 @@
 #include <asm-generic/bits/current.h>
 #include "wrappers.h"
 
+#ifdef HAVE___THREAD
+__thread RT_TASK __native_self __attribute__ ((tls_model ("initial-exec"))) = {
+	.opaque = XN_NO_HANDLE,
+	.opaque2 = 0
+};
+#else /* !HAVE___THREAD */
 extern pthread_key_t __native_tskey;
+#endif /* !HAVE___THREAD */
 
 extern int __native_muxid;
 
@@ -91,6 +98,10 @@ static void *rt_task_trampoline(void *co
 
 	xeno_set_current();
 
+#ifdef HAVE___THREAD
+	__native_self = *iargs->task;
+#endif /* HAVE___THREAD */
+
 	/* Wait on the barrier for the task to be started. The barrier
 	   could be released in order to process Linux signals while the
 	   Xenomai shadow is still dormant; in such a case, resume wait. */
@@ -316,6 +327,15 @@ RT_TASK *rt_task_self(void)
 {
 	RT_TASK *self;
 
+#ifdef HAVE___THREAD
+	self = &__native_self;
+
+	if (self->opaque == XN_NO_HANDLE)
+		return NULL;
+
+#else /* !HAVE___THREAD */
+	RT_TASK *self;
+
 	self = (RT_TASK *)pthread_getspecific(__native_tskey);
 
 	if (self)
@@ -330,6 +350,7 @@ RT_TASK *rt_task_self(void)
 	}
 
 	pthread_setspecific(__native_tskey, self);
+#endif /* !HAVE___THREAD */
 
 	return self;
 }
Index: b/src/skins/vxworks/init.c
===================================================================
--- a/src/skins/vxworks/init.c
+++ b/src/skins/vxworks/init.c
@@ -26,15 +26,17 @@
 #include <asm-generic/bits/bind.h>
 #include <asm-generic/bits/mlock_alert.h>
 
-pthread_key_t __vxworks_tskey;
-
 int __vxworks_muxid = -1;
 
+#ifndef HAVE___THREAD
+pthread_key_t __vxworks_tskey;
+
 static void __flush_tsd(void *tsd)
 {
 	/* Free the task descriptor allocated by taskIdSelf(). */
 	free(tsd);
 }
+#endif /* !HAVE___THREAD */
 
 static __attribute__ ((constructor))
 void __init_xeno_interface(void)
@@ -43,10 +45,12 @@ void __init_xeno_interface(void)
 					 "vxworks", "xeno_vxworks");
 	__vxworks_muxid = __xn_mux_shifted_id(__vxworks_muxid);
 
+#ifndef HAVE___THREAD
 	/* Allocate a TSD key for indexing self task pointers. */
 
 	if (pthread_key_create(&__vxworks_tskey, &__flush_tsd) != 0) {
 		fprintf(stderr, "Xenomai: failed to allocate new TSD key?!\n");
 		exit(1);
 	}
+#endif /* !HAVE___THREAD */
 }
Index: b/src/skins/vxworks/taskLib.c
===================================================================
--- a/src/skins/vxworks/taskLib.c
+++ b/src/skins/vxworks/taskLib.c
@@ -30,7 +30,14 @@
 #include <asm-generic/bits/current.h>
 #include "wrappers.h"
 
+#ifdef HAVE___THREAD
+__thread WIND_TCB
+__vxworks_self __attribute__ ((tls_model ("initial-exec"))) = {
+	.handle = XN_NO_HANDLE
+};
+#else /* !HAVE___THREAD */
 extern pthread_key_t __vxworks_tskey;
+#endif /* !HAVE___THREAD */
 
 extern int __vxworks_muxid;
 
@@ -120,6 +127,10 @@ static void *wind_task_trampoline(void *
 
 	xeno_set_current();
 
+#ifdef HAVE___THREAD
+	__vxworks_self = *iargs->pTcb;
+#endif /* HAVE___THREAD */
+
 	/* Wait on the barrier for the task to be started. The barrier
 	   could be released in order to process Linux signals while the
 	   Xenomai shadow is still dormant; in such a case, resume wait. */
@@ -309,9 +320,15 @@ STATUS taskResume(TASK_ID task_id)
 
 TASK_ID taskIdSelf(void)
 {
-	WIND_TCB *self = (WIND_TCB *)pthread_getspecific(__vxworks_tskey);
+#ifdef HAVE___THREAD
+	return __vxworks_self.handle;
+
+#else /* !HAVE___THREAD */
+	WIND_TCB *self;
 	int err;
 
+	self = (WIND_TCB *)pthread_getspecific(__vxworks_tskey);
+
 	if (self)
 		return self->handle;
 
@@ -332,6 +349,7 @@ TASK_ID taskIdSelf(void)
 	pthread_setspecific(__vxworks_tskey, self);
 
 	return self->handle;
+#endif /* !HAVE___THREAD */
 }
 
 STATUS taskPrioritySet(TASK_ID task_id, int prio)
Index: b/src/skins/vrtx/init.c
===================================================================
--- a/src/skins/vrtx/init.c
+++ b/src/skins/vrtx/init.c
@@ -26,15 +26,17 @@
 #include <asm-generic/bits/bind.h>
 #include <asm-generic/bits/mlock_alert.h>
 
-pthread_key_t __vrtx_tskey;
-
 int __vrtx_muxid = -1;
 
+#ifndef HAVE___THREAD
+pthread_key_t __vrtx_tskey;
+
 static void __flush_tsd(void *tsd)
 {
 	/* Free the TCB struct. */
 	free(tsd);
 }
+#endif /* !HAVE___THREAD */
 
 static __attribute__ ((constructor))
 void __init_xeno_interface(void)
@@ -43,10 +45,12 @@ void __init_xeno_interface(void)
 	    xeno_bind_skin(VRTX_SKIN_MAGIC, "vrtx", "xeno_vrtx");
 	__vrtx_muxid = __xn_mux_shifted_id(__vrtx_muxid);
 
+#ifndef HAVE___THREAD
 	/* Allocate a TSD key for indexing self task pointers. */
 
 	if (pthread_key_create(&__vrtx_tskey, &__flush_tsd) != 0) {
 		fprintf(stderr, "Xenomai: failed to allocate new TSD key?!\n");
 		exit(1);
 	}
+#endif /* !HAVE___THREAD */
 }
Index: b/src/skins/vrtx/task.c
===================================================================
--- a/src/skins/vrtx/task.c
+++ b/src/skins/vrtx/task.c
@@ -29,7 +29,11 @@
 #include <vrtx/vrtx.h>
 #include <asm-generic/bits/current.h>
 
+#ifdef HAVE___THREAD
+__thread TCB __vrtx_tcb __attribute__ ((tls_model ("initial-exec")));
+#else /* !HAVE___THREAD */
 extern pthread_key_t __vrtx_tskey;
+#endif /* !HAVE___THREAD */
 
 extern int __vrtx_muxid;
 
@@ -81,7 +85,9 @@ static void *vrtx_task_trampoline(void *
 	struct sched_param param;
 	int policy;
 	long err;
+#ifndef HAVE___THREAD
 	TCB *tcb;
+#endif /* !HAVE___THREAD */
 
 	/* Backup the arg struct, it might vanish after completion. */
 	memcpy(&_iargs, iargs, sizeof(_iargs));
@@ -96,6 +102,7 @@ static void *vrtx_task_trampoline(void *
 	/* vrtx_task_delete requires asynchronous cancellation */
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
 
+#ifndef HAVE___THREAD
 	tcb = (TCB *) malloc(sizeof(*tcb));
 	if (tcb == NULL) {
 		fprintf(stderr, "Xenomai: failed to allocate local TCB?!\n");
@@ -104,6 +111,7 @@ static void *vrtx_task_trampoline(void *
 	}
 
 	pthread_setspecific(__vrtx_tskey, tcb);
+#endif /* !HAVE___THREAD */
 
 	old_sigharden_handler = signal(SIGHARDEN, &vrtx_task_sigharden);
 
@@ -224,7 +232,11 @@ TCB *sc_tinquiry(int pinfo[], int tid, i
 {
 	TCB *tcb;
 
-	tcb = (TCB *) pthread_getspecific(__vrtx_tskey);	/* Cannot fail. */
+#ifdef HAVE___THREAD
+	tcb = &__vrtx_tcb;
+#else /* !HAVE___THREAD */
+	tcb = (TCB *) pthread_getspecific(__vrtx_tskey); /* Cannot fail. */
+#endif /* !HAVE___THREAD */
 
 	*errp = XENOMAI_SKINCALL3(__vrtx_muxid,
 				  __vrtx_tinquiry, pinfo, tcb, tid);



^ permalink raw reply	[flat|nested] 50+ messages in thread

* [Xenomai-core] [PATCH 10/12] Report current shadow thread mode to user space
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
                   ` (8 preceding siblings ...)
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 09/12] Optionally replace pthread_getspecific with TLS variables Jan Kiszka
@ 2008-10-16 15:46 ` Jan Kiszka
  2008-10-16 20:23   ` Gilles Chanteperdrix
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 11/12] Ensure mode switch in mutex fast paths Jan Kiszka
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 15:46 UTC (permalink / raw)
  To: xenomai; +Cc: Jan Kiszka

[-- Attachment #1: report-shadow-mode-to-userspace.patch --]
[-- Type: text/plain, Size: 23735 bytes --]

With this patch applied, the Xenomai skin libraries are able to obtain
the execution mode the current thread without issuing a syscall. The
kernel-user interface looks as follows:

 - On thread creation (which triggers xnshadow_map), user space passes a
   pointer to an unsigned long.

 - Before going primary and after completing the switch to secondary
   mode, the nucleus writes 0 or XNRELAX to that unsigned long. The mode
   updates use __xn_put_user, so they are fail-safe (write errors are
   ignored, only an initial access_wok check is reported back).

 - User space can check its state by calling xeno_get_current_mode().
   An optional light-weight version based on __thread is also provided.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 include/asm-generic/bits/bind.h    |   29 +++++++++++++++++++++++++----
 include/asm-generic/bits/current.h |   20 ++++++++++++++++++++
 include/native/syscall.h           |    1 +
 include/nucleus/shadow.h           |    3 ++-
 include/nucleus/thread.h           |    4 ++++
 include/psos+/syscall.h            |    8 ++++++++
 include/vrtx/syscall.h             |    1 +
 include/vxworks/syscall.h          |    1 +
 ksrc/nucleus/shadow.c              |   22 ++++++++++++++++++++--
 ksrc/skins/native/syscall.c        |    3 ++-
 ksrc/skins/posix/syscall.c         |   14 +++++++++-----
 ksrc/skins/psos+/syscall.c         |   34 +++++++++++++++++++++-------------
 ksrc/skins/uitron/syscall.c        |    8 ++++++--
 ksrc/skins/vrtx/syscall.c          |    4 +++-
 ksrc/skins/vxworks/syscall.c       |    4 +++-
 src/skins/native/task.c            |   10 ++++++++++
 src/skins/posix/thread.c           |   33 +++++++++++++++++++++++++++++++--
 src/skins/psos+/task.c             |   16 +++++++++++++---
 src/skins/uitron/task.c            |   11 +++++++++--
 src/skins/vrtx/task.c              |    6 ++++++
 src/skins/vxworks/taskLib.c        |    6 ++++++
 21 files changed, 201 insertions(+), 37 deletions(-)

Index: b/include/native/syscall.h
===================================================================
--- a/include/native/syscall.h
+++ b/include/native/syscall.h
@@ -134,6 +134,7 @@ struct rt_arg_bulk {
 	u_long a3;
 	u_long a4;
 	u_long a5;
+	u_long a6;
 };
 
 #ifdef __KERNEL__
Index: b/include/nucleus/shadow.h
===================================================================
--- a/include/nucleus/shadow.h
+++ b/include/nucleus/shadow.h
@@ -69,7 +69,8 @@ void xnshadow_grab_events(void);
 void xnshadow_release_events(void);
 
 int xnshadow_map(struct xnthread *thread,
-		 xncompletion_t __user *u_completion);
+		 xncompletion_t __user *u_completion,
+		 unsigned long __user *u_mode);
 
 void xnshadow_unmap(struct xnthread *thread);
 
Index: b/include/nucleus/thread.h
===================================================================
--- a/include/nucleus/thread.h
+++ b/include/nucleus/thread.h
@@ -248,6 +248,10 @@ typedef struct xnthread {
 
 	void *cookie;		/* Cookie to pass to the entry routine */
 
+#ifdef CONFIG_XENO_OPT_PERVASIVE
+	unsigned long __user *u_mode;	/* Thread mode variable in userland. */
+#endif /* CONFIG_XENO_OPT_PERVASIVE */
+
     XNARCH_DECL_DISPLAY_CONTEXT();
 
 } xnthread_t;
Index: b/ksrc/nucleus/shadow.c
===================================================================
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -1079,6 +1079,8 @@ redo:
 		/* Grab the request token. */
 		return -ERESTARTSYS;
 
+	__xn_put_user(0, thread->u_mode);
+
 	preempt_disable();
 
 	/* Assume that we might have been migrated while waiting for
@@ -1250,6 +1252,8 @@ void xnshadow_relax(int notify)
 	/* "current" is now running into the Linux domain on behalf of the
 	   root thread. */
 
+	__xn_put_user(XNRELAX, thread->u_mode);
+
 	trace_mark(xn_nucleus_shadow_relaxed,
 		  "thread %p thread_name %s comm %s",
 		  thread, xnthread_name(thread), current->comm);
@@ -1264,7 +1268,9 @@ void xnshadow_exit(void)
 }
 
 /*!
- * \fn int xnshadow_map(xnthread_t *thread, xncompletion_t __user *u_completion)
+ * \fn int xnshadow_map(xnthread_t *thread,
+ *                      xncompletion_t __user *u_completion,
+ *                      unsigned long __user *u_mode)
  * @internal
  * \brief Create a shadow thread context.
  *
@@ -1288,6 +1294,11 @@ void xnshadow_exit(void)
  * immediately started and "current" immediately resumes in the Xenomai
  * domain from this service.
  *
+ * @param: u_mode is the address of a mode variable in user space that
+ * will reflect the current thread mode (primary or secondary). The
+ * nucleus will try to update the variable before switching to secondary
+ * or after switching from primary mode.
+ *
  * @return 0 is returned on success. Otherwise:
  *
  * - -ERESTARTSYS is returned if the current Linux task has received a
@@ -1313,7 +1324,8 @@ void xnshadow_exit(void)
  *
  */
 
-int xnshadow_map(xnthread_t *thread, xncompletion_t __user *u_completion)
+int xnshadow_map(xnthread_t *thread, xncompletion_t __user *u_completion,
+		 unsigned long __user *u_mode)
 {
 	xnarch_cpumask_t affinity;
 	unsigned muxid, magic;
@@ -1325,6 +1337,9 @@ int xnshadow_map(xnthread_t *thread, xnc
 	if (xnthread_test_state(thread, XNMAPPED))
 		return -EINVAL;
 
+	if (!access_wok(u_mode, sizeof(*u_mode)))
+		return -EFAULT;
+
 #ifdef CONFIG_MMU
 	if (!(current->mm->def_flags & VM_LOCKED))
 		send_sig(SIGXCPU, current, 1);
@@ -1385,6 +1400,9 @@ int xnshadow_map(xnthread_t *thread, xnc
 	if (err)
 		return err;
 
+	thread->u_mode = u_mode;
+	__xn_put_user(XNRELAX, u_mode);
+
 	err = xnshadow_harden();
 
 	xnarch_trace_pid(xnarch_user_pid(xnthread_archtcb(thread)),
Index: b/ksrc/skins/native/syscall.c
===================================================================
--- a/ksrc/skins/native/syscall.c
+++ b/ksrc/skins/native/syscall.c
@@ -191,7 +191,8 @@ static int __rt_task_create(struct pt_re
 		if (__xn_safe_copy_to_user((void __user *)bulk.a1, &ph, sizeof(ph)))
 			err = -EFAULT;
 		else {
-			err = xnshadow_map(&task->thread_base, u_completion);
+			err = xnshadow_map(&task->thread_base, u_completion,
+					   (unsigned long __user *)bulk.a6);
 			if (!err)
 				goto out;
 		}
Index: b/ksrc/skins/posix/syscall.c
===================================================================
--- a/ksrc/skins/posix/syscall.c
+++ b/ksrc/skins/posix/syscall.c
@@ -180,7 +180,8 @@ static int __pthread_create(struct pt_re
 	if (err)
 		return -err;	/* Conventionally, our error codes are negative. */
 
-	err = xnshadow_map(&k_tid->threadbase, NULL);
+	err = xnshadow_map(&k_tid->threadbase, NULL,
+			   (unsigned long __user *)__xn_reg_arg2(regs));
 
 	if (!err && !__pthread_hash(&hkey, k_tid))
 		err = -ENOMEM;
@@ -196,7 +197,8 @@ static int __pthread_create(struct pt_re
 #define __pthread_detach  __pse51_call_not_available
 
 static pthread_t __pthread_shadow(struct task_struct *p,
-				  struct pse51_hkey *hkey)
+				  struct pse51_hkey *hkey,
+				  unsigned long __user *u_mode)
 {
 	pthread_attr_t attr;
 	pthread_t k_tid;
@@ -211,7 +213,7 @@ static pthread_t __pthread_shadow(struct
 	if (err)
 		return ERR_PTR(-err);
 
-	err = xnshadow_map(&k_tid->threadbase, NULL);
+	err = xnshadow_map(&k_tid->threadbase, NULL, u_mode);
 
 	if (!err && !__pthread_hash(hkey, k_tid))
 		err = -EAGAIN;
@@ -227,11 +229,13 @@ static pthread_t __pthread_shadow(struct
 static int __pthread_setschedparam(struct pt_regs *regs)
 {
 	int policy, err, promoted = 0;
+	unsigned long __user *u_mode;
 	struct sched_param param;
 	struct pse51_hkey hkey;
 	pthread_t k_tid;
 
 	policy = __xn_reg_arg2(regs);
+	u_mode = (unsigned long __user *)__xn_reg_arg4(regs);
 
 	if (__xn_safe_copy_from_user(&param,
 				     (void __user *)__xn_reg_arg3(regs), sizeof(param)))
@@ -241,10 +245,10 @@ static int __pthread_setschedparam(struc
 	hkey.mm = current->mm;
 	k_tid = __pthread_find(&hkey);
 
-	if (!k_tid && __xn_reg_arg1(regs) == __xn_reg_arg4(regs)) {
+	if (!k_tid && u_mode) {
 		/* If the syscall applies to "current", and the latter is not
 		   a Xenomai thread already, then shadow it. */
-		k_tid = __pthread_shadow(current, &hkey);
+		k_tid = __pthread_shadow(current, &hkey, u_mode);
 		if (IS_ERR(k_tid))
 			return PTR_ERR(k_tid);
 
Index: b/ksrc/skins/psos+/syscall.c
===================================================================
--- a/ksrc/skins/psos+/syscall.c
+++ b/ksrc/skins/psos+/syscall.c
@@ -60,11 +60,14 @@ static psostask_t *__psos_task_current(s
 }
 
 /*
- * int __t_create(const char *name,
- *                u_long prio,
- *                u_long flags,
+ * int __t_create(struct psos_arg_bulk *bulk,
  *                u_long *tid_r,
  *                xncompletion_t *completion)
+ * bulk = {
+ * a1: const char *name;
+ * a2: u_long prio;
+ * a3: u_long flags;
+ * a4: unsigned long *mode;
  */
 
 static int __t_create(struct pt_regs *regs)
@@ -73,10 +76,15 @@ static int __t_create(struct pt_regs *re
 	struct task_struct *p = current;
 	u_long prio, flags, tid, err;
 	char name[XNOBJECT_NAME_LEN];
+	struct psos_arg_bulk bulk;
 	psostask_t *task;
 
+	if (__xn_safe_copy_from_user(&bulk, (void __user *)__xn_reg_arg1(regs),
+				     sizeof(bulk)))
+		return -EFAULT;
+
 	/* Get task name. */
-	if (__xn_safe_strncpy_from_user(name, (const char __user *)__xn_reg_arg1(regs),
+	if (__xn_safe_strncpy_from_user(name, (const char __user *)bulk.a1,
 					sizeof(name) - 1) < 0)
 		return -EFAULT;
 
@@ -85,12 +93,12 @@ static int __t_create(struct pt_regs *re
 	p->comm[sizeof(p->comm) - 1] = '\0';
 
 	/* Task priority. */
-	prio = __xn_reg_arg2(regs);
+	prio = bulk.a2;
 	/* Task flags. Force FPU support in user-space. This will lead
 	   to a no-op if the platform does not support it. */
-	flags = __xn_reg_arg3(regs) | T_SHADOW | T_FPU;
+	flags = bulk.a3 | T_SHADOW | T_FPU;
 	/* Completion descriptor our parent thread is pending on. */
-	u_completion = (xncompletion_t __user *)__xn_reg_arg5(regs);
+	u_completion = (xncompletion_t __user *)__xn_reg_arg3(regs);
 
 	err = t_create(name, prio, 0, 0, flags, &tid);
 
@@ -100,14 +108,14 @@ static int __t_create(struct pt_regs *re
 		 * about the new thread id, so we can manipulate its
 		 * TCB pointer freely. */
 		tid = xnthread_handle(&task->threadbase);
-		if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg4(regs), &tid,
+		if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg2(regs), &tid,
 					   sizeof(tid)))
 			return -EFAULT;
-		else {
-			err = xnshadow_map(&task->threadbase, u_completion);	/* May be NULL */
-			if (!err)
-				goto out;
-		}
+
+		err = xnshadow_map(&task->threadbase, u_completion,
+				   (unsigned long __user *)bulk.a4);
+		if (!err)
+			goto out;
 
 		t_delete((u_long)task);
 	}
Index: b/ksrc/skins/vrtx/syscall.c
===================================================================
--- a/ksrc/skins/vrtx/syscall.c
+++ b/ksrc/skins/vrtx/syscall.c
@@ -48,6 +48,7 @@ static int __muxid;
  * a1: int tid;
  * a2: int prio;
  * a3: int mode;
+ * a4: unsigned long *shadow_mode;
  * }
  */
 
@@ -89,7 +90,8 @@ static int __sc_tecreate(struct pt_regs
 					   &tid, sizeof(tid)))
 			err = -EFAULT;
 		else {
-			err = xnshadow_map(&task->threadbase, u_completion);
+			err = xnshadow_map(&task->threadbase, u_completion,
+					   (unsigned long __user *)bulk.a4);
 			if (!err)
 				goto done;
 		}
Index: b/ksrc/skins/vxworks/syscall.c
===================================================================
--- a/ksrc/skins/vxworks/syscall.c
+++ b/ksrc/skins/vxworks/syscall.c
@@ -66,6 +66,7 @@ static WIND_TCB *__wind_task_current(str
  * a2: int prio;
  * a3: int flags;
  * a4: pthread_self();
+ * a5: unsigned long *mode;
  * }
  */
 
@@ -124,7 +125,8 @@ static int __wind_task_init(struct pt_re
 					   sizeof(ph)))
 			err = -EFAULT;
 		else {
-			err = xnshadow_map(&task->threadbase, u_completion);
+			err = xnshadow_map(&task->threadbase, u_completion,
+					   (unsigned long __user *)bulk.a5);
 			if (!err)
 				goto out;
 		}
Index: b/ksrc/skins/uitron/syscall.c
===================================================================
--- a/ksrc/skins/uitron/syscall.c
+++ b/ksrc/skins/uitron/syscall.c
@@ -31,13 +31,15 @@
 int __ui_muxid;
 
 /*
- * int __uitron_cre_tsk(ID tskid, T_CTSK *pk_ctsk, xncompletion_t *completion)
+ * int __uitron_cre_tsk(ID tskid, T_CTSK *pk_ctsk, xncompletion_t *completion,
+ *                      unsigned long *mode)
  */
 
 static int __ui_cre_tsk(struct pt_regs *regs)
 {
 	xncompletion_t __user *u_completion;
 	struct task_struct *p = current;
+	unsigned long __user *u_mode;
 	uitask_t *task;
 	T_CTSK pk_ctsk;
 	ID tskid;
@@ -54,6 +56,8 @@ static int __ui_cre_tsk(struct pt_regs *
 	/* Completion descriptor our parent thread is pending on. */
 	u_completion = (xncompletion_t __user *)__xn_reg_arg3(regs);
 
+	u_mode = (unsigned long __user *)__xn_reg_arg4(regs);
+
 	err = cre_tsk(tskid, &pk_ctsk);
 
 	if (likely(err == E_OK)) {
@@ -74,7 +78,7 @@ static int __ui_cre_tsk(struct pt_regs *
 		 * recycled before we could map it; however, the risk
 		 * is mitigated by consistency checks performed in
 		 * xnshadow_map(). */
-		return xnshadow_map(&task->threadbase, u_completion);	/* May be NULL */
+		return xnshadow_map(&task->threadbase, u_completion, u_mode);
 	}
 
       fail:
Index: b/include/asm-generic/bits/bind.h
===================================================================
--- a/include/asm-generic/bits/bind.h
+++ b/include/asm-generic/bits/bind.h
@@ -17,6 +17,8 @@
 #ifdef HAVE___THREAD
 __thread xnhandle_t xeno_current __attribute__ ((tls_model ("initial-exec"))) =
 	XN_NO_HANDLE;
+__thread unsigned long
+xeno_current_mode __attribute__ ((tls_model ("initial-exec")));
 
 static inline void __xeno_set_current(xnhandle_t current)
 {
@@ -26,17 +28,36 @@ static inline void __xeno_set_current(xn
 __attribute__ ((weak))
 pthread_key_t xeno_current_key;
 __attribute__ ((weak))
-pthread_once_t xeno_init_current_key_once = PTHREAD_ONCE_INIT;
+pthread_key_t xeno_current_mode_key;
+__attribute__ ((weak))
+pthread_once_t xeno_init_current_keys_once = PTHREAD_ONCE_INIT;
 
 static inline void __xeno_set_current(xnhandle_t current)
 {
 	pthread_setspecific(xeno_current_key, (void *)current);
 }
 
-static void init_current_key(void)
+unsigned long *xeno_init_current_mode(void)
+{
+	unsigned long *mode = malloc(sizeof(unsigned long));
+	pthread_setspecific(xeno_current_mode_key, mode);
+	return mode;
+}
+
+static void cleanup_current_mode(void *ptr)
+{
+	free(ptr);
+}
+
+static void init_current_keys(void)
 {
 	int err = pthread_key_create(&xeno_current_key, NULL);
+	if (err)
+		goto error_exit;
+
+	err = pthread_key_create(&xeno_current_mode_key, cleanup_current_mode);
 	if (err) {
+	  error_exit:
 		fprintf(stderr, "Xenomai: error creating TSD key: %s\n",
 			strerror(err));
 		exit(1);
@@ -192,7 +213,7 @@ xeno_bind_skin(unsigned skin_magic, cons
 	sigaction(SIGXCPU, &sa, NULL);
 
 #ifndef HAVE___THREAD
-	pthread_once(&xeno_init_current_key_once, &init_current_key);
+	pthread_once(&xeno_init_current_keys_once, &init_current_keys);
 #endif /* !HAVE___THREAD */
 
 #ifdef CONFIG_XENO_FASTSYNCH
@@ -270,7 +291,7 @@ xeno_bind_skin_opt(unsigned skin_magic,
 #endif /* xeno_arch_features_check */
 
 #ifndef HAVE___THREAD
-	pthread_once(&xeno_init_current_key_once, &init_current_key);
+	pthread_once(&xeno_init_current_keys_once, &init_current_keys);
 #endif /* !HAVE___THREAD */
 
 #ifdef CONFIG_XENO_FASTSYNCH
Index: b/include/asm-generic/bits/current.h
===================================================================
--- a/include/asm-generic/bits/current.h
+++ b/include/asm-generic/bits/current.h
@@ -6,18 +6,38 @@
 
 #ifdef HAVE___THREAD
 extern __thread xnhandle_t xeno_current __attribute__ ((tls_model ("initial-exec")));
+extern __thread unsigned long
+xeno_current_mode __attribute__ ((tls_model ("initial-exec")));
 
 static inline xnhandle_t xeno_get_current(void)
 {
 	return xeno_current;
 }
+
+static inline unsigned long xeno_get_current_mode(void)
+{
+	return xeno_current_mode;
+}
+
+static inline unsigned long *xeno_init_current_mode(void)
+{
+	return &xeno_current_mode;
+}
 #else /* ! HAVE___THREAD */
 extern pthread_key_t xeno_current_key;
+extern pthread_key_t xeno_current_mode_key;
 
 static inline xnhandle_t xeno_get_current(void)
 {
 	return (xnhandle_t)pthread_getspecific(xeno_current_key);
 }
+
+static inline unsigned long xeno_get_current_mode(void)
+{
+	return *(unsigned long *)pthread_getspecific(xeno_current_mode_key);
+}
+
+extern unsigned long *xeno_init_current_mode(void);
 #endif /* ! HAVE___THREAD */
 
 extern void xeno_set_current(void);
Index: b/src/skins/native/task.c
===================================================================
--- a/src/skins/native/task.c
+++ b/src/skins/native/task.c
@@ -89,6 +89,12 @@ static void *rt_task_trampoline(void *co
 	bulk.a3 = (u_long)iargs->prio;
 	bulk.a4 = (u_long)iargs->mode;
 	bulk.a5 = (u_long)pthread_self();
+	bulk.a6 = (u_long)xeno_init_current_mode();
+
+	if (!bulk.a6) {
+		err = -ENOMEM;
+		goto fail;
+	}
 
 	err = XENOMAI_SKINCALL2(__native_muxid,
 				__native_task_create, &bulk,
@@ -205,6 +211,10 @@ int rt_task_shadow(RT_TASK *task, const
 	bulk.a3 = (u_long)prio;
 	bulk.a4 = (u_long)mode;
 	bulk.a5 = (u_long)pthread_self();
+	bulk.a6 = (u_long)xeno_init_current_mode();
+
+	if (!bulk.a6)
+		return -ENOMEM;
 
 	err = XENOMAI_SKINCALL2(__native_muxid, __native_task_create, &bulk,
 				NULL);
Index: b/src/skins/posix/thread.c
===================================================================
--- a/src/skins/posix/thread.c
+++ b/src/skins/posix/thread.c
@@ -47,11 +47,23 @@ int __wrap_pthread_setschedparam(pthread
 				 int policy, const struct sched_param *param)
 {
 	pthread_t myself = pthread_self();
+	unsigned long *mode_buf = NULL;
 	int err, promoted;
 
+	if (thread == myself) {
+#ifdef HAVE___THREAD
+		mode_buf = xeno_init_current_mode();
+#else /* !HAVE___THREAD */
+		mode_buf = malloc(sizeof(*mode_buf));
+
+		if (!mode_buf)
+			return ENOMEM;
+#endif /* !HAVE___THREAD */
+	}
+
 	err = -XENOMAI_SKINCALL5(__pse51_muxid,
 				 __pse51_thread_setschedparam,
-				 thread, policy, param, myself, &promoted);
+				 thread, policy, param, mode_buf, &promoted);
 
 	if (err == EPERM)
 		return __real_pthread_setschedparam(thread, policy, param);
@@ -60,10 +72,17 @@ int __wrap_pthread_setschedparam(pthread
 
 	if (!err && promoted) {
 		old_sigharden_handler = signal(SIGHARDEN, &__pthread_sigharden_handler);
+#ifndef HAVE___THREAD
+		pthread_setspecific(xeno_current_mode_key, mode_buf);
+#endif /* !HAVE___THREAD */
 		xeno_set_current();
 		if (policy != SCHED_OTHER)
 			XENOMAI_SYSCALL1(__xn_sys_migrate, XENOMAI_XENO_DOMAIN);
 	}
+#ifndef HAVE___THREAD
+	else
+		free(mode_buf);
+#endif /* !HAVE___THREAD */
 
 	return err;
 }
@@ -116,6 +135,7 @@ static void *__pthread_trampoline(void *
 	struct sched_param param;
 	void *status = NULL;
 	int parent_prio, policy;
+	unsigned long *mode_buf;
 	long err;
 
 	old_sigharden_handler = signal(SIGHARDEN, &__pthread_sigharden_handler);
@@ -123,10 +143,18 @@ static void *__pthread_trampoline(void *
 	param.sched_priority = iargs->prio;
 	policy = iargs->policy;
 	parent_prio = iargs->parent_prio;
+	mode_buf = xeno_init_current_mode();
+
+	if (!mode_buf) {
+		status = (void *)ENOMEM;
+		iargs->ret = ENOMEM;
+		goto out;
+	}
 
 	/* Do _not_ inline the call to pthread_self() in the syscall
 	   macro: this trashes the syscall regs on some archs. */
-	err = XENOMAI_SKINCALL1(__pse51_muxid, __pse51_thread_create, tid);
+	err = XENOMAI_SKINCALL2(__pse51_muxid, __pse51_thread_create, tid,
+				mode_buf);
 	iargs->ret = -err;
 
 	/* We must save anything we'll need to use from *iargs on our own
@@ -159,6 +187,7 @@ static void *__pthread_trampoline(void *
 	} else
 		status = (void *)-err;
 
+out:
 	pthread_exit(status);
 }
 
Index: b/include/vrtx/syscall.h
===================================================================
--- a/include/vrtx/syscall.h
+++ b/include/vrtx/syscall.h
@@ -85,6 +85,7 @@ struct vrtx_arg_bulk {
     u_long a1;
     u_long a2;
     u_long a3;
+    u_long a4;
 };
 
 #ifdef __KERNEL__
Index: b/include/vxworks/syscall.h
===================================================================
--- a/include/vxworks/syscall.h
+++ b/include/vxworks/syscall.h
@@ -77,6 +77,7 @@ struct wind_arg_bulk {
     u_long a2;
     u_long a3;
     u_long a4;
+    u_long a5;
 };
 
 #ifdef __KERNEL__
Index: b/src/skins/vrtx/task.c
===================================================================
--- a/src/skins/vrtx/task.c
+++ b/src/skins/vrtx/task.c
@@ -118,6 +118,12 @@ static void *vrtx_task_trampoline(void *
 	bulk.a1 = (u_long)iargs->tid;
 	bulk.a2 = (u_long)iargs->prio;
 	bulk.a3 = (u_long)iargs->mode;
+	bulk.a4 = (u_long)xeno_init_current_mode();
+
+	if (!bulk.a4) {
+		err = -ENOMEM;
+		goto fail;
+	}
 
 	err = XENOMAI_SKINCALL3(__vrtx_muxid,
 				__vrtx_tecreate,
Index: b/src/skins/vxworks/taskLib.c
===================================================================
--- a/src/skins/vxworks/taskLib.c
+++ b/src/skins/vxworks/taskLib.c
@@ -118,6 +118,12 @@ static void *wind_task_trampoline(void *
 	bulk.a2 = (u_long)iargs->prio;
 	bulk.a3 = (u_long)iargs->flags;
 	bulk.a4 = (u_long)pthread_self();
+	bulk.a5 = (u_long)xeno_init_current_mode();
+
+	if (!bulk.a5) {
+		err = -ENOMEM;
+		goto fail;
+	}
 
 	err = XENOMAI_SKINCALL3(__vxworks_muxid,
 				__vxworks_task_init,
Index: b/include/psos+/syscall.h
===================================================================
--- a/include/psos+/syscall.h
+++ b/include/psos+/syscall.h
@@ -74,6 +74,14 @@
 /* Xenomai extension: get raw count of jiffies */
 #define __psos_tm_getc      46
 
+struct psos_arg_bulk {
+
+    u_long a1;
+    u_long a2;
+    u_long a3;
+    u_long a4;
+};
+
 #ifdef __KERNEL__
 
 #ifdef __cplusplus
Index: b/src/skins/psos+/task.c
===================================================================
--- a/src/skins/psos+/task.c
+++ b/src/skins/psos+/task.c
@@ -72,6 +72,7 @@ static void *psos_task_trampoline(void *
 	struct psos_task_iargs *iargs = (struct psos_task_iargs *)cookie;
 	void (*entry)(u_long, u_long, u_long, u_long);
 	u_long dummy_args[4] = { 0, 0, 0, 0 }, *targs;
+	struct psos_arg_bulk bulk;
 	struct sched_param param;
 	int policy;
 	long err;
@@ -83,10 +84,19 @@ static void *psos_task_trampoline(void *
 
 	old_sigharden_handler = signal(SIGHARDEN, &psos_task_sigharden);
 
-	err = XENOMAI_SKINCALL5(__psos_muxid,
+	bulk.a1 = (u_long)iargs->name;
+	bulk.a2 = (u_long)iargs->prio;
+	bulk.a3 = (u_long)iargs->flags;
+	bulk.a4 = (u_long)xeno_init_current_mode();
+
+	if (!bulk.a4) {
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	err = XENOMAI_SKINCALL3(__psos_muxid,
 				__psos_t_create,
-				iargs->name, iargs->prio, iargs->flags,
-				iargs->tid_r, iargs->completionp);
+				&bulk, iargs->tid_r, iargs->completionp);
 	if (err)
 		goto fail;
 
Index: b/src/skins/uitron/task.c
===================================================================
--- a/src/skins/uitron/task.c
+++ b/src/skins/uitron/task.c
@@ -68,6 +68,7 @@ static void *uitron_task_trampoline(void
 {
 	struct uitron_task_iargs *iargs = (struct uitron_task_iargs *)cookie;
 	struct sched_param param;
+	unsigned long *mode;
 	void (*entry)(INT);
 	int policy;
 	long err;
@@ -83,10 +84,16 @@ static void *uitron_task_trampoline(void
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
 	old_sigharden_handler = signal(SIGHARDEN, &uitron_task_sigharden);
 
-	err = XENOMAI_SKINCALL3(__uitron_muxid,
+	mode = xeno_init_current_mode();
+	if (!mode) {
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	err = XENOMAI_SKINCALL4(__uitron_muxid,
 				__uitron_cre_tsk,
 				iargs->tskid, iargs->pk_ctsk,
-				iargs->completionp);
+				iargs->completionp, mode);
 	if (err)
 		goto fail;
 



^ permalink raw reply	[flat|nested] 50+ messages in thread

* [Xenomai-core] [PATCH 11/12] Ensure mode switch in mutex fast paths
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
                   ` (9 preceding siblings ...)
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 10/12] Report current shadow thread mode to user space Jan Kiszka
@ 2008-10-16 15:46 ` Jan Kiszka
  2008-10-16 20:27   ` Gilles Chanteperdrix
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 12/12] Enable SMP support for user libs by default Jan Kiszka
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 15:46 UTC (permalink / raw)
  To: xenomai; +Cc: Jan Kiszka

[-- Attachment #1: ensure-mode-switch-in-mutex-fast-paths.patch --]
[-- Type: text/plain, Size: 4664 bytes --]

With the help of xeno_get_current_mode(), this patch ensures that shadow
threads in secondary mode will be switched to primary again in case they
acquire an uncontended native or POSIX mutex, thus would otherwise only
pick the user space fast path. This prevents potential priority
inversions that the fast mutex optimizations introduced.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 src/skins/native/mutex.c |   31 ++++++++-------
 src/skins/posix/mutex.c  |   94 +++++++++++++++++++++++++++--------------------
 2 files changed, 71 insertions(+), 54 deletions(-)

Index: b/src/skins/native/mutex.c
===================================================================
--- a/src/skins/native/mutex.c
+++ b/src/skins/native/mutex.c
@@ -18,6 +18,7 @@
 
 #include <limits.h>
 #include <nucleus/synch.h>
+#include <nucleus/thread.h>
 #include <native/syscall.h>
 #include <native/mutex.h>
 #include <asm-generic/bits/current.h>
@@ -78,22 +79,24 @@ static int rt_mutex_acquire_inner(RT_MUT
 	if (!cur)
 		return -EPERM;
 
-	err = xnsynch_fast_acquire(mutex->fastlock, cur);
-	if (likely(!err)) {
-		mutex->lockcnt = 1;
-		return 0;
-	}
-
-	if (err == -EBUSY) {
-		if (mutex->lockcnt == UINT_MAX)
-			return -EAGAIN;
+	if (likely(!(xeno_get_current_mode() & XNRELAX))) {
+		err = xnsynch_fast_acquire(mutex->fastlock, cur);
+		if (likely(!err)) {
+			mutex->lockcnt = 1;
+			return 0;
+		}
+
+		if (err == -EBUSY) {
+			if (mutex->lockcnt == UINT_MAX)
+				return -EAGAIN;
+
+			mutex->lockcnt++;
+			return 0;
+		}
 
-		mutex->lockcnt++;
-		return 0;
+		if (timeout == TM_NONBLOCK && mode == XN_RELATIVE)
+			return -EWOULDBLOCK;
 	}
-
-	if (timeout == TM_NONBLOCK && mode == XN_RELATIVE)
-		return -EWOULDBLOCK;
 #endif /* CONFIG_XENO_FASTSYNCH */
 
 	err = XENOMAI_SKINCALL3(__native_muxid,
Index: b/src/skins/posix/mutex.c
===================================================================
--- a/src/skins/posix/mutex.c
+++ b/src/skins/posix/mutex.c
@@ -164,31 +164,33 @@ int __wrap_pthread_mutex_lock(pthread_mu
 		goto out;
 	}
 
-	err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
+	if (likely(!(xeno_get_current_mode() & XNRELAX))) {
+		err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
 
-	if (likely(!err)) {
-		shadow->lockcnt = 1;
-		cb_read_unlock(&shadow->lock, s);
-		return 0;
-	}
+		if (likely(!err)) {
+			shadow->lockcnt = 1;
+			cb_read_unlock(&shadow->lock, s);
+			return 0;
+		}
 
-	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:
+				err = -EDEADLK;
+				goto out;
 
-		case PTHREAD_MUTEX_RECURSIVE:
-			if (shadow->lockcnt == UINT_MAX) {
-				err = -EAGAIN;
+			case PTHREAD_MUTEX_RECURSIVE:
+				if (shadow->lockcnt == UINT_MAX) {
+					err = -EAGAIN;
+					goto out;
+				}
+				++shadow->lockcnt;
+				err = 0;
 				goto out;
 			}
-			++shadow->lockcnt;
-			err = 0;
-			goto out;
 		}
 #endif /* CONFIG_XENO_FASTSYNCH */
 
@@ -226,32 +228,34 @@ int __wrap_pthread_mutex_timedlock(pthre
 		goto out;
 	}	
 
-	err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
+	if (likely(!(xeno_get_current_mode() & XNRELAX))) {
+		err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
 
-	if (likely(!err)) {
-		shadow->lockcnt = 1;
-		cb_read_unlock(&shadow->lock, s);
-		return 0;
-	}
+		if (likely(!err)) {
+			shadow->lockcnt = 1;
+			cb_read_unlock(&shadow->lock, s);
+			return 0;
+		}
 
-	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:
+				err = -EDEADLK;
+				goto out;
 
-		case PTHREAD_MUTEX_RECURSIVE:
-			if (shadow->lockcnt == UINT_MAX) {
-				err = -EAGAIN;
+			case PTHREAD_MUTEX_RECURSIVE:
+				if (shadow->lockcnt == UINT_MAX) {
+					err = -EAGAIN;
+					goto out;
+				}
+
+				++shadow->lockcnt;
 				goto out;
 			}
-
-			++shadow->lockcnt;
-			goto out;
-		}
+	}
 #endif /* CONFIG_XENO_FASTSYNCH */
 
 	do {
@@ -286,7 +290,17 @@ int __wrap_pthread_mutex_trylock(pthread
 	if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC)) {
 		err = -EINVAL;
 		goto out;
-	}	
+	}
+
+	if (unlikely(xeno_get_current_mode() & XNRELAX)) {
+		do {
+			err = -XENOMAI_SYSCALL1(__xn_sys_migrate,
+						XENOMAI_XENO_DOMAIN);
+		} while (err == EINTR);
+
+		if (err)
+			goto out;
+	}
 
 	err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
 



^ permalink raw reply	[flat|nested] 50+ messages in thread

* [Xenomai-core] [PATCH 12/12] Enable SMP support for user libs by default
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
                   ` (10 preceding siblings ...)
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 11/12] Ensure mode switch in mutex fast paths Jan Kiszka
@ 2008-10-16 15:46 ` Jan Kiszka
  2008-10-16 20:29   ` Gilles Chanteperdrix
  2008-10-16 16:21 ` [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Gilles Chanteperdrix
  2008-10-17 12:28 ` Gilles Chanteperdrix
  13 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 15:46 UTC (permalink / raw)
  To: xenomai; +Cc: Jan Kiszka

[-- Attachment #1: make-smp-default.patch --]
[-- Type: text/plain, Size: 1691 bytes --]

With fast xnsynch/mutex support in place, the importance of getting the
user space library configuration right increases significantly. If the
user fails to provide --enable-smp, (s)he risks to break the mutex fast
path in a very subtle way. Thus, it is better to assume SMP by default
(as far as the arch bothers at all) and let the user switch it off for
intentional optimization for UP-only targets.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
 README.INSTALL |    2 +-
 configure.in   |    6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

Index: b/configure.in
===================================================================
--- a/configure.in
+++ b/configure.in
@@ -132,12 +132,12 @@ AC_ARG_ENABLE(debug,
 	esac])
 AC_MSG_RESULT(${debug_symbols:-no})
 
-dnl SMP support (default: off)
+dnl SMP support (default: on)
 
-CONFIG_SMP=
+CONFIG_SMP=y
 AC_MSG_CHECKING(for SMP support)
 AC_ARG_ENABLE(smp,
-	AS_HELP_STRING([--enable-smp], [Enable SMP support]),
+	AS_HELP_STRING([--disable-smp], [Disable SMP support (if the target supports it at all)]),
 	[case "$enableval" in
 	y | yes) CONFIG_SMP=y ;;
 	*) unset CONFIG_SMP ;;
Index: b/README.INSTALL
===================================================================
--- a/README.INSTALL
+++ b/README.INSTALL
@@ -143,7 +143,7 @@ NAME                 DESCRIPTION
 
 --prefix             Installation directory          /usr/xenomai
 --enable-debug       Enable debug symbols (-g)       disabled
---enable-smp         Enable SMP support              weak,disabled
+--disable-smp        Disable SMP support             weak,enabled
 
 1.3.3 Arch-specific configure options
 -------------------------------------



^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
                   ` (11 preceding siblings ...)
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 12/12] Enable SMP support for user libs by default Jan Kiszka
@ 2008-10-16 16:21 ` Gilles Chanteperdrix
  2008-10-17 12:28 ` Gilles Chanteperdrix
  13 siblings, 0 replies; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 16:21 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> Here comes a significantly reworked patch series to improve fast mutex
> support of Xenomai.
> 
> This approach now introduces a generic fast xnsynch core and converts
> the existing POSIX implementation over. It also comes with a second
> user, the Native skin. Additionally, it improves xeno_get_current via
> a TLS variable and addresses the issue that threads in secondary mode
> acquiring an uncontended mutex need to be migrated first.
> 
> At this chance, the TLS optimization is also applied on self-lookups of
> task handles (Native, VRTX and VxWorks). And I included my
> SMP-by-default patch for user libs which is highly recommended to reduce
> the risk of accidental code breakage on SMP with the new mutex code.

Looks like patches 11 and 12 are missing here.

-- 
                                                 Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 01/12] Generic thread registration
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 01/12] Generic thread registration Jan Kiszka
@ 2008-10-16 19:26   ` Gilles Chanteperdrix
  2008-10-16 21:55     ` Jan Kiszka
  0 siblings, 1 reply; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 19:26 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:

Why the funky last parameter added to __rt_bind_helper ?

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 02/12] Handle-based xeno_get_current service
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 02/12] Handle-based xeno_get_current service Jan Kiszka
@ 2008-10-16 19:36   ` Gilles Chanteperdrix
  0 siblings, 0 replies; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 19:36 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:

ok for me.

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 03/12] Remove xnarch_atomic_intptr
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 03/12] Remove xnarch_atomic_intptr Jan Kiszka
@ 2008-10-16 19:37   ` Gilles Chanteperdrix
  0 siblings, 0 replies; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 19:37 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:

Ok.

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 04/12] Spread xeno_set_current under all skins
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 04/12] Spread xeno_set_current under all skins Jan Kiszka
@ 2008-10-16 19:38   ` Gilles Chanteperdrix
  0 siblings, 0 replies; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 19:38 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:

Ok.

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 05/12] Factor out xnsynch_acquire/release
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 05/12] Factor out xnsynch_acquire/release Jan Kiszka
@ 2008-10-16 19:46   ` Gilles Chanteperdrix
  0 siblings, 0 replies; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 19:46 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:

Ok.

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 06/12] Lockless fast path for xnsynch_acquire/release
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 06/12] Lockless fast path for xnsynch_acquire/release Jan Kiszka
@ 2008-10-16 19:57   ` Gilles Chanteperdrix
  2008-10-16 21:55     ` Jan Kiszka
  0 siblings, 1 reply; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 19:57 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:

Ok. Though I do not see the point of the FASTSEM/FASTSYNCH rename.
FASTSEM is short, and we are not much interested in getting anything
else than semaphores faster.

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 07/12] Convert POSIX skin to fast xnsynch
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 07/12] Convert POSIX skin to fast xnsynch Jan Kiszka
@ 2008-10-16 20:05   ` Gilles Chanteperdrix
  2008-10-16 21:56     ` Jan Kiszka
  0 siblings, 1 reply; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 20:05 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:

This patch contains too many #ifdefs.

Things like

#ifdef CONFIG_XENO_FASTSYNCH
if (xnsynch_fast_owner_check(...))
#else
if (xnsynch_owner(...) == ...)
#endif

could be replaced with only one macro xnsynch_check_owner in synch.h
that would be defined with some #ifdefs, and used everywhere without
#ifdefs.

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin Jan Kiszka
@ 2008-10-16 20:13   ` Gilles Chanteperdrix
  2008-10-16 22:53     ` Jan Kiszka
  0 siblings, 1 reply; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 20:13 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:

Same remark for the #ifdefs. I also do not understand your modification
of rt_cond_wait_inner, this code is very tense; posix and native had the
same bug in this area at different times, so this change should probably
be made separately.

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 09/12] Optionally replace pthread_getspecific with TLS variables
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 09/12] Optionally replace pthread_getspecific with TLS variables Jan Kiszka
@ 2008-10-16 20:18   ` Gilles Chanteperdrix
  2008-10-16 22:26     ` Jan Kiszka
  0 siblings, 1 reply; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 20:18 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:

The real downside here is a lot of #ifdef clutter. What about the idea
of defining an API to abstract the differences between
pthread_get/setspecific and __thread and have #ifdef only in one header ?

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 10/12] Report current shadow thread mode to user space
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 10/12] Report current shadow thread mode to user space Jan Kiszka
@ 2008-10-16 20:23   ` Gilles Chanteperdrix
  2008-10-16 23:10     ` Jan Kiszka
  0 siblings, 1 reply; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 20:23 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:

Ok. I still liked the solution of using a piece of shared heap. This was
more general and would have allowed us to use this piece of shared heap
for future purposes.

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 11/12] Ensure mode switch in mutex fast paths
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 11/12] Ensure mode switch in mutex fast paths Jan Kiszka
@ 2008-10-16 20:27   ` Gilles Chanteperdrix
  0 siblings, 0 replies; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 20:27 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:

Ok.

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 12/12] Enable SMP support for user libs by default
  2008-10-16 15:46 ` [Xenomai-core] [PATCH 12/12] Enable SMP support for user libs by default Jan Kiszka
@ 2008-10-16 20:29   ` Gilles Chanteperdrix
  2008-10-16 22:14     ` Jan Kiszka
  0 siblings, 1 reply; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 20:29 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:

I do not like this patch. This sould be solved using the existing
features system. I do not want SMP to be enabled by default.

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 01/12] Generic thread registration
  2008-10-16 19:26   ` Gilles Chanteperdrix
@ 2008-10-16 21:55     ` Jan Kiszka
  0 siblings, 0 replies; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 21:55 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 320 bytes --]

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
> 
> Why the funky last parameter added to __rt_bind_helper ?

As __rt_bind_helper can now be called with an xnthread object address,
thus we take its offset inside RT_TASK into account. It is not a nice
interface, I know, but I didn't find a better one.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 258 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 06/12] Lockless fast path for xnsynch_acquire/release
  2008-10-16 19:57   ` Gilles Chanteperdrix
@ 2008-10-16 21:55     ` Jan Kiszka
  2008-10-16 21:58       ` Gilles Chanteperdrix
  0 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 21:55 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 404 bytes --]

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
> 
> Ok. Though I do not see the point of the FASTSEM/FASTSYNCH rename.
> FASTSEM is short, and we are not much interested in getting anything
> else than semaphores faster.

We aren't optimizing semaphores (at least not yet), we are optimizing
mutexes only. And if we ever optimize also semaphores, FASTSYNCH will
luckily still fit. :)

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 258 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 07/12] Convert POSIX skin to fast xnsynch
  2008-10-16 20:05   ` Gilles Chanteperdrix
@ 2008-10-16 21:56     ` Jan Kiszka
  0 siblings, 0 replies; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 21:56 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 532 bytes --]

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
> 
> This patch contains too many #ifdefs.
> 
> Things like
> 
> #ifdef CONFIG_XENO_FASTSYNCH
> if (xnsynch_fast_owner_check(...))
> #else
> if (xnsynch_owner(...) == ...)
> #endif
> 
> could be replaced with only one macro xnsynch_check_owner in synch.h
> that would be defined with some #ifdefs, and used everywhere without
> #ifdefs.

Yes, that looks like a good idea. Will go through the patch again,
checking for more cleanup possibilities like that.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 258 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 06/12] Lockless fast path for xnsynch_acquire/release
  2008-10-16 21:55     ` Jan Kiszka
@ 2008-10-16 21:58       ` Gilles Chanteperdrix
  2008-10-16 22:07         ` Jan Kiszka
  0 siblings, 1 reply; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 21:58 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> Gilles Chanteperdrix wrote:
>> Jan Kiszka wrote:
>>
>> Ok. Though I do not see the point of the FASTSEM/FASTSYNCH rename.
>> FASTSEM is short, and we are not much interested in getting anything
>> else than semaphores faster.
> 
> We aren't optimizing semaphores (at least not yet), we are optimizing
> mutexes only. And if we ever optimize also semaphores, FASTSYNCH will
> luckily still fit. :)

The name was chosen because we plan to optimize semaphores as well, and
because mutexes are simply a special kind of semaphores, so, by saying
FASTSEM, we cover semaphores as well as mutexes.

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 06/12] Lockless fast path for xnsynch_acquire/release
  2008-10-16 21:58       ` Gilles Chanteperdrix
@ 2008-10-16 22:07         ` Jan Kiszka
  2008-10-16 22:12           ` Gilles Chanteperdrix
  0 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 22:07 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 858 bytes --]

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
>> Gilles Chanteperdrix wrote:
>>> Jan Kiszka wrote:
>>>
>>> Ok. Though I do not see the point of the FASTSEM/FASTSYNCH rename.
>>> FASTSEM is short, and we are not much interested in getting anything
>>> else than semaphores faster.
>> We aren't optimizing semaphores (at least not yet), we are optimizing
>> mutexes only. And if we ever optimize also semaphores, FASTSYNCH will
>> luckily still fit. :)
> 
> The name was chosen because we plan to optimize semaphores as well, and
> because mutexes are simply a special kind of semaphores, so, by saying
> FASTSEM, we cover semaphores as well as mutexes.

That depends on how you define both - most semaphore definitions do not
include the ownership concept, thus are not a superclass of
(owner-tracking) mutexes we consider here.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 258 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 06/12] Lockless fast path for xnsynch_acquire/release
  2008-10-16 22:07         ` Jan Kiszka
@ 2008-10-16 22:12           ` Gilles Chanteperdrix
  0 siblings, 0 replies; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-16 22:12 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> Gilles Chanteperdrix wrote:
>> Jan Kiszka wrote:
>>> Gilles Chanteperdrix wrote:
>>>> Jan Kiszka wrote:
>>>>
>>>> Ok. Though I do not see the point of the FASTSEM/FASTSYNCH rename.
>>>> FASTSEM is short, and we are not much interested in getting anything
>>>> else than semaphores faster.
>>> We aren't optimizing semaphores (at least not yet), we are optimizing
>>> mutexes only. And if we ever optimize also semaphores, FASTSYNCH will
>>> luckily still fit. :)
>> The name was chosen because we plan to optimize semaphores as well, and
>> because mutexes are simply a special kind of semaphores, so, by saying
>> FASTSEM, we cover semaphores as well as mutexes.
> 
> That depends on how you define both - most semaphore definitions do not
> include the ownership concept, thus are not a superclass of
> (owner-tracking) mutexes we consider here.

>From my point of view, a mutex is a semaphore. If we imagine it in
simple OOP terms, the mutex class inherit from the semaphore class. Yes,
it has an owner member which the semaphore has not, but it still is a
semaphore.

-- 
					    Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 12/12] Enable SMP support for user libs by default
  2008-10-16 20:29   ` Gilles Chanteperdrix
@ 2008-10-16 22:14     ` Jan Kiszka
  0 siblings, 0 replies; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 22:14 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
> 
> I do not like this patch. This sould be solved using the existing
> features system. I do not want SMP to be enabled by default.

On x86, SMP is already the default case, other archs will follow soon.
I'm also fine with keeping those arch at default off which support SMP,
but use it only rarely in practice yet. But at least for x86, staying
with UP as default will quickly become annoying.

That said, I have no problem with additionally enforcing the right
configuration via the feature system. Will add that.

Jan


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 09/12] Optionally replace pthread_getspecific with TLS variables
  2008-10-16 20:18   ` Gilles Chanteperdrix
@ 2008-10-16 22:26     ` Jan Kiszka
  2008-10-17 15:02       ` Jan Kiszka
  0 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 22:26 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 604 bytes --]

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
> 
> The real downside here is a lot of #ifdef clutter. What about the idea
> of defining an API to abstract the differences between
> pthread_get/setspecific and __thread and have #ifdef only in one header ?

Sometimes you only store a value that way, sometimes you also have to
provide the object that is stored. Then its initialisation is fairly
specific.

Everything can be abstracted, but I'm not that optimistic that the
result will be better readable, just look at the patched users. Or what
abstractions do you have in mind?

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 258 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin
  2008-10-16 20:13   ` Gilles Chanteperdrix
@ 2008-10-16 22:53     ` Jan Kiszka
  2008-10-17  9:07       ` Gilles Chanteperdrix
  0 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 22:53 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 937 bytes --]

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
> 
> Same remark for the #ifdefs.

Yes, but most cases (maybe except for owner checking) are unavoidable
due to heavy differences. I hope that we may have only FASTXNSYCH archs
one day.

> I also do not understand your modification
> of rt_cond_wait_inner, this code is very tense; posix and native had the
> same bug in this area at different times, so this change should probably
> be made separately.

Which modification precisely (damn, I need to find out what makes quilt
cause this attachment confusion)? Note that lockcnt tracking changed
with this patch: the lock owner himself is in charge of maintaining it,
not some thread handing the lock over.

That said, I would happily analyse the case that broke before. I will
also check if I can break out the lockcnt maintenance change, but I
think to recall that it was coupled to the fast path changes.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 258 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 10/12] Report current shadow thread mode to user space
  2008-10-16 20:23   ` Gilles Chanteperdrix
@ 2008-10-16 23:10     ` Jan Kiszka
  2008-10-17  7:32       ` Jan Kiszka
  0 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-16 23:10 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 298 bytes --]

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
> 
> Ok. I still liked the solution of using a piece of shared heap. This was
> more general and would have allowed us to use this piece of shared heap
> for future purposes.

Shared heaps do not allow for the __thread optimization.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 258 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 10/12] Report current shadow thread mode to user space
  2008-10-16 23:10     ` Jan Kiszka
@ 2008-10-17  7:32       ` Jan Kiszka
  0 siblings, 0 replies; 50+ messages in thread
From: Jan Kiszka @ 2008-10-17  7:32 UTC (permalink / raw)
  Cc: xenomai

Jan Kiszka wrote:
> Gilles Chanteperdrix wrote:
>> Jan Kiszka wrote:
>>
>> Ok. I still liked the solution of using a piece of shared heap. This was
>> more general and would have allowed us to use this piece of shared heap
>> for future purposes.
> 
> Shared heaps do not allow for the __thread optimization.

Actually, not true. But it would add a level of indirection to this path.

So, before adding support for something that /may/ be of interest in
future (and that still could be added at that time): What further use
cases for _per-thread_ data that is shared between user space and kernel
do you see? I do have the syscall-less real-time clock in mind, but that
will be globally shared data.

Jan


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin
  2008-10-16 22:53     ` Jan Kiszka
@ 2008-10-17  9:07       ` Gilles Chanteperdrix
  2008-10-17 10:56         ` Jan Kiszka
  0 siblings, 1 reply; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-17  9:07 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> Gilles Chanteperdrix wrote:
>> Jan Kiszka wrote:
>>
>> Same remark for the #ifdefs.
> 
> Yes, but most cases (maybe except for owner checking) are unavoidable
> due to heavy differences. I hope that we may have only FASTXNSYCH archs
> one day.
> 
>> I also do not understand your modification
>> of rt_cond_wait_inner, this code is very tense; posix and native had the
>> same bug in this area at different times, so this change should probably
>> be made separately.
> 
> Which modification precisely (damn, I need to find out what makes quilt
> cause this attachment confusion)? Note that lockcnt tracking changed
> with this patch: the lock owner himself is in charge of maintaining it,
> not some thread handing the lock over.
> 
> That said, I would happily analyse the case that broke before. I will
> also check if I can break out the lockcnt maintenance change, but I
> think to recall that it was coupled to the fast path changes.

The point is that in case of rt_cond_wait, the mutex must unlock
completely regardless of the current lock count. So, the count is set to
1 before calling the function which unlocks the last level of the
recursion count. As far as I can see, you removed the part which sets
the counter to 1.

-- 
                                                 Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin
  2008-10-17  9:07       ` Gilles Chanteperdrix
@ 2008-10-17 10:56         ` Jan Kiszka
  2008-10-17 10:58           ` Gilles Chanteperdrix
  0 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-17 10:56 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 2208 bytes --]

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
>> Gilles Chanteperdrix wrote:
>>> Jan Kiszka wrote:
>>>
>>> Same remark for the #ifdefs.
>> Yes, but most cases (maybe except for owner checking) are unavoidable
>> due to heavy differences. I hope that we may have only FASTXNSYCH archs
>> one day.
>>
>>> I also do not understand your modification
>>> of rt_cond_wait_inner, this code is very tense; posix and native had the
>>> same bug in this area at different times, so this change should probably
>>> be made separately.
>> Which modification precisely (damn, I need to find out what makes quilt
>> cause this attachment confusion)? Note that lockcnt tracking changed
>> with this patch: the lock owner himself is in charge of maintaining it,
>> not some thread handing the lock over.
>>
>> That said, I would happily analyse the case that broke before. I will
>> also check if I can break out the lockcnt maintenance change, but I
>> think to recall that it was coupled to the fast path changes.
> 
> The point is that in case of rt_cond_wait, the mutex must unlock
> completely regardless of the current lock count. So, the count is set to
> 1 before calling the function which unlocks the last level of the
> recursion count. As far as I can see, you removed the part which sets
> the counter to 1.
> 

Don't find that spot. Are we talking about this change or something else?

> --- a/ksrc/skins/native/cond.c
> +++ b/ksrc/skins/native/cond.c
> @@ -407,24 +407,26 @@ int rt_cond_wait_inner(RT_COND *cond, RT
...
>  	mutex->lockcnt = 0;
>  
> -	if (xnsynch_release(&mutex->synch_base)) {
> -		mutex->lockcnt = 1;
> -		/* Scheduling deferred */
> -	}
> +	xnsynch_release(&mutex->synch_base);
> +	/* Scheduling deferred */
>  
>  	xnsynch_sleep_on(&cond->synch_base, timeout, timeout_mode);
>  

In case it's the above: That setting of lockcnt is actually on behalf of
the new owner (xnsynch_release != NULL => we woke up a new owner). And
that has been sanitized in the patch in so far that only the owner
manipulates lockcnt, always. If you see a remaining issue in this
approach or find a hole in the implementation, please let me know.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin
  2008-10-17 10:56         ` Jan Kiszka
@ 2008-10-17 10:58           ` Gilles Chanteperdrix
  2008-10-17 11:11             ` Jan Kiszka
  2008-10-17 11:14             ` Gilles Chanteperdrix
  0 siblings, 2 replies; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-17 10:58 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> Gilles Chanteperdrix wrote:
>> Jan Kiszka wrote:
>>> Gilles Chanteperdrix wrote:
>>>> Jan Kiszka wrote:
>>>>
>>>> Same remark for the #ifdefs.
>>> Yes, but most cases (maybe except for owner checking) are unavoidable
>>> due to heavy differences. I hope that we may have only FASTXNSYCH archs
>>> one day.
>>>
>>>> I also do not understand your modification
>>>> of rt_cond_wait_inner, this code is very tense; posix and native had the
>>>> same bug in this area at different times, so this change should probably
>>>> be made separately.
>>> Which modification precisely (damn, I need to find out what makes quilt
>>> cause this attachment confusion)? Note that lockcnt tracking changed
>>> with this patch: the lock owner himself is in charge of maintaining it,
>>> not some thread handing the lock over.
>>>
>>> That said, I would happily analyse the case that broke before. I will
>>> also check if I can break out the lockcnt maintenance change, but I
>>> think to recall that it was coupled to the fast path changes.
>> The point is that in case of rt_cond_wait, the mutex must unlock
>> completely regardless of the current lock count. So, the count is set to
>> 1 before calling the function which unlocks the last level of the
>> recursion count. As far as I can see, you removed the part which sets
>> the counter to 1.
>>
> 
> Don't find that spot. Are we talking about this change or something else?
> 
>> --- a/ksrc/skins/native/cond.c
>> +++ b/ksrc/skins/native/cond.c
>> @@ -407,24 +407,26 @@ int rt_cond_wait_inner(RT_COND *cond, RT
> ...
>>  	mutex->lockcnt = 0;
>>  
>> -	if (xnsynch_release(&mutex->synch_base)) {
>> -		mutex->lockcnt = 1;
>> -		/* Scheduling deferred */
>> -	}
>> +	xnsynch_release(&mutex->synch_base);
>> +	/* Scheduling deferred */
>>  
>>  	xnsynch_sleep_on(&cond->synch_base, timeout, timeout_mode);
>>  
> 
> In case it's the above: That setting of lockcnt is actually on behalf of
> the new owner (xnsynch_release != NULL => we woke up a new owner). And
> that has been sanitized in the patch in so far that only the owner
> manipulates lockcnt, always. If you see a remaining issue in this
> approach or find a hole in the implementation, please let me know.

Who sets the lockcnt to 0 if there is no next owner ?

-- 
                                                 Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin
  2008-10-17 10:58           ` Gilles Chanteperdrix
@ 2008-10-17 11:11             ` Jan Kiszka
  2008-10-17 11:14             ` Gilles Chanteperdrix
  1 sibling, 0 replies; 50+ messages in thread
From: Jan Kiszka @ 2008-10-17 11:11 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 2450 bytes --]

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
>> Gilles Chanteperdrix wrote:
>>> Jan Kiszka wrote:
>>>> Gilles Chanteperdrix wrote:
>>>>> Jan Kiszka wrote:
>>>>>
>>>>> Same remark for the #ifdefs.
>>>> Yes, but most cases (maybe except for owner checking) are unavoidable
>>>> due to heavy differences. I hope that we may have only FASTXNSYCH archs
>>>> one day.
>>>>
>>>>> I also do not understand your modification
>>>>> of rt_cond_wait_inner, this code is very tense; posix and native had the
>>>>> same bug in this area at different times, so this change should probably
>>>>> be made separately.
>>>> Which modification precisely (damn, I need to find out what makes quilt
>>>> cause this attachment confusion)? Note that lockcnt tracking changed
>>>> with this patch: the lock owner himself is in charge of maintaining it,
>>>> not some thread handing the lock over.
>>>>
>>>> That said, I would happily analyse the case that broke before. I will
>>>> also check if I can break out the lockcnt maintenance change, but I
>>>> think to recall that it was coupled to the fast path changes.
>>> The point is that in case of rt_cond_wait, the mutex must unlock
>>> completely regardless of the current lock count. So, the count is set to
>>> 1 before calling the function which unlocks the last level of the
>>> recursion count. As far as I can see, you removed the part which sets
>>> the counter to 1.
>>>
>> Don't find that spot. Are we talking about this change or something else?
>>
>>> --- a/ksrc/skins/native/cond.c
>>> +++ b/ksrc/skins/native/cond.c
>>> @@ -407,24 +407,26 @@ int rt_cond_wait_inner(RT_COND *cond, RT
>> ...
>>>  	mutex->lockcnt = 0;
>>>  
>>> -	if (xnsynch_release(&mutex->synch_base)) {
>>> -		mutex->lockcnt = 1;
>>> -		/* Scheduling deferred */
>>> -	}
>>> +	xnsynch_release(&mutex->synch_base);
>>> +	/* Scheduling deferred */
>>>  
>>>  	xnsynch_sleep_on(&cond->synch_base, timeout, timeout_mode);
>>>  
>> In case it's the above: That setting of lockcnt is actually on behalf of
>> the new owner (xnsynch_release != NULL => we woke up a new owner). And
>> that has been sanitized in the patch in so far that only the owner
>> manipulates lockcnt, always. If you see a remaining issue in this
>> approach or find a hole in the implementation, please let me know.
> 
> Who sets the lockcnt to 0 if there is no next owner ?

Look up, only a few lines...

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin
  2008-10-17 10:58           ` Gilles Chanteperdrix
  2008-10-17 11:11             ` Jan Kiszka
@ 2008-10-17 11:14             ` Gilles Chanteperdrix
  2008-10-17 11:21               ` Jan Kiszka
  1 sibling, 1 reply; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-17 11:14 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
>> Gilles Chanteperdrix wrote:
>>> Jan Kiszka wrote:
>>>> Gilles Chanteperdrix wrote:
>>>>> Jan Kiszka wrote:
>>>>>
>>>>> Same remark for the #ifdefs.
>>>> Yes, but most cases (maybe except for owner checking) are unavoidable
>>>> due to heavy differences. I hope that we may have only FASTXNSYCH archs
>>>> one day.
>>>>
>>>>> I also do not understand your modification
>>>>> of rt_cond_wait_inner, this code is very tense; posix and native had the
>>>>> same bug in this area at different times, so this change should probably
>>>>> be made separately.
>>>> Which modification precisely (damn, I need to find out what makes quilt
>>>> cause this attachment confusion)? Note that lockcnt tracking changed
>>>> with this patch: the lock owner himself is in charge of maintaining it,
>>>> not some thread handing the lock over.
>>>>
>>>> That said, I would happily analyse the case that broke before. I will
>>>> also check if I can break out the lockcnt maintenance change, but I
>>>> think to recall that it was coupled to the fast path changes.
>>> The point is that in case of rt_cond_wait, the mutex must unlock
>>> completely regardless of the current lock count. So, the count is set to
>>> 1 before calling the function which unlocks the last level of the
>>> recursion count. As far as I can see, you removed the part which sets
>>> the counter to 1.
>>>
>> Don't find that spot. Are we talking about this change or something else?
>>
>>> --- a/ksrc/skins/native/cond.c
>>> +++ b/ksrc/skins/native/cond.c
>>> @@ -407,24 +407,26 @@ int rt_cond_wait_inner(RT_COND *cond, RT
>> ...
>>>  	mutex->lockcnt = 0;
>>>  
>>> -	if (xnsynch_release(&mutex->synch_base)) {
>>> -		mutex->lockcnt = 1;
>>> -		/* Scheduling deferred */
>>> -	}
>>> +	xnsynch_release(&mutex->synch_base);
>>> +	/* Scheduling deferred */
>>>  
>>>  	xnsynch_sleep_on(&cond->synch_base, timeout, timeout_mode);
>>>  
>> In case it's the above: That setting of lockcnt is actually on behalf of
>> the new owner (xnsynch_release != NULL => we woke up a new owner). And
>> that has been sanitized in the patch in so far that only the owner
>> manipulates lockcnt, always. If you see a remaining issue in this
>> approach or find a hole in the implementation, please let me know.
> 
> Who sets the lockcnt to 0 if there is no next owner ?

Ok. It appears in the code you quoted. However, your modification
changes the behaviour of the mutex code:

with the old version, the mutex will appear locked if an owner has been
woken up
with the new version, the mutex will appear unlocked between the time
when a new owner has been woken up and the time this new owner gets out
of xnsynch_acquire, allowing the lock to be stolen by another thread.


-- 
                                                 Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin
  2008-10-17 11:14             ` Gilles Chanteperdrix
@ 2008-10-17 11:21               ` Jan Kiszka
  2008-10-17 11:37                 ` Gilles Chanteperdrix
  0 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-17 11:21 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 3353 bytes --]

Gilles Chanteperdrix wrote:
> Gilles Chanteperdrix wrote:
>> Jan Kiszka wrote:
>>> Gilles Chanteperdrix wrote:
>>>> Jan Kiszka wrote:
>>>>> Gilles Chanteperdrix wrote:
>>>>>> Jan Kiszka wrote:
>>>>>>
>>>>>> Same remark for the #ifdefs.
>>>>> Yes, but most cases (maybe except for owner checking) are unavoidable
>>>>> due to heavy differences. I hope that we may have only FASTXNSYCH archs
>>>>> one day.
>>>>>
>>>>>> I also do not understand your modification
>>>>>> of rt_cond_wait_inner, this code is very tense; posix and native had the
>>>>>> same bug in this area at different times, so this change should probably
>>>>>> be made separately.
>>>>> Which modification precisely (damn, I need to find out what makes quilt
>>>>> cause this attachment confusion)? Note that lockcnt tracking changed
>>>>> with this patch: the lock owner himself is in charge of maintaining it,
>>>>> not some thread handing the lock over.
>>>>>
>>>>> That said, I would happily analyse the case that broke before. I will
>>>>> also check if I can break out the lockcnt maintenance change, but I
>>>>> think to recall that it was coupled to the fast path changes.
>>>> The point is that in case of rt_cond_wait, the mutex must unlock
>>>> completely regardless of the current lock count. So, the count is set to
>>>> 1 before calling the function which unlocks the last level of the
>>>> recursion count. As far as I can see, you removed the part which sets
>>>> the counter to 1.
>>>>
>>> Don't find that spot. Are we talking about this change or something else?
>>>
>>>> --- a/ksrc/skins/native/cond.c
>>>> +++ b/ksrc/skins/native/cond.c
>>>> @@ -407,24 +407,26 @@ int rt_cond_wait_inner(RT_COND *cond, RT
>>> ...
>>>>  	mutex->lockcnt = 0;
>>>>  
>>>> -	if (xnsynch_release(&mutex->synch_base)) {
>>>> -		mutex->lockcnt = 1;
>>>> -		/* Scheduling deferred */
>>>> -	}
>>>> +	xnsynch_release(&mutex->synch_base);
>>>> +	/* Scheduling deferred */
>>>>  
>>>>  	xnsynch_sleep_on(&cond->synch_base, timeout, timeout_mode);
>>>>  
>>> In case it's the above: That setting of lockcnt is actually on behalf of
>>> the new owner (xnsynch_release != NULL => we woke up a new owner). And
>>> that has been sanitized in the patch in so far that only the owner
>>> manipulates lockcnt, always. If you see a remaining issue in this
>>> approach or find a hole in the implementation, please let me know.
>> Who sets the lockcnt to 0 if there is no next owner ?
> 
> Ok. It appears in the code you quoted. However, your modification
> changes the behaviour of the mutex code:
> 
> with the old version, the mutex will appear locked if an owner has been
> woken up
> with the new version, the mutex will appear unlocked between the time
> when a new owner has been woken up and the time this new owner gets out
> of xnsynch_acquire, allowing the lock to be stolen by another thread.

But that is what cond_wait is about: releasing the associated lock to
whoever gets it - either directly or via lock-stealing. I see no problem
here. Moreover, lockcnt is never used (and must not!) as an indication
if a lock is free. It is a pure helper for the lock owner to track
recursion. And it is also no longer consistent between kernel and user
side, another reason to allow only the lock owner to play with it.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin
  2008-10-17 11:21               ` Jan Kiszka
@ 2008-10-17 11:37                 ` Gilles Chanteperdrix
  0 siblings, 0 replies; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-17 11:37 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> But that is what cond_wait is about: releasing the associated lock to
> whoever gets it - either directly or via lock-stealing. I see no problem
> here. Moreover, lockcnt is never used (and must not!) as an indication
> if a lock is free. It is a pure helper for the lock owner to track
> recursion. And it is also no longer consistent between kernel and user
> side, another reason to allow only the lock owner to play with it.

Right.

-- 
                                                 Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more
  2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
                   ` (12 preceding siblings ...)
  2008-10-16 16:21 ` [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Gilles Chanteperdrix
@ 2008-10-17 12:28 ` Gilles Chanteperdrix
  2008-10-17 12:44   ` Jan Kiszka
  13 siblings, 1 reply; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-17 12:28 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> Here comes a significantly reworked patch series to improve fast mutex
> support of Xenomai.
> 
> This approach now introduces a generic fast xnsynch core and converts
> the existing POSIX implementation over. It also comes with a second
> user, the Native skin. Additionally, it improves xeno_get_current via
> a TLS variable and addresses the issue that threads in secondary mode
> acquiring an uncontended mutex need to be migrated first.
> 
> At this chance, the TLS optimization is also applied on self-lookups of
> task handles (Native, VRTX and VxWorks). And I included my
> SMP-by-default patch for user libs which is highly recommended to reduce
> the risk of accidental code breakage on SMP with the new mutex code.

A minor remark. This is the third round of patches for fast mutexes, and
 each round, you submit even more changes to review than the previous
round. If I doubted of your honesty, I could think that you are trying
to dilute some questionable changes into more changes so that they get
unnoticed.

Could we focus on a small set of changes, reach consensus, merge them,
and then move to the next set of changes?

-- 
                                                 Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more
  2008-10-17 12:28 ` Gilles Chanteperdrix
@ 2008-10-17 12:44   ` Jan Kiszka
  2008-10-17 12:51     ` Gilles Chanteperdrix
  0 siblings, 1 reply; 50+ messages in thread
From: Jan Kiszka @ 2008-10-17 12:44 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
>> Here comes a significantly reworked patch series to improve fast mutex
>> support of Xenomai.
>>
>> This approach now introduces a generic fast xnsynch core and converts
>> the existing POSIX implementation over. It also comes with a second
>> user, the Native skin. Additionally, it improves xeno_get_current via
>> a TLS variable and addresses the issue that threads in secondary mode
>> acquiring an uncontended mutex need to be migrated first.
>>
>> At this chance, the TLS optimization is also applied on self-lookups of
>> task handles (Native, VRTX and VxWorks). And I included my
>> SMP-by-default patch for user libs which is highly recommended to reduce
>> the risk of accidental code breakage on SMP with the new mutex code.
> 
> A minor remark. This is the third round of patches for fast mutexes, and
>  each round, you submit even more changes to review than the previous
> round. If I doubted of your honesty, I could think that you are trying
> to dilute some questionable changes into more changes so that they get
> unnoticed.

May I recall the changelog of this round? In short:

 - generic xnsynch
 - fixed prio-inversion when coming from secondary mode

These are major changes, addressing specifically the NACKs of the
previous rounds.

If you find "questionable changes", please point them out. So far I only
recall the discussion about lockcnt maintenance policy, and I will try
to sort that one out.

> Could we focus on a small set of changes, reach consensus, merge them,
> and then move to the next set of changes?

No problem. Maybe I missed or forgot the clear OK for patches 1..4 to
commit them, but I will now soon. Moreover, I just felt uncomfortable
with merging patch 5 without having written to following ones.

Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more
  2008-10-17 12:44   ` Jan Kiszka
@ 2008-10-17 12:51     ` Gilles Chanteperdrix
  2008-10-17 13:31       ` Jan Kiszka
  2008-10-17 13:36       ` Philippe Gerum
  0 siblings, 2 replies; 50+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-17 12:51 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> Gilles Chanteperdrix wrote:
>> Jan Kiszka wrote:
>>> Here comes a significantly reworked patch series to improve fast mutex
>>> support of Xenomai.
>>>
>>> This approach now introduces a generic fast xnsynch core and converts
>>> the existing POSIX implementation over. It also comes with a second
>>> user, the Native skin. Additionally, it improves xeno_get_current via
>>> a TLS variable and addresses the issue that threads in secondary mode
>>> acquiring an uncontended mutex need to be migrated first.
>>>
>>> At this chance, the TLS optimization is also applied on self-lookups of
>>> task handles (Native, VRTX and VxWorks). And I included my
>>> SMP-by-default patch for user libs which is highly recommended to reduce
>>> the risk of accidental code breakage on SMP with the new mutex code.
>> A minor remark. This is the third round of patches for fast mutexes, and
>>  each round, you submit even more changes to review than the previous
>> round. If I doubted of your honesty, I could think that you are trying
>> to dilute some questionable changes into more changes so that they get
>> unnoticed.
> 
> May I recall the changelog of this round? In short:
> 
>  - generic xnsynch
>  - fixed prio-inversion when coming from secondary mode
> 
> These are major changes, addressing specifically the NACKs of the
> previous rounds.
> 
> If you find "questionable changes", please point them out. So far I only
> recall the discussion about lockcnt maintenance policy, and I will try
> to sort that one out.

The problem is that it took me about one hour reviewing your 12 patches
(I know, I am a slow guy), and that I am not even sure that I saw all
the changes.

The lockcnt change in patch 8 for instance is not even mentioned in the
patch comments, and it is only because I originally did not understand
the change in rt_cond_wait_inner that I now know about this change.

> 
>> Could we focus on a small set of changes, reach consensus, merge them,
>> and then move to the next set of changes?
> 
> No problem. Maybe I missed or forgot the clear OK for patches 1..4 to
> commit them, but I will now soon. Moreover, I just felt uncomfortable
> with merging patch 5 without having written to following ones.

I think Philippe should merge the patches.

-- 
                                                 Gilles.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more
  2008-10-17 12:51     ` Gilles Chanteperdrix
@ 2008-10-17 13:31       ` Jan Kiszka
  2008-10-17 13:36       ` Philippe Gerum
  1 sibling, 0 replies; 50+ messages in thread
From: Jan Kiszka @ 2008-10-17 13:31 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
>> Gilles Chanteperdrix wrote:
>>> Jan Kiszka wrote:
>>>> Here comes a significantly reworked patch series to improve fast mutex
>>>> support of Xenomai.
>>>>
>>>> This approach now introduces a generic fast xnsynch core and converts
>>>> the existing POSIX implementation over. It also comes with a second
>>>> user, the Native skin. Additionally, it improves xeno_get_current via
>>>> a TLS variable and addresses the issue that threads in secondary mode
>>>> acquiring an uncontended mutex need to be migrated first.
>>>>
>>>> At this chance, the TLS optimization is also applied on self-lookups of
>>>> task handles (Native, VRTX and VxWorks). And I included my
>>>> SMP-by-default patch for user libs which is highly recommended to reduce
>>>> the risk of accidental code breakage on SMP with the new mutex code.
>>> A minor remark. This is the third round of patches for fast mutexes, and
>>>  each round, you submit even more changes to review than the previous
>>> round. If I doubted of your honesty, I could think that you are trying
>>> to dilute some questionable changes into more changes so that they get
>>> unnoticed.
>> May I recall the changelog of this round? In short:
>>
>>  - generic xnsynch
>>  - fixed prio-inversion when coming from secondary mode
>>
>> These are major changes, addressing specifically the NACKs of the
>> previous rounds.
>>
>> If you find "questionable changes", please point them out. So far I only
>> recall the discussion about lockcnt maintenance policy, and I will try
>> to sort that one out.
> 
> The problem is that it took me about one hour reviewing your 12 patches
> (I know, I am a slow guy), and that I am not even sure that I saw all
> the changes.

I appreciate your effort very much, and you already provided valuable
input. But I feel it is much better to have the full picture instead of
scattered bits. And this 12 patches belong together until none of their
features are merged.

> 
> The lockcnt change in patch 8 for instance is not even mentioned in the
> patch comments, and it is only because I originally did not understand
> the change in rt_cond_wait_inner that I now know about this change.

Sorry for that, but it fell under the table on which all the other
significant changes were already lying. Moreover, I originally felt it
was only a minor cleanup as I simply aligned the code to the POSIX
implementation in this regard. Nevertheless, the next posting will
contain a separate patch for this.

>>> Could we focus on a small set of changes, reach consensus, merge them,
>>> and then move to the next set of changes?
>> No problem. Maybe I missed or forgot the clear OK for patches 1..4 to
>> commit them, but I will now soon. Moreover, I just felt uncomfortable
>> with merging patch 5 without having written to following ones.
> 
> I think Philippe should merge the patches.

Also fine.

Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more
  2008-10-17 12:51     ` Gilles Chanteperdrix
  2008-10-17 13:31       ` Jan Kiszka
@ 2008-10-17 13:36       ` Philippe Gerum
  1 sibling, 0 replies; 50+ messages in thread
From: Philippe Gerum @ 2008-10-17 13:36 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: Jan Kiszka, xenomai

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
>> Gilles Chanteperdrix wrote:
>>> Jan Kiszka wrote:
>>>> Here comes a significantly reworked patch series to improve fast mutex
>>>> support of Xenomai.
>>>>
>>>> This approach now introduces a generic fast xnsynch core and converts
>>>> the existing POSIX implementation over. It also comes with a second
>>>> user, the Native skin. Additionally, it improves xeno_get_current via
>>>> a TLS variable and addresses the issue that threads in secondary mode
>>>> acquiring an uncontended mutex need to be migrated first.
>>>>
>>>> At this chance, the TLS optimization is also applied on self-lookups of
>>>> task handles (Native, VRTX and VxWorks). And I included my
>>>> SMP-by-default patch for user libs which is highly recommended to reduce
>>>> the risk of accidental code breakage on SMP with the new mutex code.
>>> A minor remark. This is the third round of patches for fast mutexes, and
>>>  each round, you submit even more changes to review than the previous
>>> round. If I doubted of your honesty, I could think that you are trying
>>> to dilute some questionable changes into more changes so that they get
>>> unnoticed.
>> May I recall the changelog of this round? In short:
>>
>>  - generic xnsynch
>>  - fixed prio-inversion when coming from secondary mode
>>
>> These are major changes, addressing specifically the NACKs of the
>> previous rounds.
>>
>> If you find "questionable changes", please point them out. So far I only
>> recall the discussion about lockcnt maintenance policy, and I will try
>> to sort that one out.
> 
> The problem is that it took me about one hour reviewing your 12 patches
> (I know, I am a slow guy), and that I am not even sure that I saw all
> the changes.
> 
> The lockcnt change in patch 8 for instance is not even mentioned in the
> patch comments, and it is only because I originally did not understand
> the change in rt_cond_wait_inner that I now know about this change.
> 
>>> Could we focus on a small set of changes, reach consensus, merge them,
>>> and then move to the next set of changes?
>> No problem. Maybe I missed or forgot the clear OK for patches 1..4 to
>> commit them, but I will now soon. Moreover, I just felt uncomfortable
>> with merging patch 5 without having written to following ones.
> 
> I think Philippe should merge the patches.
> 

Ack.

-- 
Philippe.


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Xenomai-core] [PATCH 09/12] Optionally replace pthread_getspecific with TLS variables
  2008-10-16 22:26     ` Jan Kiszka
@ 2008-10-17 15:02       ` Jan Kiszka
  0 siblings, 0 replies; 50+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:02 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai

Jan Kiszka wrote:
> Gilles Chanteperdrix wrote:
>> Jan Kiszka wrote:
>>
>> The real downside here is a lot of #ifdef clutter. What about the idea
>> of defining an API to abstract the differences between
>> pthread_get/setspecific and __thread and have #ifdef only in one header ?
> 
> Sometimes you only store a value that way, sometimes you also have to
> provide the object that is stored. Then its initialisation is fairly
> specific.
> 
> Everything can be abstracted, but I'm not that optimistic that the
> result will be better readable, just look at the patched users. Or what
> abstractions do you have in mind?

I tried, but I failed. The usage differences in the skins are to
significant to define a generic per-thread wrapper that fits at least a
subset of use cases.

Anyway, I was at least able to eliminate two #ifdefs by converting the
xeno_current_key initialization from pthread_once to a constructor
function (that is under #ifdef anyway). Updates will follow.

Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux


^ permalink raw reply	[flat|nested] 50+ messages in thread

end of thread, other threads:[~2008-10-17 15:02 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-16 15:46 [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Jan Kiszka
2008-10-16 15:46 ` [Xenomai-core] [PATCH 01/12] Generic thread registration Jan Kiszka
2008-10-16 19:26   ` Gilles Chanteperdrix
2008-10-16 21:55     ` Jan Kiszka
2008-10-16 15:46 ` [Xenomai-core] [PATCH 02/12] Handle-based xeno_get_current service Jan Kiszka
2008-10-16 19:36   ` Gilles Chanteperdrix
2008-10-16 15:46 ` [Xenomai-core] [PATCH 03/12] Remove xnarch_atomic_intptr Jan Kiszka
2008-10-16 19:37   ` Gilles Chanteperdrix
2008-10-16 15:46 ` [Xenomai-core] [PATCH 04/12] Spread xeno_set_current under all skins Jan Kiszka
2008-10-16 19:38   ` Gilles Chanteperdrix
2008-10-16 15:46 ` [Xenomai-core] [PATCH 05/12] Factor out xnsynch_acquire/release Jan Kiszka
2008-10-16 19:46   ` Gilles Chanteperdrix
2008-10-16 15:46 ` [Xenomai-core] [PATCH 06/12] Lockless fast path for xnsynch_acquire/release Jan Kiszka
2008-10-16 19:57   ` Gilles Chanteperdrix
2008-10-16 21:55     ` Jan Kiszka
2008-10-16 21:58       ` Gilles Chanteperdrix
2008-10-16 22:07         ` Jan Kiszka
2008-10-16 22:12           ` Gilles Chanteperdrix
2008-10-16 15:46 ` [Xenomai-core] [PATCH 07/12] Convert POSIX skin to fast xnsynch Jan Kiszka
2008-10-16 20:05   ` Gilles Chanteperdrix
2008-10-16 21:56     ` Jan Kiszka
2008-10-16 15:46 ` [Xenomai-core] [PATCH 08/12] Use fast xnsynch with native skin Jan Kiszka
2008-10-16 20:13   ` Gilles Chanteperdrix
2008-10-16 22:53     ` Jan Kiszka
2008-10-17  9:07       ` Gilles Chanteperdrix
2008-10-17 10:56         ` Jan Kiszka
2008-10-17 10:58           ` Gilles Chanteperdrix
2008-10-17 11:11             ` Jan Kiszka
2008-10-17 11:14             ` Gilles Chanteperdrix
2008-10-17 11:21               ` Jan Kiszka
2008-10-17 11:37                 ` Gilles Chanteperdrix
2008-10-16 15:46 ` [Xenomai-core] [PATCH 09/12] Optionally replace pthread_getspecific with TLS variables Jan Kiszka
2008-10-16 20:18   ` Gilles Chanteperdrix
2008-10-16 22:26     ` Jan Kiszka
2008-10-17 15:02       ` Jan Kiszka
2008-10-16 15:46 ` [Xenomai-core] [PATCH 10/12] Report current shadow thread mode to user space Jan Kiszka
2008-10-16 20:23   ` Gilles Chanteperdrix
2008-10-16 23:10     ` Jan Kiszka
2008-10-17  7:32       ` Jan Kiszka
2008-10-16 15:46 ` [Xenomai-core] [PATCH 11/12] Ensure mode switch in mutex fast paths Jan Kiszka
2008-10-16 20:27   ` Gilles Chanteperdrix
2008-10-16 15:46 ` [Xenomai-core] [PATCH 12/12] Enable SMP support for user libs by default Jan Kiszka
2008-10-16 20:29   ` Gilles Chanteperdrix
2008-10-16 22:14     ` Jan Kiszka
2008-10-16 16:21 ` [Xenomai-core] [PATCH 00/12] Generic fast xnsynch support & more Gilles Chanteperdrix
2008-10-17 12:28 ` Gilles Chanteperdrix
2008-10-17 12:44   ` Jan Kiszka
2008-10-17 12:51     ` Gilles Chanteperdrix
2008-10-17 13:31       ` Jan Kiszka
2008-10-17 13:36       ` Philippe Gerum

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.