> I suggest you patch your kernel with the patch Philippe sent, adapt it
> to suit your needs, maybe changing TASK_DESC as in vxworks taskLib.h,
> test and debug it, then send us a patch which we will be happy to
> merge.
>
> --
> Gilles
Ok, I was about doing it.
I still have some questions about the migration of my app, as I don't know
Xenomai in details.
Here is part of my code which aims at defining a procedure to restart a
task. If you have time to have a look on it, it would be helpful.
/*****************************************************************************
*
* vx_t_restart - task restart routine.
*
* Restart a task with its original priority and mode.
*
* RETURNS:
* EOK if successful.
* ERR_OBJID if the task id is invalid.
* ERR_OBJDEL if the task is deleted by another task while in t_restart.
* ANAIS_ERROR if an unknown failure in taskRestart.
*/
UINT32 vx_t_restart ( UINT32 tid, /* task ID of task to restart */
UINT32 args[4]) /* new
arguments for task */
{
WIND_TCB *pTcb; /* the task's control block */
P2V_SHADOW_TCB *pShadow; /* the TCB extension */
UINT32 tmp1;
UINT32 i;
UINT32 vxArgs[10]; /* larger arg array for vxWorks */
UINT32 lock;
struct sigtcb *pSigTcb;
/* get the task's TCB, and check for validity */
if (tid == 0)
tid = taskIdSelf();
if( (pTcb = taskTcb(tid)) == NULL)
return (ERR_OBJID);
/* get the TCB extension and make sure it's a p2v task */
if( (pShadow = taskExtTcb(tid)) == NULL )
return (ERR_OBJID);
if (tid == taskIdSelf())
{
/* self restart not possible because we have we have no context
* from which to sucessfully terminate or reinitialize ourself.
* We defer all self restarts to the exception task.
* To self restart within a critical section, we must TASK_UNSAFE ()
* until the safeCnt == 0. Otherwise, the excTask would block
* forever trying to terminate us.
*/
while (pTcb->safeCnt > 0) /* make task unsafe */
TASK_UNSAFE ();
taskSpawn ("t_restart", 0, 0,
6000, ( FUNCPTR)vx_t_restart, (int) tid,
0, 0, 0, 0, 0, 0, 0, 0, 0);
FOREVER
taskSuspend (0); /* wait for restart */
}
/* The following loop allows the target task to run until
* it gives up all critical resources and can be suspended
* without causing an interlock. The criteria for suspending
* the task here are the same as deleting a task -- both the
* safeCnt and the lockCnt must be 0. Note: this loop does
* things which should never appear in user code, namely entering
* kernel mode and directly manipulating task queues.
*/
lock = intLock();
while ((pTcb->safeCnt > 0) ||
((pTcb->status == WIND_READY) && (pTcb->lockCnt > 0)))
{
kernelState = TRUE; /* KERNEL ENTER */
intUnlock (lock); /* UNLOCK INTERRUPTS */
if (pTcb == taskIdCurrent)
{
pTcb->safeCnt = 0; /* unprotect */
pTcb->lockCnt = 0; /* unlock */
if (Q_FIRST (&pTcb->safetyQHead) != NULL) /* flush safe
queue */
windPendQFlush (&pTcb->safetyQHead);
windExit (); /* KERNEL EXIT */
}
else /* wait to destroy */
{
if (windPendQPut (&pTcb->safetyQHead, WAIT_FOREVER) != OK)
{
windExit (); /* KERNEL EXIT
*/
return (ANAIS_ERROR);
}
switch (windExit())
{
case ERROR : /* timed out */
return (ANAIS_ERROR);
default : /* we were
flushed */
break;
}
}
/* Make sure target task didn't exit */
lock = intLock (); /* LOCK INTERRTUPTS */
if (TASK_ID_VERIFY (pTcb) != OK)
{
intUnlock (lock); /* UNLOCK
INTERRUPTS */
return (ERR_OBJDEL);
}
}
/* Suspend the task being restarted (this already happened above
* if the task is restarting itself.
*/
taskSuspend (tid);
TASK_SAFE(); /* protect deleter */
/* At this point target task is suspended and can't be deleted
* by anyone else. If task is restarting itself, it is safe from
* deletion.
*/
/* Save the pointers to the TCB extension, since the VxWorks TCB will
* be wiped clean by taskRestart.
*/
/* Set reserved field to NULL because delete hook runs when a
* task is restarted -- and we don't want that!
*/
tmp1 = (UINT32) pTcb->pTaskVar;
pTcb->pTaskVar = NULL;
/* Reuse signal info structure in the task stack */
pSigTcb = pTcb->pSignalInfo;
intUnlock(lock); /* INT UNLOCK */
/* Disarm all the task's timers.
* Need to taskLock because we don't want timers expiring and
* trying to update linked list while we are.
*/
/* set the task's new arguments */
if ( args == NULL )
vxArgs[0] = vxArgs[1] = vxArgs[2] = vxArgs[3] = 0;
else
for ( i = 0; i < 4; i++ )
vxArgs[i] = args[i];
taskArgsSet (pTcb, pTcb->pStackBase, (int *) vxArgs);
/*
* Note: vxWorks' taskRestart keeps the current stack, rather than
* reducing the stacksize to the original.
* To keep the outermost stack frame intact, must modify
* the vxWorks option word -- otherwise the stack would be
* reinitialized to 0xee's
*/
pTcb->options |= VX_NO_STACK_FILL;
/* don't let restarted task run till its TCB is fixed */
taskLock (); /* TASK LOCK */
if (taskRestart (tid) == ERROR)
{
taskUnlock (); /* TASK UNLOCK */
if (errno == S_objLib_OBJ_DELETED)
return (ERR_OBJDEL);
else
return (ANAIS_ERROR);
}
/* Reconnect TCB extension */
pTcb->pTaskVar = (struct taskVar *) tmp1;
/* reinitialize signal info */
bzero ((char *) pSigTcb, sizeof (struct sigtcb));
for (i = 0; i <= _NSIGS; i++)
pSigTcb->sigt_qhead[i].sigq_next = pSigTcb->sigt_qhead[i].sigq_prev =
&pSigTcb->sigt_qhead[i];
pTcb->pSignalInfo = pSigTcb;
/*
* restarting a task clears all pending signals and events and resets
* the signal handler.
*/
taskUnlock (); /* TASK UNLOCK */
taskUnsafe (); /* TASK UNSAFE */
return (EOK);
}
There are still WIND_TCB members use in this part of code, and I thing it's
possible to simplify this routine...
What do you think about it ?
Matthieu
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help