Chapter 15. Managing system clocks to satisfy application needs Multiprocessor systems such as NUMA or SMP have multiple instances of hardware clocks. During boot time the kernel discovers the available clock sources and selects one to use. To improve performance, you can change the clock source used to meet the minimum requirements of a real-time system. 15.1. Hardware clocks Multiple instances of clock sources found in multiprocessor systems, such as non-uniform memory access (NUMA) and Symmetric multiprocessing (SMP), interact among themselves and the way they react to system events, such as CPU frequency scaling or entering energy economy modes, determine whether they are suitable clock sources for the real-time kernel. The preferred clock source is the Time Stamp Counter (TSC). If the TSC is not available, the High Precision Event Timer (HPET) is the second best option. However, not all systems have HPET clocks, and some HPET clocks can be unreliable. In the absence of TSC and HPET, other options include the ACPI Power Management Timer (ACPI_PM), the Programmable Interval Timer (PIT), and the Real Time Clock (RTC). The last two options are either costly to read or have a low resolution (time granularity), therefore they are sub-optimal for use with the real-time kernel. 15.2. Viewing the available clock sources in your system The list of available clock sources in your system is in the /sys/devices/system/clocksource/clocksource0/available_clocksource file. Procedure Display the available_clocksource file. In this example, the available clock sources in the system are TSC, HPET, and ACPI_PM. 15.3. Viewing the clock source currently in use The currently used clock source in your system is stored in the /sys/devices/system/clocksource/clocksource0/current_clocksource file. Procedure Display the current_clocksource file. In this example, the current clock source in the system is TSC. 15.4. Temporarily changing the clock source to use Sometimes the best-performing clock for a system's main application is not used due to known problems on the clock. After ruling out all problematic clocks, the system can be left with a hardware clock that is unable to satisfy the minimum requirements of a real-time system. Requirements for crucial applications vary on each system. Therefore, the best clock for each application, and consequently each system, also varies. Some applications depend on clock resolution, and a clock that delivers reliable nanoseconds readings can be more suitable. Applications that read the clock too often can benefit from a clock with a smaller reading cost (the time between a read request and the result). In these cases it is possible to override the clock selected by the kernel, provided that you understand the side effects of the override and can create an environment which will not trigger the known shortcomings of the given hardware clock. Important The kernel automatically selects the best available clock source. Overriding the selected clock source is not recommended unless the implications are well understood. Prerequisites You have root permissions on the system. Procedure View the available clock sources. As an example, consider the available clock sources in the system are TSC, HPET, and ACPI_PM. Write the name of the clock source you want to use to the /sys/devices/system/clocksource/clocksource0/current_clocksource file. Note The changes apply to the clock source currently in use. When the system reboots, the default clock is used. To make the change persistent, see Making persistent kernel tuning parameter changes . Verification Display the current_clocksource file to ensure that the current clock source is the specified clock source. The example uses HPET as the current clock source in the system. 15.5. Comparing the cost of reading hardware clock sources You can compare the speed of the clocks in your system. Reading from the TSC involves reading a register from the processor. Reading from the HPET clock involves reading a memory area. Reading from the TSC is faster, which provides a significant performance advantage when timestamping hundreds of thousands of messages per second. Prerequisites You have root permissions on the system. The clock_timing program must be on the system. For more information, see the clock_timing program . Procedure Change to the directory in which the clock_timing program is saved. View the available clock sources in your system. In this example, the available clock sources in the system are TSC , HPET , and ACPI_PM . View the currently used clock source. In this example, the current clock source in the system is TSC . Run the time utility in conjunction with the ./ clock_timing program. The output displays the duration required to read the clock source 10 million times. The example shows the following parameters: real - The total time spent beginning from program invocation until the process ends. real includes user and kernel times, and will usually be larger than the sum of the latter two. If this process is interrupted by an application with higher priority, or by a system event such as a hardware interrupt (IRQ), this time spent waiting is also computed under real . user - The time the process spent in user space performing tasks that did not require kernel intervention. sys - The time spent by the kernel while performing tasks required by the user process. These tasks include opening files, reading and writing to files or I/O ports, memory allocation, thread creation, and network related activities. Write the name of the clock source you want to test to the /sys/devices/system/clocksource/clocksource0/current_clocksource file. In this example, the current clock source is changed to HPET . Repeat steps 4 and 5 for all of the available clock sources. Compare the results of step 4 for all of the available clock sources. Additional resources time(1) man page on your system 15.6. Synchronizing the TSC timer on Opteron CPUs The current generation of AMD64 Opteron processors can be susceptible to a large gettimeofday skew. This skew occurs when both cpufreq and the Time Stamp Counter (TSC) are in use. RHEL for Real Time provides a method to prevent this skew by forcing all processors to simultaneously change to the same frequency. As a result, the TSC on a single processor never increments at a different rate than the TSC on another processor. Prerequisites You have root permissions on the system. Procedure Enable the clocksource=tsc and powernow-k8.tscsync=1 kernel options: This forces the use of TSC and enables simultaneous core processor frequency transitions. Restart the machine. Additional resources gettimeofday(2) man page on your system 15.7. The clock_timing program The clock_timing program reads the current clock source 10 million times. In conjunction with the time utility it measures the amount of time needed to do this. Procedure To create the clock_timing program: Create a directory for the program files. Change to the created directory. Create a source file and open it in a text editor. Enter the following into the file: Save the file and exit the editor. Compile the file. The clock_timing program is ready and can be run from the directory in which it is saved.

Commands:
cat /sys/devices/system/clocksource/clocksource0/available_clocksource tsc hpet acpi_pm
cat /sys/devices/system/clocksource/clocksource0/current_clocksource tsc
cat /sys/devices/system/clocksource/clocksource0/available_clocksource tsc hpet acpi_pm
echo hpet > /sys/devices/system/clocksource/clocksource0/current_clocksource
cat /sys/devices/system/clocksource/clocksource0/current_clocksource hpet
cd clock_test
cat /sys/devices/system/clocksource/clocksource0/available_clocksource tsc hpet acpi_pm
cat /sys/devices/system/clocksource/clocksource0/current_clocksource tsc
time ./clock_timing real 0m0.601s user 0m0.592s sys 0m0.002s
echo hpet > /sys/devices/system/clocksource/clocksource0/current_clocksource
grubby --update-kernel=ALL --args="clocksource=tsc powernow-k8.tscsync=1"
mkdir clock_test
cd clock_test
{EDITOR} clock_timing.c
#include <time.h> void main() { int rc; long i; struct timespec ts; for(i=0; i<10000000; i++) { rc = clock_gettime(CLOCK_MONOTONIC, &ts); } }
gcc clock_timing.c -o clock_timing -lrt