completion 1

completion也是继续wait queue实现的。主要是一方调用下面的接口来等到某个操作完成
extern void wait_for_completion(struct completion *);
extern void wait_for_completion_io(struct completion *);
extern int wait_for_completion_interruptible(struct completion *x);
extern int wait_for_completion_killable(struct completion *x);
extern unsigned long wait_for_completion_timeout(struct completion *x,
                           unsigned long timeout);
extern unsigned long wait_for_completion_io_timeout(struct completion *x,
                            unsigned long timeout);
extern long wait_for_completion_interruptible_timeout(
    struct completion *x, unsigned long timeout);
extern long wait_for_completion_killable_timeout(
    struct completion *x, unsigned long timeout);
另外一方是调用下面的即可告诉正在等待的对象,操作已经完成了。
extern bool completion_done(struct completion *x);
extern void complete(struct completion *);
extern void complete_all(struct completion *);

在kernel中用completion 来表示一个完成量.
struct completion {
    unsigned int done;
    wait_queue_head_t wait;
};
在使用completion之前需要初始化。可以调用下面两种方法初始化
#define DECLARE_COMPLETION(work) \
    struct completion work = COMPLETION_INITIALIZER(work)


static inline void init_completion(struct completion *x)
{
    x->done = 0;
    init_waitqueue_head(&x->wait);
}

这两种的区别是第二种需要在调用init_completion之前先定义好completion,也就是为completion申请空间.
还有一种定义如下:
#ifdef CONFIG_LOCKDEP
# define DECLARE_COMPLETION_ONSTACK(work) \
    struct completion work = COMPLETION_INITIALIZER_ONSTACK(work)
#else
# define DECLARE_COMPLETION_ONSTACK(work) DECLARE_COMPLETION(work)
#endif
即在stack上建立completion。但是如上面定义所以如果没有定义CONFIG_LOCKDEP的话,DECLARE_COMPLETION_ONSTACK 就和DECLARE_COMPLETION 是一样的。因为如果在函数中调用DECLARE_COMPLETION 本来就是在stack上建立的,而COMPLETION_INITIALIZER_ONSTACK 只是为了防止死锁,我们一般没有定义.
而如果定义了CONFIG_LOCKDEP,DECLARE_COMPLETION_ONSTACK 感觉也是先定义一个completion,然后调用init_completion初始化,暂时没有看出这两个有什么区别.
#define init_waitqueue_head(q)                \
    do {                        \
        static struct lock_class_key __key;    \
                            \
        __init_waitqueue_head((q), #q, &__key);    \
    } while (0)
直接调用__init_waitqueue_head来初始化,这里会申请一个lock_class_key对象,也是用于死锁debug的.
void __init_waitqueue_head(wait_queue_head_t *q, const char *name, struct lock_class_key *key)
{
    spin_lock_init(&q->lock);
    lockdep_set_class_and_name(&q->lock, key, name);
    INIT_LIST_HEAD(&q->task_list);
}
最终调用INIT_LIST_HEAD 来初始化completion的wait_queue_head_t。

#define COMPLETION_INITIALIZER(work) \
    { 0, __WAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
注意这里传递的是(work).wait)。
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) {                \
    .lock        = __SPIN_LOCK_UNLOCKED(name.lock),        \
    .task_list    = { &(name).task_list, &(name).task_list } }
这里让task_list的前后指针都指向(name).task_list 来完成初始化.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值