calling vTaskResume() before the scheduler is started may lead to a call to portYIELD()

oprs wrote on Sunday, September 27, 2015:

Hi rtel,

My motivation was to present a minimal example, stripped out of all context, in order to trigger the issue (with no or little concern on how ugly/stupid the code may end up looking like). Sorry if I didn’t make my point clear about that.

The issue I’m raising is the following:

This sequence does induce a crash:

   (void)xTaskCreate( task, "task1", 128, NULL, 1, &t1 );
   (void)xTaskCreate( task, "task2", 128, NULL, 1, &t2 );

   vTaskSuspend( t1 );
   vTaskResume( t1 );

This one does not:

   (void)xTaskCreate( task, "task1", 128, NULL, 1, &t1 );

   vTaskSuspend( t1 );
   vTaskResume( t1 );

Nor does this one (note the priority change on t2):

   (void)xTaskCreate( task, "task1", 128, NULL, 1, &t1 );
   (void)xTaskCreate( task, "task2", 128, NULL, 2, &t2 );

   vTaskSuspend( t1 );
   vTaskResume( t1 );

Thus, the crash occurs where vTaskResume(t1) is called under the following conditions:

  • the scheduler hasn’t started yet,
  • t1 is in xSuspendedTaskList,
  • t2 is in pxReadyTasksLists[n], with n <= t1’s uxPriority

Furthermore, I was able to observe that the crash only occurs after control is given to t1. In my original example (top post), t1 calls vTaskDelay() in a loop; unsurprisingly, this is where it all goes wrong.

Perhaps this is just me splitting hairs here. As you said, this sequence does not achieve anything anyway.


A quick word on the context since it might be relevant to the discussion.

My application (micro-satellite) involves running several tasks, each in charge of one aspect of the mission: power monitoring, ground communication, attitude control, etc… Which tasks are active at one given time depends on the mode the satellite is in. The mission plan can be expressed in terms of a directed graph, with each node representing a mode. Transitions between modes are triggered in response to external events (sensor readouts, commands from the ground, etc…).

Also running along those tasks are (higher priority) driver tasks, essentially implementing a one-to-one threaded model; I won’t bother you with this since I don’t believe it adds much to the discussion.

The first code sequence above pretty much illustrates all that. Say t1 and t2 are applicative tasks (initially suspended). The dimwitted suspend/resume sequence that prompted my first post occurs during the setting up of the tasks associated to the initial state of my mission graph.

Of course there are a million ways around this, the most obvious to me being to create a parent task (think “init” in unix terms) and to manage everything from there. No more fiddling with task management before the scheduler is started -> problem gone.

My initial point was just about what I thought was (and still think is :wink: a slight inconsistency in how FreeRTOS deals with vTaskSuspend()/vTaskResume() before control is passed to the scheduler (admittedly very marginal case).

Thanks a lot for your input (to yourself and to Hein). I have to say that getting a glimpse of the internals of FreeRTOS only increased my confidence in it.

Regards,
-Olivier.