[vmkit-commits] [vmkit] r180504 - improving prk/unpark implementation

Peter Senna Tschudin peter.senna at gmail.com
Thu Apr 25 10:18:52 PDT 2013


Author: peter.senna
Date: Thu Apr 25 12:17:21 2013
New Revision: 180504

URL: http://llvm.org/viewvc/llvm-project?rev=180504&view=rev
Log:
improving prk/unpark implementation
(cherry picked from commit db2918b65307f8acbf0fc92804182b599287edfa)

Modified:
    vmkit/trunk/lib/j3/ClassLib/GNUClasspath/ClasspathVMThread.inc
    vmkit/trunk/lib/j3/ClassLib/Unsafe.inc
    vmkit/trunk/lib/j3/VMCore/JavaThread.cpp
    vmkit/trunk/lib/j3/VMCore/JavaThread.h
    vmkit/trunk/lib/j3/VMCore/Jnjvm.cpp

Modified: vmkit/trunk/lib/j3/ClassLib/GNUClasspath/ClasspathVMThread.inc
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/j3/ClassLib/GNUClasspath/ClasspathVMThread.inc?rev=180504&r1=180503&r2=180504&view=diff
==============================================================================
--- vmkit/trunk/lib/j3/ClassLib/GNUClasspath/ClasspathVMThread.inc (original)
+++ vmkit/trunk/lib/j3/ClassLib/GNUClasspath/ClasspathVMThread.inc Thu Apr 25 12:17:21 2013
@@ -126,7 +126,10 @@ JavaObject* vmthread) {
   
   JavaThread* th = (JavaThread*)field->getInstanceObjectField(vmthread);
   th->lockingThread.interruptFlag = 1;
-  th->parkLock.interrupt();
+  //th->parkLock.interrupt();
+  //fprintf(stderr, "Interrupting started%lld\n", th->getThreadID());
+  th->parkLock.unpark();
+  //fprintf(stderr, "Interrupting done%lld\n", th->getThreadID());
   vmkit::FatLock* lock = th->lockingThread.waitsOn;
 
   // If the thread is blocked on a wait. We also verify nextWaiting in case

Modified: vmkit/trunk/lib/j3/ClassLib/Unsafe.inc
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/j3/ClassLib/Unsafe.inc?rev=180504&r1=180503&r2=180504&view=diff
==============================================================================
--- vmkit/trunk/lib/j3/ClassLib/Unsafe.inc (original)
+++ vmkit/trunk/lib/j3/ClassLib/Unsafe.inc Thu Apr 25 12:17:21 2013
@@ -486,7 +486,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Uns
 JavaObject* unsafe, jboolean isAbsolute, jlong time) {
   llvm_gcroot(unsafe, 0);
   JavaThread* thread = (JavaThread*)JavaThread::get();
-  thread->parkLock.park(isAbsolute, time);
+  thread->parkLock.park(isAbsolute, time, thread);
 }
 
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_unpark(
@@ -511,7 +511,9 @@ JavaObject* unsafe, JavaObject* thread)
   	JavaThread::yield();
   	th = (JavaThread*)field->getInstanceObjectField(vmthread);
   }
+  //fprintf(stderr, "unparking started %lld\n", th->getThreadID());
   th->parkLock.unpark();
+  //fprintf(stderr, "unparking done %lld\n", th->getThreadID());
 }
 
 //===--- Monitor support --------------------------------------------------===//

Modified: vmkit/trunk/lib/j3/VMCore/JavaThread.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/j3/VMCore/JavaThread.cpp?rev=180504&r1=180503&r2=180504&view=diff
==============================================================================
--- vmkit/trunk/lib/j3/VMCore/JavaThread.cpp (original)
+++ vmkit/trunk/lib/j3/VMCore/JavaThread.cpp Thu Apr 25 12:17:21 2013
@@ -206,58 +206,166 @@ void JavaThread::throwNullPointerExcepti
 }
 
 ParkLock::ParkLock() {
-	permit = 1;
+	permit = 0;
 }
 
 ParkLock::~ParkLock() {
 
 }
 
+inline void _OrderAccess_fence() {
+    // Always use locked addl since mfence is sometimes expensive
+	__sync_synchronize();
+    //__asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory");
+}
+
 // Implementation of method park, see LockSupport.java
 // time is in nanoseconds if !isAboslute, otherwise it is in milliseconds
