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.

Task scheduler and Task states

Other Parts Discussed in Thread: SYSBIOS

I have a Task scheduling problem in SysBios (6.33.5.46).

I'm creating a (static) task "InitTask" with the highest priority whose purpose is to initialize some IPC resources (which can't be initialized in main).  These resources may be used by any other Task.  I want the code to be composable, so instead of blocking all other tasks on a semaphore until the initialization is done, InitTask (the only task at the highest priority) calls Task_disable on entry and Task_restore after it's done with the initializations.

However, when I call Task_restore, the kernel switches to a lower priority Task, instead of continuing in InitTask (which would log some info and exit).  At this point the RTOS Object Viewer says InitTask is blocked, the current Task is Running, and all other Tasks are Ready.  Later on, my process doesn't exit, apparently because InitTask is still blocked.

BTW, I'm suspicious about the ROS because it claims when I'm in Task_allBlockedFunction, it claims a Task I know has terminated is Running.

So, am I doing something wrong, or is the scheduler broken?

Thanks

  • Hi Elron A Yellin,

    Can you please take a screen shot of ROV that's showing what you say above?  It will be helpful for me to see that.

    Also, I just want to make sure that you are aware that a priority of "1" is lowest priority, and priority of "15" is the highest priority for tasks ... just to make sure your priorities haven't been configured backwards by any chance ...

    Steve

  • Here I'm stopped at Task_restore in my highest priority task "InitTask".  I'll step over Task_restore, and end up in task "tsk1".  (Same results if I step into Task_restore and through the kernel code.)

  • Later tsk1 exits, and then LoggerTask exits (which I know because the last thing they do is a System_printf) I end up in Task_allBlockFunction

  • Hi Elron A Yellin,

    I see what you are talking about with ROV seeming out of sync.  It looks as if it's one step behind.

    Can you try hitting the refresh button in ROV when you hit your break point for the Task_restore() call inside your InitTask() function?  Does the InitTask state changed to 'Blocked' at that point?  Similarly, when you are in Task_allBlockedFunction() if you hit refresh does the mode of LoggerTask change to Terminated?

    I'm also wondering about the functions that you are calling within the Task disable/restore block:

    • OpenStdOut()
    • LogTransport::Instance().Connect();
    • UnitTest::TestMgr::Instance().RunTests(logger);

    Is it possible these functions are making any blocking calls?


    Steve

  • Sorry, I should have mentioned up front that the refresh button had no effect on what I was seeing in the RTOS viewer.

    OpenStdOut sets up a MessageQ which I use for a printf facility which outputs on the host's stdout.

    LogTransport::Instance().Connect sets up another MessageQ which I use to transport xdc.runtime.Log messages to the host's stdout (in a task with priority 1).

    (Frankly I was surprised that these two features were not already available.)

    So they each do Ipc_attach, Ipc_writeConfig, HeapMemMP_open, MessageQ_registerHeap, MessageQ_open (and a few System_printfs).  Additionally, OpenStdOut constructs a GateMutex. 

    RunTests runs all the unit tests (which get registered at static init time) and prints the results via the MessageQ set up in OpenStdOut.

    Despite any that happens in InitTask, shouldn't it be resumed by Task_restore?

    Elron

  • Elron,

    Elron A Yellin said:
    Sorry, I should have mentioned up front that the refresh button had no effect on what I was seeing in the RTOS viewer.

    Looking at your screen shot, I was wondering what OS are you running on your comp?  Are you running Linux? (it doesn't look like Windows... I'm wondering if this out of sync issue could be a problem on Linux that we don't see on Windows ...).

    Any chance that you've hit the "pause" button on ROV?

    Elron A Yellin said:
    Despite any that happens in InitTask, shouldn't it be resumed by Task_restore?

    Not necessarily.  Any code that may cause the Task to block should *not* be called within a Task_disable/restore block.  Doing so can lead to unpredictable results.

    Would you mind trying an experiment?  I'm curious what might happen if you comment out the calls to these functions:

    • OpenStdOut()
    • LogTransport::Instance().Connect();
    • UnitTest::TestMgr::Instance().RunTests(logger);

    Do you still have the same problem?

    Steve

  • Steven Connell said:

    Any code that may cause the Task to block should *not* be called within a Task_disable/restore block.  Doing so can lead to unpredictable results.

    Would you mind trying an experiment?  I'm curious what might happen if you comment out the calls to these functions:

    • OpenStdOut()
    • LogTransport::Instance().Connect();
    • UnitTest::TestMgr::Instance().RunTests(logger);

    Do you still have the same problem?

    The problem goes away.  So I get the message that blocking can't be done inside Task_disable/Task_restore.  Please add mention of that in the SysBios User Guide-- I don't see it there, though I do see the constraint mentioned in ccs help (which I might have seen and assumed it was a caution only about potential deadlocks, not general undefined behavior).

    Anyway, I guess I can either sacrifice composability and wait on a semaphore at the top of every other Task, or in InitTask I can iterate over Tasks changing their priorities to -1, do my setup, and then restore the original priorities.

    Thanks for the help

  • Elron A Yellin said:
    Anyway, I guess I can either sacrifice composability and wait on a semaphore at the top of every other Task, or in InitTask I can iterate over Tasks changing their priorities to -1, do my setup, and then restore the original priorities.

    Another idea ... why not create your "other" tasks dynamically?  This would ensure that they don't run until after your InitTask is through.

    E.g.:

    Void InitTask_func(...)

    {

    ...

    OpenStdOut()
    LogTransport::Instance().Connect();
    UnitTest::TestMgr::Instance().RunTests(logger);

    <call Task_create() to dynamically create Tasks here.  They won't run until this function exits ...>

    System_printf("InitTask complete\n");

    }