* [Xenomai-core] xenomai-solo vxWorks: know whether a task is safe or not
@ 2008-09-21 20:34 Niklaus Giger
2008-09-22 16:17 ` Philippe Gerum
0 siblings, 1 reply; 5+ messages in thread
From: Niklaus Giger @ 2008-09-21 20:34 UTC (permalink / raw)
To: xenomai-core
[-- Attachment #1: Type: text/plain, Size: 431 bytes --]
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?
Best regards
--
NIklaus Giger
[-- Attachment #2: taskIsSafe.diff --]
[-- Type: text/x-patch, Size: 1369 bytes --]
diff --git a/include/vxworks/taskInfo.h b/include/vxworks/taskInfo.h
index 61315d5..27b3cc6 100644
--- a/include/vxworks/taskInfo.h
+++ b/include/vxworks/taskInfo.h
@@ -50,6 +50,8 @@ TASK_ID taskNameToId(const char *name);
TASK_ID taskIdDefault(TASK_ID task_id);
+BOOL taskIsSafe(TASK_ID task_id);
+
BOOL taskIsReady(TASK_ID task_id);
BOOL taskIsSuspended (TASK_ID task_id);
diff --git a/vxworks/taskLib.c b/vxworks/taskLib.c
index f6253b2..7dd52ae 100644
--- a/vxworks/taskLib.c
+++ b/vxworks/taskLib.c
@@ -595,7 +595,7 @@ STATUS taskSafe(void)
}
pthread_mutex_lock(¤t->safelock);
-
+ current->safeCnt = 1;
return OK;
}
@@ -615,11 +615,24 @@ STATUS taskUnsafe(void)
return ERROR;
}
+ current->safeCnt = 0;
pthread_mutex_unlock(¤t->safelock);
return OK;
}
+BOOL taskIsSafe(TASK_ID tid)
+{
+ struct wind_task *task = find_wind_task(tid);
+
+ if (task == NULL) {
+ errno = S_objLib_OBJ_ID_ERROR;
+ return ERROR;
+ }
+
+ return (task->safeCnt > 0);
+}
+
STATUS taskIdVerify(TASK_ID tid)
{
struct wind_task *task = find_wind_task(tid);
diff --git a/vxworks/taskLib.h b/vxworks/taskLib.h
index 299d059..f743270 100644
--- a/vxworks/taskLib.h
+++ b/vxworks/taskLib.h
@@ -42,6 +42,7 @@ struct wind_task_args {
struct wind_task {
pthread_mutex_t safelock;
+ int safeCnt;
sem_t barrier;
struct WIND_TCB *tcb;
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Xenomai-core] xenomai-solo vxWorks: know whether a task is safe or not
2008-09-21 20:34 [Xenomai-core] xenomai-solo vxWorks: know whether a task is safe or not Niklaus Giger
@ 2008-09-22 16:17 ` Philippe Gerum
2008-09-22 19:45 ` Niklaus Giger
0 siblings, 1 reply; 5+ messages in thread
From: Philippe Gerum @ 2008-09-22 16:17 UTC (permalink / raw)
To: Niklaus Giger; +Cc: xenomai-core
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.
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Xenomai-core] xenomai-solo vxWorks: know whether a task is safe or not
2008-09-22 16:17 ` Philippe Gerum
@ 2008-09-22 19:45 ` Niklaus Giger
2008-09-26 8:36 ` Philippe Gerum
2008-09-26 8:37 ` Philippe Gerum
0 siblings, 2 replies; 5+ messages in thread
From: Niklaus Giger @ 2008-09-22 19:45 UTC (permalink / raw)
To: rpm; +Cc: xenomai-core
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?
Best regards
Niklaus
> 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;
> }
--
NIklaus Giger
Wieshoschet 6
CH-8753 Mollis
+41 (0)55 612 20 54 P
+41 (0)55 618 64 68 G
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Xenomai-core] xenomai-solo vxWorks: know whether a task is safe or not
2008-09-22 19:45 ` Niklaus Giger
@ 2008-09-26 8:36 ` Philippe Gerum
2008-09-26 8:37 ` Philippe Gerum
1 sibling, 0 replies; 5+ messages in thread
From: Philippe Gerum @ 2008-09-26 8:36 UTC (permalink / raw)
To: Niklaus Giger; +Cc: xenomai-core
[-- Attachment #1: Type: text/plain, Size: 1978 bytes --]
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.
[-- Attachment #2: solo-vxworks-add-task-restart.patch --]
[-- Type: text/x-diff, Size: 6062 bytes --]
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;
+ threadobj_unlock(&task->thobj);
+
args->entry(args->arg0, args->arg1, args->arg2, args->arg3,
args->arg4, args->arg5, args->arg6, args->arg7,
args->arg8, args->arg9);
@@ -356,7 +369,7 @@ STATUS taskInit(WIND_TCB *pTcb,
errno = S_intLib_NOT_ISR_CALLABLE;
return ERROR;
}
-
+
task = alloc_task();
if (task == NULL) {
errno = S_memLib_NOT_ENOUGH_MEMORY;
@@ -396,6 +409,30 @@ STATUS taskActivate(TASK_ID tid)
return OK;
}
+STATUS taskRestart(TASK_ID tid)
+{
+ struct wind_task *task;
+
+ if (threadobj_async_p()) {
+ errno = S_intLib_NOT_ISR_CALLABLE;
+ return ERROR;
+ }
+
+ /* The thread lock will be released at jump site. */
+ task = get_wind_task_or_self(tid);
+ if (task == NULL) {
+ errno = S_objLib_OBJ_ID_ERROR;
+ return ERROR;
+ }
+
+ task->tcb->status |= WIND_RESTART;
+
+ if (task == wind_task_current())
+ siglongjmp(task->ienv, 1); /* Does not return. */
+
+ return OK;
+}
+
TASK_ID taskSpawn(const char *name,
int prio,
int flags,
@@ -454,8 +491,10 @@ static STATUS __taskDelete(TASK_ID tid, int force)
if (task == NULL)
goto objid_error;
- if (task == wind_task_current()) /* Self-deletion. */
+ if (task == wind_task_current()) { /* Self-deletion. */
+ check_task_restart(task);
pthread_exit(NULL);
+ }
/*
* We always attempt to grab the thread safe lock first, then
@@ -517,11 +556,12 @@ TASK_ID taskIdSelf(void)
}
current = wind_task_current();
-
if (current == NULL) {
errno = S_objLib_OBJ_NO_METHOD;
return ERROR;
}
+
+ check_task_restart(current);
return (TASK_ID)current->tcb;
}
@@ -546,6 +586,7 @@ STATUS taskSuspend(TASK_ID tid)
if (task == NULL)
goto objid_error;
+ check_task_restart(wind_task_current());
ret = threadobj_suspend(&task->thobj);
put_wind_task(task);
@@ -648,7 +689,6 @@ STATUS taskPrioritySet(TASK_ID tid, int prio)
goto objid_error;
ret = check_task_priority(prio);
-
if (ret) {
put_wind_task(task);
errno = ret;
@@ -745,12 +785,13 @@ STATUS taskDelay(int ticks)
}
current = wind_task_current();
-
if (current == NULL) {
errno = S_objLib_OBJ_NO_METHOD;
return ERROR;
}
+ check_task_restart(current);
+
if (ticks == 0) {
sched_yield(); /* Manual round-robin. */
return OK;
diff --git a/vxworks/taskLib.h b/vxworks/taskLib.h
index 299d059..46718e1 100644
--- a/vxworks/taskLib.h
+++ b/vxworks/taskLib.h
@@ -20,6 +20,7 @@
#define _VXWORKS_TASKLIB_H
#include <semaphore.h>
+#include <setjmp.h>
#include <xenomai/threadobj.h>
#include <xenomai/registry.h>
#include <vxworks/taskLib.h>
@@ -53,6 +54,8 @@ struct wind_task {
struct threadobj thobj;
struct fsobj fsobj;
struct hashobj obj;
+
+ jmp_buf ienv;
};
int wind_task_get_priority(struct wind_task *task);
@@ -97,6 +100,8 @@ struct wind_task *get_wind_task_or_self(TASK_ID tid);
void put_wind_task(struct wind_task *task);
+void check_task_restart(struct wind_task *current);
+
extern struct hash_table wind_task_table;
#endif /* _VXWORKS_TASKLIB_H */
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Xenomai-core] xenomai-solo vxWorks: know whether a task is safe or not
2008-09-22 19:45 ` Niklaus Giger
2008-09-26 8:36 ` Philippe Gerum
@ 2008-09-26 8:37 ` Philippe Gerum
1 sibling, 0 replies; 5+ messages in thread
From: Philippe Gerum @ 2008-09-26 8:37 UTC (permalink / raw)
To: Niklaus Giger; +Cc: xenomai-core
[-- Attachment #1: Type: text/plain, Size: 1982 bytes --]
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.
[-- Attachment #2: solo-vxworks-add-task-restart.patch --]
[-- Type: text/x-diff, Size: 6063 bytes --]
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;
+ threadobj_unlock(&task->thobj);
+
args->entry(args->arg0, args->arg1, args->arg2, args->arg3,
args->arg4, args->arg5, args->arg6, args->arg7,
args->arg8, args->arg9);
@@ -356,7 +369,7 @@ STATUS taskInit(WIND_TCB *pTcb,
errno = S_intLib_NOT_ISR_CALLABLE;
return ERROR;
}
-
+
task = alloc_task();
if (task == NULL) {
errno = S_memLib_NOT_ENOUGH_MEMORY;
@@ -396,6 +409,30 @@ STATUS taskActivate(TASK_ID tid)
return OK;
}
+STATUS taskRestart(TASK_ID tid)
+{
+ struct wind_task *task;
+
+ if (threadobj_async_p()) {
+ errno = S_intLib_NOT_ISR_CALLABLE;
+ return ERROR;
+ }
+
+ /* The thread lock will be released at jump site. */
+ task = get_wind_task_or_self(tid);
+ if (task == NULL) {
+ errno = S_objLib_OBJ_ID_ERROR;
+ return ERROR;
+ }
+
+ task->tcb->status |= WIND_RESTART;
+
+ if (task == wind_task_current())
+ siglongjmp(task->ienv, 1); /* Does not return. */
+
+ return OK;
+}
+
TASK_ID taskSpawn(const char *name,
int prio,
int flags,
@@ -454,8 +491,10 @@ static STATUS __taskDelete(TASK_ID tid, int force)
if (task == NULL)
goto objid_error;
- if (task == wind_task_current()) /* Self-deletion. */
+ if (task == wind_task_current()) { /* Self-deletion. */
+ check_task_restart(task);
pthread_exit(NULL);
+ }
/*
* We always attempt to grab the thread safe lock first, then
@@ -517,11 +556,12 @@ TASK_ID taskIdSelf(void)
}
current = wind_task_current();
-
if (current == NULL) {
errno = S_objLib_OBJ_NO_METHOD;
return ERROR;
}
+
+ check_task_restart(current);
return (TASK_ID)current->tcb;
}
@@ -546,6 +586,7 @@ STATUS taskSuspend(TASK_ID tid)
if (task == NULL)
goto objid_error;
+ check_task_restart(wind_task_current());
ret = threadobj_suspend(&task->thobj);
put_wind_task(task);
@@ -648,7 +689,6 @@ STATUS taskPrioritySet(TASK_ID tid, int prio)
goto objid_error;
ret = check_task_priority(prio);
-
if (ret) {
put_wind_task(task);
errno = ret;
@@ -745,12 +785,13 @@ STATUS taskDelay(int ticks)
}
current = wind_task_current();
-
if (current == NULL) {
errno = S_objLib_OBJ_NO_METHOD;
return ERROR;
}
+ check_task_restart(current);
+
if (ticks == 0) {
sched_yield(); /* Manual round-robin. */
return OK;
diff --git a/vxworks/taskLib.h b/vxworks/taskLib.h
index 299d059..46718e1 100644
--- a/vxworks/taskLib.h
+++ b/vxworks/taskLib.h
@@ -20,6 +20,7 @@
#define _VXWORKS_TASKLIB_H
#include <semaphore.h>
+#include <setjmp.h>
#include <xenomai/threadobj.h>
#include <xenomai/registry.h>
#include <vxworks/taskLib.h>
@@ -53,6 +54,8 @@ struct wind_task {
struct threadobj thobj;
struct fsobj fsobj;
struct hashobj obj;
+
+ jmp_buf ienv;
};
int wind_task_get_priority(struct wind_task *task);
@@ -97,6 +100,8 @@ struct wind_task *get_wind_task_or_self(TASK_ID tid);
void put_wind_task(struct wind_task *task);
+void check_task_restart(struct wind_task *current);
+
extern struct hash_table wind_task_table;
#endif /* _VXWORKS_TASKLIB_H */
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2008-09-26 8:37 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-21 20:34 [Xenomai-core] xenomai-solo vxWorks: know whether a task is safe or not Niklaus Giger
2008-09-22 16:17 ` Philippe Gerum
2008-09-22 19:45 ` Niklaus Giger
2008-09-26 8:36 ` Philippe Gerum
2008-09-26 8:37 ` Philippe Gerum
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.