Deep dive: High-Resolution vs. Tick-Resolution Scheduling
Every RTOS has to decide when a sleeping thread wakes. Tick-Resolution Scheduling wakes it on a tick of a periodic interrupt. High-Resolution Scheduling, in KideRT, sets the hardware timer for the time it asked for. This deep dive starts with what that changes in your code, works down through the kernel to the timer, and ends with a conclusion.
Thread asleepThread runsTimer interrupt
For a 2.3 ms sleep, High-Resolution Scheduling sets the timer for 2.3 ms, and the thread wakes after 1 timer interrupt. Tick-Resolution Scheduling rounds the wakeup up to 3 ms, the next tick, after 3 timer interrupts.
On the surface
A tick-based kernel counts time in ticks of a periodic interrupt, commonly 1 kHz on Arm Cortex-M, and every timed wait ends on a tick. KideRT has no periodic tick. It programs the hardware timer for the next scheduled event, so each wait is set for its own time, to the resolution of the timer. Everything else on this page follows from that.
| Tick-Resolution Scheduling | High-Resolution Scheduling | |
|---|---|---|
| Time is counted in | Ticks of a periodic interrupt, commonly 1 ms | The hardware timer’s own units |
| A 2.3 ms sleep | Rounded up to a tick, 3 ms or up to a tick more | Timer set for 2.3 ms |
| A 250 µs period | Needs a tick of 250 µs or faster | Set like any other period |
| Timer interrupts in a 50 ms sleep | Fifty, one per tick | One, when it is due |
| While idle | The tick fires, unless tickless idle stops it | Nothing fires until the next event |
| Set for the whole application | One tick rate, a compromise between resolution and interrupts | Nothing, each wait sets its own time |
First dive: what your code sees
The code does not change. Sleeps, timers and timed waits are the POSIX calls your code already uses, and the periodic thread shown here runs on KideRT as it runs on Linux.
What changes is which periods and timeouts are possible, how far each is rounded, and how often the processor is interrupted while it waits.
Read about the POSIX interface#include <pthread.h>
#include <time.h>
#define PERIOD_NS 250000L /* 250 µs */
static void *sampling(void *arg)
{
struct timespec next;
clock_gettime(CLOCK_MONOTONIC, &next);
for (;;)
{
next.tv_nsec += PERIOD_NS;
if (next.tv_nsec >= 1000000000L)
{
next.tv_sec += 1;
next.tv_nsec -= 1000000000L;
}
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL);
read_sensor(arg);
}
}Periods that do not divide the tick
A 250 µs sampling period is out of reach with a 1 ms tick, and a 250 µs tick interrupts the whole application 4,000 times a second to provide it. With the timer set per event, a period is a number, not a multiple of the tick.
Timeouts shorter than a tick
A timed wait on a mutex, semaphore or message queue can be as short as the timer allows, without a busy-wait. On a 1 ms tick, no timeout is shorter than a tick.
Long waits without idle interrupts
A thread that sleeps for 50 ms costs one timer interrupt, at 50 ms, not fifty. There is no tickless idle mode to enable.
How long a sleep lasts
A kernel that counts time in ticks knows which tick it is in, not how far into it. A 2.3 ms sleep on a 1 ms tick is rounded up to three ticks, and the part of the current tick already gone, the partial tick, has to be counted one way or the other.
Either way, how long the sleep lasts depends on when in the tick it was requested, by up to a tick, and nothing in the application decides that. With High-Resolution Scheduling there is no tick for the request to fall into.
Where the wakeup can fallTimer set for the requestAxis: ms after the request
A 2.3 ms sleep on a 1 ms tick lasts between 2 and 3 ms if the kernel counts the partial tick, and between 3 and 4 ms if it does not, depending on when in the tick it was requested. With High-Resolution Scheduling the timer is set for 2.3 ms.
- Partial tick counted
- The wait ends on the third tick, so it lasts between 2 and 3 ms. It can end before the time asked for, so a one-tick sleep requested late in a tick lasts almost nothing.
- Partial tick not counted
- The wait ends on the fourth tick, so it lasts between 3 and 4 ms. It is never short, but up to 1.7 ms long. POSIX requires a sleep to last at least the time requested, so a POSIX interface on a tick works this way.
- High-Resolution Scheduling
- KideRT sets the hardware timer for 2.3 ms after the request, to the resolution of the timer. There is no tick for the request to fall into.
Periodic work: drift and jitter
A periodic thread can wait for its next period in two ways. A relative sleep, for 2.3 ms, starts counting after the work, so each period is the work plus the sleep plus its rounding, and the loop drifts. An absolute sleep, until a time advanced by 2.3 ms each round, does not drift, because how long the work takes does not move the next wakeup. That is the loop above, with clock_nanosleep() and TIMER_ABSTIME.
On a tick, an absolute time is reached on the first tick at or after it. The rate holds, but each period is rounded to whole ticks. A 2.3 ms loop on a 1 ms tick runs periods of 3, 2, 2, 3 and 2 ms, and averages 2.3 ms only over time. A period that is a multiple of the tick runs evenly; any other swings by one tick. With High-Resolution Scheduling each wakeup is set for its own absolute time, 2.3 ms after the last, to the resolution of the timer.
Period, msThread wakes and runsTick interrupt
A thread with a 2.3 ms period. High-Resolution Scheduling wakes it every 2.3 ms. Tick-Resolution Scheduling on a 1 ms tick wakes it after periods of 2 or 3 ms.
The deep end: inside the kernel
The difference starts in the timer interrupt. A tick-based kernel keeps time in an interrupt at a fixed rate and does its timed work there, due or not. KideRT keeps no periodic interrupt. It sets the hardware timer for the next event and does its timed work when that event is due.
Tick-Resolution Scheduling: every tick
The tick fires
At a fixed rate, commonly every millisecond, whether or not anything is due.
The count advances
The tick count is the kernel’s clock. Every delay and timeout was converted to a number of ticks when it was requested.
Due threads wake
Each thread whose tick has come is made ready, wherever in the last tick its time passed.
The kernel reschedules
If a woken thread outranks the running one, it runs. If nothing was due, the interrupt was bookkeeping.
High-Resolution Scheduling: every event
The timer is set
For the next scheduled event, the end of a sleep or a timer’s expiry, whichever comes first.
Nothing fires
Until that event is due. A thread asleep for 50 ms costs no interrupt until 50 ms.
The timer interrupts
KideRT handles every event due at that instant, and the threads waiting on them become ready.
The timer is set again
For the next event still pending.
The scheduler dispatches
The highest-priority ready thread runs, by priority and scheduling policy.
Where the resolution comes from
On a tick, the resolution is the tick period, chosen once for the application, for example 1 ms at 1 kHz. With High-Resolution Scheduling it is the resolution of the hardware timer the port uses, set by its clock and configuration. A timer counting at 1 MHz, for example, sets times in 1 µs steps. It is a property of the target, not a figure KideRT fixes.
A false bottom: tickless idle
Tickless idle is a power-saving mode of tick-based kernels. When no thread is ready, the kernel stops the tick, sets the timer for the tick on which the next thread is due, and lets the processor sleep. When the timer fires, the kernel adds the ticks that passed to its count and starts the tick again.
Time is still counted in ticks, so the wakeup still lands on one, and the tick returns as soon as a thread runs. Tickless idle removes the interrupts while idle. It does not change the resolution, and it does nothing while the processor is busy.
High-Resolution Scheduling is tickless in the literal sense. KideRT has no periodic tick, idle or busy.
Thread asleepThread runsTimer interrupt
A 2.3 ms sleep with nothing else to run, over the first 5 ms. With a periodic tick the thread wakes at 3 ms, after 5 timer interrupts in the 5 ms. With tickless idle the tick stops while idle, the thread still wakes at 3 ms, and the tick returns while it runs, for 3 interrupts. With High-Resolution Scheduling the thread wakes at 2.3 ms after 1 interrupt.
What it does not change
High-Resolution Scheduling sets when the timer fires. Everything between that interrupt and your code running is the same scheduling problem as on any kernel, and the claims stop where the measurements begin.
Read the scheduling designPriorities still decide what runs
A wakeup makes a thread ready. Whether it runs at once depends on the priorities of the other ready threads and on the scheduling policy.
Interrupts and critical sections still add delay
Interrupt handling and the kernel’s short critical sections sit between the timer event and the thread resuming, as on any kernel. Measure the path on your target under application load.
A wakeup is not a deadline
Meeting a deadline also depends on execution time and interference. Evaluate the whole workload, and treat an observed maximum as the maximum of that run, not as a bound.
Elapsed time can still be read as a count
Code written for a tick-based kernel often measures elapsed time by reading a tick count. For compatibility, KideRT provides a call for that. It returns the time since boot as a count in the hardware timer’s units.
Back on the surface
A periodic tick makes time a shared, coarse resource. One rate is chosen for the whole application as a compromise between resolution and interrupt load. It rounds every sleep, timeout and period to whole ticks, moves each by where in a tick it was requested, and interrupts the processor whether or not anything is due. A faster or slower tick moves the compromise. It cannot remove it.
High-Resolution Scheduling removes it. Each timed event sets the hardware timer for its own time, the processor is interrupted when something is due, and the resolution is the timer’s, not a rate chosen for the application. What remains is the part no timer settles. Priorities, interrupts and execution time decide when your code runs, on KideRT as on any RTOS, so measure that on the target.
A tick is enough when
- every period and timeout is a whole number of ticks,
- a tick of rounding is small against your deadlines,
- an interrupt every tick costs nothing you can measure.
High-Resolution Scheduling matters when
- a period or timeout is finer than a tick, or does not divide it,
- a tick of jitter is a real share of the period,
- a long wait should cost one interrupt, idle or busy.
The difference is not a faster tick. It is no tick at all.
Timing requirements
Discuss your target, sampling rates and deadlines with our engineers.