While playing Starcraft with the ddraw patch (this effectively uncovers
race condition problems, since then the game freezes and I get angry, but
since I can't play on anyway, I attach some gdbs)
I think I've uncovered one in QUEUE_WaitBits. In windows/queue.c, there's
this:
int QUEUE_WaitBits( WORD bits, DWORD timeout )
{
[1] MESSAGEQUEUE *queue
...
for (;;)
{
[2] if (queue->changeBits & bits)
{
/* One of the bits is set; we can return */
queue->wakeMask = 0;
QUEUE_Unlock( queue );
return 1;
}
if (queue->wakeBits & QS_SENDMESSAGE)
{
/* Process the sent message immediately */
queue->wakeMask = 0;
QUEUE_ReceiveMessage( queue );
continue; /* nested sm crux */
}
queue->wakeMask = bits | QS_SENDMESSAGE;
[3] if(queue->changeBits & bits)
{
continue;
}
...
OK, this code may look all fine and dandy, even for sendmessages. But what
happens when an optimizing C compiler like gcc gets run on it? Well, it
figures that the changeBits are tested at [2], so when it gets to [3], it
sees no change, and optimizes [3] out... so, instant race condition.
Obviously, we need to add a "volatile" here somewhere (no, this is not a
gcc bug), but perhaps someone that doesn't like unnecessary compiler
warnings can think of a better place to put this "volatile" than [1] ?
(Or Alexandre can fix it himself?)