This is the mail archive of the java-patches@sourceware.cygnus.com mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch: Posix thread sleep timeout fix



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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]