我有一个问题,关于在具有先发制人的 linux 3.0 内核的 Android 嵌入式平台(基于 Exynos5dual)上 wait_event 和 wake_up 的奇怪行为。在具有非抢占式内核(任何版本)的普通 SMP 笔记本电脑上不会发生这种情况
我们有一个带有经典睡眠/唤醒场景的 linux 设备驱动程序,这就是发生的情况:
T0: taskA:
if(!flag)
wait_event_interruptible_timeout(wq, flag==true, timeout=0.5sec)
T1: (after a few msec) taskB:
atomic set flag
wake_up_interruptible()
T2: (after timeout msec) taskA:
wait_event_interruptible_timeout expires (ret 0) instead of waking up at T1
标志的所有读写都是原子的,并且已经使用了从 atomic bitops(内核设置/测试位)到 volatile atomic_t,再到使用 atomic_t vars 对每个读/写使用内存屏障(根据this)
如果 TaskA 实际上开始等待(wait_event_* 内核函数首先检查条件,因此可能并非总是如此),那么它会等待完全超时,而不是在标志更改值并调用 wake_up() 时被 taskB 唤醒。
我们怀疑这两个任务发生在不同的内核上。Core1 在 wait_event_..() 之后进入深度睡眠,并且无法被 Core2 上发生的 wake_up_interruptible() 唤醒。
有谁知道这是真的,还是其他原因?
注意:如果我们保存 sleeper 的任务结构 ptr,然后在(除此之外)wake_up_interruptible() 之前执行 wake_up_process (saved_ptr),问题似乎就消失了。我们发现这不是最优的,想知道是否有更好的方法。