Last Updated on August 23, 2026
Degrees of Real-Time on i.MX6 Quad Linux 6.6.x
Objectives
This post shows you “degrees of real-time” by observing the maximum jitter/latencies of cyclictest over an upstream kernel configured and patched in various ways and latmus for Xenomai 4 with EVL. All this without and with load produced by stress-ng. Understanding the different degrees of real-time the Linux kernel provides can help ensure optimal system performance.
Prerequisites
Kernel/Patches/Configurations
Those are the kernels/kernel configurations we’ll have a look at:
| Kernel Version | Patch applied | SCHED Configuration | Notes |
| 6.6.52-rt43 | preempt-rt patch | PREEMPT_NONE (preempt-rt patch not required) | patch applied, default config slightly tweaked |
| 6.6.52-rt43 | preempt-rt patch | PREEMPT_VOLUNTARY (preempt-rt patch not required) | see above |
| 6.6.52-rt43 | preempt-rt patch | PREEMPT (preempt-rt patch not required) | see above |
| 6.6.52-rt43 | preempt-rt patch | PREEMPT_RT (preempt-rt patch required) | see above |
| 6.6.52-evl | “Branch”: v6.6.y-evl-rebase Tag: v6.6.52-evl1-rebase | PREEMPT_NONE (but it does not matter since we’ll run Xenomai 4 with EVL on it) | libevl r49 |
cyclictest/latmus
As mentioned above, cyclictest is used for our benchmarks except for Xenomai 4. Xenomai comes with a tool called latmus. For the graphs below, we run one high-priority process periodically for 500 microseconds and measure the jitter.
stress-ng
We use stress-ng to apply stress to the system. The real-time behaviour is visible via the worst-case jitter/latency under heavy load. The “loadavg” in “load” test cases is measured between “number of CPUs * 2” and “number of CPUs * 3”.
Latency/Jitter Measurements
The worst-case jitter in the graphs to the left looks pretty promising. Unfortunately, jitter in an “idle system” does not mean much. For more realistic worst-case latencies we use stress-ng to apply a heavy load to the system. This gives us a better understanding of how real-time a system is. You’ll see those results in the graphs to the right.
PREEMPT_NONE
PREEMPT_NONE is the scheduler preemption model here. This is possible without any kernel patches. Please note the maximum jitter under load in the graph on the right.
PREEMPT_VOLUNTARY
PREEMPT_VOLUNTARY is the preemption model here. This is possible without any kernel patches. It might surprise you that the maximum jitter got worse.
PREEMPT
PREEMPT is the preemption model here. This is possible without any kernel patches. Please note the improved maximum jitter under load in the graph on the right.
PREEMPT_RT
PREEMPT_RT is the scheduler preemption model here. For this to work, we’ll need to apply the preempt-rt kernel patch. Please note the improved maximum jitter under load in the graph on the right.
Xenomai 4 with EVL
We use latmus (the litmus test for latency) for Xenomai 4 with EVL. This means the preemption model configured here is irrelevant to the test case.
We use a specially patched “kernel” in combination with r49 of libevil.
The improvement in maximum jitter is pretty good. The latency is typically a factor of two less with Xenomai than with preempt-rt. The disadvantage of Xenomai compared to preempt-rt is, that preempt-rt is the only real-time Linux solution that can be/was upstreamed to kernel.org. Unfortunately, not (yet) for arm32.
Conclusion
As you can see above, depending on kernel configuration and patch level, we can reduce the maximum jitter in our test case. The graphs here should give you some initial idea about available options. You will most likely need to write custom test cases to cover your specific real-time problems.
For a similar blog post with a Linux kernel where you can also see test results with release and debug kernels, check here. For a blog post about the Yocto Project® kernel tooling, dig into the post here. To learn how Embedded Linux works plus additional real-time, examine this link. To learn more about the Yocto Project® have a look here.