One of the Linux time subsystems: Clock source "Turn"

Source: Internet
Author: User

Transferred from: http://blog.csdn.net/droidphone/article/details/7975694

Clock source is used to provide a time baseline for the Linux kernel, and if you get the current time with the Linux Date command, the kernel reads the current clock source, transforms and returns the appropriate time units to the user space. At the hardware level, it is usually implemented as a counter driven by a fixed clock frequency, and the counter can only grow monotonically until it overflows. The clock source is the basis of the kernel timing, when the system starts, the kernel obtains the current time through the hardware RTC, after which, in most cases, the kernel updates the real time information (wall time) with the selected clock source and no longer reads the RTC time. The kernel code tree for this section is based on V3.4.10.

/*****************************************************************************************************/
Statement: The content of this blog by Http://blog.csdn.net/droidphone Original, reproduced please indicate the source, thank you!
/*****************************************************************************************************/

1. struct Clocksource structure

The kernel uses a CLOCKSOURCE structure to abstract software from the real clock source, and now we start with the data structure of clock sources, which is defined as follows:

[CPP]View PlainCopy
  1. struct Clocksource {
  2. /* 
  3. * Hotpath data, fits in a single cache line when the
  4. * Clocksource itself is cacheline aligned.
  5. */
  6. cycle_t (*read) (struct clocksource *cs);
  7. cycle_t Cycle_last;
  8. cycle_t Mask;
  9. U32 mult;
  10. U32 shift;
  11. U64 Max_idle_ns;
  12. U32 Maxadj;
  13. #ifdef Config_arch_clocksource_data
  14. struct Arch_clocksource_data archdata;
  15. #endif
  16. Const Char *name;
  17. struct List_head list;
  18. int rating;
  19. Int (*enable) (struct clocksource *cs);
  20. void (*disable) (struct clocksource *cs);
  21. unsigned long flags;
  22. void (*suspend) (struct clocksource *cs);
  23. void (*resume) (struct clocksource *cs);
  24. /* Private: */
  25. #ifdef Config_clocksource_watchdog
  26. / * Watchdog related data, used by the framework * /
  27. struct List_head wd_list;
  28. cycle_t Cs_last;
  29. cycle_t Wd_last;
  30. #endif
  31. } ____cacheline_aligned;

We only focus on a few important fields in Clocksource.

1.1 Rating: The accuracy of the clock source can have multiple clock sources under the same device, and the precision of each clock source is determined by the clock frequency that drives it, such as a clock source driven by a 10MHz clock, whose accuracy is 100nS. There is a rating field in the Clocksource structure that represents the precision range of the clock source, and its value range is as follows:
    • 1--99: not suitable for use as the actual clock source, only for the start-up process or for testing;
    • 100--199: Basic available, can be used as a real clock source, but not recommended;
    • 200--299: Good accuracy, can be used as a real clock source;
    • 300--399: Very good, accurate clock source;
    • 400--499: The ideal clock source, if possible, it must be selected as the clock source;

1.2 Read callback function The clock source itself does not produce interrupts, to obtain the current count of the clock source, only by actively invoking its read callback function to obtain the current count value, note here can only get the count value, that is called cycle, to obtain the corresponding time, Conversion calculations must be performed with Clocksource's mult and Shift fields. 1.3 Mult and Shift fields because the value read from Clocksource is a cycle count value, to convert to time, we have to know the clock frequency f that drives the Clocksource, a simple calculation can be done:

t = cycle/f;

However, Clocksource does not save the clock frequency F, because using the above formula to calculate, need to use floating-point arithmetic, which is not allowed in the kernel, so the kernel uses another workaround, based on the clock frequency and expected precision, Calculate the two auxiliary constants mult and shift in advance, and then use the following formula to convert cycle and T:

t = (cycle * mult) >> shift;

As long as we guarantee:

F = (1 << shift)/mult;

The kernel internally uses 64-bit for this conversion calculation:
[CPP]View PlainCopy
    1. Static inline S64 clocksource_cyc2ns (cycle_t cycles, u32 mult, u32 shift)
    2. {
    3. return ((u64) cycles * mult) >> shift;
    4. }
