/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/**
* @page article_jitter Response Time and Jitter
* Response time jitter is one of the most sneaky source of problems when
* designing a real time system. When using a RTOS like ChibiOS/RT one must
* be aware of what the jitter is and how it can affect the performance of the
* system. A good place to start is this
* Wikipedia
* article.
*
*
Interrupt handlers execution time
* The total execution time of an interrupt handler includes:
* - Hardware interrupts latency, this parameter is pretty much fixed and
* characteristic of the system.
* - Fixed handler overhead, as example registers stacking/unstacking.
* - Interrupt specific handler code execution time, as example, in a serial
* driver, this is the time used by the handler to transfer data from/to
* the UART.
* - OS overhead. Any operating system requires to run some extra code
* in interrupt handlers in order to handle correct preemption and Context
* Switching.
* .
* Interrupt Response Time
* The Interrupt Response Time is the time from an interrupt event and the
* execution of the handler code. Unfortunately this time is not constant
* in most cases, see the following graph:
*
* @dot
digraph example {
rankdir="LR";
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.75", height="0.75"];
edge [fontname=Helvetica, fontsize=8];
int [label="Interrupt"];
busy [label="Busy"];
served [label="Interrupt\nServed"];
int -> served [label="Not Busy (minimum latency)"];
int -> busy [label="Not Ready"];
busy -> busy [label="Still Busy\n(added latency)"];
busy -> served [label="Finally Ready"];
}
* @enddot
*
* In this scenario the jitter (busy state) is represented by the sum of:
* - Higher or equal priority interrupt handlers execution time combined.
* This time can go from zero to the maximum randomly. This value can be
* guaranteed to be zero only if the interrupt has the highest priority in
* the system.
* - Highest execution time among lower priority handlers. This value is zero
* on those architectures (Cortex-M3 as example) where interrupt handlers
* can be preempted by higher priority sources.
* - Longest time in a kernel lock zone that can delay interrupt servicing.
* This value is zero for fast interrupt sources, see @ref system_states.
* .
* Threads Flyback Time
* This is the time between an event, as example an interrupt, and the
* execution of the thread that will process it. Imagine the following
* graph as the continuation of the previous one.
*
* @dot
digraph example {
rankdir="LR";
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.75", height="0.75"];
edge [fontname=Helvetica, fontsize=8];
served [label="Interrupt\nServed"];
busy [label="Busy"];
thread [label="Thread\nAwakened"];
served -> busy [label="Not highest Priority"];
busy -> busy [label="Higher priority Threads\n(added latency)"];
busy -> thread [label="Highest Priority"];
served -> thread [label="Highest Priority (minimum latency)"];
}
* @enddot
*
* In this scenario all the jitter sources previously discussed are also
* present and there is the added jitter caused by the activity of the
* higher priority threads.
*
* Jitter Mitigation
* For each of the previously described jitter sources there are possible
* mitigation actions.
*
* Interrupt handlers optimization
* An obvious mitigation action is to optimize the interrupt handler code as
* much as possible for speed.
* Complex actions should never be performed in interrupt handlers.
* An handler should just serve the interrupt and wakeup a dedicated thread in
* order to handle the bulk of the work.
* Another possible mitigation action is to evaluate if a specific interrupt
* handler really needs to interact with the OS, if the handler uses full
* stand-alone code then it is possible to remove the OS related overhead.
*
* Kernel lock zones
* The OS kernel protects some critical internal data structure by disabling
* (fully in simple architecture, to some extent in more advanced
* microcontrollers) the interrupt sources. Because of this the kernel itself
* is a jitter cause, a good OS design minimizes the jitter generated by the
* kernel by using adequate data structures, algorithms and coding
* practices.
* A good OS design is not the whole story, some OS primitives may generate
* more or less jitter depending on the system state, as example the maximum
* number of threads on a certain queue, the maximum number of nested mutexes
* and so on. Some algorithms employed internally can have constant execution
* time but others may have linear execution time or be even more complex.
*
* Higher priority threads activity
* At thread level, the response time is affected by the interrupt-related
* jitter but mainly by the activity of the higher priority threads and
* contention on protected resources.
* It is possible to improve the system overall response time and reduce jitter
* by carefully assigning priorities to the various threads and carefully
* designing mutual exclusion zones.
* The use of the proper synchronization mechanism (semaphores, mutexes, events,
* messages and so on) also helps to improve the overall system performance.
* The use of the Priority Inheritance algorithm implemented in the mutexes
* subsystem can improve the overall response time and reduce jitter but it is
* not a magic wand, a proper system design comes first.
*/