> 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

Reply via email to