re PR java/9254 (java::lang::Object::wait(), threads-win32.cc returns wrong return codes)

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
This commit is contained in:
Ranjit Mathew 2003-01-28 22:23:36 +00:00 committed by Tom Tromey
parent c1c1d12306
commit 65b8e87409
3 changed files with 139 additions and 55 deletions

View 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);
int somebody_is_blocked = cv->blocked_count > 0;
LeaveCriticalSection(&cv->count_mutex);
if (mu->owner != GetCurrentThreadId ( ))
return _JV_NOT_OWNER;
if (somebody_is_blocked) return SetEvent (cv->ev[0]) ? 0 : GetLastError();
else return 0;
EnterCriticalSection (&cv->count_mutex);
ensure_condvar_initialized (cv);
int somebody_is_blocked = cv->blocked_count > 0;
LeaveCriticalSection (&cv->count_mutex);
if (somebody_is_blocked)
SetEvent (cv->ev[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);
int somebody_is_blocked = cv->blocked_count > 0;
LeaveCriticalSection(&cv->count_mutex);
if (mu->owner != GetCurrentThreadId ( ))
return _JV_NOT_OWNER;
if (somebody_is_blocked) return SetEvent (cv->ev[1]) ? 0 : GetLastError();
else return 0;
EnterCriticalSection (&cv->count_mutex);
ensure_condvar_initialized (cv);
int somebody_is_blocked = cv->blocked_count > 0;
LeaveCriticalSection (&cv->count_mutex);
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