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

前面已经讲过,高精度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;   }  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/22409.html