Documentation/translations/zh_CN/scheduler/completion.rst

Source file repositories/reference/linux-study-clean/Documentation/translations/zh_CN/scheduler/completion.rst

File Facts

System
Linux kernel
Corpus path
Documentation/translations/zh_CN/scheduler/completion.rst
Extension
.rst
Size
11867 bytes
Lines
257
Domain
Support Tooling And Documentation
Bucket
Documentation
Inferred role
Support Tooling And Documentation: documentation
Status
atlas-only

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

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

结构体提供了->wait等待队列来放置任务进行等待(如果有的话),以及->done完成标志来表明它
是否完成。

完成的命名应当与正在被同步的事件名一致。一个好的例子是::

	wait_for_completion(&early_console_added);

	complete(&early_console_added);

好的、直观的命名(一如既往地)有助于代码的可读性。将一个完成命名为 ``complete``
是没有帮助的,除非其目的是超级明显的...


初始化完成:
-----------

动态分配的完成对象最好被嵌入到数据结构中,以确保在函数/驱动的生命周期内存活,以防
止与异步complete()调用发生竞争。

在使用wait_for_completion()的_timeout()或_killable()/_interruptible()变体
时应特别小心,因为必须保证在所有相关活动(complete()或reinit_completion())发生
之前不会发生内存解除分配,即使这些等待函数由于超时或信号触发而过早返回。

动态分配的完成对象的初始化是通过调用init_completion()来完成的::

	init_completion(&dynamic_object->done);

在这个调用中,我们初始化 waitqueue 并将 ->done 设置为 0,即“not completed”或
“not done”。

重新初始化函数reinit_completion(),只是将->done字段重置为0(“not done”),而
不触及等待队列。这个函数的调用者必须确保没有任何令人讨厌的wait_for_completion()
调用在并行进行。

在同一个完成对象上调用init_completion()两次很可能是一个bug,因为它将队列重新初始
化为一个空队列,已排队的任务可能会“丢失”--在这种情况下使用reinit_completion(),但
要注意其他竞争。

对于静态声明和初始化,可以使用宏。

对于文件范围内的静态(或全局)声明,你可以使用 DECLARE_COMPLETION()::

	static DECLARE_COMPLETION(setup_done);
	DECLARE_COMPLETION(setup_done);

注意,在这种情况下,完成在启动时(或模块加载时)被初始化为“not done”,不需要调用
init_completion()。

当完成被声明为一个函数中的局部变量时,那么应该总是明确地使用
DECLARE_COMPLETION_ONSTACK()来初始化,这不仅仅是为了让lockdep正确运行,也是明确表
名它有限的使用范围是有意为之并被仔细考虑的::

	DECLARE_COMPLETION_ONSTACK(setup_done)

请注意,当使用完成对象作为局部变量时,你必须敏锐地意识到函数堆栈的短暂生命期:在所有
活动(如等待的线程)停止并且完成对象完全未被使用之前,函数不得返回到调用上下文。

再次强调这一点:特别是在使用一些具有更复杂结果的等待API变体时,比如超时或信号
(_timeout(), _killable()和_interruptible())变体,等待可能会提前完成,而对象可
能仍在被其他线程使用 - 从wait_on_completion*()调用者函数的返回会取消分配函数栈,如
果complete()在其它某线程中完成调用,会引起微小的数据损坏。简单的测试可能不会触发这
些类型的竞争。

如果不确定的话,使用动态分配的完成对象, 最好是嵌入到其它一些生命周期长的对象中,长到
超过使用完成对象的任何辅助线程的生命周期,或者有一个锁或其他同步机制来确保complete()

Annotation

Implementation Notes