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 来完成初始化.
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 来完成初始化.