wait queue 6

wait queue 还可以用于等待某个atomic变量为0,例如下下例中等待cookie->n_active == 0
wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t, TASK_UNINTERRUPTIBLE);
其中fscache_wait_atomic_t 仅仅就是通过schedule() 让出cpu.
int fscache_wait_atomic_t(atomic_t *p)
{
    schedule();
    return 0;
}
和wait_on_atomic_t 对应的wakeup函数如下:
void wake_up_atomic_t(atomic_t *p)
{
    __wake_up_bit(atomic_t_waitqueue(p), p, WAIT_ATOMIC_T_BIT_NR);
}
wake_up_atomic_t 就是简单的调用__wake_up_bit而已。
我们重点看看wait_on_atomic_t的实现
static inline
int wait_on_atomic_t(atomic_t *val, int (*action)(atomic_t *), unsigned mode)
{
    might_sleep();
    if (atomic_read(val) == 0)
        return 0;
    return out_of_line_wait_on_atomic_t(val, action, mode);
}
首先判断val 是否为0,如果已经是0了,就不用等待了,否则调用out_of_line_wait_on_atomic_t
__sched int out_of_line_wait_on_atomic_t(atomic_t *p, int (*action)(atomic_t *),
                     unsigned mode)
{
    wait_queue_head_t *wq = atomic_t_waitqueue(p);
    DEFINE_WAIT_ATOMIC_T(wait, p);

    return __wait_on_atomic_t(wq, &wait, action, mode);
}
out_of_line_wait_on_atomic_t 首先得到wait_queue_head_t
static inline wait_queue_head_t *atomic_t_waitqueue(atomic_t *p)
{
    if (BITS_PER_LONG == 64) {
        unsigned long q = (unsigned long)p;
        return bit_waitqueue((void *)(q & ~1), q & 1);
    }
    return bit_waitqueue(p, 0);
}
这个函数通过bit_waitqueue得到wait_queue_head_t。64 和 32 bit的参数会有点区别.
out_of_line_wait_on_atomic_t 通过 DEFINE_WAIT_ATOMIC_T得到 wait queue
#define DEFINE_WAIT_ATOMIC_T(name, p)                    \
    struct wait_bit_queue name = {                    \
        .key = __WAIT_ATOMIC_T_KEY_INITIALIZER(p),        \
        .wait    = {                        \
            .private    = current,            \
            .func        = wake_atomic_t_function,    \
            .task_list    =                \
                LIST_HEAD_INIT((name).wait.task_list),    \
        },                            \
    }
这个和之前非atomic的却别是func不一样wake_atomic_t_function
wake_atomic_t_function 和之前的autoremove_wake_function 相比也就多了key.flags 和 key.bit_nr 的判断.看起来是wakeup的时候
key.flags 和 key.bit_nr和之前注册到wait_queue_head_t 里面的可能会变化.
static int wake_atomic_t_function(wait_queue_t *wait, unsigned mode, int sync,
                  void *arg)
{
    struct wait_bit_key *key = arg;
    struct wait_bit_queue *wait_bit
        = container_of(wait, struct wait_bit_queue, wait);
    atomic_t *val = key->flags;

    if (wait_bit->key.flags != key->flags ||
        wait_bit->key.bit_nr != key->bit_nr ||
        atomic_read(val) != 0)
        return 0;
    return autoremove_wake_function(wait, mode, sync, key);
}
out_of_line_wait_on_atomic_t 最后调用__wait_on_atomic_t
static __sched
int __wait_on_atomic_t(wait_queue_head_t *wq, struct wait_bit_queue *q,
               int (*action)(atomic_t *), unsigned mode)
{
    atomic_t *val;
    int ret = 0;

    do {
        prepare_to_wait(wq, &q->wait, mode);
        val = q->key.flags;
        if (atomic_read(val) == 0)
            break;
        ret = (*action)(val);
    } while (!ret && atomic_read(val) != 0);
    finish_wait(wq, &q->wait);
    return ret;
}
这个和之前的___wait_event 相比也就是多了对atomic_read(val) 值的判断.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值