Back to home page

OSCL-LXR

 
 

    


0001 =====================================================
0002 High resolution timers and dynamic ticks design notes
0003 =====================================================
0004 
0005 Further information can be found in the paper of the OLS 2006 talk "hrtimers
0006 and beyond". The paper is part of the OLS 2006 Proceedings Volume 1, which can
0007 be found on the OLS website:
0008 https://www.kernel.org/doc/ols/2006/ols2006v1-pages-333-346.pdf
0009 
0010 The slides to this talk are available from:
0011 http://www.cs.columbia.edu/~nahum/w6998/papers/ols2006-hrtimers-slides.pdf
0012 
0013 The slides contain five figures (pages 2, 15, 18, 20, 22), which illustrate the
0014 changes in the time(r) related Linux subsystems. Figure #1 (p. 2) shows the
0015 design of the Linux time(r) system before hrtimers and other building blocks
0016 got merged into mainline.
0017 
0018 Note: the paper and the slides are talking about "clock event source", while we
0019 switched to the name "clock event devices" in meantime.
0020 
0021 The design contains the following basic building blocks:
0022 
0023 - hrtimer base infrastructure
0024 - timeofday and clock source management
0025 - clock event management
0026 - high resolution timer functionality
0027 - dynamic ticks
0028 
0029 
0030 hrtimer base infrastructure
0031 ---------------------------
0032 
0033 The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of
0034 the base implementation are covered in Documentation/timers/hrtimers.rst. See
0035 also figure #2 (OLS slides p. 15)
0036 
0037 The main differences to the timer wheel, which holds the armed timer_list type
0038 timers are:
0039 
0040        - time ordered enqueueing into a rb-tree
0041        - independent of ticks (the processing is based on nanoseconds)
0042 
0043 
0044 timeofday and clock source management
0045 -------------------------------------
0046 
0047 John Stultz's Generic Time Of Day (GTOD) framework moves a large portion of
0048 code out of the architecture-specific areas into a generic management
0049 framework, as illustrated in figure #3 (OLS slides p. 18). The architecture
0050 specific portion is reduced to the low level hardware details of the clock
0051 sources, which are registered in the framework and selected on a quality based
0052 decision. The low level code provides hardware setup and readout routines and
0053 initializes data structures, which are used by the generic time keeping code to
0054 convert the clock ticks to nanosecond based time values. All other time keeping
0055 related functionality is moved into the generic code. The GTOD base patch got
0056 merged into the 2.6.18 kernel.
0057 
0058 Further information about the Generic Time Of Day framework is available in the
0059 OLS 2005 Proceedings Volume 1:
0060 
0061         http://www.linuxsymposium.org/2005/linuxsymposium_procv1.pdf
0062 
0063 The paper "We Are Not Getting Any Younger: A New Approach to Time and
0064 Timers" was written by J. Stultz, D.V. Hart, & N. Aravamudan.
0065 
0066 Figure #3 (OLS slides p.18) illustrates the transformation.
0067 
0068 
0069 clock event management
0070 ----------------------
0071 
0072 While clock sources provide read access to the monotonically increasing time
0073 value, clock event devices are used to schedule the next event
0074 interrupt(s). The next event is currently defined to be periodic, with its
0075 period defined at compile time. The setup and selection of the event device
0076 for various event driven functionalities is hardwired into the architecture
0077 dependent code. This results in duplicated code across all architectures and
0078 makes it extremely difficult to change the configuration of the system to use
0079 event interrupt devices other than those already built into the
0080 architecture. Another implication of the current design is that it is necessary
0081 to touch all the architecture-specific implementations in order to provide new
0082 functionality like high resolution timers or dynamic ticks.
0083 
0084 The clock events subsystem tries to address this problem by providing a generic
0085 solution to manage clock event devices and their usage for the various clock
0086 event driven kernel functionalities. The goal of the clock event subsystem is
0087 to minimize the clock event related architecture dependent code to the pure
0088 hardware related handling and to allow easy addition and utilization of new
0089 clock event devices. It also minimizes the duplicated code across the
0090 architectures as it provides generic functionality down to the interrupt
0091 service handler, which is almost inherently hardware dependent.
0092 
0093 Clock event devices are registered either by the architecture dependent boot
0094 code or at module insertion time. Each clock event device fills a data
0095 structure with clock-specific property parameters and callback functions. The
0096 clock event management decides, by using the specified property parameters, the
0097 set of system functions a clock event device will be used to support. This
0098 includes the distinction of per-CPU and per-system global event devices.
0099 
0100 System-level global event devices are used for the Linux periodic tick. Per-CPU
0101 event devices are used to provide local CPU functionality such as process
0102 accounting, profiling, and high resolution timers.
0103 
0104 The management layer assigns one or more of the following functions to a clock
0105 event device:
0106 
0107       - system global periodic tick (jiffies update)
0108       - cpu local update_process_times
0109       - cpu local profiling
0110       - cpu local next event interrupt (non periodic mode)
0111 
0112 The clock event device delegates the selection of those timer interrupt related
0113 functions completely to the management layer. The clock management layer stores
0114 a function pointer in the device description structure, which has to be called
0115 from the hardware level handler. This removes a lot of duplicated code from the
0116 architecture specific timer interrupt handlers and hands the control over the
0117 clock event devices and the assignment of timer interrupt related functionality
0118 to the core code.
0119 
0120 The clock event layer API is rather small. Aside from the clock event device
0121 registration interface it provides functions to schedule the next event
0122 interrupt, clock event device notification service and support for suspend and
0123 resume.
0124 
0125 The framework adds about 700 lines of code which results in a 2KB increase of
0126 the kernel binary size. The conversion of i386 removes about 100 lines of
0127 code. The binary size decrease is in the range of 400 byte. We believe that the
0128 increase of flexibility and the avoidance of duplicated code across
0129 architectures justifies the slight increase of the binary size.
0130 
0131 The conversion of an architecture has no functional impact, but allows to
0132 utilize the high resolution and dynamic tick functionalities without any change
0133 to the clock event device and timer interrupt code. After the conversion the
0134 enabling of high resolution timers and dynamic ticks is simply provided by
0135 adding the kernel/time/Kconfig file to the architecture specific Kconfig and
0136 adding the dynamic tick specific calls to the idle routine (a total of 3 lines
0137 added to the idle function and the Kconfig file)
0138 
0139 Figure #4 (OLS slides p.20) illustrates the transformation.
0140 
0141 
0142 high resolution timer functionality
0143 -----------------------------------
0144 
0145 During system boot it is not possible to use the high resolution timer
0146 functionality, while making it possible would be difficult and would serve no
0147 useful function. The initialization of the clock event device framework, the
0148 clock source framework (GTOD) and hrtimers itself has to be done and
0149 appropriate clock sources and clock event devices have to be registered before
0150 the high resolution functionality can work. Up to the point where hrtimers are
0151 initialized, the system works in the usual low resolution periodic mode. The
0152 clock source and the clock event device layers provide notification functions
0153 which inform hrtimers about availability of new hardware. hrtimers validates
0154 the usability of the registered clock sources and clock event devices before
0155 switching to high resolution mode. This ensures also that a kernel which is
0156 configured for high resolution timers can run on a system which lacks the
0157 necessary hardware support.
0158 
0159 The high resolution timer code does not support SMP machines which have only
0160 global clock event devices. The support of such hardware would involve IPI
0161 calls when an interrupt happens. The overhead would be much larger than the
0162 benefit. This is the reason why we currently disable high resolution and
0163 dynamic ticks on i386 SMP systems which stop the local APIC in C3 power
0164 state. A workaround is available as an idea, but the problem has not been
0165 tackled yet.
0166 
0167 The time ordered insertion of timers provides all the infrastructure to decide
0168 whether the event device has to be reprogrammed when a timer is added. The
0169 decision is made per timer base and synchronized across per-cpu timer bases in
0170 a support function. The design allows the system to utilize separate per-CPU
0171 clock event devices for the per-CPU timer bases, but currently only one
0172 reprogrammable clock event device per-CPU is utilized.
0173 
0174 When the timer interrupt happens, the next event interrupt handler is called
0175 from the clock event distribution code and moves expired timers from the
0176 red-black tree to a separate double linked list and invokes the softirq
0177 handler. An additional mode field in the hrtimer structure allows the system to
0178 execute callback functions directly from the next event interrupt handler. This
0179 is restricted to code which can safely be executed in the hard interrupt
0180 context. This applies, for example, to the common case of a wakeup function as
0181 used by nanosleep. The advantage of executing the handler in the interrupt
0182 context is the avoidance of up to two context switches - from the interrupted
0183 context to the softirq and to the task which is woken up by the expired
0184 timer.
0185 
0186 Once a system has switched to high resolution mode, the periodic tick is
0187 switched off. This disables the per system global periodic clock event device -
0188 e.g. the PIT on i386 SMP systems.
0189 
0190 The periodic tick functionality is provided by an per-cpu hrtimer. The callback
0191 function is executed in the next event interrupt context and updates jiffies
0192 and calls update_process_times and profiling. The implementation of the hrtimer
0193 based periodic tick is designed to be extended with dynamic tick functionality.
0194 This allows to use a single clock event device to schedule high resolution
0195 timer and periodic events (jiffies tick, profiling, process accounting) on UP
0196 systems. This has been proved to work with the PIT on i386 and the Incrementer
0197 on PPC.
0198 
0199 The softirq for running the hrtimer queues and executing the callbacks has been
0200 separated from the tick bound timer softirq to allow accurate delivery of high
0201 resolution timer signals which are used by itimer and POSIX interval
0202 timers. The execution of this softirq can still be delayed by other softirqs,
0203 but the overall latencies have been significantly improved by this separation.
0204 
0205 Figure #5 (OLS slides p.22) illustrates the transformation.
0206 
0207 
0208 dynamic ticks
0209 -------------
0210 
0211 Dynamic ticks are the logical consequence of the hrtimer based periodic tick
0212 replacement (sched_tick). The functionality of the sched_tick hrtimer is
0213 extended by three functions:
0214 
0215 - hrtimer_stop_sched_tick
0216 - hrtimer_restart_sched_tick
0217 - hrtimer_update_jiffies
0218 
0219 hrtimer_stop_sched_tick() is called when a CPU goes into idle state. The code
0220 evaluates the next scheduled timer event (from both hrtimers and the timer
0221 wheel) and in case that the next event is further away than the next tick it
0222 reprograms the sched_tick to this future event, to allow longer idle sleeps
0223 without worthless interruption by the periodic tick. The function is also
0224 called when an interrupt happens during the idle period, which does not cause a
0225 reschedule. The call is necessary as the interrupt handler might have armed a
0226 new timer whose expiry time is before the time which was identified as the
0227 nearest event in the previous call to hrtimer_stop_sched_tick.
0228 
0229 hrtimer_restart_sched_tick() is called when the CPU leaves the idle state before
0230 it calls schedule(). hrtimer_restart_sched_tick() resumes the periodic tick,
0231 which is kept active until the next call to hrtimer_stop_sched_tick().
0232 
0233 hrtimer_update_jiffies() is called from irq_enter() when an interrupt happens
0234 in the idle period to make sure that jiffies are up to date and the interrupt
0235 handler has not to deal with an eventually stale jiffy value.
0236 
0237 The dynamic tick feature provides statistical values which are exported to
0238 userspace via /proc/stat and can be made available for enhanced power
0239 management control.
0240 
0241 The implementation leaves room for further development like full tickless
0242 systems, where the time slice is controlled by the scheduler, variable
0243 frequency profiling, and a complete removal of jiffies in the future.
0244 
0245 
0246 Aside the current initial submission of i386 support, the patchset has been
0247 extended to x86_64 and ARM already. Initial (work in progress) support is also
0248 available for MIPS and PowerPC.
0249 
0250           Thomas, Ingo