re PR java/9254 (java::lang::Object::wait(), threads-win32.cc returns wrong return...
authorRanjit Mathew <rmathew@hotmail.com>
Tue, 28 Jan 2003 22:23:36 +0000 (22:23 +0000)
committerTom Tromey <tromey@gcc.gnu.org>
Tue, 28 Jan 2003 22:23:36 +0000 (22:23 +0000)
2003-01-28  Ranjit Mathew  <rmathew@hotmail.com>

Fixes PR java/9254:
* include/win32-threads.h (_Jv_Mutex_t): Convert to a struct
additionally containing id of the owner thread as well as
the number of nested times the thread has acquired the mutex.
(_Jv_MutexInit): Initialise owner thread id and refcount to 0.
(_Jv_MutexDestroy): Reset owner thread id and refcount to 0.
(_Jv_MutexUnlock): Check if really the owner thread, reset
owner thread id to 0 before leaving, if leaving for the last
time.
(_Jv_MutexLock): Set owner thread id in the mutex and increment
refcount.
(_Jv_ThreadYield): Yield using a call to Sleep(0).
* win32-threads.cc (_Jv_CondWait): Check if really owner of
the passed mutex.
Pass handle of the broadcast event, instead of a pointer to it
in Win32 ResetEvent( ) call.
Remove incorrect return values.
(_Jv_CondDestroy): Close both event handles and delete
critical section.
(_Jv_CondNotify): Check if really the owner thread.
(_Jv_CondNotifyAll): Check if really the owner thread.
(_Jv_InitThreads): Change daemon_cond to a manual-reset event.
(really_start): Use SetEvent( ) to signal daemon_cond.
(_Jv_ThreadWait): Remove SignalObjectAndWait( ) and use
WaitForSingleObject( ) instead to wait for daemon_cond to be
signalled.

From-SVN: r62033

libjava/ChangeLog
libjava/include/win32-threads.h
libjava/win32-threads.cc

index 8952b0b193e7eb73bd3bd10c870ea21336d3f8aa..dbcd959957cfda5c544416ef559b8a795248f34a 100644 (file)
@@ -1,3 +1,32 @@
+2003-01-28  Ranjit Mathew  <rmathew@hotmail.com>
+
+       Fixes PR java/9254:
+       * include/win32-threads.h (_Jv_Mutex_t): Convert to a struct
+       additionally containing id of the owner thread as well as
+       the number of nested times the thread has acquired the mutex.
+       (_Jv_MutexInit): Initialise owner thread id and refcount to 0.
+       (_Jv_MutexDestroy): Reset owner thread id and refcount to 0.
+       (_Jv_MutexUnlock): Check if really the owner thread, reset
+       owner thread id to 0 before leaving, if leaving for the last
+       time.
+       (_Jv_MutexLock): Set owner thread id in the mutex and increment
+       refcount.
+       (_Jv_ThreadYield): Yield using a call to Sleep(0).
+       * win32-threads.cc (_Jv_CondWait): Check if really owner of
+       the passed mutex.
+       Pass handle of the broadcast event, instead of a pointer to it
+       in Win32 ResetEvent( ) call.
+       Remove incorrect return values.
+       (_Jv_CondDestroy): Close both event handles and delete
+       critical section.
+       (_Jv_CondNotify): Check if really the owner thread.
+       (_Jv_CondNotifyAll): Check if really the owner thread.
+       (_Jv_InitThreads): Change daemon_cond to a manual-reset event.
+       (really_start): Use SetEvent( ) to signal daemon_cond.
+       (_Jv_ThreadWait): Remove SignalObjectAndWait( ) and use
+       WaitForSingleObject( ) instead to wait for daemon_cond to be
+       signalled.
+
 2003-01-27  Ranjit Mathew  <rmathew@hotmail.com>
 
        * configure.in: Specifically define HAVE_BACKTRACE if building
index e8cf80598c2a914f20d529b9f801e3ace36fb25c..5e40ae24b87b4c252cddecfb68bced95173853f7 100644 (file)
@@ -1,7 +1,8 @@
 // -*- c++ -*-
 // win32-threads.h - Defines for using Win32 threads.
 
-/* Copyright (C) 1998, 1999, 2000  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software
+   Foundation
 
    This file is part of libgcj.
 
@@ -18,13 +19,32 @@ details.  */
 // Typedefs.
 //
 
-typedef struct _Jv_ConditionVariable_t {
+typedef struct
+{
+  // ev[0] (signal) is a Win32 auto-reset event for _Jv_CondNotify
+  // ev[1] (broadcast) is a Win32 manual-reset event for _Jv_CondNotifyAll
   HANDLE ev[2];
-  CRITICAL_SECTION count_mutex;
+
+  // Number of threads waiting on this condition variable
   int blocked_count;
-};
 
-typedef CRITICAL_SECTION _Jv_Mutex_t;
+  // Protects access to the blocked_count variable
+  CRITICAL_SECTION count_mutex;
+
+} _Jv_ConditionVariable_t;
+
+typedef struct
+{
+  // The thread-id of the owner thread if any, 0 otherwise
+  DWORD owner;
+
+  // Track nested mutex acquisitions by the same thread
+  int refcount;
+
+  // The actual Windows construct used to implement this mutex
+  CRITICAL_SECTION cs;
+
+} _Jv_Mutex_t;
 
 typedef struct
 {
@@ -60,25 +80,39 @@ int _Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *);
 
 inline void _Jv_MutexInit (_Jv_Mutex_t *mu)
 {
-  InitializeCriticalSection(mu);
+  mu->owner = 0UL;
+  mu->refcount = 0;
+  InitializeCriticalSection (&(mu->cs));
 }
 
 #define _Jv_HaveMutexDestroy
 inline void _Jv_MutexDestroy (_Jv_Mutex_t *mu)
 {
-  DeleteCriticalSection(mu);
+  mu->owner = 0UL;
+  mu->refcount = 0;
+  DeleteCriticalSection (&(mu->cs));
   mu = NULL;
 }
 
 inline int _Jv_MutexUnlock (_Jv_Mutex_t *mu)
 {
-  LeaveCriticalSection(mu);
-  return 0;
+  if (mu->owner == GetCurrentThreadId ( ))
+    {
+      mu->refcount--;
+      if (mu->refcount == 0)
+        mu->owner = 0UL;
+      LeaveCriticalSection (&(mu->cs));
+      return 0;
+    }
+  else
+    return 1;
 }
 
 inline int _Jv_MutexLock (_Jv_Mutex_t *mu)
 {
-  EnterCriticalSection(mu);
+  EnterCriticalSection (&(mu->cs));
+  mu->owner = GetCurrentThreadId ( );
+  mu->refcount++;
   return 0;
 }
 
@@ -104,9 +138,7 @@ inline _Jv_Thread_t *_Jv_ThreadCurrentData(void)
 
 inline void _Jv_ThreadYield (void)
 {
-  // FIXME: win98 freezes hard (OS hang) when we use this --
-  //        for now, we simply don't yield
-  // Sleep (0);
+  Sleep (0);
 }
 
 void _Jv_ThreadRegister (_Jv_Thread_t *data);
index d31c1919a1e222e37f110861c7917df7eddd3176..3a3999a8f2d394811e35186b10237ca9484c7237 100644 (file)
@@ -1,6 +1,7 @@
 // win32-threads.cc - interface between libjava and Win32 threads.
 
-/* Copyright (C) 1998, 1999  Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software
+   Foundation, Inc.
 
    This file is part of libgcj.
 
@@ -70,12 +71,14 @@ DWORD _Jv_ThreadDataKey;
 inline void
 ensure_condvar_initialized(_Jv_ConditionVariable_t *cv)
 {
-  if (cv->ev[0] == 0) {
-    cv->ev[0] = CreateEvent (NULL, 0, 0, NULL);
-    if (cv->ev[0] == 0) JvFail("CreateEvent() failed");
-    cv->ev[1] = CreateEvent (NULL, 1, 0, NULL);
-    if (cv->ev[1] == 0) JvFail("CreateEvent() failed");
-  }
+  if (cv->ev[0] == 0)
+    {
+      cv->ev[0] = CreateEvent (NULL, 0, 0, NULL);
+      if (cv->ev[0] == 0) JvFail("CreateEvent() failed");
+
+      cv->ev[1] = CreateEvent (NULL, 1, 0, NULL);
+      if (cv->ev[1] == 0) JvFail("CreateEvent() failed");
+    }
 }
 
 // Reimplementation of the general algorithm described at
@@ -85,11 +88,13 @@ ensure_condvar_initialized(_Jv_ConditionVariable_t *cv)
 int
 _Jv_CondWait(_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu, jlong millis, jint nanos)
 {
+  if (mu->owner != GetCurrentThreadId ( ))
+    return _JV_NOT_OWNER;
 
-  EnterCriticalSection(&cv->count_mutex);
-  ensure_condvar_initialized(cv);
+  EnterCriticalSection (&cv->count_mutex);
+  ensure_condvar_initialized (cv);
   cv->blocked_count++;
-  LeaveCriticalSection(&cv->count_mutex);
+  LeaveCriticalSection (&cv->count_mutex);
 
   DWORD time;
   if ((millis == 0) && (nanos > 0)) time = 1;
@@ -102,18 +107,17 @@ _Jv_CondWait(_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu, jlong millis, jint na
 
   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 signal.
-  int last_waiter = rval == WAIT_OBJECT_0 + 1 && cv->blocked_count == 0;
+  // 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]);
+  if (last_waiter)
+    ResetEvent (cv->ev[1]);
 
   _Jv_MutexLock (mu);
 
-  if (rval == WAIT_FAILED) return GetLastError();
-  else if (rval == WAIT_TIMEOUT) return ETIMEDOUT;
-  else return 0;
+  return 0;
 }
 
 void
@@ -121,39 +125,56 @@ _Jv_CondInit (_Jv_ConditionVariable_t *cv)
 {
   // we do lazy creation of Events since CreateEvent() is insanely expensive
   cv->ev[0] = 0;
-  InitializeCriticalSection(&cv->count_mutex);
+  InitializeCriticalSection (&cv->count_mutex);
   cv->blocked_count = 0;
 }
 
 void
 _Jv_CondDestroy (_Jv_ConditionVariable_t *cv)
 {
-  if (cv->ev[0] != 0) CloseHandle(cv->ev[0]);
-  cv = NULL;
+  if (cv->ev[0] != 0)
+    {
+      CloseHandle (cv->ev[0]);
+      CloseHandle (cv->ev[1]);
+
+      cv->ev[0] = 0;
+    }
+
+  DeleteCriticalSection (&cv->count_mutex);
 }
 
 int
-_Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *)
+_Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu)
 {
-  EnterCriticalSection(&cv->count_mutex);
-  ensure_condvar_initialized(cv);
+  if (mu->owner != GetCurrentThreadId ( ))
+    return _JV_NOT_OWNER;
+
+  EnterCriticalSection (&cv->count_mutex);
+  ensure_condvar_initialized (cv);
   int somebody_is_blocked = cv->blocked_count > 0;
-  LeaveCriticalSection(&cv->count_mutex);
+  LeaveCriticalSection (&cv->count_mutex);
+
+  if (somebody_is_blocked)
+    SetEvent (cv->ev[0]);
 
-  if (somebody_is_blocked) return SetEvent (cv->ev[0]) ? 0 : GetLastError();
-  else return 0;
+  return 0;
 }
 
 int
-_Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *)
+_Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu)
 {
-  EnterCriticalSection(&cv->count_mutex);
-  ensure_condvar_initialized(cv);
+  if (mu->owner != GetCurrentThreadId ( ))
+    return _JV_NOT_OWNER;
+
+  EnterCriticalSection (&cv->count_mutex);
+  ensure_condvar_initialized (cv);
   int somebody_is_blocked = cv->blocked_count > 0;
-  LeaveCriticalSection(&cv->count_mutex);
+  LeaveCriticalSection (&cv->count_mutex);
 
-  if (somebody_is_blocked) return SetEvent (cv->ev[1]) ? 0 : GetLastError();
-  else return 0;
+  if (somebody_is_blocked)
+    SetEvent (cv->ev[1]);
+
+  return 0;
 }
 
 //
@@ -165,8 +186,8 @@ _Jv_InitThreads (void)
 {
   _Jv_ThreadKey = TlsAlloc();
   _Jv_ThreadDataKey = TlsAlloc();
-  daemon_mutex = CreateMutex(NULL, 0, NULL);
-  daemon_cond = CreateEvent(NULL, 0, 0, NULL);
+  daemon_mutex = CreateMutex (NULL, 0, NULL);
+  daemon_cond = CreateEvent (NULL, 1, 0, NULL);
   non_daemon_count = 0;
 }
 
@@ -255,7 +276,7 @@ really_start (void* x)
       WaitForSingleObject (daemon_mutex, INFINITE);
       non_daemon_count--;
       if (! non_daemon_count)
-          PulseEvent (daemon_cond);
+        SetEvent (daemon_cond);
       ReleaseMutex (daemon_mutex);
     }
 
@@ -297,10 +318,12 @@ _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, _Jv_ThreadStart
 void
 _Jv_ThreadWait (void)
 {
-  WaitForSingleObject(daemon_mutex, INFINITE);
-  if(non_daemon_count)
-      SignalObjectAndWait(daemon_mutex, daemon_cond, INFINITE, 0);
-  ReleaseMutex(daemon_mutex);
+  WaitForSingleObject (daemon_mutex, INFINITE);
+  if (non_daemon_count)
+    {
+      ReleaseMutex (daemon_mutex);
+      WaitForSingleObject (daemon_cond, INFINITE);
+    }
 }
 
 void