(Win XP, VC 7.1, Intel Core 2, CryptoPP 5.5.2 statically linked)
In my code I effectively ends up calling NonblockingRng::GenerateBlock
() in several (at least 3) threads at the same time.
This causes race condition inside this call:
Singleton<MicrosoftCryptoProvider>().Ref()
template <class T, class F, int instance>
const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT)
const
{
static simple_ptr<T> s_pObject;
static char s_objectState = 0; // [*]
retry:
switch (s_objectState)
{
case 0:
s_objectState = 1; // [1]
try
{
s_pObject.m_p = m_objectFactory();
}
catch(...)
{
s_objectState = 0;
throw;
}
s_objectState = 2; // [2]
break;
case 1:
goto retry; // [3]
default:
break;
}
return *s_pObject.m_p;
}
As I understand the code, when thread 2 calls Ref() while thread 1
already passed line [1] , but not yet got to line [2], second thread
will enter tight goto loop that would be broken by first thread
executing line [2] when it gets to it.
Well, for me out of my 3+ threads that potentially enter the function
together, one never leaves the loop. Happens only in release build,
which in this case means optimizer decides to save on reading
s_objectState every time.
Looking at disassembly it seems that is exactly what happens. Here is
all of the five instructions it loops over. At the biginning of the
loop EAX is 0 and ECX is 1.
00440310 mov eax,ecx
00440312 sub eax,0
00440315 je retry+0Ch (44031Ch)
00440317 dec eax
00440318 je retry (440310h)
Changing line [*] to have volatile keyword in it seems to fix that.
static volatile char s_objectState = 0; // [*]
Disassembly now looks like that:
004402E4 movsx eax,byte ptr [s_objectState (4D6144h)]
004402EB sub eax,0
004402EE je retry+11h (4402F5h)
004402F0 dec eax
004402F1 je retry (4402E4h)
(My first honest optimizer related bug I found. And proper use of
volatile. Woot! :)).
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the "Crypto++ Users"
Google Group.
To unsubscribe, send an email to [email protected].
More information about Crypto++ and this group is available at
http://www.cryptopp.com.
-~----------~----~----~----~------~----~------~--~---