-void ParkLock::park(bool isAbsolute, int64_t time) {
-	JavaThread* thread = (JavaThread*)vmkit::Thread::get();
-	lock.lock();
-		if (permit == 0){
-			permit = 1;
-			__sync_synchronize();
-			lock.unlock(thread);
-			return;
-		}
-		if (isAbsolute && time == 0) {
-			lock.unlock(thread);
-			return;
-		}
-		if (time == 0) {
-			thread->setState(vmkit::LockingThread::StateWaiting);
-			permit = 2;
-			__sync_synchronize();
-			cond.wait(&lock);
-			permit = 1;
-		}
-		else {
-			thread->setState(vmkit::LockingThread::StateTimeWaiting);
-			permit = 2;
-			__sync_synchronize();
-			cond.myTimeWait(&lock, isAbsolute, time);
-			permit = 1;
-		}
-		thread->setState(vmkit::LockingThread::StateRunning);
-		__sync_synchronize();
-	lock.unlock(thread);
+void ParkLock::park(bool isAbsolute, int64_t time, JavaThread* thread) {
+//	lock.lock();
+//		if (permit == 0){
+//			permit = 1;
+//			__sync_synchronize();
+//			lock.unlock(thread);
+//			return;
+//		}
+//		if (isAbsolute && time == 0) {
+//			lock.unlock(thread);
+//			return;
+//		}
+//		if (thread->lockingThread.interruptFlag) {
+//			lock.unlock(thread);
+//			return;
+//		}
+//		if (time == 0) {
+//			thread->setState(vmkit::LockingThread::StateWaiting);
+//			//permit = 2;
+//			__sync_synchronize();
+//			cond.wait(&lock);
+//			//if (permit == 2) permit = 1;
+//			//permit = 1;
+//		}
+//		else {
+//			thread->setState(vmkit::LockingThread::StateTimeWaiting);
+//			//permit = 2;
+//			__sync_synchronize();
+//			cond.myTimeWait(&lock, isAbsolute, time);
+//			//if (permit == 2) permit = 1;
+//			//permit = 1;
+//		}
+//		thread->setState(vmkit::LockingThread::StateRunning);
+//		__sync_synchronize();
+//	lock.unlock(thread);
+	 // Optional fast-path check:
+	  // Return immediately if a permit is available.
+	  if (permit > 0) {
+		  permit = 0 ;
+		  _OrderAccess_fence();//__sync_synchronize();//OrderAccess::fence();
+	      return ;
+	  }
+
+	  // Optional optimization -- avoid state transitions if there's an interrupt pending.
+	  // Check interrupt before trying to wait
+	  if (thread->lockingThread.interruptFlag) {
+	    return;
+	  }
+
+	  if (time < 0 || (isAbsolute && time == 0) ) { // don't wait at all
+	    return;
+	  }
+
+
+	  // Enter safepoint region
+	  // Beware of deadlocks such as 6317397.
+	  // The per-thread Parker:: mutex is a classic leaf-lock.
+	  // In particular a thread must never block on the Threads_lock while
+	  // holding the Parker:: mutex.  If safepoints are pending both the
+	  // the ThreadBlockInVM() CTOR and DTOR may grab Threads_lock.
+	  //ThreadBlockInVM tbivm(jt);
+
+	  // Don't wait if cannot get lock since interference arises from
+	  // unblocking.  Also. check interrupt before trying wait
+	  if (thread->lockingThread.interruptFlag || lock.tryLock() != 0) {
+	    return;
+	  }
+
+	  //fprintf(stderr, "Starting method %lld\n", thread->getThreadID());
+
+	  int status ;
+	  if (permit > 0)  { // no wait needed
+		permit = 0;
+		lock.unlock(thread);
+		_OrderAccess_fence();//__sync_synchronize();//OrderAccess::fence();
+		//fprintf(stderr, "Finishing method 0 %lld\n", thread->getThreadID());
+		return;
+	  }
+
+	  //OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
+	  //jt->set_suspend_equivalent();
+	  // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
+
+	  if (time == 0) {
+		  //thread->setState(vmkit::LockingThread::StateWaiting);
+		  cond.wait(&lock);
+	  } else {
+		  //thread->setState(vmkit::LockingThread::StateTimeWaiting);
+		  cond.myTimeWait(&lock, isAbsolute, time);
+	  }
+	  //thread->setState(vmkit::LockingThread::StateRunning);
+	  permit = 0 ;
+	  lock.unlock(thread);
+	  // If externally suspended while waiting, re-suspend
+	  //if (jt->handle_special_suspend_equivalent_condition()) {
+	  //  jt->java_suspend_self();
+	  //}
+
+	  __sync_synchronize();//OrderAccess::fence();
+	  //fprintf(stderr, "Finishing method 1 %lld\n", thread->getThreadID());
 }
 
 void ParkLock::unpark() {
+
 	JavaThread* thread = (JavaThread*)vmkit::Thread::get();
-	bool flag = false;
+	//bool flag = false;
+//	lock.lock();
+//		if (permit == 0) {
+//			lock.unlock(thread);
+//			return;
+//		}
+//		//if (permit != 0)
+//		//	flag = !__sync_bool_compare_and_swap(&permit, 1, 0);
+//		permit = 0;
+//		__sync_synchronize();
+//		//flag = true;
+//		cond.signal();
+//	lock.unlock(thread);
+	//if (flag)
+	//	cond.signal();
+	int s ;
 	lock.lock();
-		if (permit != 0)
-			flag = !__sync_bool_compare_and_swap(&permit, 1, 0);
-	lock.unlock(thread);
-	if (flag)
-		cond.signal();
+	s = permit;
+	permit = 1;
+	_OrderAccess_fence();
+	if (s < 1) {
+		if (false) {
+			cond.signal();
+			lock.unlock(thread);
+		} else {
+			lock.unlock(thread);
+			cond.signal();
+		}
+	} else {
+		lock.unlock(thread);
+	}
 }
 
-void ParkLock::interrupt() {
-	cond.signal();
-}
+//void ParkLock::interrupt() {
+//	//
+//	if (lock.tryLock() == 0) {
+//		JavaThread* thread = (JavaThread*)vmkit::Thread::get();
+//		cond.signal();
+//
+//		lock.unlock(thread);
+//	}
+//	_OrderAccess_fence();
+//}

Modified: vmkit/trunk/lib/j3/VMCore/JavaThread.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/j3/VMCore/JavaThread.h?rev=180504&r1=180503&r2=180504&view=diff
==============================================================================
--- vmkit/trunk/lib/j3/VMCore/JavaThread.h (original)
+++ vmkit/trunk/lib/j3/VMCore/JavaThread.h Thu Apr 25 12:17:21 2013
@@ -68,9 +68,9 @@ public:
 	ParkLock();
 	~ParkLock();
 
-	void park(bool isAbsolute, int64_t time);
+	void park(bool isAbsolute, int64_t time, JavaThread* thread);
 	void unpark();
-	void interrupt();
+//	void interrupt();
 };
 
 /// JavaThread - This class is the internal representation of a Java thread.

