[vmkit-commits] [vmkit] r180485 - Implementing methods unpark/park in class sun.misc.Unsafe. Very important for performance in multithread-applications.

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


Author: peter.senna
Date: Thu Apr 25 12:15:33 2013
New Revision: 180485

URL: http://llvm.org/viewvc/llvm-project?rev=180485&view=rev
Log:
Implementing methods unpark/park in class sun.misc.Unsafe. Very important for performance in multithread-applications.
(cherry picked from commit 8a9e28bfb4101c4b7bbe9df45f820238decf764a)

Modified:
    vmkit/trunk/lib/j3/ClassLib/GNUClasspath/ClasspathVMThread.inc
    vmkit/trunk/lib/j3/ClassLib/Unsafe.inc
    vmkit/trunk/lib/j3/VMCore/JavaObject.cpp
    vmkit/trunk/lib/j3/VMCore/JavaThread.cpp
    vmkit/trunk/lib/j3/VMCore/JavaThread.h
    vmkit/trunk/lib/vmkit/CommonThread/ctlock.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=180485&r1=180484&r2=180485&view=diff
==============================================================================
--- vmkit/trunk/lib/j3/ClassLib/GNUClasspath/ClasspathVMThread.inc (original)
+++ vmkit/trunk/lib/j3/ClassLib/GNUClasspath/ClasspathVMThread.inc Thu Apr 25 12:15:33 2013
@@ -126,6 +126,7 @@ JavaObject* vmthread) {
   
   JavaThread* th = (JavaThread*)field->getInstanceObjectField(vmthread);
   th->lockingThread.interruptFlag = 1;
+  th->parkLock.interrupt();
   vmkit::FatLock* lock = th->lockingThread.waitsOn;
 
   // If the thread is blocked on a wait. We also verify nextWaiting in case
@@ -240,7 +241,7 @@ JavaObject* vmthread) {
     return obj;
   }
   else {
-  	switch (th->status) {
+  	switch (th->state) {
   		case vmkit::LockingThread::StateWaiting:
   			obj = vm->asciizToStr("WAITING");
   			return obj;

Modified: vmkit/trunk/lib/j3/ClassLib/Unsafe.inc
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/j3/ClassLib/Unsafe.inc?rev=180485&r1=180484&r2=180485&view=diff
==============================================================================
--- vmkit/trunk/lib/j3/ClassLib/Unsafe.inc (original)
+++ vmkit/trunk/lib/j3/ClassLib/Unsafe.inc Thu Apr 25 12:15:33 2013
@@ -484,12 +484,34 @@ JavaObject* unsafe, jlong ptr, jlong val
 //===--- Park/Unpark thread support ---------------------------------------===//
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_park(
 JavaObject* unsafe, jboolean isAbsolute, jlong time) {
-  // Nothing, for now.
+  llvm_gcroot(unsafe, 0);
+  JavaThread* thread = (JavaThread*)JavaThread::get();
+  thread->parkLock.park(isAbsolute, time);
 }
 
 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_unpark(
 JavaObject* unsafe, JavaObject* thread) {
-  // Nothing, for now.
+  llvm_gcroot(unsafe, 0);
+  llvm_gcroot(thread, 0);
+  JavaObject* vmthread;
+  llvm_gcroot(vmthread, 0);
+  Jnjvm* vm = JavaThread::get()->getJVM();
+  JavaField* field = vm->upcalls->vmdataVMThread;
+  JavaField* field2 = vm->upcalls->vmThread; 
+  
+  // It's possible that the thread to be interrupted has not finished
+  // its initialization. Wait until the initialization is done.
+  vmthread = field2->getInstanceObjectField(thread);
+  while (vmthread == 0) {
+  	JavaThread::yield();
+  	vmthread = field2->getInstanceObjectField(thread);
+  }
+  JavaThread* th = (JavaThread*)field->getInstanceObjectField(vmthread);
+  while (th == 0) {
+  	JavaThread::yield();
+  	th = (JavaThread*)field->getInstanceObjectField(vmthread);
+  }
+  th->parkLock.unpark();
 }
 
 //===--- Monitor support --------------------------------------------------===//

Modified: vmkit/trunk/lib/j3/VMCore/JavaObject.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/j3/VMCore/JavaObject.cpp?rev=180485&r1=180484&r2=180485&view=diff
==============================================================================
--- vmkit/trunk/lib/j3/VMCore/JavaObject.cpp (original)
+++ vmkit/trunk/lib/j3/VMCore/JavaObject.cpp Thu Apr 25 12:15:33 2013
@@ -84,9 +84,9 @@ void JavaObject::waitIntern(
     UNREACHABLE();
   }
 
-  thread->status = (timed)? vmkit::LockingThread::StateTimeWaiting: vmkit::LockingThread::StateWaiting;
+  thread->state = (timed)? vmkit::LockingThread::StateTimeWaiting: vmkit::LockingThread::StateWaiting;
   bool interrupted = thread->lockingThread.wait(self, table, info, timed);
-  thread->status = vmkit::LockingThread::StateRunning;
+  thread->state = vmkit::LockingThread::StateRunning;
 
   if (interrupted) {
     thread->getJVM()->interruptedException(self);
@@ -238,9 +238,9 @@ void JavaObject::overflowThinLock(JavaOb
 
 void JavaObject::acquire(JavaObject* self) {
   llvm_gcroot(self, 0);
-  JavaThread::get()->status = vmkit::LockingThread::StateBlocked;
+  JavaThread::get()->state = vmkit::LockingThread::StateBlocked;
   vmkit::ThinLock::acquire(self, JavaThread::get()->getJVM()->lockSystem);
-  JavaThread::get()->status = vmkit::LockingThread::StateRunning;
+  JavaThread::get()->state = vmkit::LockingThread::StateRunning;
 }
 
 void JavaObject::release(JavaObject* self) {

Modified: vmkit/trunk/lib/j3/VMCore/JavaThread.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/j3/VMCore/JavaThread.cpp?rev=180485&r1=180484&r2=180485&view=diff
==============================================================================
--- vmkit/trunk/lib/j3/VMCore/JavaThread.cpp (original)
+++ vmkit/trunk/lib/j3/VMCore/JavaThread.cpp Thu Apr 25 12:15:33 2013
@@ -31,6 +31,7 @@ JavaThread::JavaThread(vmkit::VirtualMac
   currentAddedReferences = NULL;
   javaThread = NULL;
   vmThread = NULL;
+  state = vmkit::LockingThread::StateRunning;
 }
 
 void JavaThread::initialise(JavaObject* thread, JavaObject* vmth) {
@@ -203,3 +204,96 @@ void JavaThread::throwNullPointerExcepti
 	MyVM->nullPointerException();
 	UNREACHABLE();
 }
+
+ParkLock::ParkLock() {
+	permit = 1;
+}
+
+ParkLock::~ParkLock() {
+
+}
+
+// Fill the structure t with the values from time
+// time is in nanoseconds
+void ParkLock::calculateTime(timeval* t, uint64_t time) {
+	uint64_t milli = time / 10;
+	//uint64_t microseconds = time; // /1000
+	//uint64_t seconds = microseconds / 1000000;
+	//microseconds %= 1000000;
+	t->tv_sec = milli / 1000;
+	t->tv_usec = (milli % 1000) * 1000 + time / 1000;
+}
+
+#include <sys/time.h>
+
+// Implementation of method park, see LockSupport.java
+// time is in nanoseconds if !isAboslute, otherwise it is in milliseconds
+void ParkLock::park(bool isAbsolute, uint64_t time) {
+	JavaThread* thread = (JavaThread*)vmkit::Thread::get();
+	lock.lock();
+		if (permit == 0){
+			permit = 1;
+			__sync_synchronize();
+			lock.unlock(thread);
+			return;
+		}
+		if (isAbsolute) {
+			fprintf(stderr, "PUTA MADRE QUE LO PARIO\n");
+			struct timeval  tv;
+			gettimeofday(&tv, NULL);
+			uint64_t l = tv.tv_sec*1000L + tv.tv_usec / 1000; // to milliseconds
+			if (time <= l) {
+				lock.unlock(thread);
+				return;
+			}
+			time = time - l;
+			time *= 1000000;	// to nanoseconds
+		}
+
+		if (time == 0) {
+			thread->setState(vmkit::LockingThread::StateWaiting);
+			permit = 2;
+			__sync_synchronize();
+			cond.wait(&lock);
+			permit = 1;
+		}
+		else {
+			timeval t;
+			calculateTime(&t, time);
+			thread->setState(vmkit::LockingThread::StateTimeWaiting);
+			permit = 2;
+			__sync_synchronize();
+			cond.timedWait(&lock, &t);
+			permit = 1;
+		}
+		thread->setState(vmkit::LockingThread::StateRunning);
+		__sync_synchronize();
+		//} catch (InterruptedException e) {
+		//		permit = 1;
+		//		th.interrupt();
+		//}
+	lock.unlock(thread);
+}
+
+void ParkLock::unpark() {
+	JavaThread* thread = (JavaThread*)vmkit::Thread::get();
+	lock.lock();
+		int p = permit;
+		if (p != 0) {
+			if (p == 2)
+				cond.signal();
+			else {
+				permit = 0;
+				__sync_synchronize();
+			}
+		}
+	lock.unlock(thread);
+}
+
+void ParkLock::interrupt() {
+	JavaThread* thread = (JavaThread*)vmkit::Thread::get();
+	lock.lock();
+		if (permit == 2)
+			cond.signal();
+	lock.unlock(thread);
+}

Modified: vmkit/trunk/lib/j3/VMCore/JavaThread.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/j3/VMCore/JavaThread.h?rev=180485&r1=180484&r2=180485&view=diff
==============================================================================
--- vmkit/trunk/lib/j3/VMCore/JavaThread.h (original)
+++ vmkit/trunk/lib/j3/VMCore/JavaThread.h Thu Apr 25 12:15:33 2013
@@ -56,6 +56,25 @@ class Jnjvm;
   th->enterUncooperativeCode(SP); \
   return; } \
 
+/// This is used to implement park/unpark behavior.
+/// The functionalities is the foundation for java.util.concurrency package
+class ParkLock {
+private:
+	vmkit::LockNormal lock;
+	vmkit::Cond cond;
+	int permit;
+
+
+	void calculateTime(timeval* t, uint64_t time);
+
+public:
+	ParkLock();
+	~ParkLock();
+
+	void park(bool isAbsolute, uint64_t time);
+	void unpark();
+	void interrupt();
+};
 
 /// JavaThread - This class is the internal representation of a Java thread.
 /// It maintains thread-specific information such as its state, the current
@@ -94,7 +113,11 @@ public:
   ///
   JNILocalReferences* localJNIRefs;
 
-  int status;
+  // State of this Thread
+  int state;
+
+  // Lock to implement park/unpark
+  ParkLock parkLock;
 
 
   JavaObject** pushJNIRef(JavaObject* obj) {
@@ -113,7 +136,7 @@ public:
   /// JavaThread - Empty constructor, used to get the VT.
   ///
   JavaThread() {
-	  status = vmkit::LockingThread::StateRunning;
+	  state = vmkit::LockingThread::StateRunning;
   }
 
   /// ~JavaThread - Delete any potential malloc'ed objects used by this thread.
@@ -211,7 +234,9 @@ public:
   /// the stack.
   ///
   uint32 getJavaFrameContext(void** buffer);
-  
+
+  inline void setState(int a) { state= a; }
+
 private:
   /// internalClearException - Clear the C++ and Java exceptions
   /// currently pending.

Modified: vmkit/trunk/lib/vmkit/CommonThread/ctlock.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/vmkit/CommonThread/ctlock.cpp?rev=180485&r1=180484&r2=180485&view=diff
==============================================================================
--- vmkit/trunk/lib/vmkit/CommonThread/ctlock.cpp (original)
+++ vmkit/trunk/lib/vmkit/CommonThread/ctlock.cpp Thu Apr 25 12:15:33 2013
@@ -184,7 +184,7 @@ int Cond::timedWait(Lock* l, struct time
                                    &timeout);
   th->leaveUncooperativeCode();
   
-  assert((!res || res == ETIMEDOUT) && "Error on timed wait");
+  //assert((!res || res == ETIMEDOUT) && "Error on timed wait");
   l->unsafeLock(n);
 
   return res;





More information about the vmkit-commits mailing list