This is the mail archive of the java-patches@gcc.gnu.org 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]
Other format: [Raw text]

Patch [ecj]: Central Parking


Hi All,

This does away with _Jv_ThreadPark and _Jv_ThreadUnpark and
keeps park() and unpark() in natUnsafe.cc, thereby allowing
a shared implementation using the cross-platform synchronization
functions and objects in posix-threads.h and win32-threads.h.
Since the park() implementation uses _Jv_CondNotify, we also get
thread interrupt support for free and can do away with the _Jv_ThreadUnpark
call in Thread.interrupt(). I hope I did this right and understood
everything correctly.

I built this on a native i686-pc-linux-gnu compiler as
well as a (i686-pc-linux-gnu,i686-pc-mingw32) cross, but didn't
see any tests in the libjava testsuite for this, so it's
untested. I figure that since it compiled without any
errors, it must work flawlessly, but it would be nice to
have a second set of eyes here.

-- Mohan
http://www.thisiscool.com/
http://www.animalsong.org/

2006-12-05  Mohan Embar  <gnustuff@thisiscool.com>

	* include/posix-threads.h (_Jv_ThreadUnpark, _Jv_ThreadPark): Removed.
	* include/jvm.h (struct natThread): Replaced POSIX mutex and condition
	variables with cross-platform equivalents.
	* sun/misc/natUnsafe.cc (unpark): Ported implementation from
	posix-threads.cc; made cross-platform.
	(park): Likewise.
	* posix-threads.cc (_Jv_ThreadUnpark, _Jv_ThreadPark): Removed.
	* java/lang/natThread.cc (initialize_native): Replaced POSIX mutex
	and condition variable initialization with cross-platform equivalents.
	(finalize_native):  Replaced POSIX mutex and condition variable
	destruction with cross-platform equivalents; conditionalized.
	(interrupt): Removed call to _Jv_ThreadUnpark().
	* win32-threads.cc (_Jv_ThreadUnpark, _Jv_ThreadPark): Removed.

Index: include/posix-threads.h
===================================================================
--- include/posix-threads.h	(revision 119567)
+++ include/posix-threads.h	(working copy)
@@ -350,7 +350,4 @@
 
 void _Jv_ThreadInterrupt (_Jv_Thread_t *data);
 
-void _Jv_ThreadUnpark (::java::lang::Thread *thread);
-void _Jv_ThreadPark (jboolean isAbsolute, jlong time);
-
 #endif /* __JV_POSIX_THREADS__ */
Index: include/jvm.h
===================================================================
--- include/jvm.h	(revision 119567)
+++ include/jvm.h	(working copy)
@@ -775,8 +775,8 @@
 
   // These are used by Unsafe.park() and Unsafe.unpark().
   volatile obj_addr_t park_permit;
-  pthread_mutex_t park_mutex;
-  pthread_cond_t park_cond;
+  _Jv_Mutex_t park_mutex;
+  _Jv_ConditionVariable_t park_cond;
 
   // This is private data for the thread system layer.
   _Jv_Thread_t *thread;
Index: sun/misc/natUnsafe.cc
===================================================================
--- sun/misc/natUnsafe.cc	(revision 119567)
+++ sun/misc/natUnsafe.cc	(working copy)
@@ -238,11 +238,66 @@
 void
 sun::misc::Unsafe::unpark (::java::lang::Thread *thread)
 {
-  _Jv_ThreadUnpark (thread);
+  using namespace ::java::lang;
+  natThread *nt = (natThread *) thread->data;
+  volatile obj_addr_t *ptr = &nt->park_permit;
+
+  /* If this thread is in state RUNNING, give it a permit and return
+     immediately.  */
+  if (compare_and_swap 
+      (ptr, Thread::THREAD_PARK_RUNNING, Thread::THREAD_PARK_PERMIT))
+    return;
+  
+  /* If this thread is parked, put it into state RUNNING and send it a
+     signal.  */
+  if (compare_and_swap 
+      (ptr, Thread::THREAD_PARK_PARKED, Thread::THREAD_PARK_RUNNING))
+    {
+      _Jv_MutexLock (&nt->park_mutex);
+      _Jv_CondNotify (&nt->park_cond, &nt->park_mutex);
+      _Jv_MutexUnlock (&nt->park_mutex);
+    }
 }
 
 void
 sun::misc::Unsafe::park (jboolean isAbsolute, jlong time)
 {
-  _Jv_ThreadPark (isAbsolute, time);
+  using namespace ::java::lang;
+  Thread *thread = Thread::currentThread();
+  natThread *nt = (natThread *) thread->data;
+  volatile obj_addr_t *ptr = &nt->park_permit;
+
+  /* If we have a permit, return immediately.  */
+  if (compare_and_swap 
+      (ptr, Thread::THREAD_PARK_PERMIT, Thread::THREAD_PARK_RUNNING))
+    return;
+
+  jlong millis = 0, nanos = 0;
+
+  if (time)
+    {
+      if (isAbsolute)
+	{
+	  millis = time;
+	  nanos = 0;
+	}
+      else
+	{
+	  millis = java::lang::System::currentTimeMillis();
+	  nanos = time;
+	}
+    }
+
+  _Jv_MutexLock (&nt->park_mutex);
+  if (compare_and_swap 
+      (ptr, Thread::THREAD_PARK_RUNNING, Thread::THREAD_PARK_PARKED))
+    {
+      _Jv_CondWait (&nt->park_cond, &nt->park_mutex, millis, nanos);
+      /* If we were unparked by some other thread, this will already
+	 be in state THREAD_PARK_RUNNING.  If we were interrupted or
+	 timed out, we have to do it ourself.  */
+      compare_and_swap 
+	(ptr, Thread::THREAD_PARK_PARKED, Thread::THREAD_PARK_RUNNING);
+    }
+  _Jv_MutexUnlock (&nt->park_mutex);
 }
