Asynchronous function calls for boot performance

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tiantao2012/article/details/84314341
Asynchronous function calls for boot performance
个人理解主要是通过函数异步调用还减少启动时间,即将没有依赖且没有严格串行
的程序可以异步执行来减少启动时间。
异步函数调用的具体实现在kernel/async.c中。我们举例说明async的用法.
这个例子是在drivers/acpi/battery.c中
static int __init acpi_battery_init(void)
{
	if (acpi_disabled)
		return -ENODEV;
#可见在入口函数中,通过async_schedule来让acpi_battery_init_async 异步调用以
#加快系统的启动时间,从这里可以知道acpi_battery_init_async和其他硬件没有依赖,且
#没有严格的串行关系.注意这里会返回一个static async_cookie_t async_cookie;在模块的注销函数
#中需要调用acpi_battery_init_async。

	async_cookie = async_schedule(acpi_battery_init_async, NULL);
	return 0;
}

static void __exit acpi_battery_exit(void)
{
#
	async_synchronize_cookie(async_cookie + 1);
	if (battery_driver_registered) {
		acpi_bus_unregister_driver(&acpi_battery_driver);
		battery_hook_exit();
	}
#ifdef CONFIG_ACPI_PROCFS_POWER
	if (acpi_battery_dir)
		acpi_unlock_battery_dir(acpi_battery_dir);
#endif
}
#定义模块的入口函数
module_init(acpi_battery_init);
module_exit(acpi_battery_exit);
所以async的用法就是这样。
下来我们看看acpi_battery_init_async的具体实现
async_cookie_t async_schedule(async_func_t func, void *data)
{
#默认的domain是async_dfl_domain
	return __async_schedule(func, data, &async_dfl_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 */
#注册一个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.
	 */
#异步执行的函数执行的个数有限制,不能超过MAX_WORK,这个限制应该和memory有关
	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);
#初始化一个workqueue,并设置回调函数为async_run_entry_fn
	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添加到全局列表中
	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;
#开始调度workqueue,这里可以看明白async的精髓,以本例为例,也就是你调用module_init后你的函数不一定立刻运行了
	/* schedule for execution */
	queue_work(system_unbound_wq, &entry->work);

	return newcookie;
}
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();
	}
#执行用户调用__async_schedule时传入的回调函数
	entry->func(entry->data, entry->cookie);
	}

猜你喜欢

转载自blog.csdn.net/tiantao2012/article/details/84314341