Linux系统中,很多的异步通知,尤其是中断和任务之间作同步的时候,有一种固定的休眠模式流程,如下图所示:
一种等价的流程
细节图
再介绍一种睡眠模式,下图代表的模式也经常在流程中遇到:
对比上面的两类流程,他们有什么差异呢?我们分析一下:
差异点1:第一种add wait queue 入队操作没有包含在循环里,而第二种操作,prepare to wait在循环体内重复执行。
差异点2:第一种的唤醒操作是default_wake_function,而第二种的唤醒操作是.autoremove_wake_function,autoremove_wake_function是对default_wake_function的瘦封装,只不过多了一个链表删除操作:
其实问题2回答了问题1,既然autoremove_wake_function多了一个删除操作,会将被唤醒的进程从等待队列中删除,那么下次循环时就必须要重新再加入等待队列,循环执行。
为何prepare_to_wait和 schedule之间要加入唤醒条件检测?
其实这是一个barrier问题,如下的时许保证两点:
1.在检查点之前发生的事件,可以被有限检测到从而不必休眠。
2.在检查点之后发生的事件,通过task->state状态互锁,使schedule不会真正休眠,条件同样检测到。