Index: posix-threads.cc
===================================================================
--- posix-threads.cc	(revision 119567)
+++ posix-threads.cc	(working copy)
@@ -339,129 +339,6 @@
   pthread_mutex_unlock (&data->wait_mutex);
 }
 
-/**
- * Releases the block on a thread created by _Jv_ThreadPark().  This
- * method can also be used to terminate a blockage caused by a prior
- * call to park.  This operation is unsafe, as the thread must be
- * guaranteed to be live.
- *
- * @param thread the thread to unblock.
- */
-
-void
-_Jv_ThreadUnpark (::java::lang::Thread *thread)
-{
-  using namespace ::java::lang;
-  natThread *nt = (natThread *) thread->data;
-  volatile obj_addr_t *ptr = &nt->park_permit;
-
-  /* If this thread is in state RUNNING, give it a permit and return
-     immediately.  */
-  if (compare_and_swap 
-      (ptr, Thread::THREAD_PARK_RUNNING, Thread::THREAD_PARK_PERMIT))
-    return;
-  
-  /* If this thread is parked, put it into state RUNNING and send it a
-     signal.  */
-  if (compare_and_swap 
-      (ptr, Thread::THREAD_PARK_PARKED, Thread::THREAD_PARK_RUNNING))
-    {
-      pthread_mutex_lock (&nt->park_mutex);
-      pthread_cond_signal (&nt->park_cond);
-      pthread_mutex_unlock (&nt->park_mutex);
-    }
-}
-
-/**
- * Blocks the thread until a matching _Jv_ThreadUnpark() occurs, the
- * thread is interrupted or the optional timeout expires.  If an
- * unpark call has already occurred, this also counts.  A timeout
- * value of zero is defined as no timeout.  When isAbsolute is true,
- * the timeout is in milliseconds relative to the epoch.  Otherwise,
- * the value is the number of nanoseconds which must occur before
- * timeout.  This call may also return spuriously (i.e.  for no
- * apparent reason).
- *
- * @param isAbsolute true if the timeout is specified in milliseconds from
- *                   the epoch.
- * @param time either the number of nanoseconds to wait, or a time in
- *             milliseconds from the epoch to wait for.
- */
-
-void
-_Jv_ThreadPark (jboolean isAbsolute, jlong time)
-{
-  using namespace ::java::lang;
-  Thread *thread = Thread::currentThread();
-  natThread *nt = (natThread *) thread->data;
-  volatile obj_addr_t *ptr = &nt->park_permit;
-
-  /* If we have a permit, return immediately.  */
-  if (compare_and_swap 
-      (ptr, Thread::THREAD_PARK_PERMIT, Thread::THREAD_PARK_RUNNING))
-    return;
-
-  struct timespec ts;
-  jlong millis = 0, nanos = 0;
-
-  if (time)
-    {
-      if (isAbsolute)
-	{
-	  millis = time;
-	  nanos = 0;
-	}
-      else
-	{
-	  millis = java::lang::System::currentTimeMillis();
-	  nanos = time;
-	}
-
-      if (millis > 0 || nanos > 0)
-	{
-	  // Calculate the abstime corresponding to the timeout.
-	  // Everything is in milliseconds.
-	  //
-	  // We use `unsigned long long' rather than jlong because our
-	  // caller may pass up to Long.MAX_VALUE millis.  This would
-	  // overflow the range of a timespec.
-
-	  unsigned long long m = (unsigned long long)millis;
-	  unsigned long long seconds = m / 1000; 
-
-	  ts.tv_sec = seconds;
-	  if (ts.tv_sec < 0 || (unsigned long long)ts.tv_sec != seconds)
-	    {
-	      // We treat a timeout that won't fit into a struct timespec
-	      // as a wait forever.
-	      millis = nanos = 0;
-	    }
-	  else
-	    {
-	      m %= 1000;
-	      ts.tv_nsec = m * 1000000 + (unsigned long long)nanos;
-	    }
-	}
-    }
-      
-  pthread_mutex_lock (&nt->park_mutex);
-  if (compare_and_swap 
-      (ptr, Thread::THREAD_PARK_RUNNING, Thread::THREAD_PARK_PARKED))
-    {
-      if (millis == 0 && nanos == 0)
-	pthread_cond_wait (&nt->park_cond, &nt->park_mutex);
-      else
-	pthread_cond_timedwait (&nt->park_cond, &nt->park_mutex, 
-					&ts);
-      /* If we were unparked by some other thread, this will already
-	 be in state THREAD_PARK_RUNNING.  If we timed out, we have to
-	 do it ourself.  */
-      compare_and_swap 
-	(ptr, Thread::THREAD_PARK_PARKED, Thread::THREAD_PARK_RUNNING);
-    }
-  pthread_mutex_unlock (&nt->park_mutex);
-}
-
 static void
 handle_intr (int)
 {
Index: java/lang/natThread.cc
===================================================================
--- java/lang/natThread.cc	(revision 119567)
+++ java/lang/natThread.cc	(working copy)
@@ -54,8 +54,8 @@
   _Jv_MutexInit (&nt->join_mutex);
   _Jv_CondInit (&nt->join_cond);
 
-  pthread_mutex_init (&nt->park_mutex, NULL);
-  pthread_cond_init (&nt->park_cond, NULL);
+  _Jv_MutexInit (&nt->park_mutex);
+  _Jv_CondInit (&nt->park_cond);
 
   nt->thread = _Jv_ThreadInitData (this);
   // FIXME: if JNI_ENV is set we will want to free it.  It is
@@ -70,14 +70,14 @@
   _Jv_ThreadDestroyData (nt->thread);
 #ifdef _Jv_HaveCondDestroy
   _Jv_CondDestroy (&nt->join_cond);
+  _Jv_CondDestroy (&nt->park_cond);
 #endif
 #ifdef _Jv_HaveMutexDestroy
   _Jv_MutexDestroy (&nt->join_mutex);
+  _Jv_MutexDestroy (&nt->park_mutex);
 #endif
   _Jv_FreeJNIEnv((JNIEnv*)nt->jni_env);
 
-  pthread_mutex_destroy (&nt->park_mutex);
-  pthread_cond_destroy (&nt->park_cond);
 }
 
 jint
