Linux hrtimer的实现


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.     /* 
  27.      * Second part is written at each timer interrupt 
  28.      * Keep it in a different cache line to dirty no 
  29.      * more than one cache line. 
  30.      */  
  31.     cycle_t cycle_last ____cacheline_aligned_in_smp;  
  32.   
  33. #ifdef CONFIG_CLOCKSOURCE_WATCHDOG   
  34.     /* Watchdog related data, used by the framework */  
  35.     struct list_head wd_list;  
  36.     cycle_t wd_last;  
  37. #endif   
  38. };  

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. };  
  43.    

上述两个结构内核源代码中有较详细的注解,分别位于文件 clocksource.h 和 clockchips.h 中。需要特别注意的是结构 clock_event_device 的成员 event_handler ,它指定了当硬件时钟中断发生时,内核应该执行那些操作,也就是真正的时钟中断处理函数。

Linux 内核维护了两个链表,分别存储了系统中所有时钟源的信息和时钟事件设备的信息。这两个链表的表头在内核中分别是 clocksource_list 和 clockevent_devices 。 

  • 1
  • 2
  • 下一页

相关内容