Modified: vmkit/trunk/lib/j3/VMCore/Jnjvm.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/j3/VMCore/Jnjvm.cpp?rev=180504&r1=180503&r2=180504&view=diff
==============================================================================
--- vmkit/trunk/lib/j3/VMCore/Jnjvm.cpp (original)
+++ vmkit/trunk/lib/j3/VMCore/Jnjvm.cpp Thu Apr 25 12:17:21 2013
@@ -44,6 +44,27 @@ const char* Jnjvm::dirSeparator = "/";
 const char* Jnjvm::envSeparator = ":";
 const unsigned int Jnjvm::Magic = 0xcafebabe;
 
+/**
+ * In JVM specification, the virtual machine should execute some code.
+ * See Runtime.addShutdownHook
+ * In GNUClasspath the default behavior when the program call System.exit
+ * is to execute such a code.
+ * Hence, the only mission of this thread is to call System.exit when
+ * the user press Ctrl_C
+ */
+void threadToDetectCtrl_C(vmkit::Thread* th) {
+	while (!vmkit::finishForCtrl_C) {
+		vmkit::lockForCtrl_C.lock();
+		vmkit::condForCtrl_C.wait(&vmkit::lockForCtrl_C);
+		vmkit::lockForCtrl_C.unlock(th);
+	}
+	fprintf(stderr, "Crazy stuff\n");
+	JavaThread* kk = (JavaThread*)th;
+	UserClass* cl = kk->getJVM()->upcalls->SystemClass;
+	kk->getJVM() -> upcalls->SystemExit->invokeIntStatic(kk->getJVM(), cl, 0);
+}
+
+
 /// initialiseClass - Java class initialization. Java specification §2.17.5.
 
 void UserClass::initialiseClass(Jnjvm* vm) {
@@ -1320,6 +1341,9 @@ void Jnjvm::runApplication(int argc, cha
   argumentsInfo.argv = argv;
   mainThread = new JavaThread(this);
   mainThread->start((void (*)(vmkit::Thread*))mainJavaStart);
+
+  JavaThread* th = new JavaThread(this);
+  th->start((void (*)(vmkit::Thread*))threadToDetectCtrl_C);
 }
 
 Jnjvm::Jnjvm(vmkit::BumpPtrAllocator& Alloc,





More information about the vmkit-commits mailing list