Chinaunix首页 | 论坛 | 博客
  • 博客访问: 851402
  • 博文数量: 143
  • 博客积分: 455
  • 博客等级: 一等列兵
  • 技术积分: 861
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-03 00:11
文章分类

全部博文(143)

文章存档

2018年(10)

2017年(6)

2016年(28)

2015年(14)

2014年(67)

2013年(1)

2012年(17)

我的朋友

分类: 其他平台

2014-01-01 09:53:59

一.头文件

  1. #include   

二.结构体

1.等待队列头

  1. struct __wait_queue_head {  
  2.     spinlock_t lock;  
  3.     struct list_head task_list;  
  4. };  
  5. typedef struct __wait_queue_head wait_queue_head_t;  

2.等待队列

  1. struct __wait_queue {  
  2.     unsigned int flags;  
  3.     void *private;  
  4.     wait_queue_func_t func;  
  5.     struct list_head task_list;  
  6. };  
  7. typedef struct __wait_queue wait_queue_t;  


三.初始化

1.等待队列头

定义声明等待队列头

  1. #define DECLARE_WAIT_QUEUE_HEAD(name) \   
  2.     wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)  

定义了一个等待队列头,并初始化其成员

  1. #define __WAIT_QUEUE_HEAD_INITIALIZER(name) {           \   
  2.     .lock   = __SPIN_LOCK_UNLOCKED(name.lock),      \  
  3.     .task_list  = { &(name).task_list, &(name).task_list } }  

2.等待队列

定义声明等待队列

  1. #define DECLARE_WAITQUEUE(name, tsk)                \   
  2.     wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)  

初始化其成员

  1. #define __WAITQUEUE_INITIALIZER(name, tsk) {            \   
  2.     .private    = tsk,                  \  
  3.     .func   = default_wake_function,            \  
  4.     .task_list  = { NULL, NULL } }  

四.添加与移除等待队列

1.添加等待队列

  1. void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)  
  2. {  
  3.     unsigned long flags;  
  4.   
  5.     wait->flags &= ~WQ_FLAG_EXCLUSIVE;  
  6.     spin_lock_irqsave(&q->lock, flags);  
  7.     __add_wait_queue(q, wait);  
  8.     spin_unlock_irqrestore(&q->lock, flags);  
  9. }  

__add_wait_queue本质上就是添加等待队列的task_list进等待队列头的task_list为首项的list链表

  1. static inline void __add_wait_queue_tail(wait_queue_head_t *head, wait_queue_t *new)  
  2. {  
  3.     list_add_tail(&new->task_list, &head->task_list);  
  4. }  

2.移除等待队列

  1. void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)  
  2. {  
  3.     unsigned long flags;  
  4.   
  5.     spin_lock_irqsave(&q->lock, flags);  
  6.     __remove_wait_queue(q, wait);  
  7.     spin_unlock_irqrestore(&q->lock, flags);  
  8. }  

__remove_wait_queue本质上就是从等待队列头的task_list为首项的list链表中移除等待队列的task_list

  1. static inline void __remove_wait_queue(wait_queue_head_t *head,wait_queue_t *old)  
  2. {  
  3.     list_del(&old->task_list);  
  4. }  

五.等待,唤醒,睡眠
1.等待