Considering the conversion precision, the value of the mult is greater, but in order to calculate the process does not overflow, the value of mult can not be achieved too large. This kernel assumes that the value of the cycle meter value is converted to the maximum time: 10 minutes (600 seconds), the main consideration is that the CPU enters the idle state, the time information will not be updated, as long as within 10 minutes to exit the idle, The cycle count value of the Clocksource can be correctly converted to the appropriate time, and then the system's time information can be updated correctly. Of course the final result is not necessarily 10 minutes, it is calculated by clocksource_max_deferment, and save the Max_idle_ns field, tickless code to consider this value, in order to prevent in the No_hz configuration environment, The system remains idle for too long. In this case, by 10 minutes of this hypothetical time value, we can deduce the appropriate mult and shift values. 2. Registration and initialization of Clocksource normally, Clocksource to notify the kernel of the frequency of its working clock through the CLOCKSOURCE_REGISTER_HZ function during the initialization phase, the process is called as follows:


By visible, most of the work will eventually be done by __clocksource_register_scale, which first completes the calculation of the mult and shift values, and then, based on the mult and shift values, eventually passes Clocksource_max_ Deferment obtains the maximum idle time acceptable to the Clocksource and is recorded in the Max_idle_ns field of the Clocksource. Clocksource_enqueue function is responsible for the size of the Clocksource rating, the Clocksource in order to hang on the global list clocksource_list, the greater the rating value, the position on the list is higher. Each time a new Clocksource is registered, the Clocksource_select function is called, which selects the best Clocksource according to the rating value and is recorded in the global variable Curr_clocksource. Then through the Timekeeping_notify function to notify timekeeping, the current clocksource has changed, about timekeeping, I will be in the following blog post. 3. Clocksource watchdog

The system may be registered to a clocksource at the same time, the accuracy and stability of each clocksource are different, in order to filter these registered Clocksource, the kernel enables a timer to monitor the performance of these clocksource, The timer period is set to 0.5 seconds:

[CPP]View PlainCopy
    1. #define WATCHDOG_INTERVAL (HZ >> 1)
    2. #define Watchdog_threshold (nsec_per_sec >> 4)

When a new Clocksource is registered, in addition to hanging in the global list clocksource_list, but also hanging on a watchdog linked list: Watchdog_list. The timer periodically (0.5 seconds) checks the Clocksource,watchdog_ on the watchdog_list. The value of threshold is defined as 0.0625 seconds, and if within 0.5 seconds the deviation of clocksource is greater than this value means that the clocksource is unstable, and the callback function of the timer is Clocksource_watchdog_ The kthread thread marks the Clocksource and changes its rate to 0, which means that the accuracy is very poor.

4. The brief process of establishing a Clocksource

During the startup phase of the system, the kernel registers a jiffies-based Clocksource, which is located in KERNEL/TIME/JIFFIES.C:

[CPP]View PlainCopy
  1. struct Clocksource clocksource_jiffies = {
  2. . Name = "Jiffies",
  3. . rating = 1,/ * Lowest valid rating*/
  4. . Read = Jiffies_read,
  5. . Mask = 0xFFFFFFFF, /*32bits*/
  6. . mult = Nsec_per_jiffy << jiffies_shift,/ * Details above * /
  7. . Shift = Jiffies_shift,
  8. };
  9. ......
  10. static int __init init_jiffies_clocksource (void)
  11. {
  12. return Clocksource_register (&clocksource_jiffies);
  13. }
  14. Core_initcall (Init_jiffies_clocksource);

Its precision is only 1/hz seconds, the rating value is 1, and if the platform's code does not provide a custom clocksource_default_clock function, it returns the Clocksource:

[CPP]View PlainCopy
    1. struct Clocksource * __init __weak clocksource_default_clock (void)
    2. {
    3. return &clocksource_jiffies;
    4. }

Then, in the latter part of the initialization, the Clocksource code sets the global variable Curr_clocksource to the Clocksource above:

[CPP]View PlainCopy
  1. static int __init clocksource_done_booting (void)
  2. {
  3. ......
  4. Curr_clocksource = Clocksource_default_clock ();
  5. ......
  6. finished_booting = 1;
  7. ......
  8. Clocksource_select ();
  9. ......
  10. return 0;
  11. }
  12. Fs_initcall (clocksource_done_booting);

Of course, if the platform-level code is initialized with a real hardware clocksource, after the Clocksource_select () function, Curr_clocksource will be set to the most appropriate clocksource. If the Clocksource_select function believes that a better clock source needs to be switched, it notifies the timekeeping system via Timekeeping_notify and uses the new Clocksource for time counting and update operations.

One of the Linux time subsystems: Clock source "Turn"

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.