数据结构如下:
struct completion { unsigned int done; //指示等待的事件是否完成。初始化时为0。 //如果为0,则表示等待的事件未完成。大于0表示等待的事件已经完成 wait_queue_head_t wait;//存放等待该事件完成的进程队列};1) init_completion(&completion) init_completion()会将done字段初始化为0,wait字段的自旋锁为未锁,等待队列为空。 这说明调用该完成量的进程必须等待某事件完成(即另外一进程必须先调用completiom()唤醒该完成量)。
static inline void init_completion(struct completion *x){ x->done = 0; init_waitqueue_head(&x->wait);}#define init_waitqueue_head(q) / do { / static struct lock_class_key __key; / / __init_waitqueue_head((q), #q, &__key); / } while (0)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);}2) DECLARE_COMPLETION(completion); 直接定义并初始化completion完成量,效果等同于以上定义方式
1) wait_for_completion()函数
void __sched wait_for_completion(struct completion *x){ wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);}static long __schedwait_for_common(struct completion *x, long timeout, int state){ return __wait_for_common(x, schedule_timeout, timeout, state);}static inline long __sched__wait_for_common(struct completion *x, long (*action)(long), long timeout, int state){ might_sleep(); spin_lock_irq(&x->wait.lock); timeout = do_wait_for_common(x, action, timeout, state); spin_unlock_irq(&x->wait.lock); return timeout;}static inline long __scheddo_wait_for_common(struct completion *x, long (*action)(long), long timeout, int state){ if (!x->done) { /*该函数相当于信号量中的down()操作。不过在操作中对使用其自身的自旋锁。如果done为0, 则说明等待的事件没有完成,则调用DECLARE_WAITQUEUE()定义等待队列wait并将当前进程 添加进等待队列wait。然后将wait添加进该完成量的等待队列的末尾,进入循环。 设置当前进程为不可中断状态(TASK_UNINTERRUPTIBLE),释放自旋锁并让当前进程进入睡眠状态。 一旦进程被调度唤醒据又获得自旋锁并查看等待的事件是否完成。如果完成(大于0), 则从完成量的等待队列中删除等待的进程,并自减*/ DECLARE_WAITQUEUE(wait, current); __add_wait_queue_tail_exclusive(&x->wait, &wait); do { if (signal_pending_state(state, current)) { timeout = -ERESTARTSYS; break; } __set_current_state(state); spin_unlock_irq(&x->wait.lock); timeout = action(timeout); spin_lock_irq(&x->wait.lock); } while (!x->done && timeout); __remove_wait_queue(&x->wait, &wait); if (!x->done) return timeout; } x->done--; return timeout ?: 1;}2) wait_for_completion_timeout() 也是等待完成量。与wait_for_completion()最大的区别是它等待超时的情况下返回。也就是说如果经过给定的时间该完成量还没有被唤醒,就直接返回。这样最大的好处是经过一定的时间该进程已经不需要等待某事件,那么就可以直接被唤醒继续执行。
3) wait_for_completion_interruptible() 这个函数的等待完成量的方式是可以被信号打断的。如果当前进程收到 如果收到TIF_SIGPENDING信号,则等待该完成量的进程会被从等待队列中删除,并返回ERESTARTSYS
4) wait_for_completion_interruptible_timeout() 可中断的并且可超时返回的等待完成量。
completion()函数 : 唤醒所有等待给完成量的进程
新闻热点
疑难解答