git: kernel - Attempt to fix two out-of-order read MP races
dillon at crater.dragonflybsd.org
Sun Sep 19 08:52:57 PDT 2010
Author: Matthew Dillon <dillon at apollo.backplane.com>
Date: Sun Sep 19 08:36:16 2010 -0700
kernel - Attempt to fix two out-of-order read MP races
* Example of issue during buildworld -j 8 loop tests, cc1 occassionally
fails after upwards of a trillion instructions worth of testing:
Sep 18 07:11:58 test29 kernel: seg-fault accessing address 0
rip=0x584ef7 pid=30229 p_comm=cc1
In this example gdb'ing cc1 and examining the code revealed an impossible
crash case where off(%ebx) was deterministically accessed a few
instructions before, then accessed again and somehow %ebx had become zero.
Unfortunately I could find no smoking gun, but my conjecture is that it
is a MP race which can occur when the thread migrates between cpus and/or
a mis-handled IPI.
* In the LWKT messaging code move the cpu_mfence() call in the sequence,
from rindex->read_args->MFENCE->call to rindex->MFENCE->read_args->call.
* In the LWKT thread acquisition code (for thread migration between cpus),
add a cpu_mfence() call after the td_flags check indicates success,
instead of inside the loop where we are waiting for the flags check to
* In both cases the issue seems to be out-of-order reads and/or speculative
reads. Even though MP writes are well ordered on Intel/AMD systems reads
are not. In the case of the IPIQ FIFO the data related to the arguments
can be ordered ahead of the read of the FIFO rindex and thus wind up being
stale relative to the other CPU writing the entry. Moving the mfence
ensures that the args stored in the FIFO are not accessed until after
the rindex is read.
For the thread aquisition code access to and manipulation of the thread
td_allq might be based on stale out-of-order reads prior to the
determination that the thread completed its move.
This can be a problem because several mechanisms in DragonFly are able
to operate without even having to use locked bus cycle. The IPIQ, thread
migration, and kern/sys_pipe.c being the best examples, so the natural
barrier provided by the locked bus-cycle instruction is not necessarily
Summary of changes:
sys/kern/lwkt_ipiq.c | 21 +++++++++++++--------
sys/kern/lwkt_thread.c | 4 +++-
2 files changed, 16 insertions(+), 9 deletions(-)
DragonFly BSD source repository
More information about the Commits