Visiting the idle-task performance again

Being frustrated with debugging my new port, searching for the reason the integer-math tasks fail every 15,000 iterations or so, I noticed something funny with the idle-task. Perhaps this could lead to another optimization. When running just the integer-math-tasks, performace is severly degraded by the idle-task consuming it’s timeslice doing absolutely nothing usefull. I think the same does apply with tasks waiting for eg external interrupts while other tasks are constantly doing heavy calculations at idle-priority. But why at idle-priority? Well, eg because the calc-tasks run continously and the idle-task must get control now and then to cleanup deleted-tasks-stuff. Running all at idle-priority it is imperative that round-robin handles timeslicing between these tasks. I think it might be a good idea to have a fast mechanism (only for the idletask??) to determine if another task would be swapped in if the idletask calls yield(). If so, the idletask indeed calls yield(), if not the idletask just loops as it does now. To (perhaps) simplify the design of such fast way of checking: It does not harm much if the idletask now and then makes a wrong descision and calls yield() to only be pre-empted again immediately.

Visiting the idle-task performance again

Hi, Im not sure if I quite follow what you are saying, but here are a few notes regarding the idle task. First, when using the cooperative scheduler The idle task will be preempted if there is a task with higher priority that is ready to run.  It does not wait until the end of the time slice.  Prior to version 2.6.1 the idle task would suspend the scheduler each loop to check for tasks that have been deleted (assuming INCLUDE_vTaskDelete was defined as 1).  This could cause a performance hit if the idle task used a lot of the processing time.  The introduction of ucTasksDeleted improved the efficiency here. The demo program has a lot of other tasks that run at the idle priority.  This is done to test the scheduler mechanism  running these tasks at a lower priority ensures that they get interrupted frequently  it would >not< however be a good idea for a real application as {as you say} it waists CPU time.  If you want low priority tasks such as this then they can be created as idle task hooks, or other mechanisms as described in the real time application design section of the FreeRTOS.org WEB site. One efficient way of using the idle task is to actually put the processor into sleep mode within the idle task.  It will wake when there is something to do. With the cooperative scheduler you have the problem of having to periodically yield the processor.  Again putting the processor into sleep mode can be a very efficient way of preventing this.  However, again the design at the application level should try to prevent wasted idle CPU cycles. Not sure if this answers you comments? Regards.

Visiting the idle-task performance again

Richard, thank you for all those lines of text. But, frankly, it is not what I meant (sorry if I’m a bit rude here. I’m still frustrated over my integer-error). I’ll try to explain better. Using the pre-emptive scheduler. Two tasks are ready to run: The idle-task and task X. (There may be several other tasks present, but let’s assume all of them is waiting for some external interrupt which will not occur for some time.). There are no tasks being created or deleted in the timeframe I would like to describe. So, there are just two tasks the scheduler has to worry about: The idletask which has nothing productive to do (no taskdeletes) and task X which does some heavy processing and never suspends or blocks. In the observed timeframe the only interrupt that will occur is the systemtick (=end-of-timeslice). This is what happens: - Systemtick-interrupt - A taskswitch to X occurs - X executes happily, doing all kinds of usefull calculations until - Systemtick-interrupt - A taskswitch to IDLE occurs - IDLE executes happily doing absolutely nothing usefull until - Systemtick-interrupt - A taskswitch to X occurs - X executes happily, doing all kinds of usefull calculations until - Systemtick-interrupt - A taskswitch to IDLE occurs - IDLE executes happily doing absolutely nothing usefull until - Systemtick-interrupt etc, etc As you can see, about 50% of the available cycles is wasted on the idle-task doing nothing but looping. My idea was about a way to recover these lost cycles and give them to a task that can make better use of them (X in the example). This could be done by always executing a yield in IDLE, even when using the pre-emptive scheduler. But this would degrade responsetimes to interrupts because yield is quite heavy. The idea is to have IDLE do a fast check if a yield would give control  to a task other than IDLE. If so, let IDLE yield. If not, let IDLE do another loop and then do this check again. Is this a better explanation?

Visiting the idle-task performance again

Hi, I think I understand what you are saying – but really my point is the same.  This is an application issue rather than a kernel issue.  If X always has something to do then either: + Give X a higher priority than the idle task so the idle task never runns, and the processor is always doing something usefull. or + Write the X functionality within an Idle task hook.  This way the X functionality will run when the idle task is given processing time – and the task delete functionality still works. ??? Regards.

Visiting the idle-task performance again

Yes, you got mypoint :-) And I do agree (up to some point) that it is application-specific. But I wouldlike to write my port as a general-use RTOS and therefore do not like to modify default RTOS-files. Regarding the options you gave: Setting X to ahigher priority than IDLE is only possible when there are no tasks being deleted in the system. Implementing X as part of IDLE would a good solution, but contradicts my desire to have the default RTOS-files untouched. And X wouldn’t "look" like an independant task anymore. (unable to kill, change priorities, etc). Therefore I came up with a third possibility: Have IDLE execute this pseudo-code during it’s loop: <code> if (there is a task on the readylist for IDLE-priority) && (this task != IDLE) {   yield(); } </code> This way IDLE will do just one iteration before giving the cpu back to a waiting task or IDLE loops just like it does now until the end of it’s slice or until some external interrupt.

Visiting the idle-task performance again

Hi Marcel, I wonder if you can explain this point in your last post: Regarding the options you gave: Setting X to ahigher priority than IDLE is only possible when there are no tasks being deleted in the system. I dont understand why this is so; Isn’t task priority setting your choice? Mike.

Visiting the idle-task performance again

Yes,of course. You set the priority of the tasks. When I say that setting the priority for X higher than the idle-priority is not possible, I mean that doing so will result in undesired side-effects. Because X is always ready-to-run (it continiously calculates), the idle-task will never run (because it has a lower priority). Because the idle-task is responsible for cleaning up when tasks are deleted, this is not desirable in a system where indeed tasks are deleted.

Visiting the idle-task performance again

ah ok, I understand what you are saying now. hum…

Visiting the idle-task performance again

The only drawback I can see in this is that when the idle task is the only task that is able to run it will be continuously yielding, which will lead to interrupts being disabled for a large proportion of time. I will give it some thought …. Regards.

Visiting the idle-task performance again

If you look at the pseudocode above, you’ll see that I only yield when this yield would pass control to another ( as in "not the IDLE-task") task. So, the behaviour of the idle-task will be: When there is at least one other task on the idle-priority-ready-list. In this case the idle-task will yield because it is 100% certain that another task will get control. If the idle-task finds out that there is no other task on the idle-priority-ready-list, it will continue it’s looping making it possible to be interrupted at any time. An important question would be: Is it possible to check on this idle-priority-ready-list without interrupts being disabled? If this leads to a situation where the idle-task incorrectly decides that there is another task, then this will only make the idle-task do a unneeded yield. No big problem. If it leads to a situation where the idle-task incorrectly decides that there is no other task, the idle-task will (worst case) run to the end of it’s timeslice. No big problem either. When not-touching-interrupts leads to crashes, then there is a problem…