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.

    # cat /sys/devices/system/clocksource/clocksource0/available_clocksource
    tsc hpet acpi_pm

    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.

    # cat /sys/devices/system/clocksource/clocksource0/current_clocksource
    tsc

    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

  1. View the available clock sources.

    # cat /sys/devices/system/clocksource/clocksource0/available_clocksource
    tsc hpet acpi_pm

    As an example, consider the available clock sources in the system are TSC, HPET, and ACPI_PM.

  2. Write the name of the clock source you want to use to the /sys/devices/system/clocksource/clocksource0/current_clocksource file.

    # echo hpet > /sys/devices/system/clocksource/clocksource0/current_clocksource
    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 steps

  • Display the current_clocksource file to ensure that the current clock source is the specified clock source.

    # cat /sys/devices/system/clocksource/clocksource0/current_clocksource
    hpet

    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

  1. Change to the directory in which the clock_timing program is saved.

    # cd clock_test
  2. View the available clock sources in your system.

    # cat /sys/devices/system/clocksource/clocksource0/available_clocksource
    tsc hpet acpi_pm

    In this example, the available clock sources in the system are TSC, HPET, and ACPI_PM.

  3. View the currently used clock source.

    # cat /sys/devices/system/clocksource/clocksource0/current_clocksource
    tsc

    In this example, the current clock source in the system is TSC.

  4. 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.

    # time ./clock_timing
    
    	real	0m0.601s
    	user	0m0.592s
    	sys	0m0.002s

    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.
  5. Write the name of the next clock source you want to test to the /sys/devices/system/clocksource/clocksource0/current_clocksource file.

    # echo hpet > /sys/devices/system/clocksource/clocksource0/current_clocksource

    In this example, the current clock source is changed to HPET.

  6. Repeat steps 4 and 5 for all of the available clock sources.
  7. Compare the results of step 4 for all of the available clock sources.

Additional resources

  • time(1) man page

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

  1. Enable the clocksource=tsc and powernow-k8.tscsync=1 kernel options:

    # grubby --update-kernel=ALL --args="clocksource=tsc powernow-k8.tscsync=1"

    This forces the use of TSC and enables simultaneous core processor frequency transitions.

  2. Restart the machine.

Additional resources

  • gettimeofday(2) man page

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:

  1. Create a directory for the program files.

    $ mkdir clock_test
  2. Change to the created directory.

    $ cd clock_test
  3. Create a source file and open it in a text editor.

    $ {EDITOR} clock_timing.c
  4. Enter the following into the file:

    #include <time.h>
    void main()
    {
    	int rc;
    	long i;
    	struct timespec ts;
    
            for(i=0; i<10000000; i++) {
    		rc = clock_gettime(CLOCK_MONOTONIC, &ts);
    	}
    }
  5. Save the file and exit the editor.
  6. Compile the file.

    $ gcc clock_timing.c -o clock_timing -lrt

    The clock_timing program is ready and can be run from the directory in which it is saved.