This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Stop task partway through execution

Other Parts Discussed in Thread: SYSBIOS, TM4C1294NCPDT

Hello,


Is there a way to stop a task partway through it's execution?  For example, lets say I have a task with the normal while() loop and it is running through a series of functions after its corresponding semaphore has been posted.  If I want to stop the task before it loops back around to the semaphore_pend(), how can I do that?  I'm assuming either an interrupt or input from another task will be the trigger to stop the first task's execution.  I just don't know how to actually stop a task mid stride.

Thanks,

Eric

  • Hi Eric,

    A task cannot control another task (i.e. stop another task).

    However, what you can do, is wait for an event which will indicate that you wish to terminate the task.

    So in the task that you want to be "terminated", you wait on two events (Semaphore or task termination). When an event occurs, you check first if task termination is requested. If yes, you can use Task_exit(...) to stop the execution. You would then use Task_delete(...) to recover the memory space used by the terminated task, otherwise you might run out of memory if you create tasks without deleting them.

    You can read about events in the TI-RTOS kernel User Guide (if you have TI-RTOS already installed on your computer, the documentation will be located in the following folder (Just open the Documentation Overview html page) : C:\ti\tirtos_cc13xx_cc26xx_2_18_00_03\docs )

    Regards,
    Michel
  • Hi Michel,


    Thanks for the tip!  From your description, it seems like I can choose to exit the task by pending on an event and then taking the appropriate action depending on what triggered the event.  In other words, I can exit the task just as it is coming unblocked.  But, it is possible to exit a task while it is running? For example,

    TaskOne()
    {

    while(true)
    {

    Semaphore_pend();

    Call functionOne();

    Call functionTwo();

    Call functionThree();

    Call functionFour();

    Call functionFive();

    }

    }

    If the trigger to stop the task execution occurs while it's processing functionThree(), how can I exit the task before it calls functionFour?  In my application, one of my tasks repeatedly processes a fairly large number of user commands from a file.  These commands can include multiple "wait" calls of a few minutes in duration each, for which I'm using the task_sleep() function.  So it can take 20-30 minutes before the task processes all the functions and returns back to the semaphore_pend().  If the trigger to exit happens, I need to be able to respond within about a second and exit.  Since everything else  happens very quickly, it's almost certain that, if a trigger exit happens, it will occur while the task is sleeping.  So maybe I should amend my original question and ask if it's possible to cause a task which is sleeping to exit?

    Thanks again,

    Eric

  • Eric,

    By the way, which device are you using? And which TI-RTOS and SYSBIOS version are you working with? I don't think it would make much difference but just making sure that I give you the proper answer.

    I've looked at the TI-RTOS documentation for the CC13XX/CC26XX, (you should have something specific to your device) and you can confirm what I have found. The documentation on my computer was located in that folder: C:\ti\tirtos_cc13xx_cc26xx_2_18_00_03\docs (I presume yours would be in a similar location) and I opened the Documentation Overview html page. In the kernel cdoc, I found the task module (under ti\sys\knl\Task). I don't think that there would be much difference between your device and the CC26XX, but it's a good thing to see all the available functions for Tasks (and maybe there is something in there that I don't know about).

    In my document, there is a constant Task_E_deleteNotAllowed which would be set if you are not allowed to delete a task. I believe this error would be set when trying to delete (or destruct depending on how you created your task) a non-terminated task. You could test it by creating an empty project and adding two tasks to try to delete one of them from the other task. My hypothesis is that the application will crash or assert, but it shouldn't be too hard to try. I don't believe that TI-RTOS was designed to kill tasks like Linux for example.

    If you cannot delete a running task, the only option that remains would be to check when termination was requested between each function call. I would use a global variable in the file where the task is to be terminated. And to avoid adding an additional event module to your application, you can re-use your task semaphore when requesting the termination (i.e. you set the variable and you post to the semaphore; in case, your task is waiting). After you exit the Semaphore_pend, you check first that your task does not need to terminate itself.

    TaskOne()
    {
      taskExitIsSet = false;
      while(true)
      {
        Semaphore_pend();
        if (taskExitIsSet) TaskExit();
        Call functionOne();
        if (taskExitIsSet) TaskExit();
        Call functionTwo();
        if (taskExitIsSet) TaskExit();
        Call functionThree();
        if (taskExitIsSet) TaskExit();
        Call functionFour();
        if (taskExitIsSet) TaskExit();
        Call functionFive();
        if (taskExitIsSet) TaskExit();
      }
    }
    
    void requestTerminate(void)
    {
      taskExitIsSet = true;
      Semaphore_post(...);  
    }

    Not the prettiest solution, but you won't have to go through the whole loop before exiting the task.

    Michel

  • Hi Michel,


    Thanks again for your time and input!  I'm using a TIVA TM4C1294NCPDT processor with RTOS version 2.16 and BIOS 6.45.  I do see the note about the deleteNotAllowed and I'll have to read through this further.  I also need to read through the Kernel documentation a bit more as there seems to be discussion there I haven't seen yet on the various task states and changing them.

    Since I'm reading the commands from a file, it will be easy to implement your solution in a simple loop that reads the command, checks taskExitIsSet, and calls the appropriate function if not.  The only downside is that if the function that gets called is Task_sleep(), I won't get another opportunity to check taskExitIsSet until the sleep period is over.  I was hoping there would be a way to interrupt the sleep state, but I'm not sure this is possible.

    Eric

  • There is always a way to work around obstacles. If terminating a task is not possible, you could have a sort of "state machine" and instead of using BIOS_WAIT_FOREVER, you could put your sleep delay for timeout. When a timeout occurs, Semaphore_pend returns FALSE (or false, whichever is defined). You just need

    So your code would now look like this:

    typedef enum {
    state_1 = 0,
    state_1_wait,
    state_2,
    state_2_wait,
    ....
    };
    
    TaskOne()
    {
      static uint8_t currentState = state_1; // it could also be global in the file
      taskExitIsSet = false;
      uint32_t someTimeoutInTicks = BIOS_WAIT_FOREVER; // the first wait will be forever
      while(true)
      {
        if (Semaphore_pend(yourSemHandle, someTimeoutInTicks))
        {
          // the semaphore was posted, we check if we need to terminate
          if (taskExitIsSet) TaskExit();
        }
        //else
        //{
        //  A timeout occurred so that means the sleep delay is over
        //}
    
        switch(currentState)
        {
        case state_1:
          // execute everything up to the Task_sleep(..)
          Call functionOne();
          someTimeoutInTicks = SOME_TIME_DELAY;
          currentState++;
          break;
        case state_1_wait:
          // sleep is finished (semaphore timed out)
          // execute any steps after the sleep
          // the delay can BIOS_NO_WAIT to jump to the next step right away or any other value for an additional delay
          someTimeoutInTicks = BIOS_NO_WAIT;
          currentState++;
          break;
    
        ...
        ...
        ...
    
        default:
          // you can do error checking here if you want
          currentState = 0;
          break;
      }
    }
    
    void requestTerminate(void)
    {
      taskExitIsSet = true;
      Semaphore_post(...);  
    }

    I believe that's as much help as I can provide.

    Regards,

    Michel

  • Hi Michel,

    I think this could work!  I hadn't thought about using the wait period as the timeout for the Semaphore_pend().  I'm going to give this a go.

    Much appreciated!

    Eric