1.1 wait_event 等待事件发生,不可中断

  1. #define wait_event(wq, condition)                   \   
  2. do {                                \  
  3.     if (condition)                      \   //唤醒的条件为真,则退出   
  4.         break;                      \  
  5.     __wait_event(wq, condition);                \  
  6. while (0)  

__wait_event

  1. #define __wait_event(wq, condition)                     \   
  2. do {                                \  
  3.     DEFINE_WAIT(__wait);                    \  
  4.                                 \  
  5.     for (;;) {                      \  
  6.         prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);    \   //TASK_UNINTERRUPTIBLE标明不可中断   
  7.         if (condition)                  \   //唤醒的条件为真,则退出for循环   
  8.             break;                  \  
  9.         schedule();                 \   //进入调度   
  10.     }                           \  
  11.     finish_wait(&wq, &__wait);                  \   //设置进程为TASK_RUNNING,并移除等待队列中的队列项   
  12. while (0)  

1.2 wait_event_interruptible 等待事件发生,可中断

  1. #define wait_event_interruptible(wq, condition)         \   
  2. ({                              \  
  3.     int __ret = 0;                      \  
  4.     if (!(condition))                       \   //条件为真则退出   
  5.         __wait_event_interruptible(wq, condition, __ret);   \     
  6.     __ret;                          \  
  7. })  

__wait_event_interruptible

  1. #define __wait_event_interruptible(wq, condition, ret)          \   
  2. do {                                \  
  3.     DEFINE_WAIT(__wait);                    \  
  4.                                 \  
  5.     for (;;) {                      \  
  6.         prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);  \   //TASK_INTERRUPTIBLE标明可中断   
  7.         if (condition)                  \   //唤醒的条件为真,则退出for循环   
  8.             break;                  \  
  9.         if (!signal_pending(current)) {         \   //检测当前进程是否有信号要处理   
  10.             schedule();             \   //进入调度   
  11.             continue;                   \  
  12.         }                       \  
  13.         ret = -ERESTARTSYS;             \  
  14.         break;                      \  
  15.     }                           \  
  16.     finish_wait(&wq, &__wait);                  \   //设置进程为TASK_RUNNING,并移除等待队列中的队列项   
  17. while (0)  

1.3 wait_event_timeout 超时等待事件,不可中断

  1. #define wait_event_timeout(wq, condition, timeout)          \   
  2. ({                              \  
  3.     long __ret = timeout;                   \  
  4.     if (!(condition))                       \   //等待条件为真则退出   
  5.         __wait_event_timeout(wq, condition, __ret);     \     
  6.     __ret;                          \  
  7. })  

__wait_event_timeout

  1. #define __wait_event_timeout(wq, condition, ret)            \   
  2. do {                                \  
  3.     DEFINE_WAIT(__wait);                    \  
  4.                                 \  
  5.     for (;;) {                      \  
  6.         prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);    \   //TASK_UNINTERRUPTIBLE标明不可中断   
  7.         if (condition)                  \   //唤醒的条件为真,则退出for循环   
  8.             break;                  \  
  9.         ret = schedule_timeout(ret);            \   //调度,并设置超时值   
  10.         if (!ret)                       \   //超时则退出   
  11.             break;                  \  
  12.     }                           \  
  13.     finish_wait(&wq, &__wait);                  \   //设置进程为TASK_RUNNING,并移除等待队列中的队列项       
  14. while (0)  

1.4 wait_event_interruptible_timeout 超时等待事件,可中断

  1. #define wait_event_interruptible_timeout(wq, condition, timeout)    \   
  2. ({                              \  
  3.     long __ret = timeout;                   \  
  4.     if (!(condition))                       \   //等待条件为真则退出   
  5.         __wait_event_interruptible_timeout(wq, condition, __ret); \   
  6.     __ret;                          \  
  7. })  

__wait_event_interruptible_timeout

  1. #define __wait_event_interruptible_timeout(wq, condition, ret)      \   
  2. do {                                \  
  3.     DEFINE_WAIT(__wait);                    \  
  4.                                 \  
  5.     for (;;) {                      \  
  6.         prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);  \   //TASK_INTERRUPTIBLE标明可中断   
  7.         if (condition)                  \   //唤醒的条件为真,则退出for循环   
  8.             break;                  \  
  9.         if (!signal_pending(current)) {         \   //检测当前进程是否有信号要处理   
  10.             ret = schedule_timeout(ret);        \   //调度,并设置超时值   
  11.             if (!ret)                   \   //超时则退出   
  12.                 break;              \  
  13.             continue;                   \     
  14.         }                       \  
  15.         ret = -ERESTARTSYS;             \  
  16.         break;                      \  
  17.     }                           \  
  18.     finish_wait(&wq, &__wait);                  \   //设置进程为TASK_RUNNING,并移除等待队列中的队列项   
  19. while (0)  


2.唤醒
2.1 wake_up唤醒不可中断的等待队列

  1. #define wake_up(x)   __wake_up(x, TASK_NORMAL, 1, NULL)  

衍生的其他宏

  1. #define wake_up_nr(x, nr)       __wake_up(x, TASK_NORMAL, nr, NULL)   
  2. #define wake_up_all(x)          __wake_up(x, TASK_NORMAL, 0, NULL)   
  3. #define wake_up_locked(x)       __wake_up_locked((x), TASK_NORMAL)  

2.2 wake_up_interruptible唤醒可中断的等待队列

  1. #define wake_up_interruptible(x) __wake_up(x, TASK_INTERRUPTIBLE, 1, NULL)  

衍生的其他宏

  1. #define wake_up_interruptible_nr(x, nr) __wake_up(x, TASK_INTERRUPTIBLE, nr, NULL)   
  2. #define wake_up_interruptible_all(x)    __wake_up(x, TASK_INTERRUPTIBLE, 0, NULL)   
  3. #define wake_up_interruptible_sync(x)   __wake_up_sync((x), TASK_INTERRUPTIBLE, 1)  

 

两个宏最终都调用__wake_up

  1. void __wake_up(wait_queue_head_t *q, unsigned int mode,int nr_exclusive, void *key)  
  2. {  
  3.     unsigned long flags;  
  4.   
  5.     spin_lock_irqsave(&q->lock, flags);  
  6.     __wake_up_common(q, mode, nr_exclusive, 0, key);    //-->__wake_up_common   
  7.     spin_unlock_irqrestore(&q->lock, flags);  
  8. }  

__wake_up_common

  1. static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,int nr_exclusive, int wake_flags, void *key)  
  2. {  
  3.     wait_queue_t *curr, *next;  
  4.   
  5.     list_for_each_entry_safe(curr, next, &q->task_list, task_list) { //遍历等待队列表   
  6.         unsigned flags = curr->flags;      
  7.         //调用其等待队列项的func方法,-->default_wake_function   
  8.         if (curr->func(curr, mode, wake_flags, key) &&(flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)  
  9.             break;  
  10.     }  
  11. }  

default_wake_function

  1. int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags,void *key)  
  2. {  
  3.     return try_to_wake_up(curr->private, mode, wake_flags);  //-->try_to_wake_up   
  4.     }  

