This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[win32] notifyAll also notifying following wait calls
- From: Marco Trudel <mtrudel at gmx dot ch>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: Sun, 04 Feb 2007 16:56:03 +0100
- Subject: [win32] notifyAll also notifying following wait calls
Hey list
win32-threads.cc has a thread race for notifyAll() and wait(). Test.java
should actually deadlock, but sometimes it doesn't because the second
wait increments blocked_count before the event is reset and thus will
also be called.
My proposed patch moves the reset of the event into notifyAll because
this way, the even is reset just after all waiting threads have been
notified instead of when the last waiting thread has started working
again. As I said, there might be a new thread which called wait() before
the last waiting thread would reset the event.
Was I more or less clear? I'd really appreciate if a couple of persons
could take a look at the problem and my proposed solution because it's
always a good thing to triple check concurrency problems...
thanks
Marco
public class Test
{
private static final Object mainLock = new Object();
public static void main(String[] args) throws Exception
{
new Thread()
{
public void run()
{
synchronized(mainLock)
{
try
{
System.out.println("wait 1 start");
mainLock.wait(); // might be notified
System.out.println("wait 1 done");
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}.start();
new Thread()
{
public void run()
{
synchronized(mainLock)
{
mainLock.notifyAll();
try
{
System.out.println("wait 2 start");
mainLock.wait(); // not allowed to be notified
System.out.println("wait 2 done! Not allowed!");
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}.start();
}
}
Index: win32-threads.cc
===================================================================
--- win32-threads.cc (revision 121541)
+++ win32-threads.cc (working copy)
@@ -177,14 +177,8 @@
EnterCriticalSection(&cv->count_mutex);
cv->blocked_count--;
- // If we were unblocked by the second event (the broadcast one)
- // and nobody is left, then reset the event.
- int last_waiter = (rval == (WAIT_OBJECT_0 + 1)) && (cv->blocked_count == 0);
LeaveCriticalSection(&cv->count_mutex);
- if (last_waiter)
- ResetEvent (cv->ev[1]);
-
// Call _Jv_MutexLock repeatedly until the mutex's refcount is the
// same as before we originally released it.
while (curcount < count)
@@ -248,7 +242,10 @@
LeaveCriticalSection (&cv->count_mutex);
if (somebody_is_blocked)
- SetEvent (cv->ev[1]);
+ {
+ SetEvent (cv->ev[1]); // notify all waiting threads
+ ResetEvent (cv->ev[1]); // reset the notification
+ }
return 0;
}