Kernel中如何使用高精度timer(hrtimer)

原文链接: https://my.oschina.net/abcijkxyz/blog/788722

   前面已经讲过,高精度timer是通过hrtimer来实现的,hrtimer通过可编程定时器来现,在等待时,不占用CPU。

       在用户态,只要我们调用usleep,则线程在kernel态执行时,则使用hrtimer进行不占CPU的等待。

       在Kernel中如何使用的呢?

       先看看eventpoll.c中的ep_poll函数:

 

static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
		   int maxevents, long timeout)
{
	int res = 0, eavail, timed_out = 0;
	unsigned long flags;
	long slack = 0;
	wait_queue_t wait;
	ktime_t expires, *to = NULL;

	if (timeout > 0) {
		struct timespec end_time = ep_set_mstimeout(timeout);

		slack = select_estimate_accuracy(&end_time);
		to = &expires;
		*to = timespec_to_ktime(end_time);
	} else if (timeout == 0) {
		/*
		 * Avoid the unnecessary trip to the wait queue loop, if the
		 * caller specified a non blocking operation.
		 */
		timed_out = 1;
		spin_lock_irqsave(&ep->lock, flags);
		goto check_events;
	}

fetch_events:
	spin_lock_irqsave(&ep->lock, flags);

	if (!ep_events_available(ep)) {
		/*
		 * We don't have any available event to return to the caller.
		 * We need to sleep here, and we will be wake up by
		 * ep_poll_callback() when events will become available.
		 */
		init_waitqueue_entry(&wait, current);
		__add_wait_queue_exclusive(&ep->wq, &wait);

		for (;;) {
			/*
			 * We don't want to sleep if the ep_poll_callback() sends us
			 * a wakeup in between. That's why we set the task state
			 * to TASK_INTERRUPTIBLE before doing the checks.
			 */
			set_current_state(TASK_INTERRUPTIBLE);
			if (ep_events_available(ep) || timed_out)
				break;
			if (signal_pending(current)) {
				res = -EINTR;
				break;
			}

			spin_unlock_irqrestore(&ep->lock, flags);
			if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))
				timed_out = 1;

			spin_lock_irqsave(&ep->lock, flags);
		}
		__remove_wait_queue(&ep->wq, &wait);

		set_current_state(TASK_RUNNING);
	}
check_events:
	/* Is it worth to try to dig for events ? */
	eavail = ep_events_available(ep);

	spin_unlock_irqrestore(&ep->lock, flags);

	/*
	 * Try to transfer events to user space. In case we get 0 events and
	 * there's still timeout left over, we go trying again in search of
	 * more luck.
	 */
	if (!res && eavail &&
	    !(res = ep_send_events(ep, events, maxevents)) && !timed_out)
		goto fetch_events;

	return res;
}


       看到上面的schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS)了吗?它就是hrtimer中调用来执行等待超时的函数

,其函数原型为:

/**
 * schedule_hrtimeout_range - sleep until timeout
 * @expires: timeout value (ktime_t)
 * @delta : slack in expires timeout (ktime_t)
 * @mode : timer mode, HRTIMER_MODE_ABS or HRTIMER_MODE_REL
 */
int __sched schedule_hrtimeout_range(ktime_t *expires, unsigned long delta,
         const enum hrtimer_mode mode)
{
 return schedule_hrtimeout_range_clock(expires, delta, mode,
           CLOCK_MONOTONIC);
}
      在ep_poll中,其slack和to的计算方法如下:

struct timespec end_time = ep_set_mstimeout(timeout);
slack = select_estimate_accuracy(&end_time);
to = &expires;
*to = timespec_to_ktime(end_time);

      如果你在Kernel中需要高精度timer,可以参照此方法实现自己的高精度timer超时。

转载于:https://my.oschina.net/abcijkxyz/blog/788722

你可能感兴趣的:(Kernel中如何使用高精度timer(hrtimer))