kernel - Fix SMP tsleep_interlock() vs wakeup() race
* Problem triggered by kern_mutex.c, probably only triggered by mutexes.
The mutex sets state non-atomically and calls wakeup() with no
intervening atomic op. wakeup() loads the cpumask to wakeup
non-atomically. This can cause the wakeup() code to miss an
interaction with the cpumask set by another cpu.
cpu A:
set state <-- sets state
wakeup() <-- loads cpu mask non-atomically
cpu B:
tsleep_interlock() <-- sets cpu mask atomically
if (checkstate failed) <-- checks state
tsleep()
* Fix the problem by add a lfence() in the wakeup() code prior to
loading the cpumask. Even though I'm fairly sure only the kern_mutex.c
code can causing this problem, putting the lfence in wakeup() is the
safest mechanic.