@@ -128,10 +128,6 @@
       _Jv_ThreadInterrupt (nt->thread);
       compare_and_swap 
 	(&nt->alive_flag, THREAD_SIGNALED, Thread::THREAD_ALIVE);
-
-      // Even though we've interrupted this thread, it might still be
-      // parked.
-      _Jv_ThreadUnpark (this);
     }
 }
 
Index: win32-threads.cc
===================================================================
--- win32-threads.cc	(revision 119567)
+++ win32-threads.cc	(working copy)
@@ -419,40 +419,3 @@
   SetEvent (data->interrupt_event);
   LeaveCriticalSection (&data->interrupt_mutex);
 }
-
-/**
- * Releases the block on a thread created by _Jv_ThreadPark().  This
- * method can also be used to terminate a blockage caused by a prior
- * call to park.  This operation is unsafe, as the thread must be
- * guaranteed to be live.
- *
- * @param thread the thread to unblock.
- */
-
-void
-_Jv_ThreadUnpark (::java::lang::Thread *thread)
-{
-  // WRITEME:
-}
-
-/**
- * Blocks the thread until a matching _Jv_ThreadUnpark() occurs, the
- * thread is interrupted or the optional timeout expires.  If an
- * unpark call has already occurred, this also counts.  A timeout
- * value of zero is defined as no timeout.  When isAbsolute is true,
- * the timeout is in milliseconds relative to the epoch.  Otherwise,
- * the value is the number of nanoseconds which must occur before
- * timeout.  This call may also return spuriously (i.e.  for no
- * apparent reason).
- *
- * @param isAbsolute true if the timeout is specified in milliseconds from
- *                   the epoch.
- * @param time either the number of nanoseconds to wait, or a time in
- *             milliseconds from the epoch to wait for.
- */
-
-void
-_Jv_ThreadPark (jboolean isAbsolute, jlong time)
-{
-  // WRITEME:
-}




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