try_to_wake_up

  1. static int try_to_wake_up(struct task_struct *p, unsigned int state,int wake_flags)  
  2. {  
  3.     int cpu, orig_cpu, this_cpu, success = 0;  
  4.     unsigned long flags;  
  5.     unsigned long en_flags = ENQUEUE_WAKEUP;  
  6.     struct rq *rq;  
  7.     this_cpu = get_cpu();  
  8.   
  9.     smp_wmb();  
  10.     rq = task_rq_lock(p, &flags);  
  11.     if (!(p->state & state))  
  12.         goto out;  
  13.   
  14.     if (p->se.on_rq)  
  15.         goto out_running;  
  16.   
  17.     cpu = task_cpu(p);  
  18.     orig_cpu = cpu;  
  19.   
  20. #ifdef CONFIG_SMP   
  21.     if (unlikely(task_running(rq, p)))  
  22.         goto out_activate;  
  23.   
  24.     if (task_contributes_to_load(p)) {  
  25.         if (likely(cpu_online(orig_cpu)))  
  26.             rq->nr_uninterruptible--;  
  27.         else  
  28.             this_rq()->nr_uninterruptible--;  
  29.     }  
  30.     p->state = TASK_WAKING;  
  31.   
  32.     if (p->sched_class->task_waking) {  
  33.         p->sched_class->task_waking(rq, p);  
  34.         en_flags |= ENQUEUE_WAKING;  
  35.     }  
  36.   
  37.     cpu = select_task_rq(rq, p, SD_BALANCE_WAKE, wake_flags);  
  38.     if (cpu != orig_cpu)  
  39.         set_task_cpu(p, cpu);  
  40.     __task_rq_unlock(rq);  
  41.   
  42.     rq = cpu_rq(cpu);  
  43.     raw_spin_lock(&rq->lock);  
  44.   
  45.     WARN_ON(task_cpu(p) != cpu);  
  46.     WARN_ON(p->state != TASK_WAKING);  
  47.   
  48. #ifdef CONFIG_SCHEDSTATS   
  49.     schedstat_inc(rq, ttwu_count);  
  50.     if (cpu == this_cpu)  
  51.         schedstat_inc(rq, ttwu_local);  
  52.     else {  
  53.         struct sched_domain *sd;  
  54.         for_each_domain(this_cpu, sd) {  
  55.             if (cpumask_test_cpu(cpu, sched_domain_span(sd))) {  
  56.                 schedstat_inc(sd, ttwu_wake_remote);  
  57.                 break;  
  58.             }  
  59.         }  
  60.     }  
  61. #endif /* CONFIG_SCHEDSTATS */   
  62.   
  63. out_activate:  
  64. #endif /* CONFIG_SMP */   
  65.     ttwu_activate(p, rq, wake_flags & WF_SYNC, orig_cpu != cpu, cpu == this_cpu, en_flags); //最终调用activate_task激活等待进程   
  66.     success = 1;  
  67. out_running:  
  68.     ttwu_post_activation(p, rq, wake_flags, success);  
  69. out:  
  70.     task_rq_unlock(rq, &flags);  
  71.     put_cpu();  
  72.   
  73.     return success;  
  74. }  

