微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Linux 时钟管理

Linux 时钟管理

时间:06-13 来源:IBM 点击:

schedule_hrtimeout 用来产生一个高精度的调度超时,以 ns 为单位。这样可以更加细粒度的使用内核的调度器。在 Arjan van de Ven 的最初实现中,这个函数有一个很大的问题:由于其粒度很细,所以可能会更加频繁的唤醒内核,导致消耗更多的能源。为了实现既能节省能源,又能确保精确的调度超时,Arjan van de Ven 的办法是将一个超时点变成一个超时范围。设置 hrtimer A 的超时值有一个上限,称为 hard expire,在 hard expire 这个时间点上设置 hrtimer A 的超时中断;同时设置 hrtimer A 的超时值有一个下限,称为 soft expire。在 soft expire 到 hard expire 之间如果有一个 hrtimer B 的中断被触发,在 hrtimer B 的中断处理函数中,内核会检查是否有其他 hrtimer 的 soft expire 超时了,譬如 hrtimer A 的 soft expire 超时了,即使 hrtimer A 的 hard expire 没有到,也可以顺带被处理。换言之,将原来必须在 hard expire 超时才能执行的一个点变成一个范围后,可以尽量把 hrtimer 中断放在一起处理,这样 CPU 被重复唤醒的几率会变小,从而达到节能的效果,同时这个 hrtimer 也可以保证其执行精度。

Deferrable timers & round jiffies

在内核中使用的某些 legacy timer 对于精确的超时值并不敏感,早一点或者晚一点执行并不会产生多大的影响,因此,如果可以把这些对时间不敏感同时超时时间又比较接近的 timer 收集在一起执行,可以进一步减少 CPU 被唤醒的次数,从而达到节能的目地。这正是引入 Deferrable timers 的目地。如果一个 timer 可以被短暂延时,那么可以通过调用 init_timer_deferrable 设置 defer 标记,从而在执行时灵活选择处理方式。不过,如果这些 timers 都被延时到同一个时间点上也不是最优的选择,这样同样会产生 lock 竞争以及 cache-line 的问题。因此,即便将 defer timers 收集到一起,彼此之间也必须稍稍错开一些以防止上述问题。这正是引入 round_jiffies 函数的原因。虽然这样做会使得 CPU 被唤醒的次数稍多一些,但是由于间隔短,CPU 并不会进入很深的睡眠,这个代价还是可以接受的。由于 round_jiffies 需要在每次更新 timer 的超时值(mod_timer)时被调用,显得有些繁琐,因此又出现了更为便捷的 round jiffies 机制,称为 timer slack。Timer slack 修改了 timer_list 的结构定义,将需要偏移的 jiffies 值保存在 timer_list 内部,通过 apply_slack 在每次更新 timer 的过程中自动更新超时值。apply_slack 的实现如清单 9 所示:

清单 9. apply_slack 的实现

/* * Decide where to put the timer while taking the slack into account * * Algorithm: * 1) calculate the maximum (absolute) time * 2) calculate the highest bit where the expires and new max are different * 3) use this bit to make a mask * 4) use the bitmask to round down the maximum time, so that all last * bits are zeros */ static inline unsigned long apply_slack(struct timer_list *timer, unsigned long expires) { unsigned long expires_limit, mask; int bit; expires_limit = expires; if (timer->slack >= 0) { expires_limit = expires + timer->slack; } else { unsigned long now = jiffies; /* avoid reading jiffies twice */ /* if already expired, no slack; otherwise slack 0.4% */ if (time_after(expires, now)) expires_limit = expires + (expires - now)/256; } mask = expires ^ expires_limit; if (mask == 0) return expires; bit = find_last_bit(&mask, BITS_PER_LONG); mask = (1 << bit) - 1; expires_limit = expires_limit & ~(mask); return expires_limit; }

随着现代计算机系统的发展,对节能的需求越来越高,尤其是在使用笔记本,手持设备等移动环境是对节能要求更高。Linux 当然也会更加关注这方面的需求。hrtimer 子系统的优化尽量确保在使用高精度的时钟的同时节约能源,如果系统在空闲时也可以尽量的节能,则 Linux 系统的节能优势可以进一步放大。这也是引入 dynamic tick 的根本原因。

Dynamic tick & tickless

在 dynamic tick 引入之前,内核一直使用周期性的基于 HZ 的 tick。传统的 tick 机制在系统进入空

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top