Chinaunix首页 | 论坛 | 博客
  • 博客访问: 177217
  • 博文数量: 37
  • 博客积分: 1367
  • 博客等级: 中尉
  • 技术积分: 465
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-06 17:41
文章分类

全部博文(37)

文章存档

2015年(1)

2012年(17)

2011年(10)

2010年(1)

2009年(8)

我的朋友

分类: 嵌入式

2011-10-20 17:07:40

  1. /* 有多少空间被释放 */
  2. static int spacefreee(struct scull_pipe *dev)
  3. {
  4.     if (dev->rp == dev->wp)
  5.     {
  6.         return dev->buffersize - 1;
  7.     }
  8.     
  9.     /* 这条语句很好,空间为写指针位置之后,
  10.      * 读指针位置之前的这段空间
  11.      */
  12.     return ( (dev->rp - dev->wp + dev->buffersize) % dev->buffersize ) -1 ;
  13. }

下面看手工休眠的过程。
第一步是建立并初始化一个等待队列入口。
  1. DEFINE_WAIT(my_wait);

其中name是等待队列入口变量的名称。也可以通过下面两个步骤完成这个工作:
  1. wait_queue_t my_wait;
  2. init_wait(&my_wait);
下一个步骤是将等待队列入口添加到队列中,并设置进程的状态,前面的两种方法都可通过下面的函数完成:
  1. void prepare_to_wait(wait_queue_head_t *queue, wait_queue_t *wait, int state);
queue 和 wait分别是等待队列头和进程入口。state是进程的新状态;它应该是TASK_INTERRUPTIBLE 或TASK_UNINTERRUPTIBLE


这里先看下,结构体wait_queue_head_t和wait_queue_t 的具体定义:
  1. typedef struct __wait_queue_head wait_queue_head_t;
  2. struct __wait_queue_head
  3. {
  4.     spinlock_t lock;
  5.     struct list_head task_list;
  6. };

  1. typedef struct __wait_queue wait_queue_t;
  2. typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key);
  3. int default_wake_function(wait_queue_t *wait, unsigned mode, int flags, void *key);

  4. struct __wait_queue
  5. {
  6.     unsigned int flags;
  7. #define WQ_FLAG_EXCLUSIVE    0x01
  8.     void *private;
  9.     wait_queue_func_t func;
  10.     struct list_head task_list;
  11. };
在调用了prepare_to_wait 之后,进程即可调用schedule,当然在这之前,应确保仍有必要等待。
一旦schedule返回,就到了清理时间了,这个工作也可通过下面的特殊函数完成:
  1. void finish_wait(wait_queue_head_t *queue, wait_queue_t *wait);

  1. /*
  2.  * finish_wait - clean up after waiting in a queue
  3.  * @q: waitqueue waited on
  4.  * @wait: wait descriptor
  5.  *
  6.  * Sets current thread back to running state and removes
  7.  * the wait descriptor from the given waitqueue if still
  8.  * queued.
  9.  */
  10. void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
  11. {
  12.     unsigned long flags;

  13.     __set_current_state(TASK_RUNNING);
  14.     /*
  15.      * We can check for list emptiness outside the lock
  16.      * IFF:
  17.      * - we use the "careful" check that verifies both
  18.      * the next and prev pointers, so that there cannot
  19.      * be any half-pending updates in progress on other
  20.      * CPU's that we haven't seen yet (and that might
  21.      * still change the stack area.
  22.      * and
  23.      * - all other users take the lock (ie we can only
  24.      * have _one_ other CPU that looks at or modifies
  25.      * the list).
  26.      */
  27.     if (!list_empty_careful(&wait->task_list)) {
  28.         spin_lock_irqsave(&q->lock, flags);
  29.         list_del_init(&wait->task_list);
  30.         spin_unlock_irqrestore(&q->lock, flags);
  31.     }
  32. }
之后,代码可测试其状态,并判断是否需要重新等待。

