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:
parent
c1c1d12306
commit
65b8e87409
3 changed files with 139 additions and 55 deletions
|
@ -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>
|
2003-01-27 Ranjit Mathew <rmathew@hotmail.com>
|
||||||
|
|
||||||
* configure.in: Specifically define HAVE_BACKTRACE if building
|
* configure.in: Specifically define HAVE_BACKTRACE if building
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// -*- c++ -*-
|
// -*- c++ -*-
|
||||||
// win32-threads.h - Defines for using Win32 threads.
|
// 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.
|
This file is part of libgcj.
|
||||||
|
|
||||||
|
@ -18,13 +19,32 @@ details. */
|
||||||
// Typedefs.
|
// 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];
|
HANDLE ev[2];
|
||||||
CRITICAL_SECTION count_mutex;
|
|
||||||
int blocked_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef CRITICAL_SECTION _Jv_Mutex_t;
|
// Number of threads waiting on this condition variable
|
||||||
|
int blocked_count;
|
||||||
|
|
||||||
|
// 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
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -60,25 +80,39 @@ int _Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *);
|
||||||
|
|
||||||
inline void _Jv_MutexInit (_Jv_Mutex_t *mu)
|
inline void _Jv_MutexInit (_Jv_Mutex_t *mu)
|
||||||
{
|
{
|
||||||
InitializeCriticalSection(mu);
|
mu->owner = 0UL;
|
||||||
|
mu->refcount = 0;
|
||||||
|
InitializeCriticalSection (&(mu->cs));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _Jv_HaveMutexDestroy
|
#define _Jv_HaveMutexDestroy
|
||||||
inline void _Jv_MutexDestroy (_Jv_Mutex_t *mu)
|
inline void _Jv_MutexDestroy (_Jv_Mutex_t *mu)
|
||||||
{
|
{
|
||||||
DeleteCriticalSection(mu);
|
mu->owner = 0UL;
|
||||||
|
mu->refcount = 0;
|
||||||
|
DeleteCriticalSection (&(mu->cs));
|
||||||
mu = NULL;
|
mu = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int _Jv_MutexUnlock (_Jv_Mutex_t *mu)
|
inline int _Jv_MutexUnlock (_Jv_Mutex_t *mu)
|
||||||
{
|
{
|
||||||
LeaveCriticalSection(mu);
|
if (mu->owner == GetCurrentThreadId ( ))
|
||||||
return 0;
|
{
|
||||||
|
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)
|
inline int _Jv_MutexLock (_Jv_Mutex_t *mu)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(mu);
|
EnterCriticalSection (&(mu->cs));
|
||||||
|
mu->owner = GetCurrentThreadId ( );
|
||||||
|
mu->refcount++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +138,7 @@ inline _Jv_Thread_t *_Jv_ThreadCurrentData(void)
|
||||||
|
|
||||||
inline void _Jv_ThreadYield (void)
|
inline void _Jv_ThreadYield (void)
|
||||||
{
|
{
|
||||||
// FIXME: win98 freezes hard (OS hang) when we use this --
|
Sleep (0);
|
||||||
// for now, we simply don't yield
|
|
||||||
// Sleep (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _Jv_ThreadRegister (_Jv_Thread_t *data);
|
void _Jv_ThreadRegister (_Jv_Thread_t *data);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// win32-threads.cc - interface between libjava and Win32 threads.
|
// 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.
|
This file is part of libgcj.
|
||||||
|
|
||||||
|
@ -70,12 +71,14 @@ DWORD _Jv_ThreadDataKey;
|
||||||
inline void
|
inline void
|
||||||
ensure_condvar_initialized(_Jv_ConditionVariable_t *cv)
|
ensure_condvar_initialized(_Jv_ConditionVariable_t *cv)
|
||||||
{
|
{
|
||||||
if (cv->ev[0] == 0) {
|
if (cv->ev[0] == 0)
|
||||||
cv->ev[0] = CreateEvent (NULL, 0, 0, NULL);
|
{
|
||||||
if (cv->ev[0] == 0) JvFail("CreateEvent() failed");
|
cv->ev[0] = CreateEvent (NULL, 0, 0, NULL);
|
||||||
cv->ev[1] = CreateEvent (NULL, 1, 0, NULL);
|
if (cv->ev[0] == 0) JvFail("CreateEvent() failed");
|
||||||
if (cv->ev[1] == 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
|
// Reimplementation of the general algorithm described at
|
||||||
|
@ -85,11 +88,13 @@ ensure_condvar_initialized(_Jv_ConditionVariable_t *cv)
|
||||||
int
|
int
|
||||||
_Jv_CondWait(_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu, jlong millis, jint nanos)
|
_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);
|
EnterCriticalSection (&cv->count_mutex);
|
||||||
ensure_condvar_initialized(cv);
|
ensure_condvar_initialized (cv);
|
||||||
cv->blocked_count++;
|
cv->blocked_count++;
|
||||||
LeaveCriticalSection(&cv->count_mutex);
|
LeaveCriticalSection (&cv->count_mutex);
|
||||||
|
|
||||||
DWORD time;
|
DWORD time;
|
||||||
if ((millis == 0) && (nanos > 0)) time = 1;
|
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);
|
EnterCriticalSection(&cv->count_mutex);
|
||||||
cv->blocked_count--;
|
cv->blocked_count--;
|
||||||
// If we were unblocked by the second event (the broadcast one) and nobody is
|
// If we were unblocked by the second event (the broadcast one)
|
||||||
// left, then reset the signal.
|
// and nobody is left, then reset the event.
|
||||||
int last_waiter = rval == WAIT_OBJECT_0 + 1 && cv->blocked_count == 0;
|
int last_waiter = (rval == (WAIT_OBJECT_0 + 1)) && (cv->blocked_count == 0);
|
||||||
LeaveCriticalSection(&cv->count_mutex);
|
LeaveCriticalSection(&cv->count_mutex);
|
||||||
|
|
||||||
if (last_waiter) ResetEvent(&cv->ev[1]);
|
if (last_waiter)
|
||||||
|
ResetEvent (cv->ev[1]);
|
||||||
|
|
||||||
_Jv_MutexLock (mu);
|
_Jv_MutexLock (mu);
|
||||||
|
|
||||||
if (rval == WAIT_FAILED) return GetLastError();
|
return 0;
|
||||||
else if (rval == WAIT_TIMEOUT) return ETIMEDOUT;
|
|
||||||
else return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -121,39 +125,56 @@ _Jv_CondInit (_Jv_ConditionVariable_t *cv)
|
||||||
{
|
{
|
||||||
// we do lazy creation of Events since CreateEvent() is insanely expensive
|
// we do lazy creation of Events since CreateEvent() is insanely expensive
|
||||||
cv->ev[0] = 0;
|
cv->ev[0] = 0;
|
||||||
InitializeCriticalSection(&cv->count_mutex);
|
InitializeCriticalSection (&cv->count_mutex);
|
||||||
cv->blocked_count = 0;
|
cv->blocked_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_Jv_CondDestroy (_Jv_ConditionVariable_t *cv)
|
_Jv_CondDestroy (_Jv_ConditionVariable_t *cv)
|
||||||
{
|
{
|
||||||
if (cv->ev[0] != 0) CloseHandle(cv->ev[0]);
|
if (cv->ev[0] != 0)
|
||||||
cv = NULL;
|
{
|
||||||
|
CloseHandle (cv->ev[0]);
|
||||||
|
CloseHandle (cv->ev[1]);
|
||||||
|
|
||||||
|
cv->ev[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteCriticalSection (&cv->count_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *)
|
_Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&cv->count_mutex);
|
if (mu->owner != GetCurrentThreadId ( ))
|
||||||
ensure_condvar_initialized(cv);
|
return _JV_NOT_OWNER;
|
||||||
int somebody_is_blocked = cv->blocked_count > 0;
|
|
||||||
LeaveCriticalSection(&cv->count_mutex);
|
|
||||||
|
|
||||||
if (somebody_is_blocked) return SetEvent (cv->ev[0]) ? 0 : GetLastError();
|
EnterCriticalSection (&cv->count_mutex);
|
||||||
else return 0;
|
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
|
int
|
||||||
_Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *)
|
_Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&cv->count_mutex);
|
if (mu->owner != GetCurrentThreadId ( ))
|
||||||
ensure_condvar_initialized(cv);
|
return _JV_NOT_OWNER;
|
||||||
int somebody_is_blocked = cv->blocked_count > 0;
|
|
||||||
LeaveCriticalSection(&cv->count_mutex);
|
|
||||||
|
|
||||||
if (somebody_is_blocked) return SetEvent (cv->ev[1]) ? 0 : GetLastError();
|
EnterCriticalSection (&cv->count_mutex);
|
||||||
else return 0;
|
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_ThreadKey = TlsAlloc();
|
||||||
_Jv_ThreadDataKey = TlsAlloc();
|
_Jv_ThreadDataKey = TlsAlloc();
|
||||||
daemon_mutex = CreateMutex(NULL, 0, NULL);
|
daemon_mutex = CreateMutex (NULL, 0, NULL);
|
||||||
daemon_cond = CreateEvent(NULL, 0, 0, NULL);
|
daemon_cond = CreateEvent (NULL, 1, 0, NULL);
|
||||||
non_daemon_count = 0;
|
non_daemon_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +276,7 @@ really_start (void* x)
|
||||||
WaitForSingleObject (daemon_mutex, INFINITE);
|
WaitForSingleObject (daemon_mutex, INFINITE);
|
||||||
non_daemon_count--;
|
non_daemon_count--;
|
||||||
if (! non_daemon_count)
|
if (! non_daemon_count)
|
||||||
PulseEvent (daemon_cond);
|
SetEvent (daemon_cond);
|
||||||
ReleaseMutex (daemon_mutex);
|
ReleaseMutex (daemon_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,10 +318,12 @@ _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, _Jv_ThreadStart
|
||||||
void
|
void
|
||||||
_Jv_ThreadWait (void)
|
_Jv_ThreadWait (void)
|
||||||
{
|
{
|
||||||
WaitForSingleObject(daemon_mutex, INFINITE);
|
WaitForSingleObject (daemon_mutex, INFINITE);
|
||||||
if(non_daemon_count)
|
if (non_daemon_count)
|
||||||
SignalObjectAndWait(daemon_mutex, daemon_cond, INFINITE, 0);
|
{
|
||||||
ReleaseMutex(daemon_mutex);
|
ReleaseMutex (daemon_mutex);
|
||||||
|
WaitForSingleObject (daemon_cond, INFINITE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue