完成量代码分析



结构体

D:\linux31026\include\linux\completion.h


struct completion {
	unsigned int done;		
	wait_queue_head_t wait;
};



done: 完成计数,0 表示未完成, 大于0表示等待的事件已经完成。
wait: 存放等待该事件完成的进程队列。


定义/初始化



init_completion

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





DECLARE_COMPLETION


#define COMPLETION_INITIALIZER(work) \
	{ 0, __WAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
	
#define DECLARE_COMPLETION(work) \
	struct completion work = COMPLETION_INITIALIZER(work)
	



INIT_COMPLETION

- reinitialize a completion structure

/* This macro should be used to reinitialize a completion structure so it can
 * be reused. This is especially important after complete_all() is used.
 */
#define INIT_COMPLETION(x)	((x).done = 0)




D:\linux31026\kernel\sched\core.c


API

/* 不超时,不可中断 */

wait_for_completion

	wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE); 


wait_for_completion_interruptible_timeout

/* 会超时,可中断 */
/*
返回值
	-ERESTARTSYS if interrupted
	0 if timed out,
	positive (at least 1, or number of jiffies left till timeout) if completed.
*/
wait_for_completion_interruptible_timeout
	wait_for_common(x, timeout, TASK_INTERRUPTIBLE);






代码分析

wait_for_common(struct completion *x, long timeout, int state)
	__wait_for_common(x, schedule_timeout, timeout, state);
		do_wait_for_common(x, action, timeout, state);
		




static inline long __sched
do_wait_for_common(struct completion *x,
		   long (*action)(long), long timeout, int state)
{
	/* done 初始化为0, 表示未完成 */
	if (!x->done) {
		/* 初始化一个wait_queue_t wait, 
		wait_queue_t->private = current
		wait_queue_t->func = default_wake_function
		wait_queue_t->task_list = { NULL, NULL }	
		*/
		DECLARE_WAITQUEUE(wait, current);


		/* 将这个wait加入到完成量的完成量等待队列wait_queue_head_t */	
		__add_wait_queue_tail_exclusive(&x->wait, &wait);
		do {
			/* 当前进程被interrupted,也就是收到信号SIGKILL,返回,返回值是-ERESTARTSYS */
			if (signal_pending_state(state, current)) {
				timeout = -ERESTARTSYS;
				break;
			}
			
			/* 设置当前进程状态,是否可以被interrupt,等待 */
			__set_current_state(state);
			
			/* 释放lock */
			spin_unlock_irq(&x->wait.lock);
			
			/* 调度,也就是调用schedule_timeout() --> schedule() */
			timeout = action(timeout);
			
			/* timeout超时,或者schedule() 返回,回到当前进程,释放lock*/
			spin_lock_irq(&x->wait.lock);
			
		/* 如果done > 0, 或者timeout超时,二者满足其一,则退出循环
		   如果二者都不满足,重新获得lock,重新调度。
		 */	
		} while (!x->done && timeout);
		
		/* 从完成量等待队列删除 */
		__remove_wait_queue(&x->wait, &wait);
		
		if (!x->done)
			return timeout;
	}
	x->done--;
	return timeout ?: 1;
}



complete
	x->done++;
	__wake_up_common(&x->wait, TASK_NORMAL, 1, 0, NULL);
		curr->func(curr, mode, wake_flags, key)
		curr->func == default_wake_function, see __WAITQUEUE_INITIALIZER 
			try_to_wake_up



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值