My company is investigating what it would take to modify FreeRTOS to be truly tickless. What that means is we can make threads operate with much finer timing resolution than 1 ms. This is necessary for our applications. In the modern age of 100+ MHz processors, only being able to manage time on 1 ms boundaries is lame. That’s 100,000 instructions.
Our present code uses a complex interrupt driven timer layer under FreeRTOS that has task queues, timed events, and so forth that is complex to maintain and use and it only exists because FreeRTOS timing granularity is too coarse. We desire sub 10 us granularity, or even down to 1 us if we can get it. The idea is that a “real time” operating system should allow us to have things happen at “precise time”, and that means better than 1 ms granularity.
An obvious “solution” is to redefine the tick to be faster, but it is impractical to have a tick interrupt every 10 us.
Instead, we propose to change the system to truly tickless. What this means is the scheduler only runs when it needs to, not gratuitously every 1 ms. This is accomplished by using a timer which has a compare interrupt set to the next time the scheduler needs to run. For example, some future higher priority task wants to run in 4.37 ms, so set the timer compare to that time. The currently running task then runs without interruption until that time expires, the scheduler runs, and the high priority task is activated.
For low power sleep, the implementation is to notice when the idle task will run longer than some minimum time (look ahead to the next timed event), put the processor to sleep during that time, and then wakeup with sufficient time to fix up timers and state to keep running.
For time slicing, any thread can be given a fixed amount of time when it starts to run, say 1 ms. If the thread doesn’t complete in that time, the scheduler is triggered by the timer and context switch can occur. So time slicing can happen. You can weight threads, giving some threads more “run time” per slice than others. Say one thread is 1 ms and another is 5 ms, you now load balance 5 to 1.
I am aware of the opposition to true tickless mode, for example this from 7 years ago from rtel:
As you already noted, time slicing won’t work if the OS is always tickless.
Not true. Give each thread a limited time to run before scheduler runs again and you can time slice just fine. The next timer interrupt is the lesser of the time slice chunk for the current thread or the soonest next thread timer event. Like I indicated above, this also gives you ability to time slice “unfairly” by controlling the slice size for each thread if you want.
It is difficult to keep re-programming the clock without slippage between the RTOS system time and calendar time.
Not if you do it properly. The timer would be free running with a compare register, so time never slips. You simply move the compare point. Using one shot timing is lame and does suffer the issues you indicate, but that’s not how it should be implemented.
Under heavy load it is simply more efficient to use a fixed per-calculated time period than to re-calculate a time period each time the scheduler runs and then re-program the clock.
That seems backwards. Running the scheduler gratuitously when you don’t have to is wasting resources. Moving the timer compare interrupt is just adding something to a compare value which is very fast.
For example presently, the scheduler starts a thread that finishes in 0.95 ms, scheduler runs, new thread starts. 0.05 ms into the new thread, tick, scheduler runs again and maybe even slices to another thread. That hardly seems efficient or fair. Instead, each new thread slice starts with a 1 ms time it can run before being “ticked off” (ha!).
Using the tickless idle mode CPU cycles are dedicated to saving power only when it is possible to save power, that is, when it is known nothing wants to run.
True tickless mode enables sleeping even for very brief periods like 250 us. All you need is the idle thread to see the next event isn’t too close (which depends on the processor sleep/wake timings) and then you can sleep. For some applications which do a lot of little things very often, you may never sleep in the current system due to 1 ms time granularity.
It is very common for people to add their own code to the tick interrupt using a tick hook.
That’s horrible, IMO, and should not be encouraged.
But in any case, you can define a thread that runs every 1 ms if you want and get back this capability. The true tickless mode can even allow sleep to occur with such a system since it can sleep sub 1 ms times.
The implementation covers more use case scenarios (FreeRTOS is probably used in a more wide number of use cases than Contiki).
True tickless mode can do everything the tick mode can do, so I don’t understand this point. In the limit, if you force all times to be 1 ms boundaries, you have the present tick system, so what can’t tickless mode do?
Backward compatibility with old versions of FreeRTOS.
That can be maintained. The old threads simply have 1 ms boundary timings but we can still sleep and can still do finer grained timing for threads using the new capability.
Probably other reasons too, the decision was taken quite a long time ago.
Right, times have changed. We are no longer in the 8 bit 2 MHz microcontroller era any more. As processors have grown, the 1 ms tick has become some sort of codified commandment that hasn’t scaled with time. I think it might be time to reassess that decision in light of current and future embedded systems, and the heavy emphasis on low power operation. It gets to the very heart of what it means to be “real time”.
Obviously this post is meant to be a conversation starter on the merits and issues of this idea. What do you think?
Mike C.