async_schedule异步执行函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tiantao2012/article/details/88192476
在os中如果想推后执行一个函数可以调用async_schedule来进行
例如下面的例子
	async_cookie = async_schedule(acpi_battery_init_async, NULL);
我们看看async_schedule 是如何推后执行的?
这个函数第二个形参可以设置为null,这样就会用系统默认的domain  async_dfl_domain
async_cookie_t async_schedule(async_func_t func, void *data)
{
	return __async_schedule(func, data, &async_dfl_domain);
}
这里所以的domain 定义如下:
struct async_domain {
	struct list_head pending;
	unsigned registered:1;
};
可见所谓的domain就两个参数,一个表示要异步执行函数的列表,一个表示这个domain是否注册过
static async_cookie_t __async_schedule(async_func_t func, void *data, struct async_domain *domain)
{
	struct async_entry *entry;
	unsigned long flags;
	async_cookie_t newcookie;

	/* allow irq-off callers */
#申请一个async_entry的数据结构
	entry = kzalloc(sizeof(struct async_entry), GFP_ATOMIC);

	/*
	 * If we're out of memory or if there's too much work
	 * pending already, we execute synchronously.
	 */
#如果没有申请到空间或者domain中异步执行的函数已经达到最大值,则直接同步执行这个函数
	if (!entry || atomic_read(&entry_count) > MAX_WORK) {
		kfree(entry);
		spin_lock_irqsave(&async_lock, flags);
		newcookie = next_cookie++;
		spin_unlock_irqrestore(&async_lock, flags);

		/* low on memory.. run synchronously */
#同步执行这个函数
		func(data, newcookie);
		return newcookie;
	}
#申请两个链表
	INIT_LIST_HEAD(&entry->domain_list);
	INIT_LIST_HEAD(&entry->global_list);
#初始化一个work
	INIT_WORK(&entry->work, async_run_entry_fn);
	entry->func = func;
	entry->data = data;
	entry->domain = domain;

	spin_lock_irqsave(&async_lock, flags);

	/* allocate cookie and queue */
	newcookie = entry->cookie = next_cookie++;
#将新申请的entry分别挂到domain->pending 和 async_global_pending 这两个全局链表上
	list_add_tail(&entry->domain_list, &domain->pending);
	if (domain->registered)
		list_add_tail(&entry->global_list, &async_global_pending);

	atomic_inc(&entry_count);
	spin_unlock_irqrestore(&async_lock, flags);

	/* mark that this task has queued an async job, used by module init */
	current->flags |= PF_USED_ASYNC;

	/* schedule for execution */
#把前面已经初始化话的worl 放到system_unbound_wq 中执行
	queue_work(system_unbound_wq, &entry->work);

	return newcookie;
}
重点看看work的执行函数async_run_entry_fn

static void async_run_entry_fn(struct work_struct *work)
{
	struct async_entry *entry =
		container_of(work, struct async_entry, work);
	unsigned long flags;
	ktime_t uninitialized_var(calltime), delta, rettime;

	/* 1) run (and print duration) */
	if (initcall_debug && system_state < SYSTEM_RUNNING) {
		pr_debug("calling  %lli_%pF @ %i\n",
			(long long)entry->cookie,
			entry->func, task_pid_nr(current));
		calltime = ktime_get();
	}
#直接执行用户要执行的func函数
	entry->func(entry->data, entry->cookie);
	if (initcall_debug && system_state < SYSTEM_RUNNING) {
		rettime = ktime_get();
		delta = ktime_sub(rettime, calltime);
		pr_debug("initcall %lli_%pF returned 0 after %lld usecs\n",
			(long long)entry->cookie,
			entry->func,
			(long long)ktime_to_ns(delta) >> 10);
	}
#从全局链表中删除
	/* 2) remove self from the pending queues */
	spin_lock_irqsave(&async_lock, flags);
	list_del_init(&entry->domain_list);
	list_del_init(&entry->global_list);

	/* 3) free the entry */
	kfree(entry);
	atomic_dec(&entry_count);

	spin_unlock_irqrestore(&async_lock, flags);

	/* 4) wake up any waiters */
	wake_up(&async_done);
}
从这里可以看到所谓的异步执行就是将要执行的函数放到一个工作队列中,然后推后执行

猜你喜欢

转载自blog.csdn.net/tiantao2012/article/details/88192476
今日推荐