* [Xenomai-core] [PATCH 01/13] Generic thread registration
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
@ 2008-10-17 15:46 ` Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 02/13] Handle-based xeno_get_current service Jan Kiszka
` (14 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:46 UTC (permalink / raw)
To: xenomai; +Cc: Jan Kiszka
Lay groundwork for registering every thread at least anonymously with
the Xenomai registry when required (e.g. handle-based fast xnsynch
support). Wrap the operations appropriately, also saving a few #ifdefs.
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
include/nucleus/registry.h | 1
include/nucleus/thread.h | 25 +++++++++++++++++
ksrc/nucleus/thread.c | 2 +
ksrc/skins/native/syscall.c | 61 ++++++++++++++++++++++++++-----------------
ksrc/skins/native/task.c | 13 ---------
ksrc/skins/psos+/syscall.c | 19 ++++++++-----
ksrc/skins/psos+/task.c | 20 +++-----------
ksrc/skins/vxworks/syscall.c | 31 ++++++++++++---------
ksrc/skins/vxworks/taskLib.c | 10 -------
9 files changed, 102 insertions(+), 80 deletions(-)
Index: b/ksrc/skins/native/syscall.c
===================================================================
--- a/ksrc/skins/native/syscall.c
+++ b/ksrc/skins/native/syscall.c
@@ -52,7 +52,8 @@ int __native_muxid;
static int __rt_bind_helper(struct task_struct *p,
struct pt_regs *regs,
xnhandle_t *handlep,
- unsigned magic, void **objaddrp)
+ unsigned magic, void **objaddrp,
+ unsigned long objoffs)
{
char name[XNOBJECT_NAME_LEN];
RTIME timeout;
@@ -82,7 +83,7 @@ static int __rt_bind_helper(struct task_
/* Also validate the type of the bound object. */
- if (xeno_test_magic(objaddr, magic)) {
+ if (xeno_test_magic(objaddr + objoffs, magic)) {
if (objaddrp)
*objaddrp = objaddr;
} else
@@ -93,6 +94,11 @@ static int __rt_bind_helper(struct task_
return err;
}
+static RT_TASK *__rt_task_lookup(xnhandle_t threadh)
+{
+ return thread2rtask(xnthread_lookup(threadh));
+}
+
static RT_TASK *__rt_task_current(struct task_struct *p)
{
xnthread_t *thread = xnshadow_thread(p);
@@ -223,7 +229,9 @@ static int __rt_task_bind(struct pt_regs
RT_TASK_PLACEHOLDER ph;
int err;
- err = __rt_bind_helper(p, regs, &ph.opaque, XENO_TASK_MAGIC, NULL);
+ err =
+ __rt_bind_helper(p, regs, &ph.opaque, XENO_TASK_MAGIC, NULL,
+ -offsetof(RT_TASK, thread_base));
if (err)
return err;
@@ -253,7 +261,7 @@ static int __rt_task_start(struct pt_reg
sizeof(ph)))
return -EFAULT;
- task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+ task = __rt_task_lookup(ph.opaque);
if (!task)
return -ESRCH;
@@ -279,7 +287,7 @@ static int __rt_task_suspend(struct pt_r
sizeof(ph)))
return -EFAULT;
- task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+ task = __rt_task_lookup(ph.opaque);
} else
task = __rt_task_current(p);
@@ -302,7 +310,7 @@ static int __rt_task_resume(struct pt_re
sizeof(ph)))
return -EFAULT;
- task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+ task = __rt_task_lookup(ph.opaque);
if (!task)
return -ESRCH;
@@ -326,7 +334,7 @@ static int __rt_task_delete(struct pt_re
sizeof(ph)))
return -EFAULT;
- task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+ task = __rt_task_lookup(ph.opaque);
} else
task = __rt_task_current(p);
@@ -364,7 +372,7 @@ static int __rt_task_set_periodic(struct
sizeof(ph)))
return -EFAULT;
- task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+ task = __rt_task_lookup(ph.opaque);
} else
task = __rt_task_current(p);
@@ -418,7 +426,7 @@ static int __rt_task_set_priority(struct
sizeof(ph)))
return -EFAULT;
- task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+ task = __rt_task_lookup(ph.opaque);
} else
task = __rt_task_current(p);
@@ -473,7 +481,7 @@ static int __rt_task_unblock(struct pt_r
sizeof(ph)))
return -EFAULT;
- task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+ task = __rt_task_lookup(ph.opaque);
if (!task)
return -ESRCH;
@@ -500,7 +508,7 @@ static int __rt_task_inquire(struct pt_r
sizeof(ph)))
return -EFAULT;
- task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+ task = __rt_task_lookup(ph.opaque);
} else
task = __rt_task_current(p);
@@ -541,7 +549,7 @@ static int __rt_task_notify(struct pt_re
sizeof(ph)))
return -EFAULT;
- task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+ task = __rt_task_lookup(ph.opaque);
} else
task = __rt_task_current(p);
@@ -627,7 +635,7 @@ static int __rt_task_slice(struct pt_reg
sizeof(ph)))
return -EFAULT;
- task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+ task = __rt_task_lookup(ph.opaque);
} else
task = __rt_task_current(current);
@@ -667,7 +675,7 @@ static int __rt_task_send(struct pt_regs
sizeof(ph)))
return -EFAULT;
- task = (RT_TASK *)xnregistry_fetch(ph.opaque);
+ task = __rt_task_lookup(ph.opaque);
} else
task = __rt_task_current(current);
@@ -1104,7 +1112,9 @@ static int __rt_sem_bind(struct pt_regs
RT_SEM_PLACEHOLDER ph;
int err;
- err = __rt_bind_helper(current, regs, &ph.opaque, XENO_SEM_MAGIC, NULL);
+ err =
+ __rt_bind_helper(current, regs, &ph.opaque, XENO_SEM_MAGIC,
+ NULL, 0);
if (err)
return err;
@@ -1324,7 +1334,8 @@ static int __rt_event_bind(struct pt_reg
int err;
err =
- __rt_bind_helper(current, regs, &ph.opaque, XENO_EVENT_MAGIC, NULL);
+ __rt_bind_helper(current, regs, &ph.opaque, XENO_EVENT_MAGIC,
+ NULL, 0);
if (err)
return err;
@@ -1567,7 +1578,8 @@ static int __rt_mutex_bind(struct pt_reg
int err;
err =
- __rt_bind_helper(current, regs, &ph.opaque, XENO_MUTEX_MAGIC, NULL);
+ __rt_bind_helper(current, regs, &ph.opaque, XENO_MUTEX_MAGIC,
+ NULL, 0);
if (err)
return err;
@@ -1758,7 +1770,8 @@ static int __rt_cond_bind(struct pt_regs
int err;
err =
- __rt_bind_helper(current, regs, &ph.opaque, XENO_COND_MAGIC, NULL);
+ __rt_bind_helper(current, regs, &ph.opaque, XENO_COND_MAGIC,
+ NULL, 0);
if (err)
return err;
@@ -2008,7 +2021,7 @@ static int __rt_queue_bind(struct pt_reg
err =
__rt_bind_helper(p, regs, &ph.opaque, XENO_QUEUE_MAGIC,
- (void **)&q);
+ (void **)&q, 0);
if (err)
goto unlock_and_exit;
@@ -2507,7 +2520,7 @@ static int __rt_heap_bind(struct pt_regs
err =
__rt_bind_helper(p, regs, &ph.opaque, XENO_HEAP_MAGIC,
- (void **)&heap);
+ (void **)&heap, 0);
if (err)
goto unlock_and_exit;
@@ -3018,7 +3031,7 @@ static int __rt_intr_bind(struct pt_regs
RT_INTR_PLACEHOLDER ph;
int err;
- err = __rt_bind_helper(p, regs, &ph.opaque, XENO_INTR_MAGIC, NULL);
+ err = __rt_bind_helper(p, regs, &ph.opaque, XENO_INTR_MAGIC, NULL, 0);
if (err)
return err;
@@ -3275,7 +3288,7 @@ static int __rt_pipe_bind(struct pt_regs
RT_PIPE_PLACEHOLDER ph;
int err;
- err = __rt_bind_helper(p, regs, &ph.opaque, XENO_PIPE_MAGIC, NULL);
+ err = __rt_bind_helper(p, regs, &ph.opaque, XENO_PIPE_MAGIC, NULL, 0);
if (err)
return err;
@@ -3551,7 +3564,9 @@ static int __rt_buffer_bind(struct pt_re
RT_BUFFER_PLACEHOLDER ph;
int ret;
- ret = __rt_bind_helper(current, regs, &ph.opaque, XENO_BUFFER_MAGIC, NULL);
+ ret =
+ __rt_bind_helper(current, regs, &ph.opaque, XENO_BUFFER_MAGIC,
+ NULL, 0);
if (ret)
return ret;
Index: b/ksrc/skins/native/task.c
===================================================================
--- a/ksrc/skins/native/task.c
+++ b/ksrc/skins/native/task.c
@@ -46,7 +46,6 @@
#include <nucleus/pod.h>
#include <nucleus/heap.h>
-#include <nucleus/registry.h>
#include <native/task.h>
#include <native/timer.h>
@@ -80,11 +79,6 @@ static void __task_delete_hook(xnthread_
xnsynch_destroy(&task->msendq);
#endif /* CONFIG_XENO_OPT_NATIVE_MPS */
-#ifdef CONFIG_XENO_OPT_REGISTRY
- if (xnthread_handle(&task->thread_base) != XN_NO_HANDLE)
- xnregistry_remove(xnthread_handle(&task->thread_base));
-#endif /* CONFIG_XENO_OPT_REGISTRY */
-
xnsynch_destroy(&task->safesynch);
removeq(&__xeno_task_q, &task->link);
@@ -285,20 +279,15 @@ int rt_task_create(RT_TASK *task,
appendq(&__xeno_task_q, &task->link);
xnlock_put_irqrestore(&nklock, s);
-#ifdef CONFIG_XENO_OPT_REGISTRY
/* <!> Since xnregister_enter() may reschedule, only register
complete objects, so that the registry cannot return handles to
half-baked objects... */
if (name) {
- err = xnregistry_enter(task->rname,
- task,
- &xnthread_handle(&task->thread_base),
- NULL);
+ err = xnthread_register(&task->thread_base, task->rname);
if (err)
xnpod_delete_thread(&task->thread_base);
}
-#endif /* CONFIG_XENO_OPT_REGISTRY */
return err;
}
Index: b/ksrc/skins/psos+/syscall.c
===================================================================
--- a/ksrc/skins/psos+/syscall.c
+++ b/ksrc/skins/psos+/syscall.c
@@ -44,6 +44,11 @@
int __psos_muxid;
+static inline psostask_t *__psos_task_lookup(xnhandle_t taskh)
+{
+ return thread2psostask(xnthread_lookup(taskh));
+}
+
static psostask_t *__psos_task_current(struct task_struct *p)
{
xnthread_t *thread = xnshadow_thread(p);
@@ -131,7 +136,7 @@ static int __t_start(struct pt_regs *reg
psostask_t *task;
handle = __xn_reg_arg1(regs);
- task = (psostask_t *)xnregistry_fetch(handle);
+ task = __psos_task_lookup(handle);
if (!task)
return ERR_OBJID;
@@ -162,7 +167,7 @@ static int __t_delete(struct pt_regs *re
handle = __xn_reg_arg1(regs);
if (handle)
- task = (psostask_t *)xnregistry_fetch(handle);
+ task = __psos_task_lookup(handle);
else
task = __psos_task_current(current);
@@ -182,7 +187,7 @@ static int __t_suspend(struct pt_regs *r
psostask_t *task;
if (handle)
- task = (psostask_t *)xnregistry_fetch(handle);
+ task = __psos_task_lookup(handle);
else
task = __psos_task_current(current);
@@ -202,7 +207,7 @@ static int __t_resume(struct pt_regs *re
psostask_t *task;
if (handle)
- task = (psostask_t *)xnregistry_fetch(handle);
+ task = __psos_task_lookup(handle);
else
task = __psos_task_current(current);
@@ -284,7 +289,7 @@ static int __t_setpri(struct pt_regs *re
psostask_t *task;
if (handle)
- task = (psostask_t *)xnregistry_fetch(handle);
+ task = __psos_task_lookup(handle);
else
task = __psos_task_current(current);
@@ -314,7 +319,7 @@ static int __ev_send(struct pt_regs *reg
u_long events;
if (handle)
- task = (psostask_t *)xnregistry_fetch(handle);
+ task = __psos_task_lookup(handle);
else
task = __psos_task_current(current);
@@ -1317,7 +1322,7 @@ static int __as_send(struct pt_regs *reg
psostask_t *task;
if (handle)
- task = (psostask_t *)xnregistry_fetch(handle);
+ task = __psos_task_lookup(handle);
else
task = __psos_task_current(current);
Index: b/ksrc/skins/psos+/task.c
===================================================================
--- a/ksrc/skins/psos+/task.c
+++ b/ksrc/skins/psos+/task.c
@@ -17,7 +17,6 @@
* 02111-1307, USA.
*/
-#include <nucleus/registry.h>
#include <psos+/task.h>
#include <psos+/tm.h>
@@ -45,11 +44,6 @@ static void psostask_delete_hook(xnthrea
if (xnthread_get_magic(thread) != PSOS_SKIN_MAGIC)
return;
-#ifdef CONFIG_XENO_OPT_REGISTRY
- if (xnthread_handle(thread) != XN_NO_HANDLE)
- xnregistry_remove(xnthread_handle(thread));
-#endif /* CONFIG_XENO_OPT_REGISTRY */
-
task = thread2psostask(thread);
removeq(&psostaskq, &task->link);
@@ -95,6 +89,7 @@ u_long t_create(const char *name,
{
xnflags_t bflags = 0;
psostask_t *task;
+ u_long err;
spl_t s;
int n;
@@ -159,16 +154,11 @@ u_long t_create(const char *name,
*tid_r = (u_long)task;
xnlock_put_irqrestore(&nklock, s);
-#ifdef CONFIG_XENO_OPT_REGISTRY
- {
- u_long err = xnregistry_enter(task->name,
- task, &xnthread_handle(&task->threadbase), NULL);
- if (err) {
- t_delete((u_long)task);
- return err;
- }
+ err = xnthread_register(&task->threadbase, task->name);
+ if (err) {
+ t_delete((u_long)task);
+ return err;
}
-#endif /* CONFIG_XENO_OPT_REGISTRY */
xnarch_create_display(&task->threadbase, task->name, psostask);
Index: b/ksrc/skins/vxworks/syscall.c
===================================================================
--- a/ksrc/skins/vxworks/syscall.c
+++ b/ksrc/skins/vxworks/syscall.c
@@ -42,6 +42,11 @@
int __wind_muxid;
+static inline WIND_TCB *__wind_lookup_task(xnhandle_t threadh)
+{
+ return thread2wind_task(xnthread_lookup(threadh));
+}
+
static WIND_TCB *__wind_task_current(struct task_struct *p)
{
xnthread_t *thread = xnshadow_thread(p);
@@ -146,7 +151,7 @@ out:
static int __wind_task_activate(struct pt_regs *regs)
{
- WIND_TCB *pTcb = (WIND_TCB *)xnregistry_fetch(__xn_reg_arg1(regs));
+ WIND_TCB *pTcb = __wind_lookup_task(__xn_reg_arg1(regs));
if (!pTcb)
return S_objLib_OBJ_ID_ERROR;
@@ -167,7 +172,7 @@ static int __wind_task_deleteforce(struc
WIND_TCB *pTcb;
if (handle)
- pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ pTcb = __wind_lookup_task(handle);
else
pTcb = __wind_task_current(current);
@@ -190,7 +195,7 @@ static int __wind_task_delete(struct pt_
WIND_TCB *pTcb;
if (handle)
- pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ pTcb = __wind_lookup_task(handle);
else
pTcb = __wind_task_current(current);
@@ -213,7 +218,7 @@ static int __wind_task_suspend(struct pt
WIND_TCB *pTcb;
if (handle)
- pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ pTcb = __wind_lookup_task(handle);
else
pTcb = __wind_task_current(current);
@@ -232,7 +237,7 @@ static int __wind_task_suspend(struct pt
static int __wind_task_resume(struct pt_regs *regs)
{
- WIND_TCB *pTcb = (WIND_TCB *)xnregistry_fetch(__xn_reg_arg1(regs));
+ WIND_TCB *pTcb = __wind_lookup_task(__xn_reg_arg1(regs));
if (!pTcb)
return S_objLib_OBJ_ID_ERROR;
@@ -275,7 +280,7 @@ static int __wind_task_priorityset(struc
WIND_TCB *pTcb;
if (handle)
- pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ pTcb = __wind_lookup_task(handle);
else
pTcb = __wind_task_current(current);
@@ -299,7 +304,7 @@ static int __wind_task_priorityget(struc
int prio;
if (handle)
- pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ pTcb = __wind_lookup_task(handle);
else
pTcb = __wind_task_current(current);
@@ -374,7 +379,7 @@ static int __wind_task_verifyid(struct p
xnhandle_t handle = __xn_reg_arg1(regs);
WIND_TCB *pTcb;
- pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ pTcb = __wind_lookup_task(handle);
if (!pTcb)
return S_objLib_OBJ_ID_ERROR;
@@ -574,7 +579,7 @@ static int __wind_taskinfo_name(struct p
const char *name;
WIND_TCB *pTcb;
- pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ pTcb = __wind_lookup_task(handle);
if (!pTcb)
return S_objLib_OBJ_ID_ERROR;
@@ -618,7 +623,7 @@ static int __wind_taskinfo_status(struct
xnlock_get_irqsave(&nklock, s);
- pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ pTcb = __wind_lookup_task(handle);
if (!pTcb || pTcb->magic != WIND_TASK_MAGIC) {
xnlock_put_irqrestore(&nklock, s);
@@ -643,7 +648,7 @@ static int __wind_taskinfo_get(struct pt
WIND_TCB *pTcb;
int err;
- pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ pTcb = __wind_lookup_task(handle);
if (!pTcb)
return S_objLib_OBJ_ID_ERROR;
@@ -673,7 +678,7 @@ static int __wind_errno_taskset(struct p
return 0;
}
- pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ pTcb = __wind_lookup_task(handle);
if (!pTcb)
return S_objLib_OBJ_ID_ERROR;
@@ -696,7 +701,7 @@ static int __wind_errno_taskget(struct p
if (!handle)
errcode = wind_errnoget();
else {
- pTcb = (WIND_TCB *)xnregistry_fetch(handle);
+ pTcb = __wind_lookup_task(handle);
if (!pTcb)
return S_objLib_OBJ_ID_ERROR;
Index: b/ksrc/skins/vxworks/taskLib.c
===================================================================
--- a/ksrc/skins/vxworks/taskLib.c
+++ b/ksrc/skins/vxworks/taskLib.c
@@ -170,14 +170,11 @@ STATUS taskInit(WIND_TCB *pTcb,
appendq(&wind_tasks_q, &pTcb->link);
xnlock_put_irqrestore(&nklock, s);
-#ifdef CONFIG_XENO_OPT_REGISTRY
- if (xnregistry_enter(pTcb->name,
- pTcb, &xnthread_handle(&pTcb->threadbase), NULL)) {
+ if (xnthread_register(&pTcb->threadbase, pTcb->name)) {
wind_errnoset(S_objLib_OBJ_ID_ERROR);
taskDeleteForce((TASK_ID) pTcb);
return ERROR;
}
-#endif /* CONFIG_XENO_OPT_REGISTRY */
return OK;
}
@@ -618,11 +615,6 @@ static void wind_task_delete_hook(xnthre
if (xnthread_get_magic(thread) != VXWORKS_SKIN_MAGIC)
return;
-#ifdef CONFIG_XENO_OPT_REGISTRY
- if (xnthread_handle(thread) != XN_NO_HANDLE)
- xnregistry_remove(xnthread_handle(thread));
-#endif /* CONFIG_XENO_OPT_REGISTRY */
-
task = thread2wind_task(thread);
xnsynch_destroy(&task->safesync);
Index: b/include/nucleus/registry.h
===================================================================
--- a/include/nucleus/registry.h
+++ b/include/nucleus/registry.h
@@ -35,7 +35,6 @@
#if defined(__KERNEL__) || defined(__XENO_SIM__)
#include <nucleus/synch.h>
-#include <nucleus/thread.h>
struct xnpnode;
Index: b/include/nucleus/thread.h
===================================================================
--- a/include/nucleus/thread.h
+++ b/include/nucleus/thread.h
@@ -130,6 +130,7 @@
#include <nucleus/stat.h>
#include <nucleus/timer.h>
+#include <nucleus/registry.h>
#ifdef __XENO_SIM__
/* Pseudo-status (must not conflict with other bits) */
@@ -392,6 +393,30 @@ static inline xnticks_t xnthread_get_per
return period;
}
+#ifdef CONFIG_XENO_OPT_REGISTRY
+static inline int xnthread_register(xnthread_t *thread, const char *name)
+{
+ return xnregistry_enter(name, thread, &xnthread_handle(thread), NULL);
+}
+
+static inline xnthread_t *xnthread_lookup(xnhandle_t threadh)
+{
+ xnthread_t *thread = xnregistry_fetch(threadh);
+
+ return (thread && xnthread_handle(thread) == threadh) ? thread : NULL;
+}
+#else /* !CONFIG_XENO_OPT_REGISTRY */
+static inline int xnthread_register(xnthread_t *thread, const char *name)
+{
+ return 0;
+}
+
+static inline xnthread_t *xnthread_lookup(xnhandle_t threadh)
+{
+ return NULL;
+}
+#endif /* !CONFIG_XENO_OPT_REGISTRY */
+
#ifdef __cplusplus
}
#endif
Index: b/ksrc/nucleus/thread.c
===================================================================
--- a/ksrc/nucleus/thread.c
+++ b/ksrc/nucleus/thread.c
@@ -136,6 +136,8 @@ void xnthread_cleanup_tcb(xnthread_t *th
#endif
#ifdef CONFIG_XENO_OPT_REGISTRY
+ if (thread->registry.handle != XN_NO_HANDLE)
+ xnregistry_remove(thread->registry.handle);
thread->registry.handle = XN_NO_HANDLE;
#endif /* CONFIG_XENO_OPT_REGISTRY */
}
^ permalink raw reply [flat|nested] 17+ messages in thread* [Xenomai-core] [PATCH 02/13] Handle-based xeno_get_current service
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 01/13] Generic thread registration Jan Kiszka
@ 2008-10-17 15:46 ` Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 03/13] Remove xnarch_atomic_intptr Jan Kiszka
` (13 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:46 UTC (permalink / raw)
To: xenomai; +Cc: Jan Kiszka
To avoid sharing kernel object pointers with user space, a handle-based
approach is installed by this patch. It also reserves a few bits of the
handle value for special use (like the claimed bit of fast xnsynch).
Furthermore, the patch ensures that threads are registered at least
anonymously to allow them being used with fast xnsynch objects.
As a cleanup, the xeno_current_key creation is switched from a
pthread_once scheme to a constructor.
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
include/asm-generic/bits/bind.h | 18 ++++++----
include/asm-generic/bits/current.h | 10 ++++--
include/nucleus/types.h | 13 +++++++
ksrc/nucleus/shadow.c | 16 +++++++--
ksrc/skins/native/Kconfig | 1
ksrc/skins/native/task.c | 8 +---
ksrc/skins/posix/Kconfig | 1
ksrc/skins/posix/cb_lock.h | 15 ++++++---
ksrc/skins/posix/cond.c | 12 ++++---
ksrc/skins/posix/mutex.c | 21 +++++++-----
ksrc/skins/posix/mutex.h | 61 +++++++++++++++++++++++--------------
ksrc/skins/posix/syscall.c | 11 +++---
ksrc/skins/posix/thread.c | 12 +++++++
ksrc/skins/psos+/Kconfig | 2 -
ksrc/skins/rtai/Kconfig | 1
ksrc/skins/rtai/task.c | 10 ++++++
ksrc/skins/rtdm/drvlib.c | 8 ++++
ksrc/skins/uitron/Kconfig | 1
ksrc/skins/uitron/task.c | 11 ++++++
ksrc/skins/vrtx/Kconfig | 2 -
ksrc/skins/vrtx/task.c | 17 +++++++++-
ksrc/skins/vxworks/Kconfig | 2 -
src/skins/posix/mutex.c | 41 ++++++++++++------------
23 files changed, 206 insertions(+), 88 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,20 @@
#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);
+ void *val = pthread_getspecific(xeno_current_key);
+
+ if (!val)
+ return XN_NO_HANDLE;
+
+ return (xnhandle_t)val;
}
#endif /* _XENO_ASM_GENERIC_CURRENT_H */
Index: b/include/nucleus/types.h
===================================================================
--- a/include/nucleus/types.h
+++ b/include/nucleus/types.h
@@ -61,6 +61,19 @@ typedef unsigned long xnhandle_t;
#define XN_NO_HANDLE ((xnhandle_t)0)
+#define XN_HANDLE_SPARE0 ((xnhandle_t)0x10000000)
+#define XN_HANDLE_SPARE1 ((xnhandle_t)0x20000000)
+#define XN_HANDLE_SPARE2 ((xnhandle_t)0x40000000)
+#define XN_HANDLE_SPARE3 ((xnhandle_t)0x80000000)
+#define XN_HANDLE_SPARE_MASK ((xnhandle_t)0xf0000000)
+
+#define xnhandle_mask_spare(handle) ((handle) & ~XN_HANDLE_SPARE_MASK)
+#define xnhandle_test_spare(handle, bits) (!!((handle) & (bits)))
+#define xnhandle_set_spare(handle, bits) \
+ do { (handle) |= (bits); } while (0)
+#define xnhandle_clear_spare(handle, bits) \
+ do { (handle) &= ~(bits); } while (0)
+
struct xnintr;
typedef int (*xnisr_t)(struct xnintr *intr);
Index: b/ksrc/nucleus/shadow.c
===================================================================
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -1908,13 +1908,21 @@ static int xnshadow_sys_sem_heap(struct
return __xn_safe_copy_to_user(us_hinfo, &hinfo, sizeof(*us_hinfo));
}
+#ifdef CONFIG_XENO_OPT_REGISTRY
static int xnshadow_sys_current(struct pt_regs *regs)
{
- xnthread_t * __user *us_current, *cur = xnshadow_thread(current);
- us_current = (xnthread_t *__user *) __xn_reg_arg1(regs);
+ xnthread_t *cur = xnshadow_thread(current);
+ xnhandle_t __user *us_handle;
- return __xn_safe_copy_to_user(us_current, &cur, sizeof(*us_current));
+ if (!cur)
+ return -EPERM;
+
+ us_handle = (xnhandle_t __user *) __xn_reg_arg1(regs);
+
+ return __xn_safe_copy_to_user(us_handle, &xnthread_handle(cur),
+ sizeof(*us_handle));
}
+#endif /* CONFIG_XENO_OPT_REGISTRY */
static xnsysent_t __systab[] = {
[__xn_sys_migrate] = {&xnshadow_sys_migrate, __xn_exec_current},
@@ -1925,7 +1933,9 @@ static xnsysent_t __systab[] = {
[__xn_sys_barrier] = {&xnshadow_sys_barrier, __xn_exec_lostage},
[__xn_sys_trace] = {&xnshadow_sys_trace, __xn_exec_any},
[__xn_sys_sem_heap] = {&xnshadow_sys_sem_heap, __xn_exec_any},
+#ifdef CONFIG_XENO_OPT_REGISTRY
[__xn_sys_current] = {&xnshadow_sys_current, __xn_exec_any},
+#endif /* CONFIG_XENO_OPT_REGISTRY */
};
static void *xnshadow_sys_event(int event, void *data)
Index: b/ksrc/skins/posix/cb_lock.h
===================================================================
--- a/ksrc/skins/posix/cb_lock.h
+++ b/ksrc/skins/posix/cb_lock.h
@@ -3,15 +3,22 @@
#include <asm/xenomai/atomic.h>
#include <nucleus/compiler.h>
+#include <nucleus/types.h>
#ifndef __KERNEL__
typedef void xnthread_t;
#endif /* __KERNEL__ */
-#define test_claimed(owner) ((long) (owner) & 1)
-#define clear_claimed(owner) ((xnthread_t *) ((long) (owner) & ~1))
-#define set_claimed(owner, bit) \
- ((xnthread_t *) ((long) clear_claimed(owner) | !!(bit)))
+#define __CLAIMED_BIT XN_HANDLE_SPARE3
+
+#define test_claimed(owner) xnhandle_test_spare(owner, __CLAIMED_BIT)
+#define clear_claimed(owner) xnhandle_mask_spare(owner)
+#define set_claimed(owner, bit) ({ \
+ xnhandle_t __tmp = xnhandle_mask_spare(owner); \
+ if (bit) \
+ xnhandle_set_spare(__tmp, __CLAIMED_BIT); \
+ __tmp; \
+})
#ifdef CONFIG_XENO_FASTSEM
Index: b/ksrc/skins/posix/cond.c
===================================================================
--- a/ksrc/skins/posix/cond.c
+++ b/ksrc/skins/posix/cond.c
@@ -230,18 +230,20 @@ static inline int mutex_save_count(xnthr
mutex = shadow->mutex;
- if (clear_claimed(xnarch_atomic_intptr_get(mutex->owner)) != cur)
+ if (clear_claimed(xnarch_atomic_get(mutex->owner)) !=
+ xnthread_handle(cur))
return EPERM;
*count_ptr = shadow->lockcnt;
- if (likely(xnarch_atomic_intptr_cmpxchg(mutex->owner, cur, NULL) == cur))
+ if (likely(xnarch_atomic_cmpxchg(mutex->owner, cur, XN_NO_HANDLE) ==
+ xnthread_handle(cur)))
return 0;
owner = xnsynch_wakeup_one_sleeper(&mutex->synchbase);
- xnarch_atomic_intptr_set
- (mutex->owner,
- set_claimed(owner,xnsynch_nsleepers(&mutex->synchbase)));
+ xnarch_atomic_set(mutex->owner,
+ set_claimed(xnthread_handle(owner),
+ xnsynch_nsleepers(&mutex->synchbase)));
/* Do not reschedule here, releasing the mutex and suspension must be
done atomically in pthread_cond_*wait. */
Index: b/ksrc/skins/posix/mutex.c
===================================================================
--- a/ksrc/skins/posix/mutex.c
+++ b/ksrc/skins/posix/mutex.c
@@ -82,7 +82,7 @@ int pse51_mutex_check_init(struct __shad
int pse51_mutex_init_internal(struct __shadow_mutex *shadow,
pse51_mutex_t *mutex,
- xnarch_atomic_intptr_t *ownerp,
+ xnarch_atomic_t *ownerp,
const pthread_mutexattr_t *attr)
{
xnflags_t synch_flags = XNSYNCH_PRIO | XNSYNCH_NOPIP;
@@ -118,7 +118,7 @@ int pse51_mutex_init_internal(struct __s
mutex->owner = ownerp;
mutex->owningq = kq;
mutex->sleepers = 0;
- xnarch_atomic_intptr_set(ownerp, NULL);
+ xnarch_atomic_set(ownerp, XN_NO_HANDLE);
xnlock_get_irqsave(&nklock, s);
appendq(&kq->mutexq, &mutex->link);
@@ -159,7 +159,7 @@ int pthread_mutex_init(pthread_mutex_t *
&((union __xeno_mutex *)mx)->shadow_mutex;
DECLARE_CB_LOCK_FLAGS(s);
pse51_mutex_t *mutex;
- xnarch_atomic_intptr_t *ownerp;
+ xnarch_atomic_t *ownerp;
int err;
if (!attr)
@@ -185,9 +185,9 @@ int pthread_mutex_init(pthread_mutex_t *
if (!mutex)
return ENOMEM;
- ownerp = (xnarch_atomic_intptr_t *)
+ ownerp = (xnarch_atomic_t *)
xnheap_alloc(&xnsys_ppd_get(attr->pshared)->sem_heap,
- sizeof(xnarch_atomic_intptr_t));
+ sizeof(xnarch_atomic_t));
if (!ownerp) {
xnfree(mutex);
return EAGAIN;
@@ -266,7 +266,7 @@ int pthread_mutex_destroy(pthread_mutex_
return EPERM;
}
- if (xnarch_atomic_intptr_get(mutex->owner)) {
+ if (xnarch_atomic_get(mutex->owner) != XN_NO_HANDLE) {
cb_write_unlock(&shadow->lock, s);
return EBUSY;
}
@@ -290,6 +290,10 @@ int pse51_mutex_timedlock_break(struct _
spl_t s;
int err;
+ /* We need a valid thread handle for the fast lock. */
+ if (xnthread_handle(cur) == XN_NO_HANDLE)
+ return -EPERM;
+
err = pse51_mutex_timedlock_internal(cur, shadow, 1, timed, abs_to);
if (err != -EBUSY)
goto unlock_and_return;
@@ -392,7 +396,7 @@ int pthread_mutex_trylock(pthread_mutex_
return -PTR_ERR(owner);
err = EBUSY;
- if (clear_claimed(owner) == cur) {
+ if (owner == cur) {
pse51_mutex_t *mutex = shadow->mutex;
if (mutex->attr.type == PTHREAD_MUTEX_RECURSIVE) {
@@ -573,7 +577,8 @@ int pthread_mutex_unlock(pthread_mutex_t
mutex = shadow->mutex;
- if (clear_claimed(xnarch_atomic_intptr_get(mutex->owner)) != cur) {
+ if (clear_claimed(xnarch_atomic_get(mutex->owner)) !=
+ xnthread_handle(cur)) {
err = EPERM;
goto out;
}
Index: b/ksrc/skins/posix/mutex.h
===================================================================
--- a/ksrc/skins/posix/mutex.h
+++ b/ksrc/skins/posix/mutex.h
@@ -34,7 +34,7 @@ union __xeno_mutex {
xnarch_atomic_t lock;
union {
unsigned owner_offset;
- xnarch_atomic_intptr_t *owner;
+ xnarch_atomic_t *owner;
};
struct pse51_mutexattr attr;
#endif /* CONFIG_XENO_FASTSEM */
@@ -54,7 +54,7 @@ typedef struct pse51_mutex {
#define link2mutex(laddr) \
((pse51_mutex_t *)(((char *)laddr) - offsetof(pse51_mutex_t, link)))
- xnarch_atomic_intptr_t *owner;
+ xnarch_atomic_t *owner;
pthread_mutexattr_t attr;
unsigned sleepers;
pse51_kqueues_t *owningq;
@@ -77,7 +77,7 @@ int pse51_mutex_check_init(struct __shad
int pse51_mutex_init_internal(struct __shadow_mutex *shadow,
pse51_mutex_t *mutex,
- xnarch_atomic_intptr_t *ownerp,
+ xnarch_atomic_t *ownerp,
const pthread_mutexattr_t *attr);
void pse51_mutex_destroy_internal(pse51_mutex_t *mutex,
@@ -88,6 +88,7 @@ pse51_mutex_trylock_internal(xnthread_t
struct __shadow_mutex *shadow, unsigned count)
{
pse51_mutex_t *mutex = shadow->mutex;
+ xnhandle_t ownerh;
xnthread_t *owner;
if (xnpod_unblockable_p())
@@ -101,9 +102,14 @@ pse51_mutex_trylock_internal(xnthread_t
return ERR_PTR(-EPERM);
#endif /* XENO_DEBUG(POSIX) */
- owner = xnarch_atomic_intptr_cmpxchg(mutex->owner, NULL, cur);
- if (unlikely(owner != NULL))
+ ownerh = xnarch_atomic_cmpxchg(mutex->owner, XN_NO_HANDLE,
+ xnthread_handle(cur));
+ if (unlikely(ownerh != XN_NO_HANDLE)) {
+ owner = xnthread_lookup(clear_claimed(ownerh));
+ if (!owner)
+ return ERR_PTR(-EINVAL);
return owner;
+ }
shadow->lockcnt = count;
return NULL;
@@ -118,7 +124,8 @@ static inline int pse51_mutex_timedlock_
{
pse51_mutex_t *mutex;
- xnthread_t *owner, *old;
+ xnthread_t *owner;
+ xnhandle_t ownerh, old;
spl_t s;
int err;
@@ -128,32 +135,39 @@ static inline int pse51_mutex_timedlock_
return PTR_ERR(owner);
mutex = shadow->mutex;
- if (clear_claimed(owner) == cur)
+ if (owner == cur)
return -EBUSY;
/* Set bit 0, so that mutex_unlock will know that the mutex is claimed.
Hold the nklock, for mutual exclusion with slow mutex_unlock. */
xnlock_get_irqsave(&nklock, s);
- if (test_claimed(owner)) {
- old = xnarch_atomic_intptr_get(mutex->owner);
+ if (test_claimed(ownerh)) {
+ old = xnarch_atomic_get(mutex->owner);
goto test_no_owner;
}
do {
- old = xnarch_atomic_intptr_cmpxchg(mutex->owner,
- owner, set_claimed(owner, 1));
- if (likely(old == owner))
+ old = xnarch_atomic_cmpxchg(mutex->owner, ownerh,
+ set_claimed(ownerh, 1));
+ if (likely(old == ownerh))
break;
test_no_owner:
- if (old == NULL) {
+ if (old == XN_NO_HANDLE) {
/* Owner called fast mutex_unlock
(on another cpu) */
xnlock_put_irqrestore(&nklock, s);
goto retry_lock;
}
- owner = old;
- } while (!test_claimed(owner));
+ ownerh = old;
+ } while (!test_claimed(ownerh));
+
+ owner = xnthread_lookup(clear_claimed(ownerh));
+
+ if (unlikely(!owner)) {
+ err = -EINVAL;
+ goto error;
+ }
- xnsynch_set_owner(&mutex->synchbase, clear_claimed(owner));
+ xnsynch_set_owner(&mutex->synchbase, owner);
++mutex->sleepers;
if (timed)
xnsynch_sleep_on(&mutex->synchbase, abs_to, XN_REALTIME);
@@ -174,7 +188,8 @@ static inline int pse51_mutex_timedlock_
goto error;
}
- xnarch_atomic_intptr_set(mutex->owner,set_claimed(cur, mutex->sleepers));
+ ownerh = set_claimed(xnthread_handle(cur), mutex->sleepers);
+ xnarch_atomic_set(mutex->owner, ownerh);
shadow->lockcnt = count;
xnlock_put_irqrestore(&nklock, s);
@@ -182,9 +197,9 @@ static inline int pse51_mutex_timedlock_
error:
if (!mutex->sleepers)
- xnarch_atomic_intptr_set
+ xnarch_atomic_set
(mutex->owner,
- clear_claimed(xnarch_atomic_intptr_get(mutex->owner)));
+ clear_claimed(xnarch_atomic_get(mutex->owner)));
xnlock_put_irqrestore(&nklock, s);
return err;
}
@@ -192,16 +207,18 @@ static inline int pse51_mutex_timedlock_
static inline void pse51_mutex_unlock_internal(xnthread_t *cur,
pse51_mutex_t *mutex)
{
+ xnhandle_t ownerh;
xnthread_t *owner;
spl_t s;
- if (likely(xnarch_atomic_intptr_cmpxchg(mutex->owner, cur, NULL) == cur))
+ if (likely(xnarch_atomic_cmpxchg(mutex->owner, cur, XN_NO_HANDLE) ==
+ xnthread_handle(cur)))
return;
xnlock_get_irqsave(&nklock, s);
owner = xnsynch_wakeup_one_sleeper(&mutex->synchbase);
- xnarch_atomic_intptr_set(mutex->owner,
- set_claimed(owner, mutex->sleepers));
+ ownerh = set_claimed(xnthread_handle(owner), mutex->sleepers);
+ xnarch_atomic_set(mutex->owner, ownerh);
if (owner)
xnpod_schedule();
xnlock_put_irqrestore(&nklock, s);
Index: b/ksrc/skins/posix/syscall.c
===================================================================
--- a/ksrc/skins/posix/syscall.c
+++ b/ksrc/skins/posix/syscall.c
@@ -1060,7 +1060,8 @@ static int __pthread_mutex_unlock(struct
mutex = shadow->mutex;
- if (clear_claimed(xnarch_atomic_intptr_get(mutex->owner)) != cur) {
+ if (clear_claimed(xnarch_atomic_get(mutex->owner)) !=
+ xnthread_handle(cur)) {
err = -EPERM;
goto out;
}
@@ -1119,7 +1120,7 @@ static int __pthread_mutex_init(struct p
pthread_mutexattr_t locattr, *attr, *uattrp;
union __xeno_mutex mx, *umx;
pse51_mutex_t *mutex;
- xnarch_atomic_intptr_t *ownerp;
+ xnarch_atomic_t *ownerp;
int err;
umx = (union __xeno_mutex *)__xn_reg_arg1(regs);
@@ -1144,9 +1145,9 @@ static int __pthread_mutex_init(struct p
if (!mutex)
return -ENOMEM;
- ownerp = (xnarch_atomic_intptr_t *)
+ ownerp = (xnarch_atomic_t *)
xnheap_alloc(&xnsys_ppd_get(attr->pshared)->sem_heap,
- sizeof(xnarch_atomic_intptr_t));
+ sizeof(xnarch_atomic_t));
if (!ownerp) {
xnfree(mutex);
return -EAGAIN;
@@ -1185,7 +1186,7 @@ static int __pthread_mutex_destroy(struc
if (pse51_kqueues(mutex->attr.pshared) != mutex->owningq)
return -EPERM;
- if (xnarch_atomic_intptr_get(mutex->owner))
+ if (xnarch_atomic_get(mutex->owner) != XN_NO_HANDLE)
return -EBUSY;
pse51_mark_deleted(shadow);
Index: b/src/skins/posix/mutex.c
===================================================================
--- a/src/skins/posix/mutex.c
+++ b/src/skins/posix/mutex.c
@@ -31,12 +31,12 @@ extern int __pse51_muxid;
extern unsigned long xeno_sem_heap[2];
-static xnarch_atomic_intptr_t *get_ownerp(struct __shadow_mutex *shadow)
+static xnarch_atomic_t *get_ownerp(struct __shadow_mutex *shadow)
{
if (likely(!shadow->attr.pshared))
return shadow->owner;
- return (xnarch_atomic_intptr_t *) (xeno_sem_heap[1] + shadow->owner_offset);
+ return (xnarch_atomic_t *) (xeno_sem_heap[1] + shadow->owner_offset);
}
#endif /* CONFIG_XENO_FASTSEM */
@@ -117,7 +117,7 @@ int __wrap_pthread_mutex_init(pthread_mu
#ifdef CONFIG_XENO_FASTSEM
if (!shadow->attr.pshared)
- shadow->owner = (xnarch_atomic_intptr_t *)
+ shadow->owner = (xnarch_atomic_t *)
(xeno_sem_heap[0] + shadow->owner_offset);
cb_write_unlock(&shadow->lock, s);
@@ -149,10 +149,10 @@ int __wrap_pthread_mutex_lock(pthread_mu
int err = 0;
#ifdef CONFIG_XENO_FASTSEM
- xnthread_t *cur, *owner;
+ xnhandle_t cur, owner;
cur = xeno_get_current();
- if (!cur)
+ if (cur == XN_NO_HANDLE)
return EPERM;
if (unlikely(cb_try_read_lock(&shadow->lock, s)))
@@ -163,8 +163,8 @@ int __wrap_pthread_mutex_lock(pthread_mu
goto out;
}
- owner = xnarch_atomic_intptr_cmpxchg(get_ownerp(shadow), NULL, cur);
- if (likely(!owner)) {
+ owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
+ if (likely(owner == XN_NO_HANDLE)) {
shadow->lockcnt = 1;
cb_read_unlock(&shadow->lock, s);
return 0;
@@ -210,10 +210,10 @@ int __wrap_pthread_mutex_timedlock(pthre
int err = 0;
#ifdef CONFIG_XENO_FASTSEM
- xnthread_t *cur, *owner;
+ xnhandle_t cur, owner;
cur = xeno_get_current();
- if (!cur)
+ if (cur == XN_NO_HANDLE)
return EPERM;
if (unlikely(cb_try_read_lock(&shadow->lock, s)))
@@ -224,8 +224,8 @@ int __wrap_pthread_mutex_timedlock(pthre
goto out;
}
- owner = xnarch_atomic_intptr_cmpxchg(get_ownerp(shadow), NULL, cur);
- if (likely(!owner)) {
+ owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
+ if (likely(owner == XN_NO_HANDLE)) {
shadow->lockcnt = 1;
cb_read_unlock(&shadow->lock, s);
return 0;
@@ -271,10 +271,10 @@ int __wrap_pthread_mutex_trylock(pthread
int err = 0;
#ifdef CONFIG_XENO_FASTSEM
- xnthread_t *cur, *owner;
+ xnhandle_t cur, owner;
cur = xeno_get_current();
- if (!cur)
+ if (cur == XN_NO_HANDLE)
return EPERM;
if (unlikely(cb_try_read_lock(&shadow->lock, s)))
@@ -285,8 +285,8 @@ int __wrap_pthread_mutex_trylock(pthread
goto out;
}
- owner = xnarch_atomic_intptr_cmpxchg(get_ownerp(shadow), NULL, cur);
- if (likely(!owner)) {
+ owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
+ if (likely(owner == XN_NO_HANDLE)) {
shadow->lockcnt = 1;
cb_read_unlock(&shadow->lock, s);
return 0;
@@ -325,11 +325,11 @@ int __wrap_pthread_mutex_unlock(pthread_
int err = 0;
#ifdef CONFIG_XENO_FASTSEM
- xnarch_atomic_intptr_t *ownerp;
- xnthread_t *cur;
+ xnarch_atomic_t *ownerp;
+ xnhandle_t cur, owner;
cur = xeno_get_current();
- if (!cur)
+ if (cur == XN_NO_HANDLE)
return EPERM;
if (unlikely(cb_try_read_lock(&shadow->lock, s)))
@@ -341,7 +341,8 @@ int __wrap_pthread_mutex_unlock(pthread_
}
ownerp = get_ownerp(shadow);
- if (unlikely(clear_claimed(xnarch_atomic_intptr_get(ownerp)) != cur)) {
+ owner = clear_claimed(xnarch_atomic_get(ownerp));
+ if (unlikely(owner != cur)) {
err = -EPERM;
goto out_err;
}
@@ -352,7 +353,7 @@ int __wrap_pthread_mutex_unlock(pthread_
goto out;
}
- if (likely(xnarch_atomic_intptr_cmpxchg(ownerp, cur, NULL) == cur)) {
+ if (likely(xnarch_atomic_cmpxchg(ownerp, cur, XN_NO_HANDLE) == cur)) {
out:
cb_read_unlock(&shadow->lock, s);
return 0;
Index: b/ksrc/skins/posix/thread.c
===================================================================
--- a/ksrc/skins/posix/thread.c
+++ b/ksrc/skins/posix/thread.c
@@ -234,6 +234,18 @@ int pthread_create(pthread_t *tid,
thread->hkey.mm = NULL;
#endif /* CONFIG_XENO_OPT_PERVASIVE */
+#ifdef CONFIG_XENO_FASTSEM
+ /* We need an anonymous registry entry to obtain a handle for fast
+ mutex locking. */
+ {
+ int err = xnthread_register(&thread->threadbase, "");
+ if (err) {
+ thread_destroy(thread);
+ return err;
+ }
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
*tid = thread; /* Must be done before the thread is started. */
if (start) /* Do not start shadow threads (i.e. start == NULL). */
Index: b/ksrc/skins/posix/Kconfig
===================================================================
--- a/ksrc/skins/posix/Kconfig
+++ b/ksrc/skins/posix/Kconfig
@@ -1,5 +1,6 @@
menuconfig XENO_SKIN_POSIX
depends on XENO_OPT_NUCLEUS
+ select XENO_OPT_REGISTRY if XENO_FASTSEM
tristate "POSIX API"
default y
help
Index: b/include/asm-generic/bits/bind.h
===================================================================
--- a/include/asm-generic/bits/bind.h
+++ b/include/asm-generic/bits/bind.h
@@ -15,18 +15,24 @@
__attribute__ ((weak))
pthread_key_t xeno_current_key;
-__attribute__ ((weak))
-pthread_once_t xeno_init_current_key_once = PTHREAD_ONCE_INIT;
__attribute__ ((weak))
void xeno_set_current(void)
{
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);
}
-static void init_current_key(void)
+static __attribute__ ((constructor))
+void init_current_key(void)
{
int err = pthread_key_create(&xeno_current_key, NULL);
if (err) {
@@ -168,8 +174,6 @@ xeno_bind_skin(unsigned skin_magic, cons
sa.sa_flags = 0;
sigaction(SIGXCPU, &sa, NULL);
- pthread_once(&xeno_init_current_key_once, &init_current_key);
-
#ifdef CONFIG_XENO_FASTSEM
/* In case we forked, we need to map the new local semaphore heap */
if (xeno_sem_heap[0])
@@ -244,8 +248,6 @@ xeno_bind_skin_opt(unsigned skin_magic,
xeno_arch_features_check();
#endif /* xeno_arch_features_check */
- pthread_once(&xeno_init_current_key_once, &init_current_key);
-
#ifdef CONFIG_XENO_FASTSEM
/* In case we forked, we need to map the new local semaphore heap */
if (xeno_sem_heap[0])
Index: b/ksrc/skins/native/Kconfig
===================================================================
--- a/ksrc/skins/native/Kconfig
+++ b/ksrc/skins/native/Kconfig
@@ -1,5 +1,6 @@
menuconfig XENO_SKIN_NATIVE
depends on XENO_OPT_NUCLEUS
+ select XENO_OPT_REGISTRY if XENO_FASTSEM
tristate "Native API"
default y
help
Index: b/ksrc/skins/native/task.c
===================================================================
--- a/ksrc/skins/native/task.c
+++ b/ksrc/skins/native/task.c
@@ -283,11 +283,9 @@ int rt_task_create(RT_TASK *task,
complete objects, so that the registry cannot return handles to
half-baked objects... */
- if (name) {
- err = xnthread_register(&task->thread_base, task->rname);
- if (err)
- xnpod_delete_thread(&task->thread_base);
- }
+ err = xnthread_register(&task->thread_base, name ? task->rname : "");
+ if (err)
+ xnpod_delete_thread(&task->thread_base);
return err;
}
Index: b/ksrc/skins/psos+/Kconfig
===================================================================
--- a/ksrc/skins/psos+/Kconfig
+++ b/ksrc/skins/psos+/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_PSOS
depends on XENO_OPT_NUCLEUS
select XENO_OPT_TIMING_PERIODIC
tristate "pSOS+ emulator"
- select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE
+ select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSEM
help
This API skin emulates WindRiver's pSOS+ operating system.
Index: b/ksrc/skins/uitron/Kconfig
===================================================================
--- a/ksrc/skins/uitron/Kconfig
+++ b/ksrc/skins/uitron/Kconfig
@@ -2,6 +2,7 @@ menuconfig XENO_SKIN_UITRON
depends on XENO_OPT_NUCLEUS
select XENO_OPT_TIMING_PERIODIC
select XENO_OPT_MAP
+ select XENO_OPT_REGISTRY if XENO_FASTSEM
tristate "uITRON API"
help
Index: b/ksrc/skins/uitron/task.c
===================================================================
--- a/ksrc/skins/uitron/task.c
+++ b/ksrc/skins/uitron/task.c
@@ -16,7 +16,6 @@
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include <nucleus/registry.h>
#include <nucleus/pod.h>
#include <nucleus/heap.h>
#include <uitron/task.h>
@@ -151,6 +150,16 @@ ER cre_tsk(ID tskid, T_CTSK *pk_ctsk)
xnlock_put_irqrestore(&nklock, s);
task->magic = uITRON_TASK_MAGIC;
+#ifdef CONFIG_XENO_FASTSEM
+ /* We need an anonymous registry entry to obtain a handle for fast
+ mutex locking. */
+ if (xnthread_register(&task->threadbase, "")) {
+ xnmap_remove(ui_task_idmap, tskid);
+ xnpod_abort_thread(&task->threadbase);
+ return E_NOMEM;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
return E_OK;
}
Index: b/ksrc/skins/rtai/Kconfig
===================================================================
--- a/ksrc/skins/rtai/Kconfig
+++ b/ksrc/skins/rtai/Kconfig
@@ -1,5 +1,6 @@
menuconfig XENO_SKIN_RTAI
depends on XENO_OPT_NUCLEUS
+ select XENO_OPT_REGISTRY if XENO_FASTSEM
tristate "RTAI emulator"
help
Index: b/ksrc/skins/rtai/task.c
===================================================================
--- a/ksrc/skins/rtai/task.c
+++ b/ksrc/skins/rtai/task.c
@@ -152,6 +152,16 @@ int rt_task_init(RT_TASK *task,
task->magic = RTAI_TASK_MAGIC;
appendq(&__rtai_task_q, &task->link);
+#ifdef CONFIG_XENO_FASTSEM
+ /* We need an anonymous registry entry to obtain a handle for fast
+ mutex locking. */
+ err = xnthread_register(&task->thread_base, "");
+ if (err) {
+ xnpod_abort_thread(&task->thread_base);
+ goto unlock_and_exit;
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
/* Add a switch hook only if a signal function has been declared
at least once for some created task. */
Index: b/ksrc/skins/vrtx/Kconfig
===================================================================
--- a/ksrc/skins/vrtx/Kconfig
+++ b/ksrc/skins/vrtx/Kconfig
@@ -3,7 +3,7 @@ menuconfig XENO_SKIN_VRTX
select XENO_OPT_TIMING_PERIODIC
select XENO_OPT_MAP
tristate "VRTX emulator"
- select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE
+ select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || CONFIG_XENO_FASTSEM
help
This API skin emulates Mentor Graphics's VRTX operating
Index: b/ksrc/skins/vrtx/task.c
===================================================================
--- a/ksrc/skins/vrtx/task.c
+++ b/ksrc/skins/vrtx/task.c
@@ -188,12 +188,25 @@ int sc_tecreate_inner(vrtxtask_t *task,
if (mode & 0x10)
bmode |= XNRRB;
- *errp = RET_OK;
-
xnlock_get_irqsave(&nklock, s);
appendq(&vrtx_task_q, &task->link);
xnlock_put_irqrestore(&nklock, s);
+#ifdef CONFIG_XENO_FASTSEM
+ /* We need an anonymous registry entry to obtain a handle for fast
+ mutex locking. */
+ {
+ int err = xnthread_register(&task->threadbase, "");
+ if (err) {
+ xnpod_abort_thread(&task->threadbase);
+ *errp = ER_MEM;
+ return -1;
+ }
+ }
+#endif /* CONFIG_XENO_FASTSEM */
+
+ *errp = RET_OK;
+
xnpod_start_thread(&task->threadbase,
bmode, 0, XNPOD_ALL_CPUS, &vrtxtask_trampoline,
task);
Index: b/ksrc/skins/vxworks/Kconfig
===================================================================
--- a/ksrc/skins/vxworks/Kconfig
+++ b/ksrc/skins/vxworks/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_VXWORKS
depends on XENO_OPT_NUCLEUS
select XENO_OPT_TIMING_PERIODIC
tristate "VxWorks emulator"
- select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE
+ select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSEM
help
This API skin emulates WindRiver's VxWorks operating system.
Index: b/ksrc/skins/rtdm/drvlib.c
===================================================================
--- a/ksrc/skins/rtdm/drvlib.c
+++ b/ksrc/skins/rtdm/drvlib.c
@@ -145,6 +145,14 @@ int rtdm_task_init(rtdm_task_t *task, co
if (err)
return err;
+#ifdef CONFIG_XENO_FASTSEM
+ /* We need an anonymous registry entry to obtain a handle for fast
+ mutex locking. */
+ err = xnthread_register(task, "");
+ if (err)
+ goto cleanup_out;
+#endif /* CONFIG_XENO_FASTSEM */
+
if (period > 0) {
err = xnpod_set_thread_periodic(task, XN_INFINITE,
xntbase_ns2ticks_ceil
^ permalink raw reply [flat|nested] 17+ messages in thread* [Xenomai-core] [PATCH 03/13] Remove xnarch_atomic_intptr
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 01/13] Generic thread registration Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 02/13] Handle-based xeno_get_current service Jan Kiszka
@ 2008-10-17 15:46 ` Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 04/13] Spread xeno_set_current under all skins Jan Kiszka
` (12 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:46 UTC (permalink / raw)
To: xenomai; +Cc: Jan Kiszka
No more users, no more use cases in sight, let's get rid of it.
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
include/asm-arm/atomic.h | 3 ---
include/asm-blackfin/atomic.h | 2 --
include/asm-generic/Makefile.am | 2 +-
include/asm-generic/Makefile.in | 2 +-
include/asm-generic/atomic.h | 24 ------------------------
include/asm-ia64/atomic.h | 2 --
include/asm-powerpc/atomic.h | 2 --
include/asm-x86/atomic.h | 2 --
8 files changed, 2 insertions(+), 37 deletions(-)
Index: b/include/asm-arm/atomic.h
===================================================================
--- a/include/asm-arm/atomic.h
+++ b/include/asm-arm/atomic.h
@@ -412,9 +412,6 @@ static __inline__ void xnarch_atomic_cle
typedef unsigned long atomic_flags_t;
-/* Add support for xnarch_atomic_intptr_t */
-#include <asm-generic/xenomai/atomic.h>
-
#endif /* !_XENO_ASM_ARM_ATOMIC_H */
// vim: ts=4 et sw=4 sts=4
Index: b/include/asm-blackfin/atomic.h
===================================================================
--- a/include/asm-blackfin/atomic.h
+++ b/include/asm-blackfin/atomic.h
@@ -42,8 +42,6 @@
typedef atomic_t atomic_counter_t;
typedef atomic_t xnarch_atomic_t;
-#include <asm-generic/xenomai/atomic.h>
-
#else /* !__KERNEL__ */
#include <asm/xenomai/syscall.h>
Index: b/include/asm-generic/Makefile.am
===================================================================
--- a/include/asm-generic/Makefile.am
+++ b/include/asm-generic/Makefile.am
@@ -1,5 +1,5 @@
includesubdir = $(includedir)/asm-generic
-includesub_HEADERS = arith.h atomic.h features.h hal.h syscall.h system.h wrappers.h
+includesub_HEADERS = arith.h features.h hal.h syscall.h system.h wrappers.h
SUBDIRS = bits
Index: b/include/asm-generic/Makefile.in
===================================================================
--- a/include/asm-generic/Makefile.in
+++ b/include/asm-generic/Makefile.in
@@ -226,7 +226,7 @@ target_vendor = @target_vendor@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
includesubdir = $(includedir)/asm-generic
-includesub_HEADERS = arith.h atomic.h features.h hal.h syscall.h system.h wrappers.h
+includesub_HEADERS = arith.h features.h hal.h syscall.h system.h wrappers.h
SUBDIRS = bits
all: all-recursive
Index: b/include/asm-generic/atomic.h
===================================================================
--- a/include/asm-generic/atomic.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _XENO_ASM_GENERIC_ATOMIC_H
-#define _XENO_ASM_GENERIC_ATOMIC_H
-
-typedef xnarch_atomic_t xnarch_atomic_intptr_t;
-
-static inline void *xnarch_atomic_intptr_get(xnarch_atomic_intptr_t *l)
-{
- xnarch_atomic_t *v = (xnarch_atomic_t *)l;
-
- return (void *)xnarch_atomic_get(v);
-}
-
-static inline void xnarch_atomic_intptr_set(xnarch_atomic_intptr_t *l, void *i)
-{
- xnarch_atomic_t *v = (xnarch_atomic_t *)l;
-
- xnarch_atomic_set(v, (long)i);
-}
-
-#define xnarch_atomic_intptr_cmpxchg(l, old, newval) \
- (void *)(xnarch_atomic_cmpxchg((xnarch_atomic_t *)(l), \
- (long)(old), (long)(newval)))
-
-#endif /* _XENO_ASM_GENERIC_ATOMIC_H */
Index: b/include/asm-ia64/atomic.h
===================================================================
--- a/include/asm-ia64/atomic.h
+++ b/include/asm-ia64/atomic.h
@@ -71,8 +71,6 @@ static inline void atomic_clear_mask(uns
#define xnarch_atomic_cmpxchg(pcounter,old,new) \
cmpxchg((&(pcounter)->counter),(old),(new))
-#include <asm-generic/xenomai/atomic.h>
-
#else /* !__KERNEL__ */
#include <asm/xenomai/features.h>
Index: b/include/asm-powerpc/atomic.h
===================================================================
--- a/include/asm-powerpc/atomic.h
+++ b/include/asm-powerpc/atomic.h
@@ -262,6 +262,4 @@ xnarch_atomic_cmpxchg(xnarch_atomic_t *p
typedef unsigned long atomic_flags_t;
-#include <asm-generic/xenomai/atomic.h>
-
#endif /* !_XENO_ASM_POWERPC_ATOMIC_H */
Index: b/include/asm-x86/atomic.h
===================================================================
--- a/include/asm-x86/atomic.h
+++ b/include/asm-x86/atomic.h
@@ -136,6 +136,4 @@ xnarch_atomic_cmpxchg(xnarch_atomic_t *v
#endif /* __KERNEL__ */
-#include <asm-generic/xenomai/atomic.h>
-
#endif /* !_XENO_ASM_X86_ATOMIC_64_H */
^ permalink raw reply [flat|nested] 17+ messages in thread* [Xenomai-core] [PATCH 04/13] Spread xeno_set_current under all skins
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (2 preceding siblings ...)
2008-10-17 15:46 ` [Xenomai-core] [PATCH 03/13] Remove xnarch_atomic_intptr Jan Kiszka
@ 2008-10-17 15:46 ` Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 05/13] Factor out xnsynch_acquire/release Jan Kiszka
` (11 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:46 UTC (permalink / raw)
To: xenomai; +Cc: Jan Kiszka
Spread xeno_set_current under all user space supporting skins.
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
src/skins/native/task.c | 13 +++++++++++--
src/skins/psos+/task.c | 18 ++++++++++++++----
src/skins/uitron/task.c | 18 +++++++++++++-----
src/skins/vrtx/task.c | 3 +++
src/skins/vxworks/taskLib.c | 3 +++
5 files changed, 44 insertions(+), 11 deletions(-)
Index: b/src/skins/native/task.c
===================================================================
--- a/src/skins/native/task.c
+++ b/src/skins/native/task.c
@@ -26,6 +26,7 @@
#include <limits.h>
#include <native/syscall.h>
#include <native/task.h>
+#include <asm-generic/bits/current.h>
#include "wrappers.h"
extern pthread_key_t __native_tskey;
@@ -88,6 +89,8 @@ static void *rt_task_trampoline(void *co
if (err)
goto fail;
+ xeno_set_current();
+
/* Wait on the barrier for the task to be started. The barrier
could be released in order to process Linux signals while the
Xenomai shadow is still dormant; in such a case, resume wait. */
@@ -169,6 +172,7 @@ int rt_task_shadow(RT_TASK *task, const
struct sched_param param;
struct rt_arg_bulk bulk;
RT_TASK task_desc;
+ int err;
if (task == NULL)
task = &task_desc; /* Discarded. */
@@ -191,8 +195,13 @@ int rt_task_shadow(RT_TASK *task, const
bulk.a4 = (u_long)mode;
bulk.a5 = (u_long)pthread_self();
- return XENOMAI_SKINCALL2(__native_muxid, __native_task_create, &bulk,
- NULL);
+ err = XENOMAI_SKINCALL2(__native_muxid, __native_task_create, &bulk,
+ NULL);
+
+ if (!err)
+ xeno_set_current();
+
+ return err;
}
int rt_task_bind(RT_TASK *task, const char *name, RTIME timeout)
Index: b/src/skins/psos+/task.c
===================================================================
--- a/src/skins/psos+/task.c
+++ b/src/skins/psos+/task.c
@@ -26,6 +26,7 @@
#include <memory.h>
#include <string.h>
#include <psos+/psos.h>
+#include <asm-generic/bits/current.h>
extern int __psos_muxid;
@@ -89,6 +90,8 @@ static void *psos_task_trampoline(void *
if (err)
goto fail;
+ xeno_set_current();
+
/* Wait on the barrier for the task to be started. The barrier
could be released in order to process Linux signals while the
Xenomai shadow is still dormant; in such a case, resume wait. */
@@ -173,14 +176,21 @@ u_long t_shadow(const char *name, /* Xen
u_long flags,
u_long *tid_r)
{
+ int err;
+
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
old_sigharden_handler = signal(SIGHARDEN, &psos_task_sigharden);
- return XENOMAI_SKINCALL5(__psos_muxid,
- __psos_t_create,
- name, prio, flags,
- tid_r, NULL);
+ err = XENOMAI_SKINCALL5(__psos_muxid,
+ __psos_t_create,
+ name, prio, flags,
+ tid_r, NULL);
+
+ if (!err)
+ xeno_set_current();
+
+ return err;
}
u_long t_start(u_long tid,
Index: b/src/skins/uitron/task.c
===================================================================
--- a/src/skins/uitron/task.c
+++ b/src/skins/uitron/task.c
@@ -25,6 +25,7 @@
#include <limits.h>
#include <asm/xenomai/system.h>
#include <uitron/uitron.h>
+#include <asm-generic/bits/current.h>
extern int __uitron_muxid;
@@ -89,6 +90,8 @@ static void *uitron_task_trampoline(void
if (err)
goto fail;
+ xeno_set_current();
+
/* iargs->pk_ctsk might not be valid anymore, after our parent
was released from the completion sync, so do not
dereference this pointer. */
@@ -150,7 +153,7 @@ ER cre_tsk(ID tskid, T_CTSK *pk_ctsk)
ER shd_tsk(ID tskid, T_CTSK *pk_ctsk) /* Xenomai extension. */
{
struct sched_param param;
- int policy;
+ int policy, err;
/* Make sure the POSIX library caches the right priority. */
policy = uitron_task_set_posix_priority(pk_ctsk->itskpri, ¶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;
@@ -116,6 +117,8 @@ static void *vrtx_task_trampoline(void *
if (err)
goto fail;
+ xeno_set_current();
+
/* Wait on the barrier for the task to be started. The barrier
could be released in order to process Linux signals while the
Xenomai shadow is still dormant; in such a case, resume wait. */
Index: b/src/skins/vxworks/taskLib.c
===================================================================
--- a/src/skins/vxworks/taskLib.c
+++ b/src/skins/vxworks/taskLib.c
@@ -27,6 +27,7 @@
#include <errno.h>
#include <limits.h>
#include <vxworks/vxworks.h>
+#include <asm-generic/bits/current.h>
#include "wrappers.h"
extern pthread_key_t __vxworks_tskey;
@@ -117,6 +118,8 @@ static void *wind_task_trampoline(void *
if (err)
goto fail;
+ xeno_set_current();
+
/* Wait on the barrier for the task to be started. The barrier
could be released in order to process Linux signals while the
Xenomai shadow is still dormant; in such a case, resume wait. */
^ permalink raw reply [flat|nested] 17+ messages in thread* [Xenomai-core] [PATCH 05/13] Factor out xnsynch_acquire/release
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (3 preceding siblings ...)
2008-10-17 15:46 ` [Xenomai-core] [PATCH 04/13] Spread xeno_set_current under all skins Jan Kiszka
@ 2008-10-17 15:46 ` Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 06/13] Refactor mutex lockcnt tracking Jan Kiszka
` (10 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:46 UTC (permalink / raw)
To: xenomai; +Cc: Jan Kiszka
This patch addresses the increasing divergence of owner-tracking vs.
owner-less xnsynch objects.
Services dealing with the former will include the new, lockless xnsynch
prologue for optimizing its fastpath. At the the same time, this
additional code should not disturb too much in those cases where we do
not track ownership (condition variables, events, semaphores etc.).
Moreover, I noticed that some of the existing code assumes XNSYNCH_NOPIP
means no ownership, which is surely not true. The already visible effect
is that lock stealing is needlessly restricted to XNSYNCH_PIP.
Going through the API, I dug out three diverging services and replaced
them with two new ones:
Owner-less xnsynch objects:
- xnsynch_sleep_on
- xnsynch_wakeup_one_sleeper
- xnsynch_wakeup_this_sleeper
Owner-tracking xnsynch objects:
- xnsynch_acquire
- xnsynch_release
The latter type of objects are marked with the new flag XNSYNCH_OWNER,
used only for debugging and code documentation purposes in the current
implementation.
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
include/nucleus/synch.h | 16 +
include/rtdm/rtdm_driver.h | 2
ksrc/nucleus/synch.c | 418 +++++++++++++++++++++++++++++---------------
ksrc/skins/native/cond.c | 2
ksrc/skins/native/mutex.c | 7
ksrc/skins/native/task.c | 5
ksrc/skins/posix/cond.c | 2
ksrc/skins/posix/mutex.c | 10 -
ksrc/skins/posix/mutex.h | 6
ksrc/skins/rtai/sem.c | 10 -
ksrc/skins/rtdm/drvlib.c | 15 -
ksrc/skins/vrtx/mx.c | 6
ksrc/skins/vxworks/semLib.c | 6
13 files changed, 326 insertions(+), 179 deletions(-)
Index: b/include/nucleus/synch.h
===================================================================
--- a/include/nucleus/synch.h
+++ b/include/nucleus/synch.h
@@ -30,10 +30,11 @@
#define XNSYNCH_NOPIP 0x0
#define XNSYNCH_PIP 0x2
#define XNSYNCH_DREORD 0x4
+#define XNSYNCH_OWNER 0x8
#if defined(__KERNEL__) || defined(__XENO_SIM__)
-#define XNSYNCH_CLAIMED 0x8 /* Claimed by other thread(s) w/ PIP */
+#define XNSYNCH_CLAIMED 0x10 /* Claimed by other thread(s) w/ PIP */
/* Spare flags usable by upper interfaces */
#define XNSYNCH_SPARE0 0x01000000
@@ -105,13 +106,18 @@ void xnsynch_sleep_on(xnsynch_t *synch,
struct xnthread *xnsynch_wakeup_one_sleeper(xnsynch_t *synch);
-struct xnthread *xnsynch_peek_pendq(xnsynch_t *synch);
-
xnpholder_t *xnsynch_wakeup_this_sleeper(xnsynch_t *synch,
xnpholder_t *holder);
-int xnsynch_flush(xnsynch_t *synch,
- xnflags_t reason);
+void xnsynch_acquire(xnsynch_t *synch,
+ xnticks_t timeout,
+ xntmode_t timeout_mode);
+
+struct xnthread *xnsynch_release(xnsynch_t *synch);
+
+struct xnthread *xnsynch_peek_pendq(xnsynch_t *synch);
+
+int xnsynch_flush(xnsynch_t *synch, xnflags_t reason);
void xnsynch_release_all_ownerships(struct xnthread *thread);
Index: b/ksrc/nucleus/synch.c
===================================================================
--- a/ksrc/nucleus/synch.c
+++ b/ksrc/nucleus/synch.c
@@ -59,6 +59,12 @@
* - XNSYNCH_PRIO causes the threads waiting for the resource to pend
* in priority order. Otherwise, FIFO ordering is used (XNSYNCH_FIFO).
*
+ * - XNSYNCH_OWNER indicates that the synchronization object shall
+ * track its owning thread (required if XNSYNCH_PIP is selected). Note
+ * that setting this flag implies the use xnsynch_acquire and
+ * xnsynch_release instead of xnsynch_sleep_on and
+ * xnsynch_wakeup_one_sleeper/xnsynch_wakeup_this_sleeper.
+ *
* - XNSYNCH_PIP causes the priority inheritance mechanism to be
* automatically activated when a priority inversion is detected among
* threads using this object. Otherwise, no priority inheritance takes
@@ -89,7 +95,7 @@ void xnsynch_init(xnsynch_t *synch, xnfl
initph(&synch->link);
if (flags & XNSYNCH_PIP)
- flags |= XNSYNCH_PRIO; /* Obviously... */
+ flags |= XNSYNCH_PRIO | XNSYNCH_OWNER; /* Obviously... */
synch->status = flags & ~XNSYNCH_CLAIMED;
synch->owner = NULL;
@@ -98,6 +104,209 @@ void xnsynch_init(xnsynch_t *synch, xnfl
xnarch_init_display_context(synch);
}
+/*!
+ * \fn void xnsynch_sleep_on(xnsynch_t *synch, xnticks_t timeout,
+ * xntmode_t timeout_mode);
+ * \brief Sleep on an ownerless synchronization object.
+ *
+ * Makes the calling thread sleep on the specified synchronization
+ * object, waiting for it to be signaled.
+ *
+ * This service should be called by upper interfaces wanting the
+ * current thread to pend on the given resource. It must not be used
+ * with synchronization objects that are supposed to track ownership
+ * (XNSYNCH_OWNER).
+ *
+ * @param synch The descriptor address of the synchronization object
+ * to sleep on.
+ *
+ * @param timeout The timeout which may be used to limit the time the
+ * thread pends on the resource. This value is a wait time given in
+ * ticks (see note). It can either be relative, absolute monotonic, or
+ * absolute adjustable depending on @a timeout_mode. Passing XN_INFINITE
+ * @b and setting @a mode to XN_RELATIVE specifies an unbounded wait. All
+ * other values are used to initialize a watchdog timer.
+ *
+ * @param timeout_mode The mode of the @a timeout parameter. It can
+ * either be set to XN_RELATIVE, XN_ABSOLUTE, or XN_REALTIME (see also
+ * xntimer_start()).
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Kernel-based task
+ * - User-space task
+ *
+ * Rescheduling: always.
+ *
+ * @note The @a timeout value will be interpreted as jiffies if the
+ * current thread is bound to a periodic time base (see
+ * xnpod_init_thread), or nanoseconds otherwise.
+ */
+
+void xnsynch_sleep_on(xnsynch_t *synch, xnticks_t timeout,
+ xntmode_t timeout_mode)
+{
+ xnthread_t *thread = xnpod_current_thread();
+ spl_t s;
+
+ XENO_BUGON(NUCLEUS, testbits(synch->status, XNSYNCH_OWNER));
+
+ xnlock_get_irqsave(&nklock, s);
+
+ trace_mark(xn_nucleus_synch_sleepon,
+ "thread %p thread_name %s synch %p",
+ thread, xnthread_name(thread), synch);
+
+ if (!testbits(synch->status, XNSYNCH_PRIO)) /* i.e. FIFO */
+ appendpq(&synch->pendq, &thread->plink);
+ else /* i.e. priority-sorted */
+ insertpqf(&synch->pendq, &thread->plink, thread->cprio);
+
+ xnpod_suspend_thread(thread, XNPEND, timeout, timeout_mode, synch);
+
+ xnlock_put_irqrestore(&nklock, s);
+}
+
+/*!
+ * \fn xnthread_t *xnsynch_wakeup_one_sleeper(xnsynch_t *synch);
+ * \brief Give the resource ownership to the next waiting thread.
+ *
+ * This service wakes up the thread which is currently leading the
+ * synchronization object's pending list. The sleeping thread is
+ * unblocked from its pending state, but no reschedule is performed.
+ *
+ * This service should be called by upper interfaces wanting to signal
+ * the given resource so that a single waiter is resumed. It must not
+ * be used with synchronization objects that are supposed to track
+ * ownership (XNSYNCH_OWNER not set).
+ *
+ * @param synch The descriptor address of the synchronization object
+ * whose ownership is changed.
+ *
+ * @return The descriptor address of the unblocked thread.
+ *
+ * Side-effects:
+ *
+ * - The effective priority of the previous resource owner might be
+ * lowered to its base priority value as a consequence of the priority
+ * inheritance boost being cleared.
+ *
+ * - The synchronization object ownership is transfered to the
+ * unblocked thread.
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Interrupt service routine
+ * - Kernel-based task
+ * - User-space task
+ *
+ * Rescheduling: never.
+ */
+
+xnthread_t *xnsynch_wakeup_one_sleeper(xnsynch_t *synch)
+{
+ xnthread_t *thread = NULL;
+ xnpholder_t *holder;
+ spl_t s;
+
+ XENO_BUGON(NUCLEUS, testbits(synch->status, XNSYNCH_OWNER));
+
+ xnlock_get_irqsave(&nklock, s);
+
+ holder = getpq(&synch->pendq);
+
+ if (holder) {
+ thread = link2thread(holder, plink);
+ thread->wchan = NULL;
+ trace_mark(xn_nucleus_synch_wakeup_one,
+ "thread %p thread_name %s synch %p",
+ thread, xnthread_name(thread), synch);
+ xnpod_resume_thread(thread, XNPEND);
+ }
+
+ xnlock_put_irqrestore(&nklock, s);
+
+ xnarch_post_graph_if(synch, 0, emptypq_p(&synch->pendq));
+
+ return thread;
+}
+
+/*!
+ * \fn void xnsynch_wakeup_this_sleeper(xnsynch_t *synch, xnpholder_t *holder);
+ * \brief Give the resource ownership to a given waiting thread.
+ *
+ * This service wakes up a specific thread which is currently pending on
+ * the given synchronization object. The sleeping thread is unblocked
+ * from its pending state, but no reschedule is performed.
+ *
+ * This service should be called by upper interfaces wanting to signal
+ * the given resource so that a specific waiter is resumed. It must not
+ * be used with synchronization objects that are supposed to track
+ * ownership (XNSYNCH_OWNER not set).
+ *
+ * @param synch The descriptor address of the synchronization object
+ * whose ownership is changed.
+ *
+ * @param holder The link holder address of the thread to unblock
+ * (&thread->plink) which MUST be currently linked to the
+ * synchronization object's pending queue (i.e. synch->pendq).
+ *
+ * @return The link address of the unblocked thread in the
+ * synchronization object's pending queue.
+ *
+ * Side-effects:
+ *
+ * - The effective priority of the previous resource owner might be
+ * lowered to its base priority value as a consequence of the priority
+ * inheritance boost being cleared.
+ *
+ * - The synchronization object ownership is transfered to the
+ * unblocked thread.
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Interrupt service routine
+ * - Kernel-based task
+ * - User-space task
+ *
+ * Rescheduling: never.
+ */
+
+xnpholder_t *xnsynch_wakeup_this_sleeper(xnsynch_t *synch, xnpholder_t *holder)
+{
+ xnthread_t *thread;
+ xnpholder_t *nholder;
+ spl_t s;
+
+ XENO_BUGON(NUCLEUS, testbits(synch->status, XNSYNCH_OWNER));
+
+ xnlock_get_irqsave(&nklock, s);
+
+ nholder = poppq(&synch->pendq, holder);
+
+ thread = link2thread(holder, plink);
+ thread->wchan = NULL;
+ trace_mark(xn_nucleus_synch_wakeup_this,
+ "thread %p thread_name %s synch %p",
+ thread, xnthread_name(thread), synch);
+ xnpod_resume_thread(thread, XNPEND);
+
+ xnlock_put_irqrestore(&nklock, s);
+
+ xnarch_post_graph_if(synch, 0, emptypq_p(&synch->pendq));
+
+ return nholder;
+}
+
/*
* xnsynch_renice_thread() -- This service is used by the PIP code to
* raise/lower a thread's priority. The thread's base priority value
@@ -125,19 +334,20 @@ static void xnsynch_renice_thread(xnthre
}
/*!
- * \fn void xnsynch_sleep_on(xnsynch_t *synch, xnticks_t timeout,
- * xntmode_t timeout_mode)
- *
- * \brief Sleep on a synchronization object.
- *
- * Makes the calling thread sleep on the specified synchronization
- * object, waiting for it to be signaled.
+ * \fn void xnsynch_acquire(xnsynch_t *synch, xnticks_t timeout,
+ * xntmode_t timeout_mode);
+ * \brief Acquire the ownership of a synchronization object.
*
* This service should be called by upper interfaces wanting the
- * current thread to pend on the given resource.
+ * current thread to acquire the ownership of the given resource. If
+ * the resource is already assigned to a thread, the caller is
+ * suspended.
+ *
+ * This service must be used only with synchronization objects that
+ * track ownership (XNSYNCH_OWNER set.
*
* @param synch The descriptor address of the synchronization object
- * to sleep on.
+ * to acquire.
*
* @param timeout The timeout which may be used to limit the time the
* thread pends on the resource. This value is a wait time given in
@@ -158,36 +368,24 @@ static void xnsynch_renice_thread(xnthre
* - Kernel-based task
* - User-space task
*
- * Rescheduling: always.
+ * Rescheduling: possible.
*
* @note The @a timeout value will be interpreted as jiffies if the
* current thread is bound to a periodic time base (see
* xnpod_init_thread), or nanoseconds otherwise.
*/
-void xnsynch_sleep_on(xnsynch_t *synch, xnticks_t timeout,
- xntmode_t timeout_mode)
+void xnsynch_acquire(xnsynch_t *synch, xnticks_t timeout,
+ xntmode_t timeout_mode)
{
xnthread_t *thread = xnpod_current_thread(), *owner;
spl_t s;
- xnlock_get_irqsave(&nklock, s);
+ XENO_BUGON(NUCLEUS, !testbits(synch->status, XNSYNCH_OWNER));
- trace_mark(xn_nucleus_synch_sleepon,
- "thread %p thread_name %s synch %p",
- thread, xnthread_name(thread), synch);
+ xnlock_get_irqsave(&nklock, s);
- if (!testbits(synch->status, XNSYNCH_PRIO)) { /* i.e. FIFO */
- appendpq(&synch->pendq, &thread->plink);
- xnpod_suspend_thread(thread, XNPEND, timeout, timeout_mode, synch);
- goto unlock_and_exit;
- }
-
- if (!testbits(synch->status, XNSYNCH_PIP)) { /* i.e. no ownership */
- insertpqf(&synch->pendq, &thread->plink, thread->cprio);
- xnpod_suspend_thread(thread, XNPEND, timeout, timeout_mode, synch);
- goto unlock_and_exit;
- }
+ trace_mark(xn_nucleus_synch_acquire, "synch %p", synch);
redo:
owner = synch->owner;
@@ -198,6 +396,12 @@ redo:
goto unlock_and_exit;
}
+ if (!testbits(synch->status, XNSYNCH_PRIO)) { /* i.e. FIFO */
+ appendpq(&synch->pendq, &thread->plink);
+ xnpod_suspend_thread(thread, XNPEND, timeout, timeout_mode, synch);
+ goto unlock_and_exit;
+ }
+
if (thread->cprio > owner->cprio) {
if (xnthread_test_info(owner, XNWAKEN) && owner->wwake == synch) {
/* Ownership is still pending, steal the resource. */
@@ -207,19 +411,22 @@ redo:
goto unlock_and_exit;
}
- if (!xnthread_test_state(owner, XNBOOST)) {
- owner->bprio = owner->cprio;
- xnthread_set_state(owner, XNBOOST);
- }
+ insertpqf(&synch->pendq, &thread->plink, thread->cprio);
- if (testbits(synch->status, XNSYNCH_CLAIMED))
- removepq(&owner->claimq, &synch->link);
- else
- __setbits(synch->status, XNSYNCH_CLAIMED);
+ if (testbits(synch->status, XNSYNCH_PIP)) {
+ if (!xnthread_test_state(owner, XNBOOST)) {
+ owner->bprio = owner->cprio;
+ xnthread_set_state(owner, XNBOOST);
+ }
+
+ if (testbits(synch->status, XNSYNCH_CLAIMED))
+ removepq(&owner->claimq, &synch->link);
+ else
+ __setbits(synch->status, XNSYNCH_CLAIMED);
- insertpqf(&owner->claimq, &synch->link, thread->cprio);
- insertpqf(&synch->pendq, &thread->plink, thread->cprio);
- xnsynch_renice_thread(owner, thread->cprio);
+ insertpqf(&owner->claimq, &synch->link, thread->cprio);
+ xnsynch_renice_thread(owner, thread->cprio);
+ }
} else
insertpqf(&synch->pendq, &thread->plink, thread->cprio);
@@ -335,17 +542,17 @@ void xnsynch_renice_sleeper(xnthread_t *
}
}
-/*!
- * \fn xnthread_t *xnsynch_wakeup_one_sleeper(xnsynch_t *synch);
+/*!
+ * \fn xnthread_t *xnsynch_release(xnsynch_t *synch);
* \brief Give the resource ownership to the next waiting thread.
*
- * This service gives the ownership of a synchronization object to the
- * thread which is currently leading the object's pending list. The
- * sleeping thread is unblocked, but no action is taken regarding the
- * previous owner of the resource.
+ * This service releases the ownership of the given synchronization
+ * object. The thread which is currently leading the object's pending
+ * list, if any, is unblocked from its pending state. However, no
+ * reschedule is performed.
*
- * This service should be called by upper interfaces wanting to signal
- * the given resource so that a single waiter is resumed.
+ * This service must be used only with synchronization objects that
+ * track ownership (XNSYNCH_OWNER set.
*
* @param synch The descriptor address of the synchronization object
* whose ownership is changed.
@@ -373,38 +580,41 @@ void xnsynch_renice_sleeper(xnthread_t *
* Rescheduling: never.
*/
-xnthread_t *xnsynch_wakeup_one_sleeper(xnsynch_t *synch)
+struct xnthread *xnsynch_release(xnsynch_t *synch)
{
- xnthread_t *thread = NULL, *lastowner;
+ xnthread_t *newowner, *lastowner;
xnpholder_t *holder;
spl_t s;
+ XENO_BUGON(NUCLEUS, !testbits(synch->status, XNSYNCH_OWNER));
+
xnlock_get_irqsave(&nklock, s);
- lastowner = synch->owner;
+ trace_mark(xn_nucleus_synch_release, "synch %p", synch);
+
holder = getpq(&synch->pendq);
if (holder) {
- thread = link2thread(holder, plink);
- thread->wchan = NULL;
- thread->wwake = synch;
- synch->owner = thread;
- xnthread_set_info(thread, XNWAKEN);
- trace_mark(xn_nucleus_synch_wakeup_one,
- "thread %p thread_name %s synch %p",
- thread, xnthread_name(thread), synch);
- xnpod_resume_thread(thread, XNPEND);
- } else
- synch->owner = NULL;
+ newowner = link2thread(holder, plink);
+ newowner->wchan = NULL;
+ newowner->wwake = synch;
+ lastowner = synch->owner;
+ synch->owner = newowner;
+ xnthread_set_info(newowner, XNWAKEN);
+ xnpod_resume_thread(newowner, XNPEND);
- if (testbits(synch->status, XNSYNCH_CLAIMED))
- xnsynch_clear_boost(synch, lastowner);
+ if (testbits(synch->status, XNSYNCH_CLAIMED))
+ xnsynch_clear_boost(synch, lastowner);
+ } else {
+ newowner = NULL;
+ synch->owner = NULL;
+ }
xnlock_put_irqrestore(&nklock, s);
xnarch_post_graph_if(synch, 0, emptypq_p(&synch->pendq));
- return thread;
+ return newowner;
}
/*!
@@ -446,80 +656,6 @@ xnthread_t *xnsynch_peek_pendq(xnsynch_t
}
/*!
- * \fn void xnsynch_wakeup_this_sleeper(xnsynch_t *synch, xnpholder_t *holder);
- * \brief Give the resource ownership to a given waiting thread.
- *
- * This service gives the ownership of a given synchronization object
- * to a specific thread which is currently pending on it. The sleeping
- * thread is unblocked from its pending state. No action is taken
- * regarding the previous resource owner.
- *
- * This service should be called by upper interfaces wanting to signal
- * the given resource so that a specific waiter is resumed.
- *
- * @param synch The descriptor address of the synchronization object
- * whose ownership is changed.
- *
- * @param holder The link holder address of the thread to unblock
- * (&thread->plink) which MUST be currently linked to the
- * synchronization object's pending queue (i.e. synch->pendq).
- *
- * @return The link address of the unblocked thread in the
- * synchronization object's pending queue.
- *
- * Side-effects:
- *
- * - The effective priority of the previous resource owner might be
- * lowered to its base priority value as a consequence of the priority
- * inheritance boost being cleared.
- *
- * - The synchronization object ownership is transfered to the
- * unblocked thread.
- *
- * Environments:
- *
- * This service can be called from:
- *
- * - Kernel module initialization/cleanup code
- * - Interrupt service routine
- * - Kernel-based task
- * - User-space task
- *
- * Rescheduling: never.
- */
-
-xnpholder_t *xnsynch_wakeup_this_sleeper(xnsynch_t *synch, xnpholder_t *holder)
-{
- xnthread_t *thread, *lastowner;
- xnpholder_t *nholder;
- spl_t s;
-
- xnlock_get_irqsave(&nklock, s);
-
- lastowner = synch->owner;
- nholder = poppq(&synch->pendq, holder);
-
- thread = link2thread(holder, plink);
- thread->wchan = NULL;
- thread->wwake = synch;
- synch->owner = thread;
- xnthread_set_info(thread, XNWAKEN);
- trace_mark(xn_nucleus_synch_wakeup_all,
- "thread %p thread_name %s synch %p",
- thread, xnthread_name(thread), synch);
- xnpod_resume_thread(thread, XNPEND);
-
- if (testbits(synch->status, XNSYNCH_CLAIMED))
- xnsynch_clear_boost(synch, lastowner);
-
- xnlock_put_irqrestore(&nklock, s);
-
- xnarch_post_graph_if(synch, 0, emptypq_p(&synch->pendq));
-
- return nholder;
-}
-
-/*!
* \fn void xnsynch_flush(xnsynch_t *synch, xnflags_t reason);
* \brief Unblock all waiters pending on a resource.
*
@@ -679,12 +815,12 @@ void xnsynch_release_all_ownerships(xnth
for (holder = getheadpq(&thread->claimq); holder != NULL;
holder = nholder) {
- /* Since xnsynch_wakeup_one_sleeper() alters the claim
+ /* Since xnsynch_release() alters the claim
queue, we need to be conservative while scanning
it. */
xnsynch_t *synch = link2synch(holder);
nholder = nextpq(&thread->claimq, holder);
- xnsynch_wakeup_one_sleeper(synch);
+ xnsynch_release(synch);
if (synch->cleanup)
synch->cleanup(synch);
}
@@ -701,3 +837,5 @@ EXPORT_SYMBOL(xnsynch_sleep_on);
EXPORT_SYMBOL(xnsynch_wakeup_one_sleeper);
EXPORT_SYMBOL(xnsynch_wakeup_this_sleeper);
EXPORT_SYMBOL(xnsynch_peek_pendq);
+EXPORT_SYMBOL(xnsynch_acquire);
+EXPORT_SYMBOL(xnsynch_release);
Index: b/include/rtdm/rtdm_driver.h
===================================================================
--- a/include/rtdm/rtdm_driver.h
+++ b/include/rtdm/rtdm_driver.h
@@ -1134,7 +1134,7 @@ static inline void rtdm_mutex_unlock(rtd
trace_mark(xn_rtdm_mutex_unlock, "mutex %p", mutex);
- if (unlikely(xnsynch_wakeup_one_sleeper(&mutex->synch_base) != NULL))
+ if (unlikely(xnsynch_release(&mutex->synch_base) != NULL))
xnpod_schedule();
}
Index: b/ksrc/skins/native/cond.c
===================================================================
--- a/ksrc/skins/native/cond.c
+++ b/ksrc/skins/native/cond.c
@@ -421,7 +421,7 @@ int rt_cond_wait_inner(RT_COND *cond, RT
mutex->lockcnt = 0;
- if (xnsynch_wakeup_one_sleeper(&mutex->synch_base)) {
+ if (xnsynch_release(&mutex->synch_base)) {
mutex->lockcnt = 1;
/* Scheduling deferred */
}
Index: b/ksrc/skins/native/mutex.c
===================================================================
--- a/ksrc/skins/native/mutex.c
+++ b/ksrc/skins/native/mutex.c
@@ -170,7 +170,8 @@ int rt_mutex_create(RT_MUTEX *mutex, con
if (xnpod_asynch_p())
return -EPERM;
- xnsynch_init(&mutex->synch_base, XNSYNCH_PRIO | XNSYNCH_PIP);
+ xnsynch_init(&mutex->synch_base,
+ XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER);
mutex->handle = 0; /* i.e. (still) unregistered mutex. */
mutex->magic = XENO_MUTEX_MAGIC;
mutex->lockcnt = 0;
@@ -309,7 +310,7 @@ int rt_mutex_acquire_inner(RT_MUTEX *mut
goto unlock_and_exit;
}
- xnsynch_sleep_on(&mutex->synch_base, timeout, timeout_mode);
+ xnsynch_acquire(&mutex->synch_base, timeout, timeout_mode);
if (xnthread_test_info(thread, XNRMID))
err = -EIDRM; /* Mutex deleted while pending. */
@@ -523,7 +524,7 @@ int rt_mutex_release(RT_MUTEX *mutex)
if (--mutex->lockcnt > 0)
goto unlock_and_exit;
- if (xnsynch_wakeup_one_sleeper(&mutex->synch_base)) {
+ if (xnsynch_release(&mutex->synch_base)) {
mutex->lockcnt = 1;
xnpod_schedule();
}
Index: b/ksrc/skins/native/task.c
===================================================================
--- a/ksrc/skins/native/task.c
+++ b/ksrc/skins/native/task.c
@@ -269,7 +269,8 @@ int rt_task_create(RT_TASK *task,
#ifdef CONFIG_XENO_OPT_NATIVE_MPS
xnsynch_init(&task->mrecv, XNSYNCH_FIFO);
- xnsynch_init(&task->msendq, XNSYNCH_PRIO | XNSYNCH_PIP);
+ xnsynch_init(&task->msendq,
+ XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER);
xnsynch_set_owner(&task->msendq, &task->thread_base);
task->flowgen = 0;
#endif /* CONFIG_XENO_OPT_NATIVE_MPS */
@@ -1773,7 +1774,7 @@ ssize_t rt_task_send(RT_TASK *task,
client in the case required by the priority inheritance
protocol (i.e. prio(client) > prio(server)). */
- xnsynch_sleep_on(&task->msendq, timeout, XN_RELATIVE);
+ xnsynch_acquire(&task->msendq, timeout, XN_RELATIVE);
/* At this point, the server task might have exited right
* after having replied to us, so do not make optimistic
Index: b/ksrc/skins/posix/cond.c
===================================================================
--- a/ksrc/skins/posix/cond.c
+++ b/ksrc/skins/posix/cond.c
@@ -240,7 +240,7 @@ static inline int mutex_save_count(xnthr
xnthread_handle(cur)))
return 0;
- owner = xnsynch_wakeup_one_sleeper(&mutex->synchbase);
+ owner = xnsynch_release(&mutex->synchbase);
xnarch_atomic_set(mutex->owner,
set_claimed(xnthread_handle(owner),
xnsynch_nsleepers(&mutex->synchbase)));
Index: b/ksrc/skins/posix/mutex.c
===================================================================
--- a/ksrc/skins/posix/mutex.c
+++ b/ksrc/skins/posix/mutex.c
@@ -85,7 +85,7 @@ int pse51_mutex_init_internal(struct __s
xnarch_atomic_t *ownerp,
const pthread_mutexattr_t *attr)
{
- xnflags_t synch_flags = XNSYNCH_PRIO | XNSYNCH_NOPIP;
+ xnflags_t synch_flags = XNSYNCH_PRIO | XNSYNCH_OWNER;
struct xnsys_ppd *sys_ppd;
pse51_kqueues_t *kq;
spl_t s;
@@ -307,11 +307,11 @@ int pse51_mutex_timedlock_break(struct _
for (;;) {
++mutex->sleepers;
if (timed)
- xnsynch_sleep_on(&mutex->synchbase,
- abs_to, XN_REALTIME);
+ xnsynch_acquire(&mutex->synchbase,
+ abs_to, XN_REALTIME);
else
- xnsynch_sleep_on(&mutex->synchbase,
- XN_INFINITE, XN_RELATIVE);
+ xnsynch_acquire(&mutex->synchbase,
+ XN_INFINITE, XN_RELATIVE);
--mutex->sleepers;
if (xnthread_test_info(cur, XNBREAK)) {
Index: b/ksrc/skins/posix/mutex.h
===================================================================
--- a/ksrc/skins/posix/mutex.h
+++ b/ksrc/skins/posix/mutex.h
@@ -170,9 +170,9 @@ static inline int pse51_mutex_timedlock_
xnsynch_set_owner(&mutex->synchbase, owner);
++mutex->sleepers;
if (timed)
- xnsynch_sleep_on(&mutex->synchbase, abs_to, XN_REALTIME);
+ xnsynch_acquire(&mutex->synchbase, abs_to, XN_REALTIME);
else
- xnsynch_sleep_on(&mutex->synchbase, XN_INFINITE, XN_RELATIVE);
+ xnsynch_acquire(&mutex->synchbase, XN_INFINITE, XN_RELATIVE);
--mutex->sleepers;
if (xnthread_test_info(cur, XNBREAK)) {
@@ -216,7 +216,7 @@ static inline void pse51_mutex_unlock_in
return;
xnlock_get_irqsave(&nklock, s);
- owner = xnsynch_wakeup_one_sleeper(&mutex->synchbase);
+ owner = xnsynch_release(&mutex->synchbase);
ownerh = set_claimed(xnthread_handle(owner), mutex->sleepers);
xnarch_atomic_set(mutex->owner, ownerh);
if (owner)
Index: b/ksrc/skins/rtai/sem.c
===================================================================
--- a/ksrc/skins/rtai/sem.c
+++ b/ksrc/skins/rtai/sem.c
@@ -28,7 +28,7 @@ void rt_typed_sem_init(SEM * sem, int va
int mode = XNSYNCH_PRIO;
if ((type & RES_SEM) == RES_SEM) {
- mode |= XNSYNCH_PIP;
+ mode |= XNSYNCH_PIP | XNSYNCH_OWNER;
value = 0; /* We will use this as a lock count. */
} else {
if ((type & BIN_SEM) && value > 1)
@@ -98,7 +98,7 @@ int rt_sem_signal(SEM * sem)
goto unlock_and_exit;
sem->owner =
- thread2rtask(xnsynch_wakeup_one_sleeper(&sem->synch_base));
+ thread2rtask(xnsynch_release(&sem->synch_base));
if (sem->owner != NULL)
xnpod_schedule();
@@ -141,12 +141,12 @@ int rt_sem_wait(SEM * sem)
err = ++sem->count;
goto unlock_and_exit;
}
+ xnsynch_acquire(&sem->synch_base, XN_INFINITE, XN_RELATIVE);
} else if (sem->count > 0) {
err = sem->count--;
goto unlock_and_exit;
- }
-
- xnsynch_sleep_on(&sem->synch_base, XN_INFINITE, XN_RELATIVE);
+ } else
+ xnsynch_sleep_on(&sem->synch_base, XN_INFINITE, XN_RELATIVE);
if (xnthread_test_info(&task->thread_base, XNRMID))
err = SEM_ERR; /* Semaphore deleted while pending. */
Index: b/ksrc/skins/rtdm/drvlib.c
===================================================================
--- a/ksrc/skins/rtdm/drvlib.c
+++ b/ksrc/skins/rtdm/drvlib.c
@@ -1390,7 +1390,8 @@ void rtdm_mutex_init(rtdm_mutex_t *mutex
/* Make atomic for re-initialisation support */
xnlock_get_irqsave(&nklock, s);
- xnsynch_init(&mutex->synch_base, XNSYNCH_PRIO | XNSYNCH_PIP);
+ xnsynch_init(&mutex->synch_base,
+ XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER);
xnlock_put_irqrestore(&nklock, s);
}
@@ -1534,14 +1535,14 @@ int rtdm_mutex_timedlock(rtdm_mutex_t *m
restart:
if (timeout_seq && (timeout > 0)) {
/* timeout sequence */
- xnsynch_sleep_on(&mutex->synch_base, *timeout_seq,
- XN_ABSOLUTE);
+ xnsynch_acquire(&mutex->synch_base, *timeout_seq,
+ XN_ABSOLUTE);
} else {
/* infinite or relative timeout */
- xnsynch_sleep_on(&mutex->synch_base,
- xntbase_ns2ticks_ceil
- (xnthread_time_base(curr_thread),
- timeout), XN_RELATIVE);
+ xnsynch_acquire(&mutex->synch_base,
+ xntbase_ns2ticks_ceil
+ (xnthread_time_base(curr_thread),
+ timeout), XN_RELATIVE);
}
if (unlikely(xnthread_test_info(curr_thread,
Index: b/ksrc/skins/vrtx/mx.c
===================================================================
--- a/ksrc/skins/vrtx/mx.c
+++ b/ksrc/skins/vrtx/mx.c
@@ -161,7 +161,7 @@ int sc_mcreate(unsigned int opt, int *er
inith(&mx->link);
mx->mid = mid;
mx->owner = NULL;
- xnsynch_init(&mx->synchbase, bflags | XNSYNCH_DREORD);
+ xnsynch_init(&mx->synchbase, bflags | XNSYNCH_DREORD | XNSYNCH_OWNER);
xnlock_get_irqsave(&nklock, s);
appendq(&vrtx_mx_q, &mx->link);
@@ -192,7 +192,7 @@ void sc_mpost(int mid, int *errp)
}
/* Undefined behaviour if the poster does not own the mutex. */
- mx->owner = xnsynch_wakeup_one_sleeper(&mx->synchbase);
+ mx->owner = xnsynch_release(&mx->synchbase);
*errp = RET_OK;
@@ -267,7 +267,7 @@ void sc_mpend(int mid, unsigned long tim
if (timeout)
task->vrtxtcb.TCBSTAT |= TBSDELAY;
- xnsynch_sleep_on(&mx->synchbase, timeout, XN_RELATIVE);
+ xnsynch_acquire(&mx->synchbase, timeout, XN_RELATIVE);
if (xnthread_test_info(&task->threadbase, XNBREAK))
*errp = -EINTR;
Index: b/ksrc/skins/vxworks/semLib.c
===================================================================
--- a/ksrc/skins/vxworks/semLib.c
+++ b/ksrc/skins/vxworks/semLib.c
@@ -138,7 +138,7 @@ SEM_ID semCCreate(int flags, int count)
SEM_ID semMCreate(int flags)
{
- int bflags = 0;
+ int bflags = XNSYNCH_OWNER;
error_check(flags & ~WIND_SEMM_OPTION_MASK, S_semLib_INVALID_QUEUE_TYPE,
return 0);
@@ -346,7 +346,7 @@ static STATUS semm_take(wind_sem_t *sem,
error_check(to == XN_NONBLOCK, S_objLib_OBJ_UNAVAILABLE,
return ERROR);
- xnsynch_sleep_on(&sem->synchbase, to, XN_RELATIVE);
+ xnsynch_acquire(&sem->synchbase, to, XN_RELATIVE);
error_check(xnthread_test_info(cur, XNBREAK),
-EINTR, return ERROR);
@@ -385,7 +385,7 @@ static STATUS semm_give(wind_sem_t *sem)
if (--sem->count > 0)
return OK;
- if (xnsynch_wakeup_one_sleeper(&sem->synchbase)) {
+ if (xnsynch_release(&sem->synchbase)) {
sem->count = 1;
resched = 1;
}
^ permalink raw reply [flat|nested] 17+ messages in thread* [Xenomai-core] [PATCH 06/13] Refactor mutex lockcnt tracking
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (4 preceding siblings ...)
2008-10-17 15:46 ` [Xenomai-core] [PATCH 05/13] Factor out xnsynch_acquire/release Jan Kiszka
@ 2008-10-17 15:46 ` Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 07/13] Lockless fast path for xnsynch_acquire/release Jan Kiszka
` (9 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:46 UTC (permalink / raw)
To: xenomai; +Cc: Jan Kiszka
This patch establishes the policy that only the current owner of a mutex
shall modify its lockcnt value (the POSIX skin works like that, too).
So far, needless updates took place when the previous owner just woke up
the new one. Moreover, the only spot that assumed lockcnt > 0 <=> mutex
assigned is changed to use xnsynch_owner instead.
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
ksrc/skins/native/cond.c | 6 ++----
ksrc/skins/native/mutex.c | 8 ++------
2 files changed, 4 insertions(+), 10 deletions(-)
Index: b/ksrc/skins/native/cond.c
===================================================================
--- a/ksrc/skins/native/cond.c
+++ b/ksrc/skins/native/cond.c
@@ -421,10 +421,8 @@ int rt_cond_wait_inner(RT_COND *cond, RT
mutex->lockcnt = 0;
- if (xnsynch_release(&mutex->synch_base)) {
- mutex->lockcnt = 1;
- /* Scheduling deferred */
- }
+ xnsynch_release(&mutex->synch_base);
+ /* Scheduling deferred */
xnsynch_sleep_on(&cond->synch_base, timeout, timeout_mode);
Index: b/ksrc/skins/native/mutex.c
===================================================================
--- a/ksrc/skins/native/mutex.c
+++ b/ksrc/skins/native/mutex.c
@@ -320,8 +320,6 @@ int rt_mutex_acquire_inner(RT_MUTEX *mut
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;
}
@@ -524,10 +522,8 @@ int rt_mutex_release(RT_MUTEX *mutex)
if (--mutex->lockcnt > 0)
goto unlock_and_exit;
- if (xnsynch_release(&mutex->synch_base)) {
- mutex->lockcnt = 1;
+ if (xnsynch_release(&mutex->synch_base))
xnpod_schedule();
- }
unlock_and_exit:
@@ -584,7 +580,7 @@ int rt_mutex_inquire(RT_MUTEX *mutex, RT
strcpy(info->name, mutex->name);
info->lockcnt = mutex->lockcnt;
info->nwaiters = xnsynch_nsleepers(&mutex->synch_base);
- if (mutex->lockcnt)
+ if (xnsynch_owner(&mutex->synch_base))
strcpy(info->owner,
xnthread_name(xnsynch_owner(&mutex->synch_base)));
else
^ permalink raw reply [flat|nested] 17+ messages in thread* [Xenomai-core] [PATCH 07/13] Lockless fast path for xnsynch_acquire/release
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (5 preceding siblings ...)
2008-10-17 15:46 ` [Xenomai-core] [PATCH 06/13] Refactor mutex lockcnt tracking Jan Kiszka
@ 2008-10-17 15:46 ` Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 08/13] Convert POSIX skin to fast xnsynch Jan Kiszka
` (8 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:46 UTC (permalink / raw)
To: xenomai; +Cc: Jan Kiszka
This patch adds optional lockless fast paths to xnsynch_acquire and
xnsynch_release. Those paths are considered if CONFIG_XENO_FASTSYNC
is defined and the owner-tracking xnsynch object is given a non-NULL
reference to an atomic fastlock variable on initialization. This allows
for a smooth migration of existing mutex implementations in Xenomai
skins to a fast xnsynch scheme.
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
configure.in | 16 ++--
include/asm-generic/bits/bind.h | 16 ++--
include/asm-generic/features.h | 24 +++---
include/nucleus/synch.h | 58 ++++++++++++++++
ksrc/arch/arm/Kconfig | 2
ksrc/arch/powerpc/Kconfig | 2
ksrc/arch/x86/Kconfig | 2
ksrc/drivers/testing/switchtest.c | 2
ksrc/nucleus/pipe.c | 2
ksrc/nucleus/registry.c | 4 -
ksrc/nucleus/select.c | 2
ksrc/nucleus/synch.c | 132 ++++++++++++++++++++++++++++++++------
ksrc/skins/native/Kconfig | 2
ksrc/skins/native/alarm.c | 2
ksrc/skins/native/buffer.c | 4 -
ksrc/skins/native/cond.c | 2
ksrc/skins/native/event.c | 2
ksrc/skins/native/heap.c | 2
ksrc/skins/native/intr.c | 2
ksrc/skins/native/mutex.c | 2
ksrc/skins/native/queue.c | 2
ksrc/skins/native/sem.c | 2
ksrc/skins/native/task.c | 6 -
ksrc/skins/posix/Kconfig | 2
ksrc/skins/posix/cb_lock.h | 6 -
ksrc/skins/posix/cond.c | 18 ++---
ksrc/skins/posix/intr.c | 2
ksrc/skins/posix/mq.c | 4 -
ksrc/skins/posix/mutex.c | 12 +--
ksrc/skins/posix/mutex.h | 4 -
ksrc/skins/posix/sem.c | 2
ksrc/skins/posix/syscall.c | 20 ++---
ksrc/skins/posix/thread.c | 6 -
ksrc/skins/psos+/Kconfig | 2
ksrc/skins/psos+/event.c | 2
ksrc/skins/psos+/queue.c | 2
ksrc/skins/psos+/rn.c | 2
ksrc/skins/psos+/sem.c | 2
ksrc/skins/rtai/Kconfig | 2
ksrc/skins/rtai/sem.c | 2
ksrc/skins/rtai/task.c | 4 -
ksrc/skins/rtdm/drvlib.c | 10 +-
ksrc/skins/uitron/Kconfig | 2
ksrc/skins/uitron/flag.c | 2
ksrc/skins/uitron/mbx.c | 3
ksrc/skins/uitron/sem.c | 3
ksrc/skins/uitron/task.c | 4 -
ksrc/skins/vrtx/Kconfig | 2
ksrc/skins/vrtx/event.c | 2
ksrc/skins/vrtx/mb.c | 2
ksrc/skins/vrtx/mx.c | 3
ksrc/skins/vrtx/queue.c | 2
ksrc/skins/vrtx/sem.c | 2
ksrc/skins/vxworks/Kconfig | 2
ksrc/skins/vxworks/module.c | 2
ksrc/skins/vxworks/msgQLib.c | 2
ksrc/skins/vxworks/semLib.c | 2
ksrc/skins/vxworks/syscall.c | 2
ksrc/skins/vxworks/taskLib.c | 2
src/skins/posix/mutex.c | 42 ++++++------
60 files changed, 313 insertions(+), 162 deletions(-)
Index: b/configure.in
===================================================================
--- a/configure.in
+++ b/configure.in
@@ -59,27 +59,27 @@ AM_PROG_LEX
AC_MSG_CHECKING([for target architecture])
-CONFIG_XENO_FASTSEM=
+CONFIG_XENO_FASTSYNCH=
case "$host" in
i*86*-*)
XENO_TARGET_ARCH=x86
XENO_LINUX_ARCH=i386
XENO_LINUX_INSTALL_TARGET=install
- CONFIG_XENO_FASTSEM=y
+ CONFIG_XENO_FASTSYNCH=y
;;
powerpc-*|ppc-*)
XENO_TARGET_ARCH=powerpc
XENO_LINUX_ARCH=ppc
XENO_LINUX_INSTALL_TARGET=install_image
XENO_LINUX_IMAGE=arch/ppc/boot/images/zImage.elf
- CONFIG_XENO_FASTSEM=y
+ CONFIG_XENO_FASTSYNCH=y
;;
powerpc64-*|ppc64-*)
XENO_TARGET_ARCH=powerpc
XENO_LINUX_ARCH=ppc64
XENO_LINUX_INSTALL_TARGET=install_image
XENO_LINUX_IMAGE=arch/ppc64/boot/images/zImage
- CONFIG_XENO_FASTSEM=y
+ CONFIG_XENO_FASTSYNCH=y
;;
ia64-*)
XENO_TARGET_ARCH=ia64
@@ -96,14 +96,14 @@ case "$host" in
XENO_LINUX_ARCH=arm
XENO_LINUX_INSTALL_TARGET=install_image
XENO_LINUX_IMAGE=arch/arm/boot/zImage
- # We set CONFIG_XENO_FASTSEM later, when we know what architecture we
+ # We set CONFIG_XENO_FASTSYNCH later, when we know what architecture we
# are running
;;
x86_64-*|amd64-*)
XENO_TARGET_ARCH=x86
XENO_LINUX_ARCH=x86_64
XENO_LINUX_INSTALL_TARGET=install
- CONFIG_XENO_FASTSEM=y
+ CONFIG_XENO_FASTSYNCH=y
;;
*) echo ""
echo "*******************************************"
@@ -288,7 +288,7 @@ user-space]),
AC_MSG_RESULT(${CONFIG_XENO_ARM_EABI:-no})
if test $CONFIG_XENO_ARM_ARCH -ge 6 || test x$CONFIG_SMP != xy; then
- CONFIG_XENO_FASTSEM=y
+ CONFIG_XENO_FASTSYNCH=y
fi
fi
@@ -570,7 +570,7 @@ dnl
test x$CONFIG_XENO_X86_SEP = xy && AC_DEFINE(CONFIG_XENO_X86_SEP,1,[config])
test x$CONFIG_SMP = xy && AC_DEFINE(CONFIG_SMP,1,[config])
-test x$CONFIG_XENO_FASTSEM = xy && AC_DEFINE(CONFIG_XENO_FASTSEM,1,[config])
+test x$CONFIG_XENO_FASTSYNCH = xy && AC_DEFINE(CONFIG_XENO_FASTSYNCH,1,[config])
test x$CONFIG_X86_TSC = xy && AC_DEFINE(CONFIG_X86_TSC,1,[config])
test -n "$CONFIG_XENO_ARM_ARCH" && AC_DEFINE_UNQUOTED(CONFIG_XENO_ARM_ARCH,$CONFIG_XENO_ARM_ARCH,[config])
Index: b/include/asm-generic/bits/bind.h
===================================================================
--- a/include/asm-generic/bits/bind.h
+++ b/include/asm-generic/bits/bind.h
@@ -42,14 +42,14 @@ void init_current_key(void)
}
}
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
__attribute__ ((weak))
unsigned long xeno_sem_heap[2] = { 0, 0 };
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
void xeno_handle_mlock_alert(int sig);
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
static void *map_sem_heap(unsigned shared)
{
struct heap_info {
@@ -103,7 +103,7 @@ static void unmap_sem_heap(unsigned long
munmap((void *) heap_addr, hinfo.size);
}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
void __attribute__((weak)) xeno_sigill_handler(int sig)
{
@@ -174,7 +174,7 @@ xeno_bind_skin(unsigned skin_magic, cons
sa.sa_flags = 0;
sigaction(SIGXCPU, &sa, NULL);
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
/* In case we forked, we need to map the new local semaphore heap */
if (xeno_sem_heap[0])
unmap_sem_heap(xeno_sem_heap[0], 0);
@@ -193,7 +193,7 @@ xeno_bind_skin(unsigned skin_magic, cons
exit(EXIT_FAILURE);
}
}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
return muxid;
}
@@ -248,7 +248,7 @@ xeno_bind_skin_opt(unsigned skin_magic,
xeno_arch_features_check();
#endif /* xeno_arch_features_check */
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
/* In case we forked, we need to map the new local semaphore heap */
if (xeno_sem_heap[0])
unmap_sem_heap(xeno_sem_heap[0], 0);
@@ -267,7 +267,7 @@ xeno_bind_skin_opt(unsigned skin_magic,
exit(EXIT_FAILURE);
}
}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
return muxid;
}
Index: b/include/asm-generic/features.h
===================================================================
--- a/include/asm-generic/features.h
+++ b/include/asm-generic/features.h
@@ -25,9 +25,9 @@
#include <xeno_config.h>
#endif /* __KERNEL__ */
-#define __xn_feat_smp 0x80000000
-#define __xn_feat_fastsem 0x40000000
-#define __xn_feat_nofastsem 0x20000000
+#define __xn_feat_smp 0x80000000
+#define __xn_feat_fastsynch 0x40000000
+#define __xn_feat_nofastsynch 0x20000000
#ifdef CONFIG_SMP
#define __xn_feat_smp_mask __xn_feat_smp
@@ -35,25 +35,25 @@
#define __xn_feat_smp_mask 0
#endif
-#ifdef CONFIG_XENO_FASTSEM
-#define __xn_feat_fastsem_mask __xn_feat_fastsem
+#ifdef CONFIG_XENO_FASTSYNCH
+#define __xn_feat_fastsynch_mask __xn_feat_fastsynch
#else
-#define __xn_feat_fastsem_mask __xn_feat_nofastsem
+#define __xn_feat_fastsynch_mask __xn_feat_nofastsynch
#endif
-#define __xn_feat_generic_mask (__xn_feat_smp_mask | __xn_feat_fastsem_mask)
+#define __xn_feat_generic_mask (__xn_feat_smp_mask | __xn_feat_fastsynch_mask)
-#define __xn_feat_generic_man_mask (__xn_feat_fastsem | __xn_feat_nofastsem)
+#define __xn_feat_generic_man_mask (__xn_feat_fastsynch | __xn_feat_nofastsynch)
static inline const char *get_generic_feature_label (unsigned feature)
{
switch (feature) {
case __xn_feat_smp:
return "smp";
- case __xn_feat_fastsem:
- return "fastsem";
- case __xn_feat_nofastsem:
- return "nofastsem";
+ case __xn_feat_fastsynch:
+ return "fastsynch";
+ case __xn_feat_nofastsynch:
+ return "nofastsynch";
default:
return 0;
}
Index: b/include/nucleus/synch.h
===================================================================
--- a/include/nucleus/synch.h
+++ b/include/nucleus/synch.h
@@ -32,10 +32,42 @@
#define XNSYNCH_DREORD 0x4
#define XNSYNCH_OWNER 0x8
+/* Fast lock API */
+static inline int xnsynch_fast_owner_check(xnarch_atomic_t *fastlock,
+ xnhandle_t ownerh)
+{
+ return (xnhandle_mask_spare(xnarch_atomic_get(fastlock)) == ownerh) ?
+ 0 : -EPERM;
+}
+
+static inline int xnsynch_fast_acquire(xnarch_atomic_t *fastlock,
+ xnhandle_t new_ownerh)
+{
+ xnhandle_t lock_state =
+ xnarch_atomic_cmpxchg(fastlock, XN_NO_HANDLE, new_ownerh);
+
+ if (likely(lock_state == XN_NO_HANDLE))
+ return 0;
+
+ if (xnhandle_mask_spare(lock_state) == new_ownerh)
+ return -EBUSY;
+
+ return -EAGAIN;
+}
+
+static inline int xnsynch_fast_release(xnarch_atomic_t *fastlock,
+ xnhandle_t cur_ownerh)
+{
+ return (xnarch_atomic_cmpxchg(fastlock, cur_ownerh, XN_NO_HANDLE) ==
+ cur_ownerh);
+}
+
#if defined(__KERNEL__) || defined(__XENO_SIM__)
#define XNSYNCH_CLAIMED 0x10 /* Claimed by other thread(s) w/ PIP */
+#define XNSYNCH_FLCLAIM XN_HANDLE_SPARE3 /* Corresponding bit in fast lock */
+
/* Spare flags usable by upper interfaces */
#define XNSYNCH_SPARE0 0x01000000
#define XNSYNCH_SPARE1 0x02000000
@@ -67,6 +99,10 @@ typedef struct xnsynch {
struct xnthread *owner; /* Thread which owns the resource */
+#ifdef CONFIG_XENO_FASTSYNCH
+ xnarch_atomic_t *fastlock; /* Pointer to fast lock word */
+#endif /* CONFIG_XENO_FASTSYNCH */
+
void (*cleanup)(struct xnsynch *synch); /* Cleanup handler */
XNARCH_DECL_DISPLAY_CONTEXT();
@@ -81,12 +117,30 @@ typedef struct xnsynch {
#define xnsynch_pended_p(synch) (!emptypq_p(&((synch)->pendq)))
#define xnsynch_owner(synch) ((synch)->owner)
+#ifdef CONFIG_XENO_FASTSYNCH
+#define xnsynch_fastlock(synch) ((synch)->fastlock)
+#define xnsynch_fastlock_p(synch) ((synch)->fastlock != NULL)
+#define xnsynch_owner_check(synch, thread) \
+ xnsynch_fast_owner_check((synch)->fastlock, xnthread_handle(thread))
+#else /* !CONFIG_XENO_FASTSYNCH */
+#define xnsynch_fastlock(synch) NULL
+#define xnsynch_fastlock_p(synch) 0
+#define xnsynch_owner_check(synch, thread) \
+ ((synch)->owner == thread ? 0 : -EPERM)
+#endif /* !CONFIG_XENO_FASTSYNCH */
+
+#define xnsynch_fast_is_claimed(fastlock) \
+ xnhandle_test_spare(fastlock, XNSYNCH_FLCLAIM)
+#define xnsynch_fast_set_claimed(fastlock, enable) \
+ (((fastlock) & ~XNSYNCH_FLCLAIM) | ((enable) ? XNSYNCH_FLCLAIM : 0))
+#define xnsynch_fast_mask_claimed(fastlock) ((fastlock) & ~XNSYNCH_FLCLAIM)
+
#ifdef __cplusplus
extern "C" {
#endif
-void xnsynch_init(xnsynch_t *synch,
- xnflags_t flags);
+void xnsynch_init(xnsynch_t *synch, xnflags_t flags,
+ xnarch_atomic_t *fastlock);
#define xnsynch_destroy(synch) xnsynch_flush(synch,XNRMID)
Index: b/ksrc/arch/arm/Kconfig
===================================================================
--- a/ksrc/arch/arm/Kconfig
+++ b/ksrc/arch/arm/Kconfig
@@ -2,7 +2,7 @@ config XENO_GENERIC_STACKPOOL
bool
default y
-config XENO_FASTSEM
+config XENO_FASTSYNCH
bool
default y if (CPU_32v3 || CPU_32v4T || CPU_32v5) && !SMP || CPU_32v6 || CPU_32v7
Index: b/ksrc/arch/powerpc/Kconfig
===================================================================
--- a/ksrc/arch/powerpc/Kconfig
+++ b/ksrc/arch/powerpc/Kconfig
@@ -2,7 +2,7 @@ config XENO_GENERIC_STACKPOOL
bool
default y
-config XENO_FASTSEM
+config XENO_FASTSYNCH
bool
default y
Index: b/ksrc/arch/x86/Kconfig
===================================================================
--- a/ksrc/arch/x86/Kconfig
+++ b/ksrc/arch/x86/Kconfig
@@ -2,7 +2,7 @@ config XENO_GENERIC_STACKPOOL
bool
default y
-config XENO_FASTSEM
+config XENO_FASTSYNCH
bool
default y
Index: b/ksrc/skins/native/Kconfig
===================================================================
--- a/ksrc/skins/native/Kconfig
+++ b/ksrc/skins/native/Kconfig
@@ -1,6 +1,6 @@
menuconfig XENO_SKIN_NATIVE
depends on XENO_OPT_NUCLEUS
- select XENO_OPT_REGISTRY if XENO_FASTSEM
+ select XENO_OPT_REGISTRY if XENO_FASTSYNCH
tristate "Native API"
default y
help
Index: b/ksrc/skins/posix/Kconfig
===================================================================
--- a/ksrc/skins/posix/Kconfig
+++ b/ksrc/skins/posix/Kconfig
@@ -1,6 +1,6 @@
menuconfig XENO_SKIN_POSIX
depends on XENO_OPT_NUCLEUS
- select XENO_OPT_REGISTRY if XENO_FASTSEM
+ select XENO_OPT_REGISTRY if XENO_FASTSYNCH
tristate "POSIX API"
default y
help
Index: b/ksrc/skins/posix/cb_lock.h
===================================================================
--- a/ksrc/skins/posix/cb_lock.h
+++ b/ksrc/skins/posix/cb_lock.h
@@ -20,7 +20,7 @@ typedef void xnthread_t;
__tmp; \
})
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
static __inline__ int __cb_try_read_lock(xnarch_atomic_t *lock)
{
@@ -68,7 +68,7 @@ static __inline__ void __cb_write_unlock
#define cb_try_write_lock(lock, flags) __cb_try_write_lock(lock)
#define cb_force_write_lock(lock, flags) __cb_force_write_lock(lock)
#define cb_write_unlock(lock, flags) __cb_write_unlock(lock)
-#else /* !CONFIG_XENO_FASTSEM */
+#else /* !CONFIG_XENO_FASTSYNCH */
#ifdef __KERNEL__
#define DECLARE_CB_LOCK_FLAGS(name) spl_t name
#define cb_try_read_lock(lock, flags) \
@@ -87,6 +87,6 @@ static __inline__ void __cb_write_unlock
#define cb_force_write_lock(lock, flags) do { } while (0)
#define cb_write_unlock(lock, flags) do { } while (0)
#endif /* !__KERNEL__ */
-#endif /* !CONFIG_XENO_FASTSEM */
+#endif /* !CONFIG_XENO_FASTSYNCH */
#endif /* CB_LOCK_H */
Index: b/ksrc/skins/posix/cond.c
===================================================================
--- a/ksrc/skins/posix/cond.c
+++ b/ksrc/skins/posix/cond.c
@@ -142,7 +142,7 @@ int pthread_cond_init(pthread_cond_t * c
shadow->magic = PSE51_COND_MAGIC;
shadow->cond = cond;
- xnsynch_init(&cond->synchbase, synch_flags);
+ xnsynch_init(&cond->synchbase, synch_flags, NULL);
inith(&cond->link);
cond->attr = *attr;
cond->mutex = NULL;
@@ -424,10 +424,10 @@ int pthread_cond_wait(pthread_cond_t * c
unsigned count;
int err;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
if (unlikely(cb_try_read_lock(&mutex->lock, s)))
return EINVAL;
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
err = pse51_cond_timedwait_prologue(cur, cond, mutex,
&count, 0, XN_INFINITE);
@@ -437,9 +437,9 @@ int pthread_cond_wait(pthread_cond_t * c
mutex, count))
;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
cb_read_unlock(&mutex->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
return err != EINTR ? err : 0;
}
@@ -492,10 +492,10 @@ int pthread_cond_timedwait(pthread_cond_
unsigned count;
int err;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
if (unlikely(cb_try_read_lock(&mutex->lock, s)))
return EINVAL;
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
err = pse51_cond_timedwait_prologue(cur, cond, mutex, &count, 1,
ts2ticks_ceil(abstime) + 1);
@@ -505,9 +505,9 @@ int pthread_cond_timedwait(pthread_cond_
mutex, count))
;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
cb_read_unlock(&mutex->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
return err != EINTR ? err : 0;
}
Index: b/ksrc/skins/posix/mutex.c
===================================================================
--- a/ksrc/skins/posix/mutex.c
+++ b/ksrc/skins/posix/mutex.c
@@ -103,16 +103,16 @@ int pse51_mutex_init_internal(struct __s
shadow->mutex = mutex;
shadow->lockcnt = 0;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
xnarch_atomic_set(&shadow->lock, -1);
shadow->attr = *attr;
shadow->owner_offset = xnheap_mapped_offset(&sys_ppd->sem_heap, ownerp);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
if (attr->protocol == PTHREAD_PRIO_INHERIT)
synch_flags |= XNSYNCH_PIP;
- xnsynch_init(&mutex->synchbase, synch_flags);
+ xnsynch_init(&mutex->synchbase, synch_flags, NULL);
inith(&mutex->link);
mutex->attr = *attr;
mutex->owner = ownerp;
@@ -169,16 +169,16 @@ int pthread_mutex_init(pthread_mutex_t *
goto checked;
err = pse51_mutex_check_init(shadow, attr);
-#ifndef CONFIG_XENO_FASTSEM
+#ifndef CONFIG_XENO_FASTSYNCH
cb_read_unlock(&shadow->lock, s);
if (err)
return -err;
-#else /* CONFIG_XENO_FASTSEM */
+#else /* CONFIG_XENO_FASTSYNCH */
if (err) {
cb_read_unlock(&shadow->lock, s);
return -err;
}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
checked:
mutex = (pse51_mutex_t *) xnmalloc(sizeof(*mutex));
Index: b/ksrc/skins/posix/mutex.h
===================================================================
--- a/ksrc/skins/posix/mutex.h
+++ b/ksrc/skins/posix/mutex.h
@@ -30,14 +30,14 @@ union __xeno_mutex {
unsigned magic;
unsigned lockcnt;
struct pse51_mutex *mutex;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
xnarch_atomic_t lock;
union {
unsigned owner_offset;
xnarch_atomic_t *owner;
};
struct pse51_mutexattr attr;
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
} shadow_mutex;
};
Index: b/ksrc/skins/posix/syscall.c
===================================================================
--- a/ksrc/skins/posix/syscall.c
+++ b/ksrc/skins/posix/syscall.c
@@ -886,7 +886,7 @@ static int __pthread_mutexattr_setpshare
return __xn_safe_copy_to_user((void __user *)uattrp, &attr, sizeof(*uattrp));
}
-#ifndef CONFIG_XENO_FASTSEM
+#ifndef CONFIG_XENO_FASTSYNCH
static int __pthread_mutex_init(struct pt_regs *regs)
{
pthread_mutexattr_t locattr, *attr, *uattrp;
@@ -1088,7 +1088,7 @@ static int __pthread_mutex_unlock(struct
return err;
}
-#else /* !CONFIG_XENO_FASTSEM */
+#else /* !CONFIG_XENO_FASTSYNCH */
static int __pthread_mutex_check_init(struct pt_regs *regs)
{
pthread_mutexattr_t locattr, *attr, *uattrp;
@@ -1279,7 +1279,7 @@ static int __pthread_mutex_unlock(struct
return 0;
}
-#endif /* !CONFIG_XENO_FASTSEM */
+#endif /* !CONFIG_XENO_FASTSYNCH */
static int __pthread_condattr_init(struct pt_regs *regs)
{
@@ -1469,11 +1469,11 @@ static int __pthread_cond_wait_prologue(
if (__xn_safe_copy_from_user(&mx.shadow_mutex,
(void __user *)&umx->shadow_mutex,
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
offsetof(struct __shadow_mutex, lock)
-#else /* !CONFIG_XENO_FASTSEM */
+#else /* !CONFIG_XENO_FASTSYNCH */
sizeof(mx.shadow_mutex)
-#endif /* !CONFIG_XENO_FASTSEM */
+#endif /* !CONFIG_XENO_FASTSYNCH */
))
return -EFAULT;
@@ -1537,11 +1537,11 @@ static int __pthread_cond_wait_epilogue(
if (__xn_safe_copy_from_user(&mx.shadow_mutex,
(void __user *)&umx->shadow_mutex,
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
offsetof(struct __shadow_mutex, lock)
-#else /* !CONFIG_XENO_FASTSEM */
+#else /* !CONFIG_XENO_FASTSYNCH */
sizeof(mx.shadow_mutex)
-#endif /* !CONFIG_XENO_FASTSEM */
+#endif /* !CONFIG_XENO_FASTSYNCH */
))
return -EFAULT;
@@ -2695,7 +2695,7 @@ static xnsysent_t __systab[] = {
[__pse51_mutex_lock] = {&__pthread_mutex_lock, __xn_exec_primary},
[__pse51_mutex_timedlock] =
{&__pthread_mutex_timedlock, __xn_exec_primary},
-#ifndef CONFIG_XENO_FASTSEM
+#ifndef CONFIG_XENO_FASTSYNCH
[__pse51_mutex_trylock] = {&__pthread_mutex_trylock, __xn_exec_primary},
#else
[__pse51_check_init] = {&__pthread_mutex_check_init, __xn_exec_any},
Index: b/ksrc/skins/posix/thread.c
===================================================================
--- a/ksrc/skins/posix/thread.c
+++ b/ksrc/skins/posix/thread.c
@@ -209,7 +209,7 @@ int pthread_create(pthread_t *tid,
thread->magic = PSE51_THREAD_MAGIC;
thread->entry = start;
thread->arg = arg;
- xnsynch_init(&thread->join_synch, XNSYNCH_PRIO);
+ xnsynch_init(&thread->join_synch, XNSYNCH_PRIO, NULL);
thread->nrt_joiners = 0;
pse51_cancel_init_thread(thread);
@@ -234,7 +234,7 @@ int pthread_create(pthread_t *tid,
thread->hkey.mm = NULL;
#endif /* CONFIG_XENO_OPT_PERVASIVE */
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
/* We need an anonymous registry entry to obtain a handle for fast
mutex locking. */
{
@@ -244,7 +244,7 @@ int pthread_create(pthread_t *tid,
return err;
}
}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
*tid = thread; /* Must be done before the thread is started. */
Index: b/ksrc/skins/psos+/Kconfig
===================================================================
--- a/ksrc/skins/psos+/Kconfig
+++ b/ksrc/skins/psos+/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_PSOS
depends on XENO_OPT_NUCLEUS
select XENO_OPT_TIMING_PERIODIC
tristate "pSOS+ emulator"
- select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSEM
+ select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSYNCH
help
This API skin emulates WindRiver's pSOS+ operating system.
Index: b/ksrc/skins/rtai/Kconfig
===================================================================
--- a/ksrc/skins/rtai/Kconfig
+++ b/ksrc/skins/rtai/Kconfig
@@ -1,6 +1,6 @@
menuconfig XENO_SKIN_RTAI
depends on XENO_OPT_NUCLEUS
- select XENO_OPT_REGISTRY if XENO_FASTSEM
+ select XENO_OPT_REGISTRY if XENO_FASTSYNCH
tristate "RTAI emulator"
help
Index: b/ksrc/skins/rtai/task.c
===================================================================
--- a/ksrc/skins/rtai/task.c
+++ b/ksrc/skins/rtai/task.c
@@ -152,7 +152,7 @@ int rt_task_init(RT_TASK *task,
task->magic = RTAI_TASK_MAGIC;
appendq(&__rtai_task_q, &task->link);
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
/* We need an anonymous registry entry to obtain a handle for fast
mutex locking. */
err = xnthread_register(&task->thread_base, "");
@@ -160,7 +160,7 @@ int rt_task_init(RT_TASK *task,
xnpod_abort_thread(&task->thread_base);
goto unlock_and_exit;
}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
/* Add a switch hook only if a signal function has been declared
at least once for some created task. */
Index: b/ksrc/skins/uitron/Kconfig
===================================================================
--- a/ksrc/skins/uitron/Kconfig
+++ b/ksrc/skins/uitron/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_UITRON
depends on XENO_OPT_NUCLEUS
select XENO_OPT_TIMING_PERIODIC
select XENO_OPT_MAP
- select XENO_OPT_REGISTRY if XENO_FASTSEM
+ select XENO_OPT_REGISTRY if XENO_FASTSYNCH
tristate "uITRON API"
help
Index: b/ksrc/skins/uitron/task.c
===================================================================
--- a/ksrc/skins/uitron/task.c
+++ b/ksrc/skins/uitron/task.c
@@ -150,7 +150,7 @@ ER cre_tsk(ID tskid, T_CTSK *pk_ctsk)
xnlock_put_irqrestore(&nklock, s);
task->magic = uITRON_TASK_MAGIC;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
/* We need an anonymous registry entry to obtain a handle for fast
mutex locking. */
if (xnthread_register(&task->threadbase, "")) {
@@ -158,7 +158,7 @@ ER cre_tsk(ID tskid, T_CTSK *pk_ctsk)
xnpod_abort_thread(&task->threadbase);
return E_NOMEM;
}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
return E_OK;
}
Index: b/ksrc/skins/vrtx/Kconfig
===================================================================
--- a/ksrc/skins/vrtx/Kconfig
+++ b/ksrc/skins/vrtx/Kconfig
@@ -3,7 +3,7 @@ menuconfig XENO_SKIN_VRTX
select XENO_OPT_TIMING_PERIODIC
select XENO_OPT_MAP
tristate "VRTX emulator"
- select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || CONFIG_XENO_FASTSEM
+ select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || CONFIG_XENO_FASTSYNCH
help
This API skin emulates Mentor Graphics's VRTX operating
Index: b/ksrc/skins/vxworks/Kconfig
===================================================================
--- a/ksrc/skins/vxworks/Kconfig
+++ b/ksrc/skins/vxworks/Kconfig
@@ -2,7 +2,7 @@ menuconfig XENO_SKIN_VXWORKS
depends on XENO_OPT_NUCLEUS
select XENO_OPT_TIMING_PERIODIC
tristate "VxWorks emulator"
- select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSEM
+ select XENO_OPT_REGISTRY if XENO_OPT_PERVASIVE || XENO_FASTSYNCH
help
This API skin emulates WindRiver's VxWorks operating system.
Index: b/src/skins/posix/mutex.c
===================================================================
--- a/src/skins/posix/mutex.c
+++ b/src/skins/posix/mutex.c
@@ -26,7 +26,7 @@
extern int __pse51_muxid;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
#define PSE51_MUTEX_MAGIC (0x86860303)
extern unsigned long xeno_sem_heap[2];
@@ -38,7 +38,7 @@ static xnarch_atomic_t *get_ownerp(struc
return (xnarch_atomic_t *) (xeno_sem_heap[1] + shadow->owner_offset);
}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
int __wrap_pthread_mutexattr_init(pthread_mutexattr_t *attr)
{
@@ -98,7 +98,7 @@ int __wrap_pthread_mutex_init(pthread_mu
struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
int err;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
if (unlikely(cb_try_read_lock(&shadow->lock, s)))
goto checked;
@@ -111,17 +111,17 @@ int __wrap_pthread_mutex_init(pthread_mu
checked:
cb_force_write_lock(&shadow->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
err = -XENOMAI_SKINCALL2(__pse51_muxid,__pse51_mutex_init,shadow,attr);
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
if (!shadow->attr.pshared)
shadow->owner = (xnarch_atomic_t *)
(xeno_sem_heap[0] + shadow->owner_offset);
cb_write_unlock(&shadow->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
return err;
}
@@ -148,7 +148,7 @@ int __wrap_pthread_mutex_lock(pthread_mu
struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
int err = 0;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
xnhandle_t cur, owner;
cur = xeno_get_current();
@@ -188,16 +188,16 @@ int __wrap_pthread_mutex_lock(pthread_mu
++shadow->lockcnt;
goto out;
}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
do {
err = XENOMAI_SKINCALL1(__pse51_muxid,__pse51_mutex_lock,shadow);
} while (err == -EINTR);
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
out:
cb_read_unlock(&shadow->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
return -err;
}
@@ -209,7 +209,7 @@ int __wrap_pthread_mutex_timedlock(pthre
struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
int err = 0;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
xnhandle_t cur, owner;
cur = xeno_get_current();
@@ -249,17 +249,17 @@ int __wrap_pthread_mutex_timedlock(pthre
++shadow->lockcnt;
goto out;
}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
do {
err = XENOMAI_SKINCALL2(__pse51_muxid,
__pse51_mutex_timedlock, shadow, to);
} while (err == -EINTR);
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
out:
cb_read_unlock(&shadow->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
return -err;
}
@@ -270,7 +270,7 @@ int __wrap_pthread_mutex_trylock(pthread
struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
int err = 0;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
xnhandle_t cur, owner;
cur = xeno_get_current();
@@ -306,14 +306,14 @@ int __wrap_pthread_mutex_trylock(pthread
out:
cb_read_unlock(&shadow->lock, s);
-#else /* !CONFIG_XENO_FASTSEM */
+#else /* !CONFIG_XENO_FASTSYNCH */
do {
err = XENOMAI_SKINCALL1(__pse51_muxid,
__pse51_mutex_trylock, shadow);
} while (err == -EINTR);
-#endif /* !CONFIG_XENO_FASTSEM */
+#endif /* !CONFIG_XENO_FASTSYNCH */
return -err;
}
@@ -324,7 +324,7 @@ int __wrap_pthread_mutex_unlock(pthread_
struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
int err = 0;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
xnarch_atomic_t *ownerp;
xnhandle_t cur, owner;
@@ -358,17 +358,17 @@ int __wrap_pthread_mutex_unlock(pthread_
cb_read_unlock(&shadow->lock, s);
return 0;
}
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
do {
err = XENOMAI_SKINCALL1(__pse51_muxid,
__pse51_mutex_unlock, shadow);
} while (err == -EINTR);
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
out_err:
cb_read_unlock(&shadow->lock, s);
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
return -err;
}
Index: b/ksrc/nucleus/pipe.c
===================================================================
--- a/ksrc/nucleus/pipe.c
+++ b/ksrc/nucleus/pipe.c
@@ -250,7 +250,7 @@ int xnpipe_connect(int minor,
__setbits(state->status, XNPIPE_KERN_CONN);
- xnsynch_init(&state->synchbase, XNSYNCH_FIFO);
+ xnsynch_init(&state->synchbase, XNSYNCH_FIFO, NULL);
state->output_handler = output_handler;
state->input_handler = input_handler;
state->alloc_handler = alloc_handler;
Index: b/ksrc/nucleus/registry.c
===================================================================
--- a/ksrc/nucleus/registry.c
+++ b/ksrc/nucleus/registry.c
@@ -186,7 +186,7 @@ int xnregistry_init(void)
for (n = 0; n < registry_hash_entries; n++)
registry_hash_table[n] = NULL;
- xnsynch_init(®istry_hash_synch, XNSYNCH_FIFO);
+ xnsynch_init(®istry_hash_synch, XNSYNCH_FIFO, NULL);
return 0;
}
@@ -615,7 +615,7 @@ int xnregistry_enter(const char *key,
object = link2xnobj(holder);
- xnsynch_init(&object->safesynch, XNSYNCH_FIFO);
+ xnsynch_init(&object->safesynch, XNSYNCH_FIFO, NULL);
object->objaddr = objaddr;
object->cstamp = ++registry_obj_stamp;
object->safelock = 0;
Index: b/ksrc/nucleus/select.c
===================================================================
--- a/ksrc/nucleus/select.c
+++ b/ksrc/nucleus/select.c
@@ -274,7 +274,7 @@ int xnselector_init(struct xnselector *s
{
unsigned i;
- xnsynch_init(&selector->synchbase, XNSYNCH_FIFO | XNSYNCH_NOPIP);
+ xnsynch_init(&selector->synchbase, XNSYNCH_FIFO, NULL);
for (i = 0; i < XNSELECT_MAX_TYPES; i++) {
__FD_ZERO(&selector->fds[i].expected);
__FD_ZERO(&selector->fds[i].pending);
Index: b/ksrc/nucleus/synch.c
===================================================================
--- a/ksrc/nucleus/synch.c
+++ b/ksrc/nucleus/synch.c
@@ -37,7 +37,9 @@
#include <nucleus/module.h>
/*!
- * \fn void xnsynch_init(xnsynch_t *synch, xnflags_t flags);
+ * \fn void xnsynch_init(xnsynch_t *synch, xnflags_t flags,
+ * xnarch_atomic_t *fastlock)
+ *
* \brief Initialize a synchronization object.
*
* Initializes a new specialized object which can subsequently be used
@@ -79,6 +81,10 @@
* synchronization object makes the waiters wait by priority order on
* the awaited resource (XNSYNCH_PRIO).
*
+ * @param fastlock Address of the fast lock word to be associated with
+ * the synchronization object. If NULL is passed or XNSYNCH_OWNER is not
+ * set, fast-lock support is disabled.
+ *
* Environments:
*
* This service can be called from:
@@ -90,7 +96,7 @@
* Rescheduling: never.
*/
-void xnsynch_init(xnsynch_t *synch, xnflags_t flags)
+void xnsynch_init(xnsynch_t *synch, xnflags_t flags, xnarch_atomic_t *fastlock)
{
initph(&synch->link);
@@ -100,6 +106,13 @@ void xnsynch_init(xnsynch_t *synch, xnfl
synch->status = flags & ~XNSYNCH_CLAIMED;
synch->owner = NULL;
synch->cleanup = NULL; /* Only works for PIP-enabled objects. */
+#ifdef CONFIG_XENO_FASTSYNCH
+ if ((flags & XNSYNCH_OWNER) && fastlock) {
+ synch->fastlock = fastlock;
+ xnarch_atomic_set(fastlock, XN_NO_HANDLE);
+ } else
+ synch->fastlock = NULL;
+#endif /* CONFIG_XENO_FASTSYNCH */
initpq(&synch->pendq);
xnarch_init_display_context(synch);
}
@@ -379,36 +392,87 @@ void xnsynch_acquire(xnsynch_t *synch, x
xntmode_t timeout_mode)
{
xnthread_t *thread = xnpod_current_thread(), *owner;
+ xnhandle_t threadh = xnthread_handle(thread), fastlock, old;
+ const int use_fastlock = xnsynch_fastlock_p(synch);
spl_t s;
XENO_BUGON(NUCLEUS, !testbits(synch->status, XNSYNCH_OWNER));
- xnlock_get_irqsave(&nklock, s);
-
trace_mark(xn_nucleus_synch_acquire, "synch %p", synch);
-redo:
- owner = synch->owner;
+ redo:
- if (!owner) {
- synch->owner = thread;
- xnthread_clear_info(thread, XNRMID | XNTIMEO | XNBREAK);
- goto unlock_and_exit;
- }
+ if (use_fastlock) {
+ fastlock = xnarch_atomic_cmpxchg(xnsynch_fastlock(synch),
+ XN_NO_HANDLE, threadh);
+
+ if (likely(fastlock == XN_NO_HANDLE)) {
+ xnthread_clear_info(thread,
+ XNRMID | XNTIMEO | XNBREAK);
+ return;
+ }
- if (!testbits(synch->status, XNSYNCH_PRIO)) { /* i.e. FIFO */
- appendpq(&synch->pendq, &thread->plink);
- xnpod_suspend_thread(thread, XNPEND, timeout, timeout_mode, synch);
- goto unlock_and_exit;
+ xnlock_get_irqsave(&nklock, s);
+
+ /* Set claimed bit.
+ In case it appears to be set already, re-read its state
+ under nklock so that we don't miss any change between the
+ lock-less read and here. But also try to avoid cmpxchg
+ where possible. Only if it appears not to be set, start
+ with cmpxchg directly. */
+ if (xnsynch_fast_is_claimed(fastlock)) {
+ old = xnarch_atomic_get(xnsynch_fastlock(synch));
+ goto test_no_owner;
+ }
+ do {
+ old = xnarch_atomic_cmpxchg
+ (xnsynch_fastlock(synch), fastlock,
+ xnsynch_fast_set_claimed(fastlock, 1));
+ if (likely(old == fastlock))
+ break;
+
+ test_no_owner:
+ if (old == XN_NO_HANDLE) {
+ /* Owner called xnsynch_release
+ (on another cpu) */
+ xnlock_put_irqrestore(&nklock, s);
+ goto redo;
+ }
+ fastlock = old;
+ } while (!xnsynch_fast_is_claimed(fastlock));
+
+ owner = xnthread_lookup(xnsynch_fast_mask_claimed(fastlock));
+
+ if (!owner) {
+ /* The handle is broken, therefore pretend that the synch
+ object was deleted to signal an error. */
+ xnthread_set_info(thread, XNRMID);
+ goto unlock_and_exit;
+ }
+
+ xnsynch_set_owner(synch, owner);
+ } else {
+ xnlock_get_irqsave(&nklock, s);
+
+ owner = synch->owner;
+
+ if (!owner) {
+ synch->owner = thread;
+ xnthread_clear_info(thread,
+ XNRMID | XNTIMEO | XNBREAK);
+ goto unlock_and_exit;
+ }
}
- if (thread->cprio > owner->cprio) {
+ if (!testbits(synch->status, XNSYNCH_PRIO)) /* i.e. FIFO */
+ appendpq(&synch->pendq, &thread->plink);
+ else if (thread->cprio > owner->cprio) {
if (xnthread_test_info(owner, XNWAKEN) && owner->wwake == synch) {
/* Ownership is still pending, steal the resource. */
synch->owner = thread;
xnthread_clear_info(thread, XNRMID | XNTIMEO | XNBREAK);
xnthread_set_info(owner, XNROBBED);
- goto unlock_and_exit;
+ goto grab_and_exit;
}
insertpqf(&synch->pendq, &thread->plink, thread->cprio);
@@ -439,12 +503,28 @@ redo:
/* Somebody stole us the ownership while we were ready
to run, waiting for the CPU: we need to wait again
for the resource. */
- if (timeout_mode != XN_RELATIVE || timeout == XN_INFINITE)
+ if (timeout_mode != XN_RELATIVE || timeout == XN_INFINITE) {
+ xnlock_put_irqrestore(&nklock, s);
goto redo;
+ }
timeout = xntimer_get_timeout_stopped(&thread->rtimer);
- if (timeout > 1) /* Otherwise, it's too late. */
+ if (timeout > 1) { /* Otherwise, it's too late. */
+ xnlock_put_irqrestore(&nklock, s);
goto redo;
+ }
xnthread_set_info(thread, XNTIMEO);
+ } else {
+
+ grab_and_exit:
+
+ if (use_fastlock) {
+ /* We are the new owner, update the fastlock
+ accordingly. */
+ if (xnsynch_pended_p(synch))
+ threadh =
+ xnsynch_fast_set_claimed(threadh, 1);
+ xnarch_atomic_set(xnsynch_fastlock(synch), threadh);
+ }
}
unlock_and_exit:
@@ -582,12 +662,20 @@ void xnsynch_renice_sleeper(xnthread_t *
struct xnthread *xnsynch_release(xnsynch_t *synch)
{
+ const int use_fastlock = xnsynch_fastlock_p(synch);
xnthread_t *newowner, *lastowner;
+ xnhandle_t lastownerh, newownerh;
xnpholder_t *holder;
spl_t s;
XENO_BUGON(NUCLEUS, !testbits(synch->status, XNSYNCH_OWNER));
+ lastownerh = xnthread_handle(xnpod_current_thread());
+
+ if (use_fastlock &&
+ likely(xnsynch_fast_release(xnsynch_fastlock(synch), lastownerh)))
+ return NULL;
+
xnlock_get_irqsave(&nklock, s);
trace_mark(xn_nucleus_synch_release, "synch %p", synch);
@@ -605,10 +693,16 @@ struct xnthread *xnsynch_release(xnsynch
if (testbits(synch->status, XNSYNCH_CLAIMED))
xnsynch_clear_boost(synch, lastowner);
+
+ newownerh = xnsynch_fast_set_claimed(xnthread_handle(newowner),
+ xnsynch_pended_p(synch));
} else {
newowner = NULL;
synch->owner = NULL;
+ newownerh = XN_NO_HANDLE;
}
+ if (use_fastlock)
+ xnarch_atomic_set(xnsynch_fastlock(synch), newownerh);
xnlock_put_irqrestore(&nklock, s);
Index: b/ksrc/drivers/testing/switchtest.c
===================================================================
--- a/ksrc/drivers/testing/switchtest.c
+++ b/ksrc/drivers/testing/switchtest.c
@@ -219,7 +219,7 @@ static int rtswitch_register_task(rtswit
ctx->next_index++;
t->base = *arg;
sema_init(&t->nrt_synch, 0);
- xnsynch_init(&t->rt_synch, XNSYNCH_FIFO);
+ xnsynch_init(&t->rt_synch, XNSYNCH_FIFO, NULL);
up(&ctx->lock);
Index: b/ksrc/skins/native/alarm.c
===================================================================
--- a/ksrc/skins/native/alarm.c
+++ b/ksrc/skins/native/alarm.c
@@ -207,7 +207,7 @@ int rt_alarm_create(RT_ALARM *alarm,
xnlock_put_irqrestore(&nklock, s);
#ifdef CONFIG_XENO_OPT_PERVASIVE
- xnsynch_init(&alarm->synch_base, XNSYNCH_PRIO);
+ xnsynch_init(&alarm->synch_base, XNSYNCH_PRIO, NULL);
alarm->cpid = 0;
#endif /* CONFIG_XENO_OPT_PERVASIVE */
Index: b/ksrc/skins/native/buffer.c
===================================================================
--- a/ksrc/skins/native/buffer.c
+++ b/ksrc/skins/native/buffer.c
@@ -192,8 +192,8 @@ int rt_buffer_create(RT_BUFFER *bf, cons
if (bf->bufmem == NULL)
return -ENOMEM;
- xnsynch_init(&bf->isynch_base, mode & B_PRIO);
- xnsynch_init(&bf->osynch_base, mode & B_PRIO);
+ xnsynch_init(&bf->isynch_base, mode & B_PRIO, NULL);
+ xnsynch_init(&bf->osynch_base, mode & B_PRIO, NULL);
bf->handle = 0; /* i.e. (still) unregistered buffer. */
xnobject_copy_name(bf->name, name);
Index: b/ksrc/skins/native/cond.c
===================================================================
--- a/ksrc/skins/native/cond.c
+++ b/ksrc/skins/native/cond.c
@@ -160,7 +160,7 @@ int rt_cond_create(RT_COND *cond, const
if (xnpod_asynch_p())
return -EPERM;
- xnsynch_init(&cond->synch_base, XNSYNCH_PRIO);
+ xnsynch_init(&cond->synch_base, XNSYNCH_PRIO, NULL);
cond->handle = 0; /* i.e. (still) unregistered cond. */
cond->magic = XENO_COND_MAGIC;
xnobject_copy_name(cond->name, name);
Index: b/ksrc/skins/native/event.c
===================================================================
--- a/ksrc/skins/native/event.c
+++ b/ksrc/skins/native/event.c
@@ -183,7 +183,7 @@ int rt_event_create(RT_EVENT *event,
if (xnpod_asynch_p())
return -EPERM;
- xnsynch_init(&event->synch_base, mode & EV_PRIO);
+ xnsynch_init(&event->synch_base, mode & EV_PRIO, NULL);
event->value = ivalue;
event->handle = 0; /* i.e. (still) unregistered event. */
event->magic = XENO_EVENT_MAGIC;
Index: b/ksrc/skins/native/heap.c
===================================================================
--- a/ksrc/skins/native/heap.c
+++ b/ksrc/skins/native/heap.c
@@ -292,7 +292,7 @@ int rt_heap_create(RT_HEAP *heap, const
}
}
- xnsynch_init(&heap->synch_base, mode & (H_PRIO | H_FIFO));
+ xnsynch_init(&heap->synch_base, mode & (H_PRIO | H_FIFO), NULL);
heap->handle = 0; /* i.e. (still) unregistered heap. */
heap->magic = XENO_HEAP_MAGIC;
heap->mode = mode;
Index: b/ksrc/skins/native/intr.c
===================================================================
--- a/ksrc/skins/native/intr.c
+++ b/ksrc/skins/native/intr.c
@@ -266,7 +266,7 @@ int rt_intr_create(RT_INTR *intr,
xnintr_init(&intr->intr_base, intr->name, irq, isr, iack, mode);
#ifdef CONFIG_XENO_OPT_PERVASIVE
- xnsynch_init(&intr->synch_base, XNSYNCH_PRIO);
+ xnsynch_init(&intr->synch_base, XNSYNCH_PRIO, NULL);
intr->pending = 0;
intr->cpid = 0;
intr->mode = 0;
Index: b/ksrc/skins/native/mutex.c
===================================================================
--- a/ksrc/skins/native/mutex.c
+++ b/ksrc/skins/native/mutex.c
@@ -171,7 +171,7 @@ int rt_mutex_create(RT_MUTEX *mutex, con
return -EPERM;
xnsynch_init(&mutex->synch_base,
- XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER);
+ XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER, NULL);
mutex->handle = 0; /* i.e. (still) unregistered mutex. */
mutex->magic = XENO_MUTEX_MAGIC;
mutex->lockcnt = 0;
Index: b/ksrc/skins/native/queue.c
===================================================================
--- a/ksrc/skins/native/queue.c
+++ b/ksrc/skins/native/queue.c
@@ -255,7 +255,7 @@ int rt_queue_create(RT_QUEUE *q,
}
}
- xnsynch_init(&q->synch_base, mode & (Q_PRIO | Q_FIFO));
+ xnsynch_init(&q->synch_base, mode & (Q_PRIO | Q_FIFO), NULL);
initq(&q->pendq);
q->handle = 0; /* i.e. (still) unregistered queue. */
q->magic = XENO_QUEUE_MAGIC;
Index: b/ksrc/skins/native/sem.c
===================================================================
--- a/ksrc/skins/native/sem.c
+++ b/ksrc/skins/native/sem.c
@@ -181,7 +181,7 @@ int rt_sem_create(RT_SEM *sem, const cha
if ((mode & S_PULSE) && icount > 0)
return -EINVAL;
- xnsynch_init(&sem->synch_base, mode & S_PRIO);
+ xnsynch_init(&sem->synch_base, mode & S_PRIO, NULL);
sem->count = icount;
sem->mode = mode;
sem->handle = 0; /* i.e. (still) unregistered semaphore. */
Index: b/ksrc/skins/native/task.c
===================================================================
--- a/ksrc/skins/native/task.c
+++ b/ksrc/skins/native/task.c
@@ -255,7 +255,7 @@ int rt_task_create(RT_TASK *task,
task->overrun = -1;
task->cstamp = ++__xeno_task_stamp;
task->safelock = 0;
- xnsynch_init(&task->safesynch, XNSYNCH_FIFO);
+ xnsynch_init(&task->safesynch, XNSYNCH_FIFO, NULL);
xnarch_cpus_clear(task->affinity);
@@ -268,9 +268,9 @@ int rt_task_create(RT_TASK *task,
task->affinity = XNPOD_ALL_CPUS;
#ifdef CONFIG_XENO_OPT_NATIVE_MPS
- xnsynch_init(&task->mrecv, XNSYNCH_FIFO);
+ xnsynch_init(&task->mrecv, XNSYNCH_FIFO, NULL);
xnsynch_init(&task->msendq,
- XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER);
+ XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER, NULL);
xnsynch_set_owner(&task->msendq, &task->thread_base);
task->flowgen = 0;
#endif /* CONFIG_XENO_OPT_NATIVE_MPS */
Index: b/ksrc/skins/posix/intr.c
===================================================================
--- a/ksrc/skins/posix/intr.c
+++ b/ksrc/skins/posix/intr.c
@@ -116,7 +116,7 @@ int pthread_intr_attach_np(pthread_intr_
xnintr_init(&intr->intr_base, NULL, irq, isr, iack, 0);
#ifdef CONFIG_XENO_OPT_PERVASIVE
- xnsynch_init(&intr->synch_base, XNSYNCH_PRIO);
+ xnsynch_init(&intr->synch_base, XNSYNCH_PRIO, NULL);
intr->pending = 0;
#endif /* CONFIG_XENO_OPT_PERVASIVE */
intr->magic = PSE51_INTR_MAGIC;
Index: b/ksrc/skins/posix/mq.c
===================================================================
--- a/ksrc/skins/posix/mq.c
+++ b/ksrc/skins/posix/mq.c
@@ -129,8 +129,8 @@ static int pse51_mq_init(pse51_mq_t * mq
mq->memsize = memsize;
initpq(&mq->queued);
- xnsynch_init(&mq->receivers, XNSYNCH_PRIO | XNSYNCH_NOPIP);
- xnsynch_init(&mq->senders, XNSYNCH_PRIO | XNSYNCH_NOPIP);
+ xnsynch_init(&mq->receivers, XNSYNCH_PRIO | XNSYNCH_NOPIP, NULL);
+ xnsynch_init(&mq->senders, XNSYNCH_PRIO | XNSYNCH_NOPIP, NULL);
mq->mem = mem;
/* Fill the pool. */
Index: b/ksrc/skins/posix/sem.c
===================================================================
--- a/ksrc/skins/posix/sem.c
+++ b/ksrc/skins/posix/sem.c
@@ -99,7 +99,7 @@ static int pse51_sem_init_inner(pse51_se
inith(&sem->link);
appendq(&pse51_kqueues(pshared)->semq, &sem->link);
- xnsynch_init(&sem->synchbase, XNSYNCH_PRIO);
+ xnsynch_init(&sem->synchbase, XNSYNCH_PRIO, NULL);
sem->value = value;
sem->pshared = pshared;
sem->is_named = 0;
Index: b/ksrc/skins/psos+/event.c
===================================================================
--- a/ksrc/skins/psos+/event.c
+++ b/ksrc/skins/psos+/event.c
@@ -21,7 +21,7 @@
void taskev_init(psosevent_t *evgroup)
{
- xnsynch_init(&evgroup->synchbase, XNSYNCH_FIFO);
+ xnsynch_init(&evgroup->synchbase, XNSYNCH_FIFO, NULL);
evgroup->events = 0;
}
Index: b/ksrc/skins/psos+/queue.c
===================================================================
--- a/ksrc/skins/psos+/queue.c
+++ b/ksrc/skins/psos+/queue.c
@@ -259,7 +259,7 @@ static u_long q_create_internal(const ch
}
}
- xnsynch_init(&queue->synchbase, bflags);
+ xnsynch_init(&queue->synchbase, bflags, NULL);
queue->magic = PSOS_QUEUE_MAGIC;
xnobject_copy_name(queue->name, name);
Index: b/ksrc/skins/psos+/rn.c
===================================================================
--- a/ksrc/skins/psos+/rn.c
+++ b/ksrc/skins/psos+/rn.c
@@ -214,7 +214,7 @@ u_long rn_create(const char *name,
rn->usize = usize;
xnobject_copy_name(rn->name, name);
- xnsynch_init(&rn->synchbase, bflags);
+ xnsynch_init(&rn->synchbase, bflags, NULL);
rn->magic = PSOS_RN_MAGIC;
inith(&rn->rlink);
Index: b/ksrc/skins/psos+/sem.c
===================================================================
--- a/ksrc/skins/psos+/sem.c
+++ b/ksrc/skins/psos+/sem.c
@@ -114,7 +114,7 @@ u_long sm_create(const char *name, u_lon
if (flags & SM_PRIOR)
bflags |= XNSYNCH_PRIO;
- xnsynch_init(&sem->synchbase, bflags);
+ xnsynch_init(&sem->synchbase, bflags, NULL);
inith(&sem->link);
sem->count = icount;
Index: b/ksrc/skins/rtai/sem.c
===================================================================
--- a/ksrc/skins/rtai/sem.c
+++ b/ksrc/skins/rtai/sem.c
@@ -38,7 +38,7 @@ void rt_typed_sem_init(SEM * sem, int va
mode = XNSYNCH_FIFO;
}
- xnsynch_init(&sem->synch_base, mode);
+ xnsynch_init(&sem->synch_base, mode, NULL);
sem->count = value;
sem->type = type & 0x3;
sem->owner = NULL;
Index: b/ksrc/skins/rtdm/drvlib.c
===================================================================
--- a/ksrc/skins/rtdm/drvlib.c
+++ b/ksrc/skins/rtdm/drvlib.c
@@ -145,13 +145,13 @@ int rtdm_task_init(rtdm_task_t *task, co
if (err)
return err;
-#ifdef CONFIG_XENO_FASTSEM
+#ifdef CONFIG_XENO_FASTSYNCH
/* We need an anonymous registry entry to obtain a handle for fast
mutex locking. */
err = xnthread_register(task, "");
if (err)
goto cleanup_out;
-#endif /* CONFIG_XENO_FASTSEM */
+#endif /* CONFIG_XENO_FASTSYNCH */
if (period > 0) {
err = xnpod_set_thread_periodic(task, XN_INFINITE,
@@ -761,7 +761,7 @@ void rtdm_event_init(rtdm_event_t *event
/* Make atomic for re-initialisation support */
xnlock_get_irqsave(&nklock, s);
- xnsynch_init(&event->synch_base, XNSYNCH_PRIO);
+ xnsynch_init(&event->synch_base, XNSYNCH_PRIO, NULL);
if (pending)
xnsynch_set_flags(&event->synch_base, RTDM_EVENT_PENDING);
xnselect_init(&event->select_block);
@@ -1109,7 +1109,7 @@ void rtdm_sem_init(rtdm_sem_t *sem, unsi
xnlock_get_irqsave(&nklock, s);
sem->value = value;
- xnsynch_init(&sem->synch_base, XNSYNCH_PRIO);
+ xnsynch_init(&sem->synch_base, XNSYNCH_PRIO, NULL);
xnselect_init(&sem->select_block);
xnlock_put_irqrestore(&nklock, s);
@@ -1391,7 +1391,7 @@ void rtdm_mutex_init(rtdm_mutex_t *mutex
xnlock_get_irqsave(&nklock, s);
xnsynch_init(&mutex->synch_base,
- XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER);
+ XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER, NULL);
xnlock_put_irqrestore(&nklock, s);
}
Index: b/ksrc/skins/uitron/flag.c
===================================================================
--- a/ksrc/skins/uitron/flag.c
+++ b/ksrc/skins/uitron/flag.c
@@ -122,7 +122,7 @@ ER cre_flg(ID flgid, T_CFLG *pk_cflg)
return E_OBJ;
}
- xnsynch_init(&flag->synchbase, XNSYNCH_FIFO);
+ xnsynch_init(&flag->synchbase, XNSYNCH_FIFO, NULL);
flag->id = flgid;
flag->exinf = pk_cflg->exinf;
flag->flgatr = pk_cflg->flgatr;
Index: b/ksrc/skins/uitron/mbx.c
===================================================================
--- a/ksrc/skins/uitron/mbx.c
+++ b/ksrc/skins/uitron/mbx.c
@@ -138,7 +138,8 @@ ER cre_mbx(ID mbxid, T_CMBX *pk_cmbx)
}
xnsynch_init(&mbx->synchbase,
- (pk_cmbx->mbxatr & TA_TPRI) ? XNSYNCH_PRIO : XNSYNCH_FIFO);
+ (pk_cmbx->mbxatr & TA_TPRI) ? XNSYNCH_PRIO : XNSYNCH_FIFO,
+ NULL);
mbx->id = mbxid;
mbx->exinf = pk_cmbx->exinf;
Index: b/ksrc/skins/uitron/sem.c
===================================================================
--- a/ksrc/skins/uitron/sem.c
+++ b/ksrc/skins/uitron/sem.c
@@ -127,7 +127,8 @@ ER cre_sem(ID semid, T_CSEM *pk_csem)
}
xnsynch_init(&sem->synchbase,
- (pk_csem->sematr & TA_TPRI) ? XNSYNCH_PRIO : XNSYNCH_FIFO);
+ (pk_csem->sematr & TA_TPRI) ? XNSYNCH_PRIO : XNSYNCH_FIFO,
+ NULL);
sem->id = semid;
sem->exinf = pk_csem->exinf;
Index: b/ksrc/skins/vrtx/event.c
===================================================================
--- a/ksrc/skins/vrtx/event.c
+++ b/ksrc/skins/vrtx/event.c
@@ -151,7 +151,7 @@ int sc_fcreate(int *errp)
goto nocb;
}
- xnsynch_init(&evgroup->synchbase, XNSYNCH_PRIO | XNSYNCH_DREORD);
+ xnsynch_init(&evgroup->synchbase, XNSYNCH_PRIO | XNSYNCH_DREORD, NULL);
inith(&evgroup->link);
evgroup->evid = evid;
evgroup->magic = VRTX_EVENT_MAGIC;
Index: b/ksrc/skins/vrtx/mb.c
===================================================================
--- a/ksrc/skins/vrtx/mb.c
+++ b/ksrc/skins/vrtx/mb.c
@@ -210,7 +210,7 @@ vrtxmb_t *mb_map(char **mboxp)
mb->mboxp = mboxp;
mb->msg = NULL;
mb->hnext = NULL;
- xnsynch_init(&mb->synchbase, XNSYNCH_PRIO | XNSYNCH_DREORD);
+ xnsynch_init(&mb->synchbase, XNSYNCH_PRIO | XNSYNCH_DREORD, NULL);
appendq(&vrtx_mbox_q, &mb->link);
mb_hash(mboxp, mb);
Index: b/ksrc/skins/vrtx/mx.c
===================================================================
--- a/ksrc/skins/vrtx/mx.c
+++ b/ksrc/skins/vrtx/mx.c
@@ -161,7 +161,8 @@ int sc_mcreate(unsigned int opt, int *er
inith(&mx->link);
mx->mid = mid;
mx->owner = NULL;
- xnsynch_init(&mx->synchbase, bflags | XNSYNCH_DREORD | XNSYNCH_OWNER);
+ xnsynch_init(&mx->synchbase, bflags | XNSYNCH_DREORD | XNSYNCH_OWNER,
+ NULL);
xnlock_get_irqsave(&nklock, s);
appendq(&vrtx_mx_q, &mx->link);
Index: b/ksrc/skins/vrtx/queue.c
===================================================================
--- a/ksrc/skins/vrtx/queue.c
+++ b/ksrc/skins/vrtx/queue.c
@@ -165,7 +165,7 @@ int sc_qecreate(int qid, int qsize, int
bflags = XNSYNCH_PRIO;
inith(&queue->link);
- xnsynch_init(&queue->synchbase, bflags | XNSYNCH_DREORD);
+ xnsynch_init(&queue->synchbase, bflags | XNSYNCH_DREORD, NULL);
queue->magic = VRTX_QUEUE_MAGIC;
queue->qid = qid;
queue->qsize = qsize;
Index: b/ksrc/skins/vrtx/sem.c
===================================================================
--- a/ksrc/skins/vrtx/sem.c
+++ b/ksrc/skins/vrtx/sem.c
@@ -155,7 +155,7 @@ int sc_screate(unsigned initval, int opt
else
bflags = XNSYNCH_FIFO;
- xnsynch_init(&sem->synchbase, bflags | XNSYNCH_DREORD);
+ xnsynch_init(&sem->synchbase, bflags | XNSYNCH_DREORD, NULL);
inith(&sem->link);
sem->semid = semid;
sem->magic = VRTX_SEM_MAGIC;
Index: b/ksrc/skins/vxworks/module.c
===================================================================
--- a/ksrc/skins/vxworks/module.c
+++ b/ksrc/skins/vxworks/module.c
@@ -59,7 +59,7 @@ int SKIN_INIT(vxworks)
/* The following fields are unused in the global holder;
still, we initialize them not to leave such data in an
invalid state. */
- xnsynch_init(&__wind_global_rholder.wdsynch, XNSYNCH_FIFO);
+ xnsynch_init(&__wind_global_rholder.wdsynch, XNSYNCH_FIFO, NULL);
initq(&__wind_global_rholder.wdpending);
__wind_global_rholder.wdcount = 0;
Index: b/ksrc/skins/vxworks/msgQLib.c
===================================================================
--- a/ksrc/skins/vxworks/msgQLib.c
+++ b/ksrc/skins/vxworks/msgQLib.c
@@ -174,7 +174,7 @@ MSG_Q_ID msgQCreate(int nb_msgs, int len
if (flags & MSG_Q_PRIORITY)
bflags |= XNSYNCH_PRIO;
- xnsynch_init(&queue->synchbase, bflags);
+ xnsynch_init(&queue->synchbase, bflags, NULL);
msg_size = sizeof(wind_msg_t) + length;
Index: b/ksrc/skins/vxworks/semLib.c
===================================================================
--- a/ksrc/skins/vxworks/semLib.c
+++ b/ksrc/skins/vxworks/semLib.c
@@ -423,7 +423,7 @@ static SEM_ID sem_create_internal(int fl
check_alloc(wind_sem_t, sem, return 0);
- xnsynch_init(&sem->synchbase, (xnflags_t)flags);
+ xnsynch_init(&sem->synchbase, (xnflags_t)flags, NULL);
sem->magic = WIND_SEM_MAGIC;
sem->count = count;
sem->vtbl = vtbl;
Index: b/ksrc/skins/vxworks/syscall.c
===================================================================
--- a/ksrc/skins/vxworks/syscall.c
+++ b/ksrc/skins/vxworks/syscall.c
@@ -1171,7 +1171,7 @@ static void *__wind_shadow_eventcb(int e
initq(&rh->wdq);
/* A single server thread pends on this. */
- xnsynch_init(&rh->wdsynch, XNSYNCH_FIFO);
+ xnsynch_init(&rh->wdsynch, XNSYNCH_FIFO, NULL);
initq(&rh->wdpending);
rh->wdcount = 0;
initq(&rh->msgQq);
Index: b/ksrc/skins/vxworks/taskLib.c
===================================================================
--- a/ksrc/skins/vxworks/taskLib.c
+++ b/ksrc/skins/vxworks/taskLib.c
@@ -146,7 +146,7 @@ STATUS taskInit(WIND_TCB *pTcb,
xnthread_time_slice(&pTcb->threadbase) = rrperiod;
pTcb->safecnt = 0;
- xnsynch_init(&pTcb->safesync, 0);
+ xnsynch_init(&pTcb->safesync, 0, NULL);
/* TODO: fill in attributes of wind_task_t:
pTcb->status
^ permalink raw reply [flat|nested] 17+ messages in thread* [Xenomai-core] [PATCH 08/13] Convert POSIX skin to fast xnsynch
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (6 preceding siblings ...)
2008-10-17 15:46 ` [Xenomai-core] [PATCH 07/13] Lockless fast path for xnsynch_acquire/release Jan Kiszka
@ 2008-10-17 15:46 ` Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 09/13] Use fast xnsynch with native skin Jan Kiszka
` (7 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:46 UTC (permalink / raw)
To: xenomai; +Cc: Jan Kiszka
Migrates the existing fast mutex implementation of the POSIX skin to
fast xnsynch services, also fixing the build for arch that do not
support fast mutexes.
Lock stealing via pthread_trylock is not considered by this patch,
keeping this services lockless and syscall-less until we identify the
need for using the steal mechanism also for this case.
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
ksrc/skins/posix/cond.c | 13 ----
ksrc/skins/posix/mutex.c | 87 +++++++++++++++++++---------
ksrc/skins/posix/mutex.h | 138 ++++++---------------------------------------
ksrc/skins/posix/syscall.c | 22 ++-----
src/skins/posix/mutex.c | 55 +++++++++--------
5 files changed, 117 insertions(+), 198 deletions(-)
Index: b/ksrc/skins/posix/cond.c
===================================================================
--- a/ksrc/skins/posix/cond.c
+++ b/ksrc/skins/posix/cond.c
@@ -223,27 +223,18 @@ static inline int mutex_save_count(xnthr
unsigned *count_ptr)
{
pse51_mutex_t *mutex;
- xnthread_t *owner;
if (!pse51_obj_active(shadow, PSE51_MUTEX_MAGIC, struct __shadow_mutex))
return EINVAL;
mutex = shadow->mutex;
- if (clear_claimed(xnarch_atomic_get(mutex->owner)) !=
- xnthread_handle(cur))
+ if (xnsynch_owner_check(&mutex->synchbase, cur) != 0)
return EPERM;
*count_ptr = shadow->lockcnt;
- if (likely(xnarch_atomic_cmpxchg(mutex->owner, cur, XN_NO_HANDLE) ==
- xnthread_handle(cur)))
- return 0;
-
- owner = xnsynch_release(&mutex->synchbase);
- xnarch_atomic_set(mutex->owner,
- set_claimed(xnthread_handle(owner),
- xnsynch_nsleepers(&mutex->synchbase)));
+ xnsynch_release(&mutex->synchbase);
/* Do not reschedule here, releasing the mutex and suspension must be
done atomically in pthread_cond_*wait. */
Index: b/ksrc/skins/posix/mutex.c
===================================================================
--- a/ksrc/skins/posix/mutex.c
+++ b/ksrc/skins/posix/mutex.c
@@ -102,9 +102,9 @@ int pse51_mutex_init_internal(struct __s
shadow->magic = PSE51_MUTEX_MAGIC;
shadow->mutex = mutex;
shadow->lockcnt = 0;
+ xnarch_atomic_set(&shadow->lock, -1);
#ifdef CONFIG_XENO_FASTSYNCH
- xnarch_atomic_set(&shadow->lock, -1);
shadow->attr = *attr;
shadow->owner_offset = xnheap_mapped_offset(&sys_ppd->sem_heap, ownerp);
#endif /* CONFIG_XENO_FASTSYNCH */
@@ -112,13 +112,10 @@ int pse51_mutex_init_internal(struct __s
if (attr->protocol == PTHREAD_PRIO_INHERIT)
synch_flags |= XNSYNCH_PIP;
- xnsynch_init(&mutex->synchbase, synch_flags, NULL);
+ xnsynch_init(&mutex->synchbase, synch_flags, ownerp);
inith(&mutex->link);
mutex->attr = *attr;
- mutex->owner = ownerp;
mutex->owningq = kq;
- mutex->sleepers = 0;
- xnarch_atomic_set(ownerp, XN_NO_HANDLE);
xnlock_get_irqsave(&nklock, s);
appendq(&kq->mutexq, &mutex->link);
@@ -159,7 +156,7 @@ int pthread_mutex_init(pthread_mutex_t *
&((union __xeno_mutex *)mx)->shadow_mutex;
DECLARE_CB_LOCK_FLAGS(s);
pse51_mutex_t *mutex;
- xnarch_atomic_t *ownerp;
+ xnarch_atomic_t *ownerp = NULL;
int err;
if (!attr)
@@ -185,6 +182,7 @@ int pthread_mutex_init(pthread_mutex_t *
if (!mutex)
return ENOMEM;
+#ifdef CONFIG_XENO_FASTSYNCH
ownerp = (xnarch_atomic_t *)
xnheap_alloc(&xnsys_ppd_get(attr->pshared)->sem_heap,
sizeof(xnarch_atomic_t));
@@ -192,6 +190,7 @@ int pthread_mutex_init(pthread_mutex_t *
xnfree(mutex);
return EAGAIN;
}
+#endif /* CONFIG_XENO_FASTSYNCH */
cb_force_write_lock(&shadow->lock, s);
err = pse51_mutex_init_internal(shadow, mutex, ownerp, attr);
@@ -199,7 +198,9 @@ int pthread_mutex_init(pthread_mutex_t *
if (err) {
xnfree(mutex);
+#ifdef CONFIG_XENO_FASTSYNCH
xnheap_free(&xnsys_ppd_get(attr->pshared)->sem_heap, ownerp);
+#endif /* CONFIG_XENO_FASTSYNCH */
}
return -err;
}
@@ -216,8 +217,10 @@ void pse51_mutex_destroy_internal(pse51_
xnsynch_destroy(&mutex->synchbase);
xnlock_put_irqrestore(&nklock, s);
- if (mutex->attr.pshared)
- xnheap_free(&xnsys_ppd_get(1)->sem_heap, mutex->owner);
+#ifdef CONFIG_XENO_FASTSYNCH
+ xnheap_free(&xnsys_ppd_get(mutex->attr.pshared)->sem_heap,
+ mutex->synchbase.fastlock);
+#endif /* CONFIG_XENO_FASTSYNCH */
/* We do not free the owner if the mutex is not pshared, because when
this function is called from pse51_mutexq_cleanup, the sem_heap has
been destroyed, and we have no way to find it back. */
@@ -266,7 +269,12 @@ int pthread_mutex_destroy(pthread_mutex_
return EPERM;
}
- if (xnarch_atomic_get(mutex->owner) != XN_NO_HANDLE) {
+#ifdef CONFIG_XENO_FASTSYNCH
+ if (xnsynch_fast_owner_check(mutex->synchbase.fastlock,
+ XN_NO_HANDLE) != 0) {
+#else /* CONFIG_XENO_FASTSYNCH */
+ if (xnsynch_owner_check(&mutex->synchbase, NULL) {
+#endif
cb_write_unlock(&shadow->lock, s);
return EBUSY;
}
@@ -274,9 +282,6 @@ int pthread_mutex_destroy(pthread_mutex_
pse51_mark_deleted(shadow);
cb_write_unlock(&shadow->lock, s);
- if (!mutex->attr.pshared)
- xnheap_free(&xnsys_ppd_get(mutex->attr.pshared)->sem_heap,
- mutex->owner);
pse51_mutex_destroy_internal(mutex, pse51_kqueues(mutex->attr.pshared));
return 0;
@@ -305,14 +310,12 @@ int pse51_mutex_timedlock_break(struct _
/* Attempting to relock a normal mutex, deadlock. */
xnlock_get_irqsave(&nklock, s);
for (;;) {
- ++mutex->sleepers;
if (timed)
xnsynch_acquire(&mutex->synchbase,
abs_to, XN_REALTIME);
else
xnsynch_acquire(&mutex->synchbase,
XN_INFINITE, XN_RELATIVE);
- --mutex->sleepers;
if (xnthread_test_info(cur, XNBREAK)) {
err = -EINTR;
@@ -384,19 +387,48 @@ int pthread_mutex_trylock(pthread_mutex_
{
struct __shadow_mutex *shadow =
&((union __xeno_mutex *)mx)->shadow_mutex;
- xnthread_t *owner, *cur = xnpod_current_thread();
+ xnthread_t *cur = xnpod_current_thread();
+ pse51_mutex_t *mutex = shadow->mutex;
DECLARE_CB_LOCK_FLAGS(s);
int err;
+ if (xnpod_unblockable_p())
+ return EPERM;
+
if (unlikely(cb_try_read_lock(&shadow->lock, s)))
return EINVAL;
- owner = pse51_mutex_trylock_internal(cur, shadow, 1);
- if (likely(!owner) || IS_ERR(owner))
- return -PTR_ERR(owner);
+ if (!pse51_obj_active(shadow, PSE51_MUTEX_MAGIC,
+ struct __shadow_mutex)) {
+ err = EINVAL;
+ goto unlock_and_return;
+ }
- err = EBUSY;
- if (owner == cur) {
+#if XENO_DEBUG(POSIX)
+ if (mutex->owningq != pse51_kqueues(mutex->attr.pshared)) {
+ err = EPERM;
+ goto unlock_and_return;
+ }
+#endif /* XENO_DEBUG(POSIX) */
+
+#ifdef CONFIG_XENO_FASTSYNCH
+ err = -xnsynch_fast_acquire(mutex->synchbase.fastlock,
+ xnthread_handle(cur));
+#else /* !CONFIG_XENO_FASTSYNCH */
+ {
+ xnthread_t *owner = xnsynch_owner(&mutex->synchbase);
+ if (!owner)
+ err = 0;
+ else if (owner == cur)
+ err = EBUSY;
+ else
+ err = EAGAIN;
+ }
+#endif /* !CONFIG_XENO_FASTSYNCH */
+
+ if (likely(!err))
+ shadow->lockcnt = 1;
+ else if (err == EBUSY) {
pse51_mutex_t *mutex = shadow->mutex;
if (mutex->attr.type == PTHREAD_MUTEX_RECURSIVE) {
@@ -409,6 +441,7 @@ int pthread_mutex_trylock(pthread_mutex_
}
}
+ unlock_and_return:
cb_read_unlock(&shadow->lock, s);
return err;
@@ -564,7 +597,7 @@ int pthread_mutex_unlock(pthread_mutex_t
int err;
if (xnpod_root_p() || xnpod_interrupt_p())
- return -EPERM;
+ return EPERM;
if (unlikely(cb_try_read_lock(&shadow->lock, s)))
return EINVAL;
@@ -576,14 +609,11 @@ int pthread_mutex_unlock(pthread_mutex_t
}
mutex = shadow->mutex;
-
- if (clear_claimed(xnarch_atomic_get(mutex->owner)) !=
- xnthread_handle(cur)) {
- err = EPERM;
+
+ err = -xnsynch_owner_check(&mutex->synchbase, cur);
+ if (err)
goto out;
- }
- err = 0;
if (shadow->lockcnt > 1) {
/* Mutex is recursive */
--shadow->lockcnt;
@@ -591,7 +621,8 @@ int pthread_mutex_unlock(pthread_mutex_t
return 0;
}
- pse51_mutex_unlock_internal(cur, mutex);
+ if (xnsynch_release(&mutex->synchbase))
+ xnpod_schedule();
out:
cb_read_unlock(&shadow->lock, s);
Index: b/ksrc/skins/posix/mutex.h
===================================================================
--- a/ksrc/skins/posix/mutex.h
+++ b/ksrc/skins/posix/mutex.h
@@ -30,8 +30,8 @@ union __xeno_mutex {
unsigned magic;
unsigned lockcnt;
struct pse51_mutex *mutex;
-#ifdef CONFIG_XENO_FASTSYNCH
xnarch_atomic_t lock;
+#ifdef CONFIG_XENO_FASTSYNCH
union {
unsigned owner_offset;
xnarch_atomic_t *owner;
@@ -54,9 +54,7 @@ typedef struct pse51_mutex {
#define link2mutex(laddr) \
((pse51_mutex_t *)(((char *)laddr) - offsetof(pse51_mutex_t, link)))
- xnarch_atomic_t *owner;
pthread_mutexattr_t attr;
- unsigned sleepers;
pse51_kqueues_t *owningq;
} pse51_mutex_t;
@@ -83,145 +81,47 @@ int pse51_mutex_init_internal(struct __s
void pse51_mutex_destroy_internal(pse51_mutex_t *mutex,
pse51_kqueues_t *q);
-static inline xnthread_t *
-pse51_mutex_trylock_internal(xnthread_t *cur,
- struct __shadow_mutex *shadow, unsigned count)
+/* must be called with nklock locked, interrupts off. */
+static inline int pse51_mutex_timedlock_internal(xnthread_t *cur,
+ struct __shadow_mutex *shadow,
+ unsigned count,
+ int timed,
+ xnticks_t abs_to)
+
{
pse51_mutex_t *mutex = shadow->mutex;
- xnhandle_t ownerh;
- xnthread_t *owner;
if (xnpod_unblockable_p())
- return ERR_PTR(-EPERM);
+ return -EPERM;
if (!pse51_obj_active(shadow, PSE51_MUTEX_MAGIC, struct __shadow_mutex))
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
#if XENO_DEBUG(POSIX)
if (mutex->owningq != pse51_kqueues(mutex->attr.pshared))
- return ERR_PTR(-EPERM);
+ return -EPERM;
#endif /* XENO_DEBUG(POSIX) */
- ownerh = xnarch_atomic_cmpxchg(mutex->owner, XN_NO_HANDLE,
- xnthread_handle(cur));
- if (unlikely(ownerh != XN_NO_HANDLE)) {
- owner = xnthread_lookup(clear_claimed(ownerh));
- if (!owner)
- return ERR_PTR(-EINVAL);
- return owner;
- }
-
- shadow->lockcnt = count;
- return NULL;
-}
-
-/* must be called with nklock locked, interrupts off. */
-static inline int pse51_mutex_timedlock_internal(xnthread_t *cur,
- struct __shadow_mutex *shadow,
- unsigned count,
- int timed,
- xnticks_t abs_to)
-
-{
- pse51_mutex_t *mutex;
- xnthread_t *owner;
- xnhandle_t ownerh, old;
- spl_t s;
- int err;
-
- retry_lock:
- owner = pse51_mutex_trylock_internal(cur, shadow, count);
- if (likely(!owner) || IS_ERR(owner))
- return PTR_ERR(owner);
-
- mutex = shadow->mutex;
- if (owner == cur)
+ if (xnsynch_owner_check(&mutex->synchbase, cur) == 0)
return -EBUSY;
- /* Set bit 0, so that mutex_unlock will know that the mutex is claimed.
- Hold the nklock, for mutual exclusion with slow mutex_unlock. */
- xnlock_get_irqsave(&nklock, s);
- if (test_claimed(ownerh)) {
- old = xnarch_atomic_get(mutex->owner);
- goto test_no_owner;
- }
- do {
- old = xnarch_atomic_cmpxchg(mutex->owner, ownerh,
- set_claimed(ownerh, 1));
- if (likely(old == ownerh))
- break;
- test_no_owner:
- if (old == XN_NO_HANDLE) {
- /* Owner called fast mutex_unlock
- (on another cpu) */
- xnlock_put_irqrestore(&nklock, s);
- goto retry_lock;
- }
- ownerh = old;
- } while (!test_claimed(ownerh));
-
- owner = xnthread_lookup(clear_claimed(ownerh));
-
- if (unlikely(!owner)) {
- err = -EINVAL;
- goto error;
- }
-
- xnsynch_set_owner(&mutex->synchbase, owner);
- ++mutex->sleepers;
if (timed)
xnsynch_acquire(&mutex->synchbase, abs_to, XN_REALTIME);
else
xnsynch_acquire(&mutex->synchbase, XN_INFINITE, XN_RELATIVE);
- --mutex->sleepers;
- if (xnthread_test_info(cur, XNBREAK)) {
- err = -EINTR;
- goto error;
- }
- if (xnthread_test_info(cur, XNRMID)) {
- err = -EINVAL;
- goto error;
- }
- if (xnthread_test_info(cur, XNTIMEO)) {
- err = -ETIMEDOUT;
- goto error;
+ if (unlikely(xnthread_test_info(cur, XNBREAK | XNRMID | XNTIMEO))) {
+ if (xnthread_test_info(cur, XNBREAK))
+ return -EINTR;
+ else if (xnthread_test_info(cur, XNTIMEO))
+ return -ETIMEDOUT;
+ else /* XNRMID */
+ return -EINVAL;
}
- ownerh = set_claimed(xnthread_handle(cur), mutex->sleepers);
- xnarch_atomic_set(mutex->owner, ownerh);
shadow->lockcnt = count;
- xnlock_put_irqrestore(&nklock, s);
return 0;
-
- error:
- if (!mutex->sleepers)
- xnarch_atomic_set
- (mutex->owner,
- clear_claimed(xnarch_atomic_get(mutex->owner)));
- xnlock_put_irqrestore(&nklock, s);
- return err;
-}
-
-static inline void pse51_mutex_unlock_internal(xnthread_t *cur,
- pse51_mutex_t *mutex)
-{
- xnhandle_t ownerh;
- xnthread_t *owner;
- spl_t s;
-
- if (likely(xnarch_atomic_cmpxchg(mutex->owner, cur, XN_NO_HANDLE) ==
- xnthread_handle(cur)))
- return;
-
- xnlock_get_irqsave(&nklock, s);
- owner = xnsynch_release(&mutex->synchbase);
- ownerh = set_claimed(xnthread_handle(owner), mutex->sleepers);
- xnarch_atomic_set(mutex->owner, ownerh);
- if (owner)
- xnpod_schedule();
- xnlock_put_irqrestore(&nklock, s);
}
#endif /* __KERNEL__ */
Index: b/ksrc/skins/posix/syscall.c
===================================================================
--- a/ksrc/skins/posix/syscall.c
+++ b/ksrc/skins/posix/syscall.c
@@ -1060,13 +1060,10 @@ static int __pthread_mutex_unlock(struct
mutex = shadow->mutex;
- if (clear_claimed(xnarch_atomic_get(mutex->owner)) !=
- xnthread_handle(cur)) {
- err = -EPERM;
+ err = (xnsynch_owner(&mutex->synchbase) == cur) ? 0 : -EPERM;
+ if (err)
goto out;
- }
- err = 0;
if (shadow->lockcnt > 1) {
/* Mutex is recursive */
--shadow->lockcnt;
@@ -1080,8 +1077,9 @@ static int __pthread_mutex_unlock(struct
return 0;
}
-
- pse51_mutex_unlock_internal(cur, mutex);
+
+ if (xnsynch_release(&mutex->synchbase))
+ xnpod_schedule();
out:
cb_read_unlock(&shadow->lock, s);
@@ -1186,13 +1184,11 @@ static int __pthread_mutex_destroy(struc
if (pse51_kqueues(mutex->attr.pshared) != mutex->owningq)
return -EPERM;
- if (xnarch_atomic_get(mutex->owner) != XN_NO_HANDLE)
+ if (xnsynch_fast_owner_check(mutex->synchbase.fastlock,
+ XN_NO_HANDLE) != 0)
return -EBUSY;
pse51_mark_deleted(shadow);
- if (!mutex->attr.pshared)
- xnheap_free(&xnsys_ppd_get(mutex->attr.pshared)->sem_heap,
- mutex->owner);
pse51_mutex_destroy_internal(mutex, mutex->owningq);
return __xn_safe_copy_to_user((void __user *)&umx->shadow_mutex,
@@ -1262,7 +1258,6 @@ static int __pthread_mutex_timedlock(str
static int __pthread_mutex_unlock(struct pt_regs *regs)
{
- xnthread_t *cur = xnpod_current_thread();
union __xeno_mutex mx, *umx;
if (xnpod_root_p())
@@ -1275,7 +1270,8 @@ static int __pthread_mutex_unlock(struct
offsetof(struct __shadow_mutex, lock)))
return -EFAULT;
- pse51_mutex_unlock_internal(cur, mx.shadow_mutex.mutex);
+ if (xnsynch_release(&mx.shadow_mutex.mutex->synchbase))
+ xnpod_schedule();
return 0;
}
Index: b/src/skins/posix/mutex.c
===================================================================
--- a/src/skins/posix/mutex.c
+++ b/src/skins/posix/mutex.c
@@ -19,6 +19,7 @@
#include <errno.h>
#include <pthread.h>
#include <limits.h>
+#include <nucleus/synch.h>
#include <posix/mutex.h>
#include <posix/syscall.h>
#include <posix/cb_lock.h>
@@ -146,10 +147,10 @@ int __wrap_pthread_mutex_lock(pthread_mu
{
union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
- int err = 0;
+ int err;
#ifdef CONFIG_XENO_FASTSYNCH
- xnhandle_t cur, owner;
+ xnhandle_t cur;
cur = xeno_get_current();
if (cur == XN_NO_HANDLE)
@@ -163,14 +164,15 @@ int __wrap_pthread_mutex_lock(pthread_mu
goto out;
}
- owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
- if (likely(owner == XN_NO_HANDLE)) {
+ err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
+
+ if (likely(!err)) {
shadow->lockcnt = 1;
cb_read_unlock(&shadow->lock, s);
return 0;
}
- if (clear_claimed(owner) == cur)
+ if (err == -EBUSY)
switch(shadow->attr.type) {
case PTHREAD_MUTEX_NORMAL:
break;
@@ -184,8 +186,8 @@ int __wrap_pthread_mutex_lock(pthread_mu
err = -EAGAIN;
goto out;
}
-
++shadow->lockcnt;
+ err = 0;
goto out;
}
#endif /* CONFIG_XENO_FASTSYNCH */
@@ -207,10 +209,10 @@ int __wrap_pthread_mutex_timedlock(pthre
{
union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
- int err = 0;
+ int err;
#ifdef CONFIG_XENO_FASTSYNCH
- xnhandle_t cur, owner;
+ xnhandle_t cur;
cur = xeno_get_current();
if (cur == XN_NO_HANDLE)
@@ -224,14 +226,15 @@ int __wrap_pthread_mutex_timedlock(pthre
goto out;
}
- owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
- if (likely(owner == XN_NO_HANDLE)) {
+ err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
+
+ if (likely(!err)) {
shadow->lockcnt = 1;
cb_read_unlock(&shadow->lock, s);
return 0;
}
- if (clear_claimed(owner) == cur)
+ if (err == -EBUSY)
switch(shadow->attr.type) {
case PTHREAD_MUTEX_NORMAL:
break;
@@ -268,10 +271,10 @@ int __wrap_pthread_mutex_trylock(pthread
{
union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
- int err = 0;
+ int err;
#ifdef CONFIG_XENO_FASTSYNCH
- xnhandle_t cur, owner;
+ xnhandle_t cur;
cur = xeno_get_current();
if (cur == XN_NO_HANDLE)
@@ -285,23 +288,23 @@ int __wrap_pthread_mutex_trylock(pthread
goto out;
}
- owner = xnarch_atomic_cmpxchg(get_ownerp(shadow), XN_NO_HANDLE, cur);
- if (likely(owner == XN_NO_HANDLE)) {
+ err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
+
+ if (likely(!err)) {
shadow->lockcnt = 1;
cb_read_unlock(&shadow->lock, s);
return 0;
}
- err = -EBUSY;
- if (clear_claimed(owner) == cur
- && shadow->attr.type == PTHREAD_MUTEX_RECURSIVE) {
+ if (err == -EBUSY && shadow->attr.type == PTHREAD_MUTEX_RECURSIVE) {
if (shadow->lockcnt == UINT_MAX)
err = -EAGAIN;
else {
++shadow->lockcnt;
err = 0;
}
- }
+ } else
+ err = -EBUSY;
out:
cb_read_unlock(&shadow->lock, s);
@@ -322,11 +325,11 @@ int __wrap_pthread_mutex_unlock(pthread_
{
union __xeno_mutex *_mutex = (union __xeno_mutex *)mutex;
struct __shadow_mutex *shadow = &_mutex->shadow_mutex;
- int err = 0;
+ int err;
#ifdef CONFIG_XENO_FASTSYNCH
xnarch_atomic_t *ownerp;
- xnhandle_t cur, owner;
+ xnhandle_t cur;
cur = xeno_get_current();
if (cur == XN_NO_HANDLE)
@@ -341,19 +344,17 @@ int __wrap_pthread_mutex_unlock(pthread_
}
ownerp = get_ownerp(shadow);
- owner = clear_claimed(xnarch_atomic_get(ownerp));
- if (unlikely(owner != cur)) {
- err = -EPERM;
+
+ err = xnsynch_fast_owner_check(ownerp, cur);
+ if (unlikely(err))
goto out_err;
- }
- err = 0;
if (shadow->lockcnt > 1) {
--shadow->lockcnt;
goto out;
}
- if (likely(xnarch_atomic_cmpxchg(ownerp, cur, XN_NO_HANDLE) == cur)) {
+ if (likely(xnsynch_fast_release(ownerp, cur))) {
out:
cb_read_unlock(&shadow->lock, s);
return 0;
^ permalink raw reply [flat|nested] 17+ messages in thread* [Xenomai-core] [PATCH 09/13] Use fast xnsynch with native skin
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (7 preceding siblings ...)
2008-10-17 15:46 ` [Xenomai-core] [PATCH 08/13] Convert POSIX skin to fast xnsynch Jan Kiszka
@ 2008-10-17 15:46 ` Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 10/13] Optionally replace pthread_getspecific with TLS variables Jan Kiszka
` (6 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:46 UTC (permalink / raw)
To: xenomai; +Cc: Jan Kiszka
Implement a fast path for rt_mutex_acquire/release, making use of fast
xnsynch services. Just as for the POSIX skin, lock stealing via trylock
is sacrificed for a syscall-less user space implementation.
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
include/native/mutex.h | 23 ++-
ksrc/skins/native/cond.c | 11 -
ksrc/skins/native/mutex.c | 298 ++++++++++++++++++++++++++------------------
ksrc/skins/native/syscall.c | 70 ++++++++--
src/skins/native/cond.c | 30 ++++
src/skins/native/mutex.c | 102 +++++++++++++--
6 files changed, 382 insertions(+), 152 deletions(-)
Index: b/include/native/mutex.h
===================================================================
--- a/include/native/mutex.h
+++ b/include/native/mutex.h
@@ -32,7 +32,7 @@ struct rt_task;
*/
typedef struct rt_mutex_info {
- int lockcnt; /**< Lock nesting level (> 0 means "locked"). */
+ int locked; /**< > 0 if mutex is locked. */
int nwaiters; /**< Number of pending tasks. */
@@ -44,7 +44,15 @@ typedef struct rt_mutex_info {
} RT_MUTEX_INFO;
typedef struct rt_mutex_placeholder {
+
xnhandle_t opaque;
+
+#ifdef CONFIG_XENO_FASTSYNCH
+ xnarch_atomic_t *fastlock;
+
+ int lockcnt;
+#endif /* CONFIG_XENO_FASTSYNCH */
+
} RT_MUTEX_PLACEHOLDER;
#if (defined(__KERNEL__) || defined(__XENO_SIM__)) && !defined(DOXYGEN_CPP)
@@ -54,6 +62,8 @@ typedef struct rt_mutex_placeholder {
#define XENO_MUTEX_MAGIC 0x55550505
+#define RT_MUTEX_EXPORTED XNSYNCH_SPARE0 /* Mutex registered by name */
+
typedef struct __rt_mutex {
unsigned magic; /* !< Magic code - must be first */
@@ -74,7 +84,7 @@ typedef struct __rt_mutex {
#define rlink2mutex(ln) container_of(ln, RT_MUTEX, rlink)
- xnqueue_t *rqueue; /* !< Backpointer to resource queue. */
+ xnqueue_t *rqueue; /* !< Backpointer to resource queue. */
} RT_MUTEX;
@@ -93,9 +103,8 @@ static inline void __native_mutex_flush_
xeno_flush_rq(RT_MUTEX, rq, mutex);
}
-int rt_mutex_acquire_inner(RT_MUTEX *mutex,
- xntmode_t timeout_mode,
- RTIME timeout);
+int rt_mutex_acquire_inner(RT_MUTEX *mutex, RTIME timeout,
+ xntmode_t timeout_mode);
#else /* !CONFIG_XENO_OPT_NATIVE_MUTEX */
@@ -138,6 +147,10 @@ static inline int rt_mutex_unbind (RT_MU
extern "C" {
#endif
+int rt_mutex_create_inner(RT_MUTEX *mutex, const char *name,
+ xnarch_atomic_t *fastlock);
+int rt_mutex_delete_inner(RT_MUTEX *mutex);
+
/* Public interface. */
int rt_mutex_create(RT_MUTEX *mutex,
Index: b/ksrc/skins/native/cond.c
===================================================================
--- a/ksrc/skins/native/cond.c
+++ b/ksrc/skins/native/cond.c
@@ -378,7 +378,7 @@ int rt_cond_broadcast(RT_COND *cond)
int rt_cond_wait_inner(RT_COND *cond, RT_MUTEX *mutex,
xntmode_t timeout_mode, RTIME timeout)
{
- int err = 0, kicked = 0;
+ int err, kicked = 0;
xnthread_t *thread;
int lockcnt;
spl_t s;
@@ -407,15 +407,14 @@ int rt_cond_wait_inner(RT_COND *cond, RT
thread = xnpod_current_thread();
- if (thread != xnsynch_owner(&mutex->synch_base)) {
- err = -EPERM;
+ err = xnsynch_owner_check(&mutex->synch_base, thread);
+
+ if (err)
goto unlock_and_exit;
- }
/*
* We can't use rt_mutex_release since that might reschedule
- * before enter xnsynch_sleep_on, hence most of the code is
- * duplicated here.
+ * before enter xnsynch_sleep_on.
*/
lockcnt = mutex->lockcnt; /* Leave even if mutex is nested */
Index: b/ksrc/skins/native/mutex.c
===================================================================
--- a/ksrc/skins/native/mutex.c
+++ b/ksrc/skins/native/mutex.c
@@ -57,29 +57,42 @@ static int __mutex_read_proc(char *page,
off_t off, int count, int *eof, void *data)
{
RT_MUTEX *mutex = (RT_MUTEX *)data;
+#ifdef CONFIG_XENO_FASTSYNCH
+ xnhandle_t lock_state;
+#endif /* CONFIG_XENO_FASTSYNCH */
+ xnthread_t *owner;
char *p = page;
int len;
spl_t s;
xnlock_get_irqsave(&nklock, s);
- if (xnsynch_owner(&mutex->synch_base) != NULL) {
- xnpholder_t *holder;
+#ifndef CONFIG_XENO_FASTSYNCH
+ owner = xnsynch_owner(&mutex->synch_base);
+#else /* CONFIG_XENO_FASTSYNCH */
+ lock_state = xnarch_atomic_get(mutex->synch_base.fastlock);
+
+ owner = (lock_state == XN_NO_HANDLE) ? NULL :
+ xnthread_lookup(xnsynch_fast_mask_claimed(lock_state));
+ if (!owner && lock_state != XN_NO_HANDLE)
+ p += sprintf(p, "=<DAMAGED HANDLE!>");
+ else
+#endif /* CONFIG_XENO_FASTSYNCH */
+ if (owner) {
/* Locked mutex -- dump owner and waiters, if any. */
+ xnpholder_t *holder;
- p += sprintf(p, "=locked by %s depth=%d\n",
- xnthread_name(xnsynch_owner(&mutex->synch_base)),
- mutex->lockcnt);
+ p += sprintf(p, "=locked by %s\n", xnthread_name(owner));
holder = getheadpq(xnsynch_wait_queue(&mutex->synch_base));
while (holder) {
xnthread_t *sleeper = link2thread(holder, plink);
+
p += sprintf(p, "+%s\n", xnthread_name(sleeper));
- holder =
- nextpq(xnsynch_wait_queue(&mutex->synch_base),
- holder);
+ holder = nextpq(xnsynch_wait_queue(&mutex->synch_base),
+ holder);
}
} else
/* Mutex unlocked. */
@@ -120,49 +133,8 @@ static xnpnode_t __mutex_pnode = {
#endif /* CONFIG_XENO_EXPORT_REGISTRY */
-/**
- * @fn int rt_mutex_create(RT_MUTEX *mutex,const char *name)
- *
- * @brief Create a mutex.
- *
- * Create a mutual exclusion object that allows multiple tasks to
- * synchronize access to a shared resource. A mutex is left in an
- * unlocked state after creation.
- *
- * @param mutex The address of a mutex descriptor Xenomai will use to
- * store the mutex-related data. This descriptor must always be valid
- * while the mutex is active therefore it must be allocated in
- * permanent memory.
- *
- * @param name An ASCII string standing for the symbolic name of the
- * mutex. When non-NULL and non-empty, this string is copied to a safe
- * place into the descriptor, and passed to the registry package if
- * enabled for indexing the created mutex.
- *
- * @return 0 is returned upon success. Otherwise:
- *
- * - -ENOMEM is returned if the system fails to get enough dynamic
- * memory from the global real-time heap in order to register the
- * mutex.
- *
- * - -EEXIST is returned if the @a name is already in use by some
- * registered object.
- *
- * - -EPERM is returned if this service was called from an
- * asynchronous context.
- *
- * Environments:
- *
- * This service can be called from:
- *
- * - Kernel module initialization/cleanup code
- * - Kernel-based task
- * - User-space task
- *
- * Rescheduling: possible.
- */
-
-int rt_mutex_create(RT_MUTEX *mutex, const char *name)
+int rt_mutex_create_inner(RT_MUTEX *mutex, const char *name,
+ xnarch_atomic_t *fastlock)
{
int err = 0;
spl_t s;
@@ -171,7 +143,7 @@ int rt_mutex_create(RT_MUTEX *mutex, con
return -EPERM;
xnsynch_init(&mutex->synch_base,
- XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER, NULL);
+ XNSYNCH_PRIO | XNSYNCH_PIP | XNSYNCH_OWNER, fastlock);
mutex->handle = 0; /* i.e. (still) unregistered mutex. */
mutex->magic = XENO_MUTEX_MAGIC;
mutex->lockcnt = 0;
@@ -196,7 +168,7 @@ int rt_mutex_create(RT_MUTEX *mutex, con
&__mutex_pnode);
if (err)
- rt_mutex_delete(mutex);
+ rt_mutex_delete_inner(mutex);
}
#endif /* CONFIG_XENO_OPT_REGISTRY */
@@ -204,22 +176,32 @@ int rt_mutex_create(RT_MUTEX *mutex, con
}
/**
- * @fn int rt_mutex_delete(RT_MUTEX *mutex)
+ * @fn int rt_mutex_create(RT_MUTEX *mutex,const char *name)
*
- * @brief Delete a mutex.
+ * @brief Create a mutex.
*
- * Destroy a mutex and release all the tasks currently pending on it.
- * A mutex exists in the system since rt_mutex_create() has been
- * called to create it, so this service must be called in order to
- * destroy it afterwards.
+ * Create a mutual exclusion object that allows multiple tasks to
+ * synchronize access to a shared resource. A mutex is left in an
+ * unlocked state after creation.
*
- * @param mutex The descriptor address of the affected mutex.
+ * @param mutex The address of a mutex descriptor Xenomai will use to
+ * store the mutex-related data. This descriptor must always be valid
+ * while the mutex is active therefore it must be allocated in
+ * permanent memory.
+ *
+ * @param name An ASCII string standing for the symbolic name of the
+ * mutex. When non-NULL and non-empty, this string is copied to a safe
+ * place into the descriptor, and passed to the registry package if
+ * enabled for indexing the created mutex.
*
* @return 0 is returned upon success. Otherwise:
*
- * - -EINVAL is returned if @a mutex is not a mutex descriptor.
+ * - -ENOMEM is returned if the system fails to get enough dynamic
+ * memory from the global real-time heap in order to register the
+ * mutex.
*
- * - -EIDRM is returned if @a mutex is a deleted mutex descriptor.
+ * - -EEXIST is returned if the @a name is already in use by some
+ * registered object.
*
* - -EPERM is returned if this service was called from an
* asynchronous context.
@@ -235,7 +217,30 @@ int rt_mutex_create(RT_MUTEX *mutex, con
* Rescheduling: possible.
*/
-int rt_mutex_delete(RT_MUTEX *mutex)
+int rt_mutex_create(RT_MUTEX *mutex, const char *name)
+{
+ xnarch_atomic_t *fastlock = NULL;
+ int err;
+
+#ifdef CONFIG_XENO_FASTSYNCH
+ /* Allocate lock memory for in-kernel use */
+ fastlock = xnmalloc(sizeof(xnarch_atomic_t));
+
+ if (!fastlock)
+ return -ENOMEM;
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+ err = rt_mutex_create_inner(mutex, name, fastlock);
+
+#ifdef CONFIG_XENO_FASTSYNCH
+ if (err)
+ xnfree(fastlock);
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+ return err;
+}
+
+int rt_mutex_delete_inner(RT_MUTEX *mutex)
{
int err = 0, rc;
spl_t s;
@@ -275,59 +280,109 @@ int rt_mutex_delete(RT_MUTEX *mutex)
return err;
}
-int rt_mutex_acquire_inner(RT_MUTEX *mutex, xntmode_t timeout_mode, RTIME timeout)
+/**
+ * @fn int rt_mutex_delete(RT_MUTEX *mutex)
+ *
+ * @brief Delete a mutex.
+ *
+ * Destroy a mutex and release all the tasks currently pending on it.
+ * A mutex exists in the system since rt_mutex_create() has been
+ * called to create it, so this service must be called in order to
+ * destroy it afterwards.
+ *
+ * @param mutex The descriptor address of the affected mutex.
+ *
+ * @return 0 is returned upon success. Otherwise:
+ *
+ * - -EINVAL is returned if @a mutex is not a mutex descriptor.
+ *
+ * - -EIDRM is returned if @a mutex is a deleted mutex descriptor.
+ *
+ * - -EPERM is returned if this service was called from an
+ * asynchronous context.
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Kernel-based task
+ * - User-space task
+ *
+ * Rescheduling: possible.
+ */
+
+int rt_mutex_delete(RT_MUTEX *mutex)
+{
+ int err;
+
+ err = rt_mutex_delete_inner(mutex);
+
+#ifdef CONFIG_XENO_FASTSYNCH
+ if (!err)
+ xnfree(mutex->synch_base.fastlock);
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+ return err;
+}
+
+int rt_mutex_acquire_inner(RT_MUTEX *mutex, RTIME timeout,
+ xntmode_t timeout_mode)
{
xnthread_t *thread;
- int err = 0;
- spl_t s;
if (xnpod_unblockable_p())
return -EPERM;
- xnlock_get_irqsave(&nklock, s);
-
mutex = xeno_h2obj_validate(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
- if (!mutex) {
- err = xeno_handle_error(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
- goto unlock_and_exit;
- }
+ if (!mutex)
+ return xeno_handle_error(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
thread = xnpod_current_thread();
- if (xnsynch_owner(&mutex->synch_base) == NULL) {
- xnsynch_set_owner(&mutex->synch_base, thread);
- goto grab_mutex;
- }
-
- if (xnsynch_owner(&mutex->synch_base) == thread) {
+ if (xnsynch_owner_check(&mutex->synch_base, thread) == 0) {
mutex->lockcnt++;
- goto unlock_and_exit;
+ return 0;
}
- if (timeout == TM_NONBLOCK) {
- err = -EWOULDBLOCK;
- goto unlock_and_exit;
+ if (timeout == TM_NONBLOCK && timeout_mode == XN_RELATIVE) {
+#ifdef CONFIG_XENO_FASTSYNCH
+ if (xnsynch_fast_acquire(mutex->synch_base.fastlock,
+ xnthread_handle(thread)) == 0) {
+ mutex->lockcnt = 1;
+ return 0;
+ } else
+ return -EWOULDBLOCK;
+
+#else /* !CONFIG_XENO_FASTSYNCH */
+ int err = 0;
+ spl_t s;
+
+ xnlock_get_irqsave(&nklock, s);
+ if (xnsynch_owner(&mutex->synch_base) == NULL)
+ mutex->lockcnt = 1;
+ else
+ err = -EWOULDBLOCK;
+ xnlock_put_irqrestore(&nklock, s);
+ return err;
+#endif /* !CONFIG_XENO_FASTSYNCH */
}
xnsynch_acquire(&mutex->synch_base, timeout, timeout_mode);
- if (xnthread_test_info(thread, XNRMID))
- err = -EIDRM; /* Mutex deleted while pending. */
- else if (xnthread_test_info(thread, XNTIMEO))
- err = -ETIMEDOUT; /* Timeout. */
- else if (xnthread_test_info(thread, XNBREAK))
- err = -EINTR; /* Unblocked. */
- else {
- grab_mutex:
- mutex->lockcnt = 1;
+ if (unlikely(xnthread_test_info(thread, XNBREAK | XNRMID | XNTIMEO))) {
+ if (xnthread_test_info(thread, XNBREAK))
+ return -EINTR;
+ else if (xnthread_test_info(thread, XNTIMEO))
+ return -ETIMEDOUT;
+ else /* XNRMID */
+ return -EIDRM;
}
- unlock_and_exit:
-
- xnlock_put_irqrestore(&nklock, s);
+ mutex->lockcnt = 1;
- return err;
+ return 0;
}
/**
@@ -396,7 +451,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);
}
/**
@@ -462,7 +517,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);
}
/**
@@ -499,37 +554,28 @@ int rt_mutex_acquire_until(RT_MUTEX *mut
int rt_mutex_release(RT_MUTEX *mutex)
{
- int err = 0;
- spl_t s;
+ xnthread_t *thread = xnpod_current_thread();
+ int err;
if (xnpod_unblockable_p())
return -EPERM;
- xnlock_get_irqsave(&nklock, s);
-
mutex = xeno_h2obj_validate(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
- if (!mutex) {
- err = xeno_handle_error(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
- goto unlock_and_exit;
- }
+ if (!mutex)
+ return xeno_handle_error(mutex, XENO_MUTEX_MAGIC, RT_MUTEX);
- if (xnpod_current_thread() != xnsynch_owner(&mutex->synch_base)) {
- err = -EPERM;
- goto unlock_and_exit;
- }
+ err = xnsynch_owner_check(&mutex->synch_base, thread);
+ if (err)
+ return err;
if (--mutex->lockcnt > 0)
- goto unlock_and_exit;
+ return 0;
if (xnsynch_release(&mutex->synch_base))
xnpod_schedule();
- unlock_and_exit:
-
- xnlock_put_irqrestore(&nklock, s);
-
- return err;
+ return 0;
}
/**
@@ -565,6 +611,10 @@ int rt_mutex_release(RT_MUTEX *mutex)
int rt_mutex_inquire(RT_MUTEX *mutex, RT_MUTEX_INFO *info)
{
+#ifdef CONFIG_XENO_FASTSYNCH
+ xnhandle_t lock_state;
+#endif /* CONFIG_XENO_FASTSYNCH */
+ xnthread_t *owner;
int err = 0;
spl_t s;
@@ -578,11 +628,21 @@ int rt_mutex_inquire(RT_MUTEX *mutex, RT
}
strcpy(info->name, mutex->name);
- info->lockcnt = mutex->lockcnt;
info->nwaiters = xnsynch_nsleepers(&mutex->synch_base);
- if (xnsynch_owner(&mutex->synch_base))
- strcpy(info->owner,
- xnthread_name(xnsynch_owner(&mutex->synch_base)));
+
+#ifndef CONFIG_XENO_FASTSYNCH
+ owner = xnsynch_owner(&mutex->synch_base);
+#else /* CONFIG_XENO_FASTSYNCH */
+ lock_state = xnarch_atomic_get(mutex->synch_base.fastlock);
+ info->locked = (lock_state != XN_NO_HANDLE);
+ owner = (info->locked) ?
+ xnthread_lookup(xnsynch_fast_mask_claimed(lock_state)) : NULL;
+ if (!owner && info->locked)
+ strcpy(info->owner, "<DAMAGED HANDLE!>");
+ else
+#endif /* CONFIG_XENO_FASTSYNCH */
+ if (owner)
+ strcpy(info->owner, xnthread_name(owner));
else
info->owner[0] = 0;
Index: b/ksrc/skins/native/syscall.c
===================================================================
--- a/ksrc/skins/native/syscall.c
+++ b/ksrc/skins/native/syscall.c
@@ -24,6 +24,7 @@
#include <nucleus/heap.h>
#include <nucleus/shadow.h>
#include <nucleus/registry.h>
+#include <nucleus/sys_ppd.h>
#include <native/syscall.h>
#include <native/task.h>
#include <native/timer.h>
@@ -1532,6 +1533,8 @@ static int __rt_event_inquire(struct pt_
static int __rt_mutex_create(struct pt_regs *regs)
{
char name[XNOBJECT_NAME_LEN];
+ xnarch_atomic_t *fastlock = NULL;
+ xnheap_t *sem_heap;
RT_MUTEX_PLACEHOLDER ph;
RT_MUTEX *mutex;
int err;
@@ -1546,22 +1549,45 @@ static int __rt_mutex_create(struct pt_r
} else
*name = '\0';
+ sem_heap = &xnsys_ppd_get(*name != '\0')->sem_heap;
+
mutex = (RT_MUTEX *)xnmalloc(sizeof(*mutex));
if (!mutex)
return -ENOMEM;
- err = rt_mutex_create(mutex, name);
+#ifdef CONFIG_XENO_FASTSYNCH
+ fastlock = xnheap_alloc(sem_heap, sizeof(xnarch_atomic_t));
+
+ if (!fastlock) {
+ xnfree(mutex);
+ return -ENOMEM;
+ }
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+ err = rt_mutex_create_inner(mutex, name, fastlock);
if (err == 0) {
mutex->cpid = current->pid;
/* Copy back the registry handle to the ph struct. */
ph.opaque = mutex->handle;
+#ifdef CONFIG_XENO_FASTSYNCH
+ /* The lock address will be finished in user space. */
+ ph.fastlock =
+ (void *)xnheap_mapped_offset(sem_heap, fastlock);
+ if (*name != '\0')
+ xnsynch_set_flags(&mutex->synch_base,
+ RT_MUTEX_EXPORTED);
+#endif /* CONFIG_XENO_FASTSYNCH */
if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg1(regs), &ph,
sizeof(ph)))
err = -EFAULT;
- } else
+ } else {
+#ifdef CONFIG_XENO_FASTSYNCH
+ xnheap_free(&xnsys_ppd_get(*name != '\0')->sem_heap, fastlock);
+#endif /* CONFIG_XENO_FASTSYNCH */
xnfree(mutex);
+ }
return err;
}
@@ -1575,15 +1601,22 @@ static int __rt_mutex_create(struct pt_r
static int __rt_mutex_bind(struct pt_regs *regs)
{
RT_MUTEX_PLACEHOLDER ph;
+ RT_MUTEX *mutex;
int err;
err =
__rt_bind_helper(current, regs, &ph.opaque, XENO_MUTEX_MAGIC,
- NULL, 0);
+ (void **)&mutex, 0);
if (err)
return err;
+#ifdef CONFIG_XENO_FASTSYNCH
+ ph.fastlock =
+ (void *)xnheap_mapped_offset(&xnsys_ppd_get(1)->sem_heap,
+ mutex->synch_base.fastlock);
+#endif /* CONFIG_XENO_FASTSYNCH */
+
if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg1(regs), &ph,
sizeof(ph)))
return -EFAULT;
@@ -1610,10 +1643,17 @@ static int __rt_mutex_delete(struct pt_r
if (!mutex)
return -ESRCH;
- err = rt_mutex_delete(mutex);
+ err = rt_mutex_delete_inner(mutex);
- if (!err && mutex->cpid)
+ if (!err && mutex->cpid) {
+#ifdef CONFIG_XENO_FASTSYNCH
+ int global = xnsynch_test_flags(&mutex->synch_base,
+ RT_MUTEX_EXPORTED);
+ xnheap_free(&xnsys_ppd_get(global)->sem_heap,
+ mutex->synch_base.fastlock);
+#endif /* CONFIG_XENO_FASTSYNCH */
xnfree(mutex);
+ }
return err;
}
@@ -1626,13 +1666,14 @@ static int __rt_mutex_delete(struct pt_r
static int __rt_mutex_acquire(struct pt_regs *regs)
{
- RT_MUTEX_PLACEHOLDER ph;
+ RT_MUTEX_PLACEHOLDER __user *ph;
xntmode_t timeout_mode;
+ xnhandle_t mutexh;
RT_MUTEX *mutex;
RTIME timeout;
- if (__xn_safe_copy_from_user(&ph, (void __user *)__xn_reg_arg1(regs),
- sizeof(ph)))
+ ph = (RT_MUTEX_PLACEHOLDER __user *)__xn_reg_arg1(regs);
+ if (__xn_safe_copy_from_user(&mutexh, &ph->opaque, sizeof(mutexh)))
return -EFAULT;
timeout_mode = __xn_reg_arg2(regs);
@@ -1641,12 +1682,12 @@ static int __rt_mutex_acquire(struct pt_
sizeof(timeout)))
return -EFAULT;
- mutex = (RT_MUTEX *)xnregistry_fetch(ph.opaque);
+ mutex = (RT_MUTEX *)xnregistry_fetch(mutexh);
if (!mutex)
return -ESRCH;
- return rt_mutex_acquire_inner(mutex, timeout_mode, timeout);
+ return rt_mutex_acquire_inner(mutex, timeout, timeout_mode);
}
/*
@@ -1655,14 +1696,15 @@ static int __rt_mutex_acquire(struct pt_
static int __rt_mutex_release(struct pt_regs *regs)
{
- RT_MUTEX_PLACEHOLDER ph;
+ RT_MUTEX_PLACEHOLDER __user *ph;
+ xnhandle_t mutexh;
RT_MUTEX *mutex;
- if (__xn_safe_copy_from_user(&ph, (void __user *)__xn_reg_arg1(regs),
- sizeof(ph)))
+ ph = (RT_MUTEX_PLACEHOLDER __user *)__xn_reg_arg1(regs);
+ if (__xn_safe_copy_from_user(&mutexh, &ph->opaque, sizeof(mutexh)))
return -EFAULT;
- mutex = (RT_MUTEX *)xnregistry_fetch(ph.opaque);
+ mutex = (RT_MUTEX *)xnregistry_fetch(mutexh);
if (!mutex)
return -ESRCH;
Index: b/src/skins/native/cond.c
===================================================================
--- a/src/skins/native/cond.c
+++ b/src/skins/native/cond.c
@@ -41,16 +41,46 @@ int rt_cond_delete(RT_COND *cond)
int rt_cond_wait(RT_COND *cond, RT_MUTEX *mutex, RTIME timeout)
{
+#ifdef CONFIG_XENO_FASTSYNCH
+ int saved_lockcnt, err;
+
+ saved_lockcnt = mutex->lockcnt;
+
+ err = XENOMAI_SKINCALL4(__native_muxid,
+ __native_cond_wait, cond, mutex,
+ XN_RELATIVE, &timeout);
+
+ mutex->lockcnt = saved_lockcnt;
+
+ return err;
+
+#else /* !CONFIG_XENO_FASTSYNCH */
return XENOMAI_SKINCALL4(__native_muxid,
__native_cond_wait, cond, mutex,
XN_RELATIVE, &timeout);
+#endif /* !CONFIG_XENO_FASTSYNCH */
}
int rt_cond_wait_until(RT_COND *cond, RT_MUTEX *mutex, RTIME timeout)
{
+#ifdef CONFIG_XENO_FASTSYNCH
+ int saved_lockcnt, err;
+
+ saved_lockcnt = mutex->lockcnt;
+
+ err = XENOMAI_SKINCALL4(__native_muxid,
+ __native_cond_wait, cond, mutex,
+ XN_REALTIME, &timeout);
+
+ mutex->lockcnt = saved_lockcnt;
+
+ return err;
+
+#else /* !CONFIG_XENO_FASTSYNCH */
return XENOMAI_SKINCALL4(__native_muxid,
__native_cond_wait, cond, mutex,
XN_REALTIME, &timeout);
+#endif /* !CONFIG_XENO_FASTSYNCH */
}
int rt_cond_signal(RT_COND *cond)
Index: b/src/skins/native/mutex.c
===================================================================
--- a/src/skins/native/mutex.c
+++ b/src/skins/native/mutex.c
@@ -16,21 +16,51 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
+#include <limits.h>
+#include <nucleus/synch.h>
#include <native/syscall.h>
#include <native/mutex.h>
+#include <asm-generic/bits/current.h>
extern int __native_muxid;
+extern unsigned long xeno_sem_heap[2];
int rt_mutex_create(RT_MUTEX *mutex, const char *name)
{
- return XENOMAI_SKINCALL2(__native_muxid,
- __native_mutex_create, mutex, name);
+ int err;
+
+ err = XENOMAI_SKINCALL2(__native_muxid,
+ __native_mutex_create, mutex, name);
+
+#ifdef CONFIG_XENO_FASTSYNCH
+ if (!err) {
+ mutex->fastlock = (xnarch_atomic_t *)
+ (xeno_sem_heap[(name && *name) ? 1 : 0] +
+ (unsigned long)mutex->fastlock);
+ mutex->lockcnt = 0;
+ }
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+ return err;
}
int rt_mutex_bind(RT_MUTEX *mutex, const char *name, RTIME timeout)
{
- return XENOMAI_SKINCALL3(__native_muxid,
- __native_mutex_bind, mutex, name, &timeout);
+ int err;
+
+ err = XENOMAI_SKINCALL3(__native_muxid,
+ __native_mutex_bind, mutex, name, &timeout);
+
+#ifdef CONFIG_XENO_FASTSYNCH
+ if (!err) {
+ mutex->fastlock = (xnarch_atomic_t *)
+ (xeno_sem_heap[(name && *name) ? 1 : 0] +
+ (unsigned long)mutex->fastlock);
+ mutex->lockcnt = 0;
+ }
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+ return err;
}
int rt_mutex_delete(RT_MUTEX *mutex)
@@ -38,20 +68,76 @@ int rt_mutex_delete(RT_MUTEX *mutex)
return XENOMAI_SKINCALL1(__native_muxid, __native_mutex_delete, mutex);
}
+static int rt_mutex_acquire_inner(RT_MUTEX *mutex, RTIME timeout, xntmode_t mode)
+{
+ int err;
+#ifdef CONFIG_XENO_FASTSYNCH
+ xnhandle_t cur;
+
+ cur = xeno_get_current();
+ if (!cur)
+ return -EPERM;
+
+ err = xnsynch_fast_acquire(mutex->fastlock, cur);
+ if (likely(!err)) {
+ mutex->lockcnt = 1;
+ return 0;
+ }
+
+ if (err == -EBUSY) {
+ if (mutex->lockcnt == UINT_MAX)
+ return -EAGAIN;
+
+ mutex->lockcnt++;
+ return 0;
+ }
+
+ if (timeout == TM_NONBLOCK && mode == XN_RELATIVE)
+ return -EWOULDBLOCK;
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+ err = XENOMAI_SKINCALL3(__native_muxid,
+ __native_mutex_acquire, mutex, mode, &timeout);
+
+#ifdef CONFIG_XENO_FASTSYNCH
+ if (!err)
+ mutex->lockcnt = 1;
+#endif /* CONFIG_XENO_FASTSYNCH */
+
+ return err;
+}
+
int rt_mutex_acquire(RT_MUTEX *mutex, RTIME timeout)
{
- return XENOMAI_SKINCALL3(__native_muxid,
- __native_mutex_acquire, mutex, XN_RELATIVE, &timeout);
+ return rt_mutex_acquire_inner(mutex, timeout, XN_RELATIVE);
}
int rt_mutex_acquire_until(RT_MUTEX *mutex, RTIME timeout)
{
- return XENOMAI_SKINCALL3(__native_muxid,
- __native_mutex_acquire, mutex, XN_REALTIME, &timeout);
+ return rt_mutex_acquire_inner(mutex, timeout, XN_REALTIME);
}
int rt_mutex_release(RT_MUTEX *mutex)
{
+#ifdef CONFIG_XENO_FASTSYNCH
+ xnhandle_t cur;
+
+ cur = xeno_get_current();
+ if (!cur)
+ return -EPERM;
+
+ if (unlikely(xnsynch_fast_owner_check(mutex->fastlock, cur) != 0))
+ return -EPERM;
+
+ if (mutex->lockcnt > 1) {
+ mutex->lockcnt--;
+ return 0;
+ }
+
+ if (likely(xnsynch_fast_release(mutex->fastlock, cur)))
+ return 0;
+#endif /* CONFIG_XENO_FASTSYNCH */
+
return XENOMAI_SKINCALL1(__native_muxid, __native_mutex_release, mutex);
}
^ permalink raw reply [flat|nested] 17+ messages in thread* [Xenomai-core] [PATCH 10/13] Optionally replace pthread_getspecific with TLS variables
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (8 preceding siblings ...)
2008-10-17 15:46 ` [Xenomai-core] [PATCH 09/13] Use fast xnsynch with native skin Jan Kiszka
@ 2008-10-17 15:46 ` Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 11/13] Report current shadow thread mode to user space Jan Kiszka
` (5 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:46 UTC (permalink / raw)
To: xenomai; +Cc: Jan Kiszka
On architectures that support the __thread storage class and the
initial-exec TLS model, several use cases of pthread_get/setspecific can
be optimized. On x86, e.g., we are able to implement xeno_get_current()
via just two instructions instead of a call into glibc and all the
included pthread_key lookup. The minor downside of initial-exec TLS is
that libraries using such variables are excluded from dlopen.
This patch adds the required check to configure, also installing a
switch (--without-__thread) in order to disable the support if dlopen
compatibility should be required. It adds a __thread-variant for
xeno_get_current and self-references of the current Native, VRTX and
VxWorks tasks.
RTDK's rt_printf services are intentionally not converted as they are
heavy-weighted anyway and depend on the pthread_key destructor
mechanism.
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
configure.in | 23 ++++++++++++++++++++
include/asm-generic/bits/bind.h | 41 +++++++++++++++++++++++++------------
include/asm-generic/bits/current.h | 14 ++++++++++--
src/skins/native/init.c | 23 ++++++++++++--------
src/skins/native/task.c | 21 ++++++++++++++++++
src/skins/vrtx/init.c | 20 +++++++++++-------
src/skins/vrtx/task.c | 14 +++++++++++-
src/skins/vxworks/init.c | 20 +++++++++++-------
src/skins/vxworks/taskLib.c | 20 +++++++++++++++++-
9 files changed, 156 insertions(+), 40 deletions(-)
Index: b/configure.in
===================================================================
--- a/configure.in
+++ b/configure.in
@@ -762,6 +762,29 @@ LIBS="$LIBS -lrt"
AC_CHECK_FUNCS([shm_open shm_unlink])
LIBS="$save_LIBS"
+AC_ARG_WITH([__thread],
+ AC_HELP_STRING([--without-__thread],
+ [do not use TLS features (allows for dlopen'ing Xenomai libs)]),
+ [use__thread=$withval],
+ [use__thread=yes])
+
+dnl Check whether the compiler supports the __thread keyword.
+if test "x$use__thread" != xno; then
+ AC_CACHE_CHECK([for __thread], libc_cv_gcc___thread,
+ [cat > conftest.c <<\EOF
+__thread int a __attribute__ ((tls_model ("initial-exec"))) = 42;
+EOF
+ if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -c -Werror conftest.c >&AS_MESSAGE_LOG_FD]); then
+ libc_cv_gcc___thread=yes
+ else
+ libc_cv_gcc___thread=no
+ fi
+ rm -f conftest*])
+ if test "$libc_cv_gcc___thread" = yes; then
+ AC_DEFINE(HAVE___THREAD,1,[config])
+ fi
+fi
+
dnl
dnl Build the Makefiles
dnl
Index: b/include/asm-generic/bits/bind.h
===================================================================
--- a/include/asm-generic/bits/bind.h
+++ b/include/asm-generic/bits/bind.h
@@ -11,24 +11,23 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
+#include <nucleus/types.h>
#include <asm/xenomai/syscall.h>
-__attribute__ ((weak))
-pthread_key_t xeno_current_key;
+#ifdef HAVE___THREAD
+__thread xnhandle_t xeno_current __attribute__ ((tls_model ("initial-exec"))) =
+ XN_NO_HANDLE;
-__attribute__ ((weak))
-void xeno_set_current(void)
+static inline void __xeno_set_current(xnhandle_t current)
{
- void *kthread_cb;
- int err;
+ xeno_current = current;
+}
+#else /* !HAVE___THREAD */
+pthread_key_t xeno_current_key;
- 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);
+static inline void __xeno_set_current(xnhandle_t current)
+{
+ pthread_setspecific(xeno_current_key, (void *)current);
}
static __attribute__ ((constructor))
@@ -41,6 +40,22 @@ void init_current_key(void)
exit(1);
}
}
+#endif /* !HAVE___THREAD */
+
+__attribute__ ((weak))
+void xeno_set_current(void)
+{
+ xnhandle_t current;
+ int err;
+
+ err = XENOMAI_SYSCALL1(__xn_sys_current, ¤t);
+ if (err) {
+ fprintf(stderr, "Xenomai: error obtaining handle for current "
+ "thread: %s\n", strerror(err));
+ exit(1);
+ }
+ __xeno_set_current(current);
+}
#ifdef CONFIG_XENO_FASTSYNCH
__attribute__ ((weak))
Index: b/include/asm-generic/bits/current.h
===================================================================
--- a/include/asm-generic/bits/current.h
+++ b/include/asm-generic/bits/current.h
@@ -4,9 +4,16 @@
#include <pthread.h>
#include <nucleus/types.h>
-extern pthread_key_t xeno_current_key;
+#ifdef HAVE___THREAD
+extern __thread xnhandle_t xeno_current __attribute__ ((tls_model ("initial-exec")));
-extern void xeno_set_current(void);
+static inline xnhandle_t xeno_get_current(void)
+{
+ return xeno_current;
+}
+
+#else /* ! HAVE___THREAD */
+extern pthread_key_t xeno_current_key;
static inline xnhandle_t xeno_get_current(void)
{
@@ -17,5 +24,8 @@ static inline xnhandle_t xeno_get_curren
return (xnhandle_t)val;
}
+#endif /* ! HAVE___THREAD */
+
+void xeno_set_current(void);
#endif /* _XENO_ASM_GENERIC_CURRENT_H */
Index: b/src/skins/native/init.c
===================================================================
--- a/src/skins/native/init.c
+++ b/src/skins/native/init.c
@@ -27,11 +27,12 @@
#include <asm-generic/bits/bind.h>
#include <asm-generic/bits/mlock_alert.h>
-pthread_key_t __native_tskey;
-
int __native_muxid = -1;
void native_timer_init(int);
+#ifndef HAVE___THREAD
+pthread_key_t __native_tskey;
+
static void __flush_tsd(void *tsd)
{
/* Free the task descriptor allocated by rt_task_self(). */
@@ -39,6 +40,17 @@ static void __flush_tsd(void *tsd)
}
static __attribute__ ((constructor))
+void __init_native_tskey(void)
+ /* Allocate a TSD key for indexing self task pointers. */
+
+ if (pthread_key_create(&__native_tskey, &__flush_tsd) != 0) {
+ fprintf(stderr, "Xenomai: failed to allocate new TSD key?!\n");
+ exit(1);
+ }
+}
+#endif /* !HAVE___THREAD */
+
+static __attribute__ ((constructor))
void __init_xeno_interface(void)
{
__native_muxid =
@@ -49,11 +61,4 @@ void __init_xeno_interface(void)
#endif /* CONFIG_XENO_HW_DIRECT_TSC */
__native_muxid = __xn_mux_shifted_id(__native_muxid);
-
- /* Allocate a TSD key for indexing self task pointers. */
-
- if (pthread_key_create(&__native_tskey, &__flush_tsd) != 0) {
- fprintf(stderr, "Xenomai: failed to allocate new TSD key?!\n");
- exit(1);
- }
}
Index: b/src/skins/native/task.c
===================================================================
--- a/src/skins/native/task.c
+++ b/src/skins/native/task.c
@@ -29,7 +29,14 @@
#include <asm-generic/bits/current.h>
#include "wrappers.h"
+#ifdef HAVE___THREAD
+__thread RT_TASK __native_self __attribute__ ((tls_model ("initial-exec"))) = {
+ .opaque = XN_NO_HANDLE,
+ .opaque2 = 0
+};
+#else /* !HAVE___THREAD */
extern pthread_key_t __native_tskey;
+#endif /* !HAVE___THREAD */
extern int __native_muxid;
@@ -91,6 +98,10 @@ static void *rt_task_trampoline(void *co
xeno_set_current();
+#ifdef HAVE___THREAD
+ __native_self = *iargs->task;
+#endif /* HAVE___THREAD */
+
/* Wait on the barrier for the task to be started. The barrier
could be released in order to process Linux signals while the
Xenomai shadow is still dormant; in such a case, resume wait. */
@@ -316,6 +327,15 @@ RT_TASK *rt_task_self(void)
{
RT_TASK *self;
+#ifdef HAVE___THREAD
+ self = &__native_self;
+
+ if (self->opaque == XN_NO_HANDLE)
+ return NULL;
+
+#else /* !HAVE___THREAD */
+ RT_TASK *self;
+
self = (RT_TASK *)pthread_getspecific(__native_tskey);
if (self)
@@ -330,6 +350,7 @@ RT_TASK *rt_task_self(void)
}
pthread_setspecific(__native_tskey, self);
+#endif /* !HAVE___THREAD */
return self;
}
Index: b/src/skins/vxworks/init.c
===================================================================
--- a/src/skins/vxworks/init.c
+++ b/src/skins/vxworks/init.c
@@ -26,10 +26,11 @@
#include <asm-generic/bits/bind.h>
#include <asm-generic/bits/mlock_alert.h>
-pthread_key_t __vxworks_tskey;
-
int __vxworks_muxid = -1;
+#ifndef HAVE___THREAD
+pthread_key_t __vxworks_tskey;
+
static void __flush_tsd(void *tsd)
{
/* Free the task descriptor allocated by taskIdSelf(). */
@@ -37,12 +38,8 @@ static void __flush_tsd(void *tsd)
}
static __attribute__ ((constructor))
-void __init_xeno_interface(void)
+void __init_vxworks_tskey(void)
{
- __vxworks_muxid = xeno_bind_skin(VXWORKS_SKIN_MAGIC,
- "vxworks", "xeno_vxworks");
- __vxworks_muxid = __xn_mux_shifted_id(__vxworks_muxid);
-
/* Allocate a TSD key for indexing self task pointers. */
if (pthread_key_create(&__vxworks_tskey, &__flush_tsd) != 0) {
@@ -50,3 +47,12 @@ void __init_xeno_interface(void)
exit(1);
}
}
+#endif /* !HAVE___THREAD */
+
+static __attribute__ ((constructor))
+void __init_xeno_interface(void)
+{
+ __vxworks_muxid = xeno_bind_skin(VXWORKS_SKIN_MAGIC,
+ "vxworks", "xeno_vxworks");
+ __vxworks_muxid = __xn_mux_shifted_id(__vxworks_muxid);
+}
Index: b/src/skins/vxworks/taskLib.c
===================================================================
--- a/src/skins/vxworks/taskLib.c
+++ b/src/skins/vxworks/taskLib.c
@@ -30,7 +30,14 @@
#include <asm-generic/bits/current.h>
#include "wrappers.h"
+#ifdef HAVE___THREAD
+__thread WIND_TCB
+__vxworks_self __attribute__ ((tls_model ("initial-exec"))) = {
+ .handle = XN_NO_HANDLE
+};
+#else /* !HAVE___THREAD */
extern pthread_key_t __vxworks_tskey;
+#endif /* !HAVE___THREAD */
extern int __vxworks_muxid;
@@ -120,6 +127,10 @@ static void *wind_task_trampoline(void *
xeno_set_current();
+#ifdef HAVE___THREAD
+ __vxworks_self = *iargs->pTcb;
+#endif /* HAVE___THREAD */
+
/* Wait on the barrier for the task to be started. The barrier
could be released in order to process Linux signals while the
Xenomai shadow is still dormant; in such a case, resume wait. */
@@ -309,9 +320,15 @@ STATUS taskResume(TASK_ID task_id)
TASK_ID taskIdSelf(void)
{
- WIND_TCB *self = (WIND_TCB *)pthread_getspecific(__vxworks_tskey);
+#ifdef HAVE___THREAD
+ return __vxworks_self.handle;
+
+#else /* !HAVE___THREAD */
+ WIND_TCB *self;
int err;
+ self = (WIND_TCB *)pthread_getspecific(__vxworks_tskey);
+
if (self)
return self->handle;
@@ -332,6 +349,7 @@ TASK_ID taskIdSelf(void)
pthread_setspecific(__vxworks_tskey, self);
return self->handle;
+#endif /* !HAVE___THREAD */
}
STATUS taskPrioritySet(TASK_ID task_id, int prio)
Index: b/src/skins/vrtx/init.c
===================================================================
--- a/src/skins/vrtx/init.c
+++ b/src/skins/vrtx/init.c
@@ -26,10 +26,11 @@
#include <asm-generic/bits/bind.h>
#include <asm-generic/bits/mlock_alert.h>
-pthread_key_t __vrtx_tskey;
-
int __vrtx_muxid = -1;
+#ifndef HAVE___THREAD
+pthread_key_t __vrtx_tskey;
+
static void __flush_tsd(void *tsd)
{
/* Free the TCB struct. */
@@ -37,12 +38,8 @@ static void __flush_tsd(void *tsd)
}
static __attribute__ ((constructor))
-void __init_xeno_interface(void)
+void __init_vrtx_tskey(void)
{
- __vrtx_muxid =
- xeno_bind_skin(VRTX_SKIN_MAGIC, "vrtx", "xeno_vrtx");
- __vrtx_muxid = __xn_mux_shifted_id(__vrtx_muxid);
-
/* Allocate a TSD key for indexing self task pointers. */
if (pthread_key_create(&__vrtx_tskey, &__flush_tsd) != 0) {
@@ -50,3 +47,12 @@ void __init_xeno_interface(void)
exit(1);
}
}
+#endif /* !HAVE___THREAD */
+
+static __attribute__ ((constructor))
+void __init_xeno_interface(void)
+{
+ __vrtx_muxid =
+ xeno_bind_skin(VRTX_SKIN_MAGIC, "vrtx", "xeno_vrtx");
+ __vrtx_muxid = __xn_mux_shifted_id(__vrtx_muxid);
+}
Index: b/src/skins/vrtx/task.c
===================================================================
--- a/src/skins/vrtx/task.c
+++ b/src/skins/vrtx/task.c
@@ -29,7 +29,11 @@
#include <vrtx/vrtx.h>
#include <asm-generic/bits/current.h>
+#ifdef HAVE___THREAD
+__thread TCB __vrtx_tcb __attribute__ ((tls_model ("initial-exec")));
+#else /* !HAVE___THREAD */
extern pthread_key_t __vrtx_tskey;
+#endif /* !HAVE___THREAD */
extern int __vrtx_muxid;
@@ -81,7 +85,9 @@ static void *vrtx_task_trampoline(void *
struct sched_param param;
int policy;
long err;
+#ifndef HAVE___THREAD
TCB *tcb;
+#endif /* !HAVE___THREAD */
/* Backup the arg struct, it might vanish after completion. */
memcpy(&_iargs, iargs, sizeof(_iargs));
@@ -96,6 +102,7 @@ static void *vrtx_task_trampoline(void *
/* vrtx_task_delete requires asynchronous cancellation */
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+#ifndef HAVE___THREAD
tcb = (TCB *) malloc(sizeof(*tcb));
if (tcb == NULL) {
fprintf(stderr, "Xenomai: failed to allocate local TCB?!\n");
@@ -104,6 +111,7 @@ static void *vrtx_task_trampoline(void *
}
pthread_setspecific(__vrtx_tskey, tcb);
+#endif /* !HAVE___THREAD */
old_sigharden_handler = signal(SIGHARDEN, &vrtx_task_sigharden);
@@ -224,7 +232,11 @@ TCB *sc_tinquiry(int pinfo[], int tid, i
{
TCB *tcb;
- tcb = (TCB *) pthread_getspecific(__vrtx_tskey); /* Cannot fail. */
+#ifdef HAVE___THREAD
+ tcb = &__vrtx_tcb;
+#else /* !HAVE___THREAD */
+ tcb = (TCB *) pthread_getspecific(__vrtx_tskey); /* Cannot fail. */
+#endif /* !HAVE___THREAD */
*errp = XENOMAI_SKINCALL3(__vrtx_muxid,
__vrtx_tinquiry, pinfo, tcb, tid);
^ permalink raw reply [flat|nested] 17+ messages in thread* [Xenomai-core] [PATCH 11/13] Report current shadow thread mode to user space
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (9 preceding siblings ...)
2008-10-17 15:46 ` [Xenomai-core] [PATCH 10/13] Optionally replace pthread_getspecific with TLS variables Jan Kiszka
@ 2008-10-17 15:46 ` Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 12/13] Ensure mode switch in mutex fast paths Jan Kiszka
` (4 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:46 UTC (permalink / raw)
To: xenomai; +Cc: Jan Kiszka
With this patch applied, the Xenomai skin libraries are able to obtain
the execution mode the current thread without issuing a syscall. The
kernel-user interface looks as follows:
- On thread creation (which triggers xnshadow_map), user space passes a
pointer to an unsigned long.
- Before going primary and after completing the switch to secondary
mode, the nucleus writes 0 or XNRELAX to that unsigned long. The mode
updates use __xn_put_user, so they are fail-safe (write errors are
ignored, only an initial access_wok check is reported back).
- User space can check its state by calling xeno_get_current_mode().
An optional light-weight version based on __thread is also provided.
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
include/asm-generic/bits/bind.h | 22 +++++++++++++++++++++-
include/asm-generic/bits/current.h | 20 ++++++++++++++++++++
include/native/syscall.h | 1 +
include/nucleus/shadow.h | 3 ++-
include/nucleus/thread.h | 4 ++++
include/psos+/syscall.h | 8 ++++++++
include/vrtx/syscall.h | 1 +
include/vxworks/syscall.h | 1 +
ksrc/nucleus/shadow.c | 22 ++++++++++++++++++++--
ksrc/skins/native/syscall.c | 3 ++-
ksrc/skins/posix/syscall.c | 14 +++++++++-----
ksrc/skins/psos+/syscall.c | 34 +++++++++++++++++++++-------------
ksrc/skins/uitron/syscall.c | 8 ++++++--
ksrc/skins/vrtx/syscall.c | 4 +++-
ksrc/skins/vxworks/syscall.c | 4 +++-
src/skins/native/task.c | 10 ++++++++++
src/skins/posix/thread.c | 33 +++++++++++++++++++++++++++++++--
src/skins/psos+/task.c | 16 +++++++++++++---
src/skins/uitron/task.c | 11 +++++++++--
src/skins/vrtx/task.c | 6 ++++++
src/skins/vxworks/taskLib.c | 6 ++++++
21 files changed, 197 insertions(+), 34 deletions(-)
Index: b/include/native/syscall.h
===================================================================
--- a/include/native/syscall.h
+++ b/include/native/syscall.h
@@ -134,6 +134,7 @@ struct rt_arg_bulk {
u_long a3;
u_long a4;
u_long a5;
+ u_long a6;
};
#ifdef __KERNEL__
Index: b/include/nucleus/shadow.h
===================================================================
--- a/include/nucleus/shadow.h
+++ b/include/nucleus/shadow.h
@@ -69,7 +69,8 @@ void xnshadow_grab_events(void);
void xnshadow_release_events(void);
int xnshadow_map(struct xnthread *thread,
- xncompletion_t __user *u_completion);
+ xncompletion_t __user *u_completion,
+ unsigned long __user *u_mode);
void xnshadow_unmap(struct xnthread *thread);
Index: b/include/nucleus/thread.h
===================================================================
--- a/include/nucleus/thread.h
+++ b/include/nucleus/thread.h
@@ -248,6 +248,10 @@ typedef struct xnthread {
void *cookie; /* Cookie to pass to the entry routine */
+#ifdef CONFIG_XENO_OPT_PERVASIVE
+ unsigned long __user *u_mode; /* Thread mode variable in userland. */
+#endif /* CONFIG_XENO_OPT_PERVASIVE */
+
XNARCH_DECL_DISPLAY_CONTEXT();
} xnthread_t;
Index: b/ksrc/nucleus/shadow.c
===================================================================
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -1079,6 +1079,8 @@ redo:
/* Grab the request token. */
return -ERESTARTSYS;
+ __xn_put_user(0, thread->u_mode);
+
preempt_disable();
/* Assume that we might have been migrated while waiting for
@@ -1250,6 +1252,8 @@ void xnshadow_relax(int notify)
/* "current" is now running into the Linux domain on behalf of the
root thread. */
+ __xn_put_user(XNRELAX, thread->u_mode);
+
trace_mark(xn_nucleus_shadow_relaxed,
"thread %p thread_name %s comm %s",
thread, xnthread_name(thread), current->comm);
@@ -1264,7 +1268,9 @@ void xnshadow_exit(void)
}
/*!
- * \fn int xnshadow_map(xnthread_t *thread, xncompletion_t __user *u_completion)
+ * \fn int xnshadow_map(xnthread_t *thread,
+ * xncompletion_t __user *u_completion,
+ * unsigned long __user *u_mode)
* @internal
* \brief Create a shadow thread context.
*
@@ -1288,6 +1294,11 @@ void xnshadow_exit(void)
* immediately started and "current" immediately resumes in the Xenomai
* domain from this service.
*
+ * @param: u_mode is the address of a mode variable in user space that
+ * will reflect the current thread mode (primary or secondary). The
+ * nucleus will try to update the variable before switching to secondary
+ * or after switching from primary mode.
+ *
* @return 0 is returned on success. Otherwise:
*
* - -ERESTARTSYS is returned if the current Linux task has received a
@@ -1313,7 +1324,8 @@ void xnshadow_exit(void)
*
*/
-int xnshadow_map(xnthread_t *thread, xncompletion_t __user *u_completion)
+int xnshadow_map(xnthread_t *thread, xncompletion_t __user *u_completion,
+ unsigned long __user *u_mode)
{
xnarch_cpumask_t affinity;
unsigned muxid, magic;
@@ -1325,6 +1337,9 @@ int xnshadow_map(xnthread_t *thread, xnc
if (xnthread_test_state(thread, XNMAPPED))
return -EINVAL;
+ if (!access_wok(u_mode, sizeof(*u_mode)))
+ return -EFAULT;
+
#ifdef CONFIG_MMU
if (!(current->mm->def_flags & VM_LOCKED))
send_sig(SIGXCPU, current, 1);
@@ -1385,6 +1400,9 @@ int xnshadow_map(xnthread_t *thread, xnc
if (err)
return err;
+ thread->u_mode = u_mode;
+ __xn_put_user(XNRELAX, u_mode);
+
err = xnshadow_harden();
xnarch_trace_pid(xnarch_user_pid(xnthread_archtcb(thread)),
Index: b/ksrc/skins/native/syscall.c
===================================================================
--- a/ksrc/skins/native/syscall.c
+++ b/ksrc/skins/native/syscall.c
@@ -191,7 +191,8 @@ static int __rt_task_create(struct pt_re
if (__xn_safe_copy_to_user((void __user *)bulk.a1, &ph, sizeof(ph)))
err = -EFAULT;
else {
- err = xnshadow_map(&task->thread_base, u_completion);
+ err = xnshadow_map(&task->thread_base, u_completion,
+ (unsigned long __user *)bulk.a6);
if (!err)
goto out;
}
Index: b/ksrc/skins/posix/syscall.c
===================================================================
--- a/ksrc/skins/posix/syscall.c
+++ b/ksrc/skins/posix/syscall.c
@@ -180,7 +180,8 @@ static int __pthread_create(struct pt_re
if (err)
return -err; /* Conventionally, our error codes are negative. */
- err = xnshadow_map(&k_tid->threadbase, NULL);
+ err = xnshadow_map(&k_tid->threadbase, NULL,
+ (unsigned long __user *)__xn_reg_arg2(regs));
if (!err && !__pthread_hash(&hkey, k_tid))
err = -ENOMEM;
@@ -196,7 +197,8 @@ static int __pthread_create(struct pt_re
#define __pthread_detach __pse51_call_not_available
static pthread_t __pthread_shadow(struct task_struct *p,
- struct pse51_hkey *hkey)
+ struct pse51_hkey *hkey,
+ unsigned long __user *u_mode)
{
pthread_attr_t attr;
pthread_t k_tid;
@@ -211,7 +213,7 @@ static pthread_t __pthread_shadow(struct
if (err)
return ERR_PTR(-err);
- err = xnshadow_map(&k_tid->threadbase, NULL);
+ err = xnshadow_map(&k_tid->threadbase, NULL, u_mode);
if (!err && !__pthread_hash(hkey, k_tid))
err = -EAGAIN;
@@ -227,11 +229,13 @@ static pthread_t __pthread_shadow(struct
static int __pthread_setschedparam(struct pt_regs *regs)
{
int policy, err, promoted = 0;
+ unsigned long __user *u_mode;
struct sched_param param;
struct pse51_hkey hkey;
pthread_t k_tid;
policy = __xn_reg_arg2(regs);
+ u_mode = (unsigned long __user *)__xn_reg_arg4(regs);
if (__xn_safe_copy_from_user(¶m,
(void __user *)__xn_reg_arg3(regs), sizeof(param)))
@@ -241,10 +245,10 @@ static int __pthread_setschedparam(struc
hkey.mm = current->mm;
k_tid = __pthread_find(&hkey);
- if (!k_tid && __xn_reg_arg1(regs) == __xn_reg_arg4(regs)) {
+ if (!k_tid && u_mode) {
/* If the syscall applies to "current", and the latter is not
a Xenomai thread already, then shadow it. */
- k_tid = __pthread_shadow(current, &hkey);
+ k_tid = __pthread_shadow(current, &hkey, u_mode);
if (IS_ERR(k_tid))
return PTR_ERR(k_tid);
Index: b/ksrc/skins/psos+/syscall.c
===================================================================
--- a/ksrc/skins/psos+/syscall.c
+++ b/ksrc/skins/psos+/syscall.c
@@ -60,11 +60,14 @@ static psostask_t *__psos_task_current(s
}
/*
- * int __t_create(const char *name,
- * u_long prio,
- * u_long flags,
+ * int __t_create(struct psos_arg_bulk *bulk,
* u_long *tid_r,
* xncompletion_t *completion)
+ * bulk = {
+ * a1: const char *name;
+ * a2: u_long prio;
+ * a3: u_long flags;
+ * a4: unsigned long *mode;
*/
static int __t_create(struct pt_regs *regs)
@@ -73,10 +76,15 @@ static int __t_create(struct pt_regs *re
struct task_struct *p = current;
u_long prio, flags, tid, err;
char name[XNOBJECT_NAME_LEN];
+ struct psos_arg_bulk bulk;
psostask_t *task;
+ if (__xn_safe_copy_from_user(&bulk, (void __user *)__xn_reg_arg1(regs),
+ sizeof(bulk)))
+ return -EFAULT;
+
/* Get task name. */
- if (__xn_safe_strncpy_from_user(name, (const char __user *)__xn_reg_arg1(regs),
+ if (__xn_safe_strncpy_from_user(name, (const char __user *)bulk.a1,
sizeof(name) - 1) < 0)
return -EFAULT;
@@ -85,12 +93,12 @@ static int __t_create(struct pt_regs *re
p->comm[sizeof(p->comm) - 1] = '\0';
/* Task priority. */
- prio = __xn_reg_arg2(regs);
+ prio = bulk.a2;
/* Task flags. Force FPU support in user-space. This will lead
to a no-op if the platform does not support it. */
- flags = __xn_reg_arg3(regs) | T_SHADOW | T_FPU;
+ flags = bulk.a3 | T_SHADOW | T_FPU;
/* Completion descriptor our parent thread is pending on. */
- u_completion = (xncompletion_t __user *)__xn_reg_arg5(regs);
+ u_completion = (xncompletion_t __user *)__xn_reg_arg3(regs);
err = t_create(name, prio, 0, 0, flags, &tid);
@@ -100,14 +108,14 @@ static int __t_create(struct pt_regs *re
* about the new thread id, so we can manipulate its
* TCB pointer freely. */
tid = xnthread_handle(&task->threadbase);
- if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg4(regs), &tid,
+ if (__xn_safe_copy_to_user((void __user *)__xn_reg_arg2(regs), &tid,
sizeof(tid)))
return -EFAULT;
- else {
- err = xnshadow_map(&task->threadbase, u_completion); /* May be NULL */
- if (!err)
- goto out;
- }
+
+ err = xnshadow_map(&task->threadbase, u_completion,
+ (unsigned long __user *)bulk.a4);
+ if (!err)
+ goto out;
t_delete((u_long)task);
}
Index: b/ksrc/skins/vrtx/syscall.c
===================================================================
--- a/ksrc/skins/vrtx/syscall.c
+++ b/ksrc/skins/vrtx/syscall.c
@@ -48,6 +48,7 @@ static int __muxid;
* a1: int tid;
* a2: int prio;
* a3: int mode;
+ * a4: unsigned long *shadow_mode;
* }
*/
@@ -89,7 +90,8 @@ static int __sc_tecreate(struct pt_regs
&tid, sizeof(tid)))
err = -EFAULT;
else {
- err = xnshadow_map(&task->threadbase, u_completion);
+ err = xnshadow_map(&task->threadbase, u_completion,
+ (unsigned long __user *)bulk.a4);
if (!err)
goto done;
}
Index: b/ksrc/skins/vxworks/syscall.c
===================================================================
--- a/ksrc/skins/vxworks/syscall.c
+++ b/ksrc/skins/vxworks/syscall.c
@@ -66,6 +66,7 @@ static WIND_TCB *__wind_task_current(str
* a2: int prio;
* a3: int flags;
* a4: pthread_self();
+ * a5: unsigned long *mode;
* }
*/
@@ -124,7 +125,8 @@ static int __wind_task_init(struct pt_re
sizeof(ph)))
err = -EFAULT;
else {
- err = xnshadow_map(&task->threadbase, u_completion);
+ err = xnshadow_map(&task->threadbase, u_completion,
+ (unsigned long __user *)bulk.a5);
if (!err)
goto out;
}
Index: b/ksrc/skins/uitron/syscall.c
===================================================================
--- a/ksrc/skins/uitron/syscall.c
+++ b/ksrc/skins/uitron/syscall.c
@@ -31,13 +31,15 @@
int __ui_muxid;
/*
- * int __uitron_cre_tsk(ID tskid, T_CTSK *pk_ctsk, xncompletion_t *completion)
+ * int __uitron_cre_tsk(ID tskid, T_CTSK *pk_ctsk, xncompletion_t *completion,
+ * unsigned long *mode)
*/
static int __ui_cre_tsk(struct pt_regs *regs)
{
xncompletion_t __user *u_completion;
struct task_struct *p = current;
+ unsigned long __user *u_mode;
uitask_t *task;
T_CTSK pk_ctsk;
ID tskid;
@@ -54,6 +56,8 @@ static int __ui_cre_tsk(struct pt_regs *
/* Completion descriptor our parent thread is pending on. */
u_completion = (xncompletion_t __user *)__xn_reg_arg3(regs);
+ u_mode = (unsigned long __user *)__xn_reg_arg4(regs);
+
err = cre_tsk(tskid, &pk_ctsk);
if (likely(err == E_OK)) {
@@ -74,7 +78,7 @@ static int __ui_cre_tsk(struct pt_regs *
* recycled before we could map it; however, the risk
* is mitigated by consistency checks performed in
* xnshadow_map(). */
- return xnshadow_map(&task->threadbase, u_completion); /* May be NULL */
+ return xnshadow_map(&task->threadbase, u_completion, u_mode);
}
fail:
Index: b/include/asm-generic/bits/bind.h
===================================================================
--- a/include/asm-generic/bits/bind.h
+++ b/include/asm-generic/bits/bind.h
@@ -17,6 +17,8 @@
#ifdef HAVE___THREAD
__thread xnhandle_t xeno_current __attribute__ ((tls_model ("initial-exec"))) =
XN_NO_HANDLE;
+__thread unsigned long
+xeno_current_mode __attribute__ ((tls_model ("initial-exec")));
static inline void __xeno_set_current(xnhandle_t current)
{
@@ -24,17 +26,35 @@ static inline void __xeno_set_current(xn
}
#else /* !HAVE___THREAD */
pthread_key_t xeno_current_key;
+pthread_key_t xeno_current_mode_key;
static inline void __xeno_set_current(xnhandle_t current)
{
pthread_setspecific(xeno_current_key, (void *)current);
}
+unsigned long *xeno_init_current_mode(void)
+{
+ unsigned long *mode = malloc(sizeof(unsigned long));
+ pthread_setspecific(xeno_current_mode_key, mode);
+ return mode;
+}
+
+static void cleanup_current_mode(void *ptr)
+{
+ free(ptr);
+}
+
static __attribute__ ((constructor))
-void init_current_key(void)
+void init_current_keys(void)
{
int err = pthread_key_create(&xeno_current_key, NULL);
+ if (err)
+ goto error_exit;
+
+ err = pthread_key_create(&xeno_current_mode_key, cleanup_current_mode);
if (err) {
+ error_exit:
fprintf(stderr, "Xenomai: error creating TSD key: %s\n",
strerror(err));
exit(1);
Index: b/include/asm-generic/bits/current.h
===================================================================
--- a/include/asm-generic/bits/current.h
+++ b/include/asm-generic/bits/current.h
@@ -6,14 +6,27 @@
#ifdef HAVE___THREAD
extern __thread xnhandle_t xeno_current __attribute__ ((tls_model ("initial-exec")));
+extern __thread unsigned long
+xeno_current_mode __attribute__ ((tls_model ("initial-exec")));
static inline xnhandle_t xeno_get_current(void)
{
return xeno_current;
}
+static inline unsigned long xeno_get_current_mode(void)
+{
+ return xeno_current_mode;
+}
+
+static inline unsigned long *xeno_init_current_mode(void)
+{
+ return &xeno_current_mode;
+}
+
#else /* ! HAVE___THREAD */
extern pthread_key_t xeno_current_key;
+extern pthread_key_t xeno_current_mode_key;
static inline xnhandle_t xeno_get_current(void)
{
@@ -24,6 +37,13 @@ static inline xnhandle_t xeno_get_curren
return (xnhandle_t)val;
}
+
+static inline unsigned long xeno_get_current_mode(void)
+{
+ return *(unsigned long *)pthread_getspecific(xeno_current_mode_key);
+}
+
+unsigned long *xeno_init_current_mode(void);
#endif /* ! HAVE___THREAD */
void xeno_set_current(void);
Index: b/src/skins/native/task.c
===================================================================
--- a/src/skins/native/task.c
+++ b/src/skins/native/task.c
@@ -89,6 +89,12 @@ static void *rt_task_trampoline(void *co
bulk.a3 = (u_long)iargs->prio;
bulk.a4 = (u_long)iargs->mode;
bulk.a5 = (u_long)pthread_self();
+ bulk.a6 = (u_long)xeno_init_current_mode();
+
+ if (!bulk.a6) {
+ err = -ENOMEM;
+ goto fail;
+ }
err = XENOMAI_SKINCALL2(__native_muxid,
__native_task_create, &bulk,
@@ -205,6 +211,10 @@ int rt_task_shadow(RT_TASK *task, const
bulk.a3 = (u_long)prio;
bulk.a4 = (u_long)mode;
bulk.a5 = (u_long)pthread_self();
+ bulk.a6 = (u_long)xeno_init_current_mode();
+
+ if (!bulk.a6)
+ return -ENOMEM;
err = XENOMAI_SKINCALL2(__native_muxid, __native_task_create, &bulk,
NULL);
Index: b/src/skins/posix/thread.c
===================================================================
--- a/src/skins/posix/thread.c
+++ b/src/skins/posix/thread.c
@@ -47,11 +47,23 @@ int __wrap_pthread_setschedparam(pthread
int policy, const struct sched_param *param)
{
pthread_t myself = pthread_self();
+ unsigned long *mode_buf = NULL;
int err, promoted;
+ if (thread == myself) {
+#ifdef HAVE___THREAD
+ mode_buf = xeno_init_current_mode();
+#else /* !HAVE___THREAD */
+ mode_buf = malloc(sizeof(*mode_buf));
+
+ if (!mode_buf)
+ return ENOMEM;
+#endif /* !HAVE___THREAD */
+ }
+
err = -XENOMAI_SKINCALL5(__pse51_muxid,
__pse51_thread_setschedparam,
- thread, policy, param, myself, &promoted);
+ thread, policy, param, mode_buf, &promoted);
if (err == EPERM)
return __real_pthread_setschedparam(thread, policy, param);
@@ -60,10 +72,17 @@ int __wrap_pthread_setschedparam(pthread
if (!err && promoted) {
old_sigharden_handler = signal(SIGHARDEN, &__pthread_sigharden_handler);
+#ifndef HAVE___THREAD
+ pthread_setspecific(xeno_current_mode_key, mode_buf);
+#endif /* !HAVE___THREAD */
xeno_set_current();
if (policy != SCHED_OTHER)
XENOMAI_SYSCALL1(__xn_sys_migrate, XENOMAI_XENO_DOMAIN);
}
+#ifndef HAVE___THREAD
+ else
+ free(mode_buf);
+#endif /* !HAVE___THREAD */
return err;
}
@@ -116,6 +135,7 @@ static void *__pthread_trampoline(void *
struct sched_param param;
void *status = NULL;
int parent_prio, policy;
+ unsigned long *mode_buf;
long err;
old_sigharden_handler = signal(SIGHARDEN, &__pthread_sigharden_handler);
@@ -123,10 +143,18 @@ static void *__pthread_trampoline(void *
param.sched_priority = iargs->prio;
policy = iargs->policy;
parent_prio = iargs->parent_prio;
+ mode_buf = xeno_init_current_mode();
+
+ if (!mode_buf) {
+ status = (void *)ENOMEM;
+ iargs->ret = ENOMEM;
+ goto out;
+ }
/* Do _not_ inline the call to pthread_self() in the syscall
macro: this trashes the syscall regs on some archs. */
- err = XENOMAI_SKINCALL1(__pse51_muxid, __pse51_thread_create, tid);
+ err = XENOMAI_SKINCALL2(__pse51_muxid, __pse51_thread_create, tid,
+ mode_buf);
iargs->ret = -err;
/* We must save anything we'll need to use from *iargs on our own
@@ -159,6 +187,7 @@ static void *__pthread_trampoline(void *
} else
status = (void *)-err;
+out:
pthread_exit(status);
}
Index: b/include/vrtx/syscall.h
===================================================================
--- a/include/vrtx/syscall.h
+++ b/include/vrtx/syscall.h
@@ -85,6 +85,7 @@ struct vrtx_arg_bulk {
u_long a1;
u_long a2;
u_long a3;
+ u_long a4;
};
#ifdef __KERNEL__
Index: b/include/vxworks/syscall.h
===================================================================
--- a/include/vxworks/syscall.h
+++ b/include/vxworks/syscall.h
@@ -77,6 +77,7 @@ struct wind_arg_bulk {
u_long a2;
u_long a3;
u_long a4;
+ u_long a5;
};
#ifdef __KERNEL__
Index: b/src/skins/vrtx/task.c
===================================================================
--- a/src/skins/vrtx/task.c
+++ b/src/skins/vrtx/task.c
@@ -118,6 +118,12 @@ static void *vrtx_task_trampoline(void *
bulk.a1 = (u_long)iargs->tid;
bulk.a2 = (u_long)iargs->prio;
bulk.a3 = (u_long)iargs->mode;
+ bulk.a4 = (u_long)xeno_init_current_mode();
+
+ if (!bulk.a4) {
+ err = -ENOMEM;
+ goto fail;
+ }
err = XENOMAI_SKINCALL3(__vrtx_muxid,
__vrtx_tecreate,
Index: b/src/skins/vxworks/taskLib.c
===================================================================
--- a/src/skins/vxworks/taskLib.c
+++ b/src/skins/vxworks/taskLib.c
@@ -118,6 +118,12 @@ static void *wind_task_trampoline(void *
bulk.a2 = (u_long)iargs->prio;
bulk.a3 = (u_long)iargs->flags;
bulk.a4 = (u_long)pthread_self();
+ bulk.a5 = (u_long)xeno_init_current_mode();
+
+ if (!bulk.a5) {
+ err = -ENOMEM;
+ goto fail;
+ }
err = XENOMAI_SKINCALL3(__vxworks_muxid,
__vxworks_task_init,
Index: b/include/psos+/syscall.h
===================================================================
--- a/include/psos+/syscall.h
+++ b/include/psos+/syscall.h
@@ -74,6 +74,14 @@
/* Xenomai extension: get raw count of jiffies */
#define __psos_tm_getc 46
+struct psos_arg_bulk {
+
+ u_long a1;
+ u_long a2;
+ u_long a3;
+ u_long a4;
+};
+
#ifdef __KERNEL__
#ifdef __cplusplus
Index: b/src/skins/psos+/task.c
===================================================================
--- a/src/skins/psos+/task.c
+++ b/src/skins/psos+/task.c
@@ -72,6 +72,7 @@ static void *psos_task_trampoline(void *
struct psos_task_iargs *iargs = (struct psos_task_iargs *)cookie;
void (*entry)(u_long, u_long, u_long, u_long);
u_long dummy_args[4] = { 0, 0, 0, 0 }, *targs;
+ struct psos_arg_bulk bulk;
struct sched_param param;
int policy;
long err;
@@ -83,10 +84,19 @@ static void *psos_task_trampoline(void *
old_sigharden_handler = signal(SIGHARDEN, &psos_task_sigharden);
- err = XENOMAI_SKINCALL5(__psos_muxid,
+ bulk.a1 = (u_long)iargs->name;
+ bulk.a2 = (u_long)iargs->prio;
+ bulk.a3 = (u_long)iargs->flags;
+ bulk.a4 = (u_long)xeno_init_current_mode();
+
+ if (!bulk.a4) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ err = XENOMAI_SKINCALL3(__psos_muxid,
__psos_t_create,
- iargs->name, iargs->prio, iargs->flags,
- iargs->tid_r, iargs->completionp);
+ &bulk, iargs->tid_r, iargs->completionp);
if (err)
goto fail;
Index: b/src/skins/uitron/task.c
===================================================================
--- a/src/skins/uitron/task.c
+++ b/src/skins/uitron/task.c
@@ -68,6 +68,7 @@ static void *uitron_task_trampoline(void
{
struct uitron_task_iargs *iargs = (struct uitron_task_iargs *)cookie;
struct sched_param param;
+ unsigned long *mode;
void (*entry)(INT);
int policy;
long err;
@@ -83,10 +84,16 @@ static void *uitron_task_trampoline(void
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
old_sigharden_handler = signal(SIGHARDEN, &uitron_task_sigharden);
- err = XENOMAI_SKINCALL3(__uitron_muxid,
+ mode = xeno_init_current_mode();
+ if (!mode) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ err = XENOMAI_SKINCALL4(__uitron_muxid,
__uitron_cre_tsk,
iargs->tskid, iargs->pk_ctsk,
- iargs->completionp);
+ iargs->completionp, mode);
if (err)
goto fail;
^ permalink raw reply [flat|nested] 17+ messages in thread* [Xenomai-core] [PATCH 12/13] Ensure mode switch in mutex fast paths
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (10 preceding siblings ...)
2008-10-17 15:46 ` [Xenomai-core] [PATCH 11/13] Report current shadow thread mode to user space Jan Kiszka
@ 2008-10-17 15:46 ` Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 13/13] Catch inconsistent SMP feature support Jan Kiszka
` (3 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:46 UTC (permalink / raw)
To: xenomai; +Cc: Jan Kiszka
With the help of xeno_get_current_mode(), this patch ensures that shadow
threads in secondary mode will be switched to primary again in case they
acquire an uncontended native or POSIX mutex, thus would otherwise only
pick the user space fast path. This prevents potential priority
inversions that the fast mutex optimizations introduced.
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
src/skins/native/mutex.c | 31 ++++++++-------
src/skins/posix/mutex.c | 94 +++++++++++++++++++++++++++--------------------
2 files changed, 71 insertions(+), 54 deletions(-)
Index: b/src/skins/native/mutex.c
===================================================================
--- a/src/skins/native/mutex.c
+++ b/src/skins/native/mutex.c
@@ -18,6 +18,7 @@
#include <limits.h>
#include <nucleus/synch.h>
+#include <nucleus/thread.h>
#include <native/syscall.h>
#include <native/mutex.h>
#include <asm-generic/bits/current.h>
@@ -78,22 +79,24 @@ static int rt_mutex_acquire_inner(RT_MUT
if (!cur)
return -EPERM;
- err = xnsynch_fast_acquire(mutex->fastlock, cur);
- if (likely(!err)) {
- mutex->lockcnt = 1;
- return 0;
- }
-
- if (err == -EBUSY) {
- if (mutex->lockcnt == UINT_MAX)
- return -EAGAIN;
+ if (likely(!(xeno_get_current_mode() & XNRELAX))) {
+ err = xnsynch_fast_acquire(mutex->fastlock, cur);
+ if (likely(!err)) {
+ mutex->lockcnt = 1;
+ return 0;
+ }
+
+ if (err == -EBUSY) {
+ if (mutex->lockcnt == UINT_MAX)
+ return -EAGAIN;
+
+ mutex->lockcnt++;
+ return 0;
+ }
- mutex->lockcnt++;
- return 0;
+ if (timeout == TM_NONBLOCK && mode == XN_RELATIVE)
+ return -EWOULDBLOCK;
}
-
- if (timeout == TM_NONBLOCK && mode == XN_RELATIVE)
- return -EWOULDBLOCK;
#endif /* CONFIG_XENO_FASTSYNCH */
err = XENOMAI_SKINCALL3(__native_muxid,
Index: b/src/skins/posix/mutex.c
===================================================================
--- a/src/skins/posix/mutex.c
+++ b/src/skins/posix/mutex.c
@@ -164,31 +164,33 @@ int __wrap_pthread_mutex_lock(pthread_mu
goto out;
}
- err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
+ if (likely(!(xeno_get_current_mode() & XNRELAX))) {
+ err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
- if (likely(!err)) {
- shadow->lockcnt = 1;
- cb_read_unlock(&shadow->lock, s);
- return 0;
- }
+ if (likely(!err)) {
+ shadow->lockcnt = 1;
+ cb_read_unlock(&shadow->lock, s);
+ return 0;
+ }
- if (err == -EBUSY)
- switch(shadow->attr.type) {
- case PTHREAD_MUTEX_NORMAL:
- break;
+ if (err == -EBUSY)
+ switch(shadow->attr.type) {
+ case PTHREAD_MUTEX_NORMAL:
+ break;
- case PTHREAD_MUTEX_ERRORCHECK:
- err = -EDEADLK;
- goto out;
+ case PTHREAD_MUTEX_ERRORCHECK:
+ err = -EDEADLK;
+ goto out;
- case PTHREAD_MUTEX_RECURSIVE:
- if (shadow->lockcnt == UINT_MAX) {
- err = -EAGAIN;
+ case PTHREAD_MUTEX_RECURSIVE:
+ if (shadow->lockcnt == UINT_MAX) {
+ err = -EAGAIN;
+ goto out;
+ }
+ ++shadow->lockcnt;
+ err = 0;
goto out;
}
- ++shadow->lockcnt;
- err = 0;
- goto out;
}
#endif /* CONFIG_XENO_FASTSYNCH */
@@ -226,32 +228,34 @@ int __wrap_pthread_mutex_timedlock(pthre
goto out;
}
- err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
+ if (likely(!(xeno_get_current_mode() & XNRELAX))) {
+ err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
- if (likely(!err)) {
- shadow->lockcnt = 1;
- cb_read_unlock(&shadow->lock, s);
- return 0;
- }
+ if (likely(!err)) {
+ shadow->lockcnt = 1;
+ cb_read_unlock(&shadow->lock, s);
+ return 0;
+ }
- if (err == -EBUSY)
- switch(shadow->attr.type) {
- case PTHREAD_MUTEX_NORMAL:
- break;
+ if (err == -EBUSY)
+ switch(shadow->attr.type) {
+ case PTHREAD_MUTEX_NORMAL:
+ break;
- case PTHREAD_MUTEX_ERRORCHECK:
- err = -EDEADLK;
- goto out;
+ case PTHREAD_MUTEX_ERRORCHECK:
+ err = -EDEADLK;
+ goto out;
- case PTHREAD_MUTEX_RECURSIVE:
- if (shadow->lockcnt == UINT_MAX) {
- err = -EAGAIN;
+ case PTHREAD_MUTEX_RECURSIVE:
+ if (shadow->lockcnt == UINT_MAX) {
+ err = -EAGAIN;
+ goto out;
+ }
+
+ ++shadow->lockcnt;
goto out;
}
-
- ++shadow->lockcnt;
- goto out;
- }
+ }
#endif /* CONFIG_XENO_FASTSYNCH */
do {
@@ -286,7 +290,17 @@ int __wrap_pthread_mutex_trylock(pthread
if (unlikely(shadow->magic != PSE51_MUTEX_MAGIC)) {
err = -EINVAL;
goto out;
- }
+ }
+
+ if (unlikely(xeno_get_current_mode() & XNRELAX)) {
+ do {
+ err = -XENOMAI_SYSCALL1(__xn_sys_migrate,
+ XENOMAI_XENO_DOMAIN);
+ } while (err == EINTR);
+
+ if (err)
+ goto out;
+ }
err = xnsynch_fast_acquire(get_ownerp(shadow), cur);
^ permalink raw reply [flat|nested] 17+ messages in thread* [Xenomai-core] [PATCH 13/13] Catch inconsistent SMP feature support
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (11 preceding siblings ...)
2008-10-17 15:46 ` [Xenomai-core] [PATCH 12/13] Ensure mode switch in mutex fast paths Jan Kiszka
@ 2008-10-17 15:46 ` Jan Kiszka
2008-10-17 16:11 ` [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (2 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 15:46 UTC (permalink / raw)
To: xenomai; +Cc: Jan Kiszka
With fast xnsynch/mutex support in place, the importance of getting the
user space library configuration right increases significantly. If the
user fails to provide --enable-smp, (s)he risks to break the mutex fast
path in a very subtle way.
This patch catches the case that the kernel support SMP while userland
does not.
Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---
include/asm-generic/features.h | 40 ++++++++++++++++++++++++----------------
1 file changed, 24 insertions(+), 16 deletions(-)
Index: b/include/asm-generic/features.h
===================================================================
--- a/include/asm-generic/features.h
+++ b/include/asm-generic/features.h
@@ -26,13 +26,14 @@
#endif /* __KERNEL__ */
#define __xn_feat_smp 0x80000000
-#define __xn_feat_fastsynch 0x40000000
-#define __xn_feat_nofastsynch 0x20000000
+#define __xn_feat_nosmp 0x40000000
+#define __xn_feat_fastsynch 0x20000000
+#define __xn_feat_nofastsynch 0x10000000
#ifdef CONFIG_SMP
#define __xn_feat_smp_mask __xn_feat_smp
#else
-#define __xn_feat_smp_mask 0
+#define __xn_feat_smp_mask __xn_feat_nosmp
#endif
#ifdef CONFIG_XENO_FASTSYNCH
@@ -41,22 +42,29 @@
#define __xn_feat_fastsynch_mask __xn_feat_nofastsynch
#endif
-#define __xn_feat_generic_mask (__xn_feat_smp_mask | __xn_feat_fastsynch_mask)
-
-#define __xn_feat_generic_man_mask (__xn_feat_fastsynch | __xn_feat_nofastsynch)
+/* List of generic features kernel or userland may support */
+#define __xn_feat_generic_mask \
+ (__xn_feat_smp_mask | __xn_feat_fastsynch_mask)
+
+/* List of features both sides have to agree on:
+ If userland supports it, the kernel has to provide it, too. */
+#define __xn_feat_generic_man_mask \
+ (__xn_feat_fastsynch | __xn_feat_nofastsynch | __xn_feat_nosmp)
static inline const char *get_generic_feature_label (unsigned feature)
{
- switch (feature) {
- case __xn_feat_smp:
- return "smp";
- case __xn_feat_fastsynch:
- return "fastsynch";
- case __xn_feat_nofastsynch:
- return "nofastsynch";
- default:
- return 0;
- }
+ switch (feature) {
+ case __xn_feat_smp:
+ return "smp";
+ case __xn_feat_nosmp:
+ return "nosmp";
+ case __xn_feat_fastsynch:
+ return "fastsynch";
+ case __xn_feat_nofastsynch:
+ return "nofastsynch";
+ default:
+ return 0;
+ }
}
#endif /* !_XENO_ASM_GENERIC_FEATURES_H */
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (12 preceding siblings ...)
2008-10-17 15:46 ` [Xenomai-core] [PATCH 13/13] Catch inconsistent SMP feature support Jan Kiszka
@ 2008-10-17 16:11 ` Jan Kiszka
2008-10-17 16:41 ` Gilles Chanteperdrix
2008-10-18 18:47 ` Gilles Chanteperdrix
15 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2008-10-17 16:11 UTC (permalink / raw)
To: xenomai
[-- Attachment #1: Type: text/plain, Size: 1286 bytes --]
Jan Kiszka wrote:
> Hopefully the last round, addressing remarks brought up on the last
> posting. The changes are:
>
> [Patches 7-9]
> - define xnsynch_owner_check as xnsynch-implementation-independent way
> to check provided and current synch owner match (reduces #ifdefs)
>
> [Patches 6 and 9]
> - push lockcnt changes to native mutexes into separate patch (patch
>
> [Patch 2]
> - switch creation of xeno_current_key etc. from pthread_once to a
> constructor
> - translate pthread_getspecific == NULL into XN_NO_HANDLE
> (funnily, this shrinks the code on x86-64)
>
> [Patch 13]
> - detect SMP feature inconsistency between kernel and userland
> (but keep SMP off by default for now)
>
> Note that this series (as well as the latter) depends on the VRTX fix of
> Philippe which is not yet merged into SVN trunk.
>
> Jan
>
> PS: Hope this series is compatible with more mail clients /wrt
> commenting on the inlined patches.
>
Again forgot to attach the testbench we derived from Gilles' unit test.
It currently depends on my infamous inquire patches. Compile with
-D__POSIX_SKIN__ and the usual wrapping for the posix skin, or against
the native lib otherwise.
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
[-- Attachment #2: mutex-testbench.c --]
[-- Type: text/x-c++src, Size: 18149 bytes --]
/*
* Functional testing of the mutex implementation for native & posix skins.
*
* Copyright (C) Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>,
* Marion Deveaud <marion.deveaud@domain.hid>,
* Jan Kiszka <jan.kiszka@domain.hid>
*
* Released under the terms of GPLv2.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdarg.h>
#include <sys/mman.h>
#include <pthread.h>
#include <native/timer.h>
#ifdef __POSIX_SKIN__
#include <posix/syscall.h>
#else /* __NATIVE_SKIN__ */
#include <native/task.h>
#include <native/mutex.h>
#include <native/sem.h>
#include <native/cond.h>
#endif
#define MUTEX_CREATE 1
#define MUTEX_LOCK 2
#define MUTEX_TRYLOCK 3
#define MUTEX_UNLOCK 4
#define MUTEX_DESTROY 5
#define COND_CREATE 6
#define COND_SIGNAL 7
#define COND_WAIT 8
#define COND_DESTROY 9
#define THREAD_DETACH 10
#define THREAD_CREATE 11
#define NS_PER_MS 1000000
#ifdef __POSIX_SKIN__
typedef pthread_mutex_t mutex_t;
typedef pthread_t thread_t;
typedef pthread_cond_t cond_t;
#else /* __NATIVE_SKIN__ */
typedef RT_MUTEX mutex_t;
typedef RT_TASK thread_t;
typedef RT_COND cond_t;
#endif /* __NATIVE_SKIN__ */
void ms_sleep(int time)
{
#ifdef __POSIX_SKIN__
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = time*NS_PER_MS;
nanosleep(&ts, NULL);
#else /* __NATIVE_SKIN__ */
rt_task_sleep(time*NS_PER_MS);
#endif /* __NATIVE_SKIN__ */
}
void check_current_prio(int expected_prio)
{
int current_prio;
#ifdef __POSIX_SKIN__
# ifdef __pse51_get_current_prio
extern unsigned __pse51_muxid;
XENOMAI_SKINCALL1(__pse51_muxid, __pse51_get_current_prio, ¤t_prio);
# else /* !__pse51_get_current_prio */
current_prio = expected_prio;
# endif /* !__pse51_get_current_prio */
#else /* __NATIVE_SKIN__ */
int ret;
RT_TASK_INFO task_info;
if ((ret = rt_task_inquire(NULL, &task_info)) < 0) {
fprintf(stderr, "Task inquire: %i (%s)\n", -ret, strerror(-ret));
exit(EXIT_FAILURE);
}
current_prio = task_info.cprio;
#endif /* __NATIVE_SKIN__ */
if (current_prio != expected_prio) {
fprintf(stderr, "current prio (%d) != expected prio (%d)\n",
current_prio, expected_prio);
exit(EXIT_FAILURE);
}
}
void check_current_mode(int expected_primary_mode)
{
int current_in_primary, ret;
#ifdef __POSIX_SKIN__
pthread_info_t thread_info;
if ((ret = pthread_inquire_np(pthread_self(), &thread_info)) > 0) {
fprintf(stderr, "Thread inquire: %i (%s)\n", ret, strerror(ret));
exit(EXIT_FAILURE);
}
current_in_primary = !!(thread_info.status & PTHREAD_PRIMARY);
#else /* __NATIVE_SKIN__ */
RT_TASK_INFO task_info;
if ((ret = rt_task_inquire(NULL, &task_info)) < 0) {
fprintf(stderr, "Task inquire: %i (%s)\n", -ret, strerror(-ret));
exit(EXIT_FAILURE);
}
current_in_primary = !!(task_info.status & T_PRIMARY);
#endif /* __NATIVE_SKIN__ */
if (current_in_primary != expected_primary_mode) {
fprintf(stderr, "current mode (%d) != expected mode (%d)\n",
current_in_primary, expected_primary_mode);
exit(EXIT_FAILURE);
}
}
void yield(void)
{
#ifdef __POSIX_SKIN__
sched_yield();
#else /* __NATIVE_SKIN__ */
rt_task_yield();
#endif /* __NATIVE_SKIN__ */
}
int dispatch(const char *service_name, int service_type, int check, ...)
{
thread_t *thread;
cond_t *cond;
void *handler;
va_list ap;
int status;
#ifdef __POSIX_SKIN__
struct sched_param param;
pthread_attr_t threadattr;
pthread_mutexattr_t mutexattr;
pthread_mutex_t *mutex;
#else /* __NATIVE_SKIN__ */
int prio;
#endif /* __NATIVE_SKIN__ */
va_start(ap, check);
switch (service_type) {
case MUTEX_CREATE:
#ifdef __POSIX_SKIN__
mutex = va_arg(ap, pthread_mutex_t *);
pthread_mutexattr_init(&mutexattr);
if (va_arg(ap, int) != 0)
pthread_mutexattr_setprotocol(&mutexattr,
PTHREAD_PRIO_INHERIT);
pthread_mutexattr_settype(&mutexattr, va_arg(ap, int));
status = pthread_mutex_init(mutex, &mutexattr);
#else /* __NATIVE_SKIN__ */
status = -rt_mutex_create(va_arg(ap, RT_MUTEX *), NULL);
#endif /* __NATIVE_SKIN__ */
break;
case MUTEX_LOCK:
#ifdef __POSIX_SKIN__
status = pthread_mutex_lock(va_arg(ap, pthread_mutex_t *));
#else /* __NATIVE_SKIN__ */
status =
-rt_mutex_acquire(va_arg(ap, RT_MUTEX *), TM_INFINITE);
#endif /* __NATIVE_SKIN__ */
break;
case MUTEX_TRYLOCK:
#ifdef __POSIX_SKIN__
status = pthread_mutex_trylock(va_arg(ap, pthread_mutex_t *));
#else /* __NATIVE_SKIN__ */
status =
-rt_mutex_acquire(va_arg(ap, RT_MUTEX *), TM_NONBLOCK);
#endif /* __NATIVE_SKIN__ */
break;
case MUTEX_UNLOCK:
#ifdef __POSIX_SKIN__
status = pthread_mutex_unlock(va_arg(ap, pthread_mutex_t *));
#else /* __NATIVE_SKIN__ */
status = -rt_mutex_release(va_arg(ap, RT_MUTEX *));
#endif /* __NATIVE_SKIN__ */
break;
case MUTEX_DESTROY:
#ifdef __POSIX_SKIN__
status = pthread_mutex_destroy(va_arg(ap, pthread_mutex_t *));
#else /* __NATIVE_SKIN__ */
status = -rt_mutex_delete(va_arg(ap, RT_MUTEX *));
#endif /* __NATIVE_SKIN__ */
break;
case COND_CREATE:
#ifdef __POSIX_SKIN__
status = pthread_cond_init(va_arg(ap, pthread_cond_t *), NULL);
#else /* __NATIVE_SKIN__ */
status = -rt_cond_create(va_arg(ap, RT_COND *), NULL);
#endif /* __NATIVE_SKIN__ */
break;
case COND_SIGNAL:
#ifdef __POSIX_SKIN__
status = pthread_cond_signal(va_arg(ap, pthread_cond_t *));
#else /* __NATIVE_SKIN__ */
status = -rt_cond_signal(va_arg(ap, RT_COND *));
#endif /* __NATIVE_SKIN__ */
break;
case COND_WAIT:
#ifdef __POSIX_SKIN__
cond = va_arg(ap, pthread_cond_t *);
status =
pthread_cond_wait(cond, va_arg(ap, pthread_mutex_t *));
#else /* __NATIVE_SKIN__ */
cond = va_arg(ap, RT_COND *);
status =
-rt_cond_wait(cond, va_arg(ap, RT_MUTEX *), TM_INFINITE);
#endif /* __NATIVE_SKIN__ */
break;
case COND_DESTROY:
#ifdef __POSIX_SKIN__
status = pthread_cond_destroy(va_arg(ap, pthread_cond_t *));
#else /* __NATIVE_SKIN__ */
status = -rt_cond_delete(va_arg(ap, RT_COND *));
#endif /* __NATIVE_SKIN__ */
break;
#ifdef __POSIX_SKIN__
case THREAD_DETACH:
status = pthread_detach(pthread_self());
break;
#else /* __NATIVE_SKIN__ */
case THREAD_DETACH:
return 0;
#endif /* __NATIVE_SKIN__ */
case THREAD_CREATE:
#ifdef __POSIX_SKIN__
thread = va_arg(ap, pthread_t *);
pthread_attr_init(&threadattr);
pthread_attr_setschedpolicy(&threadattr, SCHED_FIFO);
param.sched_priority = va_arg(ap, int);
pthread_attr_setschedparam(&threadattr, ¶m);
pthread_attr_setinheritsched(&threadattr,
PTHREAD_EXPLICIT_SCHED);
handler = va_arg(ap, void *);
status = pthread_create(thread, &threadattr, handler,
va_arg(ap, void *));
#else /* __NATIVE_SKIN__ */
thread = va_arg(ap, RT_TASK *);
prio = va_arg(ap, int);
handler = va_arg(ap, void *);
status = -rt_task_spawn(thread, NULL, 0, prio, 0, handler,
va_arg(ap, void *));
#endif /* __NATIVE_SKIN__ */
break;
default:
fprintf(stderr, "Unknown service %i.\n", service_type);
exit(EXIT_FAILURE);
}
va_end(ap);
if (status > 0 && check) {
fprintf(stderr, "%s: %i (%s)\n",
service_name, status, strerror(status));
exit(EXIT_FAILURE);
}
return status;
}
void *waiter(void *cookie)
{
mutex_t *mutex = (mutex_t *) cookie;
unsigned long long start, diff;
dispatch("waiter pthread_detach", THREAD_DETACH, 1);
start = rt_timer_tsc();
dispatch("waiter mutex_lock", MUTEX_LOCK, 1, mutex);
diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
if (diff < 10000000) {
fprintf(stderr, "waiter, waited %Ld.%03u us\n",
diff / 1000, (unsigned) (diff % 1000));
exit(EXIT_FAILURE);
}
ms_sleep(11);
dispatch("waiter mutex_unlock", MUTEX_UNLOCK, 1, mutex);
return cookie;
}
void simple_wait(void)
{
unsigned long long start, diff;
mutex_t mutex;
thread_t waiter_tid;
fprintf(stderr, "simple_wait\n");
dispatch("simple mutex_init", MUTEX_CREATE, 1, &mutex, 0, 0);
dispatch("simple mutex_lock 1", MUTEX_LOCK, 1, &mutex);
dispatch("simple thread_create", THREAD_CREATE, 1, &waiter_tid, 2,
waiter, &mutex);
ms_sleep(10);
dispatch("simple mutex_unlock 1", MUTEX_UNLOCK, 1, &mutex);
yield();
start = rt_timer_tsc();
dispatch("simple mutex_lock 2", MUTEX_LOCK, 1, &mutex);
diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
if (diff < 10000000) {
fprintf(stderr, "main, waited %Ld.%03u us\n",
diff / 1000, (unsigned) (diff % 1000));
exit(EXIT_FAILURE);
}
dispatch("simple mutex_unlock 2", MUTEX_UNLOCK, 1, &mutex);
dispatch("simple mutex_destroy", MUTEX_DESTROY, 1, &mutex);
}
void recursive_wait(void)
{
unsigned long long start, diff;
mutex_t mutex;
thread_t waiter_tid;
fprintf(stderr, "recursive_wait\n");
dispatch("rec mutex_init", MUTEX_CREATE, 1, &mutex, 0,
PTHREAD_MUTEX_RECURSIVE);
dispatch("rec mutex_lock 1", MUTEX_LOCK, 1, &mutex);
dispatch("rec mutex_lock 2", MUTEX_LOCK, 1, &mutex);
dispatch("rec thread_create", THREAD_CREATE, 1, &waiter_tid, 2,
waiter, &mutex);
dispatch("rec mutex_unlock 2", MUTEX_UNLOCK, 1, &mutex);
ms_sleep(10);
dispatch("rec mutex_unlock 1", MUTEX_UNLOCK, 1, &mutex);
yield();
start = rt_timer_tsc();
dispatch("rec mutex_lock 3", MUTEX_LOCK, 1, &mutex);
diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
if (diff < 10000000) {
fprintf(stderr, "main, waited %Ld.%03u us\n",
diff / 1000, (unsigned) (diff % 1000));
exit(EXIT_FAILURE);
}
dispatch("rec mutex_unlock 3", MUTEX_UNLOCK, 1, &mutex);
dispatch("rec mutex_destroy", MUTEX_DESTROY, 1, &mutex);
}
void errorcheck_wait(void)
{
#ifdef __POSIX_SKIN__
/* This test only makes sense under POSIX */
unsigned long long start, diff;
mutex_t mutex;
thread_t waiter_tid;
int err;
fprintf(stderr, "errorcheck_wait\n");
dispatch("errorcheck mutex_init", MUTEX_CREATE, 1, &mutex, 0,
PTHREAD_MUTEX_ERRORCHECK);
dispatch("errorcheck mutex_lock 1", MUTEX_LOCK, 1, &mutex);
err = pthread_mutex_lock(&mutex);
if (err != EDEADLK) {
fprintf(stderr, "errorcheck mutex_lock 2: %s\n",
strerror(err));
exit(EXIT_FAILURE);
}
dispatch("errorcheck thread_create", THREAD_CREATE, 1, &waiter_tid, 2,
waiter, &mutex);
ms_sleep(10);
dispatch("errorcheck mutex_unlock 1", MUTEX_UNLOCK, 1, &mutex);
yield();
err = pthread_mutex_unlock(&mutex);
if (err != EPERM) {
fprintf(stderr, "errorcheck mutex_unlock 2: %s\n",
strerror(err));
exit(EXIT_FAILURE);
}
start = rt_timer_tsc();
dispatch("errorcheck mutex_lock 3", MUTEX_LOCK, 1, &mutex);
diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
if (diff < 10000000) {
fprintf(stderr, "main, waited %Ld.%03u us\n",
diff / 1000, (unsigned) (diff % 1000));
exit(EXIT_FAILURE);
}
dispatch("errorcheck mutex_unlock 3", MUTEX_UNLOCK, 1, &mutex);
dispatch("errorcheck mutex_destroy", MUTEX_DESTROY, 1, &mutex);
#endif /* __POSIX_SKIN__ */
}
void mode_switch(void)
{
mutex_t mutex;
fprintf(stderr, "mode_switch\n");
dispatch("switch mutex_init", MUTEX_CREATE, 1, &mutex, 1, 0);
check_current_mode(0);
dispatch("switch mutex_lock", MUTEX_LOCK, 1, &mutex);
check_current_mode(1);
dispatch("switch mutex_unlock", MUTEX_UNLOCK, 1, &mutex);
dispatch("switch mutex_destroy", MUTEX_DESTROY, 1, &mutex);
}
void pi_wait(void)
{
unsigned long long start, diff;
mutex_t mutex;
thread_t waiter_tid;
fprintf(stderr, "pi_wait\n");
dispatch("pi mutex_init", MUTEX_CREATE, 1, &mutex, 1, 0);
dispatch("pi mutex_lock 1", MUTEX_LOCK, 1, &mutex);
check_current_prio(2);
/* Give waiter a higher priority than main thread */
dispatch("pi thread_create", THREAD_CREATE, 1, &waiter_tid, 3, waiter,
&mutex);
ms_sleep(10);
check_current_prio(3);
dispatch("pi mutex_unlock 1", MUTEX_UNLOCK, 1, &mutex);
yield();
check_current_prio(2);
start = rt_timer_tsc();
dispatch("pi mutex_lock 2", MUTEX_LOCK, 1, &mutex);
diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
if (diff < 10000000) {
fprintf(stderr, "main, waited %Ld.%03u us\n",
diff / 1000, (unsigned) (diff % 1000));
exit(EXIT_FAILURE);
}
dispatch("pi mutex_unlock 2", MUTEX_UNLOCK, 1, &mutex);
dispatch("pi mutex_destroy", MUTEX_DESTROY, 1, &mutex);
}
void lock_stealing(void)
{
mutex_t mutex;
thread_t lowprio_tid;
int trylock_result;
/* Main thread acquires the mutex and starts a waiter with lower
priority. Then main thread releases the mutex, but locks it again
without giving the waiter a chance to get it beforehand. */
fprintf(stderr, "lock_stealing\n");
dispatch("lock_stealing mutex_init", MUTEX_CREATE, 1, &mutex, 1, 0);
dispatch("lock_stealing mutex_lock 1", MUTEX_LOCK, 1, &mutex);
/* Main thread should have higher priority */
dispatch("lock_stealing thread_create 1", THREAD_CREATE, 1,
&lowprio_tid, 1, waiter, &mutex);
/* Give lowprio thread 1 more ms to block on the mutex */
ms_sleep(6);
dispatch("lock_stealing mutex_unlock 1", MUTEX_UNLOCK, 1, &mutex);
/* Try to stealing the lock from low prio task */
trylock_result = dispatch("lock_stealing mutex_trylock",
MUTEX_TRYLOCK, 0, &mutex);
if (trylock_result == 0) {
ms_sleep(6);
dispatch("lock_stealing mutex_unlock 2", MUTEX_UNLOCK, 1,
&mutex);
/* Let waiter_lowprio a chance to run */
ms_sleep(20);
dispatch("lock_stealing mutex_lock 3", MUTEX_LOCK, 1, &mutex);
/* Restart the waiter */
dispatch("lock_stealing thread_create 2", THREAD_CREATE, 1,
&lowprio_tid, 1, waiter, &mutex);
ms_sleep(6);
dispatch("lock_stealing mutex_unlock 3", MUTEX_UNLOCK, 1, &mutex);
#ifdef __POSIX_SKIN__
} else if (trylock_result != EBUSY) {
#else /* __NATIVE_SKIN__ */
} else if (trylock_result != EWOULDBLOCK) {
#endif /* __NATIVE_SKIN__ */
fprintf(stderr, "lock_stealing mutex_trylock: %i (%s)\n",
trylock_result, strerror(trylock_result));
exit(EXIT_FAILURE);
}
/* Stealing the lock (again) from low prio task */
dispatch("lock_stealing mutex_lock 4", MUTEX_LOCK, 1, &mutex);
ms_sleep(6);
dispatch("lock_stealing mutex_unlock 4", MUTEX_UNLOCK, 1, &mutex);
/* Let waiter_lowprio a chance to run */
ms_sleep(20);
dispatch("lock_stealing mutex_destroy", MUTEX_DESTROY, 1, &mutex);
if (trylock_result != 0)
fprintf(stderr,
"lock_stealing mutex_trylock: not supported\n");
}
struct cond_mutex {
mutex_t *mutex;
cond_t *cond;
};
void *cond_signaler(void *cookie)
{
struct cond_mutex *cm = (struct cond_mutex *) cookie;
unsigned long long start, diff;
dispatch("cond_signaler pthread_detach", THREAD_DETACH, 1);
start = rt_timer_tsc();
dispatch("cond_signaler mutex_lock 1", MUTEX_LOCK, 1, cm->mutex);
diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
if (diff < 10000000) {
fprintf(stderr,
"cond_signaler, mutex_lock waited %Ld.%03u us\n",
diff / 1000, (unsigned) (diff % 1000));
exit(EXIT_FAILURE);
}
ms_sleep(10);
dispatch("cond_signaler cond_signal", COND_SIGNAL, 1, cm->cond);
dispatch("cond_signaler mutex_unlock 2", MUTEX_UNLOCK, 1, cm->mutex);
yield();
start = rt_timer_tsc();
dispatch("cond_signaler mutex_lock 2", MUTEX_LOCK, 1, cm->mutex);
diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
if (diff < 10000000) {
fprintf(stderr,
"cond_signaler, mutex_lock 2 waited %Ld.%03u us\n",
diff / 1000, (unsigned) (diff % 1000));
exit(EXIT_FAILURE);
}
dispatch("cond_signaler mutex_unlock 2", MUTEX_UNLOCK, 1, cm->mutex);
return cookie;
}
void simple_condwait(void)
{
unsigned long long start, diff;
mutex_t mutex;
cond_t cond;
struct cond_mutex cm = {
.mutex = &mutex,
.cond = &cond,
};
thread_t cond_signaler_tid;
fprintf(stderr, "simple_condwait\n");
dispatch("simple_condwait mutex_init", MUTEX_CREATE, 1, &mutex);
dispatch("simple_condwait cond_init", COND_CREATE, 1, &cond);
dispatch("simple_condwait mutex_lock", MUTEX_LOCK, 1, &mutex);
dispatch("simple_condwait thread_create", THREAD_CREATE, 1,
&cond_signaler_tid, 2, cond_signaler, &cm);
ms_sleep(11);
start = rt_timer_tsc();
dispatch("simple_condwait cond_wait", COND_WAIT, 1, &cond, &mutex);
diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
if (diff < 10000000) {
fprintf(stderr, "main, waited %Ld.%03u us\n",
diff / 1000, (unsigned) (diff % 1000));
exit(EXIT_FAILURE);
}
ms_sleep(10);
dispatch("simple_condwait mutex_unlock", MUTEX_UNLOCK, 1, &mutex);
yield();
dispatch("simple_condwait mutex_destroy", MUTEX_DESTROY, 1, &mutex);
dispatch("simple_condwait cond_destroy", COND_DESTROY, 1, &cond);
}
void recursive_condwait(void)
{
unsigned long long start, diff;
mutex_t mutex;
cond_t cond;
struct cond_mutex cm = {
.mutex = &mutex,
.cond = &cond,
};
thread_t cond_signaler_tid;
fprintf(stderr, "recursive_condwait\n");
dispatch("rec_condwait mutex_init", MUTEX_CREATE, 1, &mutex, 0,
PTHREAD_MUTEX_RECURSIVE);
dispatch("rec_condwait cond_init", COND_CREATE, 1, &cond);
dispatch("rec_condwait mutex_lock 1", MUTEX_LOCK, 1, &mutex);
dispatch("rec_condwait mutex_lock 2", MUTEX_LOCK, 1, &mutex);
dispatch("rec_condwait thread_create", THREAD_CREATE, 1,
&cond_signaler_tid, 2, cond_signaler, &cm);
ms_sleep(10);
start = rt_timer_tsc();
dispatch("rec_condwait cond_wait", COND_WAIT, 1, &cond, &mutex);
diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
if (diff < 10000000) {
fprintf(stderr, "main, waited %Ld.%03u us\n",
diff / 1000, (unsigned) (diff % 1000));
exit(EXIT_FAILURE);
}
dispatch("rec_condwait mutex_unlock 1", MUTEX_UNLOCK, 1, &mutex);
ms_sleep(10);
dispatch("rec_condwait mutex_unlock 2", MUTEX_UNLOCK, 1, &mutex);
yield();
dispatch("rec_condwait mutex_destroy", MUTEX_DESTROY, 1, &mutex);
dispatch("rec_condwait cond_destroy", COND_DESTROY, 1, &cond);
}
int main(void)
{
#ifdef __POSIX_SKIN__
struct sched_param sparam;
#else /* __NATIVE_SKIN__ */
RT_TASK main_tid;
#endif /* __NATIVE_SKIN__ */
mlockall(MCL_CURRENT | MCL_FUTURE);
/* Set scheduling parameters for the current process */
#ifdef __POSIX_SKIN__
sparam.sched_priority = 2;
sched_setscheduler(0, SCHED_FIFO, &sparam);
#else /* __NATIVE_SKIN__ */
rt_task_shadow(&main_tid, "main_task", 2, 0);
#endif /* __NATIVE_SKIN__ */
/* Call test routines */
simple_wait();
recursive_wait();
errorcheck_wait();
mode_switch();
pi_wait();
lock_stealing();
simple_condwait();
recursive_condwait();
fprintf(stderr, "Test OK\n");
return 0;
}
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (13 preceding siblings ...)
2008-10-17 16:11 ` [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
@ 2008-10-17 16:41 ` Gilles Chanteperdrix
2008-10-18 18:47 ` Gilles Chanteperdrix
15 siblings, 0 replies; 17+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-17 16:41 UTC (permalink / raw)
To: Jan Kiszka; +Cc: xenomai
Jan Kiszka wrote:
> Hopefully the last round, addressing remarks brought up on the last
> posting. The changes are:
>
> [Patches 7-9]
> - define xnsynch_owner_check as xnsynch-implementation-independent way
> to check provided and current synch owner match (reduces #ifdefs)
>
> [Patches 6 and 9]
> - push lockcnt changes to native mutexes into separate patch (patch
>
> [Patch 2]
> - switch creation of xeno_current_key etc. from pthread_once to a
> constructor
> - translate pthread_getspecific == NULL into XN_NO_HANDLE
> (funnily, this shrinks the code on x86-64)
>
> [Patch 13]
> - detect SMP feature inconsistency between kernel and userland
> (but keep SMP off by default for now)
>
> Note that this series (as well as the latter) depends on the VRTX fix of
> Philippe which is not yet merged into SVN trunk.
>
> Jan
>
> PS: Hope this series is compatible with more mail clients /wrt
> commenting on the inlined patches.
Ok. Let's be done with it. I am ok with the whole stack.
--
Gilles.
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
` (14 preceding siblings ...)
2008-10-17 16:41 ` Gilles Chanteperdrix
@ 2008-10-18 18:47 ` Gilles Chanteperdrix
15 siblings, 0 replies; 17+ messages in thread
From: Gilles Chanteperdrix @ 2008-10-18 18:47 UTC (permalink / raw)
To: Jan Kiszka; +Cc: xenomai
Jan Kiszka wrote:
> PS: Hope this series is compatible with more mail clients /wrt
> commenting on the inlined patches.
I tested and it is true I could reply to your patches. However, your
mailer does not put any Content-type of Content-encoding info. This may
be a problem for some.
--
Gilles.
^ permalink raw reply [flat|nested] 17+ messages in thread