wait queue 3

来源:互联网 发布:龙泉刀剑章氏有淘宝吗 编辑:程序博客网 时间:2024/05/16 23:36
wait queue的wakeup 函数有一下:
#define wake_up(x)            __wake_up(x, TASK_NORMAL, 1, NULL)
#define wake_up_nr(x, nr)        __wake_up(x, TASK_NORMAL, nr, NULL)
#define wake_up_all(x)            __wake_up(x, TASK_NORMAL, 0, NULL)
#define wake_up_locked(x)        __wake_up_locked((x), TASK_NORMAL, 1)
#define wake_up_all_locked(x)        __wake_up_locked((x), TASK_NORMAL, 0)

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

我们以#define wake_up(x)            __wake_up(x, TASK_NORMAL, 1, NULL) 为例
void __wake_up(wait_queue_head_t *q, unsigned int mode,
            int nr_exclusive, void *key)
{
    unsigned long flags;

    spin_lock_irqsave(&q->lock, flags);
    __wake_up_common(q, mode, nr_exclusive, 0, key);
    spin_unlock_irqrestore(&q->lock, flags);
}
__wake_up 首先通过spin_lock 保护临界区,然后调用__wake_up_common(q, mode, nr_exclusive, 0, key);
static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
            int nr_exclusive, int wake_flags, void *key)
{
    wait_queue_t *curr, *next;

    list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
        unsigned flags = curr->flags;

        if (curr->func(curr, mode, wake_flags, key) &&
                (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
            break;
    }
}
__wake_up_common 会通过list_for_each_entry_safe 遍历wait_queue_head_t,依次调用curr->func。而这个curr->func 就是我们在用
DEFINE_WAIT 来定义wait queue时候的默认func,autoremove_wake_function。
可见如果调用了wake_up的话是会遍历整个wait_queue_head_t。
还有一种情况就是如果wait_queue_head_t中的当前执行的wait queue设置了WQ_FLAG_EXCLUSIVE,且nr_exclusive 为1,也就是执行第一个
WQ_FLAG_EXCLUSIVE 后就返回了。也就是否符合下面这个条件
        if (curr->func(curr, mode, wake_flags, key) &&
                (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
            break;
从prepare_to_wait_exclusive我们知道如果设置了WQ_FLAG_EXCLUSIVE,就会被放到wait_queue_head_t的最后。
prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state)
{
    unsigned long flags;

    wait->flags |= WQ_FLAG_EXCLUSIVE;
    spin_lock_irqsave(&q->lock, flags);
    if (list_empty(&wait->task_list))
        __add_wait_queue_tail(q, wait);
    set_current_state(state);
    spin_unlock_irqrestore(&q->lock, flags);
}
如果一个wait_queue_head_t 中通过是有几个wait queue的flags 都有WQ_FLAG_EXCLUSIVE,那么按照我们上面的分析,在执行第一个的时候就退出了,也也就是WQ_FLAG_EXCLUSIVE 这个flag的含义吧.

0 0