之前经常在内核看到,
这样的函数。虽然好奇,但是一直没弄懂。老子就想sleep一段时间,你干嘛搞个range ?
今天搞一个跟精确时间很相关的问题,终于仔细看了一下代码。
hrtimer就是高精度定时器,精度是高,happy的同时也带来一个问题,那就是中断太多了,虽说中断是个好东西,但是有时候两个定时器相差几十个纳秒,
你完全没必要搞两个中断!
那么对于精度要求不高的情况,是不是可以降低硬件中断次数呀,
这个就是struct task_struct->timer_slack_ns的目的。通过timer_slack_ns来设置一个范围(range),在这个范围里面的hrtimer,我可以顺带一起处理了。
那么怎么个一起处理法?
-
198static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time)
-
199{
-
200 timer->node.expires = time;
-
201 timer->_softexpires = time;
-
202}
-
203
-
204static inline void hrtimer_set_expires_range(struct hrtimer *timer, ktime_t time, ktime_t delta)
-
205{
-
206 timer->_softexpires = time;
-
207 timer->node.expires = ktime_add_safe(time, delta);
-
208}
-
209
-
210static inline void hrtimer_set_expires_range_ns(struct hrtimer *timer, ktime_t time, unsigned long delta)
-
211{
-
212 timer->_softexpires = time;
-
213 timer->node.expires = ktime_add_safe(time, ns_to_ktime(delta));
-
214}
首先来看这几个函数,都是在设置expires时间,可以看到timer里两个变量一个是node.expires, 另外一个是softexpires.
在hrtimer中设置定时器的时间都是以node.expires为准,这一点从可以看出来,而且红黑树的key也是node.expires.
那么问题来了,
softexpires是什么鬼,要了干嘛?
这一点要从hrtimer_interrupt的代码来看了
-
1325 for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
-
1326 struct hrtimer_clock_base *base;
-
1327 struct timerqueue_node *node;
-
1328 ktime_t basenow;
-
1329
-
1330 if (!(cpu_base->active_bases & (1 << i)))
-
1331 continue;
-
1332
-
1333 base = cpu_base->clock_base + i;
-
1334 basenow = ktime_add(now, base->offset);
-
1335
-
1336 while ((node = timerqueue_getnext(&base->active))) {
-
1337 struct hrtimer *timer;
-
1338
-
1339 timer = container_of(node, struct hrtimer, node);
-
1340
-
1341 /*
-
1342 * The immediate goal for using the softexpires is
-
1343 * minimizing wakeups, not running timers at the
-
1344 * earliest interrupt after their soft expiration.
-
1345 * This allows us to avoid using a Priority Search
-
1346 * Tree, which can answer a stabbing querry for
-
1347 * overlapping intervals and instead use the simple
-
1348 * BST we already have.
-
1349 * We don't add extra wakeups by delaying timers that
-
1350 * are right-of a not yet expired timer, because that
-
1351 * timer will have to trigger a wakeup anyway.
-
1352 */
-
1353 if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer))
-
1354 break;
-
1355
-
1356 __run_hrtimer(timer, &basenow);
-
1357 }
-
1358 }
最关键的就是上面这句
if (. < ());
可以在别的hrtimer A中顺带把hrtimer B给处理了。
以上面的图为例,一个hrtime A, 其timeout时间为T+delat,但是如果在T~T+delat之间的某一点上,hrtimer B到期,
中断触发,在中断处理函数hrtimer_interrupt里面,顺带把hrtimer A也处理了。
现在android里面的cgroup将进程分为前台进程和后台进程,后台进程的默认的time_slack_ns为50ms,要小心了,对于性能相关的影响
比较大。
阅读(4268) | 评论(0) | 转发(0) |