您的位置:首页 > 产品设计 > UI/UE

wait queue 6

2017-01-16 11:32 211 查看
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) 值的判断.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: