内核同步机制之完成量

1. 基础知识

    a. 完成量结构

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

    b. 定义完成量

    struct completion my_completion;

    c. 初始化完成量

	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);         // 不定义CONFIG_LOCKDEP(死锁检测)时,什么也不做
		INIT_LIST_HEAD(&q->task_list);                           // 初始化 task_let 链表头
	}
	
	static inline void reinit_completion(struct completion *x)        // 重新初始化一个完成量使之可以再利用
	{
		x->done = 0;
	}

    d. 等待完成量

	/**
	 * wait_for_completion: - waits for completion of a task
	 * @x:  holds the state of this particular completion
	 *
	 * This waits to be signaled for completion of a specific task. It is NOT
	 * interruptible and there is no timeout.
	 *
	 * See also similar routines (i.e. wait_for_completion_timeout()) with timeout
	 * and interrupt capability. Also see complete().
	 */
	void __sched wait_for_completion(struct completion *x)                        // 无超时时间
	{
		wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
	}
	EXPORT_SYMBOL(wait_for_completion);
	
	#define	MAX_SCHEDULE_TIMEOUT	LONG_MAX
	#define LONG_MAX	((long)(~0UL>>1))
	#define TASK_UNINTERRUPTIBLE	2                // 任务标志位,表示不可中断
	
	/**
	 * wait_for_completion_timeout: - waits for completion of a task (w/timeout)
	 * @x:  holds the state of this particular completion
	 * @timeout:  timeout value in jiffies
	 *
	 * This waits for either a completion of a specific task to be signaled or for a
	 * specified timeout to expire. The timeout is in jiffies. It is not
	 * interruptible.
	 *
	 * Return: 0 if timed out, and positive (at least 1, or number of jiffies left
	 * till timeout) if completed.
	 */
	unsigned long __sched
	wait_for_completion_timeout(struct completion *x, unsigned long timeout)                // 有超时时间
	{
		return wait_for_common(x, timeout, TASK_UNINTERRUPTIBLE);
	}
	EXPORT_SYMBOL(wait_for_completion_timeout);

    e. 唤醒完成量

	void complete(struct completion *x)                        // 只唤醒一个等待的执行单元
	{
		unsigned long flags;
	
		spin_lock_irqsave(&x->wait.lock, flags);
		x->done++;
		__wake_up_locked(&x->wait, TASK_NORMAL, 1);
		spin_unlock_irqrestore(&x->wait.lock, flags);
	}
	EXPORT_SYMBOL(complete);
	
	void complete_all(struct completion *x)                     // 释放所有等待同一完成量的执行单元
	{
		unsigned long flags;
	
		spin_lock_irqsave(&x->wait.lock, flags);
		x->done += UINT_MAX/2;
		__wake_up_locked(&x->wait, TASK_NORMAL, 0);
		spin_unlock_irqrestore(&x->wait.lock, flags);
	}
	EXPORT_SYMBOL(complete_all);

    f. 完成量同于同步的流程:

	进程 P1         进程 P2
	代码区C1;       wait_for_completion(&done);
	complete(&done);
			代码区C2; 

2. 相关代码举例

代码位置:drivers/scsi/libsas/sas_expander.c
函数smp_execute_task()中 struct sas_task *task 先建立一个sas_task 并初始化,然后调用wait_for_completion函数

pr_debug("file:%s func:%s line:%d dr->attached_sas_addr = 0x%016llx retry = %d \n",__FILE__, __func__, __LINE__,SAS_ADDR(dr->attached_sas_addr),retry);
wait_for_completion(&task->slow_task->completion);
pr_debug("file:%s func:%s line:%d dr->attached_sas_addr = 0x%016llx retry = %d \n",__FILE__, __func__, __LINE__,SAS_ADDR(dr->attached_sas_addr),retry);

而该完成量在函数 smp_task_done() 中被唤醒
static void smp_task_done(struct sas_task *task)
{
	pr_debug("file:%s func:%s line:%d \n",__FILE__, __func__, __LINE__);
	if (!del_timer(&task->slow_task->timer))
		return;
	complete(&task->slow_task->completion);
}

而该函数由中断处理函数mvs_interrupt()中调用,调用过程:
mvs_interrupt->mvs_94xx_isr()->mvs_int_full()->mvs_int_rx()->mvs_slot_complete()->smp_task_done()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值