3.睡眠

3.1 sleep_on 睡眠,不可中断

  1. void __sched sleep_on(wait_queue_head_t *q)  
  2. {  
  3.     sleep_on_common(q, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);  
  4. }  

3.2 interruptible_sleep_on 睡眠,可中断

  1. void __sched interruptible_sleep_on(wait_queue_head_t *q)  
  2. {  
  3.     sleep_on_common(q, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);  
  4. }  

3.3 sleep_on_timeout 超时睡眠,不可中断

  1. long __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)  
  2. {  
  3.     return sleep_on_common(q, TASK_UNINTERRUPTIBLE, timeout);  
  4. }  

3.4 interruptible_sleep_on_timeout 超时睡眠,可中断

  1. long __sched interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)  
  2. {  
  3.     return sleep_on_common(q, TASK_INTERRUPTIBLE, timeout);  
  4. }  

睡眠api最终都会调用sleep_on_common

  1. static long __sched  
  2. sleep_on_common(wait_queue_head_t *q, int state, long timeout)  
  3. {  
  4.     unsigned long flags;  
  5.     wait_queue_t wait;  
  6.   
  7.     init_waitqueue_entry(&wait, current);   //初始化等待队列项   
  8.   
  9.     __set_current_state(state);     //设置当前进程的状态TASK_UNINTERRUPTIBLE、TASK_INTERRUPTIBLE   
  10.   
  11.     spin_lock_irqsave(&q->lock, flags);  
  12.     __add_wait_queue(q, &wait); //添加等待队列项   
  13.     spin_unlock(&q->lock);  
  14.     timeout = schedule_timeout(timeout);    //调度,设置超时值   
  15.     spin_lock_irq(&q->lock);  
  16.     __remove_wait_queue(q, &wait);  //移除等待队列项   
  17.     spin_unlock_irqrestore(&q->lock, flags);  
  18.   
  19.     return timeout;  
  20. }  


六.整理

  1. //等待队列头   
  2. wait_queue_head_t     
  3. //初始化等待队列头   
  4. DECLARE_WAIT_QUEUE_HEAD(name)  
  5.   
  6. //等待队列项   
  7. wait_queue_t      
  8. //初始化等待队列项   
  9. DECLARE_WAITQUEUE(name, tsk)      
  10. //添加移除等待队列项   
  11. void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)       //添加等待队列项   
  12. void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)    //移除等待队列项   
  13. //等待事件   
  14. wait_event(wq, condition)                       //等待事件,不可中断    
  15. wait_event_interruptible(wq, condition)             //等待事件,可中断          
  16. wait_event_timeout(wq, condition, timeout)              //超时等待,不可中断   
  17. wait_event_interruptible_timeout(wq, condition, timeout)        //超时等待,可中断     
  18. //唤醒事件   
  19. wake_up(x)                          //唤醒事件,不可中断   
  20. wake_up_interruptible(x)                        //唤醒事件,可中断   
  21. //等待队列上睡眠   
  22. void __sched sleep_on(wait_queue_head_t *q)             //睡眠,不可中断   
  23. void __sched interruptible_sleep_on(wait_queue_head_t *q)       //睡眠,可中断   
  24. long __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)  //超时睡眠,不可中断   
  25. long __sched interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout) //超时睡眠,可中断  

等待和睡眠本质上在于有无条件,睡眠属于旧版本内核的东西,很少使用到

 

阅读(1245) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~