Skip to contentSkip to conversation

Handle-based fast mutex owner tracking

RFC PATCH In review Jan Kiszka 3 participants 68 messages Aug 27, 2008 – Aug 29, 2008

Subsystems (2)
lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

cover Handle-based fast mutex owner tracking

Hi Gilles,

this is a prototype patch series to explore handle-based lock owner tracking in the fast mutex lock variable. It appears to work, so I'm rolling it out for collecting early comments, specifically from you.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
author
#1 lore raw

RFC PATCH 1/3 Always register threads by their base

In order to use xnthread_handle(thread) for the fast mutex lock variable, we have to ensure that all skins pass the generic object on xnregistry_enter. The following patch ensures this for preexisting registrations.

---
 ksrc/skins/native/syscall.c  |   56 +++++++++++++++++++++++++------------------
 ksrc/skins/native/task.c     |    2 -
 ksrc/skins/psos+/syscall.c   |   14 +++++-----
 ksrc/skins/psos+/task.c      |    7 +++--
 ksrc/skins/vxworks/syscall.c |   28 +++++++++++----------
 ksrc/skins/vxworks/taskLib.c |    4 +--
 6 files changed, 63 insertions(+), 48 deletions(-)
ksrc/skins/native/syscall.c +33 -23
Index: 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
@@ -223,7 +224,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 +256,7 @@ static int __rt_task_start(struct pt_reg
 				     sizeof(ph)))
 		return -EFAULT;
 
-	task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+	task = thread2rtask((xnthread_t *)xnregistry_fetch(ph.opaque));
 
 	if (!task)
 		return -ESRCH;
@@ -279,7 +282,7 @@ static int __rt_task_suspend(struct pt_r
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = thread2rtask((xnthread_t *)xnregistry_fetch(ph.opaque));
 	} else
 		task = __rt_task_current(p);
 
@@ -302,7 +305,7 @@ static int __rt_task_resume(struct pt_re
 				     sizeof(ph)))
 		return -EFAULT;
 
-	task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+	task = thread2rtask((xnthread_t *)xnregistry_fetch(ph.opaque));
 
 	if (!task)
 		return -ESRCH;
@@ -326,7 +329,7 @@ static int __rt_task_delete(struct pt_re
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = thread2rtask((xnthread_t *)xnregistry_fetch(ph.opaque));
 	} else
 		task = __rt_task_current(p);
 
@@ -364,7 +367,7 @@ static int __rt_task_set_periodic(struct
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = thread2rtask((xnthread_t *)xnregistry_fetch(ph.opaque));
 	} else
 		task = __rt_task_current(p);
 
@@ -418,7 +421,7 @@ static int __rt_task_set_priority(struct
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = thread2rtask((xnthread_t *)xnregistry_fetch(ph.opaque));
 	} else
 		task = __rt_task_current(p);
 
@@ -473,7 +476,7 @@ static int __rt_task_unblock(struct pt_r
 				     sizeof(ph)))
 		return -EFAULT;
 
-	task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+	task = thread2rtask((xnthread_t *)xnregistry_fetch(ph.opaque));
 
 	if (!task)
 		return -ESRCH;
@@ -500,7 +503,7 @@ static int __rt_task_inquire(struct pt_r
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = thread2rtask((xnthread_t *)xnregistry_fetch(ph.opaque));
 	} else
 		task = __rt_task_current(p);
 
@@ -541,7 +544,7 @@ static int __rt_task_notify(struct pt_re
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = thread2rtask((xnthread_t *)xnregistry_fetch(ph.opaque));
 	} else
 		task = __rt_task_current(p);
 
@@ -627,7 +630,7 @@ static int __rt_task_slice(struct pt_reg
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = thread2rtask((xnthread_t *)xnregistry_fetch(ph.opaque));
 	} else
 		task = __rt_task_current(current);
 
@@ -667,7 +670,7 @@ static int __rt_task_send(struct pt_regs
 					     sizeof(ph)))
 			return -EFAULT;
 
-		task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+		task = thread2rtask((xnthread_t *)xnregistry_fetch(ph.opaque));
 	} else
 		task = __rt_task_current(current);
 
@@ -1104,7 +1107,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 +1329,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 +1573,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 +1765,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 +2016,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 +2515,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 +3026,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 +3283,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 +3559,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;
 
