* [Xenomai-core] [RFC][PATCH 0/3] Handle-based fast mutex owner tracking
@ 2008-08-27 13:39 Jan Kiszka
2008-08-27 13:42 ` [Xenomai-core] [RFC][PATCH 1/3] Always register threads by their base Jan Kiszka
` (2 more replies)
0 siblings, 3 replies; 68+ messages in thread
From: Jan Kiszka @ 2008-08-27 13:39 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: xenomai-core
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
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 68+ messages in thread* [Xenomai-core] [RFC][PATCH 1/3] Always register threads by their base 2008-08-27 13:39 [Xenomai-core] [RFC][PATCH 0/3] Handle-based fast mutex owner tracking Jan Kiszka @ 2008-08-27 13:42 ` Jan Kiszka 2008-08-27 14:06 ` [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners Jan Kiszka 2008-08-27 14:08 ` [Xenomai-core] [RFC][PATCH 3/3] Remove xnarch_atomic_intptr wrappers Jan Kiszka 2 siblings, 0 replies; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 13:42 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core 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(-) Index: b/ksrc/skins/native/syscall.c =================================================================== --- a/ksrc/skins/native/syscall.c +++ b/ksrc/skins/native/syscall.c @@ -52,7 +52,8 @@ int __native_muxid; static int __rt_bind_helper(struct task_struct *p, struct pt_regs *regs, xnhandle_t *handlep, - unsigned magic, void **objaddrp) + unsigned magic, void **objaddrp, + unsigned long objoffs) { char name[XNOBJECT_NAME_LEN]; RTIME timeout; @@ -82,7 +83,7 @@ static int __rt_bind_helper(struct task_ /* Also validate the type of the bound object. */ - if (xeno_test_magic(objaddr, magic)) { + if (xeno_test_magic(objaddr + objoffs, magic)) { if (objaddrp) *objaddrp = objaddr; } else @@ -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; Index: b/ksrc/skins/native/task.c =================================================================== --- a/ksrc/skins/native/task.c +++ 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) Index: b/ksrc/skins/psos+/syscall.c =================================================================== --- a/ksrc/skins/psos+/syscall.c +++ 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); Index: b/ksrc/skins/psos+/task.c =================================================================== --- a/ksrc/skins/psos+/task.c +++ 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; Index: b/ksrc/skins/vxworks/syscall.c =================================================================== --- a/ksrc/skins/vxworks/syscall.c +++ 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; Index: b/ksrc/skins/vxworks/taskLib.c =================================================================== --- a/ksrc/skins/vxworks/taskLib.c +++ 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; ^ permalink raw reply [flat|nested] 68+ messages in thread
* [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 13:39 [Xenomai-core] [RFC][PATCH 0/3] Handle-based fast mutex owner tracking Jan Kiszka 2008-08-27 13:42 ` [Xenomai-core] [RFC][PATCH 1/3] Always register threads by their base Jan Kiszka @ 2008-08-27 14:06 ` Jan Kiszka 2008-08-27 14:14 ` Gilles Chanteperdrix 2008-08-27 14:36 ` Gilles Chanteperdrix 2008-08-27 14:08 ` [Xenomai-core] [RFC][PATCH 3/3] Remove xnarch_atomic_intptr wrappers Jan Kiszka 2 siblings, 2 replies; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 14:06 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core 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(-) Index: b/include/asm-generic/bits/current.h =================================================================== --- a/include/asm-generic/bits/current.h +++ b/include/asm-generic/bits/current.h @@ -2,14 +2,15 @@ #define _XENO_ASM_GENERIC_CURRENT_H #include <pthread.h> +#include <nucleus/types.h> extern pthread_key_t xeno_current_key; extern void xeno_set_current(void); -static inline void *xeno_get_current(void) +static inline xnhandle_t xeno_get_current(void) { - return pthread_getspecific(xeno_current_key); + return (xnhandle_t)pthread_getspecific(xeno_current_key); } #endif /* _XENO_ASM_GENERIC_CURRENT_H */ Index: b/include/nucleus/types.h =================================================================== --- a/include/nucleus/types.h +++ b/include/nucleus/types.h @@ -61,6 +61,19 @@ typedef unsigned long xnhandle_t; #define XN_NO_HANDLE ((xnhandle_t)0) +#define XN_HANDLE_SPARE0 ((xnhandle_t)0x10000000) +#define XN_HANDLE_SPARE1 ((xnhandle_t)0x20000000) +#define XN_HANDLE_SPARE2 ((xnhandle_t)0x40000000) +#define XN_HANDLE_SPARE3 ((xnhandle_t)0x80000000) +#define XN_HANDLE_SPARE_MASK ((xnhandle_t)0xf0000000) + +#define xnhandle_mask_spare(handle) ((handle) & ~XN_HANDLE_SPARE_MASK) +#define xnhandle_test_spare(handle, bits) (!!((handle) & (bits))) +#define xnhandle_set_spare(handle, bits) \ + do { (handle) |= (bits); } while (0) +#define xnhandle_clear_spare(handle, bits) \ + do { (handle) &= ~(bits); } while (0) + struct xnintr; typedef int (*xnisr_t)(struct xnintr *intr); Index: b/ksrc/nucleus/shadow.c =================================================================== --- a/ksrc/nucleus/shadow.c +++ b/ksrc/nucleus/shadow.c @@ -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) Index: b/ksrc/skins/posix/cb_lock.h =================================================================== --- a/ksrc/skins/posix/cb_lock.h +++ b/ksrc/skins/posix/cb_lock.h @@ -3,15 +3,22 @@ #include <asm/xenomai/atomic.h> #include <nucleus/compiler.h> +#include <nucleus/types.h> #ifndef __KERNEL__ typedef void xnthread_t; #endif /* __KERNEL__ */ -#define test_claimed(owner) ((long) (owner) & 1) -#define clear_claimed(owner) ((xnthread_t *) ((long) (owner) & ~1)) -#define set_claimed(owner, bit) \ - ((xnthread_t *) ((long) clear_claimed(owner) | !!(bit))) +#define __CLAIMED_BIT XN_HANDLE_SPARE3 + +#define test_claimed(owner) xnhandle_test_spare(owner, __CLAIMED_BIT) +#define clear_claimed(owner) xnhandle_mask_spare(owner) +#define set_claimed(owner, bit) ({ \ + xnhandle_t __tmp = xnhandle_mask_spare(owner); \ + if (bit) \ + xnhandle_set_spare(__tmp, __CLAIMED_BIT); \ + __tmp; \ +}) #ifdef CONFIG_XENO_FASTSEM Index: b/ksrc/skins/posix/cond.c =================================================================== --- a/ksrc/skins/posix/cond.c +++ b/ksrc/skins/posix/cond.c @@ -230,18 +230,20 @@ static inline int mutex_save_count(xnthr mutex = shadow->mutex; - if (clear_claimed(xnarch_atomic_intptr_get(mutex->owner)) != cur) + if (clear_claimed(xnarch_atomic_get(mutex->owner)) != + xnthread_handle(cur)) return EPERM; *count_ptr = shadow->lockcnt; - if (likely(xnarch_atomic_intptr_cmpxchg(mutex->owner, cur, NULL) == cur)) + if (likely(xnarch_atomic_cmpxchg(mutex->owner, cur, XN_NO_HANDLE) == + xnthread_handle(cur))) return 0; owner = xnsynch_wakeup_one_sleeper(&mutex->synchbase); - xnarch_atomic_intptr_set - (mutex->owner, - set_claimed(owner,xnsynch_nsleepers(&mutex->synchbase))); + xnarch_atomic_set(mutex->owner, + set_claimed(xnthread_handle(owner), + xnsynch_nsleepers(&mutex->synchbase))); /* Do not reschedule here, releasing the mutex and suspension must be done atomically in pthread_cond_*wait. */ Index: b/ksrc/skins/posix/mutex.c =================================================================== --- a/ksrc/skins/posix/mutex.c +++ b/ksrc/skins/posix/mutex.c @@ -82,7 +82,7 @@ int pse51_mutex_check_init(struct __shad int pse51_mutex_init_internal(struct __shadow_mutex *shadow, pse51_mutex_t *mutex, - xnarch_atomic_intptr_t *ownerp, + xnarch_atomic_t *ownerp, const pthread_mutexattr_t *attr) { xnflags_t synch_flags = XNSYNCH_PRIO | XNSYNCH_NOPIP; @@ -118,7 +118,7 @@ int pse51_mutex_init_internal(struct __s mutex->owner = ownerp; mutex->owningq = kq; mutex->sleepers = 0; - xnarch_atomic_intptr_set(ownerp, NULL); + xnarch_atomic_set(ownerp, XN_NO_HANDLE); xnlock_get_irqsave(&nklock, s); appendq(&kq->mutexq, &mutex->link); @@ -159,7 +159,7 @@ int pthread_mutex_init(pthread_mutex_t * &((union __xeno_mutex *)mx)->shadow_mutex; DECLARE_CB_LOCK_FLAGS(s); pse51_mutex_t *mutex; - xnarch_atomic_intptr_t *ownerp; + xnarch_atomic_t *ownerp; int err; if (!attr) @@ -185,9 +185,9 @@ int pthread_mutex_init(pthread_mutex_t * if (!mutex) return ENOMEM; - ownerp = (xnarch_atomic_intptr_t *) + ownerp = (xnarch_atomic_t *) xnheap_alloc(&xnsys_ppd_get(attr->pshared)->sem_heap, - sizeof(xnarch_atomic_intptr_t)); + sizeof(xnarch_atomic_t)); if (!ownerp) { xnfree(mutex); return EAGAIN; @@ -266,7 +266,7 @@ int pthread_mutex_destroy(pthread_mutex_ return EPERM; } - if (xnarch_atomic_intptr_get(mutex->owner)) { + if (xnarch_atomic_get(mutex->owner)) { 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; } Index: b/ksrc/skins/posix/mutex.h =================================================================== --- a/ksrc/skins/posix/mutex.h +++ b/ksrc/skins/posix/mutex.h @@ -34,7 +34,7 @@ union __xeno_mutex { xnarch_atomic_t lock; union { unsigned owner_offset; - xnarch_atomic_intptr_t *owner; + xnarch_atomic_t *owner; }; struct pse51_mutexattr attr; #endif /* CONFIG_XENO_FASTSEM */ @@ -43,6 +43,7 @@ union __xeno_mutex { #ifdef __KERNEL__ +#include <nucleus/registry.h> #include <posix/internal.h> #include <posix/thread.h> #include <posix/cb_lock.h> @@ -54,7 +55,7 @@ typedef struct pse51_mutex { #define link2mutex(laddr) \ ((pse51_mutex_t *)(((char *)laddr) - offsetof(pse51_mutex_t, link))) - xnarch_atomic_intptr_t *owner; + xnarch_atomic_t *owner; pthread_mutexattr_t attr; unsigned sleepers; pse51_kqueues_t *owningq; @@ -77,7 +78,7 @@ int pse51_mutex_check_init(struct __shad int pse51_mutex_init_internal(struct __shadow_mutex *shadow, pse51_mutex_t *mutex, - xnarch_atomic_intptr_t *ownerp, + xnarch_atomic_t *ownerp, const pthread_mutexattr_t *attr); void pse51_mutex_destroy_internal(pse51_mutex_t *mutex, @@ -88,6 +89,7 @@ pse51_mutex_trylock_internal(xnthread_t struct __shadow_mutex *shadow, unsigned count) { pse51_mutex_t *mutex = shadow->mutex; + xnhandle_t ownerh; xnthread_t *owner; if (xnpod_unblockable_p()) @@ -101,9 +103,14 @@ pse51_mutex_trylock_internal(xnthread_t return ERR_PTR(-EPERM); #endif /* XENO_DEBUG(POSIX) */ - owner = xnarch_atomic_intptr_cmpxchg(mutex->owner, NULL, cur); - if (unlikely(owner != NULL)) + ownerh = xnarch_atomic_cmpxchg(mutex->owner, XN_NO_HANDLE, + xnthread_handle(cur)); + if (unlikely(ownerh)) { + owner = xnregistry_fetch(clear_claimed(ownerh)); + if (!owner) + return ERR_PTR(-EINVAL); return owner; + } shadow->lockcnt = count; return NULL; @@ -118,7 +125,8 @@ static inline int pse51_mutex_timedlock_ { pse51_mutex_t *mutex; - xnthread_t *owner, *old; + xnthread_t *owner; + xnhandle_t ownerh, old; spl_t s; int err; @@ -128,27 +136,42 @@ static inline int pse51_mutex_timedlock_ return PTR_ERR(owner); mutex = shadow->mutex; - if (clear_claimed(owner) == cur) + if (owner == cur) return -EBUSY; /* Set bit 0, so that mutex_unlock will know that the mutex is claimed. Hold the nklock, for mutual exclusion with slow mutex_unlock. */ xnlock_get_irqsave(&nklock, s); - while(!test_claimed(owner)) { - old = xnarch_atomic_intptr_cmpxchg(mutex->owner, - owner, set_claimed(owner, 1)); - if (likely(old == owner)) + + ownerh = xnarch_atomic_get(mutex->owner); + while (!test_claimed(ownerh)) { + old = xnarch_atomic_cmpxchg(mutex->owner, ownerh, + set_claimed(ownerh, 1)); + if (likely(old == ownerh)) break; - if (old == NULL) { + if (old == 0) { /* Owner called fast mutex_unlock (on another cpu) */ xnlock_put_irqrestore(&nklock, s); goto retry_lock; } - owner = old; + + ownerh = old; + owner = xnregistry_fetch(clear_claimed(ownerh)); + + if (unlikely(!owner)) { + err = -EINVAL; + goto error; + } + } + + /* Consistency check for owner handle - is the object a thread? */ + if (unlikely(xnthread_handle(owner) != clear_claimed(ownerh))) { + err = -EINVAL; + goto error; } - xnsynch_set_owner(&mutex->synchbase, clear_claimed(owner)); + xnsynch_set_owner(&mutex->synchbase, owner); ++mutex->sleepers; if (timed) xnsynch_sleep_on(&mutex->synchbase, abs_to, XN_REALTIME); @@ -169,7 +192,8 @@ static inline int pse51_mutex_timedlock_ goto error; } - xnarch_atomic_intptr_set(mutex->owner,set_claimed(cur, mutex->sleepers)); + ownerh = set_claimed(xnthread_handle(cur), mutex->sleepers); + xnarch_atomic_set(mutex->owner, ownerh); shadow->lockcnt = count; xnlock_put_irqrestore(&nklock, s); @@ -177,9 +201,9 @@ static inline int pse51_mutex_timedlock_ error: if (!mutex->sleepers) - xnarch_atomic_intptr_set + xnarch_atomic_set (mutex->owner, - clear_claimed(xnarch_atomic_intptr_get(mutex->owner))); + clear_claimed(xnarch_atomic_get(mutex->owner))); xnlock_put_irqrestore(&nklock, s); return err; } @@ -187,16 +211,18 @@ static inline int pse51_mutex_timedlock_ static inline void pse51_mutex_unlock_internal(xnthread_t *cur, pse51_mutex_t *mutex) { + xnhandle_t ownerh; xnthread_t *owner; spl_t s; - if (likely(xnarch_atomic_intptr_cmpxchg(mutex->owner, cur, NULL) == cur)) + if (likely(xnarch_atomic_cmpxchg(mutex->owner, cur, XN_NO_HANDLE) == + xnthread_handle(cur))) return; xnlock_get_irqsave(&nklock, s); owner = xnsynch_wakeup_one_sleeper(&mutex->synchbase); - xnarch_atomic_intptr_set(mutex->owner, - set_claimed(owner, mutex->sleepers)); + ownerh = set_claimed(xnthread_handle(owner), mutex->sleepers); + xnarch_atomic_set(mutex->owner, ownerh); if (owner) xnpod_schedule(); xnlock_put_irqrestore(&nklock, s); Index: b/ksrc/skins/posix/syscall.c =================================================================== --- a/ksrc/skins/posix/syscall.c +++ b/ksrc/skins/posix/syscall.c @@ -1060,7 +1060,8 @@ static int __pthread_mutex_unlock(struct mutex = shadow->mutex; - if (clear_claimed(xnarch_atomic_intptr_get(mutex->owner)) != cur) { + if (clear_claimed(xnarch_atomic_get(mutex->owner)) != + xnthread_handle(cur)) { err = -EPERM; goto out; } @@ -1119,7 +1120,7 @@ static int __pthread_mutex_init(struct p pthread_mutexattr_t locattr, *attr, *uattrp; union __xeno_mutex mx, *umx; pse51_mutex_t *mutex; - xnarch_atomic_intptr_t *ownerp; + xnarch_atomic_t *ownerp; int err; umx = (union __xeno_mutex *)__xn_reg_arg1(regs); @@ -1144,9 +1145,9 @@ static int __pthread_mutex_init(struct p if (!mutex) return -ENOMEM; - ownerp = (xnarch_atomic_intptr_t *) + ownerp = (xnarch_atomic_t *) xnheap_alloc(&xnsys_ppd_get(attr->pshared)->sem_heap, - sizeof(xnarch_atomic_intptr_t)); + sizeof(xnarch_atomic_t)); if (!ownerp) { xnfree(mutex); return -EAGAIN; @@ -1185,7 +1186,7 @@ static int __pthread_mutex_destroy(struc if (pse51_kqueues(mutex->attr.pshared) != mutex->owningq) return -EPERM; - if (xnarch_atomic_intptr_get(mutex->owner)) + if (xnarch_atomic_get(mutex->owner)) return -EBUSY; pse51_mark_deleted(shadow); Index: b/src/skins/posix/mutex.c =================================================================== --- a/src/skins/posix/mutex.c +++ b/src/skins/posix/mutex.c @@ -31,12 +31,12 @@ extern int __pse51_muxid; extern unsigned long xeno_sem_heap[2]; -static xnarch_atomic_intptr_t *get_ownerp(struct __shadow_mutex *shadow) +static xnarch_atomic_t *get_ownerp(struct __shadow_mutex *shadow) { if (likely(!shadow->attr.pshared)) return shadow->owner; - return (xnarch_atomic_intptr_t *) (xeno_sem_heap[1] + shadow->owner_offset); + return (xnarch_atomic_t *) (xeno_sem_heap[1] + shadow->owner_offset); } #endif /* CONFIG_XENO_FASTSEM */ @@ -117,7 +117,7 @@ int __wrap_pthread_mutex_init(pthread_mu #ifdef CONFIG_XENO_FASTSEM if (!shadow->attr.pshared) - shadow->owner = (xnarch_atomic_intptr_t *) + shadow->owner = (xnarch_atomic_t *) (xeno_sem_heap[0] + shadow->owner_offset); cb_write_unlock(&shadow->lock, s); @@ -149,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; Index: b/ksrc/skins/posix/thread.c =================================================================== --- a/ksrc/skins/posix/thread.c +++ 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; Index: b/ksrc/skins/posix/Kconfig =================================================================== --- a/ksrc/skins/posix/Kconfig +++ b/ksrc/skins/posix/Kconfig @@ -1,5 +1,6 @@ menuconfig XENO_SKIN_POSIX depends on XENO_OPT_NUCLEUS + select XENO_OPT_REGISTRY if XENO_FASTSEM tristate "POSIX API" default y help Index: b/include/asm-generic/bits/bind.h =================================================================== --- a/include/asm-generic/bits/bind.h +++ b/include/asm-generic/bits/bind.h @@ -22,7 +22,14 @@ __attribute__ ((weak)) void xeno_set_current(void) { void *kthread_cb; - XENOMAI_SYSCALL1(__xn_sys_current, &kthread_cb); + int err; + + err = XENOMAI_SYSCALL1(__xn_sys_current, &kthread_cb); + if (err) { + fprintf(stderr, "Xenomai: error obtaining handle for current " + "thread: %s\n", strerror(err)); + exit(1); + } pthread_setspecific(xeno_current_key, kthread_cb); } ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:06 ` [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners Jan Kiszka @ 2008-08-27 14:14 ` Gilles Chanteperdrix 2008-08-27 14:38 ` Jan Kiszka 2008-08-27 14:36 ` Gilles Chanteperdrix 1 sibling, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 14:14 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > 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... -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:14 ` Gilles Chanteperdrix @ 2008-08-27 14:38 ` Jan Kiszka 2008-08-27 14:44 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 14:38 UTC (permalink / raw) To: gilles.chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> 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... 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(+) Index: b/src/skins/native/task.c =================================================================== --- a/src/skins/native/task.c +++ b/src/skins/native/task.c @@ -26,6 +26,7 @@ #include <limits.h> #include <native/syscall.h> #include <native/task.h> +#include <asm-generic/bits/current.h> #include "wrappers.h" extern pthread_key_t __native_tskey; @@ -88,6 +89,8 @@ static void *rt_task_trampoline(void *co if (err) goto fail; + xeno_set_current(); + /* Wait on the barrier for the task to be started. The barrier could be released in order to process Linux signals while the Xenomai shadow is still dormant; in such a case, resume wait. */ Index: b/src/skins/psos+/task.c =================================================================== --- a/src/skins/psos+/task.c +++ b/src/skins/psos+/task.c @@ -26,6 +26,7 @@ #include <memory.h> #include <string.h> #include <psos+/psos.h> +#include <asm-generic/bits/current.h> extern int __psos_muxid; @@ -89,6 +90,8 @@ static void *psos_task_trampoline(void * if (err) goto fail; + xeno_set_current(); + /* Wait on the barrier for the task to be started. The barrier could be released in order to process Linux signals while the Xenomai shadow is still dormant; in such a case, resume wait. */ Index: b/src/skins/uitron/task.c =================================================================== --- a/src/skins/uitron/task.c +++ b/src/skins/uitron/task.c @@ -25,6 +25,7 @@ #include <limits.h> #include <asm/xenomai/system.h> #include <uitron/uitron.h> +#include <asm-generic/bits/current.h> extern int __uitron_muxid; @@ -89,6 +90,8 @@ static void *uitron_task_trampoline(void if (err) goto fail; + xeno_set_current(); + /* iargs->pk_ctsk might not be valid anymore, after our parent was released from the completion sync, so do not dereference this pointer. */ Index: b/src/skins/vrtx/task.c =================================================================== --- a/src/skins/vrtx/task.c +++ b/src/skins/vrtx/task.c @@ -27,6 +27,7 @@ #include <errno.h> #include <limits.h> #include <vrtx/vrtx.h> +#include <asm-generic/bits/current.h> extern pthread_key_t __vrtx_tskey; @@ -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. */ Index: b/src/skins/vxworks/taskLib.c =================================================================== --- a/src/skins/vxworks/taskLib.c +++ b/src/skins/vxworks/taskLib.c @@ -27,6 +27,7 @@ #include <errno.h> #include <limits.h> #include <vxworks/vxworks.h> +#include <asm-generic/bits/current.h> #include "wrappers.h" extern pthread_key_t __vxworks_tskey; @@ -117,6 +118,8 @@ static void *wind_task_trampoline(void * if (err) goto fail; + xeno_set_current(); + /* Wait on the barrier for the task to be started. The barrier could be released in order to process Linux signals while the Xenomai shadow is still dormant; in such a case, resume wait. */ ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:38 ` Jan Kiszka @ 2008-08-27 14:44 ` Gilles Chanteperdrix 2008-08-27 14:49 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 14:44 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> 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... > > 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:44 ` Gilles Chanteperdrix @ 2008-08-27 14:49 ` Jan Kiszka 2008-08-27 14:57 ` Gilles Chanteperdrix 2008-08-27 23:49 ` Gilles Chanteperdrix 0 siblings, 2 replies; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 14:49 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> 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... >> 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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:49 ` Jan Kiszka @ 2008-08-27 14:57 ` Gilles Chanteperdrix 2008-08-27 23:49 ` Gilles Chanteperdrix 1 sibling, 0 replies; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 14:57 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>>> 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... >>> 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. Then it looks redundant with the code that does associate a handle with a new thread in the posix skin. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:49 ` Jan Kiszka 2008-08-27 14:57 ` Gilles Chanteperdrix @ 2008-08-27 23:49 ` Gilles Chanteperdrix 1 sibling, 0 replies; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 23:49 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>>> 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... >>> 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. 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:06 ` [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners Jan Kiszka 2008-08-27 14:14 ` Gilles Chanteperdrix @ 2008-08-27 14:36 ` Gilles Chanteperdrix 2008-08-27 14:45 ` Jan Kiszka 2008-08-27 15:20 ` Jan Kiszka 1 sibling, 2 replies; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 14:36 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > -#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; \ > +}) I liked doing this with no conditional. > + 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. > + /* 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 ? > Index: b/ksrc/skins/posix/thread.c > =================================================================== > --- a/ksrc/skins/posix/thread.c > +++ 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 */ > + 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 ? -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:36 ` Gilles Chanteperdrix @ 2008-08-27 14:45 ` Jan Kiszka 2008-08-27 14:47 ` Gilles Chanteperdrix ` (2 more replies) 2008-08-27 15:20 ` Jan Kiszka 1 sibling, 3 replies; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 14:45 UTC (permalink / raw) To: gilles.chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: > >> -#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; \ >> +}) > > 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)? > >> + 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. > >> + /* 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). > > >> Index: b/ksrc/skins/posix/thread.c >> =================================================================== >> --- a/ksrc/skins/posix/thread.c >> +++ 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 */ >> + > > 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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:45 ` Jan Kiszka @ 2008-08-27 14:47 ` Gilles Chanteperdrix 2008-08-27 14:51 ` Jan Kiszka 2008-08-27 14:48 ` Gilles Chanteperdrix 2008-08-27 14:50 ` Gilles Chanteperdrix 2 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 14:47 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >> >>> -#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; \ >>> +}) >> 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)? > >>> + 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. > >>> + /* 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). Yes, but the point is: how can the handle be borken ? It looks like a useless check to me. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:47 ` Gilles Chanteperdrix @ 2008-08-27 14:51 ` Jan Kiszka 2008-08-27 14:55 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 14:51 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>> >>>> -#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; \ >>>> +}) >>> 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)? >> >>>> + 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. >> >>>> + /* 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). > > 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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:51 ` Jan Kiszka @ 2008-08-27 14:55 ` Gilles Chanteperdrix 2008-08-27 15:00 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 14:55 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>> >>>>> -#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; \ >>>>> +}) >>>> 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)? >>> >>>>> + 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. >>> >>>>> + /* 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). >> 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)). -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:55 ` Gilles Chanteperdrix @ 2008-08-27 15:00 ` Jan Kiszka 2008-08-27 15:04 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 15:00 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> Gilles Chanteperdrix wrote: >>>>> Jan Kiszka wrote: >>>>> >>>>>> -#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; \ >>>>>> +}) >>>>> 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)? >>>> >>>>>> + 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. >>>> >>>>>> + /* 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). >>> 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)). 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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:00 ` Jan Kiszka @ 2008-08-27 15:04 ` Gilles Chanteperdrix 2008-08-27 15:10 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 15:04 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>>> Gilles Chanteperdrix wrote: >>>>>> Jan Kiszka wrote: >>>>>> >>>>>>> -#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; \ >>>>>>> +}) >>>>>> 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)? >>>>> >>>>>>> + 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. >>>>> >>>>>>> + /* 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). >>>> 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)). > > 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... -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:04 ` Gilles Chanteperdrix @ 2008-08-27 15:10 ` Jan Kiszka 2008-08-27 15:13 ` Gilles Chanteperdrix 2008-08-27 15:15 ` Gilles Chanteperdrix 0 siblings, 2 replies; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 15:10 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> Gilles Chanteperdrix wrote: >>>>> Jan Kiszka wrote: >>>>>> Gilles Chanteperdrix wrote: >>>>>>> Jan Kiszka wrote: >>>>>>> >>>>>>>> -#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; \ >>>>>>>> +}) >>>>>>> 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)? >>>>>> >>>>>>>> + 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. >>>>>> >>>>>>>> + /* 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). >>>>> 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)). >> 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... 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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:10 ` Jan Kiszka @ 2008-08-27 15:13 ` Gilles Chanteperdrix 2008-08-27 15:15 ` Gilles Chanteperdrix 1 sibling, 0 replies; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 15:13 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>>> Gilles Chanteperdrix wrote: >>>>>> Jan Kiszka wrote: >>>>>>> Gilles Chanteperdrix wrote: >>>>>>>> Jan Kiszka wrote: >>>>>>>> >>>>>>>>> -#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; \ >>>>>>>>> +}) >>>>>>>> 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)? >>>>>>> >>>>>>>>> + 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. >>>>>>> >>>>>>>>> + /* 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). >>>>>> 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)). >>> 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... > > 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:10 ` Jan Kiszka 2008-08-27 15:13 ` Gilles Chanteperdrix @ 2008-08-27 15:15 ` Gilles Chanteperdrix 2008-08-27 15:18 ` Jan Kiszka 1 sibling, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 15:15 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:15 ` Gilles Chanteperdrix @ 2008-08-27 15:18 ` Jan Kiszka 2008-08-27 15:29 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 15:18 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> 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. >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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:18 ` Jan Kiszka @ 2008-08-27 15:29 ` Gilles Chanteperdrix 2008-08-27 15:34 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 15:29 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> 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. > > 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:29 ` Gilles Chanteperdrix @ 2008-08-27 15:34 ` Jan Kiszka 2008-08-27 15:36 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 15:34 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> 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. >> 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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:34 ` Jan Kiszka @ 2008-08-27 15:36 ` Gilles Chanteperdrix 2008-08-27 15:37 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 15:36 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>>> 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. >>> 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... -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:36 ` Gilles Chanteperdrix @ 2008-08-27 15:37 ` Jan Kiszka 2008-08-27 23:44 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 15:37 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> Gilles Chanteperdrix wrote: >>>>> Jan Kiszka wrote: >>>>>> 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. >>>> 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... Handle lookup is not going through hash tables. It's index based (like file descriptors). Jan -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:37 ` Jan Kiszka @ 2008-08-27 23:44 ` Gilles Chanteperdrix 0 siblings, 0 replies; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 23:44 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>>> Gilles Chanteperdrix wrote: >>>>>> Jan Kiszka wrote: >>>>>>> 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. >>>>> 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... > > 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:45 ` Jan Kiszka 2008-08-27 14:47 ` Gilles Chanteperdrix @ 2008-08-27 14:48 ` Gilles Chanteperdrix 2008-08-27 14:50 ` Gilles Chanteperdrix 2 siblings, 0 replies; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 14:48 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >> >>> -#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; \ >>> +}) >> 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)? > >>> + 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. > >>> + /* 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). > >> >>> Index: b/ksrc/skins/posix/thread.c >>> =================================================================== >>> --- a/ksrc/skins/posix/thread.c >>> +++ 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 */ >>> + >> 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. Ok. But we need to add the register in all skins then. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:45 ` Jan Kiszka 2008-08-27 14:47 ` Gilles Chanteperdrix 2008-08-27 14:48 ` Gilles Chanteperdrix @ 2008-08-27 14:50 ` Gilles Chanteperdrix 2 siblings, 0 replies; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 14:50 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >> >>> -#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; \ >>> +}) >> 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)? the if is ok. I guess the compiler does !! with an if too... -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 14:36 ` Gilles Chanteperdrix 2008-08-27 14:45 ` Jan Kiszka @ 2008-08-27 15:20 ` Jan Kiszka 2008-08-27 15:28 ` Gilles Chanteperdrix 1 sibling, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 15:20 UTC (permalink / raw) To: gilles.chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > 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. Jan -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:20 ` Jan Kiszka @ 2008-08-27 15:28 ` Gilles Chanteperdrix 2008-08-27 15:43 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 15:28 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> 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. 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). -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:28 ` Gilles Chanteperdrix @ 2008-08-27 15:43 ` Jan Kiszka 2008-08-27 15:46 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 15:43 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> 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. > > 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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:43 ` Jan Kiszka @ 2008-08-27 15:46 ` Gilles Chanteperdrix 2008-08-27 16:08 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 15:46 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> 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. >> 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 15:46 ` Gilles Chanteperdrix @ 2008-08-27 16:08 ` Jan Kiszka 2008-08-27 16:13 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 16:08 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> Gilles Chanteperdrix wrote: >>>>> 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. >>> 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! 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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 16:08 ` Jan Kiszka @ 2008-08-27 16:13 ` Gilles Chanteperdrix 2008-08-27 18:15 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 16:13 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>>> Gilles Chanteperdrix wrote: >>>>>> 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. >>>> 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! > > 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 16:13 ` Gilles Chanteperdrix @ 2008-08-27 18:15 ` Jan Kiszka 2008-08-27 19:02 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 18:15 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core [-- Attachment #1: Type: text/plain, Size: 3788 bytes --] Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> Gilles Chanteperdrix wrote: >>>>> Jan Kiszka wrote: >>>>>> Gilles Chanteperdrix wrote: >>>>>>> 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. >>>>> 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! >> >> 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 [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 257 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 18:15 ` Jan Kiszka @ 2008-08-27 19:02 ` Gilles Chanteperdrix 2008-08-27 19:04 ` Gilles Chanteperdrix 2008-08-27 20:33 ` Jan Kiszka 0 siblings, 2 replies; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 19:02 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>>> Gilles Chanteperdrix wrote: >>>>>> Jan Kiszka wrote: >>>>>>> Gilles Chanteperdrix wrote: >>>>>>>> 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. >>>>>> 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! >>> >>> 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. 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". -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 19:02 ` Gilles Chanteperdrix @ 2008-08-27 19:04 ` Gilles Chanteperdrix 2008-08-27 20:35 ` Jan Kiszka 2008-08-27 20:33 ` Jan Kiszka 1 sibling, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 19:04 UTC (permalink / raw) To: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> Gilles Chanteperdrix wrote: >>>>> Jan Kiszka wrote: >>>>>> Gilles Chanteperdrix wrote: >>>>>>> Jan Kiszka wrote: >>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>> 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. >>>>>>> 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! >>>> >>>> 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. > > 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". 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 19:04 ` Gilles Chanteperdrix @ 2008-08-27 20:35 ` Jan Kiszka 2008-08-27 21:26 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 20:35 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core [-- Attachment #1: Type: text/plain, Size: 5387 bytes --] Gilles Chanteperdrix wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>>> Gilles Chanteperdrix wrote: >>>>>> Jan Kiszka wrote: >>>>>>> Gilles Chanteperdrix wrote: >>>>>>>> Jan Kiszka wrote: >>>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>>> 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. >>>>>>>> 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! >>>>> >>>>> 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. >> 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". > > 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 [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 257 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 20:35 ` Jan Kiszka @ 2008-08-27 21:26 ` Gilles Chanteperdrix 2008-08-27 21:46 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 21:26 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> Gilles Chanteperdrix wrote: >>>>> Jan Kiszka wrote: >>>>>> Gilles Chanteperdrix wrote: >>>>>>> Jan Kiszka wrote: >>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>> Jan Kiszka wrote: >>>>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>>>> 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. >>>>>>>>> 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! >>>>>> >>>>>> 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. >>> 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". >> 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. 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 21:26 ` Gilles Chanteperdrix @ 2008-08-27 21:46 ` Jan Kiszka 2008-08-27 21:55 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 21:46 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core [-- Attachment #1: Type: text/plain, Size: 6149 bytes --] Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>>> Gilles Chanteperdrix wrote: >>>>>> Jan Kiszka wrote: >>>>>>> Gilles Chanteperdrix wrote: >>>>>>>> Jan Kiszka wrote: >>>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>>> Jan Kiszka wrote: >>>>>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>>>>> 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. >>>>>>>>>> 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! >>>>>>> >>>>>>> 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. >>>> 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". >>> 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. > > 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 [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 257 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 21:46 ` Jan Kiszka @ 2008-08-27 21:55 ` Gilles Chanteperdrix 0 siblings, 0 replies; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 21:55 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Gilles Chanteperdrix wrote: >>>>> Jan Kiszka wrote: >>>>>> Gilles Chanteperdrix wrote: >>>>>>> Jan Kiszka wrote: >>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>> Jan Kiszka wrote: >>>>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>>>> Jan Kiszka wrote: >>>>>>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>>>>>> 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. >>>>>>>>>>> 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! >>>>>>>> >>>>>>>> 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. >>>>> 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". >>>> 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. >> 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 => jan.kiszka@domain.hid 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 => xenomai@xenomai.org R=dnslookup T=remote_smtp H=mail.gna.org [88.191.250.46]* 2008-08-27 17:13:08 1KYMR8-0004Uw-2w Completed -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 19:02 ` Gilles Chanteperdrix 2008-08-27 19:04 ` Gilles Chanteperdrix @ 2008-08-27 20:33 ` Jan Kiszka 2008-08-27 22:45 ` Gilles Chanteperdrix ` (2 more replies) 1 sibling, 3 replies; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 20:33 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core [-- Attachment #1: Type: text/plain, Size: 5947 bytes --] 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. 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 =================================================================== --- a/ksrc/skins/posix/mutex.c +++ 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; Index: b/ksrc/skins/posix/mutex.h =================================================================== --- a/ksrc/skins/posix/mutex.h +++ 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(); [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 257 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 20:33 ` Jan Kiszka @ 2008-08-27 22:45 ` Gilles Chanteperdrix 2008-08-28 10:01 ` Philippe Gerum 2008-08-27 23:05 ` Gilles Chanteperdrix 2008-08-27 23:14 ` Gilles Chanteperdrix 2 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 22:45 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 22:45 ` Gilles Chanteperdrix @ 2008-08-28 10:01 ` Philippe Gerum 2008-08-28 10:37 ` Jan Kiszka 2008-08-28 12:21 ` Gilles Chanteperdrix 0 siblings, 2 replies; 68+ messages in thread From: Philippe Gerum @ 2008-08-28 10:01 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: Jan Kiszka, xenomai-core 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. -- Philippe. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-28 10:01 ` Philippe Gerum @ 2008-08-28 10:37 ` Jan Kiszka 2008-08-28 10:52 ` Philippe Gerum 2008-08-28 12:21 ` Gilles Chanteperdrix 1 sibling, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-28 10:37 UTC (permalink / raw) To: rpm; +Cc: xenomai-core Philippe Gerum wrote: > 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. ... 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. > > 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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-28 10:37 ` Jan Kiszka @ 2008-08-28 10:52 ` Philippe Gerum 0 siblings, 0 replies; 68+ messages in thread From: Philippe Gerum @ 2008-08-28 10:52 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Philippe Gerum wrote: >> 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. > > ... 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 > 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... >> 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... > This is why I don't think moving part of the core logic to the skins would be a good idea. > Jan > -- Philippe. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-28 10:01 ` Philippe Gerum 2008-08-28 10:37 ` Jan Kiszka @ 2008-08-28 12:21 ` Gilles Chanteperdrix 2008-08-29 6:41 ` Jan Kiszka 1 sibling, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-28 12:21 UTC (permalink / raw) To: rpm; +Cc: Jan Kiszka, xenomai-core Philippe Gerum wrote: > 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. 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-28 12:21 ` Gilles Chanteperdrix @ 2008-08-29 6:41 ` Jan Kiszka 2008-08-29 7:00 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-29 6:41 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core [-- Attachment #1: Type: text/plain, Size: 5582 bytes --] Gilles Chanteperdrix wrote: > Philippe Gerum wrote: >> 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. > > 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). > 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. > > 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. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 257 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-29 6:41 ` Jan Kiszka @ 2008-08-29 7:00 ` Gilles Chanteperdrix 2008-08-29 7:22 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-29 7:00 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Philippe Gerum wrote: >>> 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. >> 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-29 7:00 ` Gilles Chanteperdrix @ 2008-08-29 7:22 ` Jan Kiszka 2008-08-29 7:29 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-29 7:22 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core [-- Attachment #1: Type: text/plain, Size: 4801 bytes --] Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Philippe Gerum wrote: >>>> 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. >>> 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 [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 258 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-29 7:22 ` Jan Kiszka @ 2008-08-29 7:29 ` Gilles Chanteperdrix 2008-08-29 9:36 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-29 7:29 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Philippe Gerum wrote: >>>>> 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. >>>> 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-29 7:29 ` Gilles Chanteperdrix @ 2008-08-29 9:36 ` Jan Kiszka 2008-08-29 9:41 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-29 9:36 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> Gilles Chanteperdrix wrote: >>>>> Philippe Gerum wrote: >>>>>> 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. >>>>> 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. 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. -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-29 9:36 ` Jan Kiszka @ 2008-08-29 9:41 ` Gilles Chanteperdrix 2008-08-29 10:37 ` Jan Kiszka 2008-08-29 10:39 ` Philippe Gerum 0 siblings, 2 replies; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-29 9:41 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>>> Gilles Chanteperdrix wrote: >>>>>> Philippe Gerum wrote: >>>>>>> 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. >>>>>> 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. > > 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-29 9:41 ` Gilles Chanteperdrix @ 2008-08-29 10:37 ` Jan Kiszka 2008-08-29 12:19 ` Gilles Chanteperdrix 2008-08-29 10:39 ` Philippe Gerum 1 sibling, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-29 10:37 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> Gilles Chanteperdrix wrote: >>>>> Jan Kiszka wrote: >>>>>> Gilles Chanteperdrix wrote: >>>>>>> Philippe Gerum wrote: >>>>>>>> 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. >>>>>>> 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. >> 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. > > 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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-29 10:37 ` Jan Kiszka @ 2008-08-29 12:19 ` Gilles Chanteperdrix 0 siblings, 0 replies; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-29 12:19 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > 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... -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-29 9:41 ` Gilles Chanteperdrix 2008-08-29 10:37 ` Jan Kiszka @ 2008-08-29 10:39 ` Philippe Gerum 2008-08-29 10:46 ` Jan Kiszka 1 sibling, 1 reply; 68+ messages in thread From: Philippe Gerum @ 2008-08-29 10:39 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: Jan Kiszka, xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> Gilles Chanteperdrix wrote: >>>>> Jan Kiszka wrote: >>>>>> Gilles Chanteperdrix wrote: >>>>>>> Philippe Gerum wrote: >>>>>>>> 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. >>>>>>> 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. >> 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. > And by the way, I think that with the mutex/xnsynch shared owner, we can > implement stealing without a syscall. > -- Philippe. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-29 10:39 ` Philippe Gerum @ 2008-08-29 10:46 ` Jan Kiszka 2008-08-29 12:30 ` Philippe Gerum 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-29 10:46 UTC (permalink / raw) To: rpm; +Cc: xenomai-core Philippe Gerum wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>>> Gilles Chanteperdrix wrote: >>>>>> Jan Kiszka wrote: >>>>>>> Gilles Chanteperdrix wrote: >>>>>>>> Philippe Gerum wrote: >>>>>>>>> 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. >>>>>>>> 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. >>> 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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-29 10:46 ` Jan Kiszka @ 2008-08-29 12:30 ` Philippe Gerum 2008-08-29 12:40 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Philippe Gerum @ 2008-08-29 12:30 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Philippe Gerum wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> Gilles Chanteperdrix wrote: >>>>> Jan Kiszka wrote: >>>>>> Gilles Chanteperdrix wrote: >>>>>>> Jan Kiszka wrote: >>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>> Philippe Gerum wrote: >>>>>>>>>> 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. >>>>>>>>> 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. >>>> 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. > It's very fundamentally crappy. Please don't do that. xnsynch_sleep_on() must do what it is supposed to mean. > Jan > -- Philippe. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-29 12:30 ` Philippe Gerum @ 2008-08-29 12:40 ` Jan Kiszka 2008-08-29 13:10 ` Philippe Gerum 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-29 12:40 UTC (permalink / raw) To: rpm; +Cc: xenomai-core Philippe Gerum wrote: > Jan Kiszka wrote: >> Philippe Gerum wrote: >>> Gilles Chanteperdrix wrote: >>>> Jan Kiszka wrote: >>>>> Gilles Chanteperdrix wrote: >>>>>> Jan Kiszka wrote: >>>>>>> Gilles Chanteperdrix wrote: >>>>>>>> Jan Kiszka wrote: >>>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>>> Philippe Gerum wrote: >>>>>>>>>>> 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. >>>>>>>>>> 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. >>>>> 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. >> > > 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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-29 12:40 ` Jan Kiszka @ 2008-08-29 13:10 ` Philippe Gerum 2008-08-29 13:25 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Philippe Gerum @ 2008-08-29 13:10 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Philippe Gerum wrote: >> Jan Kiszka wrote: >>> Philippe Gerum wrote: >>>> Gilles Chanteperdrix wrote: >>>>> Jan Kiszka wrote: >>>>>> Gilles Chanteperdrix wrote: >>>>>>> Jan Kiszka wrote: >>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>> Jan Kiszka wrote: >>>>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>>>> Philippe Gerum wrote: >>>>>>>>>>>> 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. >>>>>>>>>>> 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. >>>>>> 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. >>> >> 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. > 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. > Jan > -- Philippe. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-29 13:10 ` Philippe Gerum @ 2008-08-29 13:25 ` Jan Kiszka 0 siblings, 0 replies; 68+ messages in thread From: Jan Kiszka @ 2008-08-29 13:25 UTC (permalink / raw) To: rpm; +Cc: xenomai-core Philippe Gerum wrote: > Jan Kiszka wrote: >> Philippe Gerum wrote: >>> Jan Kiszka wrote: >>>> Philippe Gerum wrote: >>>>> Gilles Chanteperdrix wrote: >>>>>> Jan Kiszka wrote: >>>>>>> Gilles Chanteperdrix wrote: >>>>>>>> Jan Kiszka wrote: >>>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>>> Jan Kiszka wrote: >>>>>>>>>>> Gilles Chanteperdrix wrote: >>>>>>>>>>>> Philippe Gerum wrote: >>>>>>>>>>>>> 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. >>>>>>>>>>>> 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. >>>>>>> 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. >>>> >>> 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. 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. > >> 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 ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 20:33 ` Jan Kiszka 2008-08-27 22:45 ` Gilles Chanteperdrix @ 2008-08-27 23:05 ` Gilles Chanteperdrix 2008-08-28 7:29 ` Jan Kiszka 2008-08-27 23:14 ` Gilles Chanteperdrix 2 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 23:05 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core 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. > > 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 > =================================================================== > --- a/ksrc/skins/posix/mutex.c > +++ 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); > + } I think an atomic_cmpxchg would be better here. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 23:05 ` Gilles Chanteperdrix @ 2008-08-28 7:29 ` Jan Kiszka 2008-08-28 7:38 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-28 7:29 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core [-- Attachment #1: Type: text/plain, Size: 4499 bytes --] 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. >> >> 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 >> =================================================================== >> --- a/ksrc/skins/posix/mutex.c >> +++ 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); >> + } > > 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 [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 257 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-28 7:29 ` Jan Kiszka @ 2008-08-28 7:38 ` Gilles Chanteperdrix 0 siblings, 0 replies; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-28 7:38 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > 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. >>> >>> 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 >>> =================================================================== >>> --- a/ksrc/skins/posix/mutex.c >>> +++ 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); >>> + } >> 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. 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 20:33 ` Jan Kiszka 2008-08-27 22:45 ` Gilles Chanteperdrix 2008-08-27 23:05 ` Gilles Chanteperdrix @ 2008-08-27 23:14 ` Gilles Chanteperdrix 2008-08-28 7:30 ` Jan Kiszka 2 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-27 23:14 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > @@ -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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-27 23:14 ` Gilles Chanteperdrix @ 2008-08-28 7:30 ` Jan Kiszka 2008-08-28 8:20 ` Gilles Chanteperdrix 0 siblings, 1 reply; 68+ messages in thread From: Jan Kiszka @ 2008-08-28 7:30 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core [-- Attachment #1: Type: text/plain, Size: 999 bytes --] Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> @@ -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. 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 [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 257 bytes --] ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-28 7:30 ` Jan Kiszka @ 2008-08-28 8:20 ` Gilles Chanteperdrix 2008-08-28 9:21 ` Jan Kiszka 0 siblings, 1 reply; 68+ messages in thread From: Gilles Chanteperdrix @ 2008-08-28 8:20 UTC (permalink / raw) To: Jan Kiszka; +Cc: xenomai-core Jan Kiszka wrote: > Gilles Chanteperdrix wrote: >> Jan Kiszka wrote: >>> @@ -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. > > 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. -- Gilles. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners 2008-08-28 8:20 ` Gilles Chanteperdrix @ 2008-08-28 9:21 ` Jan Kiszka 0 siblings, 0 replies; 68+ messages in thread From: Jan Kiszka @ 2008-08-28 9:21 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core Gilles Chanteperdrix wrote: > Jan Kiszka wrote: >> Gilles Chanteperdrix wrote: >>> Jan Kiszka wrote: >>>> @@ -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. >> 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 -- Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 68+ messages in thread
* [Xenomai-core] [RFC][PATCH 3/3] Remove xnarch_atomic_intptr wrappers 2008-08-27 13:39 [Xenomai-core] [RFC][PATCH 0/3] Handle-based fast mutex owner tracking Jan Kiszka 2008-08-27 13:42 ` [Xenomai-core] [RFC][PATCH 1/3] Always register threads by their base Jan Kiszka 2008-08-27 14:06 ` [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners Jan Kiszka @ 2008-08-27 14:08 ` Jan Kiszka 2 siblings, 0 replies; 68+ messages in thread From: Jan Kiszka @ 2008-08-27 14:08 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai-core 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(-) Index: b/include/asm-arm/atomic.h =================================================================== --- a/include/asm-arm/atomic.h +++ b/include/asm-arm/atomic.h @@ -412,9 +412,6 @@ static __inline__ void xnarch_atomic_cle typedef unsigned long atomic_flags_t; -/* Add support for xnarch_atomic_intptr_t */ -#include <asm-generic/xenomai/atomic.h> - #endif /* !_XENO_ASM_ARM_ATOMIC_H */ // vim: ts=4 et sw=4 sts=4 Index: b/include/asm-blackfin/atomic.h =================================================================== --- a/include/asm-blackfin/atomic.h +++ b/include/asm-blackfin/atomic.h @@ -42,8 +42,6 @@ typedef atomic_t atomic_counter_t; typedef atomic_t xnarch_atomic_t; -#include <asm-generic/xenomai/atomic.h> - #else /* !__KERNEL__ */ #include <asm/xenomai/syscall.h> Index: b/include/asm-generic/Makefile.am =================================================================== --- a/include/asm-generic/Makefile.am +++ b/include/asm-generic/Makefile.am @@ -1,5 +1,5 @@ includesubdir = $(includedir)/asm-generic -includesub_HEADERS = arith.h atomic.h features.h hal.h syscall.h system.h wrappers.h +includesub_HEADERS = arith.h features.h hal.h syscall.h system.h wrappers.h SUBDIRS = bits Index: b/include/asm-generic/Makefile.in =================================================================== --- a/include/asm-generic/Makefile.in +++ b/include/asm-generic/Makefile.in @@ -226,7 +226,7 @@ target_vendor = @target_vendor@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ includesubdir = $(includedir)/asm-generic -includesub_HEADERS = arith.h atomic.h features.h hal.h syscall.h system.h wrappers.h +includesub_HEADERS = arith.h features.h hal.h syscall.h system.h wrappers.h SUBDIRS = bits all: all-recursive Index: b/include/asm-generic/atomic.h =================================================================== --- a/include/asm-generic/atomic.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _XENO_ASM_GENERIC_ATOMIC_H -#define _XENO_ASM_GENERIC_ATOMIC_H - -typedef xnarch_atomic_t xnarch_atomic_intptr_t; - -static inline void *xnarch_atomic_intptr_get(xnarch_atomic_intptr_t *l) -{ - xnarch_atomic_t *v = (xnarch_atomic_t *)l; - - return (void *)xnarch_atomic_get(v); -} - -static inline void xnarch_atomic_intptr_set(xnarch_atomic_intptr_t *l, void *i) -{ - xnarch_atomic_t *v = (xnarch_atomic_t *)l; - - xnarch_atomic_set(v, (long)i); -} - -#define xnarch_atomic_intptr_cmpxchg(l, old, newval) \ - (void *)(xnarch_atomic_cmpxchg((xnarch_atomic_t *)(l), \ - (long)(old), (long)(newval))) - -#endif /* _XENO_ASM_GENERIC_ATOMIC_H */ Index: b/include/asm-ia64/atomic.h =================================================================== --- a/include/asm-ia64/atomic.h +++ b/include/asm-ia64/atomic.h @@ -71,8 +71,6 @@ static inline void atomic_clear_mask(uns #define xnarch_atomic_cmpxchg(pcounter,old,new) \ cmpxchg((&(pcounter)->counter),(old),(new)) -#include <asm-generic/xenomai/atomic.h> - #else /* !__KERNEL__ */ #include <asm/xenomai/features.h> Index: b/include/asm-powerpc/atomic.h =================================================================== --- a/include/asm-powerpc/atomic.h +++ b/include/asm-powerpc/atomic.h @@ -262,6 +262,4 @@ xnarch_atomic_cmpxchg(xnarch_atomic_t *p typedef unsigned long atomic_flags_t; -#include <asm-generic/xenomai/atomic.h> - #endif /* !_XENO_ASM_POWERPC_ATOMIC_H */ Index: b/include/asm-x86/atomic.h =================================================================== --- a/include/asm-x86/atomic.h +++ b/include/asm-x86/atomic.h @@ -136,6 +136,4 @@ xnarch_atomic_cmpxchg(xnarch_atomic_t *v #endif /* __KERNEL__ */ -#include <asm-generic/xenomai/atomic.h> - #endif /* !_XENO_ASM_X86_ATOMIC_64_H */ ^ permalink raw reply [flat|nested] 68+ messages in thread
end of thread, other threads:[~2008-08-29 13:25 UTC | newest] Thread overview: 68+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-08-27 13:39 [Xenomai-core] [RFC][PATCH 0/3] Handle-based fast mutex owner tracking Jan Kiszka 2008-08-27 13:42 ` [Xenomai-core] [RFC][PATCH 1/3] Always register threads by their base Jan Kiszka 2008-08-27 14:06 ` [Xenomai-core] [RFC][PATCH 2/3] Switch to handle-based fast mutex owners Jan Kiszka 2008-08-27 14:14 ` Gilles Chanteperdrix 2008-08-27 14:38 ` Jan Kiszka 2008-08-27 14:44 ` Gilles Chanteperdrix 2008-08-27 14:49 ` Jan Kiszka 2008-08-27 14:57 ` Gilles Chanteperdrix 2008-08-27 23:49 ` Gilles Chanteperdrix 2008-08-27 14:36 ` Gilles Chanteperdrix 2008-08-27 14:45 ` Jan Kiszka 2008-08-27 14:47 ` Gilles Chanteperdrix 2008-08-27 14:51 ` Jan Kiszka 2008-08-27 14:55 ` Gilles Chanteperdrix 2008-08-27 15:00 ` Jan Kiszka 2008-08-27 15:04 ` Gilles Chanteperdrix 2008-08-27 15:10 ` Jan Kiszka 2008-08-27 15:13 ` Gilles Chanteperdrix 2008-08-27 15:15 ` Gilles Chanteperdrix 2008-08-27 15:18 ` Jan Kiszka 2008-08-27 15:29 ` Gilles Chanteperdrix 2008-08-27 15:34 ` Jan Kiszka 2008-08-27 15:36 ` Gilles Chanteperdrix 2008-08-27 15:37 ` Jan Kiszka 2008-08-27 23:44 ` Gilles Chanteperdrix 2008-08-27 14:48 ` Gilles Chanteperdrix 2008-08-27 14:50 ` Gilles Chanteperdrix 2008-08-27 15:20 ` Jan Kiszka 2008-08-27 15:28 ` Gilles Chanteperdrix 2008-08-27 15:43 ` Jan Kiszka 2008-08-27 15:46 ` Gilles Chanteperdrix 2008-08-27 16:08 ` Jan Kiszka 2008-08-27 16:13 ` Gilles Chanteperdrix 2008-08-27 18:15 ` Jan Kiszka 2008-08-27 19:02 ` Gilles Chanteperdrix 2008-08-27 19:04 ` Gilles Chanteperdrix 2008-08-27 20:35 ` Jan Kiszka 2008-08-27 21:26 ` Gilles Chanteperdrix 2008-08-27 21:46 ` Jan Kiszka 2008-08-27 21:55 ` Gilles Chanteperdrix 2008-08-27 20:33 ` Jan Kiszka 2008-08-27 22:45 ` Gilles Chanteperdrix 2008-08-28 10:01 ` Philippe Gerum 2008-08-28 10:37 ` Jan Kiszka 2008-08-28 10:52 ` Philippe Gerum 2008-08-28 12:21 ` Gilles Chanteperdrix 2008-08-29 6:41 ` Jan Kiszka 2008-08-29 7:00 ` Gilles Chanteperdrix 2008-08-29 7:22 ` Jan Kiszka 2008-08-29 7:29 ` Gilles Chanteperdrix 2008-08-29 9:36 ` Jan Kiszka 2008-08-29 9:41 ` Gilles Chanteperdrix 2008-08-29 10:37 ` Jan Kiszka 2008-08-29 12:19 ` Gilles Chanteperdrix 2008-08-29 10:39 ` Philippe Gerum 2008-08-29 10:46 ` Jan Kiszka 2008-08-29 12:30 ` Philippe Gerum 2008-08-29 12:40 ` Jan Kiszka 2008-08-29 13:10 ` Philippe Gerum 2008-08-29 13:25 ` Jan Kiszka 2008-08-27 23:05 ` Gilles Chanteperdrix 2008-08-28 7:29 ` Jan Kiszka 2008-08-28 7:38 ` Gilles Chanteperdrix 2008-08-27 23:14 ` Gilles Chanteperdrix 2008-08-28 7:30 ` Jan Kiszka 2008-08-28 8:20 ` Gilles Chanteperdrix 2008-08-28 9:21 ` Jan Kiszka 2008-08-27 14:08 ` [Xenomai-core] [RFC][PATCH 3/3] Remove xnarch_atomic_intptr wrappers Jan Kiszka
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.