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


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

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

在Kernel中如何使用的呢?

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

  1. static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,  
  2.            int maxevents, long timeout)  
  3. {  
  4.     int res = 0, eavail, timed_out = 0;  
  5.     unsigned long flags;  
  6.     long slack = 0;  
  7.     wait_queue_t wait;  
  8.     ktime_t expires, *to = NULL;  
  9.   
  10.     if (timeout > 0) {  
  11.         struct timespec end_time = ep_set_mstimeout(timeout);  
  12.   
  13.         slack = select_estimate_accuracy(&end_time);  
  14.         to = &expires;  
  15.         *to = timespec_to_ktime(end_time);  
  16.     } else if (timeout == 0) {  
  17.         /* 
  18.          * Avoid the unnecessary trip to the wait queue loop, if the 
  19.          * caller specified a non blocking operation. 
  20.          */  
  21.         timed_out = 1;  
  22.         spin_lock_irqsave(&ep->lock, flags);  
  23.         goto check_events;  
  24.     }  
  25.   
  26. fetch_events:  
  27.     spin_lock_irqsave(&ep->lock, flags);  
  28.   
  29.     if (!ep_events_available(ep)) {  
  30.         /* 
  31.          * We don't have any available event to return to the caller. 
  32.          * We need to sleep here, and we will be wake up by 
  33.          * ep_poll_callback() when events will become available. 
  34.          */  
  35.         init_waitqueue_entry(&wait, current);  
  36.         __add_wait_queue_exclusive(&ep->wq, &wait);  
  37.   
  38.         for (;;) {  
  39.             /* 
  40.              * We don't want to sleep if the ep_poll_callback() sends us 
  41.              * a wakeup in between. That's why we set the task state 
  42.              * to TASK_INTERRUPTIBLE before doing the checks. 
  43.              */  
  44.             set_current_state(TASK_INTERRUPTIBLE);  
  45.             if (ep_events_available(ep) || timed_out)  
  46.                 break;  
  47.             if (signal_pending(current)) {  
  48.                 res = -EINTR;  
  49.                 break;  
  50.             }  
  51.   
  52.             spin_unlock_irqrestore(&ep->lock, flags);  
  53.             if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))  
  54.                 timed_out = 1;  
  55.   
  56.             spin_lock_irqsave(&ep->lock, flags);  
  57.         }  
  58.         __remove_wait_queue(&ep->wq, &wait);  
  59.   
  60.         set_current_state(TASK_RUNNING);  
  61.     }  
  62. check_events:  
  63.     /* Is it worth to try to dig for events ? */  
  64.     eavail = ep_events_available(ep);  
  65.   
  66.     spin_unlock_irqrestore(&ep->lock, flags);  
  67.   
  68.     /* 
  69.      * Try to transfer events to user space. In case we get 0 events and 
  70.      * there's still timeout left over, we go trying again in search of 
  71.      * more luck. 
  72.      */  
  73.     if (!res && eavail &&  
  74.         !(res = ep_send_events(ep, events, maxevents)) && !timed_out)  
  75.         goto fetch_events;  
  76.   
  77.     return res;  
  78. }  
  • 1
  • 2
  • 下一页

相关内容