歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux hrtimer的實現

Linux hrtimer的實現

日期:2017/2/28 15:55:14   编辑:Linux教程

1. Linux hrtimer的實現方案

Linux hrtimer的實現是依賴硬件(通過可編程定時器來實現)的支持的,而且此定時器有自己的專用寄存器, 硬中斷和頻率。比如我的板子上的對應參數如下:

Timer at Vir:0xE0100200 = Phy:0xE0100200, using Irq:27, at Freq:250000000,由此可見,其頻率為250MHz,所以其精度為:1/250000000=4ns,比系統時鐘jiffy(HZ=100,精度為10ms)的精度高得太多了。可是支持此高精度timer是需要付出硬件成本的。即它是一個硬件時鐘。這裡所說的硬件時鐘特指的是硬件計時器時鐘。

2. 硬件時鐘 數據結構
  和硬件計時器(本文又稱作硬件時鐘,區別於軟件時鐘)相關的數據結構主要有兩個:
  struct clocksource :對硬件設備的抽象,描述時鐘源信息

  1. struct clocksource {
  2. /*
  3. * First part of structure is read mostly
  4. */
  5. char *name;
  6. struct list_head list;
  7. int rating;
  8. cycle_t (*read)(struct clocksource *cs);
  9. int (*enable)(struct clocksource *cs);
  10. void (*disable)(struct clocksource *cs);
  11. cycle_t mask;
  12. u32 mult;
  13. u32 shift;
  14. u64 max_idle_ns;
  15. unsigned long flags;
  16. cycle_t (*vread)(void);
  17. void (*suspend)(struct clocksource *cs);
  18. void (*resume)(struct clocksource *cs);
  19. #ifdef CONFIG_IA64
  20. void *fsys_mmio; /* used by fsyscall asm code */
  21. #define CLKSRC_FSYS_MMIO_SET(mmio, addr) ((mmio) = (addr))
  22. #else
  23. #define CLKSRC_FSYS_MMIO_SET(mmio, addr) do { } while (0)
  24. #endif
  25. /*
  26. * Second part is written at each timer interrupt
  27. * Keep it in a different cache line to dirty no
  28. * more than one cache line.
  29. */
  30. cycle_t cycle_last ____cacheline_aligned_in_smp;
  31. #ifdef CONFIG_CLOCKSOURCE_WATCHDOG
  32. /* Watchdog related data, used by the framework */
  33. struct list_head wd_list;
  34. cycle_t wd_last;
  35. #endif
  36. };

struct clock_event_device :時鐘的事件信息,包括當硬件時鐘中斷發生時要執行那些操作(實際上保存了相應函數的指針)。本文將該結構稱作為“時鐘事件設備”。

  1. /**
  2. * struct clock_event_device - clock event device descriptor
  3. * @name: ptr to clock event name
  4. * @features: features
  5. * @max_delta_ns: maximum delta value in ns
  6. * @min_delta_ns: minimum delta value in ns
  7. * @mult: nanosecond to cycles multiplier
  8. * @shift: nanoseconds to cycles divisor (power of two)
  9. * @rating: variable to rate clock event devices
  10. * @irq: IRQ number (only for non CPU local devices)
  11. * @cpumask: cpumask to indicate for which CPUs this device works
  12. * @set_next_event: set next event function
  13. * @set_mode: set mode function
  14. * @event_handler: Assigned by the framework to be called by the low
  15. * level handler of the event source
  16. * @broadcast: function to broadcast events
  17. * @list: list head for the management code
  18. * @mode: operating mode assigned by the management code
  19. * @next_event: local storage for the next event in oneshot mode
  20. * @retries: number of forced programming retries
  21. */
  22. struct clock_event_device {
  23. const char *name;
  24. unsigned int features;
  25. u64 max_delta_ns;
  26. u64 min_delta_ns;
  27. u32 mult;
  28. u32 shift;
  29. int rating;
  30. int irq;
  31. const struct cpumask *cpumask;
  32. int (*set_next_event)(unsigned long evt,
  33. struct clock_event_device *);
  34. void (*set_mode)(enum clock_event_mode mode,
  35. struct clock_event_device *);
  36. void (*event_handler)(struct clock_event_device *);
  37. void (*broadcast)(const struct cpumask *mask);
  38. struct list_head list;
  39. enum clock_event_mode mode;
  40. ktime_t next_event;
  41. unsigned long retries;
  42. };

上述兩個結構內核源代碼中有較詳細的注解,分別位於文件 clocksource.h 和 clockchips.h 中。需要特別注意的是結構 clock_event_device 的成員 event_handler ,它指定了當硬件時鐘中斷發生時,內核應該執行那些操作,也就是真正的時鐘中斷處理函數。

Linux 內核維護了兩個鏈表,分別存儲了系統中所有時鐘源的信息和時鐘事件設備的信息。這兩個鏈表的表頭在內核中分別是 clocksource_list 和 clockevent_devices 。

Copyright © Linux教程網 All Rights Reserved