好了,让我们来看看DEFINE_WAIT(my_wait)等得定义吧,跟踪下。

而init_wait(&my_wait)的定义如下:
  1. #define init_wait(wait)                            \
  2. do {                                 \
  3.     (wait)->private = current;                 \
  4.     (wait)->func = autoremove_wake_function;    \
  5.     INIT_LIST_HEAD(&(wait)->task_list);            \
  6. } while (0)

  1. static inline void INIT_LIST_HEAD(struct list_head *list)
  2. {
  3.     list->next = list;
  4.     list->prev = list;
  5. }
由上面看来DEFINE_WAIT(my_wait)同
wait_queue_t my_wait;
init_wait(my_wait);
确实做得是一样的事情。

再来看看prepare_to_wait()函数吧.
  1. void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
  2. {
  3.     unsigned long flags;

  4.     wait->flags &= ~WQ_FLAG_EXCLUSIVE;
  5.     spin_lock_irqsave(&q->lock, flags);
  6.     if (list_empty(&wait->task_list))
  7.         __add_wait_queue(q, wait);
  8.     set_current_state(state);
  9.     spin_unlock_irqrestore(&q->lock, flags);
  10. }

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

  1. static inline void __list_add(struct list_head *new,
  2.              struct list_head *prev,
  3.              struct list_head *next)
  4. {
  5.     next->prev = new;
  6.     new->next = next;
  7.     new->prev = prev;
  8.     prev->next = new;
  9. }


再来看finish_wait 函数
  1. /*
  2.  * finish_wait - clean up after waiting in a queue
  3.  * @q: waitqueue waited on
  4.  * @wait: wait descriptor
  5.  *
  6.  * Sets current thread back to running state and removes
  7.  * the wait descriptor from the given waitqueue if still
  8.  * queued.
  9.  */
  10. void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
  11. {
  12.     unsigned long flags;

  13.     __set_current_state(TASK_RUNNING);
  14.     /*
  15.      * We can check for list emptiness outside the lock
  16.      * IFF:
  17.      * - we use the "careful" check that verifies both
  18.      * the next and prev pointers, so that there cannot
  19.      * be any half-pending updates in progress on other
  20.      * CPU's that we haven't seen yet (and that might
  21.      * still change the stack area.
  22.      * and
  23.      * - all other users take the lock (ie we can only
  24.      * have _one_ other CPU that looks at or modifies
  25.      * the list).
  26.      */
  27.     if (!list_empty_careful(&wait->task_list)) {
  28.         spin_lock_irqsave(&q->lock, flags);
  29.         list_del_init(&wait->task_list);
  30.         spin_unlock_irqrestore(&q->lock, flags);
  31.     }
  32. }

  1. wait_event(queue, condition) 其实里面的内容就是我们上面说的东西,看代码:
    1. /**
    2.  * wait_event - sleep until a condition gets true
    3.  * @wq: the waitqueue to wait on
    4.  * @condition: a C expression for the event to wait for
    5.  *
    6.  * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
    7.  * @condition evaluates to true. The @condition is checked each time
    8.  * the waitqueue @wq is woken up.
    9.  *
    10.  * wake_up() has to be called after changing any variable that could
    11.  * change the result of the wait condition.
    12.  */
    13. #define wait_event(wq, condition)                     \
    14. do {                                    \
    15.     if (condition)                             \
    16.         break;                            \
    17.     __wait_event(wq, condition);                    \
    18. } while (0)
    1. #define __wait_event(wq, condition)                     \
    2. do {                                    \
    3.     DEFINE_WAIT(__wait);                        \
    4.                                     \
    5.     for (;;) {                            \
    6.         prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);    \
    7.         if (condition)                        \
    8.             break;                        \
    9.         schedule();                        \
    10.     }                                \
    11.     finish_wait(&wq, &__wait);                    \
    12. } while (0)


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