1 .. include:: ../disclaimer-zh_CN.rst 2 3 :Original: Documentation/scheduler/completion. 4 5 :翻译: 6 7 司延腾 Yanteng Si <siyanteng@loongson.cn> 8 9 :校译: 10 11 唐艺舟 Tang Yizhou <tangyeechou@gmail.com> 12 13 ======================================= 14 完成 - "等待完成" 屏障应用程序接 15 ======================================= 16 17 简介: 18 ----- 19 20 如果你有一个或多个线程必须等待 21 个问题提供一个无竞争的解决方案 22 用的案例类似 23 24 完成是一种代码同步机制,它比任 25 或一些古怪的msleep(1)循环来允许其 26 调用和completion()来代替。 27 28 使用“完成”的好处是,它们有一 29 而且它们也会生成更高效的代码, 30 待和信号都高效的使用了低层调度 31 32 完成是建立在Linux调度器的等待队 33 事件被简化为 ``struct completion`` 中 34 35 由于完成与调度有关,代码可以在k 36 37 38 用法: 39 ----- 40 41 使用完成需要三个主要部分: 42 43 - 'struct completion' 同步对象的初始 44 - 通过调用wait_for_completion()的一个 45 - 通过调用complete()或complete_all()实 46 47 也有一些辅助函数用于检查完成的 48 按任何时间顺序出现。也就是说, 49 完成标记为 "done",这是完全正常的 50 51 要使用完成API,你需要#include <linux/ 52 ``struct completion`` 类型的变量,它只 53 54 struct completion { 55 unsigned int done; 56 wait_queue_head_t wait; 57 }; 58 59 结构体提供了->wait等待队列来放置 60 是否完成。 61 62 完成的命名应当与正在被同步的事 63 64 wait_for_completion(&early_console_add 65 66 complete(&early_console_added); 67 68 好的、直观的命名(一如既往地) 69 是没有帮助的,除非其目的是超级 70 71 72 初始化完成: 73 ----------- 74 75 动态分配的完成对象最好被嵌入到 76 止与异步complete()调用发生竞争。 77 78 在使用wait_for_completion()的_timeout()或 79 时应特别小心,因为必须保证在所 80 之前不会发生内存解除分配,即使 81 82 动态分配的完成对象的初始化是通 83 84 init_completion(&dynamic_object->done) 85 86 在这个调用中,我们初始化 waitqueue 87 “not done”。 88 89 重新初始化函数reinit_completion(),只 90 不触及等待队列。这个函数的调用 91 调用在并行进行。 92 93 在同一个完成对象上调用init_completi 94 化为一个空队列,已排队的任务可 95 要注意其他竞争。 96 97 对于静态声明和初始化,可以使用 98 99 对于文件范围内的静态(或全局) 100 101 static DECLARE_COMPLETION(setup_done); 102 DECLARE_COMPLETION(setup_done); 103 104 注意,在这种情况下,完成在启动 105 init_completion()。 106 107 当完成被声明为一个函数中的局部 108 DECLARE_COMPLETION_ONSTACK()来初始化,这 109 名它有限的使用范围是有意为之并 110 111 DECLARE_COMPLETION_ONSTACK(setup_done) 112 113 请注意,当使用完成对象作为局部 114 活动(如等待的线程)停止并且完 115 116 再次强调这一点:特别是在使用一 117 (_timeout(), _killable()和_interruptible() 118 能仍在被其他线程使用 - 从wait_on_co 119 果complete()在其它某线程中完成调用 120 些类型的竞争。 121 122 如果不确定的话,使用动态分配的 123 超过使用完成对象的任何辅助线程 124 不会在一个被释放的对象中调用。 125 126 在堆栈上单纯地调用DECLARE_COMPLETION( 127 128 等待完成: 129 --------- 130 131 对于一个线程来说,要等待一些并 132 wait_for_completion():: 133 134 void wait_for_completion(struct comple 135 136 一个典型的使用场景是:: 137 138 CPU#1 139 140 struct completion setup_done; 141 142 init_completion(&setup_done); 143 initialize_work(...,&setup_done,...); 144 145 /* run non-dependent code */ 146 147 wait_for_completion(&setup_done); 148 149 这并不意味着调用wait_for_completion() 150 用complete()发生在调用wait_for_completio 151 所有的依赖都得到了满足;如果没 152 153 注意,wait_for_completion()是在调用spin 154 只有当你知道中断被启用时才能安 155 测的错误的中断启用。 156 157 默认行为是不带超时的等待,并将 158 及其变体只有在进程上下文中才是 159 被禁用或抢占被禁用的情况下是不 160 try_wait_for_completion()。 161 162 由于wait_for_completion()的所有变体都 163 待的活动的性质,所以在大多数情 164 165 166 wait_for_completion*()可用的变体: 167 --------------------------------- 168 169 下面的变体都会返回状态,在大多 170 况下,你可能要做一个说明(例如, 171 172 一个常见的问题是不准确的返回类 173 174 检查返回值的具体含义也可能被发 175 176 if (!wait_for_completion_interruptible 177 178 ...会在成功完成和中断的情况下执 179 180 int wait_for_completion_interruptible( 181 182 这个函数在任务等待时标记为TASK_IN 183 -ERESTARTSYS;否则为0:: 184 185 unsigned long wait_for_completion_time 186 187 该任务被标记为TASK_UNINTERRUPTIBLE, 188 返回0,否则返回剩余的时间(但至 189 190 超时最好用msecs_to_jiffies()或usecs_to_j 191 HZ的影响。 192 193 如果返回的超时值被故意忽略,那 194 (例如,见drivers/mfd/wm8350-core.c wm835 195 196 long wait_for_completion_interruptible 197 198 这个函数传递一个以jiffies为单位的 199 信号,则返回-ERESTARTSYS;否则,如 200 (jiffies)。 201 202 更多的变体包括_killable,它使用TASK 203 回-ERESTARTSYS,如果完成了,则返回0 204 205 long wait_for_completion_killable(stru 206 long wait_for_completion_killable_time 207 208 wait_for_completion_io()的_io变体的行为 209 这对任务在调度/IO统计中的计算方 210 211 void wait_for_completion_io(struct com 212 unsigned long wait_for_completion_io_t 213 214 215 对完成发信号: 216 ------------- 217 218 一个线程想要发出信号通知继续的 219 号表明它可以继续:: 220 221 void complete(struct completion *done) 222 223 ... or calls complete_all() to signal all curr 224 225 void complete_all(struct completion *d 226 227 即使在线程开始等待之前就发出了 228 “consuming”(递减)“struct completio 229 与它们被排队的顺序相同(FIFO顺序 230 231 如果多次调用complete(),那么这将允 232 简单地增加已完成的字段。但多次 233 complete_all()都可以在IRQ/atomic上下文 234 235 在任何时候,只能有一个线程在一 236 complete_all() - 通过等待队列自旋锁 237 complete_all() 的并发调用都可能是一 238 239 从IRQ上下文中发出完成信号 是可行 240 spin_lock_irqsave()/spin_unlock_irqrestore() 241 242 243 try_wait_for_completion()/completion_done(): 244 -------------------------------------------- 245 246 try_wait_for_completion()函数不会将线程 247 程时返回false,否则会消耗一个已 248 249 bool try_wait_for_completion(struct co 250 251 最后,为了在不以任何方式改变完 252 如果没有发布的完成尚未被等待者 253 254 bool completion_done(struct completion 255 256 try_wait_for_completion()和completion_done()
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.