While stress testing runtime on Windows ARM64 to repro an issue, I have
hit an ordering issue in access to m_maxDynamicEntries and
m_pDynamicStaticsInfo in the Module::AllocateDynamicEntry.
In one of a few thousands of runs, I got a runtime crash when the
m_pDynamicStaticsInfo was NULL. I was able to repro this issue reliably
in the above mentioned number of runs. After the fix, it doesn't repro
anymore.
The newId was 1 at the time of the crash, the m_maxDynamicEntries was
around 128. So the crashing thread has got the id 1, then another thread
updated the m_maxDynamicEntries before the crashing thread executed the
`if (newId >= m_maxDynamicEntries)`, so the thread went right to the
`m_pDynamicStaticsInfo[newId].pEnclosingMT = pMT;`. The
m_pDynamicStaticInfo is written before the m_maxDynamicEntries, so it
was expected that it cannot be NULL, but the crashing thread has seen
the operations in an opposite order due to the CPU access reordering.
The fix is to add VolatileLoad for accessing the m_maxDynamicEntries and
VolatileStore to set it. That ensures that the writes will be visible in
the intended order.
DWORD newId = FastInterlockExchangeAdd((LONG*)&m_cDynamicEntries, 1);
- if (newId >= m_maxDynamicEntries)
+ if (newId >= VolatileLoad(&m_maxDynamicEntries))
{
CrstHolder ch(&m_Crst);
memcpy(pNewDynamicStaticsInfo, m_pDynamicStaticsInfo, sizeof(DynamicStaticsInfo) * m_maxDynamicEntries);
m_pDynamicStaticsInfo = pNewDynamicStaticsInfo;
- m_maxDynamicEntries = maxDynamicEntries;
+ VolatileStore(&m_maxDynamicEntries, maxDynamicEntries);
}
}