(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.
-~----------~----~----~----~------~----~------~--~---

Reply via email to