Change the wait()/interrupt() implementation to not use a thread-local lock.
llvm-svn: 73170
diff --git a/vmkit/include/mvm/Threads/Locks.h b/vmkit/include/mvm/Threads/Locks.h
index 880a695..dbda2f9 100644
--- a/vmkit/include/mvm/Threads/Locks.h
+++ b/vmkit/include/mvm/Threads/Locks.h
@@ -157,7 +157,8 @@
virtual void lock();
virtual void unlock();
-
+ virtual int tryLock();
+
/// recursionCount - Get the number of times the lock has been locked.
///
int recursionCount() { return n; }
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMThread.cpp b/vmkit/lib/JnJVM/Classpath/ClasspathVMThread.cpp
index aa3b88f..683eb00 100644
--- a/vmkit/lib/JnJVM/Classpath/ClasspathVMThread.cpp
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMThread.cpp
@@ -105,23 +105,39 @@
Jnjvm* vm = JavaThread::get()->getJVM();
JavaObject* vmthread = (JavaObject*)_vmthread;
JavaField* field = vm->upcalls->vmdataVMThread;
+
// It's possible that the thread to be interrupted has not finished
// its initialization. Wait until the initialization is done.
while (field->getObjectField(vmthread) == 0)
mvm::Thread::yield();
JavaThread* th = (JavaThread*)field->getObjectField(vmthread);
- th->lock.lock();
th->interruptFlag = 1;
+ LockObj* lock = th->waitsOn;
- // here we could also raise a signal for interrupting I/O
- if (th->state == JavaThread::StateWaiting) {
+ // If the thread is blocked on a wait. We also verify nextWaiting in case
+ // the thread has been notified.
+ if (lock && th->nextWaiting) {
th->state = JavaThread::StateInterrupted;
- th->varcond.signal();
- }
- th->lock.unlock();
+ // Make sure the thread is waiting.
+ uint32 locked = 0;
+ while (true) {
+ locked = (lock->tryAcquire() == 0);
+ if (locked || (lock->getOwner() != th && lock->getOwner() != 0))
+ break;
+ else mvm::Thread::yield();
+ }
+
+ // Interrupt the thread.
+ th->varcond.signal();
+ // Release the lock if we acquired it.
+ if (locked) lock->release();
+ }
+
+ // Here we could also raise a signal for interrupting I/O
+
END_NATIVE_EXCEPTION
}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaObject.cpp b/vmkit/lib/JnJVM/VMCore/JavaObject.cpp
index f11dd50..c6eac26 100644
--- a/vmkit/lib/JnJVM/VMCore/JavaObject.cpp
+++ b/vmkit/lib/JnJVM/VMCore/JavaObject.cpp
@@ -37,15 +37,14 @@
if (owner()) {
LockObj * l = lock.changeToFatlock(this);
JavaThread* thread = JavaThread::get();
- mvm::Lock& mutexThread = thread->lock;
+ thread->waitsOn = l;
mvm::Cond& varcondThread = thread->varcond;
- mutexThread.lock();
if (thread->interruptFlag != 0) {
- mutexThread.unlock();
thread->interruptFlag = 0;
+ thread->waitsOn = 0;
thread->getJVM()->interruptedException(this);
- } else {
+ } else {
thread->state = JavaThread::StateWaiting;
if (l->firstThread) {
l->firstThread->prevWaiting->nextWaiting = thread;
@@ -64,19 +63,20 @@
"Inconsistent list");
bool timeout = false;
- uint32 recur = l->lock.unlockAll();
- if (timed) {
- timeout = varcondThread.timedWait(&mutexThread, info);
- } else {
- varcondThread.wait(&mutexThread);
+ if (!thread->interruptFlag) {
+ if (timed) {
+ timeout = varcondThread.timedWait(&l->lock, info);
+ } else {
+ varcondThread.wait(&l->lock);
+ }
}
+
bool interrupted = (thread->interruptFlag != 0);
- mutexThread.unlock();
- l->lock.lockAll(recur);
if (interrupted || timeout) {
+
if (thread->nextWaiting) {
if (l->firstThread != thread) {
thread->nextWaiting->prevWaiting = thread->prevWaiting;
@@ -94,10 +94,15 @@
}
thread->nextWaiting = 0;
thread->prevWaiting = 0;
+ } else {
+ assert(!thread->prevWaiting && "Inconstitent state");
+ // Notify lost, notify someone else.
+ notify();
}
}
-
+
thread->state = JavaThread::StateRunning;
+ thread->waitsOn = 0;
if (interrupted) {
thread->interruptFlag = 0;
@@ -125,11 +130,10 @@
JavaThread* cur = l->firstThread;
if (cur) {
do {
- cur->lock.lock();
if (cur->interruptFlag != 0) {
- cur->lock.unlock();
cur = cur->nextWaiting;
- } else if (cur->javaThread != 0) {
+ } else {
+ assert(cur->javaThread && "No java thread");
assert(cur->prevWaiting && cur->nextWaiting &&
"Inconsistent list");
if (cur != l->firstThread) {
@@ -149,10 +153,7 @@
cur->prevWaiting = 0;
cur->nextWaiting = 0;
cur->varcond.signal();
- cur->lock.unlock();
break;
- } else {
- cur->lock.unlock();
}
} while (cur != l->firstThread);
}
@@ -170,12 +171,10 @@
JavaThread* cur = l->firstThread;
if (cur) {
do {
- cur->lock.lock();
JavaThread* temp = cur->nextWaiting;
cur->prevWaiting = 0;
cur->nextWaiting = 0;
cur->varcond.signal();
- cur->lock.unlock();
cur = temp;
} while (cur != l->firstThread);
l->firstThread = 0;
diff --git a/vmkit/lib/JnJVM/VMCore/JavaObject.h b/vmkit/lib/JnJVM/VMCore/JavaObject.h
index 12accb8..498eb56 100644
--- a/vmkit/lib/JnJVM/VMCore/JavaObject.h
+++ b/vmkit/lib/JnJVM/VMCore/JavaObject.h
@@ -52,6 +52,12 @@
lock.lock();
}
+ /// tryAcquire - Tries to acquire the lock.
+ ///
+ int tryAcquire() {
+ return lock.tryLock();
+ }
+
/// acquireAll - Acquires the lock nb times.
void acquireAll(uint32 nb) {
lock.lockAll(nb);
diff --git a/vmkit/lib/JnJVM/VMCore/JavaThread.h b/vmkit/lib/JnJVM/VMCore/JavaThread.h
index bc70410..23eae7d 100644
--- a/vmkit/lib/JnJVM/VMCore/JavaThread.h
+++ b/vmkit/lib/JnJVM/VMCore/JavaThread.h
@@ -24,6 +24,7 @@
class Class;
class JavaObject;
class Jnjvm;
+class LockObj;
#define BEGIN_NATIVE_EXCEPTION(level) \
@@ -76,10 +77,6 @@
///
JavaObject* vmThread;
- /// lock - This lock is used when waiting or being notified or interrupted.
- ///
- mvm::LockNormal lock;
-
/// varcond - Condition variable when the thread needs to be awaken from
/// a wait.
///
@@ -97,6 +94,10 @@
///
JavaThread* prevWaiting;
+ /// waitsOn - The monitor on which the thread is waiting on.
+ ///
+ LockObj* waitsOn;
+
static const unsigned int StateRunning;
static const unsigned int StateWaiting;
static const unsigned int StateInterrupted;
diff --git a/vmkit/lib/Mvm/CommonThread/ctlock.cpp b/vmkit/lib/Mvm/CommonThread/ctlock.cpp
index b2a413e..7298bb5 100644
--- a/vmkit/lib/Mvm/CommonThread/ctlock.cpp
+++ b/vmkit/lib/Mvm/CommonThread/ctlock.cpp
@@ -81,6 +81,16 @@
++n;
}
+int LockRecursive::tryLock() {
+ int res = 0;
+ if (!selfOwner()) {
+ res = pthread_mutex_trylock((pthread_mutex_t*)&internalLock);
+ owner = mvm::Thread::get();
+ }
+ ++n;
+ return res;
+}
+
void LockRecursive::unlock() {
assert(selfOwner() && "Not owner when unlocking");
--n;