ksrc/skins/native/task.c +1 -1
Index: b/ksrc/skins/native/task.c
===================================================================
@@ -292,7 +292,7 @@ int rt_task_create(RT_TASK *task,
 
 	if (name) {
 		err = xnregistry_enter(task->rname,
-				       task,
+				       &task->thread_base,
 				       &xnthread_handle(&task->thread_base),
 				       NULL);
 		if (err)
ksrc/skins/psos+/syscall.c +7 -7
Index: b/ksrc/skins/psos+/syscall.c
===================================================================
@@ -131,7 +131,7 @@ static int __t_start(struct pt_regs *reg
 	psostask_t *task;
 
 	handle = __xn_reg_arg1(regs);
-	task = (psostask_t *)xnregistry_fetch(handle);
+	task = thread2psostask((xnthread_t *)xnregistry_fetch(handle));
 
 	if (!task)
 		return ERR_OBJID;
@@ -162,7 +162,7 @@ static int __t_delete(struct pt_regs *re
 	handle = __xn_reg_arg1(regs);
 
 	if (handle)
-		task = (psostask_t *)xnregistry_fetch(handle);
+		task = thread2psostask((xnthread_t *)xnregistry_fetch(handle));
 	else
 		task = __psos_task_current(current);
 
@@ -182,7 +182,7 @@ static int __t_suspend(struct pt_regs *r
 	psostask_t *task;
 
 	if (handle)
-		task = (psostask_t *)xnregistry_fetch(handle);
+		task = thread2psostask((xnthread_t *)xnregistry_fetch(handle));
 	else
 		task = __psos_task_current(current);
 
@@ -202,7 +202,7 @@ static int __t_resume(struct pt_regs *re
 	psostask_t *task;
 
 	if (handle)
-		task = (psostask_t *)xnregistry_fetch(handle);
+		task = thread2psostask((xnthread_t *)xnregistry_fetch(handle));
 	else
 		task = __psos_task_current(current);
 
@@ -284,7 +284,7 @@ static int __t_setpri(struct pt_regs *re
 	psostask_t *task;
 
 	if (handle)
-		task = (psostask_t *)xnregistry_fetch(handle);
+		task = thread2psostask((xnthread_t *)xnregistry_fetch(handle));
 	else
 		task = __psos_task_current(current);
 
@@ -314,7 +314,7 @@ static int __ev_send(struct pt_regs *reg
 	u_long events;
 
 	if (handle)
-		task = (psostask_t *)xnregistry_fetch(handle);
+		task = thread2psostask((xnthread_t *)xnregistry_fetch(handle));
 	else
 		task = __psos_task_current(current);
 
@@ -1317,7 +1317,7 @@ static int __as_send(struct pt_regs *reg
 	psostask_t *task;
 
 	if (handle)
-		task = (psostask_t *)xnregistry_fetch(handle);
+		task = thread2psostask((xnthread_t *)xnregistry_fetch(handle));
 	else
 		task = __psos_task_current(current);
 
ksrc/skins/psos+/task.c +5 -2
Index: b/ksrc/skins/psos+/task.c
===================================================================
@@ -161,8 +161,11 @@ u_long t_create(const char *name,
 
 #ifdef CONFIG_XENO_OPT_REGISTRY
 	{
-		u_long err = xnregistry_enter(task->name,
-					      task, &xnthread_handle(&task->threadbase), NULL);
+		u_long err =
+			xnregistry_enter(task->name,
+					 &task->threadbase,
+					 &xnthread_handle(&task->threadbase),
+					 NULL);
 		if (err) {
 			t_delete((u_long)task);
 			return err;
ksrc/skins/vxworks/syscall.c +15 -13
Index: b/ksrc/skins/vxworks/syscall.c
===================================================================
@@ -146,7 +146,8 @@ out:
 
 static int __wind_task_activate(struct pt_regs *regs)
 {
-	WIND_TCB *pTcb = (WIND_TCB *)xnregistry_fetch(__xn_reg_arg1(regs));
+	WIND_TCB *pTcb = thread2wind_task(
+		(xnthread_t *)xnregistry_fetch(__xn_reg_arg1(regs)));
 
 	if (!pTcb)
 		return S_objLib_OBJ_ID_ERROR;
@@ -167,7 +168,7 @@ static int __wind_task_deleteforce(struc
 	WIND_TCB *pTcb;
 
 	if (handle)
-		pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+		pTcb = thread2wind_task((xnthread_t *)xnregistry_fetch(handle));
 	else
 		pTcb = __wind_task_current(current);
 
@@ -190,7 +191,7 @@ static int __wind_task_delete(struct pt_
 	WIND_TCB *pTcb;
 
 	if (handle)
-		pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+		pTcb = thread2wind_task((xnthread_t *)xnregistry_fetch(handle));
 	else
 		pTcb = __wind_task_current(current);
 
@@ -213,7 +214,7 @@ static int __wind_task_suspend(struct pt
 	WIND_TCB *pTcb;
 
 	if (handle)
-		pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+		pTcb = thread2wind_task((xnthread_t *)xnregistry_fetch(handle));
 	else
 		pTcb = __wind_task_current(current);
 
@@ -232,7 +233,8 @@ 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 = thread2wind_task(
+		(xnthread_t *)xnregistry_fetch(__xn_reg_arg1(regs)));
 
 	if (!pTcb)
 		return S_objLib_OBJ_ID_ERROR;
@@ -275,7 +277,7 @@ static int __wind_task_priorityset(struc
 	WIND_TCB *pTcb;
 
 	if (handle)
-		pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+		pTcb = thread2wind_task((xnthread_t *)xnregistry_fetch(handle));
 	else
 		pTcb = __wind_task_current(current);
 
@@ -299,7 +301,7 @@ static int __wind_task_priorityget(struc
 	int prio;
 
 	if (handle)
-		pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+		pTcb = thread2wind_task((xnthread_t *)xnregistry_fetch(handle));
 	else
 		pTcb = __wind_task_current(current);
 
@@ -374,7 +376,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 = (thread2wind_task((xnthread_t *)xnregistry_fetch(handle)));
 
 	if (!pTcb)
 		return S_objLib_OBJ_ID_ERROR;
@@ -574,7 +576,7 @@ static int __wind_taskinfo_name(struct p
 	const char *name;
 	WIND_TCB *pTcb;
 
-	pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+	pTcb = thread2wind_task((xnthread_t *)xnregistry_fetch(handle));
 
 	if (!pTcb)
 		return S_objLib_OBJ_ID_ERROR;
@@ -618,7 +620,7 @@ static int __wind_taskinfo_status(struct
 
 	xnlock_get_irqsave(&nklock, s);
 
-	pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+	pTcb = thread2wind_task((xnthread_t *)xnregistry_fetch(handle));
 
 	if (!pTcb || pTcb->magic != WIND_TASK_MAGIC) {
 		xnlock_put_irqrestore(&nklock, s);
@@ -643,7 +645,7 @@ static int __wind_taskinfo_get(struct pt
 	WIND_TCB *pTcb;
 	int err;
 
-	pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+	pTcb = thread2wind_task((xnthread_t *)xnregistry_fetch(handle));
 	if (!pTcb)
 		return S_objLib_OBJ_ID_ERROR;
 
@@ -673,7 +675,7 @@ static int __wind_errno_taskset(struct p
  		return 0;
  	}
  
- 	pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ 	pTcb = thread2wind_task((xnthread_t *)xnregistry_fetch(handle));
 	if (!pTcb)
 		return S_objLib_OBJ_ID_ERROR;
 
@@ -696,7 +698,7 @@ static int __wind_errno_taskget(struct p
  	if (!handle)
  		errcode = wind_errnoget();
  	else {
- 		pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ 		pTcb = thread2wind_task((xnthread_t *)xnregistry_fetch(handle));
  		if (!pTcb)
  			return S_objLib_OBJ_ID_ERROR;
  
ksrc/skins/vxworks/taskLib.c +2 -2
Index: b/ksrc/skins/vxworks/taskLib.c
===================================================================
@@ -171,8 +171,8 @@ STATUS taskInit(WIND_TCB *pTcb,
 	xnlock_put_irqrestore(&nklock, s);
 
 #ifdef CONFIG_XENO_OPT_REGISTRY
-	if (xnregistry_enter(pTcb->name,
-			     pTcb, &xnthread_handle(&pTcb->threadbase), NULL)) {
+	if (xnregistry_enter(pTcb->name, &pTcb->threadbase,
+			     &xnthread_handle(&pTcb->threadbase), NULL)) {
 		wind_errnoset(S_objLib_OBJ_ID_ERROR);
 		taskDeleteForce((TASK_ID) pTcb);
 		return ERROR;
author
#2 lore raw

RFC PATCH 2/3 Switch to handle-based fast mutex owners

In reply to Jan Kiszka

To improve robustness of the fast mutex implementation in POSIX (and later on in native), it is better to track the mutex owner by handle instead of kernel object pointer. Therefore, this patch changes __xn_sys_current (xeno_set_current) so that it returns xnthread_handle(current_thread). It furthermore converts the POSIX mutex implementation to pick up and store the lock owner as handle in the kernel/user-shared mutex. Finally it ensures that at least POSIX threads always have an (anonymous) handle assigned.

As the value stored in the mutex variable is now an integer, we can switch over to xnarch_atomic_t, removing all atomic_intptr users.

---
 include/asm-generic/bits/bind.h    |    9 ++++-
 include/asm-generic/bits/current.h |    5 +-
 include/nucleus/types.h            |   13 +++++++
 ksrc/nucleus/shadow.c              |   31 +++++++++++++++--
 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           |   66 +++++++++++++++++++++++++------------
 ksrc/skins/posix/syscall.c         |   11 +++---
 ksrc/skins/posix/thread.c          |    8 ++++
 src/skins/posix/mutex.c            |   27 +++++++--------
 12 files changed, 158 insertions(+), 61 deletions(-)
include/asm-generic/bits/current.h +3 -2
Index: 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 */
include/nucleus/types.h +13 -0
Index: 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);
ksrc/nucleus/shadow.c +28 -3
Index: b/ksrc/nucleus/shadow.c
===================================================================
@@ -52,6 +52,7 @@
 #include <nucleus/trace.h>
 #include <nucleus/stat.h>
 #include <nucleus/sys_ppd.h>
+#include <nucleus/registry.h>
 #include <asm/xenomai/features.h>
 #include <asm/xenomai/syscall.h>
 #include <asm/xenomai/bits/shadow.h>
@@ -1907,13 +1908,35 @@ 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 cur_handle, __user *us_handle;
+	int err = 0;
+	spl_t s;
+
+	xnlock_get_irqsave(&nklock, s);
+
+	cur_handle = xnthread_handle(cur);
+
+	/* We need at least an anonymous registry entry to obtain a handle. */
+	if (!cur_handle) {
+		err = xnregistry_enter("", cur, &xnthread_handle(cur), NULL);
+		cur_handle = xnthread_handle(cur);
+	}
+
+	xnlock_put_irqrestore(&nklock, s);
+
+	if (err)
+		return err;
+
+	us_handle = (xnhandle_t __user *) __xn_reg_arg1(regs);
 
-	return __xn_safe_copy_to_user(us_current, &cur, sizeof(*us_current));
+	return __xn_safe_copy_to_user(us_handle, &cur_handle,
+				      sizeof(*us_handle));
 }
+#endif /* CONFIG_XENO_OPT_REGISTRY */
 
 static xnsysent_t __systab[] = {
 	[__xn_sys_migrate] = {&xnshadow_sys_migrate, __xn_exec_current},
@@ -1924,7 +1947,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)
ksrc/skins/posix/cb_lock.h +11 -4
Index: 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
 
ksrc/skins/posix/cond.c +7 -5
Index: 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. */
ksrc/skins/posix/mutex.c +13 -8
Index: 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)) {
 		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))
+		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;
 	}
ksrc/skins/posix/mutex.h +46 -20

154 lines not on this page · raw message

ksrc/skins/posix/syscall.c +6 -5
Index: 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))
 		return -EBUSY;
 
 	pse51_mark_deleted(shadow);
src/skins/posix/mutex.c +14 -13
Index: 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,7 +149,7 @@ 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)
@@ -163,7 +163,7 @@ int __wrap_pthread_mutex_lock(pthread_mu
 		goto out;
 	}
 
-	owner = xnarch_atomic_intptr_cmpxchg(get_ownerp(shadow), NULL, cur);
+	owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
 	if (likely(!owner)) {
 		shadow->lockcnt = 1;
 		cb_read_unlock(&shadow->lock, s);
@@ -210,7 +210,7 @@ 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)
@@ -224,7 +224,7 @@ int __wrap_pthread_mutex_timedlock(pthre
 		goto out;
 	}	
 
-	owner = xnarch_atomic_intptr_cmpxchg(get_ownerp(shadow), NULL, cur);
+	owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
 	if (likely(!owner)) {
 		shadow->lockcnt = 1;
 		cb_read_unlock(&shadow->lock, s);
@@ -271,7 +271,7 @@ 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)
@@ -285,7 +285,7 @@ int __wrap_pthread_mutex_trylock(pthread
 		goto out;
 	}	
 
-	owner = xnarch_atomic_intptr_cmpxchg(get_ownerp(shadow), NULL, cur);
+	owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
 	if (likely(!owner)) {
 		shadow->lockcnt = 1;
 		cb_read_unlock(&shadow->lock, s);
@@ -325,8 +325,8 @@ 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)
@@ -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;
ksrc/skins/posix/thread.c +8 -0
Index: b/ksrc/skins/posix/thread.c
===================================================================
@@ -28,6 +28,7 @@
  * 
  *@{*/
 
+#include <nucleus/registry.h>
 #include <posix/thread.h>
 #include <posix/cancel.h>
 #include <posix/timer.h>
@@ -229,6 +230,13 @@ int pthread_create(pthread_t *tid,
 	appendq(thread->container, &thread->link);
 	xnlock_put_irqrestore(&nklock, s);
 
+#ifdef CONFIG_XENO_OPT_REGISTRY
+	/* We need an anonymous registry entry to obtain a handle for fast
+	   mutex locking. */
+	xnregistry_enter("", &thread->threadbase,
+			 &xnthread_handle(&thread->threadbase), NULL);
+#endif /* CONFIG_XENO_OPT_REGISTRY */
+
 #ifdef CONFIG_XENO_OPT_PERVASIVE
 	thread->hkey.u_tid = 0;
 	thread->hkey.mm = NULL;
ksrc/skins/posix/Kconfig +1 -0
Index: 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
include/asm-generic/bits/bind.h +8 -1
Index: 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);
 }
 
#3 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 11 lines · Jan Kiszka

To improve robustness of the fast mutex implementation in POSIX (and later on in native), it is better to track the mutex owner by handle instead of kernel object pointer. Therefore, this patch changes __xn_sys_current (xeno_set_current) so that it returns xnthread_handle(current_thread). It furthermore converts the POSIX mutex implementation to pick up and store the lock owner as handle in the kernel/user-shared mutex. Finally it ensures that at least POSIX threads always have an (anonymous) handle assigned.

As the value stored in the mutex variable is now an integer, we can switch over to xnarch_atomic_t, removing all atomic_intptr users.

Ok. I do not know if this should be part of this patch, or in another one, but we should call xeno_set_current in the trampolines of all skins, so that they can use the native and posix mutexes.

This is another thing that I have left in a state of flux...

Signature · 1 line
                                                 Gilles.
author
#4 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 10 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka

To improve robustness of the fast mutex implementation in POSIX (and later on in native), it is better to track the mutex owner by handle instead of kernel object pointer. Therefore, this patch changes __xn_sys_current (xeno_set_current) so that it returns xnthread_handle(current_thread). It furthermore converts the POSIX mutex implementation to pick up and store the lock owner as handle in the kernel/user-shared mutex. Finally it ensures that at least POSIX threads always have an (anonymous) handle assigned.

Quoted 8 lines
Quoted 2 lines

As the value stored in the mutex variable is now an integer, we can switch over to xnarch_atomic_t, removing all atomic_intptr users.

Ok. I do not know if this should be part of this patch, or in another one, but we should call xeno_set_current in the trampolines of all skins, so that they can use the native and posix mutexes.

This is another thing that I have left in a state of flux...

Find it below (PATCH 4/3).

BTW, should we better invoke pthread_exit in xeno_set_current in case of a failure?

Jan

---
 src/skins/native/task.c     |    3 +++
 src/skins/psos+/task.c      |    3 +++
 src/skins/uitron/task.c     |    3 +++
 src/skins/vrtx/task.c       |    3 +++
 src/skins/vxworks/taskLib.c |    3 +++
 5 files changed, 15 insertions(+)
src/skins/native/task.c +3 -0
Index: 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. */
src/skins/psos+/task.c +3 -0
Index: 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. */
src/skins/uitron/task.c +3 -0
Index: 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. */
src/skins/vrtx/task.c +3 -0
Index: 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;
 
@@ -106,6 +107,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. */
src/skins/vxworks/taskLib.c +3 -0
Index: 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. */
#5 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 17 lines · Jan Kiszka
Quoted 16 lines · Gilles Chanteperdrix
Quoted 11 lines · Jan Kiszka

To improve robustness of the fast mutex implementation in POSIX (and later on in native), it is better to track the mutex owner by handle instead of kernel object pointer. Therefore, this patch changes __xn_sys_current (xeno_set_current) so that it returns xnthread_handle(current_thread). It furthermore converts the POSIX mutex implementation to pick up and store the lock owner as handle in the kernel/user-shared mutex. Finally it ensures that at least POSIX threads always have an (anonymous) handle assigned.

As the value stored in the mutex variable is now an integer, we can switch over to xnarch_atomic_t, removing all atomic_intptr users.

Ok. I do not know if this should be part of this patch, or in another one, but we should call xeno_set_current in the trampolines of all skins, so that they can use the native and posix mutexes.

Quoted 6 lines
Quoted 1 line

This is another thing that I have left in a state of flux...

Find it below (PATCH 4/3).

BTW, should we better invoke pthread_exit in xeno_set_current in case of a failure?

I prefer my application to die. This way I would know that something went wrong. And by the way, how could this syscall fail ? I mean if xenomai or the posix skin are not loaded, we would have known it earlier.

Signature · 1 line
                                                 Gilles.
author
#6 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 19 lines · Gilles Chanteperdrix
Quoted 18 lines · Jan Kiszka
Quoted 17 lines · Gilles Chanteperdrix
Quoted 11 lines · Jan Kiszka

To improve robustness of the fast mutex implementation in POSIX (and later on in native), it is better to track the mutex owner by handle instead of kernel object pointer. Therefore, this patch changes __xn_sys_current (xeno_set_current) so that it returns xnthread_handle(current_thread). It furthermore converts the POSIX mutex implementation to pick up and store the lock owner as handle in the kernel/user-shared mutex. Finally it ensures that at least POSIX threads always have an (anonymous) handle assigned.

As the value stored in the mutex variable is now an integer, we can switch over to xnarch_atomic_t, removing all atomic_intptr users.

Ok. I do not know if this should be part of this patch, or in another one, but we should call xeno_set_current in the trampolines of all skins, so that they can use the native and posix mutexes.

This is another thing that I have left in a state of flux...

Quoted 8 lines
Quoted 4 lines

Find it below (PATCH 4/3).

BTW, should we better invoke pthread_exit in xeno_set_current in case of a failure?

I prefer my application to die. This way I would know that something went wrong. And by the way, how could this syscall fail ? I mean if xenomai or the posix skin are not loaded, we would have known it earlier.

So far this syscall can trigger a thread handle registration if the current thread has no handle yet. But that could go away if all skins ensure that there is at least an anonymous handle for their threads after creation.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#7 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 24 lines · Jan Kiszka
Quoted 23 lines · Gilles Chanteperdrix
Quoted 22 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka

To improve robustness of the fast mutex implementation in POSIX (and later on in native), it is better to track the mutex owner by handle instead of kernel object pointer. Therefore, this patch changes __xn_sys_current (xeno_set_current) so that it returns xnthread_handle(current_thread). It furthermore converts the POSIX mutex implementation to pick up and store the lock owner as handle in the kernel/user-shared mutex. Finally it ensures that at least POSIX threads always have an (anonymous) handle assigned.

Quoted 7 lines
Quoted 2 lines

As the value stored in the mutex variable is now an integer, we can switch over to xnarch_atomic_t, removing all atomic_intptr users.

Ok. I do not know if this should be part of this patch, or in another one, but we should call xeno_set_current in the trampolines of all skins, so that they can use the native and posix mutexes.

This is another thing that I have left in a state of flux...

Find it below (PATCH 4/3).

BTW, should we better invoke pthread_exit in xeno_set_current in case of a failure?

Quoted 8 lines
Quoted 3 lines

I prefer my application to die. This way I would know that something went wrong. And by the way, how could this syscall fail ? I mean if xenomai or the posix skin are not loaded, we would have known it earlier.

So far this syscall can trigger a thread handle registration if the current thread has no handle yet. But that could go away if all skins ensure that there is at least an anonymous handle for their threads after creation.

Then it looks redundant with the code that does associate a handle with a new thread in the posix skin.

Signature · 1 line
                                                 Gilles.
#8 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

In reply to Jan Kiszka
Quoted 24 lines · Jan Kiszka
Quoted 23 lines · Gilles Chanteperdrix
Quoted 22 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka

To improve robustness of the fast mutex implementation in POSIX (and later on in native), it is better to track the mutex owner by handle instead of kernel object pointer. Therefore, this patch changes __xn_sys_current (xeno_set_current) so that it returns xnthread_handle(current_thread). It furthermore converts the POSIX mutex implementation to pick up and store the lock owner as handle in the kernel/user-shared mutex. Finally it ensures that at least POSIX threads always have an (anonymous) handle assigned.

Quoted 7 lines
Quoted 2 lines

As the value stored in the mutex variable is now an integer, we can switch over to xnarch_atomic_t, removing all atomic_intptr users.

Ok. I do not know if this should be part of this patch, or in another one, but we should call xeno_set_current in the trampolines of all skins, so that they can use the native and posix mutexes.

This is another thing that I have left in a state of flux...

Find it below (PATCH 4/3).

BTW, should we better invoke pthread_exit in xeno_set_current in case of a failure?

Quoted 8 lines
Quoted 3 lines

I prefer my application to die. This way I would know that something went wrong. And by the way, how could this syscall fail ? I mean if xenomai or the posix skin are not loaded, we would have known it earlier.

So far this syscall can trigger a thread handle registration if the current thread has no handle yet. But that could go away if all skins ensure that there is at least an anonymous handle for their threads after creation.

Yes please rework that and do the registration at thread creation in kernel-space. Since the system call is not called for kernel-space threads, the on-demand registry registration would not work for them, unless.... no, I can not imagine that.

Signature · 1 line
					    Gilles.
#9 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

In reply to Jan Kiszka
Quoted 4 lines · Jan Kiszka
ksrc/skins/posix/cb_lock.h +0 -4
-#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)))

ksrc/skins/posix/cb_lock.h line 21

Quoted 10 lines
ksrc/skins/posix/cb_lock.h +10 -0
+#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; \
+})

I liked doing this with no conditional.

ksrc/skins/posix/cond.c static inline int mutex_save_count(xnthr · line 246

Quoted 3 lines
ksrc/skins/posix/cond.c +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

ksrc/skins/posix/mutex.h static inline int pse51_mutex_timedlock_ · line 172

Quoted 5 lines
ksrc/skins/posix/mutex.h +4 -0
+	/* Consistency check for owner handle - is the object a thread? */
+	if (unlikely(xnthread_handle(owner) != clear_claimed(ownerh))) {
+		err = -EINVAL;
+		goto error;
 	}

What is this ?

Quoted 13 lines

Index: b/ksrc/skins/posix/thread.c
===================================================================

ksrc/skins/posix/thread.c +1 -0
@@ -28,6 +28,7 @@
  * 
  *@{*/
 
+#include <nucleus/registry.h>
 #include <posix/thread.h>
 #include <posix/cancel.h>
 #include <posix/timer.h>

ksrc/skins/posix/thread.c int pthread_create(pthread_t *tid, · line 239

Quoted 10 lines
ksrc/skins/posix/thread.c +7 -0
@@ -229,6 +230,13 @@ int pthread_create(pthread_t *tid,
 	appendq(thread->container, &thread->link);
 	xnlock_put_irqrestore(&nklock, s);
 
+#ifdef CONFIG_XENO_OPT_REGISTRY
+	/* We need an anonymous registry entry to obtain a handle for fast
+	   mutex locking. */
+	xnregistry_enter("", &thread->threadbase,
+			 &xnthread_handle(&thread->threadbase), NULL);
+#endif /* CONFIG_XENO_OPT_REGISTRY */
+

Since we need this for all threads (I want a thread from any skin to be able to use the posix skin mutexes), why doing it in the skin ?

Signature · 1 line
                                                 Gilles.
author
#10 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 18 lines · Gilles Chanteperdrix
Quoted 4 lines · Jan Kiszka
ksrc/skins/posix/cb_lock.h +0 -4
-#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)))

ksrc/skins/posix/cb_lock.h line 21

Quoted 10 lines
ksrc/skins/posix/cb_lock.h +10 -0
+#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; \
+})

I liked doing this with no conditional.

You mean let the caller pass 'bit' as 0 or __CLAIMED_BIT (the latter would require some renaming then, I guess)?

Quoted 7 lines

ksrc/skins/posix/cond.c static inline int mutex_save_count(xnthr · line 246

Quoted 4 lines
ksrc/skins/posix/cond.c +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

OK. Will you fix? I will rebase then.

Quoted 8 lines

ksrc/skins/posix/mutex.h static inline int pse51_mutex_timedlock_ · line 172

Quoted 6 lines
ksrc/skins/posix/mutex.h +4 -0
+	/* Consistency check for owner handle - is the object a thread? */
+	if (unlikely(xnthread_handle(owner) != clear_claimed(ownerh))) {
+		err = -EINVAL;
+		goto error;
 	}

What is this ?

This ensures that we are not dereferences some arbitrary registry object due to a borken handle in the mutex variable: The the object registered on this handle is an xnthread, we will find the very same handle value at the well-known place in the object. Kind of magic for xnthread objects (instead of adding a magic field to them).

Quoted 18 lines
Quoted 18 lines

Index: b/ksrc/skins/posix/thread.c
===================================================================

ksrc/skins/posix/thread.c +1 -0
@@ -28,6 +28,7 @@
  * 
  *@{*/
 
+#include <nucleus/registry.h>
 #include <posix/thread.h>
 #include <posix/cancel.h>
 #include <posix/timer.h>
@@ -229,6 +230,13 @@ int pthread_create(pthread_t *tid,
 	appendq(thread->container, &thread->link);
 	xnlock_put_irqrestore(&nklock, s);
 
Quoted 10 lines

ksrc/skins/posix/thread.c int pthread_create(pthread_t *tid, · line 239

Quoted 7 lines
ksrc/skins/posix/thread.c +7 -0
+#ifdef CONFIG_XENO_OPT_REGISTRY
+	/* We need an anonymous registry entry to obtain a handle for fast
+	   mutex locking. */
+	xnregistry_enter("", &thread->threadbase,
+			 &xnthread_handle(&thread->threadbase), NULL);
+#endif /* CONFIG_XENO_OPT_REGISTRY */
+

Since we need this for all threads (I want a thread from any skin to be able to use the posix skin mutexes), why doing it in the skin ?

Some skins register their threads unconditionally, some based on names, some not at all. The "not at all" case has to be fixed, but we need to respect the other two as well.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#11 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 37 lines · Jan Kiszka
Quoted 17 lines · Gilles Chanteperdrix
Quoted 4 lines · Jan Kiszka
ksrc/skins/posix/cb_lock.h +0 -4
-#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)))

ksrc/skins/posix/cb_lock.h line 21

Quoted 10 lines
ksrc/skins/posix/cb_lock.h +10 -0
+#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; \
+})

I liked doing this with no conditional.

You mean let the caller pass 'bit' as 0 or __CLAIMED_BIT (the latter would require some renaming then, I guess)?

Quoted 5 lines

ksrc/skins/posix/cond.c static inline int mutex_save_count(xnthr · line 246

Quoted 3 lines
ksrc/skins/posix/cond.c +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

OK. Will you fix? I will rebase then.

Quoted 6 lines

ksrc/skins/posix/mutex.h static inline int pse51_mutex_timedlock_ · line 172

Quoted 5 lines
ksrc/skins/posix/mutex.h +4 -0
+	/* Consistency check for owner handle - is the object a thread? */
+	if (unlikely(xnthread_handle(owner) != clear_claimed(ownerh))) {
+		err = -EINVAL;
+		goto error;
 	}

What is this ?

Quoted 5 lines

This ensures that we are not dereferences some arbitrary registry object due to a borken handle in the mutex variable: The the object registered on this handle is an xnthread, we will find the very same handle value at the well-known place in the object. Kind of magic for xnthread objects (instead of adding a magic field to them).

Yes, but the point is: how can the handle be borken ? It looks like a useless check to me.

Signature · 1 line
                                                 Gilles.
author
#12 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 35 lines · Gilles Chanteperdrix
Quoted 34 lines · Jan Kiszka
Quoted 17 lines · Gilles Chanteperdrix
Quoted 4 lines · Jan Kiszka
ksrc/skins/posix/cb_lock.h +0 -4
-#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)))

ksrc/skins/posix/cb_lock.h line 21

Quoted 10 lines
ksrc/skins/posix/cb_lock.h +10 -0
+#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; \
+})

I liked doing this with no conditional.

You mean let the caller pass 'bit' as 0 or __CLAIMED_BIT (the latter would require some renaming then, I guess)?

Quoted 5 lines

ksrc/skins/posix/cond.c static inline int mutex_save_count(xnthr · line 246

Quoted 3 lines
ksrc/skins/posix/cond.c +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

OK. Will you fix? I will rebase then.

Quoted 6 lines

ksrc/skins/posix/mutex.h static inline int pse51_mutex_timedlock_ · line 172

Quoted 5 lines
ksrc/skins/posix/mutex.h +4 -0
+	/* Consistency check for owner handle - is the object a thread? */
+	if (unlikely(xnthread_handle(owner) != clear_claimed(ownerh))) {
+		err = -EINVAL;
+		goto error;
 	}

What is this ?

Quoted 8 lines
Quoted 5 lines

This ensures that we are not dereferences some arbitrary registry object due to a borken handle in the mutex variable: The the object registered on this handle is an xnthread, we will find the very same handle value at the well-known place in the object. Kind of magic for xnthread objects (instead of adding a magic field to them).

Yes, but the point is: how can the handle be borken ? It looks like a useless check to me.

This is user memory. Everything can be borken. And I don't want to create yet another source for user-triggered kernel bugs (including silent ones) like with our heap management structures that are corruptible by userland. That's headache guarantee.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#13 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 41 lines · Jan Kiszka
Quoted 40 lines · Gilles Chanteperdrix
Quoted 39 lines · Jan Kiszka
Quoted 17 lines · Gilles Chanteperdrix
Quoted 4 lines · Jan Kiszka
ksrc/skins/posix/cb_lock.h +0 -4
-#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)))

ksrc/skins/posix/cb_lock.h line 21

Quoted 10 lines
ksrc/skins/posix/cb_lock.h +10 -0
+#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; \
+})

I liked doing this with no conditional.

You mean let the caller pass 'bit' as 0 or __CLAIMED_BIT (the latter would require some renaming then, I guess)?

Quoted 5 lines

ksrc/skins/posix/cond.c static inline int mutex_save_count(xnthr · line 246

Quoted 3 lines
ksrc/skins/posix/cond.c +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

OK. Will you fix? I will rebase then.

Quoted 6 lines

ksrc/skins/posix/mutex.h static inline int pse51_mutex_timedlock_ · line 172

Quoted 5 lines
ksrc/skins/posix/mutex.h +4 -0
+	/* Consistency check for owner handle - is the object a thread? */
+	if (unlikely(xnthread_handle(owner) != clear_claimed(ownerh))) {
+		err = -EINVAL;
+		goto error;
 	}

What is this ?

This ensures that we are not dereferences some arbitrary registry object due to a borken handle in the mutex variable: The the object registered on this handle is an xnthread, we will find the very same handle value at the well-known place in the object. Kind of magic for xnthread objects (instead of adding a magic field to them).

Quoted 7 lines
Quoted 2 lines

Yes, but the point is: how can the handle be borken ? It looks like a useless check to me.

This is user memory. Everything can be borken. And I don't want to create yet another source for user-triggered kernel bugs (including silent ones) like with our heap management structures that are corruptible by userland. That's headache guarantee.

No, we assume that the user application will only clobber our heap if it is broken too. Add this with a XENO_DEBUG option if you want (not XENO_DEBUG(POSIX)).

Signature · 1 line
                                                 Gilles.
author
#14 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 44 lines · Gilles Chanteperdrix
Quoted 43 lines · Jan Kiszka
Quoted 42 lines · Gilles Chanteperdrix
Quoted 34 lines · Jan Kiszka
Quoted 17 lines · Gilles Chanteperdrix
Quoted 4 lines · Jan Kiszka
ksrc/skins/posix/cb_lock.h +0 -4
-#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)))

ksrc/skins/posix/cb_lock.h line 21

Quoted 10 lines
ksrc/skins/posix/cb_lock.h +10 -0
+#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; \
+})

I liked doing this with no conditional.

You mean let the caller pass 'bit' as 0 or __CLAIMED_BIT (the latter would require some renaming then, I guess)?

Quoted 5 lines

ksrc/skins/posix/cond.c static inline int mutex_save_count(xnthr · line 246

Quoted 3 lines
ksrc/skins/posix/cond.c +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

OK. Will you fix? I will rebase then.

Quoted 6 lines

ksrc/skins/posix/mutex.h static inline int pse51_mutex_timedlock_ · line 172

Quoted 5 lines
ksrc/skins/posix/mutex.h +4 -0
+	/* Consistency check for owner handle - is the object a thread? */
+	if (unlikely(xnthread_handle(owner) != clear_claimed(ownerh))) {
+		err = -EINVAL;
+		goto error;
 	}

What is this ?

Quoted 5 lines

This ensures that we are not dereferences some arbitrary registry object due to a borken handle in the mutex variable: The the object registered on this handle is an xnthread, we will find the very same handle value at the well-known place in the object. Kind of magic for xnthread objects (instead of adding a magic field to them).

Yes, but the point is: how can the handle be borken ? It looks like a useless check to me.

Quoted 8 lines
Quoted 4 lines

This is user memory. Everything can be borken. And I don't want to create yet another source for user-triggered kernel bugs (including silent ones) like with our heap management structures that are corruptible by userland. That's headache guarantee.

No, we assume that the user application will only clobber our heap if it is broken too. Add this with a XENO_DEBUG option if you want (not XENO_DEBUG(POSIX)).

No problem for me. This check is almost 100% identical (specifically overhead-wise) to the usual object magic checks after querying the registry, and as those are unconditionally performed, I saw no need to handle this case differently.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#15 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 49 lines · Jan Kiszka
Quoted 48 lines · Gilles Chanteperdrix
Quoted 47 lines · Jan Kiszka
Quoted 35 lines · Gilles Chanteperdrix
Quoted 34 lines · Jan Kiszka
Quoted 17 lines · Gilles Chanteperdrix
Quoted 4 lines · Jan Kiszka
(quoted diff) +0 -4
-#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)))

Review

Quoted 10 lines
(quoted diff) +10 -0
+#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; \
+})

I liked doing this with no conditional.

You mean let the caller pass 'bit' as 0 or __CLAIMED_BIT (the latter would require some renaming then, I guess)?

Quoted 5 lines

Review

Quoted 3 lines
(quoted diff) +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

OK. Will you fix? I will rebase then.

Quoted 6 lines

Review

Quoted 5 lines
(quoted diff) +4 -0
+	/* Consistency check for owner handle - is the object a thread? */
+	if (unlikely(xnthread_handle(owner) != clear_claimed(ownerh))) {
+		err = -EINVAL;
+		goto error;
 	}

What is this ?

Quoted 7 lines
Quoted 5 lines

This ensures that we are not dereferences some arbitrary registry object due to a borken handle in the mutex variable: The the object registered on this handle is an xnthread, we will find the very same handle value at the well-known place in the object. Kind of magic for xnthread objects (instead of adding a magic field to them).

Yes, but the point is: how can the handle be borken ? It looks like a useless check to me.

This is user memory. Everything can be borken. And I don't want to create yet another source for user-triggered kernel bugs (including silent ones) like with our heap management structures that are corruptible by userland. That's headache guarantee.

Quoted 8 lines
Quoted 3 lines

No, we assume that the user application will only clobber our heap if it is broken too. Add this with a XENO_DEBUG option if you want (not XENO_DEBUG(POSIX)).

No problem for me. This check is almost 100% identical (specifically overhead-wise) to the usual object magic checks after querying the registry, and as those are unconditionally performed, I saw no need to handle this case differently.

But the registry lookup is already a validation in itself. I mean, if an application uses 5 as a file descriptor, there are only two cases:
- the file descriptor 5 exists in the application and the kernel has no other choice than to believe that the application is using this file descriptor, and nothing will go wrong because this is a valid descriptor;
- the file descriptor does not exist, and we will return EBADF, and nothing wrong will happen either...

Signature · 1 line
                                                 Gilles.
author
#16 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 58 lines · Gilles Chanteperdrix
Quoted 49 lines · Jan Kiszka
Quoted 48 lines · Gilles Chanteperdrix
Quoted 47 lines · Jan Kiszka
Quoted 35 lines · Gilles Chanteperdrix
Quoted 34 lines · Jan Kiszka
Quoted 17 lines · Gilles Chanteperdrix
Quoted 4 lines · Jan Kiszka
(quoted diff) +0 -4
-#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)))

Review

Quoted 10 lines
(quoted diff) +10 -0
+#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; \
+})

I liked doing this with no conditional.

You mean let the caller pass 'bit' as 0 or __CLAIMED_BIT (the latter would require some renaming then, I guess)?

Quoted 5 lines

Review

Quoted 3 lines
(quoted diff) +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

OK. Will you fix? I will rebase then.

Quoted 6 lines

Review

Quoted 5 lines
(quoted diff) +4 -0
+	/* Consistency check for owner handle - is the object a thread? */
+	if (unlikely(xnthread_handle(owner) != clear_claimed(ownerh))) {
+		err = -EINVAL;
+		goto error;
 	}

What is this ?

Quoted 7 lines
Quoted 5 lines

This ensures that we are not dereferences some arbitrary registry object due to a borken handle in the mutex variable: The the object registered on this handle is an xnthread, we will find the very same handle value at the well-known place in the object. Kind of magic for xnthread objects (instead of adding a magic field to them).

Yes, but the point is: how can the handle be borken ? It looks like a useless check to me.

This is user memory. Everything can be borken. And I don't want to create yet another source for user-triggered kernel bugs (including silent ones) like with our heap management structures that are corruptible by userland. That's headache guarantee.

Quoted 7 lines
Quoted 3 lines

No, we assume that the user application will only clobber our heap if it is broken too. Add this with a XENO_DEBUG option if you want (not XENO_DEBUG(POSIX)).

No problem for me. This check is almost 100% identical (specifically overhead-wise) to the usual object magic checks after querying the registry, and as those are unconditionally performed, I saw no need to handle this case differently.

Quoted 7 lines

But the registry lookup is already a validation in itself. I mean, if an application uses 5 as a file descriptor, there are only two cases:
- the file descriptor 5 exists in the application and the kernel has no other choice than to believe that the application is using this file descriptor, and nothing will go wrong because this is a valid descriptor;
- the file descriptor does not exist, and we will return EBADF, and nothing wrong will happen either...

File descriptors are all identically structured objects, so at worst you ruin some other app's day. But the registry contains arbitrary objects with different internal layout. If you start assuming object_a * is object_b * and use the pointer etc. included in a as if they have the meaning of b, you quickly ruin the kernel's day as well. Therefore, native, e.g., does magic checks after fetching from the registry. As I said, this test here works differently, but it has the same effect and impact.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#17 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 66 lines · Jan Kiszka
Quoted 57 lines · Gilles Chanteperdrix
Quoted 49 lines · Jan Kiszka
Quoted 48 lines · Gilles Chanteperdrix
Quoted 47 lines · Jan Kiszka
Quoted 35 lines · Gilles Chanteperdrix
Quoted 34 lines · Jan Kiszka
Quoted 17 lines · Gilles Chanteperdrix
Quoted 4 lines · Jan Kiszka
(quoted diff) +0 -4
-#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)))

Review

Quoted 10 lines
(quoted diff) +10 -0
+#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; \
+})

I liked doing this with no conditional.

You mean let the caller pass 'bit' as 0 or __CLAIMED_BIT (the latter would require some renaming then, I guess)?

Quoted 5 lines

Review

Quoted 3 lines
(quoted diff) +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

OK. Will you fix? I will rebase then.

Quoted 6 lines

Review

Quoted 5 lines
(quoted diff) +4 -0
+	/* Consistency check for owner handle - is the object a thread? */
+	if (unlikely(xnthread_handle(owner) != clear_claimed(ownerh))) {
+		err = -EINVAL;
+		goto error;
 	}

What is this ?

Quoted 7 lines
Quoted 5 lines

This ensures that we are not dereferences some arbitrary registry object due to a borken handle in the mutex variable: The the object registered on this handle is an xnthread, we will find the very same handle value at the well-known place in the object. Kind of magic for xnthread objects (instead of adding a magic field to them).

Yes, but the point is: how can the handle be borken ? It looks like a useless check to me.

This is user memory. Everything can be borken. And I don't want to create yet another source for user-triggered kernel bugs (including silent ones) like with our heap management structures that are corruptible by userland. That's headache guarantee.

Quoted 7 lines
Quoted 3 lines

No, we assume that the user application will only clobber our heap if it is broken too. Add this with a XENO_DEBUG option if you want (not XENO_DEBUG(POSIX)).

No problem for me. This check is almost 100% identical (specifically overhead-wise) to the usual object magic checks after querying the registry, and as those are unconditionally performed, I saw no need to handle this case differently.

Quoted 7 lines

But the registry lookup is already a validation in itself. I mean, if an application uses 5 as a file descriptor, there are only two cases:
- the file descriptor 5 exists in the application and the kernel has no other choice than to believe that the application is using this file descriptor, and nothing will go wrong because this is a valid descriptor;
- the file descriptor does not exist, and we will return EBADF, and nothing wrong will happen either...

Quoted 8 lines

File descriptors are all identically structured objects, so at worst you ruin some other app's day. But the registry contains arbitrary objects with different internal layout. If you start assuming object_a * is object_b * and use the pointer etc. included in a as if they have the meaning of b, you quickly ruin the kernel's day as well. Therefore, native, e.g., does magic checks after fetching from the registry. As I said, this test here works differently, but it has the same effect and impact.

Ok. Got it. Leave the check then.

Signature · 1 line
                                                 Gilles.
#18 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

In reply to Jan Kiszka
Quoted 8 lines · Jan Kiszka

File descriptors are all identically structured objects, so at worst you ruin some other app's day. But the registry contains arbitrary objects with different internal layout. If you start assuming object_a * is object_b * and use the pointer etc. included in a as if they have the meaning of b, you quickly ruin the kernel's day as well. Therefore, native, e.g., does magic checks after fetching from the registry. As I said, this test here works differently, but it has the same effect and impact.

By the way, would not it make sense to have separate hash tables for separate objects types ? I mean then we would not need any validation, and several object types could use the same name.

Signature · 1 line
                                                 Gilles.
author
#19 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 10 lines · Gilles Chanteperdrix
Quoted 8 lines · Jan Kiszka

File descriptors are all identically structured objects, so at worst you ruin some other app's day. But the registry contains arbitrary objects with different internal layout. If you start assuming object_a * is object_b * and use the pointer etc. included in a as if they have the meaning of b, you quickly ruin the kernel's day as well. Therefore, native, e.g., does magic checks after fetching from the registry. As I said, this test here works differently, but it has the same effect and impact.

Quoted 5 lines

By the way, would not it make sense to have separate hash tables for separate objects types ? I mean then we would not need any validation, and several object types could use the same name.

From that POV a good idea. The only issue I see is a management problem:

How many mutex, thread, queue, whatever slots do you want in your system? One knob for them all? Or countless knobs for all object types of all skins? That's hairy, I'm afraid.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#20 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 10 lines · Jan Kiszka
Quoted 9 lines · Gilles Chanteperdrix
Quoted 8 lines · Jan Kiszka

File descriptors are all identically structured objects, so at worst you ruin some other app's day. But the registry contains arbitrary objects with different internal layout. If you start assuming object_a * is object_b * and use the pointer etc. included in a as if they have the meaning of b, you quickly ruin the kernel's day as well. Therefore, native, e.g., does magic checks after fetching from the registry. As I said, this test here works differently, but it has the same effect and impact.

Quoted 8 lines
Quoted 3 lines

By the way, would not it make sense to have separate hash tables for separate objects types ? I mean then we would not need any validation, and several object types could use the same name.

From that POV a good idea. The only issue I see is a management problem:
How many mutex, thread, queue, whatever slots do you want in your system? One knob for them all? Or countless knobs for all object types of all skins? That's hairy, I'm afraid.

xnmalloc, the pool size is the limit.

Signature · 1 line
                                                 Gilles.
author
#21 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 14 lines · Gilles Chanteperdrix
Quoted 13 lines · Jan Kiszka
Quoted 12 lines · Gilles Chanteperdrix
Quoted 8 lines · Jan Kiszka

File descriptors are all identically structured objects, so at worst you ruin some other app's day. But the registry contains arbitrary objects with different internal layout. If you start assuming object_a * is object_b * and use the pointer etc. included in a as if they have the meaning of b, you quickly ruin the kernel's day as well. Therefore, native, e.g., does magic checks after fetching from the registry. As I said, this test here works differently, but it has the same effect and impact.

By the way, would not it make sense to have separate hash tables for separate objects types ? I mean then we would not need any validation, and several object types could use the same name.

Quoted 6 lines
Quoted 4 lines

From that POV a good idea. The only issue I see is a management problem:
How many mutex, thread, queue, whatever slots do you want in your system? One knob for them all? Or countless knobs for all object types of all skins? That's hairy, I'm afraid.

xnmalloc, the pool size is the limit.

You mean kind of "xnrealloc", including atomically copying potentially large descriptor tables over? Sounds not that attractive.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#22 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 15 lines · Jan Kiszka
Quoted 14 lines · Gilles Chanteperdrix
Quoted 13 lines · Jan Kiszka
Quoted 12 lines · Gilles Chanteperdrix
Quoted 8 lines · Jan Kiszka

File descriptors are all identically structured objects, so at worst you ruin some other app's day. But the registry contains arbitrary objects with different internal layout. If you start assuming object_a * is object_b * and use the pointer etc. included in a as if they have the meaning of b, you quickly ruin the kernel's day as well. Therefore, native, e.g., does magic checks after fetching from the registry. As I said, this test here works differently, but it has the same effect and impact.

By the way, would not it make sense to have separate hash tables for separate objects types ? I mean then we would not need any validation, and several object types could use the same name.

Quoted 8 lines
Quoted 5 lines
Quoted 4 lines

From that POV a good idea. The only issue I see is a management problem:
How many mutex, thread, queue, whatever slots do you want in your system? One knob for them all? Or countless knobs for all object types of all skins? That's hairy, I'm afraid.

xnmalloc, the pool size is the limit.

You mean kind of "xnrealloc", including atomically copying potentially large descriptor tables over? Sounds not that attractive.

No, I mean the hash table contains pointers, and the objects are allocated dynamically...

Signature · 1 line
                                                 Gilles.
author
#23 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 20 lines · Gilles Chanteperdrix
Quoted 19 lines · Jan Kiszka
Quoted 18 lines · Gilles Chanteperdrix
Quoted 17 lines · Jan Kiszka
Quoted 9 lines · Gilles Chanteperdrix
Quoted 8 lines · Jan Kiszka

File descriptors are all identically structured objects, so at worst you ruin some other app's day. But the registry contains arbitrary objects with different internal layout. If you start assuming object_a * is object_b * and use the pointer etc. included in a as if they have the meaning of b, you quickly ruin the kernel's day as well. Therefore, native, e.g., does magic checks after fetching from the registry. As I said, this test here works differently, but it has the same effect and impact.

Quoted 3 lines

By the way, would not it make sense to have separate hash tables for separate objects types ? I mean then we would not need any validation, and several object types could use the same name.

From that POV a good idea. The only issue I see is a management problem:
How many mutex, thread, queue, whatever slots do you want in your system? One knob for them all? Or countless knobs for all object types of all skins? That's hairy, I'm afraid.

Quoted 6 lines
Quoted 3 lines
Quoted 1 line

xnmalloc, the pool size is the limit.

You mean kind of "xnrealloc", including atomically copying potentially large descriptor tables over? Sounds not that attractive.

No, I mean the hash table contains pointers, and the objects are allocated dynamically...

Handle lookup is not going through hash tables. It's index based (like file descriptors).

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#24 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 21 lines · Jan Kiszka
Quoted 20 lines · Gilles Chanteperdrix
Quoted 19 lines · Jan Kiszka
Quoted 18 lines · Gilles Chanteperdrix
Quoted 17 lines · Jan Kiszka
Quoted 9 lines · Gilles Chanteperdrix
Quoted 8 lines · Jan Kiszka

File descriptors are all identically structured objects, so at worst you ruin some other app's day. But the registry contains arbitrary objects with different internal layout. If you start assuming object_a * is object_b * and use the pointer etc. included in a as if they have the meaning of b, you quickly ruin the kernel's day as well. Therefore, native, e.g., does magic checks after fetching from the registry. As I said, this test here works differently, but it has the same effect and impact.

Quoted 3 lines

By the way, would not it make sense to have separate hash tables for separate objects types ? I mean then we would not need any validation, and several object types could use the same name.

From that POV a good idea. The only issue I see is a management problem:
How many mutex, thread, queue, whatever slots do you want in your system? One knob for them all? Or countless knobs for all object types of all skins? That's hairy, I'm afraid.

Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

xnmalloc, the pool size is the limit.

You mean kind of "xnrealloc", including atomically copying potentially large descriptor tables over? Sounds not that attractive.

No, I mean the hash table contains pointers, and the objects are allocated dynamically...

Handle lookup is not going through hash tables. It's index based (like file descriptors).

Ok, but using hash tables instead of static tables allow you to have more objects in the hash than hash buckets, and a "registry slot" occupies simply a bit in a multi-level bitfield when free, so you can have preposterous registry slots limits like 2048 or 4096.

Signature · 1 line
					    Gilles.
#25 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

In reply to Jan Kiszka
Quoted 70 lines · Jan Kiszka
Quoted 17 lines · Gilles Chanteperdrix
Quoted 4 lines · Jan Kiszka
ksrc/skins/posix/cb_lock.h +0 -4
-#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)))

ksrc/skins/posix/cb_lock.h line 21

Quoted 10 lines
ksrc/skins/posix/cb_lock.h +10 -0
+#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; \
+})

I liked doing this with no conditional.

You mean let the caller pass 'bit' as 0 or __CLAIMED_BIT (the latter would require some renaming then, I guess)?

Quoted 5 lines

ksrc/skins/posix/cond.c static inline int mutex_save_count(xnthr · line 246

Quoted 3 lines
ksrc/skins/posix/cond.c +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

OK. Will you fix? I will rebase then.

Quoted 6 lines

ksrc/skins/posix/mutex.h static inline int pse51_mutex_timedlock_ · line 172

Quoted 5 lines
ksrc/skins/posix/mutex.h +4 -0
+	/* Consistency check for owner handle - is the object a thread? */
+	if (unlikely(xnthread_handle(owner) != clear_claimed(ownerh))) {
+		err = -EINVAL;
+		goto error;
 	}

What is this ?

This ensures that we are not dereferences some arbitrary registry object due to a borken handle in the mutex variable: The the object registered on this handle is an xnthread, we will find the very same handle value at the well-known place in the object. Kind of magic for xnthread objects (instead of adding a magic field to them).

Quoted 17 lines
Quoted 17 lines

Index: b/ksrc/skins/posix/thread.c
===================================================================

ksrc/skins/posix/thread.c +1 -0
@@ -28,6 +28,7 @@
  * 
  *@{*/
 
+#include <nucleus/registry.h>
 #include <posix/thread.h>
 #include <posix/cancel.h>
 #include <posix/timer.h>
@@ -229,6 +230,13 @@ int pthread_create(pthread_t *tid,
 	appendq(thread->container, &thread->link);
 	xnlock_put_irqrestore(&nklock, s);
 
Quoted 9 lines

ksrc/skins/posix/thread.c int pthread_create(pthread_t *tid, · line 239

Quoted 7 lines
ksrc/skins/posix/thread.c +7 -0
+#ifdef CONFIG_XENO_OPT_REGISTRY
+	/* We need an anonymous registry entry to obtain a handle for fast
+	   mutex locking. */
+	xnregistry_enter("", &thread->threadbase,
+			 &xnthread_handle(&thread->threadbase), NULL);
+#endif /* CONFIG_XENO_OPT_REGISTRY */
+

Since we need this for all threads (I want a thread from any skin to be able to use the posix skin mutexes), why doing it in the skin ?

Quoted 3 lines

Some skins register their threads unconditionally, some based on names, some not at all. The "not at all" case has to be fixed, but we need to respect the other two as well.

Ok. But we need to add the register in all skins then.

Signature · 1 line
                                                 Gilles.
#26 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

In reply to Jan Kiszka
Quoted 19 lines · Jan Kiszka
Quoted 17 lines · Gilles Chanteperdrix
Quoted 4 lines · Jan Kiszka
ksrc/skins/posix/cb_lock.h +0 -4
-#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)))

ksrc/skins/posix/cb_lock.h line 21

Quoted 10 lines
ksrc/skins/posix/cb_lock.h +10 -0
+#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; \
+})

I liked doing this with no conditional.

Quoted 2 lines

You mean let the caller pass 'bit' as 0 or __CLAIMED_BIT (the latter would require some renaming then, I guess)?

the if is ok. I guess the compiler does !! with an if too...

Signature · 1 line
                                                 Gilles.
author
#27 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

In reply to Gilles Chanteperdrix
Quoted 7 lines · Gilles Chanteperdrix

ksrc/skins/posix/cond.c static inline int mutex_save_count(xnthr · line 246

Quoted 3 lines · Jan Kiszka
ksrc/skins/posix/cond.c +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

BTW, why do you need to track sleepers separately in POSIX? Native doesn't do so, e.g.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#28 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 10 lines · Jan Kiszka
Quoted 6 lines · Gilles Chanteperdrix

ksrc/skins/posix/cond.c static inline int mutex_save_count(xnthr · line 246

Quoted 3 lines · Jan Kiszka
ksrc/skins/posix/cond.c +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

BTW, why do you need to track sleepers separately in POSIX? Native doesn't do so, e.g.

Because of the "syscall-needed-when-unlocking-stolen-mutex" issue I already explained (sleepers - xnsynch_nsleepers is precisely the count of pending threads which have been awake then robbed the mutex).

Signature · 1 line
                                                 Gilles.
author
#29 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 8 lines · Gilles Chanteperdrix
Quoted 7 lines · Jan Kiszka
Quoted 6 lines · Gilles Chanteperdrix

ksrc/skins/posix/cond.c static inline int mutex_save_count(xnthr · line 246

Quoted 3 lines · Jan Kiszka
ksrc/skins/posix/cond.c +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

Quoted 6 lines
Quoted 2 lines

BTW, why do you need to track sleepers separately in POSIX? Native doesn't do so, e.g.

Because of the "syscall-needed-when-unlocking-stolen-mutex" issue I already explained (sleepers - xnsynch_nsleepers is precisely the count of pending threads which have been awake then robbed the mutex).

Hmm, sounds like the new lock owner should better clear the 'claimed' bit then, not the old one on return from unlock. Or where is the pitfall? How does the futex algorithm handle this scenario?

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#30 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 11 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka
Quoted 6 lines · Gilles Chanteperdrix

ksrc/skins/posix/cond.c static inline int mutex_save_count(xnthr · line 246

Quoted 3 lines · Jan Kiszka
ksrc/skins/posix/cond.c +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

BTW, why do you need to track sleepers separately in POSIX? Native doesn't do so, e.g.

Quoted 7 lines
Quoted 3 lines

Because of the "syscall-needed-when-unlocking-stolen-mutex" issue I already explained (sleepers - xnsynch_nsleepers is precisely the count of pending threads which have been awake then robbed the mutex).

Hmm, sounds like the new lock owner should better clear the 'claimed' bit then, not the old one on return from unlock. Or where is the pitfall? How does the futex algorithm handle this scenario?

Ok. Please read my explanation again, I have already explained this in another mail.

Signature · 1 line
                                                 Gilles.
author
#31 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 15 lines · Gilles Chanteperdrix
Quoted 14 lines · Jan Kiszka
Quoted 13 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka
Quoted 6 lines · Gilles Chanteperdrix

ksrc/skins/posix/cond.c static inline int mutex_save_count(xnthr · line 246

Quoted 3 lines · Jan Kiszka
ksrc/skins/posix/cond.c +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

BTW, why do you need to track sleepers separately in POSIX? Native doesn't do so, e.g.

Because of the "syscall-needed-when-unlocking-stolen-mutex" issue I already explained (sleepers - xnsynch_nsleepers is precisely the count of pending threads which have been awake then robbed the mutex).

Quoted 6 lines
Quoted 3 lines

Hmm, sounds like the new lock owner should better clear the 'claimed' bit then, not the old one on return from unlock. Or where is the pitfall? How does the futex algorithm handle this scenario?

Ok. Please read my explanation again, I have already explained this in another mail.

I did this, but I'm unable to derive the answer for my question from it. Let's go through it in more details:

When we pass a mutex to a new owner, we set its reference in the fast lock variable + set the claimed bit if there are more waiters. Instead, I would simple set that bit if there is a new owner. That owner will then pick up the mutex eventually and clear 'claimed' on exit from it lock service (if there are no further waiters then). If the new owner is not able to run and we steal the lock, we simple keep the 'claimed' bit as is. On exit from the stolen lock we find it set, thus we are forced to issue a syscall as it should be.

OK, what happens if some waiter wants to leave the party while we are holding the stolen lock? Then the sleeper number must be correct - that is one pitfall!

I will have to dig into this more deeply, considering more cases. But the additional "sleepers" field remains at least misplaced IMHO. xnsynch_sleepers should better be fixed to respect lock stealing, as lock stealing is an xnsynch property, nothing POSIX-specific.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#32 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 34 lines · Jan Kiszka
Quoted 12 lines · Gilles Chanteperdrix
Quoted 11 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka
Quoted 6 lines · Gilles Chanteperdrix

Review

Quoted 3 lines · Jan Kiszka
(quoted diff) +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

BTW, why do you need to track sleepers separately in POSIX? Native doesn't do so, e.g.

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

Because of the "syscall-needed-when-unlocking-stolen-mutex" issue I already explained (sleepers - xnsynch_nsleepers is precisely the count of pending threads which have been awake then robbed the mutex).

Hmm, sounds like the new lock owner should better clear the 'claimed' bit then, not the old one on return from unlock. Or where is the pitfall? How does the futex algorithm handle this scenario?

Ok. Please read my explanation again, I have already explained this in another mail.

I did this, but I'm unable to derive the answer for my question from it. Let's go through it in more details:

When we pass a mutex to a new owner, we set its reference in the fast lock variable + set the claimed bit if there are more waiters. Instead, I would simple set that bit if there is a new owner. That owner will then pick up the mutex eventually and clear 'claimed' on exit from it lock service (if there are no further waiters then). If the new owner is not able to run and we steal the lock, we simple keep the 'claimed' bit as is. On exit from the stolen lock we find it set, thus we are forced to issue a syscall as it should be.

Quoted 8 lines

OK, what happens if some waiter wants to leave the party while we are holding the stolen lock? Then the sleeper number must be correct - that is one pitfall!

I will have to dig into this more deeply, considering more cases. But the additional "sleepers" field remains at least misplaced IMHO. xnsynch_sleepers should better be fixed to respect lock stealing, as lock stealing is an xnsynch property, nothing POSIX-specific.

Ok. I have read this but did not get what you mean. I will read it again
quietly from home.

Signature · 1 line
                                                 Gilles.
author
#33 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 38 lines · Gilles Chanteperdrix
Quoted 37 lines · Jan Kiszka
Quoted 12 lines · Gilles Chanteperdrix
Quoted 11 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka
Quoted 6 lines · Gilles Chanteperdrix

Review

Quoted 3 lines · Jan Kiszka
(quoted diff) +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

BTW, why do you need to track sleepers separately in POSIX? Native doesn't do so, e.g.

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

Because of the "syscall-needed-when-unlocking-stolen-mutex" issue I already explained (sleepers - xnsynch_nsleepers is precisely the count of pending threads which have been awake then robbed the mutex).

Hmm, sounds like the new lock owner should better clear the 'claimed' bit then, not the old one on return from unlock. Or where is the pitfall? How does the futex algorithm handle this scenario?

Ok. Please read my explanation again, I have already explained this in another mail.

I did this, but I'm unable to derive the answer for my question from it. Let's go through it in more details:

When we pass a mutex to a new owner, we set its reference in the fast lock variable + set the claimed bit if there are more waiters. Instead, I would simple set that bit if there is a new owner. That owner will then pick up the mutex eventually and clear 'claimed' on exit from it lock service (if there are no further waiters then). If the new owner is not able to run and we steal the lock, we simple keep the 'claimed' bit as is. On exit from the stolen lock we find it set, thus we are forced to issue a syscall as it should be.

OK, what happens if some waiter wants to leave the party while we are holding the stolen lock? Then the sleeper number must be correct - that is one pitfall!

Quoted 7 lines
Quoted 4 lines

I will have to dig into this more deeply, considering more cases. But the additional "sleepers" field remains at least misplaced IMHO. xnsynch_sleepers should better be fixed to respect lock stealing, as lock stealing is an xnsynch property, nothing POSIX-specific.

Ok. I have read this but did not get what you mean. I will read it again
quietly from home.

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

Jan

#34 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 61 lines · Jan Kiszka
Quoted 38 lines · Gilles Chanteperdrix
Quoted 37 lines · Jan Kiszka
Quoted 12 lines · Gilles Chanteperdrix
Quoted 11 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka
Quoted 6 lines · Gilles Chanteperdrix

Review

Quoted 3 lines · Jan Kiszka
(quoted diff) +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

BTW, why do you need to track sleepers separately in POSIX? Native doesn't do so, e.g.

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

Because of the "syscall-needed-when-unlocking-stolen-mutex" issue I already explained (sleepers - xnsynch_nsleepers is precisely the count of pending threads which have been awake then robbed the mutex).

Hmm, sounds like the new lock owner should better clear the 'claimed' bit then, not the old one on return from unlock. Or where is the pitfall? How does the futex algorithm handle this scenario?

Ok. Please read my explanation again, I have already explained this in another mail.

I did this, but I'm unable to derive the answer for my question from it. Let's go through it in more details:

When we pass a mutex to a new owner, we set its reference in the fast lock variable + set the claimed bit if there are more waiters. Instead, I would simple set that bit if there is a new owner. That owner will then pick up the mutex eventually and clear 'claimed' on exit from it lock service (if there are no further waiters then). If the new owner is not able to run and we steal the lock, we simple keep the 'claimed' bit as is. On exit from the stolen lock we find it set, thus we are forced to issue a syscall as it should be.

OK, what happens if some waiter wants to leave the party while we are holding the stolen lock? Then the sleeper number must be correct - that is one pitfall!

Quoted 6 lines
Quoted 4 lines

I will have to dig into this more deeply, considering more cases. But the additional "sleepers" field remains at least misplaced IMHO. xnsynch_sleepers should better be fixed to respect lock stealing, as lock stealing is an xnsynch property, nothing POSIX-specific.

Ok. I have read this but did not get what you mean. I will read it again
quietly from home.

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 5 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

Signature · 1 line
					    Gilles.
#35 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 80 lines · Gilles Chanteperdrix
Quoted 60 lines · Jan Kiszka
Quoted 38 lines · Gilles Chanteperdrix
Quoted 37 lines · Jan Kiszka
Quoted 12 lines · Gilles Chanteperdrix
Quoted 11 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka
Quoted 6 lines · Gilles Chanteperdrix

Review

Quoted 3 lines · Jan Kiszka
(quoted diff) +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

BTW, why do you need to track sleepers separately in POSIX? Native doesn't do so, e.g.

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

Because of the "syscall-needed-when-unlocking-stolen-mutex" issue I already explained (sleepers - xnsynch_nsleepers is precisely the count of pending threads which have been awake then robbed the mutex).

Hmm, sounds like the new lock owner should better clear the 'claimed' bit then, not the old one on return from unlock. Or where is the pitfall? How does the futex algorithm handle this scenario?

Ok. Please read my explanation again, I have already explained this in another mail.

I did this, but I'm unable to derive the answer for my question from it. Let's go through it in more details:

When we pass a mutex to a new owner, we set its reference in the fast lock variable + set the claimed bit if there are more waiters. Instead, I would simple set that bit if there is a new owner. That owner will then pick up the mutex eventually and clear 'claimed' on exit from it lock service (if there are no further waiters then). If the new owner is not able to run and we steal the lock, we simple keep the 'claimed' bit as is. On exit from the stolen lock we find it set, thus we are forced to issue a syscall as it should be.

OK, what happens if some waiter wants to leave the party while we are holding the stolen lock? Then the sleeper number must be correct - that is one pitfall!

Quoted 6 lines
Quoted 4 lines

I will have to dig into this more deeply, considering more cases. But the additional "sleepers" field remains at least misplaced IMHO. xnsynch_sleepers should better be fixed to respect lock stealing, as lock stealing is an xnsynch property, nothing POSIX-specific.

Ok. I have read this but did not get what you mean. I will read it again
quietly from home.

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

By the way, I think we should stop sending mails to our personal addresses in addition to the mailing list, because this results in mailing list mails being received out of orders, which make the threads hard to follow.

Signature · 1 line
					    Gilles.
author
#36 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 79 lines · Gilles Chanteperdrix
Quoted 78 lines · Gilles Chanteperdrix
Quoted 60 lines · Jan Kiszka
Quoted 38 lines · Gilles Chanteperdrix
Quoted 37 lines · Jan Kiszka
Quoted 12 lines · Gilles Chanteperdrix
Quoted 11 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka
Quoted 6 lines · Gilles Chanteperdrix

Review

Quoted 3 lines · Jan Kiszka
(quoted diff) +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

BTW, why do you need to track sleepers separately in POSIX? Native doesn't do so, e.g.

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

Because of the "syscall-needed-when-unlocking-stolen-mutex" issue I already explained (sleepers - xnsynch_nsleepers is precisely the count of pending threads which have been awake then robbed the mutex).

Hmm, sounds like the new lock owner should better clear the 'claimed' bit then, not the old one on return from unlock. Or where is the pitfall? How does the futex algorithm handle this scenario?

Ok. Please read my explanation again, I have already explained this in another mail.

I did this, but I'm unable to derive the answer for my question from it. Let's go through it in more details:

When we pass a mutex to a new owner, we set its reference in the fast lock variable + set the claimed bit if there are more waiters. Instead, I would simple set that bit if there is a new owner. That owner will then pick up the mutex eventually and clear 'claimed' on exit from it lock service (if there are no further waiters then). If the new owner is not able to run and we steal the lock, we simple keep the 'claimed' bit as is. On exit from the stolen lock we find it set, thus we are forced to issue a syscall as it should be.

OK, what happens if some waiter wants to leave the party while we are holding the stolen lock? Then the sleeper number must be correct - that is one pitfall!

Quoted 6 lines
Quoted 4 lines

I will have to dig into this more deeply, considering more cases. But the additional "sleepers" field remains at least misplaced IMHO. xnsynch_sleepers should better be fixed to respect lock stealing, as lock stealing is an xnsynch property, nothing POSIX-specific.

Ok. I have read this but did not get what you mean. I will read it again
quietly from home.

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 7 lines
Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

By the way, I think we should stop sending mails to our personal addresses in addition to the mailing list, because this results in mailing list mails being received out of orders, which make the threads hard to follow.

That's common practice on most mailing lists I know of, and I personally don't want to change this. IMO, it would only make replying more complicated, and it would bear the risk to drop CCs to non-subscribers.

I think the problem was only temporarily, maybe caused by some weird interaction of gna.org and the Siemens mailserver (we were too fast for them). Meanwhile, archives and inboxes should contain all messages. Gmane, e.g., lists them in the correct order now.

Jan

#37 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 87 lines · Jan Kiszka
Quoted 79 lines · Gilles Chanteperdrix
Quoted 78 lines · Gilles Chanteperdrix
Quoted 60 lines · Jan Kiszka
Quoted 38 lines · Gilles Chanteperdrix
Quoted 37 lines · Jan Kiszka
Quoted 12 lines · Gilles Chanteperdrix
Quoted 11 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka
Quoted 6 lines · Gilles Chanteperdrix

Review

Quoted 3 lines · Jan Kiszka
(quoted diff) +3 -0
+	xnarch_atomic_set(mutex->owner,
+		 	  set_claimed(xnthread_handle(owner),
+				      xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

BTW, why do you need to track sleepers separately in POSIX? Native doesn't do so, e.g.

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

Because of the "syscall-needed-when-unlocking-stolen-mutex" issue I already explained (sleepers - xnsynch_nsleepers is precisely the count of pending threads which have been awake then robbed the mutex).

Hmm, sounds like the new lock owner should better clear the 'claimed' bit then, not the old one on return from unlock. Or where is the pitfall? How does the futex algorithm handle this scenario?

Ok. Please read my explanation again, I have already explained this in another mail.

I did this, but I'm unable to derive the answer for my question from it. Let's go through it in more details:

When we pass a mutex to a new owner, we set its reference in the fast lock variable + set the claimed bit if there are more waiters. Instead, I would simple set that bit if there is a new owner. That owner will then pick up the mutex eventually and clear 'claimed' on exit from it lock service (if there are no further waiters then). If the new owner is not able to run and we steal the lock, we simple keep the 'claimed' bit as is. On exit from the stolen lock we find it set, thus we are forced to issue a syscall as it should be.

OK, what happens if some waiter wants to leave the party while we are holding the stolen lock? Then the sleeper number must be correct - that is one pitfall!

Quoted 6 lines
Quoted 4 lines

I will have to dig into this more deeply, considering more cases. But the additional "sleepers" field remains at least misplaced IMHO. xnsynch_sleepers should better be fixed to respect lock stealing, as lock stealing is an xnsynch property, nothing POSIX-specific.

Ok. I have read this but did not get what you mean. I will read it again
quietly from home.

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 6 lines
Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

By the way, I think we should stop sending mails to our personal addresses in addition to the mailing list, because this results in mailing list mails being received out of orders, which make the threads hard to follow.

Quoted 8 lines

That's common practice on most mailing lists I know of, and I personally don't want to change this. IMO, it would only make replying more complicated, and it would bear the risk to drop CCs to non-subscribers.

I think the problem was only temporarily, maybe caused by some weird interaction of gna.org and the Siemens mailserver (we were too fast for them). Meanwhile, archives and inboxes should contain all messages. Gmane, e.g., lists them in the correct order now.

The "weird interaction" is actually a feature and called "grey listing". It delays mails for at least 5 minutes, the real result depending on the eagerness of your relay mail server to re-transmit the delayed message.

Signature · 1 line
					    Gilles.
author
#38 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 91 lines · Gilles Chanteperdrix
Quoted 90 lines · Jan Kiszka
Quoted 79 lines · Gilles Chanteperdrix
Quoted 78 lines · Gilles Chanteperdrix
Quoted 60 lines · Jan Kiszka
Quoted 38 lines · Gilles Chanteperdrix
Quoted 37 lines · Jan Kiszka
Quoted 12 lines · Gilles Chanteperdrix
Quoted 11 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka
Quoted 6 lines · Gilles Chanteperdrix
Quoted 3 lines · Jan Kiszka

+ xnarch_atomic_set(mutex->owner,
+ set_claimed(xnthread_handle(owner),
+ xnsynch_nsleepers(&mutex->synchbase)));

Ok. I think you have spotted a bug here. This should be mutex->sleepers instead of xnsynch_nsleepers.

BTW, why do you need to track sleepers separately in POSIX? Native doesn't do so, e.g.

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

Because of the "syscall-needed-when-unlocking-stolen-mutex" issue I already explained (sleepers - xnsynch_nsleepers is precisely the count of pending threads which have been awake then robbed the mutex).

Hmm, sounds like the new lock owner should better clear the 'claimed' bit then, not the old one on return from unlock. Or where is the pitfall? How does the futex algorithm handle this scenario?

Ok. Please read my explanation again, I have already explained this in another mail.

I did this, but I'm unable to derive the answer for my question from it. Let's go through it in more details:

When we pass a mutex to a new owner, we set its reference in the fast lock variable + set the claimed bit if there are more waiters. Instead, I would simple set that bit if there is a new owner. That owner will then pick up the mutex eventually and clear 'claimed' on exit from it lock service (if there are no further waiters then). If the new owner is not able to run and we steal the lock, we simple keep the 'claimed' bit as is. On exit from the stolen lock we find it set, thus we are forced to issue a syscall as it should be.

OK, what happens if some waiter wants to leave the party while we are holding the stolen lock? Then the sleeper number must be correct - that is one pitfall!

Quoted 6 lines
Quoted 4 lines

I will have to dig into this more deeply, considering more cases. But the additional "sleepers" field remains at least misplaced IMHO. xnsynch_sleepers should better be fixed to respect lock stealing, as lock stealing is an xnsynch property, nothing POSIX-specific.

Ok. I have read this but did not get what you mean. I will read it again
quietly from home.

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 6 lines
Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

By the way, I think we should stop sending mails to our personal addresses in addition to the mailing list, because this results in mailing list mails being received out of orders, which make the threads hard to follow.

That's common practice on most mailing lists I know of, and I personally don't want to change this. IMO, it would only make replying more complicated, and it would bear the risk to drop CCs to non-subscribers.

Quoted 8 lines
Quoted 4 lines

I think the problem was only temporarily, maybe caused by some weird interaction of gna.org and the Siemens mailserver (we were too fast for them). Meanwhile, archives and inboxes should contain all messages. Gmane, e.g., lists them in the correct order now.

The "weird interaction" is actually a feature and called "grey listing". It delays mails for at least 5 minutes, the real result depending on the eagerness of your relay mail server to re-transmit the delayed message.

I'm aware of such anti-spam approaches (and their varying effect). But as I've seen specifically gna.org struggling with other mailservers as well, just recently, I'm careful with blaming solely our corporate server. Logs would help to clarify, but I don't have access to either side.

Jan

#39 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 96 lines · Jan Kiszka
Quoted 95 lines · Gilles Chanteperdrix
Quoted 94 lines · Jan Kiszka
Quoted 79 lines · Gilles Chanteperdrix
Quoted 78 lines · Gilles Chanteperdrix
Quoted 60 lines · Jan Kiszka
Quoted 38 lines · Gilles Chanteperdrix
Quoted 37 lines · Jan Kiszka
Quoted 12 lines · Gilles Chanteperdrix
Quoted 11 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka
Quoted 6 lines · Gilles Chanteperdrix

Jan Kiszka wrote:
+ xnarch_atomic_set(mutex->owner,
+ set_claimed(xnthread_handle(owner),
+ xnsynch_nsleepers(&mutex->synchbase)));
Ok. I think you have spotted a bug here. This should be mutex->sleepers
instead of xnsynch_nsleepers.

BTW, why do you need to track sleepers separately in POSIX? Native doesn't do so, e.g.

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

Because of the "syscall-needed-when-unlocking-stolen-mutex" issue I already explained (sleepers - xnsynch_nsleepers is precisely the count of pending threads which have been awake then robbed the mutex).

Hmm, sounds like the new lock owner should better clear the 'claimed' bit then, not the old one on return from unlock. Or where is the pitfall? How does the futex algorithm handle this scenario?

Ok. Please read my explanation again, I have already explained this in another mail.

I did this, but I'm unable to derive the answer for my question from it. Let's go through it in more details:

When we pass a mutex to a new owner, we set its reference in the fast lock variable + set the claimed bit if there are more waiters. Instead, I would simple set that bit if there is a new owner. That owner will then pick up the mutex eventually and clear 'claimed' on exit from it lock service (if there are no further waiters then). If the new owner is not able to run and we steal the lock, we simple keep the 'claimed' bit as is. On exit from the stolen lock we find it set, thus we are forced to issue a syscall as it should be.

OK, what happens if some waiter wants to leave the party while we are holding the stolen lock? Then the sleeper number must be correct - that is one pitfall!

Quoted 6 lines
Quoted 4 lines

I will have to dig into this more deeply, considering more cases. But the additional "sleepers" field remains at least misplaced IMHO. xnsynch_sleepers should better be fixed to respect lock stealing, as lock stealing is an xnsynch property, nothing POSIX-specific.

Ok. I have read this but did not get what you mean. I will read it again
quietly from home.

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 6 lines
Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

By the way, I think we should stop sending mails to our personal addresses in addition to the mailing list, because this results in mailing list mails being received out of orders, which make the threads hard to follow.

That's common practice on most mailing lists I know of, and I personally don't want to change this. IMO, it would only make replying more complicated, and it would bear the risk to drop CCs to non-subscribers.

I think the problem was only temporarily, maybe caused by some weird interaction of gna.org and the Siemens mailserver (we were too fast for them). Meanwhile, archives and inboxes should contain all messages. Gmane, e.g., lists them in the correct order now.

Quoted 8 lines
Quoted 3 lines

The "weird interaction" is actually a feature and called "grey listing". It delays mails for at least 5 minutes, the real result depending on the eagerness of your relay mail server to re-transmit the delayed message.

I'm aware of such anti-spam approaches (and their varying effect). But as I've seen specifically gna.org struggling with other mailservers as well, just recently, I'm careful with blaming solely our corporate server. Logs would help to clarify, but I don't have access to either side.

Here is an exerpt of the logs:

2008-08-27 16:55:54 1KYMR8-0004Uw-2w SMTP error from remote mailer after
initial connection: host mail.gna.org [88.191.250.46]: 421 mail.gna.org
service not available, please try later.
Then:
2008-08-27 16:55:55 1KYMR8-0004Uw-2w => [email protected]

R=dnslookup T=remote_smtp H=hephaistos.siemens.com [217.194.34.77] X=TLS-1.0:RSA_AES_256_CBC_SHA:32
2
And finally:

2008-08-27 17:13:08 1KYMR8-0004Uw-2w => [email protected] R=dnslookup
T=remote_smtp H=mail.gna.org [88.191.250.46]*
2008-08-27 17:13:08 1KYMR8-0004Uw-2w Completed
Signature · 1 line
					    Gilles.
author
#40 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

In reply to Gilles Chanteperdrix
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 34 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Jan

---
 ksrc/skins/posix/mutex.c |   10 +++++++---
 ksrc/skins/posix/mutex.h |   17 +++++++++++------
 2 files changed, 18 insertions(+), 9 deletions(-)
ksrc/skins/posix/mutex.c +7 -3
Index: b/ksrc/skins/posix/mutex.c
===================================================================
@@ -117,7 +117,6 @@ int pse51_mutex_init_internal(struct __s
 	mutex->attr = *attr;
 	mutex->owner = ownerp;
 	mutex->owningq = kq;
-	mutex->sleepers = 0;
 	xnarch_atomic_set(ownerp, XN_NO_HANDLE);
 
 	xnlock_get_irqsave(&nklock, s);
@@ -305,14 +304,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_sleep_on(&mutex->synchbase,
 						 abs_to, XN_REALTIME);
 			else
 				xnsynch_sleep_on(&mutex->synchbase,
 						 XN_INFINITE, XN_RELATIVE);
-			--mutex->sleepers;
 
 			if (xnthread_test_info(cur, XNBREAK)) {
 				err = -EINTR;
@@ -329,6 +326,13 @@ int pse51_mutex_timedlock_break(struct _
 				break;
 			}
 		}
+		if (!xnsynch_nsleepers(&mutex->synchbase)) {
+			xnarch_atomic_set
+				(mutex->owner,
+				 clear_claimed
+					(xnarch_atomic_get(mutex->owner)));
+			xnsynch_set_owner(&mutex->synchbase, NULL);
+		}
 		xnlock_put_irqrestore(&nklock, s);
 
 		break;
ksrc/skins/posix/mutex.h +11 -6
Index: b/ksrc/skins/posix/mutex.h
===================================================================
@@ -57,7 +57,6 @@ typedef struct pse51_mutex {
 
 	xnarch_atomic_t *owner;
 	pthread_mutexattr_t attr;
-	unsigned sleepers;
 	pse51_kqueues_t *owningq;
 } pse51_mutex_t;
 
@@ -172,12 +171,10 @@ 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);
 	else
 		xnsynch_sleep_on(&mutex->synchbase, XN_INFINITE, XN_RELATIVE);
-	--mutex->sleepers;
 
 	if (xnthread_test_info(cur, XNBREAK)) {
 		err = -EINTR;
@@ -192,7 +189,11 @@ static inline int pse51_mutex_timedlock_
 		goto error;
 	}
 
-	ownerh = set_claimed(xnthread_handle(cur), mutex->sleepers);
+	ownerh = xnthread_handle(cur);
+	if (xnsynch_nsleepers(&mutex->synchbase))
+		ownerh = set_claimed(ownerh, 1);
+	else
+		xnsynch_set_owner(&mutex->synchbase, NULL);
 	xnarch_atomic_set(mutex->owner, ownerh);
 	shadow->lockcnt = count;
 	xnlock_put_irqrestore(&nklock, s);
@@ -200,10 +201,12 @@ static inline int pse51_mutex_timedlock_
 	return 0;
 
   error:
-	if (!mutex->sleepers)
+	if (!xnsynch_nsleepers(&mutex->synchbase)) {
 		xnarch_atomic_set
 			(mutex->owner,
 			 clear_claimed(xnarch_atomic_get(mutex->owner)));
+		xnsynch_set_owner(&mutex->synchbase, NULL);
+	}
 	xnlock_put_irqrestore(&nklock, s);
 	return err;
 }
@@ -221,7 +224,9 @@ static inline void pse51_mutex_unlock_in
 
 	xnlock_get_irqsave(&nklock, s);
 	owner = xnsynch_wakeup_one_sleeper(&mutex->synchbase);
-	ownerh = set_claimed(xnthread_handle(owner), mutex->sleepers);
+	ownerh =
+	    set_claimed(xnthread_handle(owner),
+			xnsynch_nsleepers(&mutex->synchbase));
 	xnarch_atomic_set(mutex->owner, ownerh);
 	if (owner)
 		xnpod_schedule();
#41 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 41 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Signature · 1 line
					    Gilles.
#42 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 48 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Signature · 1 line
Philippe.
author
#43 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 62 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

Quoted 3 lines

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

... but would also not be able to provide PIP. Unfortunately, we want PIP here, but we do separate owner tracking, so this differentiation alone won't help.

When it comes to find a minimal invasive approach, I'm more in favor of breaking up that lock stealing loop in xnsynch_sleep_on, letting the caller handle XNROBBED instead. That feature could easily be made an add-on to the current internal handling, without risking regressions for other users.

Quoted 6 lines

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Yeah, it's clear. I'm currently considering the options and the efforts. There are some smaller differences the way POSIX does fast locking right now and native may do it, so it is also not yet clear to me how to abstract a generic service. Nevertheless, it would help a lot avoiding to invent too many skin-specific bugs when porting the algorithms back and forth...

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#44 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 62 lines · Jan Kiszka
Quoted 61 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

Quoted 6 lines
Quoted 3 lines

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

... but would also not be able to provide PIP. Unfortunately, we want PIP here,

I don't follow you here. You just can't provide PIP if you don't have ownership.

but we do separate owner tracking, so this differentiation

Quoted 8 lines

alone won't help.

When it comes to find a minimal invasive approach, I'm more in favor of breaking up that lock stealing loop in xnsynch_sleep_on, letting the caller handle XNROBBED instead. That feature could easily be made an add-on to the current internal handling, without risking regressions for other users.

Mmfff...

Quoted 6 lines
Quoted 5 lines

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Quoted 7 lines

Yeah, it's clear. I'm currently considering the options and the efforts. There are some smaller differences the way POSIX does fast locking right now and native may do it, so it is also not yet clear to me how to abstract a generic service. Nevertheless, it would help a lot avoiding to invent too many skin-specific bugs when porting the algorithms back and forth...

This is why I don't think moving part of the core logic to the skins would be a good idea.

Quoted 2 lines

Jan

Signature · 1 line
Philippe.
#45 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

In reply to Philippe Gerum
Quoted 66 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Quoted 5 lines

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED. And well, cases of more than two waiters are not tested as well, but I would not think it really matters. It could be extended as well to allow switching at start time between the posix api and the native api, after all we do not care much about the overhead of calling function pointers in a a test application.

As for evolution of xnsynch, I am all for it, but it would break anything implemented before, so it will probably be on Jan's critical path.

Signature · 1 line
                                                 Gilles.
author
#46 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 66 lines · Gilles Chanteperdrix
Quoted 65 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Quoted 8 lines
Quoted 5 lines

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED.

My colleague sent me an extension. It's native-only so far, but it already pointed out a bug in my try-acquire implementation that should be present in posix as well (trylock must go through the slow path).

Quoted 5 lines

And well, cases of more than two waiters are not tested as well, but I would not think it really matters. It could be extended as well to allow switching at start time between the posix api and the native api, after all we do not care much about the overhead of calling function pointers in a a test application.

For now we have two files already, but maybe we can merge them later based on your proposal.

Quoted 3 lines

As for evolution of xnsynch, I am all for it, but it would break anything implemented before, so it will probably be on Jan's critical path.

I have some intermediate version here that breaks up the retry-on-XNROBBED loop, doing it at skin level instead. This is targeting the first customer delivery.

I also have two implementations of fast locking now, native and posix, and they don't look that bad /wrt moving quite a few bits into xnsynch - later.

Jan

PS: The test cases + my /proc/xenomai/registry/usage probably unveiled another pending bug: Native user space tasks are leaking handles, even on vanilla Xenomai SVN (didn't test 2.4.x yet). Will look into this later.

#47 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 72 lines · Jan Kiszka
Quoted 71 lines · Gilles Chanteperdrix
Quoted 70 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Quoted 6 lines
Quoted 2 lines

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED.

My colleague sent me an extension. It's native-only so far, but it already pointed out a bug in my try-acquire implementation that should be present in posix as well (trylock must go through the slow path).

I do not see why. If mutex lock can lock without a syscall, the same goes for trylock.

Signature · 1 line
					    Gilles.
author
#48 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 73 lines · Gilles Chanteperdrix
Quoted 72 lines · Jan Kiszka
Quoted 71 lines · Gilles Chanteperdrix
Quoted 70 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED.

My colleague sent me an extension. It's native-only so far, but it already pointed out a bug in my try-acquire implementation that should be present in posix as well (trylock must go through the slow path).

I do not see why. If mutex lock can lock without a syscall, the same goes for trylock.

Lock stealing requires the slow path.

Jan

#49 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 76 lines · Jan Kiszka
Quoted 75 lines · Gilles Chanteperdrix
Quoted 74 lines · Jan Kiszka
Quoted 73 lines · Gilles Chanteperdrix
Quoted 65 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Quoted 5 lines

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED.

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines

My colleague sent me an extension. It's native-only so far, but it already pointed out a bug in my try-acquire implementation that should be present in posix as well (trylock must go through the slow path).

I do not see why. If mutex lock can lock without a syscall, the same goes for trylock.

Lock stealing requires the slow path.

Ah ok. I thought you mean that trylock had to go systematically through syscall.

As for lock stealing, I already said that it was not tested in the current test.

Signature · 1 line
                                                 Gilles.
author
#50 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 82 lines · Gilles Chanteperdrix
Quoted 81 lines · Jan Kiszka
Quoted 80 lines · Gilles Chanteperdrix
Quoted 72 lines · Jan Kiszka
Quoted 71 lines · Gilles Chanteperdrix
Quoted 70 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Quoted 5 lines
Quoted 2 lines

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED.

My colleague sent me an extension. It's native-only so far, but it already pointed out a bug in my try-acquire implementation that should be present in posix as well (trylock must go through the slow path).

I do not see why. If mutex lock can lock without a syscall, the same goes for trylock.

Quoted 7 lines
Quoted 1 line

Lock stealing requires the slow path.

Ah ok. I thought you mean that trylock had to go systematically through syscall.

As for lock stealing, I already said that it was not tested in the current test.

In fact, that bug is also present the current native skin (SVN, 2.4.x should suffer as well). Probably also current 2.4.x posix is affected, at least from a first glance.

Jan

PS: Handle leak fixed, #4156, was SVN-only, I caused it.

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#51 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 87 lines · Jan Kiszka
Quoted 86 lines · Gilles Chanteperdrix
Quoted 74 lines · Jan Kiszka
Quoted 73 lines · Gilles Chanteperdrix
Quoted 72 lines · Jan Kiszka
Quoted 71 lines · Gilles Chanteperdrix
Quoted 70 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED.

My colleague sent me an extension. It's native-only so far, but it already pointed out a bug in my try-acquire implementation that should be present in posix as well (trylock must go through the slow path).

I do not see why. If mutex lock can lock without a syscall, the same goes for trylock.

Lock stealing requires the slow path.

Ah ok. I thought you mean that trylock had to go systematically through syscall.

Quoted 6 lines
Quoted 2 lines

As for lock stealing, I already said that it was not tested in the current test.

In fact, that bug is also present the current native skin (SVN, 2.4.x should suffer as well). Probably also current 2.4.x posix is affected, at least from a first glance.

Well, yes, now that you mention it, calling xnsynch_sleep_on does not seem obvious for the implementation of a trylock.

And by the way, I think that with the mutex/xnsynch shared owner, we can implement stealing without a syscall.

Signature · 1 line
                                                 Gilles.
author
#52 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 88 lines · Gilles Chanteperdrix
Quoted 87 lines · Jan Kiszka
Quoted 86 lines · Gilles Chanteperdrix
Quoted 74 lines · Jan Kiszka
Quoted 73 lines · Gilles Chanteperdrix
Quoted 72 lines · Jan Kiszka
Quoted 71 lines · Gilles Chanteperdrix
Quoted 70 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED.

My colleague sent me an extension. It's native-only so far, but it already pointed out a bug in my try-acquire implementation that should be present in posix as well (trylock must go through the slow path).

I do not see why. If mutex lock can lock without a syscall, the same goes for trylock.

Lock stealing requires the slow path.

Ah ok. I thought you mean that trylock had to go systematically through syscall.

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

As for lock stealing, I already said that it was not tested in the current test.

In fact, that bug is also present the current native skin (SVN, 2.4.x should suffer as well). Probably also current 2.4.x posix is affected, at least from a first glance.

Well, yes, now that you mention it, calling xnsynch_sleep_on does not seem obvious for the implementation of a trylock.

Once the dust settles here, I will have a look at the stable series as well, providing a fix for the "old" mutexes.

Quoted 3 lines

And by the way, I think that with the mutex/xnsynch shared owner, we can implement stealing without a syscall.

Probably. But it will definitely need full fast locking support inside xnsynch, which is basically about defining and maintaining a generic user-shared lock word from within xnsynch services that has at least a 'claimed' and a 'assignment pending' bit. Looks like we will not run out of work soon... ;)

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#53 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 5 lines · Jan Kiszka

Probably. But it will definitely need full fast locking support inside xnsynch, which is basically about defining and maintaining a generic user-shared lock word from within xnsynch services that has at least a 'claimed' and a 'assignment pending' bit. Looks like we will not run out of work soon... ;)

The way xnsynch_sleep_on checks the owner field and retries for the implementation of the lock stealing already furiously look like a mutex compare and exchange...

Signature · 1 line
                                                 Gilles.
#54 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

In reply to Gilles Chanteperdrix
Quoted 88 lines · Gilles Chanteperdrix
Quoted 87 lines · Jan Kiszka
Quoted 86 lines · Gilles Chanteperdrix
Quoted 74 lines · Jan Kiszka
Quoted 73 lines · Gilles Chanteperdrix
Quoted 72 lines · Jan Kiszka
Quoted 71 lines · Gilles Chanteperdrix
Quoted 70 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED.

My colleague sent me an extension. It's native-only so far, but it already pointed out a bug in my try-acquire implementation that should be present in posix as well (trylock must go through the slow path).

I do not see why. If mutex lock can lock without a syscall, the same goes for trylock.

Lock stealing requires the slow path.

Ah ok. I thought you mean that trylock had to go systematically through syscall.

Quoted 9 lines
Quoted 5 lines
Quoted 2 lines

As for lock stealing, I already said that it was not tested in the current test.

In fact, that bug is also present the current native skin (SVN, 2.4.x should suffer as well). Probably also current 2.4.x posix is affected, at least from a first glance.

Well, yes, now that you mention it, calling xnsynch_sleep_on does not seem obvious for the implementation of a trylock.

Don't even try calling xnsynch_sleep_on with a nonblocking-type timeout.

Quoted 3 lines

And by the way, I think that with the mutex/xnsynch shared owner, we can implement stealing without a syscall.

Signature · 1 line
Philippe.
author
#55 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 91 lines · Philippe Gerum
Quoted 90 lines · Gilles Chanteperdrix
Quoted 89 lines · Jan Kiszka
Quoted 88 lines · Gilles Chanteperdrix
Quoted 74 lines · Jan Kiszka
Quoted 73 lines · Gilles Chanteperdrix
Quoted 72 lines · Jan Kiszka
Quoted 71 lines · Gilles Chanteperdrix
Quoted 70 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 19 lines

I think I'm getting closer to the issue. Our actual problem comes from
the fact that the xnsynch_owner is easily out of sync with the real
owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B,
causing it to become the new xnsynch owner, and clears the claimed bit
as there are no further sleepers. B returns, and when it wants to
release the mutex, it does this happily in user space because claimed is
not set. Now the fast lock variable is 'unlocked', while xnsynch still
reports B being the owner. This is no problem as the next time two
threads fight over this lock the waiter will simply overwrite the
xnsynch_owner before it falls asleep. But this "trick" doesn't work for
waiters that have been robbed. They will spin inside xnsynch_sleep_on
and stumble over this inconsistency.

I have two approaches in mind now: First one is something like
XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED
so that the robbed thread spins one level higher in the skin code -
which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return
from kernel with the lock held while there are no more xnsynch_sleepers.
That should work with even less changes and save us one syscall in the
robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED.

My colleague sent me an extension. It's native-only so far, but it already pointed out a bug in my try-acquire implementation that should be present in posix as well (trylock must go through the slow path).

I do not see why. If mutex lock can lock without a syscall, the same goes for trylock.

Lock stealing requires the slow path.

Ah ok. I thought you mean that trylock had to go systematically through syscall.

As for lock stealing, I already said that it was not tested in the current test.

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

In fact, that bug is also present the current native skin (SVN, 2.4.x should suffer as well). Probably also current 2.4.x posix is affected, at least from a first glance.

Well, yes, now that you mention it, calling xnsynch_sleep_on does not seem obvious for the implementation of a trylock.

Don't even try calling xnsynch_sleep_on with a nonblocking-type timeout.

Works nicely today (using (XN_NONBLOCK, XN_RELATIVE)) due to early timeout checks in xntimer_start. You just have to translate XNTIMEO into EWOULDBLOCK on return.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#56 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 95 lines · Jan Kiszka
Quoted 94 lines · Philippe Gerum
Quoted 93 lines · Gilles Chanteperdrix
Quoted 92 lines · Jan Kiszka
Quoted 80 lines · Gilles Chanteperdrix
Quoted 79 lines · Jan Kiszka
Quoted 78 lines · Gilles Chanteperdrix
Quoted 77 lines · Jan Kiszka
Quoted 66 lines · Gilles Chanteperdrix
Quoted 65 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 40 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 34 lines

I think I'm getting closer to the issue. Our actual problem comes from
the fact that the xnsynch_owner is easily out of sync with the real
owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B,
causing it to become the new xnsynch owner, and clears the claimed bit
as there are no further sleepers. B returns, and when it wants to
release the mutex, it does this happily in user space because claimed is
not set. Now the fast lock variable is 'unlocked', while xnsynch still
reports B being the owner. This is no problem as the next time two
threads fight over this lock the waiter will simply overwrite the
xnsynch_owner before it falls asleep. But this "trick" doesn't work for
waiters that have been robbed. They will spin inside xnsynch_sleep_on
and stumble over this inconsistency.

I have two approaches in mind now: First one is something like
XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED
so that the robbed thread spins one level higher in the skin code -
which would have to be extended a bit.
No, the stealing is the xnsynch job.

Option two is to clear xnsynch_owner once a new owner is about to return
from kernel with the lock held while there are no more xnsynch_sleepers.
That should work with even less changes and save us one syscall in the
robbed case. Need to think about it more, though.
In fact the only time when the owner is required to be in sync is when
PIP occurs, and this is guaranteed to work, because when PIP is needed a
syscall is emitted anyway. To the extent that xnsynch does not even
track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Ok. And what about the idea of the xnsynch bit to tell him "hey, the
owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Quoted 6 lines

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Quoted 7 lines
Quoted 5 lines

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED.

My colleague sent me an extension. It's native-only so far, but it already pointed out a bug in my try-acquire implementation that should be present in posix as well (trylock must go through the slow path).

Quoted 8 lines
Quoted 3 lines
Quoted 2 lines

I do not see why. If mutex lock can lock without a syscall, the same goes for trylock.

Lock stealing requires the slow path.

Ah ok. I thought you mean that trylock had to go systematically through syscall.

As for lock stealing, I already said that it was not tested in the current test.

In fact, that bug is also present the current native skin (SVN, 2.4.x should suffer as well). Probably also current 2.4.x posix is affected, at least from a first glance.

Quoted 9 lines
Quoted 4 lines
Quoted 3 lines

Well, yes, now that you mention it, calling xnsynch_sleep_on does not seem obvious for the implementation of a trylock.

Don't even try calling xnsynch_sleep_on with a nonblocking-type timeout.

Works nicely today (using (XN_NONBLOCK, XN_RELATIVE)) due to early timeout checks in xntimer_start. You just have to translate XNTIMEO into EWOULDBLOCK on return.

It's very fundamentally crappy. Please don't do that. xnsynch_sleep_on() must do what it is supposed to mean.

Quoted 2 lines

Jan

Signature · 1 line
Philippe.
author
#57 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 99 lines · Philippe Gerum
Quoted 98 lines · Jan Kiszka
Quoted 97 lines · Philippe Gerum
Quoted 96 lines · Gilles Chanteperdrix
Quoted 84 lines · Jan Kiszka
Quoted 83 lines · Gilles Chanteperdrix
Quoted 82 lines · Jan Kiszka
Quoted 73 lines · Gilles Chanteperdrix
Quoted 72 lines · Jan Kiszka
Quoted 71 lines · Gilles Chanteperdrix
Quoted 70 lines · Philippe Gerum
Quoted 47 lines · Gilles Chanteperdrix
Quoted 46 lines · Jan Kiszka

Gilles Chanteperdrix wrote:
Jan Kiszka wrote:
...
I think I'm getting closer to the issue. Our actual problem comes from
the fact that the xnsynch_owner is easily out of sync with the real
owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B,
causing it to become the new xnsynch owner, and clears the claimed bit
as there are no further sleepers. B returns, and when it wants to
release the mutex, it does this happily in user space because claimed is
not set. Now the fast lock variable is 'unlocked', while xnsynch still
reports B being the owner. This is no problem as the next time two
threads fight over this lock the waiter will simply overwrite the
xnsynch_owner before it falls asleep. But this "trick" doesn't work for
waiters that have been robbed. They will spin inside xnsynch_sleep_on
and stumble over this inconsistency.

I have two approaches in mind now: First one is something like
XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED
so that the robbed thread spins one level higher in the skin code -
which would have to be extended a bit.
No, the stealing is the xnsynch job.

Option two is to clear xnsynch_owner once a new owner is about to return
from kernel with the lock held while there are no more xnsynch_sleepers.
That should work with even less changes and save us one syscall in the
robbed case. Need to think about it more, though.
In fact the only time when the owner is required to be in sync is when
PIP occurs, and this is guaranteed to work, because when PIP is needed a
syscall is emitted anyway. To the extent that xnsynch does not even
track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Ok. And what about the idea of the xnsynch bit to tell him "hey, the
owner is tracked in the upper layer, go there to find it".
I'm yet having difficulties to imagine how this should look like when
it's implemented. Would it be simpler than my second idea?

Anyway, here is a patch (on top of my handle-based lock series) for the
approach that clears xnsynch_owner when there are no waiters. At least
it causes no regression based on your test, but I haven't checked lock
stealing yet. In theory, everything still appears to be fine to me. This
approach basically restores the state we find when some thread just
acquired the lock in user space.

Quoted 7 lines

Yes, I did not think about the stealing when writing my test, but I think it could be a good idea to add it to the test, especially if you want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED.

My colleague sent me an extension. It's native-only so far, but it already pointed out a bug in my try-acquire implementation that should be present in posix as well (trylock must go through the slow path).

I do not see why. If mutex lock can lock without a syscall, the same goes for trylock.

Lock stealing requires the slow path.

Quoted 8 lines
Quoted 5 lines

Ah ok. I thought you mean that trylock had to go systematically through syscall.

As for lock stealing, I already said that it was not tested in the current test.

In fact, that bug is also present the current native skin (SVN, 2.4.x should suffer as well). Probably also current 2.4.x posix is affected, at least from a first glance.

Well, yes, now that you mention it, calling xnsynch_sleep_on does not seem obvious for the implementation of a trylock.

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

Don't even try calling xnsynch_sleep_on with a nonblocking-type timeout.

Works nicely today (using (XN_NONBLOCK, XN_RELATIVE)) due to early timeout checks in xntimer_start. You just have to translate XNTIMEO into EWOULDBLOCK on return.

It's very fundamentally crappy. Please don't do that. xnsynch_sleep_on() must do what it is supposed to mean.

So we need xnsynch_try_to_steal + lots of new special-case code in the skins to re-implement what is already there? No, I can't imagine that this is what you want to see in the end.

Then lets better rename xnsynch_sleep_on to something like xnsynch_acquire - will be logically needed anyway when we push fast mutex maintenance into it.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#58 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 105 lines · Jan Kiszka
Quoted 104 lines · Philippe Gerum
Quoted 103 lines · Jan Kiszka
Quoted 91 lines · Philippe Gerum
Quoted 90 lines · Gilles Chanteperdrix
Quoted 89 lines · Jan Kiszka
Quoted 88 lines · Gilles Chanteperdrix
Quoted 74 lines · Jan Kiszka
Quoted 73 lines · Gilles Chanteperdrix
Quoted 72 lines · Jan Kiszka
Quoted 71 lines · Gilles Chanteperdrix
Quoted 70 lines · Philippe Gerum
Quoted 54 lines · Gilles Chanteperdrix

Jan Kiszka wrote:
Gilles Chanteperdrix wrote:
Jan Kiszka wrote:
...
I think I'm getting closer to the issue. Our actual problem comes from
the fact that the xnsynch_owner is easily out of sync with the real
owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B,
causing it to become the new xnsynch owner, and clears the claimed bit
as there are no further sleepers. B returns, and when it wants to
release the mutex, it does this happily in user space because claimed is
not set. Now the fast lock variable is 'unlocked', while xnsynch still
reports B being the owner. This is no problem as the next time two
threads fight over this lock the waiter will simply overwrite the
xnsynch_owner before it falls asleep. But this "trick" doesn't work for
waiters that have been robbed. They will spin inside xnsynch_sleep_on
and stumble over this inconsistency.

I have two approaches in mind now: First one is something like
XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED
so that the robbed thread spins one level higher in the skin code -
which would have to be extended a bit.
No, the stealing is the xnsynch job.

Option two is to clear xnsynch_owner once a new owner is about to return
from kernel with the lock held while there are no more xnsynch_sleepers.
That should work with even less changes and save us one syscall in the
robbed case. Need to think about it more, though.
In fact the only time when the owner is required to be in sync is when
PIP occurs, and this is guaranteed to work, because when PIP is needed a
syscall is emitted anyway. To the extent that xnsynch does not even
track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Ok. And what about the idea of the xnsynch bit to tell him "hey, the
owner is tracked in the upper layer, go there to find it".
I'm yet having difficulties to imagine how this should look like when
it's implemented. Would it be simpler than my second idea?

Anyway, here is a patch (on top of my handle-based lock series) for the
approach that clears xnsynch_owner when there are no waiters. At least
it causes no regression based on your test, but I haven't checked lock
stealing yet. In theory, everything still appears to be fine to me. This
approach basically restores the state we find when some thread just
acquired the lock in user space.
Yes, I did not think about the stealing when writing my test, but I
think it could be a good idea to add it to the test, especially if you
want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and
probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede your various proposals. I would suggest to decouple that: the basic property of some xnsynch that we may want to handle is exclusiveness, then dynamic priority inheritance is another property, that could stack its own semantics on top of exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would simply add dynamic priority management. Non exclusive object would not require any xnsynch_set_owner() handling.

Just to give a clear signal here: I will happily consider any change to the xnsynch object that may ease the implementation of fast ownership handling (i.e. userland-to-userland transfer). The only thing is that such code is very much prone to regressions, so a testsuite must come with core changes in that area, but I guess you know that already.

Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED.

My colleague sent me an extension. It's native-only so far, but it already pointed out a bug in my try-acquire implementation that should be present in posix as well (trylock must go through the slow path).

I do not see why. If mutex lock can lock without a syscall, the same goes for trylock.

Lock stealing requires the slow path.

Ah ok. I thought you mean that trylock had to go systematically through syscall.

As for lock stealing, I already said that it was not tested in the current test.

Quoted 7 lines
Quoted 6 lines
Quoted 3 lines

In fact, that bug is also present the current native skin (SVN, 2.4.x should suffer as well). Probably also current 2.4.x posix is affected, at least from a first glance.

Well, yes, now that you mention it, calling xnsynch_sleep_on does not seem obvious for the implementation of a trylock.

Don't even try calling xnsynch_sleep_on with a nonblocking-type timeout.

Works nicely today (using (XN_NONBLOCK, XN_RELATIVE)) due to early timeout checks in xntimer_start. You just have to translate XNTIMEO into EWOULDBLOCK on return.

Quoted 7 lines
Quoted 2 lines

It's very fundamentally crappy. Please don't do that. xnsynch_sleep_on() must do what it is supposed to mean.

So we need xnsynch_try_to_steal + lots of new special-case code in the skins to re-implement what is already there? No, I can't imagine that this is what you want to see in the end.

What I don't want is to see code running a routine called "sleep_on" knowing that it may not sleep. What I don't want either, is to go through xnsynch_sleep_on -> xnpod_suspend_thread -> xntimer_start -> xnsynch_forget_sleeper to get things right with !PIP objects, albeit the caller knows from the beginning that it does not want to sleep. So much for the fast path to trylocking.

Quoted 4 lines

Then lets better rename xnsynch_sleep_on to something like xnsynch_acquire - will be logically needed anyway when we push fast mutex maintenance into it.

This would not fix issue #2. xnsynch_try_acquire() that would attempt stealing is the way to go. It's even possible that some code could be shared between that routine, and the resource stealing support currently provided by xnsynch_sleep_on(). Only resource acquisition routines that enforce exclusive ownership would be impacted, not each and every xnsynch_sleep_on caller.

Quoted 2 lines

Jan

Signature · 1 line
Philippe.
author
#59 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 113 lines · Philippe Gerum
Quoted 105 lines · Jan Kiszka
Quoted 104 lines · Philippe Gerum
Quoted 103 lines · Jan Kiszka
Quoted 91 lines · Philippe Gerum
Quoted 90 lines · Gilles Chanteperdrix
Quoted 89 lines · Jan Kiszka
Quoted 88 lines · Gilles Chanteperdrix
Quoted 74 lines · Jan Kiszka
Quoted 73 lines · Gilles Chanteperdrix
Quoted 72 lines · Jan Kiszka
Quoted 71 lines · Gilles Chanteperdrix
Quoted 70 lines · Philippe Gerum

Gilles Chanteperdrix wrote:
Jan Kiszka wrote:
Gilles Chanteperdrix wrote:
Jan Kiszka wrote:
...
I think I'm getting closer to the issue. Our actual problem comes from
the fact that the xnsynch_owner is easily out of sync with the real
owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B,
causing it to become the new xnsynch owner, and clears the claimed bit
as there are no further sleepers. B returns, and when it wants to
release the mutex, it does this happily in user space because claimed is
not set. Now the fast lock variable is 'unlocked', while xnsynch still
reports B being the owner. This is no problem as the next time two
threads fight over this lock the waiter will simply overwrite the
xnsynch_owner before it falls asleep. But this "trick" doesn't work for
waiters that have been robbed. They will spin inside xnsynch_sleep_on
and stumble over this inconsistency.

I have two approaches in mind now: First one is something like
XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED
so that the robbed thread spins one level higher in the skin code -
which would have to be extended a bit.
No, the stealing is the xnsynch job.

Option two is to clear xnsynch_owner once a new owner is about to return
from kernel with the lock held while there are no more xnsynch_sleepers.
That should work with even less changes and save us one syscall in the
robbed case. Need to think about it more, though.
In fact the only time when the owner is required to be in sync is when
PIP occurs, and this is guaranteed to work, because when PIP is needed a
syscall is emitted anyway. To the extent that xnsynch does not even
track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Ok. And what about the idea of the xnsynch bit to tell him "hey, the
owner is tracked in the upper layer, go there to find it".
I'm yet having difficulties to imagine how this should look like when
it's implemented. Would it be simpler than my second idea?

Anyway, here is a patch (on top of my handle-based lock series) for the
approach that clears xnsynch_owner when there are no waiters. At least
it causes no regression based on your test, but I haven't checked lock
stealing yet. In theory, everything still appears to be fine to me. This
approach basically restores the state we find when some thread just
acquired the lock in user space.
Yes, I did not think about the stealing when writing my test, but I
think it could be a good idea to add it to the test, especially if you
want to port the test to the native API.

I let Philippe decide here. He is the one who did the stealing stuff and
probably knows better.

Currently, the xnsynch strongly couples PIP and ownership, which seems to impede
your various proposals. I would suggest to decouple that: the basic property of
some xnsynch that we may want to handle is exclusiveness, then dynamic priority
inheritance is another property, that could stack its own semantics on top of
exclusiveness.

XNSYNCH_EXCLUSIVE would cover all ownership-related actions, XNSYNCH_PIP would
simply add dynamic priority management. Non exclusive object would not require
any xnsynch_set_owner() handling.

Just to give a clear signal here: I will happily consider any change to the
xnsynch object that may ease the implementation of fast ownership handling (i.e.
userland-to-userland transfer). The only thing is that such code is very much
prone to regressions, so a testsuite must come with core changes in that area,
but I guess you know that already.

Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

Ok. I think unit_mutex.c is a good start. It only lacks testing XNROBBED.

My colleague sent me an extension. It's native-only so far, but it already pointed out a bug in my try-acquire implementation that should be present in posix as well (trylock must go through the slow path).

I do not see why. If mutex lock can lock without a syscall, the same goes for trylock.

Lock stealing requires the slow path.

Ah ok. I thought you mean that trylock had to go systematically through syscall.

As for lock stealing, I already said that it was not tested in the current test.

Quoted 7 lines
Quoted 6 lines
Quoted 3 lines

In fact, that bug is also present the current native skin (SVN, 2.4.x should suffer as well). Probably also current 2.4.x posix is affected, at least from a first glance.

Well, yes, now that you mention it, calling xnsynch_sleep_on does not seem obvious for the implementation of a trylock.

Don't even try calling xnsynch_sleep_on with a nonblocking-type timeout.

Works nicely today (using (XN_NONBLOCK, XN_RELATIVE)) due to early timeout checks in xntimer_start. You just have to translate XNTIMEO into EWOULDBLOCK on return.

Quoted 6 lines
Quoted 2 lines

It's very fundamentally crappy. Please don't do that. xnsynch_sleep_on() must do what it is supposed to mean.

So we need xnsynch_try_to_steal + lots of new special-case code in the skins to re-implement what is already there? No, I can't imagine that this is what you want to see in the end.

Quoted 6 lines

What I don't want is to see code running a routine called "sleep_on" knowing that it may not sleep. What I don't want either, is to go through xnsynch_sleep_on -> xnpod_suspend_thread -> xntimer_start -> xnsynch_forget_sleeper to get things right with !PIP objects, albeit the caller knows from the beginning that it does not want to sleep. So much for the fast path to trylocking.

OK, point taken. But as this is a generic API issue, I would like to see it fixed in the generic code, not in some to-be-duplicated branches in all the skins.

My point is that our timeout API nicely defines the case XN_NONBLOCK now, throughout all layers. We just need to pass the arguments as-is down, the core will handle them. Let's do optimizations at the lowest possible layer, i.e. in xnsynch_sleep_on (or whatever it may be called better). A simple 'if' before suspend should be enough. And it will keep the code small.

Quoted 11 lines
Quoted 5 lines

Then lets better rename xnsynch_sleep_on to something like xnsynch_acquire - will be logically needed anyway when we push fast mutex maintenance into it.

This would not fix issue #2. xnsynch_try_acquire() that would attempt stealing is the way to go. It's even possible that some code could be shared between that routine, and the resource stealing support currently provided by xnsynch_sleep_on(). Only resource acquisition routines that enforce exclusive ownership would be impacted, not each and every xnsynch_sleep_on caller.

For now it will be a PIP show, but atomic_cmpxchg-based semaphores might be an xnsynch extension in the future as well.

Jan

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

#60 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

In reply to Jan Kiszka
Quoted 83 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Jan

---
 ksrc/skins/posix/mutex.c |   10 +++++++---
 ksrc/skins/posix/mutex.h |   17 +++++++++++------
 2 files changed, 18 insertions(+), 9 deletions(-)

Index: b/ksrc/skins/posix/mutex.c
===================================================================

ksrc/skins/posix/mutex.c +0 -3
@@ -117,7 +117,6 @@ int pse51_mutex_init_internal(struct __s
 	mutex->attr = *attr;
 	mutex->owner = ownerp;
 	mutex->owningq = kq;
-	mutex->sleepers = 0;
 	xnarch_atomic_set(ownerp, XN_NO_HANDLE);
 
 	xnlock_get_irqsave(&nklock, s);
@@ -305,14 +304,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_sleep_on(&mutex->synchbase,
 						 abs_to, XN_REALTIME);
 			else
 				xnsynch_sleep_on(&mutex->synchbase,
 						 XN_INFINITE, XN_RELATIVE);
-			--mutex->sleepers;
 
 			if (xnthread_test_info(cur, XNBREAK)) {
 				err = -EINTR;

ksrc/skins/posix/mutex.c int pse51_mutex_timedlock_break(struct _ · line 335

Quoted 10 lines
ksrc/skins/posix/mutex.c +7 -0
@@ -329,6 +326,13 @@ int pse51_mutex_timedlock_break(struct _
 				break;
 			}
 		}
+		if (!xnsynch_nsleepers(&mutex->synchbase)) {
+			xnarch_atomic_set
+				(mutex->owner,
+				 clear_claimed
+					(xnarch_atomic_get(mutex->owner)));
+			xnsynch_set_owner(&mutex->synchbase, NULL);
+		}

I think an atomic_cmpxchg would be better here.

Signature · 1 line
					    Gilles.
author
#61 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 80 lines · Gilles Chanteperdrix
Quoted 79 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Jan

---
 ksrc/skins/posix/mutex.c |   10 +++++++---
 ksrc/skins/posix/mutex.h |   17 +++++++++++------
 2 files changed, 18 insertions(+), 9 deletions(-)

Index: b/ksrc/skins/posix/mutex.c
===================================================================

ksrc/skins/posix/mutex.c +0 -3
@@ -117,7 +117,6 @@ int pse51_mutex_init_internal(struct __s
 	mutex->attr = *attr;
 	mutex->owner = ownerp;
 	mutex->owningq = kq;
-	mutex->sleepers = 0;
 	xnarch_atomic_set(ownerp, XN_NO_HANDLE);
 
 	xnlock_get_irqsave(&nklock, s);
@@ -305,14 +304,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_sleep_on(&mutex->synchbase,
 						 abs_to, XN_REALTIME);
 			else
 				xnsynch_sleep_on(&mutex->synchbase,
 						 XN_INFINITE, XN_RELATIVE);
-			--mutex->sleepers;
 
Quoted 16 lines

ksrc/skins/posix/mutex.c int pse51_mutex_timedlock_break(struct _ · line 335

Quoted 13 lines
ksrc/skins/posix/mutex.c +7 -0
 			if (xnthread_test_info(cur, XNBREAK)) {
 				err = -EINTR;
@@ -329,6 +326,13 @@ int pse51_mutex_timedlock_break(struct _
 				break;
 			}
 		}
+		if (!xnsynch_nsleepers(&mutex->synchbase)) {
+			xnarch_atomic_set
+				(mutex->owner,
+				 clear_claimed
+					(xnarch_atomic_get(mutex->owner)));
+			xnsynch_set_owner(&mutex->synchbase, NULL);
+		}

I think an atomic_cmpxchg would be better here.

Not really. The claimed bit is set, so no one can change the owner without entering the kernel. But there we are also holding nklock. BTW, pse51_mutex_timedlock_internal does the same already.

Jan

#62 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 97 lines · Jan Kiszka
Quoted 80 lines · Gilles Chanteperdrix
Quoted 79 lines · Jan Kiszka
Quoted 1 line · Gilles Chanteperdrix

Jan Kiszka wrote:

...

Quoted 32 lines
Quoted 15 lines

I think I'm getting closer to the issue. Our actual problem comes from the fact that the xnsynch_owner is easily out of sync with the real owner, it even sometimes points to a former owner:

Thread A releases a mutex on which thread B pends. It wakes up B, causing it to become the new xnsynch owner, and clears the claimed bit as there are no further sleepers. B returns, and when it wants to release the mutex, it does this happily in user space because claimed is not set. Now the fast lock variable is 'unlocked', while xnsynch still reports B being the owner. This is no problem as the next time two threads fight over this lock the waiter will simply overwrite the xnsynch_owner before it falls asleep. But this "trick" doesn't work for waiters that have been robbed. They will spin inside xnsynch_sleep_on and stumble over this inconsistency.

Quoted 4 lines

I have two approaches in mind now: First one is something like XNSYNCH_STEALNOINFORM, i.e. causing xnsynch_sleep_on to not set XNROBBED so that the robbed thread spins one level higher in the skin code - which would have to be extended a bit.

No, the stealing is the xnsynch job.

Quoted 4 lines

Option two is to clear xnsynch_owner once a new owner is about to return from kernel with the lock held while there are no more xnsynch_sleepers. That should work with even less changes and save us one syscall in the robbed case. Need to think about it more, though.

In fact the only time when the owner is required to be in sync is when PIP occurs, and this is guaranteed to work, because when PIP is needed a syscall is emitted anyway. To the extent that xnsynch does not even track the owner on non PIP synch (which is why the posix skin originally
forcibly set the synch owner, and it was simply kept to get the fastsem
stuff working).

Quoted 2 lines

Ok. And what about the idea of the xnsynch bit to tell him "hey, the owner is tracked in the upper layer, go there to find it".

I'm yet having difficulties to imagine how this should look like when it's implemented. Would it be simpler than my second idea?

Anyway, here is a patch (on top of my handle-based lock series) for the approach that clears xnsynch_owner when there are no waiters. At least it causes no regression based on your test, but I haven't checked lock stealing yet. In theory, everything still appears to be fine to me. This approach basically restores the state we find when some thread just acquired the lock in user space.

Jan

---
 ksrc/skins/posix/mutex.c |   10 +++++++---
 ksrc/skins/posix/mutex.h |   17 +++++++++++------
 2 files changed, 18 insertions(+), 9 deletions(-)

Index: b/ksrc/skins/posix/mutex.c
===================================================================

ksrc/skins/posix/mutex.c +0 -3
@@ -117,7 +117,6 @@ int pse51_mutex_init_internal(struct __s
 	mutex->attr = *attr;
 	mutex->owner = ownerp;
 	mutex->owningq = kq;
-	mutex->sleepers = 0;
 	xnarch_atomic_set(ownerp, XN_NO_HANDLE);
 
 	xnlock_get_irqsave(&nklock, s);
@@ -305,14 +304,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_sleep_on(&mutex->synchbase,
 						 abs_to, XN_REALTIME);
 			else
 				xnsynch_sleep_on(&mutex->synchbase,
 						 XN_INFINITE, XN_RELATIVE);
-			--mutex->sleepers;
 
Quoted 15 lines

ksrc/skins/posix/mutex.c int pse51_mutex_timedlock_break(struct _ · line 335

Quoted 13 lines
ksrc/skins/posix/mutex.c +7 -0
 			if (xnthread_test_info(cur, XNBREAK)) {
 				err = -EINTR;
@@ -329,6 +326,13 @@ int pse51_mutex_timedlock_break(struct _
 				break;
 			}
 		}
+		if (!xnsynch_nsleepers(&mutex->synchbase)) {
+			xnarch_atomic_set
+				(mutex->owner,
+				 clear_claimed
+					(xnarch_atomic_get(mutex->owner)));
+			xnsynch_set_owner(&mutex->synchbase, NULL);
+		}

I think an atomic_cmpxchg would be better here.

Quoted 3 lines

Not really. The claimed bit is set, so no one can change the owner without entering the kernel. But there we are also holding nklock. BTW, pse51_mutex_timedlock_internal does the same already.

I meant from an assembly generated code point of view. atomic_set + atomic_get generates two atomic operations (well, except on x86), whereas atomic_cmpxchg is just an atomic sequence. Except that we will have to do the atomic_get also.

And we do not give a damn about this code. It is the implementation of the deadlock that happens when trying to relock a non-recursive mutex.

Signature · 1 line
					    Gilles.
#63 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

In reply to Jan Kiszka

ksrc/skins/posix/mutex.c int pse51_mutex_timedlock_break(struct _ · line 336

Quoted 12 lines · Jan Kiszka
ksrc/skins/posix/mutex.c +7 -0
@@ -329,6 +326,13 @@ int pse51_mutex_timedlock_break(struct _
 				break;
 			}
 		}
+		if (!xnsynch_nsleepers(&mutex->synchbase)) {
+			xnarch_atomic_set
+				(mutex->owner,
+				 clear_claimed
+					(xnarch_atomic_get(mutex->owner)));
+			xnsynch_set_owner(&mutex->synchbase, NULL);
+		}
 		xnlock_put_irqrestore(&nklock, s);

I do not like this at all. I mean, unless I am mistaken, we loose more than we gain, we are adding a couple of atomic, hence heavy, operations in a common case for handling a corner case. I still prefer emitting a system call in the corner case.

Signature · 1 line
					    Gilles.
author
#64 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 10 lines · Gilles Chanteperdrix
Quoted 9 lines · Jan Kiszka
ksrc/skins/posix/mutex.c +5 -0
@@ -329,6 +326,13 @@ int pse51_mutex_timedlock_break(struct _
 				break;
 			}
 		}
+		if (!xnsynch_nsleepers(&mutex->synchbase)) {
+			xnarch_atomic_set
+				(mutex->owner,
+				 clear_claimed
+					(xnarch_atomic_get(mutex->owner)));
Quoted 8 lines

ksrc/skins/posix/mutex.c int pse51_mutex_timedlock_break(struct _ · line 336

Quoted 3 lines
ksrc/skins/posix/mutex.c +2 -0
+			xnsynch_set_owner(&mutex->synchbase, NULL);
+		}
 		xnlock_put_irqrestore(&nklock, s);

I do not like this at all. I mean, unless I am mistaken, we loose more than we gain, we are adding a couple of atomic, hence heavy, operations in a common case for handling a corner case. I still prefer emitting a system call in the corner case.

The hunk above is in the mutex' deadlock path - I wouldn't call this a common case. Moreover, we don't any expensive cmpxchg here.

I haven't counted ops, but my strong feeling is that this patch actually shortens the common code paths + it safely avoids one syscall in the lock stealing case.

Jan

#65 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 19 lines · Jan Kiszka
Quoted 17 lines · Gilles Chanteperdrix

ksrc/skins/posix/mutex.c int pse51_mutex_timedlock_break(struct _ · line 336

Quoted 12 lines · Jan Kiszka
ksrc/skins/posix/mutex.c +7 -0
@@ -329,6 +326,13 @@ int pse51_mutex_timedlock_break(struct _
 				break;
 			}
 		}
+		if (!xnsynch_nsleepers(&mutex->synchbase)) {
+			xnarch_atomic_set
+				(mutex->owner,
+				 clear_claimed
+					(xnarch_atomic_get(mutex->owner)));
+			xnsynch_set_owner(&mutex->synchbase, NULL);
+		}
 		xnlock_put_irqrestore(&nklock, s);

I do not like this at all. I mean, unless I am mistaken, we loose more than we gain, we are adding a couple of atomic, hence heavy, operations in a common case for handling a corner case. I still prefer emitting a system call in the corner case.

Quoted 6 lines

The hunk above is in the mutex' deadlock path - I wouldn't call this a common case. Moreover, we don't any expensive cmpxchg here.

I haven't counted ops, but my strong feeling is that this patch actually shortens the common code paths + it safely avoids one syscall in the lock stealing case.

I have not yet understood how this happens.

Signature · 1 line
                                                 Gilles.
author
#66 lore raw

Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners

Quoted 19 lines · Gilles Chanteperdrix
Quoted 18 lines · Jan Kiszka
Quoted 17 lines · Gilles Chanteperdrix

ksrc/skins/posix/mutex.c int pse51_mutex_timedlock_break(struct _ · line 336

Quoted 12 lines · Jan Kiszka
ksrc/skins/posix/mutex.c +7 -0
@@ -329,6 +326,13 @@ int pse51_mutex_timedlock_break(struct _
 				break;
 			}
 		}
+		if (!xnsynch_nsleepers(&mutex->synchbase)) {
+			xnarch_atomic_set
+				(mutex->owner,
+				 clear_claimed
+					(xnarch_atomic_get(mutex->owner)));
+			xnsynch_set_owner(&mutex->synchbase, NULL);
+		}
 		xnlock_put_irqrestore(&nklock, s);

I do not like this at all. I mean, unless I am mistaken, we loose more than we gain, we are adding a couple of atomic, hence heavy, operations in a common case for handling a corner case. I still prefer emitting a system call in the corner case.

Quoted 8 lines
Quoted 6 lines

The hunk above is in the mutex' deadlock path - I wouldn't call this a common case. Moreover, we don't any expensive cmpxchg here.

I haven't counted ops, but my strong feeling is that this patch actually shortens the common code paths + it safely avoids one syscall in the lock stealing case.

I have not yet understood how this happens.

Argh, it won't work for all cases: When the robbed owner retries the acquisition while the current owner still holds the lock, that clearing of xnsynch_owner has the fatal effect of letting the former thread proceed as well. So we cannot get around to extend xnsynch, teaching it about the two-level ownership management - or actually folding fast lock support into xnsynch.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
author
#67 lore raw

RFC PATCH 3/3 Remove xnarch_atomic_intptr wrappers

In reply to Jan Kiszka

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

---
 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(-)
include/asm-arm/atomic.h +0 -3
Index: 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
include/asm-blackfin/atomic.h +0 -2
Index: 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>
include/asm-generic/Makefile.am +1 -1
Index: 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
include/asm-generic/Makefile.in +1 -1
Index: 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
 
include/asm-generic/atomic.h deleted +0 -24
Index: b/include/asm-generic/atomic.h
===================================================================
@@ -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 */
include/asm-ia64/atomic.h +0 -2
Index: 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>
include/asm-powerpc/atomic.h +0 -2
Index: 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 */
include/asm-x86/atomic.h +0 -2
Index: 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 */