Question regarding http://www.freertos.org/History.txt – Task Context Switching

Hello All, One of my current projects is running the 7.5.0 core – I do have a question regarding something I read in the current history.txt file:
  • Previously, when a task left the Blocked state, a context switch was performed if the priority of the unblocked task was greater than or equal to the priority of the Running task. Now a context switch is only performed if the priority of the unblocked task is greater than the priority of the Running task.
I hope I am misunderstanding what is being said here. Assuming we are not using co-routines and we are running a RISC core – all tasks have their own TCB (including stack(s)) – that are unique to each task. How is it then that a context switch isn’t done? I am assuming here that context switch is inclusive of the TCB being handled in the normal save/restore cycle as appropriate. The way the above reads to me is that the TCB’s are ‘shared’ – and somehow the task state is restored correctly. I don’t even want to get into the discussion of task starvation here – which would be exacerbated I would think. I am also assuming we are running in pre-emptive, multi-tasking mode. Please point out where I may have misunderstood something here. The only way I can understand the above is that we could be talking about co-routines being enabled (maybe). Thanks, John W.

Question regarding http://www.freertos.org/History.txt – Task Context Switching

Sorry if the statement is not clear. The history file necessarily only contains a summary of the change rather than any detail, but as I don’t understand your interpretation of the snippet you posted I guess in this case I must have made to open to misinterpretation. I think the change is much simpler than you are thinking. It has nothing to do with how context switches are actually performed, or how TCB or stacks are used. Those all remain the same. It only relates to a very minor change to when tasks of equal priority are scheduled in. It was made for one implementation reason, and a few technical logical reasons…but first what the change is, which is probably best described with an example scenario as follows. Prior to this change, the following execution pattern is possible: 1) Task A has priority 2 and is running, so priority 2 is the highest priority that is able to run. 2) An interrupt occurs. The interrupt unblocks Task B that also has priority 2, and the ISR requests a context switch (using portYIELDFROMISR/portENDSWITCHINGISR). 3) As Task B has an equal priority to Task A the scheduler will switch out Task A, switch in Task B, and return from the interrupt directly to Task B. 4) The next time the tick interrupt occurs Task A will be switched in again (assuming Task A and Task B are the only two ready state tasks at priority 2). Following the change, the same scenario will result in the following execution pattern: 1) Task A has priority 2 and is running, so priority 2 is the highest priority that is able to run. 2) An interrupt occurs. The interrupt unblocks Task B that also has priority 2, and the ISR requests a context switch (using portYIELDFROMISR/portENDSWITCHINGISR). 3) As Task B only has a priority equal to and not greater than Task A the scheduler does not change the task in the running state, and returns back to Task A when the interrupt completes. 4) The next time the tick interrupt occurs the newly unblocked Task B will be switched in (assuming Task A and Task B are the only two ready state tasks at priority 2). The implementation reason for the change is that, due to an optimisation made to the list mechanism a few versions ago, the change leads to more equal time sharing between tasks of equal priority. You can see that in the above scenario as after the change Task A uses its whole time slice, then task B uses its whole time slice, whereas prior to the change Task B only got a partial time slice before Task A was running again. One of the logical reasons for the change relates to the behaviour when configUSETIMESCLICING is set to 0. If time slicing is not used then a task in the Running state knows it will never unknowingly yield to another task of equal priority, even when it unblocks tasks of equal priority by sending them messages on queues or semaphores, etc. (here the task is being unblocked by another task, rather than by an interrupt as per the scenarios described in the above, but the same applies). That allows configUSETIMESLICING to be used to share resources between tasks of equal priority without needing any mutual exclusion primitives (use with caution – only recommended for advanced users!). I hope this clears up the confusion. Please let me know… Regards.

Question regarding http://www.freertos.org/History.txt – Task Context Switching

Richard, If you don’t mind – can you tell me what versions we’re talking about here? I have a project that is running 7.5.0 now – and I’ll have to have a good reason to rev that. Thanks, John