Re: [Xenomai-core] xenomai-solo vxWorks: know whether a task is safe or not
Niklaus Giger wrote: > Am Montag 22 September 2008 18.17:10 schrieb Philippe Gerum: >> Niklaus Giger wrote: >>> Hi >>> >>> For various reasons we were forced to examine under vxWorks 5.5 the >>> private WIND_TCB safeCnt field to determine whether a task was "safe" or >>> not. >>> >>> With the attached patch I try to add a taskIsSafe procedure to >>> xenomai-solo. It is probably not free from race condition, as I do not >>> know how to access a pthread_mutex. >>> >>> Would such (may be improved) patch find its way into the "official" >>> trunk? >> Assuming that VxWorks tracks the locking depth in safeCnt, that >> implementation would not properly account for nested locking (safelock is a >> recursive mutex). Additionally, since WIND_TCB is something of a >> semi-public structure in 5.x and earlier versions, we could just track the >> safe counter there as well, instead of adding a non-standard taskIsSafe() >> call; we already do that for the status field anyway. Here is a possible >> implementation: > > This implementation is okay for me, too. It seems to work, as far I could > test it. > > I however still have some issues because we used sometimes (for historical > reasons in order to emulate a pre-vxWorks home grown cooperative > mulit-tasking > operation system) a taskInit/taskActivate/taskRestart combination. > > Would it be a lot of work for you to add taskRestart to xenomai-solo? > I must admit that I always considered the task restart interface as a pure manifestation of the Evil, so its absence from SOLO might not be totally fortuitous. Trashing your system with that stuff is way to easy. Anyway, here is a possible implementation based on - cough, cough... - sigsetjmp(); I don't like it since it adds code to various hot paths just to provide a rarely used feature, so I may make this optional using a configuration knob at build time if/when I actually merge that, mmmh, thing. Please let me know how that works for you. -- Philippe. diff --git a/include/vxworks/taskLib.h b/include/vxworks/taskLib.h index 6334396..2f09de6 100644 --- a/include/vxworks/taskLib.h +++ b/include/vxworks/taskLib.h @@ -39,6 +39,7 @@ #define WIND_DELAY 0x4 #define WIND_DEAD 0x8 #define WIND_STOP 0x10 /* Never reported. */ +#define WIND_RESTART 0x20 /* Internal. */ typedef intptr_t TASK_ID; @@ -78,6 +79,8 @@ STATUS taskInit(WIND_TCB *pTcb, STATUS taskActivate(TASK_ID tid); +STATUS taskRestart(TASK_ID tid); + STATUS taskDelete(TASK_ID tid); STATUS taskDeleteForce(TASK_ID tid); diff --git a/vxworks/msgQLib.c b/vxworks/msgQLib.c index d591a7b..e3d071d 100644 --- a/vxworks/msgQLib.c +++ b/vxworks/msgQLib.c @@ -149,6 +149,8 @@ int msgQReceive(MSG_Q_ID msgQId, char *buffer, UINT maxNBytes, int timeout) return ERROR; } + check_task_restart(wind_task_current()); + mq = get_mq_from_id(msgQId); if (mq == NULL) { objid_error: @@ -217,6 +219,8 @@ STATUS msgQSend(MSG_Q_ID msgQId, const char *buffer, UINT bytes, UINT maxbytes; int ret; + check_task_restart(wind_task_current()); + mq = get_mq_from_id(msgQId); if (mq == NULL) { objid_error: diff --git a/vxworks/semLib.c b/vxworks/semLib.c index 6467354..dfc37cc 100644 --- a/vxworks/semLib.c +++ b/vxworks/semLib.c @@ -61,7 +61,9 @@ static STATUS xsem_take(struct wind_sem *sem, int timeout) if (threadobj_async_p()) return S_intLib_NOT_ISR_CALLABLE; - + + check_task_restart(wind_task_current()); + if (syncobj_lock(&sem->u.xsem.sobj, &syns)) return S_objLib_OBJ_ID_ERROR; @@ -196,8 +198,11 @@ static STATUS msem_take(struct wind_sem *sem, int timeout) return S_intLib_NOT_ISR_CALLABLE; current = wind_task_current(); - if (current != NULL && (sem->options & SEM_DELETE_SAFE)) - pthread_mutex_lock(¤t->safelock); + if (current != NULL) { + check_task_restart(current); + if (sem->options & SEM_DELETE_SAFE) + pthread_mutex_lock(¤t->safelock); + } if (timeout == NO_WAIT) { ret = pthread_mutex_trylock(&sem->u.msem.lock); diff --git a/vxworks/taskLib.c b/vxworks/taskLib.c index a9e12e7..7e74cf0 100644 --- a/vxworks/taskLib.c +++ b/vxworks/taskLib.c @@ -97,6 +97,8 @@ struct wind_task *get_wind_task_or_self(TASK_ID tid) if (current == NULL) return NULL; + check_task_restart(current); + /* This one might block but can't fail, it is ours. */ threadobj_lock(¤t->thobj); @@ -114,6 +116,12 @@ void put_wind_task(struct wind_task *task) threadobj_unlock(&task->thobj); } +void check_task_restart(struct wind_task *current) +{ + if (current && (current->tcb->status & WIND_RESTART) != 0) + siglongjmp(current->ienv, 1); +} + static void task_finalizer(struct threadobj *thobj) { struct wind_task *task = container_of(thobj, struct wind_task, thobj); @@ -253,6 +261,11 @@ static void *task_trampoline(void *arg) /* Wait for someone to run taskActivate() upon us. */ sem_wait(&task->barrier); + threadobj_lock(&task->thobj); + sigsetjmp(task->ienv, 1); /* For taskRestart(). */ + task->tcb->status &= ~WIND_REST
Re: [Xenomai-core] xenomai-solo vxWorks: know whether a task is safe or not
Niklaus Giger wrote: > Am Montag 22 September 2008 18.17:10 schrieb Philippe Gerum: >> Niklaus Giger wrote: >>> Hi >>> >>> For various reasons we were forced to examine under vxWorks 5.5 the >>> private WIND_TCB safeCnt field to determine whether a task was "safe" or >>> not. >>> >>> With the attached patch I try to add a taskIsSafe procedure to >>> xenomai-solo. It is probably not free from race condition, as I do not >>> know how to access a pthread_mutex. >>> >>> Would such (may be improved) patch find its way into the "official" >>> trunk? >> Assuming that VxWorks tracks the locking depth in safeCnt, that >> implementation would not properly account for nested locking (safelock is a >> recursive mutex). Additionally, since WIND_TCB is something of a >> semi-public structure in 5.x and earlier versions, we could just track the >> safe counter there as well, instead of adding a non-standard taskIsSafe() >> call; we already do that for the status field anyway. Here is a possible >> implementation: > > This implementation is okay for me, too. It seems to work, as far I could > test it. > > I however still have some issues because we used sometimes (for historical > reasons in order to emulate a pre-vxWorks home grown cooperative > mulit-tasking > operation system) a taskInit/taskActivate/taskRestart combination. > > Would it be a lot of work for you to add taskRestart to xenomai-solo? > I must admit that I always considered the task restart interface as a pure manifestation of the Evil, so it absence in SOLO might not be totally fortuitous. Trashing your system with that stuff is way to easy. Anyway, here is a possible implementation based on - cough, cough... - sigsetjmp(); I don't like it since it adds code to various hot paths just to provide a rarely used feature, so I may make this optional using a configuration knob at build time if/when I actually merge that, mmmh, thing. Please let me know how that works for you. -- Philippe. diff --git a/include/vxworks/taskLib.h b/include/vxworks/taskLib.h index 6334396..2f09de6 100644 --- a/include/vxworks/taskLib.h +++ b/include/vxworks/taskLib.h @@ -39,6 +39,7 @@ #define WIND_DELAY 0x4 #define WIND_DEAD 0x8 #define WIND_STOP 0x10 /* Never reported. */ +#define WIND_RESTART 0x20 /* Internal. */ typedef intptr_t TASK_ID; @@ -78,6 +79,8 @@ STATUS taskInit(WIND_TCB *pTcb, STATUS taskActivate(TASK_ID tid); +STATUS taskRestart(TASK_ID tid); + STATUS taskDelete(TASK_ID tid); STATUS taskDeleteForce(TASK_ID tid); diff --git a/vxworks/msgQLib.c b/vxworks/msgQLib.c index d591a7b..e3d071d 100644 --- a/vxworks/msgQLib.c +++ b/vxworks/msgQLib.c @@ -149,6 +149,8 @@ int msgQReceive(MSG_Q_ID msgQId, char *buffer, UINT maxNBytes, int timeout) return ERROR; } + check_task_restart(wind_task_current()); + mq = get_mq_from_id(msgQId); if (mq == NULL) { objid_error: @@ -217,6 +219,8 @@ STATUS msgQSend(MSG_Q_ID msgQId, const char *buffer, UINT bytes, UINT maxbytes; int ret; + check_task_restart(wind_task_current()); + mq = get_mq_from_id(msgQId); if (mq == NULL) { objid_error: diff --git a/vxworks/semLib.c b/vxworks/semLib.c index 6467354..dfc37cc 100644 --- a/vxworks/semLib.c +++ b/vxworks/semLib.c @@ -61,7 +61,9 @@ static STATUS xsem_take(struct wind_sem *sem, int timeout) if (threadobj_async_p()) return S_intLib_NOT_ISR_CALLABLE; - + + check_task_restart(wind_task_current()); + if (syncobj_lock(&sem->u.xsem.sobj, &syns)) return S_objLib_OBJ_ID_ERROR; @@ -196,8 +198,11 @@ static STATUS msem_take(struct wind_sem *sem, int timeout) return S_intLib_NOT_ISR_CALLABLE; current = wind_task_current(); - if (current != NULL && (sem->options & SEM_DELETE_SAFE)) - pthread_mutex_lock(¤t->safelock); + if (current != NULL) { + check_task_restart(current); + if (sem->options & SEM_DELETE_SAFE) + pthread_mutex_lock(¤t->safelock); + } if (timeout == NO_WAIT) { ret = pthread_mutex_trylock(&sem->u.msem.lock); diff --git a/vxworks/taskLib.c b/vxworks/taskLib.c index a9e12e7..7e74cf0 100644 --- a/vxworks/taskLib.c +++ b/vxworks/taskLib.c @@ -97,6 +97,8 @@ struct wind_task *get_wind_task_or_self(TASK_ID tid) if (current == NULL) return NULL; + check_task_restart(current); + /* This one might block but can't fail, it is ours. */ threadobj_lock(¤t->thobj); @@ -114,6 +116,12 @@ void put_wind_task(struct wind_task *task) threadobj_unlock(&task->thobj); } +void check_task_restart(struct wind_task *current) +{ + if (current && (current->tcb->status & WIND_RESTART) != 0) + siglongjmp(current->ienv, 1); +} + static void task_finalizer(struct threadobj *thobj) { struct wind_task *task = container_of(thobj, struct wind_task, thobj); @@ -253,6 +261,11 @@ static void *task_trampoline(void *arg) /* Wait for someone to run taskActivate() upon us. */ sem_wait(&task->barrier); + threadobj_lock(&task->thobj); + sigsetjmp(task->ienv, 1); /* For taskRestart(). */ + task->tcb->status &= ~WIND_RESTART;
Re: [Xenomai-core] xenomai-solo vxWorks: know whether a task is safe or not
Niklaus Giger wrote: > Hi > > For various reasons we were forced to examine under vxWorks 5.5 the private > WIND_TCB safeCnt field to determine whether a task was "safe" or not. > > With the attached patch I try to add a taskIsSafe procedure to xenomai-solo. > It is probably not free from race condition, as I do not know how to access > a pthread_mutex. > > Would such (may be improved) patch find its way into the "official" trunk? > Assuming that VxWorks tracks the locking depth in safeCnt, that implementation would not properly account for nested locking (safelock is a recursive mutex). Additionally, since WIND_TCB is something of a semi-public structure in 5.x and earlier versions, we could just track the safe counter there as well, instead of adding a non-standard taskIsSafe() call; we already do that for the status field anyway. Here is a possible implementation: diff --git a/include/vxworks/taskLib.h b/include/vxworks/taskLib.h index 510dabb..6334396 100644 --- a/include/vxworks/taskLib.h +++ b/include/vxworks/taskLib.h @@ -49,6 +49,7 @@ typedef struct WIND_TCB { void *opaque; int magic; int status; + int safeCnt; int flags; FUNCPTR entry; } WIND_TCB; diff --git a/vxworks/taskLib.c b/vxworks/taskLib.c index f6253b2..a9e12e7 100644 --- a/vxworks/taskLib.c +++ b/vxworks/taskLib.c @@ -283,7 +283,6 @@ static STATUS __taskInit(struct wind_task *task, int ret; ret = check_task_priority(prio); - if (ret) { errno = ret; return ERROR; @@ -307,6 +306,7 @@ static STATUS __taskInit(struct wind_task *task, tcb->magic = task_magic; tcb->opaque = task; tcb->status = WIND_SUSPEND; + tcb->safeCnt = 0; tcb->flags = flags; tcb->entry = entry; @@ -588,13 +588,13 @@ STATUS taskSafe(void) } current = wind_task_current(); - if (current == NULL) { errno = S_objLib_OBJ_NO_METHOD; return ERROR; } pthread_mutex_lock(¤t->safelock); + current->tcb->safeCnt++; return OK; } @@ -602,6 +602,7 @@ STATUS taskSafe(void) STATUS taskUnsafe(void) { struct wind_task *current; + int ret; if (threadobj_async_p()) { errno = S_intLib_NOT_ISR_CALLABLE; @@ -609,13 +610,14 @@ STATUS taskUnsafe(void) } current = wind_task_current(); - if (current == NULL) { errno = S_objLib_OBJ_NO_METHOD; return ERROR; } - pthread_mutex_unlock(¤t->safelock); + ret = pthread_mutex_unlock(¤t->safelock); + if (ret == 0) + current->tcb->safeCnt--; return OK; } -- Philippe. ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core