* [Xenomai-core] [PATCH 1/9] Always register threads by their base
2008-09-01 8:53 [Xenomai-core] [PATCH 0/9] Fast mutex rework, native support Jan Kiszka
@ 2008-09-01 8:39 ` Jan Kiszka
2008-09-01 8:44 ` [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners Jan Kiszka
` (7 subsequent siblings)
8 siblings, 0 replies; 26+ messages in thread
From: Jan Kiszka @ 2008-09-01 8:39 UTC (permalink / raw)
To: 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] 26+ messages in thread
* [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners
2008-09-01 8:53 [Xenomai-core] [PATCH 0/9] Fast mutex rework, native support Jan Kiszka
2008-09-01 8:39 ` [Xenomai-core] [PATCH 1/9] Always register threads by their base Jan Kiszka
@ 2008-09-01 8:44 ` Jan Kiszka
2008-09-01 11:58 ` Gilles Chanteperdrix
2008-09-05 8:34 ` [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners - v2 Jan Kiszka
2008-09-01 8:45 ` [Xenomai-core] [PATCH 3/9] Remove xnarch_atomic_intptr wrappers Jan Kiszka
` (6 subsequent siblings)
8 siblings, 2 replies; 26+ messages in thread
From: Jan Kiszka @ 2008-09-01 8:44 UTC (permalink / raw)
To: 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 all skins (except for
RTDM which must not mess around with foreign skins anyway) add their
threads to the registry so that at least anonymous handles are
available.
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.
[ PS: I wonder if we can merge xnmap and xnregistry one day. Maybe there
is a smart way to combine best of both, overcoming the redundancy. ]
---
include/asm-generic/bits/bind.h | 9 ++++-
include/asm-generic/bits/current.h | 5 +-
include/nucleus/types.h | 13 +++++++
ksrc/nucleus/shadow.c | 17 +++++++--
ksrc/skins/native/Kconfig | 1
ksrc/skins/native/task.c | 14 +++----
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 | 16 ++++++++
ksrc/skins/psos+/Kconfig | 2 -
ksrc/skins/rtai/Kconfig | 1
ksrc/skins/rtai/task.c | 12 ++++++
ksrc/skins/uitron/Kconfig | 1
ksrc/skins/uitron/task.c | 11 ++++++
ksrc/skins/vrtx/Kconfig | 2 -
ksrc/skins/vrtx/task.c | 20 ++++++++++-
ksrc/skins/vxworks/Kconfig | 2 -
src/skins/posix/mutex.c | 27 +++++++--------
22 files changed, 205 insertions(+), 74 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>
@@ -1908,13 +1909,21 @@ static int xnshadow_sys_sem_heap(struct
return __xn_safe_copy_to_user(us_hinfo, &hinfo, sizeof(*us_hinfo));
}
+#ifdef CONFIG_XENO_OPT_REGISTRY
static int xnshadow_sys_current(struct pt_regs *regs)
{
- xnthread_t * __user *us_current, *cur = xnshadow_thread(current);
- us_current = (xnthread_t *__user *) __xn_reg_arg1(regs);
+ xnthread_t *cur = xnshadow_thread(current);
+ xnhandle_t __user *us_handle;
- return __xn_safe_copy_to_user(us_current, &cur, sizeof(*us_current));
+ if (!cur)
+ return -EPERM;
+
+ us_handle = (xnhandle_t __user *) __xn_reg_arg1(regs);
+
+ return __xn_safe_copy_to_user(us_handle, &xnthread_handle(cur),
+ sizeof(*us_handle));
}
+#endif /* CONFIG_XENO_OPT_REGISTRY */
static xnsysent_t __systab[] = {
[__xn_sys_migrate] = {&xnshadow_sys_migrate, __xn_exec_current},
@@ -1925,7 +1934,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>
@@ -234,6 +235,21 @@ int pthread_create(pthread_t *tid,
thread->hkey.mm = NULL;
#endif /* CONFIG_XENO_OPT_PERVASIVE */
+#ifdef CONFIG_XENO_FASTSEM
+ /* We need an anonymous registry entry to obtain a handle for fast
+ mutex locking. */
+ {
+ int err =
+ xnregistry_enter("", &thread->threadbase,
+ &xnthread_handle(&thread->threadbase),
+ NULL);
+ if (err) {
+ thread_destroy(thread);
+ return err;
+ }
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
*tid = thread; /* Must be done before the thread is started. */
if (start) /* Do not start shadow threads (i.e. start == NULL). */
Index: b/ksrc/skins/posix/Kconfig
===================================================================
--- a/ksrc/skins/posix/Kconfig
+++ b/ksrc/skins/posix/Kconfig
@@ -1,5 +1,6 @@
menuconfig XENO_SKIN_POSIX
depends on XENO_OPT_NUCLEUS
+ select XENO_OPT_REGISTRY if XENO_FASTSEM
tristate "POSIX API"
default y
help
Index: b/include/asm-generic/bits/bind.h
===================================================================
--- a/include/asm-generic/bits/bind.h
+++ b/include/asm-generic/bits/bind.h
@@ -22,7 +22,14 @@ __attribute__ ((weak))
void xeno_set_current(void)
{
void *kthread_cb;
- XENOMAI_SYSCALL1(__xn_sys_current, &kthread_cb);
+ int err;
+
+ err = XENOMAI_SYSCALL1(__xn_sys_current, &kthread_cb);
+ if (err) {
+ fprintf(stderr, "Xenomai: error obtaining handle for current "
+ "thread: %s\n", strerror(err));
+ exit(1);
+ }
pthread_setspecific(xeno_current_key, kthread_cb);
}
Index: b/ksrc/skins/native/Kconfig
===================================================================
--- a/ksrc/skins/native/Kconfig
+++ b/ksrc/skins/native/Kconfig
@@ -1,5 +1,6 @@
menuconfig XENO_SKIN_NATIVE
depends on XENO_OPT_NUCLEUS
+ select XENO_OPT_REGISTRY if XENO_FASTSEM
tristate "Native API"
default y
help
Index: b/ksrc/skins/native/task.c
===================================================================
--- a/ksrc/skins/native/task.c
+++ b/ksrc/skins/native/task.c
@@ -290,14 +290,12 @@ int rt_task_create(RT_TASK *task,
complete objects, so that the registry cannot return handles to
half-baked objects... */
- if (name) {
- err = xnregistry_enter(task->rname,
- &task->thread_base,
- &xnthread_handle(&task->thread_base),
- NULL);
- if (err)
- xnpod_delete_thread(&task->thread_base);
- }
+ err = xnregistry_enter(name ? task->rname : "",
+ &task->thread_base,
+ &xnthread_handle(&task->thread_base),
+ NULL);
+ if (err)
+ xnpod_delete_thread(&task->thread_base);
#endif /* CONFIG_XENO_OPT_REGISTRY */
return err;
Index: b/ksrc/skins/psos+/Kconfig
===================================================================
--- a/ksrc/skins/psos+/Kconfig
+++ b/ksrc/skins/psos+/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_PSOS
depends on XENO_OPT_NUCLEUS
select XENO_OPT_TIMING_PERIODIC
tristate "pSOS+ emulator"
- select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE
+ select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSEM
help
This API skin emulates WindRiver's pSOS+ operating system.
Index: b/ksrc/skins/uitron/Kconfig
===================================================================
--- a/ksrc/skins/uitron/Kconfig
+++ b/ksrc/skins/uitron/Kconfig
@@ -2,6 +2,7 @@ menuconfig XENO_SKIN_UITRON
depends on XENO_OPT_NUCLEUS
select XENO_OPT_TIMING_PERIODIC
select XENO_OPT_MAP
+ select XENO_OPT_REGISTRY if XENO_FASTSEM
tristate "uITRON API"
help
Index: b/ksrc/skins/uitron/task.c
===================================================================
--- a/ksrc/skins/uitron/task.c
+++ b/ksrc/skins/uitron/task.c
@@ -151,6 +151,17 @@ ER cre_tsk(ID tskid, T_CTSK *pk_ctsk)
xnlock_put_irqrestore(&nklock, s);
task->magic = uITRON_TASK_MAGIC;
+#ifdef CONFIG_XENO_FASTSEM
+ /* We need an anonymous registry entry to obtain a handle for fast
+ mutex locking. */
+ if (xnregistry_enter("", &task->threadbase,
+ &xnthread_handle(&task->threadbase), NULL)) {
+ xnmap_remove(ui_task_idmap, tskid);
+ xnpod_abort_thread(&task->threadbase);
+ return E_NOMEM;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
return E_OK;
}
Index: b/ksrc/skins/rtai/Kconfig
===================================================================
--- a/ksrc/skins/rtai/Kconfig
+++ b/ksrc/skins/rtai/Kconfig
@@ -1,5 +1,6 @@
menuconfig XENO_SKIN_RTAI
depends on XENO_OPT_NUCLEUS
+ select XENO_OPT_REGISTRY if XENO_FASTSEM
tristate "RTAI emulator"
help
Index: b/ksrc/skins/rtai/task.c
===================================================================
--- a/ksrc/skins/rtai/task.c
+++ b/ksrc/skins/rtai/task.c
@@ -20,6 +20,7 @@
#include <nucleus/pod.h>
#include <nucleus/heap.h>
+#include <nucleus/registry.h>
#include <rtai/task.h>
static DEFINE_XNQUEUE(__rtai_task_q);
@@ -152,6 +153,17 @@ int rt_task_init(RT_TASK *task,
task->magic = RTAI_TASK_MAGIC;
appendq(&__rtai_task_q, &task->link);
+#ifdef CONFIG_XENO_FASTSEM
+ /* We need an anonymous registry entry to obtain a handle for fast
+ mutex locking. */
+ err = xnregistry_enter("", &task->thread_base,
+ &xnthread_handle(&task->thread_base), NULL);
+ if (err) {
+ xnpod_abort_thread(&task->thread_base);
+ goto unlock_and_exit;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
/* Add a switch hook only if a signal function has been declared
at least once for some created task. */
Index: b/ksrc/skins/vrtx/Kconfig
===================================================================
--- a/ksrc/skins/vrtx/Kconfig
+++ b/ksrc/skins/vrtx/Kconfig
@@ -3,7 +3,7 @@ menuconfig XENO_SKIN_VRTX
select XENO_OPT_TIMING_PERIODIC
select XENO_OPT_MAP
tristate "VRTX emulator"
- select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE
+ select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || CONFIG_XENO_FASTSEM
help
This API skin emulates Mentor Graphics's VRTX operating
Index: b/ksrc/skins/vrtx/task.c
===================================================================
--- a/ksrc/skins/vrtx/task.c
+++ b/ksrc/skins/vrtx/task.c
@@ -188,12 +188,28 @@ int sc_tecreate_inner(vrtxtask_t *task,
if (mode & 0x10)
bmode |= XNRRB;
- *errp = RET_OK;
-
xnlock_get_irqsave(&nklock, s);
appendq(&vrtx_task_q, &task->link);
xnlock_put_irqrestore(&nklock, s);
+#ifdef CONFIG_XENO_FASTSEM
+ /* We need an anonymous registry entry to obtain a handle for fast
+ mutex locking. */
+ {
+ int err =
+ xnregistry_enter("", &task->threadbase,
+ &xnthread_handle(&task->threadbase),
+ NULL);
+ if (err) {
+ xnpod_abort_thread(&task->threadbase);
+ *errp = ER_MEM;
+ return -1;
+ }
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
+ *errp = RET_OK;
+
xnpod_start_thread(&task->threadbase,
bmode, 0, XNPOD_ALL_CPUS, &vrtxtask_trampoline,
task);
Index: b/ksrc/skins/vxworks/Kconfig
===================================================================
--- a/ksrc/skins/vxworks/Kconfig
+++ b/ksrc/skins/vxworks/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_VXWORKS
depends on XENO_OPT_NUCLEUS
select XENO_OPT_TIMING_PERIODIC
tristate "VxWorks emulator"
- select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE
+ select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSEM
help
This API skin emulates WindRiver's VxWorks operating system.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [Xenomai-core] [PATCH 3/9] Remove xnarch_atomic_intptr wrappers
2008-09-01 8:53 [Xenomai-core] [PATCH 0/9] Fast mutex rework, native support Jan Kiszka
2008-09-01 8:39 ` [Xenomai-core] [PATCH 1/9] Always register threads by their base Jan Kiszka
2008-09-01 8:44 ` [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners Jan Kiszka
@ 2008-09-01 8:45 ` Jan Kiszka
2008-09-01 8:47 ` [Xenomai-core] [PATCH 4/9] Spread xeno_set_current Jan Kiszka
` (5 subsequent siblings)
8 siblings, 0 replies; 26+ messages in thread
From: Jan Kiszka @ 2008-09-01 8:45 UTC (permalink / raw)
To: 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] 26+ messages in thread
* [Xenomai-core] [PATCH 4/9] Spread xeno_set_current
2008-09-01 8:53 [Xenomai-core] [PATCH 0/9] Fast mutex rework, native support Jan Kiszka
` (2 preceding siblings ...)
2008-09-01 8:45 ` [Xenomai-core] [PATCH 3/9] Remove xnarch_atomic_intptr wrappers Jan Kiszka
@ 2008-09-01 8:47 ` Jan Kiszka
2008-09-01 8:54 ` [Xenomai-core] [RFC][PATCH 5/9] Allow lock stealing via pthread_mutex_trylock Jan Kiszka
` (4 subsequent siblings)
8 siblings, 0 replies; 26+ messages in thread
From: Jan Kiszka @ 2008-09-01 8:47 UTC (permalink / raw)
To: xenomai-core
Spread xeno_set_current under all user space supporting skins.
---
src/skins/native/task.c | 13 +++++++++++--
src/skins/psos+/task.c | 18 ++++++++++++++----
src/skins/uitron/task.c | 18 +++++++++++++-----
src/skins/vrtx/task.c | 3 +++
src/skins/vxworks/taskLib.c | 3 +++
5 files changed, 44 insertions(+), 11 deletions(-)
Index: b/src/skins/native/task.c
===================================================================
--- a/src/skins/native/task.c
+++ b/src/skins/native/task.c
@@ -26,6 +26,7 @@
#include <limits.h>
#include <native/syscall.h>
#include <native/task.h>
+#include <asm-generic/bits/current.h>
#include "wrappers.h"
extern pthread_key_t __native_tskey;
@@ -88,6 +89,8 @@ static void *rt_task_trampoline(void *co
if (err)
goto fail;
+ xeno_set_current();
+
/* Wait on the barrier for the task to be started. The barrier
could be released in order to process Linux signals while the
Xenomai shadow is still dormant; in such a case, resume wait. */
@@ -169,6 +172,7 @@ int rt_task_shadow(RT_TASK *task, const
struct sched_param param;
struct rt_arg_bulk bulk;
RT_TASK task_desc;
+ int err;
if (task == NULL)
task = &task_desc; /* Discarded. */
@@ -191,8 +195,13 @@ int rt_task_shadow(RT_TASK *task, const
bulk.a4 = (u_long)mode;
bulk.a5 = (u_long)pthread_self();
- return XENOMAI_SKINCALL2(__native_muxid, __native_task_create, &bulk,
- NULL);
+ err = XENOMAI_SKINCALL2(__native_muxid, __native_task_create, &bulk,
+ NULL);
+
+ if (!err)
+ xeno_set_current();
+
+ return err;
}
int rt_task_bind(RT_TASK *task, const char *name, RTIME timeout)
Index: b/src/skins/psos+/task.c
===================================================================
--- a/src/skins/psos+/task.c
+++ b/src/skins/psos+/task.c
@@ -26,6 +26,7 @@
#include <memory.h>
#include <string.h>
#include <psos+/psos.h>
+#include <asm-generic/bits/current.h>
extern int __psos_muxid;
@@ -89,6 +90,8 @@ static void *psos_task_trampoline(void *
if (err)
goto fail;
+ xeno_set_current();
+
/* Wait on the barrier for the task to be started. The barrier
could be released in order to process Linux signals while the
Xenomai shadow is still dormant; in such a case, resume wait. */
@@ -173,14 +176,21 @@ u_long t_shadow(const char *name, /* Xen
u_long flags,
u_long *tid_r)
{
+ int err;
+
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
old_sigharden_handler = signal(SIGHARDEN, &psos_task_sigharden);
- return XENOMAI_SKINCALL5(__psos_muxid,
- __psos_t_create,
- name, prio, flags,
- tid_r, NULL);
+ err = XENOMAI_SKINCALL5(__psos_muxid,
+ __psos_t_create,
+ name, prio, flags,
+ tid_r, NULL);
+
+ if (!err)
+ xeno_set_current();
+
+ return err;
}
u_long t_start(u_long tid,
Index: b/src/skins/uitron/task.c
===================================================================
--- a/src/skins/uitron/task.c
+++ b/src/skins/uitron/task.c
@@ -25,6 +25,7 @@
#include <limits.h>
#include <asm/xenomai/system.h>
#include <uitron/uitron.h>
+#include <asm-generic/bits/current.h>
extern int __uitron_muxid;
@@ -89,6 +90,8 @@ static void *uitron_task_trampoline(void
if (err)
goto fail;
+ xeno_set_current();
+
/* iargs->pk_ctsk might not be valid anymore, after our parent
was released from the completion sync, so do not
dereference this pointer. */
@@ -150,7 +153,7 @@ ER cre_tsk(ID tskid, T_CTSK *pk_ctsk)
ER shd_tsk(ID tskid, T_CTSK *pk_ctsk) /* Xenomai extension. */
{
struct sched_param param;
- int policy;
+ int policy, err;
/* Make sure the POSIX library caches the right priority. */
policy = uitron_task_set_posix_priority(pk_ctsk->itskpri, ¶m);
@@ -160,10 +163,15 @@ ER shd_tsk(ID tskid, T_CTSK *pk_ctsk) /*
old_sigharden_handler = signal(SIGHARDEN, &uitron_task_sigharden);
- return XENOMAI_SKINCALL3(__uitron_muxid,
- __uitron_cre_tsk,
- tskid, pk_ctsk,
- NULL);
+ err = XENOMAI_SKINCALL3(__uitron_muxid,
+ __uitron_cre_tsk,
+ tskid, pk_ctsk,
+ NULL);
+
+ if (!err)
+ xeno_set_current();
+
+ return err;
}
ER del_tsk(ID tskid)
Index: b/src/skins/vrtx/task.c
===================================================================
--- a/src/skins/vrtx/task.c
+++ b/src/skins/vrtx/task.c
@@ -27,6 +27,7 @@
#include <errno.h>
#include <limits.h>
#include <vrtx/vrtx.h>
+#include <asm-generic/bits/current.h>
extern pthread_key_t __vrtx_tskey;
@@ -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] 26+ messages in thread
* [Xenomai-core] [PATCH 0/9] Fast mutex rework, native support
@ 2008-09-01 8:53 Jan Kiszka
2008-09-01 8:39 ` [Xenomai-core] [PATCH 1/9] Always register threads by their base Jan Kiszka
` (8 more replies)
0 siblings, 9 replies; 26+ messages in thread
From: Jan Kiszka @ 2008-09-01 8:53 UTC (permalink / raw)
To: xenomai-core
Here comes our current patch series to fix and enhance fast mutexes for
both the POSIX as well as the native skin. After the long discussion on
this list, it is clear that this is not the last word. However, we are
currently not aware of regressions or still broken corner cases, so this
series may at least serve as a reference for future versions.
Patches 1-4 should already be mergeable. They introduce handle-based
owner tracking for the fast locks and clean up some code.
Patch 5 adds lock stealing support to pthread_mutex_trylock (something
that the glibc does not provide, BTW...). It "misuses"
xnsynch_sleep_on(..., XN_NONBLOCK) for this, but reuses a lot of code
this way. To compensate for the overhead if this path, patch 9 optimizes
xnsynch_sleep_on for XN_NONBLOCK users. Take this as a reference for one
of the three possible approaches. Another one, some dedicated
xnsynch_try_acquire (or so), may later be examined as well so that we
can compare pros and cons. But first the third one, lock stealing via
fast locks, should be analyzed /wrt feasibility.
Patch 6 is an intermediate helper to break out of the lock stealing loop
in xnsynch_sleep_on (XNSYNCH_FWDROB). Patch 7 applies it on the POSIX
skin, overcoming the duplicated sleeper tracking. XNSYNCH_FWROB will be
obsolete once we merge fast lock support into xnsynch.
Patch 8 introduces fast mutexes to the native skin. This approach is
built upon the same mechanisms as the POSIX skin (XNSYNCH_FWROB, trylock
via xnsynch_sleep_on) to compare both implementations. The reason for
differences is mostly the simpler native API. It passes an analogous
test case like Gilles wrote for POSIX (augmented with lock stealing
tests). The testsuite will be posted later after some refactoring work.
Feedback welcome.
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 26+ messages in thread
* [Xenomai-core] [RFC][PATCH 5/9] Allow lock stealing via pthread_mutex_trylock
2008-09-01 8:53 [Xenomai-core] [PATCH 0/9] Fast mutex rework, native support Jan Kiszka
` (3 preceding siblings ...)
2008-09-01 8:47 ` [Xenomai-core] [PATCH 4/9] Spread xeno_set_current Jan Kiszka
@ 2008-09-01 8:54 ` Jan Kiszka
2008-09-01 9:58 ` Gilles Chanteperdrix
2008-09-01 8:57 ` [Xenomai-core] [RFC][PATCH 6/9] Add XNSYNCH_FWDROB Jan Kiszka
` (3 subsequent siblings)
8 siblings, 1 reply; 26+ messages in thread
From: Jan Kiszka @ 2008-09-01 8:54 UTC (permalink / raw)
To: xenomai-core
By calling into the kernel in the contended case and exploiting
XN_NONBLOCK for xnsynch_sleep_on, this patch adds lock stealing support
to pthread_mutex_trylock.
The latter part may change if we decide to go for a dedicates xnsynch
trylock service. Maybe we are even lucky and able to implement lock
stealing purely with the help of the fast lock algorithm. But we first
have to merge fast locks into xnsynch to see clearer.
---
include/posix/syscall.h | 2 -
ksrc/skins/posix/cond.c | 3 +-
ksrc/skins/posix/mutex.c | 24 +++++++++++++----------
ksrc/skins/posix/mutex.h | 11 +++-------
ksrc/skins/posix/syscall.c | 46 +++++++++++++++++++++++++++++++++++----------
src/skins/posix/mutex.c | 6 ++++-
6 files changed, 62 insertions(+), 30 deletions(-)
Index: b/ksrc/skins/posix/cond.c
===================================================================
--- a/ksrc/skins/posix/cond.c
+++ b/ksrc/skins/posix/cond.c
@@ -345,7 +345,8 @@ int pse51_cond_timedwait_epilogue(xnthre
cond = shadow->cond;
- err = pse51_mutex_timedlock_internal(cur, mutex, count, 0, XN_INFINITE);
+ err = pse51_mutex_timedlock_internal(cur, mutex, count, XN_RELATIVE,
+ XN_INFINITE);
if (err == -EINTR)
goto unlock_and_return;
Index: b/ksrc/skins/posix/mutex.c
===================================================================
--- a/ksrc/skins/posix/mutex.c
+++ b/ksrc/skins/posix/mutex.c
@@ -283,7 +283,7 @@ int pthread_mutex_destroy(pthread_mutex_
}
int pse51_mutex_timedlock_break(struct __shadow_mutex *shadow,
- int timed, xnticks_t abs_to)
+ xntmode_t timeout_mode, xnticks_t timeout)
{
xnthread_t *cur = xnpod_current_thread();
pse51_mutex_t *mutex;
@@ -294,7 +294,8 @@ int pse51_mutex_timedlock_break(struct _
if (!xnthread_handle(cur))
return -EPERM;
- err = pse51_mutex_timedlock_internal(cur, shadow, 1, timed, abs_to);
+ err = pse51_mutex_timedlock_internal(cur, shadow, 1, timeout_mode,
+ timeout);
if (err != -EBUSY)
goto unlock_and_return;
@@ -306,12 +307,8 @@ int pse51_mutex_timedlock_break(struct _
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);
+ xnsynch_sleep_on(&mutex->synchbase, timeout,
+ timeout_mode);
--mutex->sleepers;
if (xnthread_test_info(cur, XNBREAK)) {
@@ -407,6 +404,12 @@ int pthread_mutex_trylock(pthread_mutex_
err = 0;
}
}
+ } else {
+ err =
+ -pse51_mutex_timedlock_internal(cur, shadow, 1,
+ XN_RELATIVE, XN_NONBLOCK);
+ if (err == ETIMEDOUT)
+ err = EBUSY;
}
cb_read_unlock(&shadow->lock, s);
@@ -461,7 +464,8 @@ int pthread_mutex_lock(pthread_mutex_t *
return EINVAL;
do {
- err = pse51_mutex_timedlock_break(shadow, 0, XN_INFINITE);
+ err = pse51_mutex_timedlock_break(shadow, XN_RELATIVE,
+ XN_INFINITE);
} while (err == -EINTR);
cb_read_unlock(&shadow->lock, s);
@@ -514,7 +518,7 @@ int pthread_mutex_timedlock(pthread_mute
return EINVAL;
do {
- err = pse51_mutex_timedlock_break(shadow, 1,
+ err = pse51_mutex_timedlock_break(shadow, XN_REALTIME,
ts2ticks_ceil(to) + 1);
} while (err == -EINTR);
Index: b/ksrc/skins/posix/mutex.h
===================================================================
--- a/ksrc/skins/posix/mutex.h
+++ b/ksrc/skins/posix/mutex.h
@@ -71,7 +71,7 @@ void pse51_mutex_pkg_cleanup(void);
/* Internal mutex functions, exposed for use by syscall.c. */
int pse51_mutex_timedlock_break(struct __shadow_mutex *shadow,
- int timed, xnticks_t to);
+ xntmode_t timeout_mode, xnticks_t timeout);
int pse51_mutex_check_init(struct __shadow_mutex *shadow,
const pthread_mutexattr_t *attr);
@@ -120,8 +120,8 @@ pse51_mutex_trylock_internal(xnthread_t
static inline int pse51_mutex_timedlock_internal(xnthread_t *cur,
struct __shadow_mutex *shadow,
unsigned count,
- int timed,
- xnticks_t abs_to)
+ xntmode_t timeout_mode,
+ xnticks_t timeout)
{
pse51_mutex_t *mutex;
@@ -173,10 +173,7 @@ 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);
+ xnsynch_sleep_on(&mutex->synchbase, timeout, timeout_mode);
--mutex->sleepers;
if (xnthread_test_info(cur, XNBREAK)) {
Index: b/ksrc/skins/posix/syscall.c
===================================================================
--- a/ksrc/skins/posix/syscall.c
+++ b/ksrc/skins/posix/syscall.c
@@ -957,7 +957,8 @@ static int __pthread_mutex_lock(struct p
if (unlikely(cb_try_read_lock(&mx.shadow_mutex.lock, s)))
return -EINVAL;
- err = pse51_mutex_timedlock_break(&mx.shadow_mutex, 0, XN_INFINITE);
+ err = pse51_mutex_timedlock_break(&mx.shadow_mutex, XN_REALTIVE,
+ XN_INFINITE);
cb_read_unlock(&mx.shadow_mutex.lock, s);
@@ -991,8 +992,8 @@ static int __pthread_mutex_timedlock(str
if (unlikely(cb_try_read_lock(&mx.shadow_mutex.lock, s)))
return -EINVAL;
- err = pse51_mutex_timedlock_break(&mx.shadow_mutex,
- 1, ts2ticks_ceil(&ts) + 1);
+ err = pse51_mutex_timedlock_break(&mx.shadow_mutex, XN_REALTIME,
+ ts2ticks_ceil(&ts) + 1);
cb_read_unlock(&mx.shadow_mutex.lock, s);
@@ -1214,7 +1215,8 @@ static int __pthread_mutex_lock(struct p
shadow = &mx.shadow_mutex;
- err = pse51_mutex_timedlock_break(&mx.shadow_mutex, 0, XN_INFINITE);
+ err = pse51_mutex_timedlock_break(&mx.shadow_mutex, XN_RELATIVE,
+ XN_INFINITE);
if (!err &&
__xn_safe_copy_to_user((void __user *)
@@ -1247,8 +1249,8 @@ static int __pthread_mutex_timedlock(str
shadow = &mx.shadow_mutex;
- err = pse51_mutex_timedlock_break(&mx.shadow_mutex,
- 1, ts2ticks_ceil(&ts) + 1);
+ err = pse51_mutex_timedlock_break(&mx.shadow_mutex, XN_REALTIME,
+ ts2ticks_ceil(&ts) + 1);
if (!err &&
__xn_safe_copy_to_user((void __user *)
@@ -1260,6 +1262,31 @@ static int __pthread_mutex_timedlock(str
return err;
}
+static int __pthread_mutex_trylock(struct pt_regs *regs)
+{
+ xnthread_t *cur = xnpod_current_thread();
+ union __xeno_mutex mx, *umx;
+ int err;
+
+ umx = (union __xeno_mutex *)__xn_reg_arg1(regs);
+
+ if (__xn_safe_copy_from_user(&mx.shadow_mutex,
+ (void __user *)&umx->shadow_mutex,
+ sizeof(mx.shadow_mutex)))
+ return -EFAULT;
+
+ err = pse51_mutex_timedlock_internal(cur, &mx.shadow_mutex, 1,
+ XN_RELATIVE, XN_NONBLOCK);
+
+ if (!err &&
+ __xn_safe_copy_to_user((void __user *)&umx->shadow_mutex.lockcnt,
+ &mx.shadow_mutex.lockcnt,
+ sizeof(umx->shadow_mutex.lockcnt)))
+ return -EFAULT;
+
+ return err;
+}
+
static int __pthread_mutex_unlock(struct pt_regs *regs)
{
xnthread_t *cur = xnpod_current_thread();
@@ -2695,11 +2722,7 @@ static xnsysent_t __systab[] = {
[__pse51_mutex_lock] = {&__pthread_mutex_lock, __xn_exec_primary},
[__pse51_mutex_timedlock] =
{&__pthread_mutex_timedlock, __xn_exec_primary},
-#ifndef CONFIG_XENO_FASTSEM
[__pse51_mutex_trylock] = {&__pthread_mutex_trylock, __xn_exec_primary},
-#else
- [__pse51_check_init] = {&__pthread_mutex_check_init, __xn_exec_any},
-#endif
[__pse51_mutex_unlock] = {&__pthread_mutex_unlock, __xn_exec_primary|__xn_exec_norestart},
[__pse51_cond_init] = {&__pthread_cond_init, __xn_exec_any},
[__pse51_cond_destroy] = {&__pthread_cond_destroy, __xn_exec_any},
@@ -2763,6 +2786,9 @@ static xnsysent_t __systab[] = {
[__pse51_condattr_setpshared] =
{&__pthread_condattr_setpshared, __xn_exec_any},
[__pse51_select] = {&__select, __xn_exec_primary},
+#ifdef CONFIG_XENO_FASTSEM
+ [__pse51_check_init] = {&__pthread_mutex_check_init, __xn_exec_any},
+#endif
};
static void __shadow_delete_hook(xnthread_t *thread)
Index: b/src/skins/posix/mutex.c
===================================================================
--- a/src/skins/posix/mutex.c
+++ b/src/skins/posix/mutex.c
@@ -301,7 +301,11 @@ int __wrap_pthread_mutex_trylock(pthread
++shadow->lockcnt;
err = 0;
}
- }
+ } else
+ do {
+ err = XENOMAI_SKINCALL1(__pse51_muxid,
+ __pse51_mutex_trylock, shadow);
+ } while (err == -EINTR);
out:
cb_read_unlock(&shadow->lock, s);
Index: b/include/posix/syscall.h
===================================================================
--- a/include/posix/syscall.h
+++ b/include/posix/syscall.h
@@ -46,7 +46,6 @@
#define __pse51_mutex_lock 20
#define __pse51_mutex_timedlock 21
#define __pse51_mutex_trylock 22
-#define __pse51_check_init __pse51_mutex_trylock
#define __pse51_mutex_unlock 23
#define __pse51_cond_init 24
#define __pse51_cond_destroy 25
@@ -102,6 +101,7 @@
#define __pse51_thread_getschedparam 75
#define __pse51_thread_kill 76
#define __pse51_select 77
+#define __pse51_check_init 78
#ifdef __KERNEL__
^ permalink raw reply [flat|nested] 26+ messages in thread
* [Xenomai-core] [RFC][PATCH 6/9] Add XNSYNCH_FWDROB
2008-09-01 8:53 [Xenomai-core] [PATCH 0/9] Fast mutex rework, native support Jan Kiszka
` (4 preceding siblings ...)
2008-09-01 8:54 ` [Xenomai-core] [RFC][PATCH 5/9] Allow lock stealing via pthread_mutex_trylock Jan Kiszka
@ 2008-09-01 8:57 ` Jan Kiszka
2008-09-01 10:00 ` Gilles Chanteperdrix
2008-09-01 9:01 ` [Xenomai-core] [RFC][PATCH 8/9] Native support for fast mutexes Jan Kiszka
` (2 subsequent siblings)
8 siblings, 1 reply; 26+ messages in thread
From: Jan Kiszka @ 2008-09-01 8:57 UTC (permalink / raw)
To: xenomai-core
Intermediate helper as long as skins implement fast locking and related
owner tracking on their own: Add 'forward XN_ROBBED state' to the caller
of xnsynch_sleep_on so that the correct owner can be looked up there.
---
include/nucleus/synch.h | 3 ++-
ksrc/nucleus/pod.c | 6 ++++--
ksrc/nucleus/synch.c | 18 +++++++++++++-----
3 files changed, 19 insertions(+), 8 deletions(-)
Index: b/include/nucleus/synch.h
===================================================================
--- a/include/nucleus/synch.h
+++ b/include/nucleus/synch.h
@@ -30,10 +30,11 @@
#define XNSYNCH_NOPIP 0x0
#define XNSYNCH_PIP 0x2
#define XNSYNCH_DREORD 0x4
+#define XNSYNCH_FWDROB 0x8
#if defined(__KERNEL__) || defined(__XENO_SIM__)
-#define XNSYNCH_CLAIMED 0x8 /* Claimed by other thread(s) w/ PIP */
+#define XNSYNCH_CLAIMED 0x10 /* Claimed by other thread(s) w/ PIP */
/* Spare flags usable by upper interfaces */
#define XNSYNCH_SPARE0 0x01000000
Index: b/ksrc/nucleus/synch.c
===================================================================
--- a/ksrc/nucleus/synch.c
+++ b/ksrc/nucleus/synch.c
@@ -231,12 +231,20 @@ redo:
if (xnthread_test_info(thread, XNROBBED)) {
/* Somebody stole us the ownership while we were ready
to run, waiting for the CPU: we need to wait again
- for the resource. */
- if (timeout_mode != XN_RELATIVE || timeout == XN_INFINITE)
- goto redo;
+ for the resource, here or at caller site. */
+ if (timeout_mode != XN_RELATIVE || timeout == XN_INFINITE) {
+ if (testbits(synch->status, XNSYNCH_FWDROB))
+ goto unlock_and_exit;
+ else
+ goto redo;
+ }
timeout = xntimer_get_timeout_stopped(&thread->rtimer);
- if (timeout > 1) /* Otherwise, it's too late. */
- goto redo;
+ if (timeout > 1) { /* Otherwise, it's too late. */
+ if (testbits(synch->status, XNSYNCH_FWDROB))
+ goto unlock_and_exit;
+ else
+ goto redo;
+ }
xnthread_set_info(thread, XNTIMEO);
}
Index: b/ksrc/nucleus/pod.c
===================================================================
--- a/ksrc/nucleus/pod.c
+++ b/ksrc/nucleus/pod.c
@@ -1400,13 +1400,15 @@ void xnpod_suspend_thread(xnthread_t *th
"(thread=%s, mask=%lx)?!",
thread->name, mask);
);
- xnthread_clear_info(thread, XNRMID | XNTIMEO);
+ xnthread_clear_info(thread,
+ XNRMID | XNTIMEO | XNROBBED);
xnthread_set_info(thread, XNBREAK);
goto unlock_and_exit;
}
#endif /* CONFIG_XENO_OPT_PERVASIVE */
- xnthread_clear_info(thread, XNRMID | XNTIMEO | XNBREAK | XNWAKEN | XNROBBED);
+ xnthread_clear_info(thread, XNRMID | XNTIMEO | XNBREAK |
+ XNWAKEN | XNROBBED);
}
/* Don't start the timer for a thread indefinitely delayed by
^ permalink raw reply [flat|nested] 26+ messages in thread
* [Xenomai-core] [RFC][PATCH 8/9] Native support for fast mutexes
2008-09-01 8:53 [Xenomai-core] [PATCH 0/9] Fast mutex rework, native support Jan Kiszka
` (5 preceding siblings ...)
2008-09-01 8:57 ` [Xenomai-core] [RFC][PATCH 6/9] Add XNSYNCH_FWDROB Jan Kiszka
@ 2008-09-01 9:01 ` Jan Kiszka
2008-09-05 8:36 ` [Xenomai-core] [RFC][PATCH 8/9] Native support for fast mutexes - v2 Jan Kiszka
2008-09-01 9:06 ` [Xenomai-core] [RFC][PATCH 9/9] Optimize xnsynch_sleep_on for XN_NONBLOCK Jan Kiszka
2008-09-01 9:12 ` [Xenomai-core] [RFC][PATCH 7/9] Switch POSIX mutexes to XNSYNCH_FWDROB Jan Kiszka
8 siblings, 1 reply; 26+ messages in thread
From: Jan Kiszka @ 2008-09-01 9:01 UTC (permalink / raw)
To: xenomai-core
Analogously to POSIX, this patch adds fast mutex support to the native
skin.
---
include/native/mutex.h | 29 +++-
ksrc/skins/native/cond.c | 17 +-
ksrc/skins/native/mutex.c | 305 ++++++++++++++++++++++++++++++--------------
ksrc/skins/native/syscall.c | 71 ++++++++--
src/skins/native/cond.c | 28 +++-
src/skins/native/mutex.c | 103 +++++++++++++-
6 files changed, 422 insertions(+), 131 deletions(-)
Index: b/include/native/mutex.h
===================================================================
--- a/include/native/mutex.h
+++ b/include/native/mutex.h
@@ -44,9 +44,22 @@ typedef struct rt_mutex_info {
} RT_MUTEX_INFO;
typedef struct rt_mutex_placeholder {
+
xnhandle_t opaque;
+
+#ifdef CONFIG_XENO_FASTSEM
+ xnarch_atomic_t *fast_lock;
+
+ int lockcnt;
+#endif /* CONFIG_XENO_FASTSEM */
+
} RT_MUTEX_PLACEHOLDER;
+#define __rt_mutex_is_claimed(state) ((state) & XN_HANDLE_SPARE3)
+#define __rt_mutex_mask_claimed(state) ((state) & ~XN_HANDLE_SPARE3)
+#define __rt_mutex_set_claimed(state, bit) \
+ (((state) & ~XN_HANDLE_SPARE3) | ((bit) ? XN_HANDLE_SPARE3 : 0))
+
#if (defined(__KERNEL__) || defined(__XENO_SIM__)) && !defined(DOXYGEN_CPP)
#include <nucleus/synch.h>
@@ -54,10 +67,16 @@ typedef struct rt_mutex_placeholder {
#define XENO_MUTEX_MAGIC 0x55550505
+#define RT_MUTEX_EXPORTED XNSYNCH_SPARE0 /* Mutex registered by name */
+
typedef struct __rt_mutex {
unsigned magic; /* !< Magic code - must be first */
+#ifdef CONFIG_XENO_FASTSEM
+ xnarch_atomic_t *fast_lock; /* !< Address of fast-path lock */
+#endif /* CONFIG_XENO_FASTSEM */
+
xnsynch_t synch_base; /* !< Base synchronization object. */
xnhandle_t handle; /* !< Handle in registry -- zero if unregistered. */
@@ -74,7 +93,7 @@ typedef struct __rt_mutex {
#define rlink2mutex(ln) container_of(ln, RT_MUTEX, rlink)
- xnqueue_t *rqueue; /* !< Backpointer to resource queue. */
+ xnqueue_t *rqueue; /* !< Backpointer to resource queue. */
} RT_MUTEX;
@@ -93,9 +112,8 @@ static inline void __native_mutex_flush_
xeno_flush_rq(RT_MUTEX, rq, mutex);
}
-int rt_mutex_acquire_inner(RT_MUTEX *mutex,
- xntmode_t timeout_mode,
- RTIME timeout);
+int rt_mutex_acquire_inner(RT_MUTEX *mutex, RTIME timeout,
+ xntmode_t timeout_mode);
#else /* !CONFIG_XENO_OPT_NATIVE_MUTEX */
@@ -138,6 +156,9 @@ static inline int rt_mutex_unbind (RT_MU
extern "C" {
#endif
+int rt_mutex_create_inner(RT_MUTEX *mutex, const char *name);
+int rt_mutex_delete_inner(RT_MUTEX *mutex);
+
/* Public interface. */
int rt_mutex_create(RT_MUTEX *mutex,
Index: b/ksrc/skins/native/mutex.c
===================================================================
--- a/ksrc/skins/native/mutex.c
+++ b/ksrc/skins/native/mutex.c
@@ -120,49 +120,7 @@ static xnpnode_t __mutex_pnode = {
#endif /* CONFIG_XENO_EXPORT_REGISTRY */
-/**
- * @fn int rt_mutex_create(RT_MUTEX *mutex,const char *name)
- *
- * @brief Create a mutex.
- *
- * Create a mutual exclusion object that allows multiple tasks to
- * synchronize access to a shared resource. A mutex is left in an
- * unlocked state after creation.
- *
- * @param mutex The address of a mutex descriptor Xenomai will use to
- * store the mutex-related data. This descriptor must always be valid
- * while the mutex is active therefore it must be allocated in
- * permanent memory.
- *
- * @param name An ASCII string standing for the symbolic name of the
- * mutex. When non-NULL and non-empty, this string is copied to a safe
- * place into the descriptor, and passed to the registry package if
- * enabled for indexing the created mutex.
- *
- * @return 0 is returned upon success. Otherwise:
- *
- * - -ENOMEM is returned if the system fails to get enough dynamic
- * memory from the global real-time heap in order to register the
- * mutex.
- *
- * - -EEXIST is returned if the @a name is already in use by some
- * registered object.
- *
- * - -EPERM is returned if this service was called from an
- * asynchronous context.
- *
- * Environments:
- *
- * This service can be called from:
- *
- * - Kernel module initialization/cleanup code
- * - Kernel-based task
- * - User-space task
- *
- * Rescheduling: possible.
- */
-
-int rt_mutex_create(RT_MUTEX *mutex, const char *name)
+int rt_mutex_create_inner(RT_MUTEX *mutex, const char *name)
{
int err = 0;
spl_t s;
@@ -170,7 +128,8 @@ int rt_mutex_create(RT_MUTEX *mutex, con
if (xnpod_asynch_p())
return -EPERM;
- xnsynch_init(&mutex->synch_base, XNSYNCH_PRIO | XNSYNCH_PIP);
+ xnsynch_init(&mutex->synch_base,
+ XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_FWDROB);
mutex->handle = 0; /* i.e. (still) unregistered mutex. */
mutex->magic = XENO_MUTEX_MAGIC;
mutex->lockcnt = 0;
@@ -185,6 +144,10 @@ int rt_mutex_create(RT_MUTEX *mutex, con
mutex->cpid = 0;
#endif /* CONFIG_XENO_OPT_PERVASIVE */
+#ifdef CONFIG_XENO_FASTSEM
+ xnarch_atomic_set(mutex->fast_lock, XN_NO_HANDLE);
+#endif /* CONFIG_XENO_FASTSEM */
+
#ifdef CONFIG_XENO_OPT_REGISTRY
/* <!> Since xnregister_enter() may reschedule, only register
complete objects, so that the registry cannot return handles to
@@ -195,7 +158,7 @@ int rt_mutex_create(RT_MUTEX *mutex, con
&__mutex_pnode);
if (err)
- rt_mutex_delete(mutex);
+ rt_mutex_delete_inner(mutex);
}
#endif /* CONFIG_XENO_OPT_REGISTRY */
@@ -203,22 +166,32 @@ int rt_mutex_create(RT_MUTEX *mutex, con
}
/**
- * @fn int rt_mutex_delete(RT_MUTEX *mutex)
+ * @fn int rt_mutex_create(RT_MUTEX *mutex,const char *name)
*
- * @brief Delete a mutex.
+ * @brief Create a mutex.
*
- * Destroy a mutex and release all the tasks currently pending on it.
- * A mutex exists in the system since rt_mutex_create() has been
- * called to create it, so this service must be called in order to
- * destroy it afterwards.
+ * Create a mutual exclusion object that allows multiple tasks to
+ * synchronize access to a shared resource. A mutex is left in an
+ * unlocked state after creation.
*
- * @param mutex The descriptor address of the affected mutex.
+ * @param mutex The address of a mutex descriptor Xenomai will use to
+ * store the mutex-related data. This descriptor must always be valid
+ * while the mutex is active therefore it must be allocated in
+ * permanent memory.
+ *
+ * @param name An ASCII string standing for the symbolic name of the
+ * mutex. When non-NULL and non-empty, this string is copied to a safe
+ * place into the descriptor, and passed to the registry package if
+ * enabled for indexing the created mutex.
*
* @return 0 is returned upon success. Otherwise:
*
- * - -EINVAL is returned if @a mutex is not a mutex descriptor.
+ * - -ENOMEM is returned if the system fails to get enough dynamic
+ * memory from the global real-time heap in order to register the
+ * mutex.
*
- * - -EIDRM is returned if @a mutex is a deleted mutex descriptor.
+ * - -EEXIST is returned if the @a name is already in use by some
+ * registered object.
*
* - -EPERM is returned if this service was called from an
* asynchronous context.
@@ -234,7 +207,29 @@ int rt_mutex_create(RT_MUTEX *mutex, con
* Rescheduling: possible.
*/
-int rt_mutex_delete(RT_MUTEX *mutex)
+int rt_mutex_create(RT_MUTEX *mutex, const char *name)
+{
+ int err;
+
+#ifdef CONFIG_XENO_FASTSEM
+ /* Allocate lock memory for in-kernel use */
+ mutex->fast_lock = xnmalloc(sizeof(xnarch_atomic_t));
+
+ if (!mutex->fast_lock)
+ return -ENOMEM;
+#endif /* CONFIG_XENO_FASTSEM */
+
+ err = rt_mutex_create_inner(mutex, name);
+
+#ifdef CONFIG_XENO_FASTSEM
+ if (err)
+ xnfree(mutex->fast_lock);
+#endif /* CONFIG_XENO_FASTSEM */
+
+ return err;
+}
+
+int rt_mutex_delete_inner(RT_MUTEX *mutex)
{
int err = 0, rc;
spl_t s;
@@ -274,15 +269,84 @@ int rt_mutex_delete(RT_MUTEX *mutex)
return err;
}
-int rt_mutex_acquire_inner(RT_MUTEX *mutex, xntmode_t timeout_mode, RTIME timeout)
+/**
+ * @fn int rt_mutex_delete(RT_MUTEX *mutex)
+ *
+ * @brief Delete a mutex.
+ *
+ * Destroy a mutex and release all the tasks currently pending on it.
+ * A mutex exists in the system since rt_mutex_create() has been
+ * called to create it, so this service must be called in order to
+ * destroy it afterwards.
+ *
+ * @param mutex The descriptor address of the affected mutex.
+ *
+ * @return 0 is returned upon success. Otherwise:
+ *
+ * - -EINVAL is returned if @a mutex is not a mutex descriptor.
+ *
+ * - -EIDRM is returned if @a mutex is a deleted mutex descriptor.
+ *
+ * - -EPERM is returned if this service was called from an
+ * asynchronous context.
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Kernel-based task
+ * - User-space task
+ *
+ * Rescheduling: possible.
+ */
+
+int rt_mutex_delete(RT_MUTEX *mutex)
{
- xnthread_t *thread;
- int err = 0;
+ int err;
+
+ err = rt_mutex_delete_inner(mutex);
+
+#ifdef CONFIG_XENO_FASTSEM
+ if (!err)
+ xnfree(mutex->fast_lock);
+#endif /* CONFIG_XENO_FASTSEM */
+
+ return err;
+}
+
+int rt_mutex_acquire_inner(RT_MUTEX *mutex, RTIME timeout,
+ xntmode_t timeout_mode)
+{
+ xnhandle_t fast_lock, threadh, old;
+ xnthread_t *thread, *owner;
+ int err;
spl_t s;
if (xnpod_unblockable_p())
return -EPERM;
+ thread = xnpod_current_thread();
+ threadh = xnthread_handle(thread);
+
+ retry:
+
+ fast_lock =
+ xnarch_atomic_cmpxchg(mutex->fast_lock, XN_NO_HANDLE, threadh);
+
+ if (likely(!fast_lock)) {
+ mutex->lockcnt = 1;
+ return 0;
+ }
+
+ if (__rt_mutex_mask_claimed(fast_lock) == threadh) {
+ if (mutex->lockcnt == UINT_MAX)
+ return -EAGAIN;
+
+ mutex->lockcnt++;
+ return 0;
+ }
+
xnlock_get_irqsave(&nklock, s);
mutex = xeno_h2obj_validate(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
@@ -292,42 +356,77 @@ int rt_mutex_acquire_inner(RT_MUTEX *mut
goto unlock_and_exit;
}
- thread = xnpod_current_thread();
-
- if (xnsynch_owner(&mutex->synch_base) == NULL) {
- xnsynch_set_owner(&mutex->synch_base, thread);
- goto grab_mutex;
+ /* Set bit 0, so that mutex_unlock will know that the mutex is
+ claimed. */
+ fast_lock = xnarch_atomic_get(mutex->fast_lock);
+ while (!__rt_mutex_is_claimed(fast_lock)) {
+ old = xnarch_atomic_cmpxchg(mutex->fast_lock, fast_lock,
+ __rt_mutex_set_claimed(fast_lock,
+ 1));
+ if (likely(old == fast_lock))
+ break;
+ if (fast_lock == 0) {
+ /* Owner called fast mutex release (on another cpu) */
+ xnlock_put_irqrestore(&nklock, s);
+ goto retry;
+ }
+ fast_lock = old;
}
- if (xnsynch_owner(&mutex->synch_base) == thread) {
- mutex->lockcnt++;
- goto unlock_and_exit;
- }
+ owner = xnregistry_fetch(__rt_mutex_mask_claimed(fast_lock));
- if (timeout == TM_NONBLOCK) {
- err = -EWOULDBLOCK;
- goto unlock_and_exit;
+ /* Consistency check for owner handle - is the object a thread? */
+ if (unlikely(!owner ||
+ xnthread_handle(owner) !=
+ __rt_mutex_mask_claimed(fast_lock))) {
+ err = -EINVAL;
+ goto cleanup_and_exit;
}
+ xnsynch_set_owner(&mutex->synch_base, owner);
xnsynch_sleep_on(&mutex->synch_base, timeout, timeout_mode);
- if (xnthread_test_info(thread, XNRMID))
+ if (unlikely
+ (xnthread_test_info(thread,
+ XNBREAK | XNRMID | XNROBBED | XNTIMEO))) {
+ if (xnthread_test_info(thread, XNROBBED)) {
+ xnlock_put_irqrestore(&nklock, s);
+ goto retry;
+ }
+ if (xnthread_test_info(thread, XNTIMEO)) {
+ if (timeout_mode == XN_RELATIVE &&
+ timeout == XN_NONBLOCK)
+ err = -EWOULDBLOCK;
+ else
+ err = -ETIMEDOUT;
+ goto cleanup_and_exit;
+ }
+ if (xnthread_test_info(thread, XNBREAK)) {
+ err = -EINTR; /* Forcibly unblocked. */
+ goto cleanup_and_exit;
+ }
err = -EIDRM; /* Mutex deleted while pending. */
- else if (xnthread_test_info(thread, XNTIMEO))
- err = -ETIMEDOUT; /* Timeout. */
- else if (xnthread_test_info(thread, XNBREAK))
- err = -EINTR; /* Unblocked. */
- else {
- grab_mutex:
- /* xnsynch_sleep_on() might have stolen the resource,
- so we need to put our internal data in sync. */
- mutex->lockcnt = 1;
+ goto cleanup_and_exit;
}
- unlock_and_exit:
+ if (xnsynch_nsleepers(&mutex->synch_base))
+ threadh = __rt_mutex_set_claimed(threadh, 1);
+ xnarch_atomic_set(mutex->fast_lock, threadh);
+ mutex->lockcnt = 1;
xnlock_put_irqrestore(&nklock, s);
+ return 0;
+ cleanup_and_exit:
+
+ if (!xnsynch_nsleepers(&mutex->synch_base))
+ xnarch_atomic_set(mutex->fast_lock,
+ __rt_mutex_mask_claimed(xnarch_atomic_get
+ (mutex->fast_lock)));
+
+ unlock_and_exit:
+
+ xnlock_put_irqrestore(&nklock, s);
return err;
}
@@ -397,7 +496,7 @@ int rt_mutex_acquire_inner(RT_MUTEX *mut
int rt_mutex_acquire(RT_MUTEX *mutex, RTIME timeout)
{
- return rt_mutex_acquire_inner(mutex, XN_RELATIVE, timeout);
+ return rt_mutex_acquire_inner(mutex, timeout, XN_RELATIVE);
}
/**
@@ -463,7 +562,7 @@ int rt_mutex_acquire(RT_MUTEX *mutex, RT
int rt_mutex_acquire_until(RT_MUTEX *mutex, RTIME timeout)
{
- return rt_mutex_acquire_inner(mutex, XN_REALTIME, timeout);
+ return rt_mutex_acquire_inner(mutex, timeout, XN_REALTIME);
}
/**
@@ -500,12 +599,30 @@ int rt_mutex_acquire_until(RT_MUTEX *mut
int rt_mutex_release(RT_MUTEX *mutex)
{
- int err = 0;
+ xnhandle_t threadh, ownerh;
+ xnthread_t *owner;
+ int err;
spl_t s;
if (xnpod_unblockable_p())
return -EPERM;
+ threadh = xnthread_handle(xnpod_current_thread());
+
+ if (__rt_mutex_mask_claimed(xnarch_atomic_get(mutex->fast_lock)) !=
+ threadh)
+ return -EPERM;
+
+ if (mutex->lockcnt > 1) {
+ mutex->lockcnt--;
+ return 0;
+ }
+
+ if (likely
+ (xnarch_atomic_cmpxchg(mutex->fast_lock, threadh, XN_NO_HANDLE) ==
+ threadh))
+ return 0;
+
xnlock_get_irqsave(&nklock, s);
mutex = xeno_h2obj_validate(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
@@ -515,18 +632,16 @@ int rt_mutex_release(RT_MUTEX *mutex)
goto unlock_and_exit;
}
- if (xnpod_current_thread() != xnsynch_owner(&mutex->synch_base)) {
- err = -EPERM;
- goto unlock_and_exit;
- }
-
- if (--mutex->lockcnt > 0)
- goto unlock_and_exit;
-
- if (xnsynch_wakeup_one_sleeper(&mutex->synch_base)) {
- mutex->lockcnt = 1;
+ owner = xnsynch_wakeup_one_sleeper(&mutex->synch_base);
+ if (owner) {
+ ownerh = __rt_mutex_set_claimed(xnthread_handle(owner),
+ xnsynch_nsleepers(&mutex->
+ synch_base));
+ xnarch_atomic_set(mutex->fast_lock, ownerh);
xnpod_schedule();
- }
+ } else
+ xnarch_atomic_set(mutex->fast_lock, XN_NO_HANDLE);
+ err = 0;
unlock_and_exit:
Index: b/ksrc/skins/native/syscall.c
===================================================================
--- a/ksrc/skins/native/syscall.c
+++ b/ksrc/skins/native/syscall.c
@@ -24,6 +24,7 @@
#include <nucleus/heap.h>
#include <nucleus/shadow.h>
#include <nucleus/registry.h>
+#include <nucleus/sys_ppd.h>
#include <native/syscall.h>
#include <native/task.h>
#include <native/timer.h>
@@ -1527,6 +1528,7 @@ static int __rt_event_inquire(struct pt_
static int __rt_mutex_create(struct pt_regs *regs)
{
char name[XNOBJECT_NAME_LEN];
+ xnheap_t *sem_heap;
RT_MUTEX_PLACEHOLDER ph;
RT_MUTEX *mutex;
int err;
@@ -1541,22 +1543,47 @@ static int __rt_mutex_create(struct pt_r
} else
*name = '\0';
+ sem_heap = &xnsys_ppd_get(*name != '\0')->sem_heap;
+
mutex = (RT_MUTEX *)xnmalloc(sizeof(*mutex));
if (!mutex)
return -ENOMEM;
- err = rt_mutex_create(mutex, name);
+#ifdef CONFIG_XENO_FASTSEM
+ mutex->fast_lock = xnheap_alloc(sem_heap, sizeof(xnarch_atomic_t));
+
+ if (!mutex->fast_lock) {
+ xnfree(mutex);
+ return -ENOMEM;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
+ err = rt_mutex_create_inner(mutex, name);
if (err == 0) {
mutex->cpid = current->pid;
/* Copy back the registry handle to the ph struct. */
ph.opaque = mutex->handle;
+#ifdef CONFIG_XENO_FASTSEM
+ /* The lock address will be finished in user space. */
+ ph.fast_lock =
+ (void *)xnheap_mapped_offset(sem_heap,
+ mutex->fast_lock);
+ if (*name != '\0')
+ xnsynch_set_flags(&mutex->synch_base,
+ RT_MUTEX_EXPORTED);
+#endif /* CONFIG_XENO_FASTSEM */
if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg1(regs), &ph,
sizeof(ph)))
err = -EFAULT;
- } else
+ } else {
+#ifdef CONFIG_XENO_FASTSEM
+ xnheap_free(&xnsys_ppd_get(*name != '\0')->sem_heap,
+ mutex->fast_lock);
+#endif /* CONFIG_XENO_FASTSEM */
xnfree(mutex);
+ }
return err;
}
@@ -1570,15 +1597,22 @@ static int __rt_mutex_create(struct pt_r
static int __rt_mutex_bind(struct pt_regs *regs)
{
RT_MUTEX_PLACEHOLDER ph;
+ RT_MUTEX *mutex;
int err;
err =
__rt_bind_helper(current, regs, &ph.opaque, XENO_MUTEX_MAGIC,
- NULL, 0);
+ (void **)&mutex, 0);
if (err)
return err;
+#ifdef CONFIG_XENO_FASTSEM
+ ph.fast_lock =
+ (void *)xnheap_mapped_offset(&xnsys_ppd_get(1)->sem_heap,
+ mutex->fast_lock);
+#endif /* CONFIG_XENO_FASTSEM */
+
if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg1(regs), &ph,
sizeof(ph)))
return -EFAULT;
@@ -1605,10 +1639,17 @@ static int __rt_mutex_delete(struct pt_r
if (!mutex)
return -ESRCH;
- err = rt_mutex_delete(mutex);
+ err = rt_mutex_delete_inner(mutex);
- if (!err && mutex->cpid)
+ if (!err && mutex->cpid) {
+#ifdef CONFIG_XENO_FASTSEM
+ int global = xnsynch_test_flags(&mutex->synch_base,
+ RT_MUTEX_EXPORTED);
+ xnheap_free(&xnsys_ppd_get(global)->sem_heap,
+ mutex->fast_lock);
+#endif /* CONFIG_XENO_FASTSEM */
xnfree(mutex);
+ }
return err;
}
@@ -1621,13 +1662,14 @@ static int __rt_mutex_delete(struct pt_r
static int __rt_mutex_acquire(struct pt_regs *regs)
{
- RT_MUTEX_PLACEHOLDER ph;
+ RT_MUTEX_PLACEHOLDER __user *ph;
xntmode_t timeout_mode;
+ xnhandle_t mutexh;
RT_MUTEX *mutex;
RTIME timeout;
- if (__xn_safe_copy_from_user(&ph, (void __user *)__xn_reg_arg1(regs),
- sizeof(ph)))
+ ph = (RT_MUTEX_PLACEHOLDER __user *)__xn_reg_arg1(regs);
+ if (__xn_safe_copy_from_user(&mutexh, &ph->opaque, sizeof(mutexh)))
return -EFAULT;
timeout_mode = __xn_reg_arg2(regs);
@@ -1636,12 +1678,12 @@ static int __rt_mutex_acquire(struct pt_
sizeof(timeout)))
return -EFAULT;
- mutex = (RT_MUTEX *)xnregistry_fetch(ph.opaque);
+ mutex = (RT_MUTEX *)xnregistry_fetch(mutexh);
if (!mutex)
return -ESRCH;
- return rt_mutex_acquire_inner(mutex, timeout_mode, timeout);
+ return rt_mutex_acquire_inner(mutex, timeout, timeout_mode);
}
/*
@@ -1650,14 +1692,15 @@ static int __rt_mutex_acquire(struct pt_
static int __rt_mutex_release(struct pt_regs *regs)
{
- RT_MUTEX_PLACEHOLDER ph;
+ RT_MUTEX_PLACEHOLDER __user *ph;
+ xnhandle_t mutexh;
RT_MUTEX *mutex;
- if (__xn_safe_copy_from_user(&ph, (void __user *)__xn_reg_arg1(regs),
- sizeof(ph)))
+ ph = (RT_MUTEX_PLACEHOLDER __user *)__xn_reg_arg1(regs);
+ if (__xn_safe_copy_from_user(&mutexh, &ph->opaque, sizeof(mutexh)))
return -EFAULT;
- mutex = (RT_MUTEX *)xnregistry_fetch(ph.opaque);
+ mutex = (RT_MUTEX *)xnregistry_fetch(mutexh);
if (!mutex)
return -ESRCH;
Index: b/src/skins/native/mutex.c
===================================================================
--- a/src/skins/native/mutex.c
+++ b/src/skins/native/mutex.c
@@ -16,21 +16,50 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
+#include <limits.h>
#include <native/syscall.h>
#include <native/mutex.h>
+#include <asm-generic/bits/current.h>
extern int __native_muxid;
+extern unsigned long xeno_sem_heap[2];
int rt_mutex_create(RT_MUTEX *mutex, const char *name)
{
- return XENOMAI_SKINCALL2(__native_muxid,
- __native_mutex_create, mutex, name);
+ int err;
+
+ err = XENOMAI_SKINCALL2(__native_muxid,
+ __native_mutex_create, mutex, name);
+
+#ifdef CONFIG_XENO_FASTSEM
+ if (!err) {
+ mutex->fast_lock = (xnarch_atomic_t *)
+ (xeno_sem_heap[(name && *name) ? 1 : 0] +
+ (unsigned long)mutex->fast_lock);
+ mutex->lockcnt = 0;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
+ return err;
}
int rt_mutex_bind(RT_MUTEX *mutex, const char *name, RTIME timeout)
{
- return XENOMAI_SKINCALL3(__native_muxid,
- __native_mutex_bind, mutex, name, &timeout);
+ int err;
+
+ err = XENOMAI_SKINCALL3(__native_muxid,
+ __native_mutex_bind, mutex, name, &timeout);
+
+#ifdef CONFIG_XENO_FASTSEM
+ if (!err) {
+ mutex->fast_lock = (xnarch_atomic_t *)
+ (xeno_sem_heap[(name && *name) ? 1 : 0] +
+ (unsigned long)mutex->fast_lock);
+ mutex->lockcnt = 0;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
+ return err;
}
int rt_mutex_delete(RT_MUTEX *mutex)
@@ -38,20 +67,78 @@ int rt_mutex_delete(RT_MUTEX *mutex)
return XENOMAI_SKINCALL1(__native_muxid, __native_mutex_delete, mutex);
}
+static int rt_mutex_acquire_inner(RT_MUTEX *mutex, RTIME timeout, xntmode_t mode)
+{
+ int err;
+#ifdef CONFIG_XENO_FASTSEM
+ xnhandle_t cur, fast_lock;
+
+ cur = xeno_get_current();
+ if (!cur)
+ return -EPERM;
+
+ fast_lock =
+ xnarch_atomic_cmpxchg(mutex->fast_lock, XN_NO_HANDLE, cur);
+
+ if (likely(fast_lock == 0)) {
+ mutex->lockcnt = 1;
+ return 0;
+ }
+
+ if (__rt_mutex_mask_claimed(fast_lock) == cur) {
+ if (mutex->lockcnt == UINT_MAX)
+ return -EAGAIN;
+
+ mutex->lockcnt++;
+ return 0;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
+ err = XENOMAI_SKINCALL3(__native_muxid,
+ __native_mutex_acquire, mutex, mode, &timeout);
+
+#ifdef CONFIG_XENO_FASTSEM
+ if (!err)
+ mutex->lockcnt = 1;
+#endif /* CONFIG_XENO_FASTSEM */
+
+ return err;
+}
+
int rt_mutex_acquire(RT_MUTEX *mutex, RTIME timeout)
{
- return XENOMAI_SKINCALL3(__native_muxid,
- __native_mutex_acquire, mutex, XN_RELATIVE, &timeout);
+ return rt_mutex_acquire_inner(mutex, timeout, XN_RELATIVE);
}
int rt_mutex_acquire_until(RT_MUTEX *mutex, RTIME timeout)
{
- return XENOMAI_SKINCALL3(__native_muxid,
- __native_mutex_acquire, mutex, XN_REALTIME, &timeout);
+ return rt_mutex_acquire_inner(mutex, timeout, XN_REALTIME);
}
int rt_mutex_release(RT_MUTEX *mutex)
{
+#ifdef CONFIG_XENO_FASTSEM
+ xnhandle_t cur, fast_lock;
+
+ cur = xeno_get_current();
+ if (!cur)
+ return -EPERM;
+
+ fast_lock = xnarch_atomic_get(mutex->fast_lock);
+
+ if (unlikely(__rt_mutex_mask_claimed(fast_lock) != cur))
+ return -EPERM;
+
+ if (mutex->lockcnt > 1) {
+ mutex->lockcnt--;
+ return 0;
+ }
+
+ if (likely(xnarch_atomic_cmpxchg(mutex->fast_lock,
+ cur, XN_NO_HANDLE) == cur))
+ return 0;
+#endif /* CONFIG_XENO_FASTSEM */
+
return XENOMAI_SKINCALL1(__native_muxid, __native_mutex_release, mutex);
}
Index: b/ksrc/skins/native/cond.c
===================================================================
--- a/ksrc/skins/native/cond.c
+++ b/ksrc/skins/native/cond.c
@@ -378,8 +378,9 @@ int rt_cond_broadcast(RT_COND *cond)
int rt_cond_wait_inner(RT_COND *cond, RT_MUTEX *mutex,
xntmode_t timeout_mode, RTIME timeout)
{
+ xnhandle_t fast_lock, threadh;
+ xnthread_t *thread, *owner;
int err = 0, kicked = 0;
- xnthread_t *thread;
int lockcnt;
spl_t s;
@@ -406,8 +407,10 @@ int rt_cond_wait_inner(RT_COND *cond, RT
}
thread = xnpod_current_thread();
+ threadh = xnthread_handle(thread);
- if (thread != xnsynch_owner(&mutex->synch_base)) {
+ fast_lock = xnarch_atomic_get(mutex->fast_lock);
+ if (__rt_mutex_mask_claimed(fast_lock) != threadh) {
err = -EPERM;
goto unlock_and_exit;
}
@@ -421,8 +424,14 @@ int rt_cond_wait_inner(RT_COND *cond, RT
mutex->lockcnt = 0;
- if (xnsynch_wakeup_one_sleeper(&mutex->synch_base)) {
- mutex->lockcnt = 1;
+ if (unlikely
+ (xnarch_atomic_cmpxchg(mutex->fast_lock, threadh, XN_NO_HANDLE) !=
+ threadh)) {
+ owner = xnsynch_wakeup_one_sleeper(&mutex->synch_base);
+ xnarch_atomic_set(mutex->fast_lock,
+ __rt_mutex_set_claimed(xnthread_handle(owner),
+ xnsynch_nsleepers
+ (&mutex->synch_base)));
/* Scheduling deferred */
}
Index: b/src/skins/native/cond.c
===================================================================
--- a/src/skins/native/cond.c
+++ b/src/skins/native/cond.c
@@ -41,16 +41,32 @@ int rt_cond_delete(RT_COND *cond)
int rt_cond_wait(RT_COND *cond, RT_MUTEX *mutex, RTIME timeout)
{
- return XENOMAI_SKINCALL4(__native_muxid,
- __native_cond_wait, cond, mutex,
- XN_RELATIVE, &timeout);
+ int saved_lockcnt, err;
+
+ saved_lockcnt = mutex->lockcnt;
+
+ err = XENOMAI_SKINCALL4(__native_muxid,
+ __native_cond_wait, cond, mutex,
+ XN_RELATIVE, &timeout);
+
+ mutex->lockcnt = saved_lockcnt;
+
+ return err;
}
int rt_cond_wait_until(RT_COND *cond, RT_MUTEX *mutex, RTIME timeout)
{
- return XENOMAI_SKINCALL4(__native_muxid,
- __native_cond_wait, cond, mutex,
- XN_REALTIME, &timeout);
+ int saved_lockcnt, err;
+
+ saved_lockcnt = mutex->lockcnt;
+
+ err = XENOMAI_SKINCALL4(__native_muxid,
+ __native_cond_wait, cond, mutex,
+ XN_REALTIME, &timeout);
+
+ mutex->lockcnt = saved_lockcnt;
+
+ return err;
}
int rt_cond_signal(RT_COND *cond)
^ permalink raw reply [flat|nested] 26+ messages in thread
* [Xenomai-core] [RFC][PATCH 9/9] Optimize xnsynch_sleep_on for XN_NONBLOCK
2008-09-01 8:53 [Xenomai-core] [PATCH 0/9] Fast mutex rework, native support Jan Kiszka
` (6 preceding siblings ...)
2008-09-01 9:01 ` [Xenomai-core] [RFC][PATCH 8/9] Native support for fast mutexes Jan Kiszka
@ 2008-09-01 9:06 ` Jan Kiszka
2008-09-01 9:12 ` [Xenomai-core] [RFC][PATCH 7/9] Switch POSIX mutexes to XNSYNCH_FWDROB Jan Kiszka
8 siblings, 0 replies; 26+ messages in thread
From: Jan Kiszka @ 2008-09-01 9:06 UTC (permalink / raw)
To: xenomai-core
This patch improves the performance of xnsynch_sleep_on when it is
called with (XN_RELATIVE, XN_NONBLOCK) timeout parameters. For this
purpose, it introduces a new thread info XNNONBLCK that is set in case
xnsynch_sleep_on fails while in XN_NONBLOCK mode. Maybe this should be
solved via a dedicated trylock (but that would duplicate quite some
code), hopefully we can avoid it completely by doing lock stealing on
trylock via (generic) fast locks, even in user space.
---
include/nucleus/thread.h | 1 +
ksrc/nucleus/pod.c | 8 +++++---
ksrc/nucleus/synch.c | 20 +++++++++++++++++---
ksrc/skins/native/mutex.c | 13 +++++++------
ksrc/skins/posix/mutex.c | 5 +----
ksrc/skins/posix/mutex.h | 8 +++++++-
6 files changed, 38 insertions(+), 17 deletions(-)
Index: b/include/nucleus/thread.h
===================================================================
--- a/include/nucleus/thread.h
+++ b/include/nucleus/thread.h
@@ -116,6 +116,7 @@
#define XNROBBED 0x00000020 /**< Robbed from resource ownership */
#define XNATOMIC 0x00000040 /**< In atomic switch from secondary to primary mode */
#define XNAFFSET 0x00000080 /**< CPU affinity changed from primary mode */
+#define XNNONBLCK 0x00000100 /**< Non-blocking mode prevented suspension */
/* These information flags are available to the real-time interfaces */
#define XNTHREAD_INFO_SPARE0 0x10000000
Index: b/ksrc/nucleus/pod.c
===================================================================
--- a/ksrc/nucleus/pod.c
+++ b/ksrc/nucleus/pod.c
@@ -1401,14 +1401,16 @@ void xnpod_suspend_thread(xnthread_t *th
thread->name, mask);
);
xnthread_clear_info(thread,
- XNRMID | XNTIMEO | XNROBBED);
+ XNRMID | XNTIMEO | XNROBBED |
+ XNNONBLCK);
xnthread_set_info(thread, XNBREAK);
goto unlock_and_exit;
}
#endif /* CONFIG_XENO_OPT_PERVASIVE */
- xnthread_clear_info(thread, XNRMID | XNTIMEO | XNBREAK |
- XNWAKEN | XNROBBED);
+ xnthread_clear_info(thread,
+ XNRMID | XNTIMEO | XNBREAK | XNWAKEN |
+ XNROBBED | XNNONBLCK);
}
/* Don't start the timer for a thread indefinitely delayed by
Index: b/ksrc/nucleus/synch.c
===================================================================
--- a/ksrc/nucleus/synch.c
+++ b/ksrc/nucleus/synch.c
@@ -194,7 +194,8 @@ redo:
if (!owner) {
synch->owner = thread;
- xnthread_clear_info(thread, XNRMID | XNTIMEO | XNBREAK);
+ xnthread_clear_info(thread,
+ XNRMID | XNTIMEO | XNBREAK | XNNONBLCK);
goto unlock_and_exit;
}
@@ -202,11 +203,18 @@ redo:
if (xnthread_test_info(owner, XNWAKEN) && owner->wwake == synch) {
/* Ownership is still pending, steal the resource. */
synch->owner = thread;
- xnthread_clear_info(thread, XNRMID | XNTIMEO | XNBREAK);
+ xnthread_clear_info(thread,
+ XNRMID | XNTIMEO | XNBREAK |
+ XNNONBLCK);
xnthread_set_info(owner, XNROBBED);
goto unlock_and_exit;
}
+ if (timeout == XN_NONBLOCK && timeout_mode == XN_RELATIVE) {
+ xnthread_set_info(thread, XNNONBLCK);
+ goto unlock_and_exit;
+ }
+
if (!xnthread_test_state(owner, XNBOOST)) {
owner->bprio = owner->cprio;
xnthread_set_state(owner, XNBOOST);
@@ -220,8 +228,14 @@ redo:
insertpqf(&owner->claimq, &synch->link, thread->cprio);
insertpqf(&synch->pendq, &thread->plink, thread->cprio);
xnsynch_renice_thread(owner, thread->cprio);
- } else
+ } else {
+ if (timeout == XN_NONBLOCK && timeout_mode == XN_RELATIVE) {
+ xnthread_set_info(thread, XNNONBLCK);
+ goto unlock_and_exit;
+ }
+
insertpqf(&synch->pendq, &thread->plink, thread->cprio);
+ }
xnpod_suspend_thread(thread, XNPEND, timeout, timeout_mode, synch);
Index: b/ksrc/skins/native/mutex.c
===================================================================
--- a/ksrc/skins/native/mutex.c
+++ b/ksrc/skins/native/mutex.c
@@ -388,17 +388,18 @@ int rt_mutex_acquire_inner(RT_MUTEX *mut
if (unlikely
(xnthread_test_info(thread,
- XNBREAK | XNRMID | XNROBBED | XNTIMEO))) {
+ XNBREAK | XNNONBLCK | XNRMID | XNROBBED |
+ XNTIMEO))) {
+ if (xnthread_test_info(thread, XNNONBLCK)) {
+ err = -EWOULDBLOCK; /* Try-to-lock failed. */
+ goto cleanup_and_exit;
+ }
if (xnthread_test_info(thread, XNROBBED)) {
xnlock_put_irqrestore(&nklock, s);
goto retry;
}
if (xnthread_test_info(thread, XNTIMEO)) {
- if (timeout_mode == XN_RELATIVE &&
- timeout == XN_NONBLOCK)
- err = -EWOULDBLOCK;
- else
- err = -ETIMEDOUT;
+ err = -ETIMEDOUT;
goto cleanup_and_exit;
}
if (xnthread_test_info(thread, XNBREAK)) {
Index: b/ksrc/skins/posix/mutex.c
===================================================================
--- a/ksrc/skins/posix/mutex.c
+++ b/ksrc/skins/posix/mutex.c
@@ -406,13 +406,10 @@ int pthread_mutex_trylock(pthread_mutex_
err = 0;
}
}
- } else {
+ } else
err =
-pse51_mutex_timedlock_internal(cur, shadow, 1,
XN_RELATIVE, XN_NONBLOCK);
- if (err == ETIMEDOUT)
- err = EBUSY;
- }
cb_read_unlock(&shadow->lock, s);
Index: b/ksrc/skins/posix/mutex.h
===================================================================
--- a/ksrc/skins/posix/mutex.h
+++ b/ksrc/skins/posix/mutex.h
@@ -174,7 +174,13 @@ static inline int pse51_mutex_timedlock_
xnsynch_sleep_on(&mutex->synchbase, timeout, timeout_mode);
if (unlikely
- (xnthread_test_info(cur, XNBREAK | XNRMID | XNROBBED | XNTIMEO))) {
+ (xnthread_test_info(cur,
+ XNBREAK | XNNONBLCK | XNRMID | XNROBBED |
+ XNTIMEO))) {
+ if (xnthread_test_info(cur, XNNONBLCK)) {
+ err = -EBUSY;
+ goto error;
+ }
if (xnthread_test_info(cur, XNROBBED)) {
xnlock_put_irqrestore(&nklock, s);
goto retry_lock;
^ permalink raw reply [flat|nested] 26+ messages in thread
* [Xenomai-core] [RFC][PATCH 7/9] Switch POSIX mutexes to XNSYNCH_FWDROB
2008-09-01 8:53 [Xenomai-core] [PATCH 0/9] Fast mutex rework, native support Jan Kiszka
` (7 preceding siblings ...)
2008-09-01 9:06 ` [Xenomai-core] [RFC][PATCH 9/9] Optimize xnsynch_sleep_on for XN_NONBLOCK Jan Kiszka
@ 2008-09-01 9:12 ` Jan Kiszka
2008-09-01 10:01 ` Gilles Chanteperdrix
8 siblings, 1 reply; 26+ messages in thread
From: Jan Kiszka @ 2008-09-01 9:12 UTC (permalink / raw)
To: xenomai-core
Switch POSIX over to XNSYNCH_FWDROB, demonstrating the use of this flag
(and aligning the implementation for following native version). This can
save the syscall so far required on releasing a stolen mutex.
---
ksrc/skins/posix/mutex.c | 10 ++++++----
ksrc/skins/posix/mutex.h | 42 +++++++++++++++++++++++++-----------------
2 files changed, 31 insertions(+), 21 deletions(-)
Index: b/ksrc/skins/posix/mutex.c
===================================================================
--- a/ksrc/skins/posix/mutex.c
+++ b/ksrc/skins/posix/mutex.c
@@ -85,7 +85,7 @@ int pse51_mutex_init_internal(struct __s
xnarch_atomic_t *ownerp,
const pthread_mutexattr_t *attr)
{
- xnflags_t synch_flags = XNSYNCH_PRIO | XNSYNCH_NOPIP;
+ xnflags_t synch_flags = XNSYNCH_PRIO | XNSYNCH_NOPIP | XNSYNCH_FWDROB;
struct xnsys_ppd *sys_ppd;
pse51_kqueues_t *kq;
spl_t s;
@@ -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);
@@ -306,10 +305,8 @@ int pse51_mutex_timedlock_break(struct _
/* Attempting to relock a normal mutex, deadlock. */
xnlock_get_irqsave(&nklock, s);
for (;;) {
- ++mutex->sleepers;
xnsynch_sleep_on(&mutex->synchbase, timeout,
timeout_mode);
- --mutex->sleepers;
if (xnthread_test_info(cur, XNBREAK)) {
err = -EINTR;
@@ -326,6 +323,11 @@ int pse51_mutex_timedlock_break(struct _
break;
}
}
+ if (!xnsynch_nsleepers(&mutex->synchbase))
+ xnarch_atomic_set
+ (mutex->owner,
+ clear_claimed
+ (xnarch_atomic_get(mutex->owner)));
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,24 +171,30 @@ static inline int pse51_mutex_timedlock_
}
xnsynch_set_owner(&mutex->synchbase, owner);
- ++mutex->sleepers;
xnsynch_sleep_on(&mutex->synchbase, timeout, timeout_mode);
- --mutex->sleepers;
- if (xnthread_test_info(cur, XNBREAK)) {
- err = -EINTR;
- goto error;
- }
- if (xnthread_test_info(cur, XNRMID)) {
+ if (unlikely
+ (xnthread_test_info(cur, XNBREAK | XNRMID | XNROBBED | XNTIMEO))) {
+ if (xnthread_test_info(cur, XNROBBED)) {
+ xnlock_put_irqrestore(&nklock, s);
+ goto retry_lock;
+ }
+ if (xnthread_test_info(cur, XNTIMEO)) {
+ err = -ETIMEDOUT;
+ goto error;
+ }
+ if (xnthread_test_info(cur, XNBREAK)) {
+ err = -EINTR;
+ goto error;
+ }
+ /* XNRMID */
err = -EINVAL;
goto error;
}
- if (xnthread_test_info(cur, XNTIMEO)) {
- err = -ETIMEDOUT;
- goto error;
- }
- ownerh = set_claimed(xnthread_handle(cur), mutex->sleepers);
+ ownerh = xnthread_handle(cur);
+ if (xnsynch_nsleepers(&mutex->synchbase))
+ ownerh = set_claimed(ownerh, 1);
xnarch_atomic_set(mutex->owner, ownerh);
shadow->lockcnt = count;
xnlock_put_irqrestore(&nklock, s);
@@ -197,7 +202,7 @@ 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)));
@@ -218,10 +223,13 @@ 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);
- xnarch_atomic_set(mutex->owner, ownerh);
- if (owner)
+ if (owner) {
+ ownerh = set_claimed(xnthread_handle(owner),
+ xnsynch_nsleepers(&mutex->synchbase));
+ xnarch_atomic_set(mutex->owner, ownerh);
xnpod_schedule();
+ } else
+ xnarch_atomic_set(mutex->owner, XN_NO_HANDLE);
xnlock_put_irqrestore(&nklock, s);
}
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 5/9] Allow lock stealing via pthread_mutex_trylock
2008-09-01 8:54 ` [Xenomai-core] [RFC][PATCH 5/9] Allow lock stealing via pthread_mutex_trylock Jan Kiszka
@ 2008-09-01 9:58 ` Gilles Chanteperdrix
0 siblings, 0 replies; 26+ messages in thread
From: Gilles Chanteperdrix @ 2008-09-01 9:58 UTC (permalink / raw)
To: Jan Kiszka; +Cc: xenomai-core
Jan Kiszka wrote:
> By calling into the kernel in the contended case and exploiting
> XN_NONBLOCK for xnsynch_sleep_on, this patch adds lock stealing support
> to pthread_mutex_trylock.
>
> The latter part may change if we decide to go for a dedicates xnsynch
> trylock service. Maybe we are even lucky and able to implement lock
> stealing purely with the help of the fast lock algorithm. But we first
> have to merge fast locks into xnsynch to see clearer.
Nak. I can live without stealing for trylock in the mean time.
--
Gilles.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 6/9] Add XNSYNCH_FWDROB
2008-09-01 8:57 ` [Xenomai-core] [RFC][PATCH 6/9] Add XNSYNCH_FWDROB Jan Kiszka
@ 2008-09-01 10:00 ` Gilles Chanteperdrix
0 siblings, 0 replies; 26+ messages in thread
From: Gilles Chanteperdrix @ 2008-09-01 10:00 UTC (permalink / raw)
To: Jan Kiszka; +Cc: xenomai-core
Jan Kiszka wrote:
> Intermediate helper as long as skins implement fast locking and related
> owner tracking on their own: Add 'forward XN_ROBBED state' to the caller
> of xnsynch_sleep_on so that the correct owner can be looked up there.
Nak. We already discussed this with Philippe, XNROBBED is an internal
thing for xnsynch and should not leak to skins code. I actually happen
to find the current workaround cleaner.
--
Gilles.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [RFC][PATCH 7/9] Switch POSIX mutexes to XNSYNCH_FWDROB
2008-09-01 9:12 ` [Xenomai-core] [RFC][PATCH 7/9] Switch POSIX mutexes to XNSYNCH_FWDROB Jan Kiszka
@ 2008-09-01 10:01 ` Gilles Chanteperdrix
0 siblings, 0 replies; 26+ messages in thread
From: Gilles Chanteperdrix @ 2008-09-01 10:01 UTC (permalink / raw)
To: Jan Kiszka; +Cc: xenomai-core
Jan Kiszka wrote:
> Switch POSIX over to XNSYNCH_FWDROB, demonstrating the use of this flag
> (and aligning the implementation for following native version). This can
> save the syscall so far required on releasing a stolen mutex.
Nak.
--
Gilles.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners
2008-09-01 8:44 ` [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners Jan Kiszka
@ 2008-09-01 11:58 ` Gilles Chanteperdrix
2008-09-01 13:48 ` Jan Kiszka
2008-09-05 8:34 ` [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners - v2 Jan Kiszka
1 sibling, 1 reply; 26+ messages in thread
From: Gilles Chanteperdrix @ 2008-09-01 11:58 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 all skins (except for
> RTDM which must not mess around with foreign skins anyway) add their
> threads to the registry so that at least anonymous handles are
> available.
>
> 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.
The current implementation allows RTDM threads to use POSIX skin
mutexes. I do not see why this should change.
--
Gilles.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners
2008-09-01 11:58 ` Gilles Chanteperdrix
@ 2008-09-01 13:48 ` Jan Kiszka
2008-09-01 14:00 ` Gilles Chanteperdrix
0 siblings, 1 reply; 26+ messages in thread
From: Jan Kiszka @ 2008-09-01 13:48 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 all skins (except for
>> RTDM which must not mess around with foreign skins anyway) add their
>> threads to the registry so that at least anonymous handles are
>> available.
>>
>> 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.
>
> The current implementation allows RTDM threads to use POSIX skin
> mutexes. I do not see why this should change.
Such mixup might technically be possible now. But there is neither a
need nor does it make the resulting driver more portable. I don't want
to introduce needless thread registration to RTDM just to cover
theoretical use cases that should not exist in the first place.
Nevertheless, some sanity check will have to be added to the
to-be-written generic xnsynch support to catch missing thread handles.
That make sense for checking future skin implementation as well.
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners
2008-09-01 13:48 ` Jan Kiszka
@ 2008-09-01 14:00 ` Gilles Chanteperdrix
2008-09-01 14:03 ` Jan Kiszka
0 siblings, 1 reply; 26+ messages in thread
From: Gilles Chanteperdrix @ 2008-09-01 14:00 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 all skins (except for
>>> RTDM which must not mess around with foreign skins anyway) add their
>>> threads to the registry so that at least anonymous handles are
>>> available.
>>>
>>> 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.
>> The current implementation allows RTDM threads to use POSIX skin
>> mutexes. I do not see why this should change.
>
> Such mixup might technically be possible now. But there is neither a
> need nor does it make the resulting driver more portable. I don't want
> to introduce needless thread registration to RTDM just to cover
> theoretical use cases that should not exist in the first place.
>
> Nevertheless, some sanity check will have to be added to the
> to-be-written generic xnsynch support to catch missing thread handles.
> That make sense for checking future skin implementation as well.
That is overhead in the hot path, whereas adding the thread registration
takes place in a non hot path.
--
Gilles.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners
2008-09-01 14:00 ` Gilles Chanteperdrix
@ 2008-09-01 14:03 ` Jan Kiszka
2008-09-01 14:08 ` Jan Kiszka
2008-09-02 12:31 ` Gilles Chanteperdrix
0 siblings, 2 replies; 26+ messages in thread
From: Jan Kiszka @ 2008-09-01 14:03 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 all skins (except for
>>>> RTDM which must not mess around with foreign skins anyway) add their
>>>> threads to the registry so that at least anonymous handles are
>>>> available.
>>>>
>>>> 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.
>>> The current implementation allows RTDM threads to use POSIX skin
>>> mutexes. I do not see why this should change.
>> Such mixup might technically be possible now. But there is neither a
>> need nor does it make the resulting driver more portable. I don't want
>> to introduce needless thread registration to RTDM just to cover
>> theoretical use cases that should not exist in the first place.
>>
>> Nevertheless, some sanity check will have to be added to the
>> to-be-written generic xnsynch support to catch missing thread handles.
>> That make sense for checking future skin implementation as well.
>
> That is overhead in the hot path, whereas adding the thread registration
> takes place in a non hot path.
It will be a debug check.
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners
2008-09-01 14:03 ` Jan Kiszka
@ 2008-09-01 14:08 ` Jan Kiszka
2008-09-02 12:31 ` Gilles Chanteperdrix
1 sibling, 0 replies; 26+ messages in thread
From: Jan Kiszka @ 2008-09-01 14:08 UTC (permalink / raw)
To: Gilles Chanteperdrix; +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 all skins (except for
>>>>> RTDM which must not mess around with foreign skins anyway) add their
>>>>> threads to the registry so that at least anonymous handles are
>>>>> available.
>>>>>
>>>>> 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.
>>>> The current implementation allows RTDM threads to use POSIX skin
>>>> mutexes. I do not see why this should change.
>>> Such mixup might technically be possible now. But there is neither a
>>> need nor does it make the resulting driver more portable. I don't want
>>> to introduce needless thread registration to RTDM just to cover
>>> theoretical use cases that should not exist in the first place.
>>>
>>> Nevertheless, some sanity check will have to be added to the
>>> to-be-written generic xnsynch support to catch missing thread handles.
>>> That make sense for checking future skin implementation as well.
>> That is overhead in the hot path, whereas adding the thread registration
>> takes place in a non hot path.
>
> It will be a debug check.
On the other hand: Once we really have generic fast xnsynch support,
this discussion should become pointless - RTDM will use them for its own
mutexes as well. So let's look at this patch only for the current
situation where there is no need for RTDM threads to have a handle as
they must not mess with foreign skin objects.
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners
2008-09-01 14:03 ` Jan Kiszka
2008-09-01 14:08 ` Jan Kiszka
@ 2008-09-02 12:31 ` Gilles Chanteperdrix
1 sibling, 0 replies; 26+ messages in thread
From: Gilles Chanteperdrix @ 2008-09-02 12:31 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 all skins (except for
>>>>> RTDM which must not mess around with foreign skins anyway) add their
>>>>> threads to the registry so that at least anonymous handles are
>>>>> available.
>>>>>
>>>>> 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.
>>>> The current implementation allows RTDM threads to use POSIX skin
>>>> mutexes. I do not see why this should change.
>>> Such mixup might technically be possible now. But there is neither a
>>> need nor does it make the resulting driver more portable. I don't want
>>> to introduce needless thread registration to RTDM just to cover
>>> theoretical use cases that should not exist in the first place.
>>>
>>> Nevertheless, some sanity check will have to be added to the
>>> to-be-written generic xnsynch support to catch missing thread handles.
>>> That make sense for checking future skin implementation as well.
>> That is overhead in the hot path, whereas adding the thread registration
>> takes place in a non hot path.
>
> It will be a debug check.
Ok. But the other points remain.
--
Gilles.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners - v2
2008-09-01 8:44 ` [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners Jan Kiszka
2008-09-01 11:58 ` Gilles Chanteperdrix
@ 2008-09-05 8:34 ` Jan Kiszka
2008-09-05 9:40 ` Gilles Chanteperdrix
1 sibling, 1 reply; 26+ messages in thread
From: Jan Kiszka @ 2008-09-05 8:34 UTC (permalink / raw)
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 all skins (except for
> RTDM which must not mess around with foreign skins anyway) add their
> threads to the registry so that at least anonymous handles are
> available.
>
> 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.
>
>
> [ PS: I wonder if we can merge xnmap and xnregistry one day. Maybe there
> is a smart way to combine best of both, overcoming the redundancy. ]
Rebased on top of the claimed-bit-race fix.
---
include/asm-generic/bits/bind.h | 9 ++++-
include/asm-generic/bits/current.h | 5 +-
include/nucleus/types.h | 13 +++++++
ksrc/nucleus/shadow.c | 17 ++++++++-
ksrc/skins/native/Kconfig | 1
ksrc/skins/native/task.c | 14 +++-----
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 | 64 ++++++++++++++++++++++++-------------
ksrc/skins/posix/syscall.c | 11 +++---
ksrc/skins/posix/thread.c | 16 +++++++++
ksrc/skins/psos+/Kconfig | 2 -
ksrc/skins/rtai/Kconfig | 1
ksrc/skins/rtai/task.c | 12 ++++++
ksrc/skins/uitron/Kconfig | 1
ksrc/skins/uitron/task.c | 11 ++++++
ksrc/skins/vrtx/Kconfig | 2 -
ksrc/skins/vrtx/task.c | 20 ++++++++++-
ksrc/skins/vxworks/Kconfig | 2 -
src/skins/posix/mutex.c | 27 ++++++++-------
22 files changed, 201 insertions(+), 76 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>
@@ -1908,13 +1909,21 @@ static int xnshadow_sys_sem_heap(struct
return __xn_safe_copy_to_user(us_hinfo, &hinfo, sizeof(*us_hinfo));
}
+#ifdef CONFIG_XENO_OPT_REGISTRY
static int xnshadow_sys_current(struct pt_regs *regs)
{
- xnthread_t * __user *us_current, *cur = xnshadow_thread(current);
- us_current = (xnthread_t *__user *) __xn_reg_arg1(regs);
+ xnthread_t *cur = xnshadow_thread(current);
+ xnhandle_t __user *us_handle;
- return __xn_safe_copy_to_user(us_current, &cur, sizeof(*us_current));
+ if (!cur)
+ return -EPERM;
+
+ us_handle = (xnhandle_t __user *) __xn_reg_arg1(regs);
+
+ return __xn_safe_copy_to_user(us_handle, &xnthread_handle(cur),
+ sizeof(*us_handle));
}
+#endif /* CONFIG_XENO_OPT_REGISTRY */
static xnsysent_t __systab[] = {
[__xn_sys_migrate] = {&xnshadow_sys_migrate, __xn_exec_current},
@@ -1925,7 +1934,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,32 +136,41 @@ static inline int pse51_mutex_timedlock_
return PTR_ERR(owner);
mutex = shadow->mutex;
- if (clear_claimed(owner) == cur)
+ if (owner == cur)
return -EBUSY;
/* Set bit 0, so that mutex_unlock will know that the mutex is claimed.
Hold the nklock, for mutual exclusion with slow mutex_unlock. */
xnlock_get_irqsave(&nklock, s);
- if (test_claimed(owner)) {
- old = xnarch_atomic_intptr_get(mutex->owner);
+ if (test_claimed(ownerh)) {
+ old = xnarch_atomic_get(mutex->owner);
goto test_no_owner;
}
do {
- old = xnarch_atomic_intptr_cmpxchg(mutex->owner,
- owner, set_claimed(owner, 1));
- if (likely(old == owner))
+ old = xnarch_atomic_cmpxchg(mutex->owner, ownerh,
+ set_claimed(ownerh, 1));
+ if (likely(old == ownerh))
break;
test_no_owner:
- if (old == NULL) {
+ if (!old) {
/* Owner called fast mutex_unlock
(on another cpu) */
xnlock_put_irqrestore(&nklock, s);
goto retry_lock;
}
- owner = old;
- } while (!test_claimed(owner));
+ ownerh = old;
+ } while (!test_claimed(ownerh));
+
+ owner = xnregistry_fetch(clear_claimed(ownerh));
+
+ /* Consistency check for owner handle - is the object a thread? */
+ if (unlikely(!owner ||
+ 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);
@@ -174,7 +191,8 @@ static inline int pse51_mutex_timedlock_
goto error;
}
- xnarch_atomic_intptr_set(mutex->owner,set_claimed(cur, mutex->sleepers));
+ ownerh = set_claimed(xnthread_handle(cur), mutex->sleepers);
+ xnarch_atomic_set(mutex->owner, ownerh);
shadow->lockcnt = count;
xnlock_put_irqrestore(&nklock, s);
@@ -182,9 +200,9 @@ static inline int pse51_mutex_timedlock_
error:
if (!mutex->sleepers)
- xnarch_atomic_intptr_set
+ xnarch_atomic_set
(mutex->owner,
- clear_claimed(xnarch_atomic_intptr_get(mutex->owner)));
+ clear_claimed(xnarch_atomic_get(mutex->owner)));
xnlock_put_irqrestore(&nklock, s);
return err;
}
@@ -192,16 +210,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>
@@ -234,6 +235,21 @@ int pthread_create(pthread_t *tid,
thread->hkey.mm = NULL;
#endif /* CONFIG_XENO_OPT_PERVASIVE */
+#ifdef CONFIG_XENO_FASTSEM
+ /* We need an anonymous registry entry to obtain a handle for fast
+ mutex locking. */
+ {
+ int err =
+ xnregistry_enter("", &thread->threadbase,
+ &xnthread_handle(&thread->threadbase),
+ NULL);
+ if (err) {
+ thread_destroy(thread);
+ return err;
+ }
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
*tid = thread; /* Must be done before the thread is started. */
if (start) /* Do not start shadow threads (i.e. start == NULL). */
Index: b/ksrc/skins/posix/Kconfig
===================================================================
--- a/ksrc/skins/posix/Kconfig
+++ b/ksrc/skins/posix/Kconfig
@@ -1,5 +1,6 @@
menuconfig XENO_SKIN_POSIX
depends on XENO_OPT_NUCLEUS
+ select XENO_OPT_REGISTRY if XENO_FASTSEM
tristate "POSIX API"
default y
help
Index: b/include/asm-generic/bits/bind.h
===================================================================
--- a/include/asm-generic/bits/bind.h
+++ b/include/asm-generic/bits/bind.h
@@ -22,7 +22,14 @@ __attribute__ ((weak))
void xeno_set_current(void)
{
void *kthread_cb;
- XENOMAI_SYSCALL1(__xn_sys_current, &kthread_cb);
+ int err;
+
+ err = XENOMAI_SYSCALL1(__xn_sys_current, &kthread_cb);
+ if (err) {
+ fprintf(stderr, "Xenomai: error obtaining handle for current "
+ "thread: %s\n", strerror(err));
+ exit(1);
+ }
pthread_setspecific(xeno_current_key, kthread_cb);
}
Index: b/ksrc/skins/native/Kconfig
===================================================================
--- a/ksrc/skins/native/Kconfig
+++ b/ksrc/skins/native/Kconfig
@@ -1,5 +1,6 @@
menuconfig XENO_SKIN_NATIVE
depends on XENO_OPT_NUCLEUS
+ select XENO_OPT_REGISTRY if XENO_FASTSEM
tristate "Native API"
default y
help
Index: b/ksrc/skins/native/task.c
===================================================================
--- a/ksrc/skins/native/task.c
+++ b/ksrc/skins/native/task.c
@@ -290,14 +290,12 @@ int rt_task_create(RT_TASK *task,
complete objects, so that the registry cannot return handles to
half-baked objects... */
- if (name) {
- err = xnregistry_enter(task->rname,
- &task->thread_base,
- &xnthread_handle(&task->thread_base),
- NULL);
- if (err)
- xnpod_delete_thread(&task->thread_base);
- }
+ err = xnregistry_enter(name ? task->rname : "",
+ &task->thread_base,
+ &xnthread_handle(&task->thread_base),
+ NULL);
+ if (err)
+ xnpod_delete_thread(&task->thread_base);
#endif /* CONFIG_XENO_OPT_REGISTRY */
return err;
Index: b/ksrc/skins/psos+/Kconfig
===================================================================
--- a/ksrc/skins/psos+/Kconfig
+++ b/ksrc/skins/psos+/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_PSOS
depends on XENO_OPT_NUCLEUS
select XENO_OPT_TIMING_PERIODIC
tristate "pSOS+ emulator"
- select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE
+ select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSEM
help
This API skin emulates WindRiver's pSOS+ operating system.
Index: b/ksrc/skins/uitron/Kconfig
===================================================================
--- a/ksrc/skins/uitron/Kconfig
+++ b/ksrc/skins/uitron/Kconfig
@@ -2,6 +2,7 @@ menuconfig XENO_SKIN_UITRON
depends on XENO_OPT_NUCLEUS
select XENO_OPT_TIMING_PERIODIC
select XENO_OPT_MAP
+ select XENO_OPT_REGISTRY if XENO_FASTSEM
tristate "uITRON API"
help
Index: b/ksrc/skins/uitron/task.c
===================================================================
--- a/ksrc/skins/uitron/task.c
+++ b/ksrc/skins/uitron/task.c
@@ -151,6 +151,17 @@ ER cre_tsk(ID tskid, T_CTSK *pk_ctsk)
xnlock_put_irqrestore(&nklock, s);
task->magic = uITRON_TASK_MAGIC;
+#ifdef CONFIG_XENO_FASTSEM
+ /* We need an anonymous registry entry to obtain a handle for fast
+ mutex locking. */
+ if (xnregistry_enter("", &task->threadbase,
+ &xnthread_handle(&task->threadbase), NULL)) {
+ xnmap_remove(ui_task_idmap, tskid);
+ xnpod_abort_thread(&task->threadbase);
+ return E_NOMEM;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
return E_OK;
}
Index: b/ksrc/skins/rtai/Kconfig
===================================================================
--- a/ksrc/skins/rtai/Kconfig
+++ b/ksrc/skins/rtai/Kconfig
@@ -1,5 +1,6 @@
menuconfig XENO_SKIN_RTAI
depends on XENO_OPT_NUCLEUS
+ select XENO_OPT_REGISTRY if XENO_FASTSEM
tristate "RTAI emulator"
help
Index: b/ksrc/skins/rtai/task.c
===================================================================
--- a/ksrc/skins/rtai/task.c
+++ b/ksrc/skins/rtai/task.c
@@ -20,6 +20,7 @@
#include <nucleus/pod.h>
#include <nucleus/heap.h>
+#include <nucleus/registry.h>
#include <rtai/task.h>
static DEFINE_XNQUEUE(__rtai_task_q);
@@ -152,6 +153,17 @@ int rt_task_init(RT_TASK *task,
task->magic = RTAI_TASK_MAGIC;
appendq(&__rtai_task_q, &task->link);
+#ifdef CONFIG_XENO_FASTSEM
+ /* We need an anonymous registry entry to obtain a handle for fast
+ mutex locking. */
+ err = xnregistry_enter("", &task->thread_base,
+ &xnthread_handle(&task->thread_base), NULL);
+ if (err) {
+ xnpod_abort_thread(&task->thread_base);
+ goto unlock_and_exit;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
/* Add a switch hook only if a signal function has been declared
at least once for some created task. */
Index: b/ksrc/skins/vrtx/Kconfig
===================================================================
--- a/ksrc/skins/vrtx/Kconfig
+++ b/ksrc/skins/vrtx/Kconfig
@@ -3,7 +3,7 @@ menuconfig XENO_SKIN_VRTX
select XENO_OPT_TIMING_PERIODIC
select XENO_OPT_MAP
tristate "VRTX emulator"
- select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE
+ select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || CONFIG_XENO_FASTSEM
help
This API skin emulates Mentor Graphics's VRTX operating
Index: b/ksrc/skins/vrtx/task.c
===================================================================
--- a/ksrc/skins/vrtx/task.c
+++ b/ksrc/skins/vrtx/task.c
@@ -188,12 +188,28 @@ int sc_tecreate_inner(vrtxtask_t *task,
if (mode & 0x10)
bmode |= XNRRB;
- *errp = RET_OK;
-
xnlock_get_irqsave(&nklock, s);
appendq(&vrtx_task_q, &task->link);
xnlock_put_irqrestore(&nklock, s);
+#ifdef CONFIG_XENO_FASTSEM
+ /* We need an anonymous registry entry to obtain a handle for fast
+ mutex locking. */
+ {
+ int err =
+ xnregistry_enter("", &task->threadbase,
+ &xnthread_handle(&task->threadbase),
+ NULL);
+ if (err) {
+ xnpod_abort_thread(&task->threadbase);
+ *errp = ER_MEM;
+ return -1;
+ }
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
+ *errp = RET_OK;
+
xnpod_start_thread(&task->threadbase,
bmode, 0, XNPOD_ALL_CPUS, &vrtxtask_trampoline,
task);
Index: b/ksrc/skins/vxworks/Kconfig
===================================================================
--- a/ksrc/skins/vxworks/Kconfig
+++ b/ksrc/skins/vxworks/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_VXWORKS
depends on XENO_OPT_NUCLEUS
select XENO_OPT_TIMING_PERIODIC
tristate "VxWorks emulator"
- select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE
+ select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSEM
help
This API skin emulates WindRiver's VxWorks operating system.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [Xenomai-core] [RFC][PATCH 8/9] Native support for fast mutexes - v2
2008-09-01 9:01 ` [Xenomai-core] [RFC][PATCH 8/9] Native support for fast mutexes Jan Kiszka
@ 2008-09-05 8:36 ` Jan Kiszka
0 siblings, 0 replies; 26+ messages in thread
From: Jan Kiszka @ 2008-09-05 8:36 UTC (permalink / raw)
Cc: xenomai-core
Jan Kiszka wrote:
> Analogously to POSIX, this patch adds fast mutex support to the native
> skin.
For reference only: Updated to include the claimed-bit-race fix.
---
include/native/mutex.h | 31 +++-
ksrc/skins/native/cond.c | 17 +-
ksrc/skins/native/mutex.c | 339 ++++++++++++++++++++++++++++++--------------
ksrc/skins/native/syscall.c | 71 +++++++--
src/skins/native/cond.c | 28 ++-
src/skins/native/mutex.c | 103 ++++++++++++-
6 files changed, 448 insertions(+), 141 deletions(-)
Index: b/include/native/mutex.h
===================================================================
--- a/include/native/mutex.h
+++ b/include/native/mutex.h
@@ -32,7 +32,7 @@ struct rt_task;
*/
typedef struct rt_mutex_info {
- int lockcnt; /**< Lock nesting level (> 0 means "locked"). */
+ int locked; /**< > 0 if mutex is locked. */
int nwaiters; /**< Number of pending tasks. */
@@ -44,9 +44,22 @@ typedef struct rt_mutex_info {
} RT_MUTEX_INFO;
typedef struct rt_mutex_placeholder {
+
xnhandle_t opaque;
+
+#ifdef CONFIG_XENO_FASTSEM
+ xnarch_atomic_t *fast_lock;
+
+ int lockcnt;
+#endif /* CONFIG_XENO_FASTSEM */
+
} RT_MUTEX_PLACEHOLDER;
+#define __rt_mutex_is_claimed(state) ((state) & XN_HANDLE_SPARE3)
+#define __rt_mutex_mask_claimed(state) ((state) & ~XN_HANDLE_SPARE3)
+#define __rt_mutex_set_claimed(state, bit) \
+ (((state) & ~XN_HANDLE_SPARE3) | ((bit) ? XN_HANDLE_SPARE3 : 0))
+
#if (defined(__KERNEL__) || defined(__XENO_SIM__)) && !defined(DOXYGEN_CPP)
#include <nucleus/synch.h>
@@ -54,10 +67,16 @@ typedef struct rt_mutex_placeholder {
#define XENO_MUTEX_MAGIC 0x55550505
+#define RT_MUTEX_EXPORTED XNSYNCH_SPARE0 /* Mutex registered by name */
+
typedef struct __rt_mutex {
unsigned magic; /* !< Magic code - must be first */
+#ifdef CONFIG_XENO_FASTSEM
+ xnarch_atomic_t *fast_lock; /* !< Address of fast-path lock */
+#endif /* CONFIG_XENO_FASTSEM */
+
xnsynch_t synch_base; /* !< Base synchronization object. */
xnhandle_t handle; /* !< Handle in registry -- zero if unregistered. */
@@ -74,7 +93,7 @@ typedef struct __rt_mutex {
#define rlink2mutex(ln) container_of(ln, RT_MUTEX, rlink)
- xnqueue_t *rqueue; /* !< Backpointer to resource queue. */
+ xnqueue_t *rqueue; /* !< Backpointer to resource queue. */
} RT_MUTEX;
@@ -93,9 +112,8 @@ static inline void __native_mutex_flush_
xeno_flush_rq(RT_MUTEX, rq, mutex);
}
-int rt_mutex_acquire_inner(RT_MUTEX *mutex,
- xntmode_t timeout_mode,
- RTIME timeout);
+int rt_mutex_acquire_inner(RT_MUTEX *mutex, RTIME timeout,
+ xntmode_t timeout_mode);
#else /* !CONFIG_XENO_OPT_NATIVE_MUTEX */
@@ -138,6 +156,9 @@ static inline int rt_mutex_unbind (RT_MU
extern "C" {
#endif
+int rt_mutex_create_inner(RT_MUTEX *mutex, const char *name);
+int rt_mutex_delete_inner(RT_MUTEX *mutex);
+
/* Public interface. */
int rt_mutex_create(RT_MUTEX *mutex,
Index: b/ksrc/skins/native/mutex.c
===================================================================
--- a/ksrc/skins/native/mutex.c
+++ b/ksrc/skins/native/mutex.c
@@ -68,9 +68,8 @@ static int __mutex_read_proc(char *page,
/* Locked mutex -- dump owner and waiters, if any. */
- p += sprintf(p, "=locked by %s depth=%d\n",
- xnthread_name(xnsynch_owner(&mutex->synch_base)),
- mutex->lockcnt);
+ p += sprintf(p, "=locked by %s\n",
+ xnthread_name(xnsynch_owner(&mutex->synch_base)));
holder = getheadpq(xnsynch_wait_queue(&mutex->synch_base));
@@ -120,49 +119,7 @@ static xnpnode_t __mutex_pnode = {
#endif /* CONFIG_XENO_EXPORT_REGISTRY */
-/**
- * @fn int rt_mutex_create(RT_MUTEX *mutex,const char *name)
- *
- * @brief Create a mutex.
- *
- * Create a mutual exclusion object that allows multiple tasks to
- * synchronize access to a shared resource. A mutex is left in an
- * unlocked state after creation.
- *
- * @param mutex The address of a mutex descriptor Xenomai will use to
- * store the mutex-related data. This descriptor must always be valid
- * while the mutex is active therefore it must be allocated in
- * permanent memory.
- *
- * @param name An ASCII string standing for the symbolic name of the
- * mutex. When non-NULL and non-empty, this string is copied to a safe
- * place into the descriptor, and passed to the registry package if
- * enabled for indexing the created mutex.
- *
- * @return 0 is returned upon success. Otherwise:
- *
- * - -ENOMEM is returned if the system fails to get enough dynamic
- * memory from the global real-time heap in order to register the
- * mutex.
- *
- * - -EEXIST is returned if the @a name is already in use by some
- * registered object.
- *
- * - -EPERM is returned if this service was called from an
- * asynchronous context.
- *
- * Environments:
- *
- * This service can be called from:
- *
- * - Kernel module initialization/cleanup code
- * - Kernel-based task
- * - User-space task
- *
- * Rescheduling: possible.
- */
-
-int rt_mutex_create(RT_MUTEX *mutex, const char *name)
+int rt_mutex_create_inner(RT_MUTEX *mutex, const char *name)
{
int err = 0;
spl_t s;
@@ -170,7 +127,8 @@ int rt_mutex_create(RT_MUTEX *mutex, con
if (xnpod_asynch_p())
return -EPERM;
- xnsynch_init(&mutex->synch_base, XNSYNCH_PRIO | XNSYNCH_PIP);
+ xnsynch_init(&mutex->synch_base,
+ XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_FWDROB);
mutex->handle = 0; /* i.e. (still) unregistered mutex. */
mutex->magic = XENO_MUTEX_MAGIC;
mutex->lockcnt = 0;
@@ -185,6 +143,10 @@ int rt_mutex_create(RT_MUTEX *mutex, con
mutex->cpid = 0;
#endif /* CONFIG_XENO_OPT_PERVASIVE */
+#ifdef CONFIG_XENO_FASTSEM
+ xnarch_atomic_set(mutex->fast_lock, XN_NO_HANDLE);
+#endif /* CONFIG_XENO_FASTSEM */
+
#ifdef CONFIG_XENO_OPT_REGISTRY
/* <!> Since xnregister_enter() may reschedule, only register
complete objects, so that the registry cannot return handles to
@@ -195,7 +157,7 @@ int rt_mutex_create(RT_MUTEX *mutex, con
&__mutex_pnode);
if (err)
- rt_mutex_delete(mutex);
+ rt_mutex_delete_inner(mutex);
}
#endif /* CONFIG_XENO_OPT_REGISTRY */
@@ -203,22 +165,32 @@ int rt_mutex_create(RT_MUTEX *mutex, con
}
/**
- * @fn int rt_mutex_delete(RT_MUTEX *mutex)
+ * @fn int rt_mutex_create(RT_MUTEX *mutex,const char *name)
*
- * @brief Delete a mutex.
+ * @brief Create a mutex.
*
- * Destroy a mutex and release all the tasks currently pending on it.
- * A mutex exists in the system since rt_mutex_create() has been
- * called to create it, so this service must be called in order to
- * destroy it afterwards.
+ * Create a mutual exclusion object that allows multiple tasks to
+ * synchronize access to a shared resource. A mutex is left in an
+ * unlocked state after creation.
*
- * @param mutex The descriptor address of the affected mutex.
+ * @param mutex The address of a mutex descriptor Xenomai will use to
+ * store the mutex-related data. This descriptor must always be valid
+ * while the mutex is active therefore it must be allocated in
+ * permanent memory.
+ *
+ * @param name An ASCII string standing for the symbolic name of the
+ * mutex. When non-NULL and non-empty, this string is copied to a safe
+ * place into the descriptor, and passed to the registry package if
+ * enabled for indexing the created mutex.
*
* @return 0 is returned upon success. Otherwise:
*
- * - -EINVAL is returned if @a mutex is not a mutex descriptor.
+ * - -ENOMEM is returned if the system fails to get enough dynamic
+ * memory from the global real-time heap in order to register the
+ * mutex.
*
- * - -EIDRM is returned if @a mutex is a deleted mutex descriptor.
+ * - -EEXIST is returned if the @a name is already in use by some
+ * registered object.
*
* - -EPERM is returned if this service was called from an
* asynchronous context.
@@ -234,7 +206,29 @@ int rt_mutex_create(RT_MUTEX *mutex, con
* Rescheduling: possible.
*/
-int rt_mutex_delete(RT_MUTEX *mutex)
+int rt_mutex_create(RT_MUTEX *mutex, const char *name)
+{
+ int err;
+
+#ifdef CONFIG_XENO_FASTSEM
+ /* Allocate lock memory for in-kernel use */
+ mutex->fast_lock = xnmalloc(sizeof(xnarch_atomic_t));
+
+ if (!mutex->fast_lock)
+ return -ENOMEM;
+#endif /* CONFIG_XENO_FASTSEM */
+
+ err = rt_mutex_create_inner(mutex, name);
+
+#ifdef CONFIG_XENO_FASTSEM
+ if (err)
+ xnfree(mutex->fast_lock);
+#endif /* CONFIG_XENO_FASTSEM */
+
+ return err;
+}
+
+int rt_mutex_delete_inner(RT_MUTEX *mutex)
{
int err = 0, rc;
spl_t s;
@@ -274,15 +268,84 @@ int rt_mutex_delete(RT_MUTEX *mutex)
return err;
}
-int rt_mutex_acquire_inner(RT_MUTEX *mutex, xntmode_t timeout_mode, RTIME timeout)
+/**
+ * @fn int rt_mutex_delete(RT_MUTEX *mutex)
+ *
+ * @brief Delete a mutex.
+ *
+ * Destroy a mutex and release all the tasks currently pending on it.
+ * A mutex exists in the system since rt_mutex_create() has been
+ * called to create it, so this service must be called in order to
+ * destroy it afterwards.
+ *
+ * @param mutex The descriptor address of the affected mutex.
+ *
+ * @return 0 is returned upon success. Otherwise:
+ *
+ * - -EINVAL is returned if @a mutex is not a mutex descriptor.
+ *
+ * - -EIDRM is returned if @a mutex is a deleted mutex descriptor.
+ *
+ * - -EPERM is returned if this service was called from an
+ * asynchronous context.
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Kernel-based task
+ * - User-space task
+ *
+ * Rescheduling: possible.
+ */
+
+int rt_mutex_delete(RT_MUTEX *mutex)
{
- xnthread_t *thread;
- int err = 0;
+ int err;
+
+ err = rt_mutex_delete_inner(mutex);
+
+#ifdef CONFIG_XENO_FASTSEM
+ if (!err)
+ xnfree(mutex->fast_lock);
+#endif /* CONFIG_XENO_FASTSEM */
+
+ return err;
+}
+
+int rt_mutex_acquire_inner(RT_MUTEX *mutex, RTIME timeout,
+ xntmode_t timeout_mode)
+{
+ xnhandle_t fast_lock, threadh, old;
+ xnthread_t *thread, *owner;
+ int err;
spl_t s;
if (xnpod_unblockable_p())
return -EPERM;
+ thread = xnpod_current_thread();
+ threadh = xnthread_handle(thread);
+
+ retry:
+
+ fast_lock =
+ xnarch_atomic_cmpxchg(mutex->fast_lock, XN_NO_HANDLE, threadh);
+
+ if (likely(!fast_lock)) {
+ mutex->lockcnt = 1;
+ return 0;
+ }
+
+ if (__rt_mutex_mask_claimed(fast_lock) == threadh) {
+ if (mutex->lockcnt == UINT_MAX)
+ return -EAGAIN;
+
+ mutex->lockcnt++;
+ return 0;
+ }
+
xnlock_get_irqsave(&nklock, s);
mutex = xeno_h2obj_validate(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
@@ -292,42 +355,83 @@ int rt_mutex_acquire_inner(RT_MUTEX *mut
goto unlock_and_exit;
}
- thread = xnpod_current_thread();
+ /* Set bit 0, so that mutex_unlock will know that the mutex is
+ claimed. */
+ if (__rt_mutex_is_claimed(fast_lock)) {
+ old = xnarch_atomic_get(mutex->fast_lock);
+ goto test_no_owner;
+ }
+ do {
+ old = xnarch_atomic_cmpxchg(mutex->fast_lock, fast_lock,
+ __rt_mutex_set_claimed(fast_lock,
+ 1));
+ if (likely(old == fast_lock))
+ break;
+
+ test_no_owner:
+
+ if (old == 0) {
+ /* Owner called fast mutex release (on another cpu) */
+ xnlock_put_irqrestore(&nklock, s);
+ goto retry;
+ }
+ fast_lock = old;
+ } while (!__rt_mutex_is_claimed(fast_lock));
- if (xnsynch_owner(&mutex->synch_base) == NULL) {
- xnsynch_set_owner(&mutex->synch_base, thread);
- goto grab_mutex;
- }
+ owner = xnregistry_fetch(__rt_mutex_mask_claimed(fast_lock));
- if (xnsynch_owner(&mutex->synch_base) == thread) {
- mutex->lockcnt++;
- goto unlock_and_exit;
- }
-
- if (timeout == TM_NONBLOCK) {
- err = -EWOULDBLOCK;
- goto unlock_and_exit;
+ /* Consistency check for owner handle - is the object a thread? */
+ if (unlikely(!owner ||
+ xnthread_handle(owner) !=
+ __rt_mutex_mask_claimed(fast_lock))) {
+ err = -EINVAL;
+ goto cleanup_and_exit;
}
+ xnsynch_set_owner(&mutex->synch_base, owner);
xnsynch_sleep_on(&mutex->synch_base, timeout, timeout_mode);
- if (xnthread_test_info(thread, XNRMID))
+ if (unlikely
+ (xnthread_test_info(thread,
+ XNBREAK | XNRMID | XNROBBED | XNTIMEO))) {
+ if (xnthread_test_info(thread, XNROBBED)) {
+ xnlock_put_irqrestore(&nklock, s);
+ goto retry;
+ }
+ if (xnthread_test_info(thread, XNTIMEO)) {
+ if (timeout_mode == XN_RELATIVE &&
+ timeout == XN_NONBLOCK)
+ err = -EWOULDBLOCK;
+ else
+ err = -ETIMEDOUT;
+ goto cleanup_and_exit;
+ }
+ if (xnthread_test_info(thread, XNBREAK)) {
+ err = -EINTR; /* Forcibly unblocked. */
+ goto cleanup_and_exit;
+ }
err = -EIDRM; /* Mutex deleted while pending. */
- else if (xnthread_test_info(thread, XNTIMEO))
- err = -ETIMEDOUT; /* Timeout. */
- else if (xnthread_test_info(thread, XNBREAK))
- err = -EINTR; /* Unblocked. */
- else {
- grab_mutex:
- /* xnsynch_sleep_on() might have stolen the resource,
- so we need to put our internal data in sync. */
- mutex->lockcnt = 1;
+ goto cleanup_and_exit;
}
- unlock_and_exit:
+ if (xnsynch_nsleepers(&mutex->synch_base))
+ threadh = __rt_mutex_set_claimed(threadh, 1);
+ xnarch_atomic_set(mutex->fast_lock, threadh);
+ mutex->lockcnt = 1;
xnlock_put_irqrestore(&nklock, s);
+ return 0;
+
+ cleanup_and_exit:
+
+ if (!xnsynch_nsleepers(&mutex->synch_base))
+ xnarch_atomic_set(mutex->fast_lock,
+ __rt_mutex_mask_claimed(xnarch_atomic_get
+ (mutex->fast_lock)));
+ unlock_and_exit:
+
+ xnlock_put_irqrestore(&nklock, s);
return err;
}
@@ -397,7 +501,7 @@ int rt_mutex_acquire_inner(RT_MUTEX *mut
int rt_mutex_acquire(RT_MUTEX *mutex, RTIME timeout)
{
- return rt_mutex_acquire_inner(mutex, XN_RELATIVE, timeout);
+ return rt_mutex_acquire_inner(mutex, timeout, XN_RELATIVE);
}
/**
@@ -463,7 +567,7 @@ int rt_mutex_acquire(RT_MUTEX *mutex, RT
int rt_mutex_acquire_until(RT_MUTEX *mutex, RTIME timeout)
{
- return rt_mutex_acquire_inner(mutex, XN_REALTIME, timeout);
+ return rt_mutex_acquire_inner(mutex, timeout, XN_REALTIME);
}
/**
@@ -500,12 +604,30 @@ int rt_mutex_acquire_until(RT_MUTEX *mut
int rt_mutex_release(RT_MUTEX *mutex)
{
- int err = 0;
+ xnhandle_t threadh, ownerh;
+ xnthread_t *owner;
+ int err;
spl_t s;
if (xnpod_unblockable_p())
return -EPERM;
+ threadh = xnthread_handle(xnpod_current_thread());
+
+ if (__rt_mutex_mask_claimed(xnarch_atomic_get(mutex->fast_lock)) !=
+ threadh)
+ return -EPERM;
+
+ if (mutex->lockcnt > 1) {
+ mutex->lockcnt--;
+ return 0;
+ }
+
+ if (likely
+ (xnarch_atomic_cmpxchg(mutex->fast_lock, threadh, XN_NO_HANDLE) ==
+ threadh))
+ return 0;
+
xnlock_get_irqsave(&nklock, s);
mutex = xeno_h2obj_validate(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
@@ -515,18 +637,16 @@ int rt_mutex_release(RT_MUTEX *mutex)
goto unlock_and_exit;
}
- if (xnpod_current_thread() != xnsynch_owner(&mutex->synch_base)) {
- err = -EPERM;
- goto unlock_and_exit;
- }
-
- if (--mutex->lockcnt > 0)
- goto unlock_and_exit;
-
- if (xnsynch_wakeup_one_sleeper(&mutex->synch_base)) {
- mutex->lockcnt = 1;
+ owner = xnsynch_wakeup_one_sleeper(&mutex->synch_base);
+ if (owner) {
+ ownerh = __rt_mutex_set_claimed(xnthread_handle(owner),
+ xnsynch_nsleepers(&mutex->
+ synch_base));
+ xnarch_atomic_set(mutex->fast_lock, ownerh);
xnpod_schedule();
- }
+ } else
+ xnarch_atomic_set(mutex->fast_lock, XN_NO_HANDLE);
+ err = 0;
unlock_and_exit:
@@ -568,6 +688,8 @@ int rt_mutex_release(RT_MUTEX *mutex)
int rt_mutex_inquire(RT_MUTEX *mutex, RT_MUTEX_INFO *info)
{
+ xnhandle_t fast_lock;
+ xnthread_t *owner;
int err = 0;
spl_t s;
@@ -581,12 +703,21 @@ int rt_mutex_inquire(RT_MUTEX *mutex, RT
}
strcpy(info->name, mutex->name);
- info->lockcnt = mutex->lockcnt;
+ fast_lock = xnarch_atomic_get(mutex->fast_lock);
+ info->locked = !!fast_lock;
info->nwaiters = xnsynch_nsleepers(&mutex->synch_base);
- if (mutex->lockcnt)
- strcpy(info->owner,
- xnthread_name(xnsynch_owner(&mutex->synch_base)));
- else
+ if (fast_lock) {
+ owner = xnregistry_fetch(__rt_mutex_mask_claimed(fast_lock));
+
+ if (owner &&
+ xnthread_handle(owner) ==
+ __rt_mutex_mask_claimed(fast_lock))
+ strcpy(info->owner,
+ xnthread_name(xnsynch_owner(&mutex->
+ synch_base)));
+ else
+ strcpy(info->owner, "<DAMAGED HANDLE!>");
+ } else
info->owner[0] = 0;
unlock_and_exit:
Index: b/ksrc/skins/native/syscall.c
===================================================================
--- a/ksrc/skins/native/syscall.c
+++ b/ksrc/skins/native/syscall.c
@@ -24,6 +24,7 @@
#include <nucleus/heap.h>
#include <nucleus/shadow.h>
#include <nucleus/registry.h>
+#include <nucleus/sys_ppd.h>
#include <native/syscall.h>
#include <native/task.h>
#include <native/timer.h>
@@ -1527,6 +1528,7 @@ static int __rt_event_inquire(struct pt_
static int __rt_mutex_create(struct pt_regs *regs)
{
char name[XNOBJECT_NAME_LEN];
+ xnheap_t *sem_heap;
RT_MUTEX_PLACEHOLDER ph;
RT_MUTEX *mutex;
int err;
@@ -1541,22 +1543,47 @@ static int __rt_mutex_create(struct pt_r
} else
*name = '\0';
+ sem_heap = &xnsys_ppd_get(*name != '\0')->sem_heap;
+
mutex = (RT_MUTEX *)xnmalloc(sizeof(*mutex));
if (!mutex)
return -ENOMEM;
- err = rt_mutex_create(mutex, name);
+#ifdef CONFIG_XENO_FASTSEM
+ mutex->fast_lock = xnheap_alloc(sem_heap, sizeof(xnarch_atomic_t));
+
+ if (!mutex->fast_lock) {
+ xnfree(mutex);
+ return -ENOMEM;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
+ err = rt_mutex_create_inner(mutex, name);
if (err == 0) {
mutex->cpid = current->pid;
/* Copy back the registry handle to the ph struct. */
ph.opaque = mutex->handle;
+#ifdef CONFIG_XENO_FASTSEM
+ /* The lock address will be finished in user space. */
+ ph.fast_lock =
+ (void *)xnheap_mapped_offset(sem_heap,
+ mutex->fast_lock);
+ if (*name != '\0')
+ xnsynch_set_flags(&mutex->synch_base,
+ RT_MUTEX_EXPORTED);
+#endif /* CONFIG_XENO_FASTSEM */
if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg1(regs), &ph,
sizeof(ph)))
err = -EFAULT;
- } else
+ } else {
+#ifdef CONFIG_XENO_FASTSEM
+ xnheap_free(&xnsys_ppd_get(*name != '\0')->sem_heap,
+ mutex->fast_lock);
+#endif /* CONFIG_XENO_FASTSEM */
xnfree(mutex);
+ }
return err;
}
@@ -1570,15 +1597,22 @@ static int __rt_mutex_create(struct pt_r
static int __rt_mutex_bind(struct pt_regs *regs)
{
RT_MUTEX_PLACEHOLDER ph;
+ RT_MUTEX *mutex;
int err;
err =
__rt_bind_helper(current, regs, &ph.opaque, XENO_MUTEX_MAGIC,
- NULL, 0);
+ (void **)&mutex, 0);
if (err)
return err;
+#ifdef CONFIG_XENO_FASTSEM
+ ph.fast_lock =
+ (void *)xnheap_mapped_offset(&xnsys_ppd_get(1)->sem_heap,
+ mutex->fast_lock);
+#endif /* CONFIG_XENO_FASTSEM */
+
if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg1(regs), &ph,
sizeof(ph)))
return -EFAULT;
@@ -1605,10 +1639,17 @@ static int __rt_mutex_delete(struct pt_r
if (!mutex)
return -ESRCH;
- err = rt_mutex_delete(mutex);
+ err = rt_mutex_delete_inner(mutex);
- if (!err && mutex->cpid)
+ if (!err && mutex->cpid) {
+#ifdef CONFIG_XENO_FASTSEM
+ int global = xnsynch_test_flags(&mutex->synch_base,
+ RT_MUTEX_EXPORTED);
+ xnheap_free(&xnsys_ppd_get(global)->sem_heap,
+ mutex->fast_lock);
+#endif /* CONFIG_XENO_FASTSEM */
xnfree(mutex);
+ }
return err;
}
@@ -1621,13 +1662,14 @@ static int __rt_mutex_delete(struct pt_r
static int __rt_mutex_acquire(struct pt_regs *regs)
{
- RT_MUTEX_PLACEHOLDER ph;
+ RT_MUTEX_PLACEHOLDER __user *ph;
xntmode_t timeout_mode;
+ xnhandle_t mutexh;
RT_MUTEX *mutex;
RTIME timeout;
- if (__xn_safe_copy_from_user(&ph, (void __user *)__xn_reg_arg1(regs),
- sizeof(ph)))
+ ph = (RT_MUTEX_PLACEHOLDER __user *)__xn_reg_arg1(regs);
+ if (__xn_safe_copy_from_user(&mutexh, &ph->opaque, sizeof(mutexh)))
return -EFAULT;
timeout_mode = __xn_reg_arg2(regs);
@@ -1636,12 +1678,12 @@ static int __rt_mutex_acquire(struct pt_
sizeof(timeout)))
return -EFAULT;
- mutex = (RT_MUTEX *)xnregistry_fetch(ph.opaque);
+ mutex = (RT_MUTEX *)xnregistry_fetch(mutexh);
if (!mutex)
return -ESRCH;
- return rt_mutex_acquire_inner(mutex, timeout_mode, timeout);
+ return rt_mutex_acquire_inner(mutex, timeout, timeout_mode);
}
/*
@@ -1650,14 +1692,15 @@ static int __rt_mutex_acquire(struct pt_
static int __rt_mutex_release(struct pt_regs *regs)
{
- RT_MUTEX_PLACEHOLDER ph;
+ RT_MUTEX_PLACEHOLDER __user *ph;
+ xnhandle_t mutexh;
RT_MUTEX *mutex;
- if (__xn_safe_copy_from_user(&ph, (void __user *)__xn_reg_arg1(regs),
- sizeof(ph)))
+ ph = (RT_MUTEX_PLACEHOLDER __user *)__xn_reg_arg1(regs);
+ if (__xn_safe_copy_from_user(&mutexh, &ph->opaque, sizeof(mutexh)))
return -EFAULT;
- mutex = (RT_MUTEX *)xnregistry_fetch(ph.opaque);
+ mutex = (RT_MUTEX *)xnregistry_fetch(mutexh);
if (!mutex)
return -ESRCH;
Index: b/src/skins/native/mutex.c
===================================================================
--- a/src/skins/native/mutex.c
+++ b/src/skins/native/mutex.c
@@ -16,21 +16,50 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
+#include <limits.h>
#include <native/syscall.h>
#include <native/mutex.h>
+#include <asm-generic/bits/current.h>
extern int __native_muxid;
+extern unsigned long xeno_sem_heap[2];
int rt_mutex_create(RT_MUTEX *mutex, const char *name)
{
- return XENOMAI_SKINCALL2(__native_muxid,
- __native_mutex_create, mutex, name);
+ int err;
+
+ err = XENOMAI_SKINCALL2(__native_muxid,
+ __native_mutex_create, mutex, name);
+
+#ifdef CONFIG_XENO_FASTSEM
+ if (!err) {
+ mutex->fast_lock = (xnarch_atomic_t *)
+ (xeno_sem_heap[(name && *name) ? 1 : 0] +
+ (unsigned long)mutex->fast_lock);
+ mutex->lockcnt = 0;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
+ return err;
}
int rt_mutex_bind(RT_MUTEX *mutex, const char *name, RTIME timeout)
{
- return XENOMAI_SKINCALL3(__native_muxid,
- __native_mutex_bind, mutex, name, &timeout);
+ int err;
+
+ err = XENOMAI_SKINCALL3(__native_muxid,
+ __native_mutex_bind, mutex, name, &timeout);
+
+#ifdef CONFIG_XENO_FASTSEM
+ if (!err) {
+ mutex->fast_lock = (xnarch_atomic_t *)
+ (xeno_sem_heap[(name && *name) ? 1 : 0] +
+ (unsigned long)mutex->fast_lock);
+ mutex->lockcnt = 0;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
+ return err;
}
int rt_mutex_delete(RT_MUTEX *mutex)
@@ -38,20 +67,78 @@ int rt_mutex_delete(RT_MUTEX *mutex)
return XENOMAI_SKINCALL1(__native_muxid, __native_mutex_delete, mutex);
}
+static int rt_mutex_acquire_inner(RT_MUTEX *mutex, RTIME timeout, xntmode_t mode)
+{
+ int err;
+#ifdef CONFIG_XENO_FASTSEM
+ xnhandle_t cur, fast_lock;
+
+ cur = xeno_get_current();
+ if (!cur)
+ return -EPERM;
+
+ fast_lock =
+ xnarch_atomic_cmpxchg(mutex->fast_lock, XN_NO_HANDLE, cur);
+
+ if (likely(fast_lock == 0)) {
+ mutex->lockcnt = 1;
+ return 0;
+ }
+
+ if (__rt_mutex_mask_claimed(fast_lock) == cur) {
+ if (mutex->lockcnt == UINT_MAX)
+ return -EAGAIN;
+
+ mutex->lockcnt++;
+ return 0;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
+ err = XENOMAI_SKINCALL3(__native_muxid,
+ __native_mutex_acquire, mutex, mode, &timeout);
+
+#ifdef CONFIG_XENO_FASTSEM
+ if (!err)
+ mutex->lockcnt = 1;
+#endif /* CONFIG_XENO_FASTSEM */
+
+ return err;
+}
+
int rt_mutex_acquire(RT_MUTEX *mutex, RTIME timeout)
{
- return XENOMAI_SKINCALL3(__native_muxid,
- __native_mutex_acquire, mutex, XN_RELATIVE, &timeout);
+ return rt_mutex_acquire_inner(mutex, timeout, XN_RELATIVE);
}
int rt_mutex_acquire_until(RT_MUTEX *mutex, RTIME timeout)
{
- return XENOMAI_SKINCALL3(__native_muxid,
- __native_mutex_acquire, mutex, XN_REALTIME, &timeout);
+ return rt_mutex_acquire_inner(mutex, timeout, XN_REALTIME);
}
int rt_mutex_release(RT_MUTEX *mutex)
{
+#ifdef CONFIG_XENO_FASTSEM
+ xnhandle_t cur, fast_lock;
+
+ cur = xeno_get_current();
+ if (!cur)
+ return -EPERM;
+
+ fast_lock = xnarch_atomic_get(mutex->fast_lock);
+
+ if (unlikely(__rt_mutex_mask_claimed(fast_lock) != cur))
+ return -EPERM;
+
+ if (mutex->lockcnt > 1) {
+ mutex->lockcnt--;
+ return 0;
+ }
+
+ if (likely(xnarch_atomic_cmpxchg(mutex->fast_lock,
+ cur, XN_NO_HANDLE) == cur))
+ return 0;
+#endif /* CONFIG_XENO_FASTSEM */
+
return XENOMAI_SKINCALL1(__native_muxid, __native_mutex_release, mutex);
}
Index: b/ksrc/skins/native/cond.c
===================================================================
--- a/ksrc/skins/native/cond.c
+++ b/ksrc/skins/native/cond.c
@@ -378,8 +378,9 @@ int rt_cond_broadcast(RT_COND *cond)
int rt_cond_wait_inner(RT_COND *cond, RT_MUTEX *mutex,
xntmode_t timeout_mode, RTIME timeout)
{
+ xnhandle_t fast_lock, threadh;
+ xnthread_t *thread, *owner;
int err = 0, kicked = 0;
- xnthread_t *thread;
int lockcnt;
spl_t s;
@@ -406,8 +407,10 @@ int rt_cond_wait_inner(RT_COND *cond, RT
}
thread = xnpod_current_thread();
+ threadh = xnthread_handle(thread);
- if (thread != xnsynch_owner(&mutex->synch_base)) {
+ fast_lock = xnarch_atomic_get(mutex->fast_lock);
+ if (__rt_mutex_mask_claimed(fast_lock) != threadh) {
err = -EPERM;
goto unlock_and_exit;
}
@@ -421,8 +424,14 @@ int rt_cond_wait_inner(RT_COND *cond, RT
mutex->lockcnt = 0;
- if (xnsynch_wakeup_one_sleeper(&mutex->synch_base)) {
- mutex->lockcnt = 1;
+ if (unlikely
+ (xnarch_atomic_cmpxchg(mutex->fast_lock, threadh, XN_NO_HANDLE) !=
+ threadh)) {
+ owner = xnsynch_wakeup_one_sleeper(&mutex->synch_base);
+ xnarch_atomic_set(mutex->fast_lock,
+ __rt_mutex_set_claimed(xnthread_handle(owner),
+ xnsynch_nsleepers
+ (&mutex->synch_base)));
/* Scheduling deferred */
}
Index: b/src/skins/native/cond.c
===================================================================
--- a/src/skins/native/cond.c
+++ b/src/skins/native/cond.c
@@ -41,16 +41,32 @@ int rt_cond_delete(RT_COND *cond)
int rt_cond_wait(RT_COND *cond, RT_MUTEX *mutex, RTIME timeout)
{
- return XENOMAI_SKINCALL4(__native_muxid,
- __native_cond_wait, cond, mutex,
- XN_RELATIVE, &timeout);
+ int saved_lockcnt, err;
+
+ saved_lockcnt = mutex->lockcnt;
+
+ err = XENOMAI_SKINCALL4(__native_muxid,
+ __native_cond_wait, cond, mutex,
+ XN_RELATIVE, &timeout);
+
+ mutex->lockcnt = saved_lockcnt;
+
+ return err;
}
int rt_cond_wait_until(RT_COND *cond, RT_MUTEX *mutex, RTIME timeout)
{
- return XENOMAI_SKINCALL4(__native_muxid,
- __native_cond_wait, cond, mutex,
- XN_REALTIME, &timeout);
+ int saved_lockcnt, err;
+
+ saved_lockcnt = mutex->lockcnt;
+
+ err = XENOMAI_SKINCALL4(__native_muxid,
+ __native_cond_wait, cond, mutex,
+ XN_REALTIME, &timeout);
+
+ mutex->lockcnt = saved_lockcnt;
+
+ return err;
}
int rt_cond_signal(RT_COND *cond)
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners - v2
2008-09-05 8:34 ` [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners - v2 Jan Kiszka
@ 2008-09-05 9:40 ` Gilles Chanteperdrix
2008-09-05 9:46 ` Jan Kiszka
0 siblings, 1 reply; 26+ messages in thread
From: Gilles Chanteperdrix @ 2008-09-05 9:40 UTC (permalink / raw)
To: Jan Kiszka; +Cc: xenomai-core
Jan Kiszka wrote:
> @@ -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)));
Ok. Can we avoid xnthread_handle() everywhere by storing its result in a
local variable and reusing this local variable, here and in the other
functions where xnthread_handle is used multiple times ?
--
Gilles.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners - v2
2008-09-05 9:40 ` Gilles Chanteperdrix
@ 2008-09-05 9:46 ` Jan Kiszka
2008-09-05 9:50 ` Gilles Chanteperdrix
0 siblings, 1 reply; 26+ messages in thread
From: Jan Kiszka @ 2008-09-05 9:46 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: xenomai-core
Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
>> @@ -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)));
>
> Ok. Can we avoid xnthread_handle() everywhere by storing its result in a
> local variable and reusing this local variable, here and in the other
> functions where xnthread_handle is used multiple times ?
True for 'cur' here (will fix), but the other case have already been
optimized as far as possible (i.e. within the respective scope).
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners - v2
2008-09-05 9:46 ` Jan Kiszka
@ 2008-09-05 9:50 ` Gilles Chanteperdrix
2008-09-05 9:55 ` Jan Kiszka
0 siblings, 1 reply; 26+ messages in thread
From: Gilles Chanteperdrix @ 2008-09-05 9:50 UTC (permalink / raw)
To: Jan Kiszka; +Cc: xenomai-core
Jan Kiszka wrote:
> Gilles Chanteperdrix wrote:
>> Jan Kiszka wrote:
>>> @@ -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)));
>> Ok. Can we avoid xnthread_handle() everywhere by storing its result in a
>> local variable and reusing this local variable, here and in the other
>> functions where xnthread_handle is used multiple times ?
>
> True for 'cur' here (will fix), but the other case have already been
> optimized as far as possible (i.e. within the respective scope).
I have found several other spots where xnthread_handle is called
multiple times in the same function. mutex_unlock comes to my mind.
--
Gilles.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners - v2
2008-09-05 9:50 ` Gilles Chanteperdrix
@ 2008-09-05 9:55 ` Jan Kiszka
2008-09-05 9:57 ` Gilles Chanteperdrix
0 siblings, 1 reply; 26+ messages in thread
From: Jan Kiszka @ 2008-09-05 9:55 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: xenomai-core
Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
>> Gilles Chanteperdrix wrote:
>>> Jan Kiszka wrote:
>>>> @@ -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)));
>>> Ok. Can we avoid xnthread_handle() everywhere by storing its result in a
>>> local variable and reusing this local variable, here and in the other
>>> functions where xnthread_handle is used multiple times ?
>> True for 'cur' here (will fix), but the other case have already been
>> optimized as far as possible (i.e. within the respective scope).
>
> I have found several other spots where xnthread_handle is called
> multiple times in the same function. mutex_unlock comes to my mind.
Please point me to the concrete spot. I went again through all
xnthread_handle instances in this patch, checking that they aren't
needed due to owner changes, but only found the one above. Specifically
pthread_mutex_unlock, pse51_mutex_unlock_internal and
__pthread_mutex_unlock have only a single reference or reference
different threads.
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners - v2
2008-09-05 9:55 ` Jan Kiszka
@ 2008-09-05 9:57 ` Gilles Chanteperdrix
0 siblings, 0 replies; 26+ messages in thread
From: Gilles Chanteperdrix @ 2008-09-05 9: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:
>>>>> @@ -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)));
>>>> Ok. Can we avoid xnthread_handle() everywhere by storing its result in a
>>>> local variable and reusing this local variable, here and in the other
>>>> functions where xnthread_handle is used multiple times ?
>>> True for 'cur' here (will fix), but the other case have already been
>>> optimized as far as possible (i.e. within the respective scope).
>> I have found several other spots where xnthread_handle is called
>> multiple times in the same function. mutex_unlock comes to my mind.
>
> Please point me to the concrete spot. I went again through all
> xnthread_handle instances in this patch, checking that they aren't
> needed due to owner changes, but only found the one above. Specifically
> pthread_mutex_unlock, pse51_mutex_unlock_internal and
> __pthread_mutex_unlock have only a single reference or reference
> different threads.
Ok. I had grepped xnthread_handle and found that it was used twice in
mutex_unlock, but did not checked if it was used for the same thread.
--
Gilles.
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2008-09-05 9:57 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-01 8:53 [Xenomai-core] [PATCH 0/9] Fast mutex rework, native support Jan Kiszka
2008-09-01 8:39 ` [Xenomai-core] [PATCH 1/9] Always register threads by their base Jan Kiszka
2008-09-01 8:44 ` [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners Jan Kiszka
2008-09-01 11:58 ` Gilles Chanteperdrix
2008-09-01 13:48 ` Jan Kiszka
2008-09-01 14:00 ` Gilles Chanteperdrix
2008-09-01 14:03 ` Jan Kiszka
2008-09-01 14:08 ` Jan Kiszka
2008-09-02 12:31 ` Gilles Chanteperdrix
2008-09-05 8:34 ` [Xenomai-core] [PATCH 2/9] Switch to handle-based fast mutex owners - v2 Jan Kiszka
2008-09-05 9:40 ` Gilles Chanteperdrix
2008-09-05 9:46 ` Jan Kiszka
2008-09-05 9:50 ` Gilles Chanteperdrix
2008-09-05 9:55 ` Jan Kiszka
2008-09-05 9:57 ` Gilles Chanteperdrix
2008-09-01 8:45 ` [Xenomai-core] [PATCH 3/9] Remove xnarch_atomic_intptr wrappers Jan Kiszka
2008-09-01 8:47 ` [Xenomai-core] [PATCH 4/9] Spread xeno_set_current Jan Kiszka
2008-09-01 8:54 ` [Xenomai-core] [RFC][PATCH 5/9] Allow lock stealing via pthread_mutex_trylock Jan Kiszka
2008-09-01 9:58 ` Gilles Chanteperdrix
2008-09-01 8:57 ` [Xenomai-core] [RFC][PATCH 6/9] Add XNSYNCH_FWDROB Jan Kiszka
2008-09-01 10:00 ` Gilles Chanteperdrix
2008-09-01 9:01 ` [Xenomai-core] [RFC][PATCH 8/9] Native support for fast mutexes Jan Kiszka
2008-09-05 8:36 ` [Xenomai-core] [RFC][PATCH 8/9] Native support for fast mutexes - v2 Jan Kiszka
2008-09-01 9:06 ` [Xenomai-core] [RFC][PATCH 9/9] Optimize xnsynch_sleep_on for XN_NONBLOCK Jan Kiszka
2008-09-01 9:12 ` [Xenomai-core] [RFC][PATCH 7/9] Switch POSIX mutexes to XNSYNCH_FWDROB Jan Kiszka
2008-09-01 10:01 ` Gilles Chanteperdrix
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.