Generic fast xnsynch support & more
Subsystems (2)
cover Generic fast xnsynch support & more
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.
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
PATCH 1/13 Generic thread registration
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.
--- 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(-)
ksrc/skins/native/syscall.c +38 -23
@@ -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_regsRT_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_regsRT_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_regint 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_regint 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_regsint 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_regsRT_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_regsRT_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_reRT_BUFFER_PLACEHOLDER ph;int ret; - ret =__rt_bind_helper (current, regs, &ph.opaque,XENO_BUFFER_MAGIC ,NULL ); + ret = +__rt_bind_helper (current, regs, &ph.opaque,XENO_BUFFER_MAGIC , +NULL ,0 );if (ret)return ret;
ksrc/skins/native/task.c +1 -12
@@ -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; }
ksrc/skins/psos+/syscall.c +12 -7
@@ -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 *regpsostask_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 *rpsostask_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 *repsostask_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 *repsostask_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 *regu_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 *regpsostask_t *task;if (handle) - task = (psostask_t *)xnregistry_fetch (handle); + task =__psos_task_lookup (handle);else task =__psos_task_current (current);
ksrc/skins/psos+/task.c +5 -15
@@ -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(xnthreaif (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);
ksrc/skins/vxworks/syscall.c +18 -13
@@ -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(strucWIND_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 ptWIND_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 ptstatic 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(strucWIND_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(strucint 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 pxnhandle_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 pconst 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(structxnlock_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 ptWIND_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 preturn 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 pif (!handle) errcode =wind_errnoget ();else { - pTcb = (WIND_TCB *)xnregistry_fetch (handle); + pTcb =__wind_lookup_task (handle);if (!pTcb)return S_objLib_OBJ_ID_ERROR;
ksrc/skins/vxworks/taskLib.c +1 -9
@@ -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(xnthreif (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);
include/nucleus/registry.h +0 -1
@@ -35,7 +35,6 @@#if defined(__KERNEL__) || defined(__XENO_SIM__)#include <nucleus/synch.h> -#include <nucleus/thread.h> struct xnpnode ;
include/nucleus/thread.h +25 -0
@@ -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_perreturn 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
ksrc/nucleus/thread.c +2 -0
@@ -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 */ }
PATCH 2/13 Handle-based xeno_get_current service
In reply to Jan KiszkaTo 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.
--- 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(-)
include/asm-generic/bits/current.h +8 -2
@@ -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 */
include/nucleus/types.h +13 -0
@@ -61,6 +61,19 @@ typedef unsigned long xnhandle_t;#define XN_NO_HANDLE ((xnhandle_t)0) +#define XN_HANDLE_SPARE0 ((xnhandle_t)0x10000000) +#define XN_HANDLE_SPARE1 ((xnhandle_t)0x20000000) +#define XN_HANDLE_SPARE2 ((xnhandle_t)0x40000000) +#define XN_HANDLE_SPARE3 ((xnhandle_t)0x80000000) +#define XN_HANDLE_SPARE_MASK ((xnhandle_t)0xf0000000) + +#define xnhandle_mask_spare (handle) ((handle) & ~XN_HANDLE_SPARE_MASK) +#define xnhandle_test_spare (handle, bits) (!!((handle) & (bits))) +#define xnhandle_set_spare (handle, bits) \ + do { (handle) |= (bits); } while (0) +#define xnhandle_clear_spare (handle, bits) \ + do { (handle) &= ~(bits); } while (0) +struct xnintr ;typedef int (*xnisr_t )(struct xnintr *intr);
ksrc/nucleus/shadow.c +13 -3
@@ -1908,13 +1908,21 @@ static int xnshadow_sys_sem_heap(structreturn __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)
ksrc/skins/posix/cb_lock.h +11 -4
@@ -3,15 +3,22 @@#include <asm/xenomai/atomic.h> #include <nucleus/compiler.h> +#include <nucleus/types.h> #ifndef __KERNEL__typedef void xnthread_t ;#endif /* __KERNEL__ */ -#define test_claimed (owner) ((long) (owner) & 1) -#define clear_claimed (owner) ((xnthread_t *) ((long) (owner) & ~1)) -#define set_claimed (owner, bit) \ - ((xnthread_t *) ((long) clear_claimed(owner) | !!(bit))) +#define __CLAIMED_BIT XN_HANDLE_SPARE3 + +#define test_claimed (owner) xnhandle_test_spare(owner, __CLAIMED_BIT) +#define clear_claimed (owner) xnhandle_mask_spare(owner) +#define set_claimed (owner, bit) ({ \ + xnhandle_t __tmp = xnhandle_mask_spare(owner); \ + if (bit) \ + xnhandle_set_spare(__tmp, __CLAIMED_BIT); \ + __tmp; \ +})#ifdef CONFIG_XENO_FASTSEM
ksrc/skins/posix/cond.c +7 -5
@@ -230,18 +230,20 @@ static inline int mutex_save_count(xnthr mutex = shadow->mutex; -if (clear_claimed (xnarch_atomic_intptr_get (mutex->owner)) != cur) +if (clear_claimed (xnarch_atomic_get (mutex->owner)) != +xnthread_handle (cur))return EPERM ; *count_ptr = shadow->lockcnt; -if (likely (xnarch_atomic_intptr_cmpxchg (mutex->owner, cur,NULL ) == cur)) +if (likely (xnarch_atomic_cmpxchg (mutex->owner, cur,XN_NO_HANDLE ) == +xnthread_handle (cur)))return 0 ; owner =xnsynch_wakeup_one_sleeper (&mutex->synchbase); -xnarch_atomic_intptr_set - (mutex->owner, -set_claimed (owner,xnsynch_nsleepers (&mutex->synchbase))); +xnarch_atomic_set (mutex->owner, +set_claimed (xnthread_handle (owner), +xnsynch_nsleepers (&mutex->synchbase)));/* Do not reschedule here, releasing the mutex and suspension must be done atomically in pthread_cond_*wait. */
ksrc/skins/posix/mutex.c +13 -8
@@ -82,7 +82,7 @@ int pse51_mutex_check_init(struct __shadint 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; }
ksrc/skins/posix/mutex.h +39 -22
146 lines not on this page · raw message
ksrc/skins/posix/syscall.c +6 -5
@@ -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 ppthread_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 pif (!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(strucif (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);
src/skins/posix/mutex.c +21 -20
119 lines not on this page · raw message
ksrc/skins/posix/thread.c +12 -0
@@ -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). */
ksrc/skins/posix/Kconfig +1 -0
@@ -1,5 +1,6 @@ menuconfig XENO_SKIN_POSIX depends on XENO_OPT_NUCLEUS + select XENO_OPT_REGISTRY if XENO_FASTSEM tristate "POSIX API" default y help
include/asm-generic/bits/bind.h +10 -8
@@ -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 ])
ksrc/skins/native/Kconfig +1 -0
@@ -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
ksrc/skins/native/task.c +3 -5
@@ -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; }
ksrc/skins/psos+/Kconfig +1 -1
@@ -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.
ksrc/skins/uitron/Kconfig +1 -0
@@ -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
ksrc/skins/uitron/task.c +10 -1
@@ -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 ; }
ksrc/skins/rtai/Kconfig +1 -0
@@ -1,5 +1,6 @@ menuconfig XENO_SKIN_RTAI depends on XENO_OPT_NUCLEUS + select XENO_OPT_REGISTRY if XENO_FASTSEM tristate "RTAI emulator" help
ksrc/skins/rtai/task.c +10 -0
@@ -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. */
ksrc/skins/vrtx/Kconfig +1 -1
@@ -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
ksrc/skins/vrtx/task.c +15 -2
@@ -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);
ksrc/skins/vxworks/Kconfig +1 -1
@@ -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.
ksrc/skins/rtdm/drvlib.c +8 -0
@@ -145,6 +145,14 @@ int rtdm_task_init(rtdm_task_t *task, coif (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
PATCH 3/13 Remove xnarch_atomic_intptr
In reply to Jan KiszkaNo more users, no more use cases in sight, let's get rid of it.
--- include/asm-arm/atomic.h | 3 --- include/asm-blackfin/atomic.h | 2 -- include/asm-generic/Makefile.am | 2 +- include/asm-generic/Makefile.in | 2 +- include/asm-generic/atomic.h | 24 ------------------------ include/asm-ia64/atomic.h | 2 -- include/asm-powerpc/atomic.h | 2 -- include/asm-x86/atomic.h | 2 -- 8 files changed, 2 insertions(+), 37 deletions(-)
include/asm-arm/atomic.h +0 -3
@@ -412,9 +412,6 @@ static __inline__ void xnarch_atomic_cletypedef unsigned long atomic_flags_t ; -/* Add support for xnarch_atomic_intptr_t */ -#include <asm-generic/xenomai/atomic.h> -#endif /* !_XENO_ASM_ARM_ATOMIC_H */ // vim: ts=4 et sw=4 sts=4
include/asm-blackfin/atomic.h +0 -2
@@ -42,8 +42,6 @@typedef atomic_t atomic_counter_t ;typedef atomic_t xnarch_atomic_t ; -#include <asm-generic/xenomai/atomic.h> -#else /* !__KERNEL__ */ #include <asm/xenomai/syscall.h>
include/asm-generic/Makefile.am +1 -1
@@ -1,5 +1,5 @@ includesubdir = $(includedir)/asm-generic -includesub_HEADERS = arith.h atomic.h features.h hal.h syscall.h system.h wrappers.h +includesub_HEADERS = arith.h features.h hal.h syscall.h system.h wrappers.h SUBDIRS = bits
include/asm-generic/Makefile.in +1 -1
@@ -226,7 +226,7 @@ target_vendor = @target_vendor@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ includesubdir = $(includedir)/asm-generic -includesub_HEADERS = arith.h atomic.h features.h hal.h syscall.h system.h wrappers.h +includesub_HEADERS = arith.h features.h hal.h syscall.h system.h wrappers.h SUBDIRS = bits all: all-recursive
include/asm-generic/atomic.h deleted +0 -24
@@ -1,24 +0,0 @@ -#ifndef _XENO_ASM_GENERIC_ATOMIC_H -#define _XENO_ASM_GENERIC_ATOMIC_H - -typedef xnarch_atomic_t xnarch_atomic_intptr_t ; - -static inline void *xnarch_atomic_intptr_get (xnarch_atomic_intptr_t *l) -{ -xnarch_atomic_t *v = (xnarch_atomic_t *)l; - -return (void *)xnarch_atomic_get (v); -} - -static inline void xnarch_atomic_intptr_set (xnarch_atomic_intptr_t *l,void *i) -{ -xnarch_atomic_t *v = (xnarch_atomic_t *)l; - -xnarch_atomic_set (v, (long )i); -} - -#define xnarch_atomic_intptr_cmpxchg (l, old, newval) \ - (void *)(xnarch_atomic_cmpxchg((xnarch_atomic_t *)(l), \ - (long)(old), (long)(newval))) - -#endif /* _XENO_ASM_GENERIC_ATOMIC_H */
include/asm-ia64/atomic.h +0 -2
@@ -71,8 +71,6 @@ static inline void atomic_clear_mask(uns#define xnarch_atomic_cmpxchg (pcounter,old,new) \ cmpxchg((&(pcounter)->counter),(old),(new)) -#include <asm-generic/xenomai/atomic.h> -#else /* !__KERNEL__ */ #include <asm/xenomai/features.h>
include/asm-powerpc/atomic.h +0 -2
@@ -262,6 +262,4 @@ xnarch_atomic_cmpxchg(xnarch_atomic_t *ptypedef unsigned long atomic_flags_t ; -#include <asm-generic/xenomai/atomic.h> -#endif /* !_XENO_ASM_POWERPC_ATOMIC_H */
include/asm-x86/atomic.h +0 -2
@@ -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 */
PATCH 4/13 Spread xeno_set_current under all skins
In reply to Jan KiszkaSpread xeno_set_current under all user space supporting skins.
--- src/skins/native/task.c | 13 +++++++++++-- src/skins/psos+/task.c | 18 ++++++++++++++---- src/skins/uitron/task.c | 18 +++++++++++++----- src/skins/vrtx/task.c | 3 +++ src/skins/vxworks/taskLib.c | 3 +++ 5 files changed, 44 insertions(+), 11 deletions(-)
src/skins/native/task.c +11 -2
@@ -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 *coif (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, conststruct 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)
src/skins/psos+/task.c +14 -4
@@ -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, /* Xenu_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,
src/skins/uitron/task.c +13 -5
@@ -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(voidif (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)
src/skins/vrtx/task.c +3 -0
@@ -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. */
src/skins/vxworks/taskLib.c +3 -0
@@ -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. */
PATCH 5/13 Factor out xnsynch_acquire/release
In reply to Jan KiszkaThis 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.
--- 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(-)
include/nucleus/synch.h +11 -5
@@ -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);
ksrc/nucleus/synch.c +278 -140
527 lines not on this page · raw message
include/rtdm/rtdm_driver.h +1 -1
@@ -1134,7 +1134,7 @@ static inline void rtdm_mutex_unlock(rtdtrace_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 (); }
ksrc/skins/native/cond.c +1 -1
@@ -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 */ }
ksrc/skins/native/mutex.c +4 -3
@@ -170,7 +170,8 @@ int rt_mutex_create(RT_MUTEX *mutex, conif (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 (); }
ksrc/skins/native/task.c +3 -2
@@ -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
ksrc/skins/posix/cond.c +1 -1
@@ -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)));
ksrc/skins/posix/mutex.c +5 -5
@@ -85,7 +85,7 @@ int pse51_mutex_init_internal(struct __sxnarch_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 )) {
ksrc/skins/posix/mutex.h +3 -3
@@ -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_inreturn ;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)
ksrc/skins/rtai/sem.c +5 -5
@@ -28,7 +28,7 @@ void rt_typed_sem_init(SEM * sem, int vaint 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. */
ksrc/skins/rtdm/drvlib.c +8 -7
@@ -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,
ksrc/skins/vrtx/mx.c +3 -3
@@ -161,7 +161,7 @@ int sc_mcreate(unsigned int opt, int *erinith (&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 timif (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 ;
ksrc/skins/vxworks/semLib.c +3 -3
@@ -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 ; }
PATCH 6/13 Refactor mutex lockcnt tracking
In reply to Jan KiszkaThis 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.
--- ksrc/skins/native/cond.c | 6 ++---- ksrc/skins/native/mutex.c | 8 ++------ 2 files changed, 4 insertions(+), 10 deletions(-)
ksrc/skins/native/cond.c +2 -4
@@ -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);
ksrc/skins/native/mutex.c +2 -6
@@ -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, RTstrcpy (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
PATCH 7/13 Lockless fast path for xnsynch_acquire/release
In reply to Jan KiszkaThis 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.
--- 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(-)
configure.in +8 -8
@@ -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])
include/asm-generic/bits/bind.h +8 -8
@@ -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; }
include/asm-generic/features.h +12 -12
@@ -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 ; }
include/nucleus/synch.h +56 -2
84 lines not on this page · raw message
ksrc/arch/arm/Kconfig +1 -1
@@ -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
ksrc/arch/powerpc/Kconfig +1 -1
@@ -2,7 +2,7 @@ config XENO_GENERIC_STACKPOOL bool default y -config XENO_FASTSEM +config XENO_FASTSYNCH bool default y
ksrc/arch/x86/Kconfig +1 -1
@@ -2,7 +2,7 @@ config XENO_GENERIC_STACKPOOL bool default y -config XENO_FASTSEM +config XENO_FASTSYNCH bool default y
ksrc/skins/native/Kconfig +1 -1
@@ -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
ksrc/skins/posix/Kconfig +1 -1
@@ -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
ksrc/skins/posix/cb_lock.h +3 -3
@@ -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 */
ksrc/skins/posix/cond.c +9 -9
@@ -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 * cunsigned 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 ; }
ksrc/skins/posix/mutex.c +6 -6
@@ -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));
ksrc/skins/posix/mutex.h +2 -2
@@ -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; };
ksrc/skins/posix/syscall.c +10 -10
@@ -886,7 +886,7 @@ static int __pthread_mutexattr_setpsharereturn __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},
ksrc/skins/posix/thread.c +3 -3
@@ -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. */
ksrc/skins/psos+/Kconfig +1 -1
@@ -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.
ksrc/skins/rtai/Kconfig +1 -1
@@ -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
ksrc/skins/rtai/task.c +2 -2
@@ -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. */
ksrc/skins/uitron/Kconfig +1 -1
@@ -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
ksrc/skins/uitron/task.c +2 -2
@@ -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 ; }
ksrc/skins/vrtx/Kconfig +1 -1
@@ -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
ksrc/skins/vxworks/Kconfig +1 -1
@@ -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.
src/skins/posix/mutex.c +21 -21
151 lines not on this page · raw message
ksrc/nucleus/pipe.c +1 -1
@@ -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;
ksrc/nucleus/registry.c +2 -2
@@ -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 ;
ksrc/nucleus/select.c +1 -1
@@ -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);
ksrc/nucleus/synch.c +113 -19
209 lines not on this page · raw message
ksrc/drivers/testing/switchtest.c +1 -1
@@ -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);
ksrc/skins/native/alarm.c +1 -1
@@ -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 */
ksrc/skins/native/buffer.c +2 -2
@@ -192,8 +192,8 @@ int rt_buffer_create(RT_BUFFER *bf, consif (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);
ksrc/skins/native/cond.c +1 -1
@@ -160,7 +160,7 @@ int rt_cond_create(RT_COND *cond, constif (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);
ksrc/skins/native/event.c +1 -1
@@ -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 ;
ksrc/skins/native/heap.c +1 -1
@@ -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;
ksrc/skins/native/intr.c +1 -1
@@ -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 ;
ksrc/skins/native/mutex.c +1 -1
@@ -171,7 +171,7 @@ int rt_mutex_create(RT_MUTEX *mutex, conreturn -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 ;
ksrc/skins/native/queue.c +1 -1
@@ -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 ;
ksrc/skins/native/sem.c +1 -1
@@ -181,7 +181,7 @@ int rt_sem_create(RT_SEM *sem, const chaif ((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. */
ksrc/skins/native/task.c +3 -3
@@ -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 */
ksrc/skins/posix/intr.c +1 -1
@@ -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 ;
ksrc/skins/posix/mq.c +2 -2
@@ -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. */
ksrc/skins/posix/sem.c +1 -1
@@ -99,7 +99,7 @@ static int pse51_sem_init_inner(pse51_seinith (&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 ;
ksrc/skins/psos+/event.c +1 -1
@@ -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 ; }
ksrc/skins/psos+/queue.c +1 -1
@@ -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);
ksrc/skins/psos+/rn.c +1 -1
@@ -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);
ksrc/skins/psos+/sem.c +1 -1
@@ -114,7 +114,7 @@ u_long sm_create(const char *name, u_lonif (flags &SM_PRIOR ) bflags |=XNSYNCH_PRIO ; -xnsynch_init (&sem->synchbase, bflags); +xnsynch_init (&sem->synchbase, bflags,NULL );inith (&sem->link); sem->count = icount;
ksrc/skins/rtai/sem.c +1 -1
@@ -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 ;
ksrc/skins/rtdm/drvlib.c +5 -5
@@ -145,13 +145,13 @@ int rtdm_task_init(rtdm_task_t *task, coif (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, unsixnlock_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 *mutexxnlock_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); }
ksrc/skins/uitron/flag.c +1 -1
@@ -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;
ksrc/skins/uitron/mbx.c +2 -1
@@ -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;
ksrc/skins/uitron/sem.c +2 -1
@@ -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;
ksrc/skins/vrtx/event.c +1 -1
@@ -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 ;
ksrc/skins/vrtx/mb.c +1 -1
@@ -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);
ksrc/skins/vrtx/mx.c +2 -1
@@ -161,7 +161,8 @@ int sc_mcreate(unsigned int opt, int *erinith (&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);
ksrc/skins/vrtx/queue.c +1 -1
@@ -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;
ksrc/skins/vrtx/sem.c +1 -1
@@ -155,7 +155,7 @@ int sc_screate(unsigned initval, int optelse 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 ;
ksrc/skins/vxworks/module.c +1 -1
@@ -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 ;
ksrc/skins/vxworks/msgQLib.c +1 -1
@@ -174,7 +174,7 @@ MSG_Q_ID msgQCreate(int nb_msgs, int lenif (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;
ksrc/skins/vxworks/semLib.c +1 -1
@@ -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;
ksrc/skins/vxworks/syscall.c +1 -1
@@ -1171,7 +1171,7 @@ static void *__wind_shadow_eventcb(int einitq (&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);
ksrc/skins/vxworks/taskLib.c +1 -1
@@ -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
PATCH 8/13 Convert POSIX skin to fast xnsynch
In reply to Jan KiszkaMigrates 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.
--- 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(-)
ksrc/skins/posix/cond.c +2 -11
@@ -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. */
ksrc/skins/posix/mutex.c +59 -28
198 lines not on this page · raw message
ksrc/skins/posix/mutex.h +19 -119
181 lines not on this page · raw message
ksrc/skins/posix/syscall.c +9 -13
@@ -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(structreturn 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(strucif (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(strstatic 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 ; }
src/skins/posix/mutex.c +28 -27
153 lines not on this page · raw message
PATCH 9/13 Use fast xnsynch with native skin
In reply to Jan KiszkaImplement 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.
--- 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(-)
include/native/mutex.h +18 -5
@@ -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_MUextern "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,
ksrc/skins/native/cond.c +5 -6
@@ -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 */
ksrc/skins/native/mutex.c +179 -119
427 lines not on this page · raw message
ksrc/skins/native/syscall.c +56 -14
154 lines not on this page · raw message
src/skins/native/cond.c +30 -0
@@ -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)
src/skins/native/mutex.c +94 -8
135 lines not on this page · raw message
PATCH 10/13 Optionally replace pthread_getspecific with TLS variables
In reply to Jan KiszkaOn 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.
--- 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(-)
configure.in +23 -0
@@ -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
include/asm-generic/bits/bind.h +28 -13
58 lines not on this page · raw message
include/asm-generic/bits/current.h +12 -2
@@ -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_currenreturn (xnhandle_t )val; } +#endif /* ! HAVE___THREAD */ + +void xeno_set_current (void );#endif /* _XENO_ASM_GENERIC_CURRENT_H */
src/skins/native/init.c +14 -9
@@ -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 ); - } }
src/skins/native/task.c +21 -0
@@ -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 *coxeno_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; }
src/skins/vxworks/init.c +13 -7
@@ -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); +}
src/skins/vxworks/taskLib.c +19 -1
@@ -30,7 +30,14 @@#include <asm-generic/bits/current.h> #include "wrappers.h" +#ifdef HAVE___THREAD +__threadWIND_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)
src/skins/vrtx/init.c +13 -7
@@ -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); +}
src/skins/vrtx/task.c +13 -1
@@ -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);
PATCH 11/13 Report current shadow thread mode to user space
In reply to Jan KiszkaWith 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.
--- 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(-)
include/native/syscall.h +1 -0
@@ -134,6 +134,7 @@ struct rt_arg_bulk {u_long a3;u_long a4;u_long a5; +u_long a6; };#ifdef __KERNEL__
include/nucleus/shadow.h +2 -1
@@ -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);
include/nucleus/thread.h +4 -0
@@ -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;
ksrc/nucleus/shadow.c +20 -2
@@ -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, xncif (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, xncif (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)),
ksrc/skins/native/syscall.c +2 -1
@@ -191,7 +191,8 @@ static int __rt_task_create(struct pt_reif (__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; }
ksrc/skins/posix/syscall.c +9 -5
@@ -180,7 +180,8 @@ static int __pthread_create(struct pt_reif (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_availablestatic 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(structif (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(structstatic 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);
ksrc/skins/psos+/syscall.c +21 -13
@@ -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 *restruct 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); }
ksrc/skins/vrtx/syscall.c +3 -1
@@ -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; }
ksrc/skins/vxworks/syscall.c +3 -1
@@ -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; }
ksrc/skins/uitron/syscall.c +6 -2
@@ -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:
include/asm-generic/bits/bind.h +21 -1
@@ -17,6 +17,8 @@#ifdef HAVE___THREAD __thread xnhandle_t xeno_current __attribute__ ((tls_model ("initial-exec"))) = XN_NO_HANDLE; +__threadunsigned 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 );
include/asm-generic/bits/current.h +20 -0
@@ -6,14 +6,27 @@#ifdef HAVE___THREAD extern __thread xnhandle_t xeno_current __attribute__ ((tls_model ("initial-exec"))); +extern __threadunsigned 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 );
src/skins/native/task.c +10 -0
@@ -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 );
src/skins/posix/thread.c +31 -2
@@ -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(pthreadif (!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); }
include/vrtx/syscall.h +1 -0
@@ -85,6 +85,7 @@ struct vrtx_arg_bulk {u_long a1;u_long a2;u_long a3; +u_long a4; };#ifdef __KERNEL__
include/vxworks/syscall.h +1 -0
@@ -77,6 +77,7 @@ struct wind_arg_bulk {u_long a2;u_long a3;u_long a4; +u_long a5; };#ifdef __KERNEL__
src/skins/vrtx/task.c +6 -0
@@ -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,
src/skins/vxworks/taskLib.c +6 -0
@@ -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,
include/psos+/syscall.h +8 -0
@@ -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
src/skins/psos+/task.c +13 -3
@@ -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;
src/skins/uitron/task.c +9 -2
@@ -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(voidpthread_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;
PATCH 12/13 Ensure mode switch in mutex fast paths
In reply to Jan KiszkaWith 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.
--- src/skins/native/mutex.c | 31 ++++++++------- src/skins/posix/mutex.c | 94 +++++++++++++++++++++++++++-------------------- 2 files changed, 71 insertions(+), 54 deletions(-)
src/skins/native/mutex.c +17 -14
@@ -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_MUTif (!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,
src/skins/posix/mutex.c +54 -40
124 lines not on this page · raw message
PATCH 13/13 Catch inconsistent SMP feature support
In reply to Jan KiszkaWith 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.
--- include/asm-generic/features.h | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-)
include/asm-generic/features.h +24 -16
@@ -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 */
Quoted 20 lines · Jan Kiszka
Hopefully the last round, addressing remarks brought up on the last posting. The changes are:
[Patches 7-9]
- definexnsynch_owner_checkas 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 ofxeno_current_keyetc. frompthread_onceto a constructor
- translatepthread_getspecific== NULL intoXN_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)
Quoted 8 lines
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
Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux
/*
* Functional testing of the mutex implementation for native & posix skins. *
* Copyright (C) Gilles Chanteperdrix <[email protected]>,
* Marion Deveaud <[email protected]>,
* Jan Kiszka <[email protected]>
*
* 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; }
Quoted 20 lines · Jan Kiszka
Hopefully the last round, addressing remarks brought up on the last posting. The changes are:
[Patches 7-9]
- definexnsynch_owner_checkas 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 ofxeno_current_keyetc. frompthread_onceto a constructor
- translatepthread_getspecific== NULL intoXN_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)
Quoted 7 lines
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.
Signature · 1 line
Gilles.
Quoted 2 lines · Jan Kiszka
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.
Signature · 1 line
Gilles.