This is the mail archive of the
java-patches@sourceware.cygnus.com
mailing list for the Java project.
Patch: Posix thread sleep timeout fix
- To: java-patches@sourceware.cygnus.com
- Subject: Patch: Posix thread sleep timeout fix
- From: Matt Welsh <mdw@cs.berkeley.edu>
- Date: Tue, 07 Sep 1999 12:52:40 -0700
- cc: tromey@cygnus.com
- Reply-To: Matt Welsh <mdw@cs.berkeley.edu>
The following patch fixes the problem where threads doing a sleep()
operation would be prematurely woken up by the GC signal handlers.
Note that on some x86 SMP systems (such as the IBM Netfinity systems I
am using), there is a problem where Linux gettimeofday() reports different
times on different CPUs. This appears to be fixed by a kernel patch from
Ingo Molnar, mingo@redhat.com.
1999-09-07 Matt Welsh <mdw@cs.berkeley.edu>
* libjava/posix-threads.cc: Added _Jv_ThreadDataKey to map
from POSIX thread back to the _Jv_Thread_t*
* Added FLAG_INTERRUPTED; this is set when the thread is
interrupted by another Java thread.
* _Jv_CondWait() continues to sleep if interrupted by the GC
* libjava/include/posix-threads.h: Added _Jv_CurrentThreadData()
Index: libjava/posix-threads.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/posix-threads.cc,v
retrieving revision 1.5
diff -c -3 -p -r1.5 posix-threads.cc
*** posix-threads.cc 1999/08/25 00:46:23 1.5
--- posix-threads.cc 1999/09/07 19:43:30
*************** struct starter
*** 46,51 ****
--- 46,55 ----
// threads, so it is ok to make it a global here.
pthread_key_t _Jv_ThreadKey;
+ // This is the key used to map from the POSIX thread value back to the
+ // _Jv_Thread_t* representing the thread.
+ pthread_key_t _Jv_ThreadDataKey;
+
// We keep a count of all non-daemon threads which are running. When
// this reaches zero, _Jv_ThreadWait returns.
static pthread_mutex_t daemon_mutex;
*************** static int non_daemon_count;
*** 68,73 ****
--- 72,79 ----
#define FLAG_START 0x01
// Thread is daemon.
#define FLAG_DAEMON 0x02
+ // Thread was interrupted by _Jv_ThreadInterrupt.
+ #define FLAG_INTERRUPTED 0x04
*************** _Jv_CondWait (_Jv_ConditionVariable_t *c
*** 77,100 ****
{
int r;
pthread_mutex_t *pmu;
#ifdef HAVE_RECURSIVE_MUTEX
pmu = mu;
#else
pmu = &mu->mutex2;
#endif
! if (millis == 0 && nanos == 0)
r = pthread_cond_wait (cv, pmu);
else
{
! struct timespec ts;
! jlong m = millis + java::lang::System::currentTimeMillis ();
ts.tv_sec = m / 1000;
ts.tv_nsec = ((m % 1000) * 1000000) + nanos;
r = pthread_cond_timedwait (cv, pmu, &ts);
! /* A timeout is a normal result. */
! if (r && errno == ETIMEDOUT)
! r = 0;
}
return r;
}
--- 83,132 ----
{
int r;
pthread_mutex_t *pmu;
+ struct timespec ts;
+ jlong m, m2, startTime;
+
#ifdef HAVE_RECURSIVE_MUTEX
pmu = mu;
#else
pmu = &mu->mutex2;
#endif
! if (millis == 0 && nanos == 0) {
r = pthread_cond_wait (cv, pmu);
+ }
else
{
! startTime = java::lang::System::currentTimeMillis();
! m = millis + startTime;
! resleep:
ts.tv_sec = m / 1000;
ts.tv_nsec = ((m % 1000) * 1000000) + nanos;
r = pthread_cond_timedwait (cv, pmu, &ts);
!
! if (r == EINTR) {
! /* We were interrupted by a signal. Either this is because we were
! * interrupted intentionally (i.e. by Thread.interrupt()) or
! * by the GC if it is signal-based.
! */
! _Jv_Thread_t *current = _Jv_ThreadCurrentData();
! if (current->flags & FLAG_INTERRUPTED) {
! current->flags &= ~(FLAG_INTERRUPTED);
! } else {
! /* We were woken up by the GC or another signal */
! m2 = java::lang::System::currentTimeMillis ();
! if (m2 < m) {
! goto resleep;
! } else {
! r = 0;
! }
! }
! } else {
! /* A timeout is a normal result. */
! if (r && errno == ETIMEDOUT) {
! r = 0;
! }
! }
}
return r;
}
*************** _Jv_MutexLock (_Jv_Mutex_t *mu)
*** 175,181 ****
else
{
// Try to acquire the lock.
! pthread_cond_wait (&mu->cond, &mu->mutex);
}
}
pthread_mutex_unlock (&mu->mutex);
--- 207,213 ----
else
{
// Try to acquire the lock.
! (void)pthread_cond_wait (&mu->cond, &mu->mutex);
}
}
pthread_mutex_unlock (&mu->mutex);
*************** void
*** 215,220 ****
--- 247,253 ----
_Jv_InitThreads (void)
{
pthread_key_create (&_Jv_ThreadKey, NULL);
+ pthread_key_create (&_Jv_ThreadDataKey, NULL);
pthread_mutex_init (&daemon_mutex, NULL);
pthread_cond_init (&daemon_cond, 0);
non_daemon_count = 0;
*************** really_start (void *x)
*** 290,295 ****
--- 323,329 ----
pthread_cleanup_push (throw_cleanup, info->data);
pthread_setspecific (_Jv_ThreadKey, info->object);
+ pthread_setspecific (_Jv_ThreadDataKey, info->data);
info->method (info->object);
pthread_cleanup_pop (0);
*************** _Jv_ThreadWait (void)
*** 359,363 ****
--- 393,398 ----
void
_Jv_ThreadInterrupt (_Jv_Thread_t *data)
{
+ data->flags |= FLAG_INTERRUPTED;
pthread_kill (data->thread, INTR);
}
cvs server: Diffing libjava/doc
cvs server: Diffing libjava/gnu
cvs server: Diffing libjava/gnu/gcj
cvs server: Diffing libjava/gnu/gcj/convert
cvs server: Diffing libjava/gnu/gcj/protocol
cvs server: Diffing libjava/gnu/gcj/protocol/file
cvs server: Diffing libjava/gnu/gcj/protocol/http
cvs server: Diffing libjava/gnu/gcj/protocol/jar
cvs server: Diffing libjava/gnu/gcj/runtime
cvs server: Diffing libjava/gnu/gcj/text
cvs server: Diffing libjava/gnu/gcj/util
cvs server: Diffing libjava/gnu/gcj/util/path
cvs server: Diffing libjava/include
Index: libjava/include/posix-threads.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/include/posix-threads.h,v
retrieving revision 1.1.1.1
diff -c -3 -p -r1.1.1.1 posix-threads.h
*** posix-threads.h 1999/04/07 14:52:35 1.1.1.1
--- posix-threads.h 1999/09/07 19:43:30
*************** _Jv_ThreadCurrent (void)
*** 181,186 ****
--- 181,193 ----
return (java::lang::Thread *) pthread_getspecific (_Jv_ThreadKey);
}
+ inline _Jv_Thread_t *
+ _Jv_ThreadCurrentData (void)
+ {
+ extern pthread_key_t _Jv_ThreadDataKey;
+ return (_Jv_Thread_t *) pthread_getspecific (_Jv_ThreadDataKey);
+ }
+
inline void
_Jv_ThreadYield (void)
{
cvs server: Diffing libjava/java
cvs server: Diffing libjava/java/awt
cvs server: Diffing libjava/java/awt/event
cvs server: Diffing libjava/java/awt/geom
cvs server: Diffing libjava/java/awt/peer
cvs server: Diffing libjava/java/io
cvs server: Diffing libjava/java/lang
cvs server: Diffing libjava/java/lang/reflect
cvs server: Diffing libjava/java/net
cvs server: Diffing libjava/java/security
cvs server: Diffing libjava/java/text
cvs server: Diffing libjava/java/util
cvs server: Diffing libjava/java/util/jar
cvs server: Diffing libjava/java/util/zip
cvs server: Diffing libjava/testsuite
cvs server: Diffing libjava/testsuite/config
cvs server: Diffing libjava/testsuite/lib
cvs server: Diffing libjava/testsuite/libjava.compile
cvs server: Diffing libjava/testsuite/libjava.compile/support
cvs server: Diffing libjava/testsuite/libjava.lang
cvs server: Diffing libjava/testsuite/libjava.mauve
cvs server: Diffing zip
cvs server: Diffing zip/acorn
cvs server: Diffing zip/amiga
cvs server: Diffing zip/aosvs
cvs server: Diffing zip/atari
cvs server: Diffing zip/cmsmvs
cvs server: Diffing zip/human68k
cvs server: Diffing zip/man
cvs server: Diffing zip/msdos
cvs server: Diffing zip/os2
cvs server: Diffing zip/tops20
cvs server: Diffing zip/unix
cvs server: Diffing zip/vms
cvs server: Diffing zip/win32
cvs server: Diffing zip/wizdll
cvs server: Diffing zlib
cvs server: Diffing zlib/amiga
cvs server: Diffing zlib/contrib
cvs server: Diffing zlib/contrib/asm386
cvs server: Diffing zlib/contrib/asm586
cvs server: Diffing zlib/contrib/asm686
cvs server: Diffing zlib/contrib/delphi
cvs server: Diffing zlib/contrib/delphi2
cvs server: Diffing zlib/contrib/iostream
cvs server: Diffing zlib/contrib/iostream2
cvs server: Diffing zlib/contrib/minizip
cvs server: Diffing zlib/contrib/untgz
cvs server: Diffing zlib/msdos
cvs server: Diffing zlib/nt
cvs server: Diffing zlib/os2