jiffies.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * This file contains the jiffies based clocksource.
  4. *
  5. * Copyright (C) 2004, 2005 IBM, John Stultz ([email protected])
  6. */
  7. #include <linux/clocksource.h>
  8. #include <linux/jiffies.h>
  9. #include <linux/module.h>
  10. #include <linux/init.h>
  11. #include "timekeeping.h"
  12. #include "tick-internal.h"
  13. static u64 jiffies_read(struct clocksource *cs)
  14. {
  15. return (u64) jiffies;
  16. }
  17. /*
  18. * The Jiffies based clocksource is the lowest common
  19. * denominator clock source which should function on
  20. * all systems. It has the same coarse resolution as
  21. * the timer interrupt frequency HZ and it suffers
  22. * inaccuracies caused by missed or lost timer
  23. * interrupts and the inability for the timer
  24. * interrupt hardware to accurately tick at the
  25. * requested HZ value. It is also not recommended
  26. * for "tick-less" systems.
  27. */
  28. static struct clocksource clocksource_jiffies = {
  29. .name = "jiffies",
  30. .rating = 1, /* lowest valid rating*/
  31. .uncertainty_margin = 32 * NSEC_PER_MSEC,
  32. .read = jiffies_read,
  33. .mask = CLOCKSOURCE_MASK(32),
  34. .mult = TICK_NSEC << JIFFIES_SHIFT, /* details above */
  35. .shift = JIFFIES_SHIFT,
  36. .max_cycles = 10,
  37. };
  38. __cacheline_aligned_in_smp DEFINE_RAW_SPINLOCK(jiffies_lock);
  39. __cacheline_aligned_in_smp seqcount_raw_spinlock_t jiffies_seq =
  40. SEQCNT_RAW_SPINLOCK_ZERO(jiffies_seq, &jiffies_lock);
  41. #if (BITS_PER_LONG < 64)
  42. u64 get_jiffies_64(void)
  43. {
  44. unsigned int seq;
  45. u64 ret;
  46. do {
  47. seq = read_seqcount_begin(&jiffies_seq);
  48. ret = jiffies_64;
  49. } while (read_seqcount_retry(&jiffies_seq, seq));
  50. return ret;
  51. }
  52. EXPORT_SYMBOL(get_jiffies_64);
  53. #endif
  54. EXPORT_SYMBOL(jiffies);
  55. static int __init init_jiffies_clocksource(void)
  56. {
  57. return __clocksource_register(&clocksource_jiffies);
  58. }
  59. core_initcall(init_jiffies_clocksource);
  60. struct clocksource * __init __weak clocksource_default_clock(void)
  61. {
  62. return &clocksource_jiffies;
  63. }
  64. static struct clocksource refined_jiffies;
  65. int register_refined_jiffies(long cycles_per_second)
  66. {
  67. u64 nsec_per_tick, shift_hz;
  68. long cycles_per_tick;
  69. refined_jiffies = clocksource_jiffies;
  70. refined_jiffies.name = "refined-jiffies";
  71. refined_jiffies.rating++;
  72. /* Calc cycles per tick */
  73. cycles_per_tick = (cycles_per_second + HZ/2)/HZ;
  74. /* shift_hz stores hz<<8 for extra accuracy */
  75. shift_hz = (u64)cycles_per_second << 8;
  76. shift_hz += cycles_per_tick/2;
  77. do_div(shift_hz, cycles_per_tick);
  78. /* Calculate nsec_per_tick using shift_hz */
  79. nsec_per_tick = (u64)NSEC_PER_SEC << 8;
  80. nsec_per_tick += (u32)shift_hz/2;
  81. do_div(nsec_per_tick, (u32)shift_hz);
  82. refined_jiffies.mult = ((u32)nsec_per_tick) << JIFFIES_SHIFT;
  83. __clocksource_register(&refined_jiffies);
  84. return 0;
  85. }