wait queue 7

来源:互联网 发布:淘宝首页css代码 编辑:程序博客网 时间:2024/06/06 02:16
wait_on_bit_lock_action 这个函数会检测一个bit是否为0,如果是0后立刻设为1.
用法如下:
首先wait    
rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
                     TASK_KILLABLE);
与之对应的wakeup函数是
#define wake_up_locked(x)        __wake_up_locked((x), TASK_NORMAL, 1)

static inline int
wait_on_bit_lock_action(unsigned long *word, int bit, wait_bit_action_f *action,
            unsigned mode)
{
    might_sleep();
    if (!test_and_set_bit(bit, word))
        return 0;
    return out_of_line_wait_on_bit_lock(word, bit, action, mode);
}

wait_on_bit_lock_action 首先调用test_and_set_bit 会返回nr这个bit之前的值,然后或上1.
static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
{
    unsigned long mask = BIT_MASK(nr);
    unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
    unsigned long old;
    unsigned long flags;

    _atomic_spin_lock_irqsave(p, flags);
    old = *p;
    *p = old | mask;
    _atomic_spin_unlock_irqrestore(p, flags);

    return (old & mask) != 0;
}
因此wait_on_bit_lock_action 调用test_and_set_bit 判断这个bit为0后就直接返回了,并设置这个bit为1
否则调用out_of_line_wait_on_bit_lock
int __sched out_of_line_wait_on_bit_lock(void *word, int bit,
                     wait_bit_action_f *action, unsigned mode)
{
    wait_queue_head_t *wq = bit_waitqueue(word, bit);
    DEFINE_WAIT_BIT(wait, word, bit);

    return __wait_on_bit_lock(wq, &wait, action, mode);
}
out_of_line_wait_on_bit_lock 会申请wait_queue_head_t,定义waitqueue,这和之前的类似,继续看__wait_on_bit_lock
int __sched
__wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q,
            wait_bit_action_f *action, unsigned mode)
{
    int ret = 0;

    for (;;) {
        prepare_to_wait_exclusive(wq, &q->wait, mode);
        if (test_bit(q->key.bit_nr, q->key.flags)) {
            ret = action(&q->key, mode);
            /*
             * See the comment in prepare_to_wait_event().
             * finish_wait() does not necessarily takes wq->lock,
             * but test_and_set_bit() implies mb() which pairs with
             * smp_mb__after_atomic() before wake_up_page().
             */
            if (ret)
                finish_wait(wq, &q->wait);
        }
        if (!test_and_set_bit(q->key.bit_nr, q->key.flags)) {
            if (!ret)
                finish_wait(wq, &q->wait);
            return 0;
        } else if (ret) {
            return ret;
        }
    }
}
__wait_on_bit_lock 会判断nr是否为1,然后根据action来判断是否要继续等待.一般action都是返回0,只有在出差的情况下返回非0
cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
{
    freezable_schedule_unsafe();
    if (signal_pending_state(mode, current))
        return -ERESTARTSYS;
    return 0;
}

后面的逻辑就和wait_on_bit_lock_action 函数是类似的.
0 0