[vmkit-commits] [vmkit] r109688 - in /vmkit/trunk: include/debug.h include/mvm/Threads/CollectionRV.h include/mvm/Threads/Thread.h include/mvm/VirtualMachine.h lib/Mvm/CommonThread/CollectionRV.cpp lib/Mvm/CommonThread/ctthread.cpp
Nicolas Geoffray
nicolas.geoffray at lip6.fr
Wed Jul 28 16:04:40 PDT 2010
Author: geoffray
Date: Wed Jul 28 18:04:40 2010
New Revision: 109688
URL: http://llvm.org/viewvc/llvm-project?rev=109688&view=rev
Log:
Rewrite CollectionRV with two classes: one for uncooperative mode, one for cooperative mode.
Modified:
vmkit/trunk/include/debug.h
vmkit/trunk/include/mvm/Threads/CollectionRV.h
vmkit/trunk/include/mvm/Threads/Thread.h
vmkit/trunk/include/mvm/VirtualMachine.h
vmkit/trunk/lib/Mvm/CommonThread/CollectionRV.cpp
vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp
Modified: vmkit/trunk/include/debug.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/debug.h?rev=109688&r1=109687&r2=109688&view=diff
==============================================================================
--- vmkit/trunk/include/debug.h (original)
+++ vmkit/trunk/include/debug.h Wed Jul 28 18:04:40 2010
@@ -70,6 +70,7 @@
abort(); } \
#define ABORT() UNIMPLEMENTED()
+#define UNREACHABLE() ABORT()
#define ASSERT(cond) { \
if (!cond) ABORT(); } \
Modified: vmkit/trunk/include/mvm/Threads/CollectionRV.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Threads/CollectionRV.h?rev=109688&r1=109687&r2=109688&view=diff
==============================================================================
--- vmkit/trunk/include/mvm/Threads/CollectionRV.h (original)
+++ vmkit/trunk/include/mvm/Threads/CollectionRV.h Wed Jul 28 18:04:40 2010
@@ -17,7 +17,7 @@
namespace mvm {
class CollectionRV {
-
+protected:
/// _lockRV - Lock for synchronization.
LockNormal _lockRV;
@@ -30,26 +30,11 @@
/// nbJoined - Number of threads that joined the rendezvous.
unsigned nbJoined;
- /// cooperative - Is the rendez-vous cooperative?
- bool cooperative;
-
- /// rendezvousNb - The identifier of the rendez-vous.
- unsigned rendezvousNb;
-
-public:
-
+public:
CollectionRV() {
- rendezvousNb = 0;
nbJoined = 0;
-#ifdef WITH_LLVM_GCC
- cooperative = true;
-#else
- cooperative = false;
-#endif
}
- bool isCooperative() { return cooperative; }
-
void lockRV() { _lockRV.lock(); }
void unlockRV() { _lockRV.unlock(); }
@@ -65,20 +50,38 @@
unlockRV();
mvm::Thread::get()->inRV = false;
}
-
- void finishRV();
- void collectorGo() { condInitiator.broadcast(); }
+ void another_mark();
- void another_mark() { nbJoined++; }
+ virtual void finishRV() = 0;
+ virtual void synchronize() = 0;
+ virtual void join() = 0;
+ virtual void joinAfterUncooperative() = 0;
+ virtual void joinBeforeUncooperative() = 0;
+};
+
+class CooperativeCollectionRV : public CollectionRV {
+public:
+ void finishRV();
void synchronize();
void join();
+ void joinAfterUncooperative();
+ void joinBeforeUncooperative();
+};
+
+class UncooperativeCollectionRV : public CollectionRV {
+public:
+ void finishRV();
+ void synchronize();
- unsigned getNumber() { return rendezvousNb; }
+ void join();
+ void joinAfterUncooperative();
+ void joinBeforeUncooperative();
};
+
}
#endif
Modified: vmkit/trunk/include/mvm/Threads/Thread.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Threads/Thread.h?rev=109688&r1=109687&r2=109688&view=diff
==============================================================================
--- vmkit/trunk/include/mvm/Threads/Thread.h (original)
+++ vmkit/trunk/include/mvm/Threads/Thread.h Wed Jul 28 18:04:40 2010
@@ -231,10 +231,6 @@
///
virtual void internalClearException() {}
- /// joinRV - Join a rendezvous.
- ///
- void joinRV();
-
public:
/// tracer - Does nothing. Used for child classes which may defined
@@ -244,6 +240,9 @@
void* getLastSP() { return lastSP; }
void setLastSP(void* V) { lastSP = V; }
+
+ void joinRVBeforeEnter();
+ void joinRVAfterLeave();
void enterUncooperativeCode(unsigned level = 0) __attribute__ ((noinline)) {
if (isMvmThread()) {
@@ -253,7 +252,7 @@
void* temp = __builtin_frame_address(0);
while (level--) temp = ((void**)temp)[0];
lastSP = temp;
- if (doYield) joinRV();
+ if (doYield) joinRVBeforeEnter();
assert(lastSP && "No last SP when entering uncooperative code");
}
}
@@ -264,7 +263,7 @@
if (!inRV) {
assert(!lastSP && "SP already set when entering uncooperative code");
lastSP = SP;
- if (doYield) joinRV();
+ if (doYield) joinRVBeforeEnter();
assert(lastSP && "No last SP when entering uncooperative code");
}
}
@@ -274,13 +273,9 @@
if (isMvmThread()) {
if (!inRV) {
assert(lastSP && "No last SP when leaving uncooperative code");
- // Check to see if a rendezvous has been set while being in native code.
- if (doYield) joinRV();
- // Clear lastSP. If a rendezvous happens there, the thread will join it
- // in the next iteration and set lastSP.
lastSP = 0;
// A rendezvous has just been initiated, join it.
- if (doYield) joinRV();
+ if (doYield) joinRVAfterLeave();
assert(!lastSP && "SP has a value after leaving uncooperative code");
}
}
Modified: vmkit/trunk/include/mvm/VirtualMachine.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/VirtualMachine.h?rev=109688&r1=109687&r2=109688&view=diff
==============================================================================
--- vmkit/trunk/include/mvm/VirtualMachine.h (original)
+++ vmkit/trunk/include/mvm/VirtualMachine.h Wed Jul 28 18:04:40 2010
@@ -510,7 +510,11 @@
/// rendezvous - The rendezvous implementation for garbage collection.
///
- CollectionRV rendezvous;
+#ifdef WITH_LLVM_GCC
+ CooperativeCollectionRV rendezvous;
+#else
+ UncooperativeCollectionRV rendezvous;
+#endif
StartEndFunctionMap RuntimeFunctions;
Modified: vmkit/trunk/lib/Mvm/CommonThread/CollectionRV.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/CommonThread/CollectionRV.cpp?rev=109688&r1=109687&r2=109688&view=diff
==============================================================================
--- vmkit/trunk/lib/Mvm/CommonThread/CollectionRV.cpp (original)
+++ vmkit/trunk/lib/Mvm/CommonThread/CollectionRV.cpp Wed Jul 28 18:04:40 2010
@@ -12,15 +12,25 @@
#include "mvm/VirtualMachine.h"
#include "mvm/Threads/CollectionRV.h"
+#include "debug.h"
+
using namespace mvm;
+void CollectionRV::another_mark() {
+ mvm::Thread* th = mvm::Thread::get();
+ assert(th->getLastSP() != NULL);
+ assert(nbJoined < th->MyVM->NumberOfThreads);
+ nbJoined++;
+ if (nbJoined == th->MyVM->NumberOfThreads) {
+ condInitiator.broadcast();
+ }
+}
+
void CollectionRV::waitEndOfRV() {
mvm::Thread* th = mvm::Thread::get();
- unsigned cm = rendezvousNb;
+ assert(th->getLastSP() != NULL);
- if (nbJoined == th->MyVM->NumberOfThreads) collectorGo();
-
- while (rendezvousNb == cm) {
+ while (th->doYield) {
condEndRV.wait(&_lockRV);
}
}
@@ -28,107 +38,140 @@
void CollectionRV::waitRV() {
mvm::Thread* self = mvm::Thread::get();
// Add myself.
- another_mark();
+ nbJoined++;
- while (nbJoined < self->MyVM->NumberOfThreads)
+ while (nbJoined != self->MyVM->NumberOfThreads) {
condInitiator.wait(&_lockRV);
-
+ }
}
-void CollectionRV::synchronize() {
-
+void CooperativeCollectionRV::synchronize() {
+ assert(nbJoined == 0);
mvm::Thread* self = mvm::Thread::get();
- assert(self && "No thread local data for this thread");
- self->inRV = true;
-
// Lock thread lock, so that we can traverse the thread list safely. This will
// be released on finishRV.
self->MyVM->ThreadLock.lock();
- if (cooperative) {
-
- mvm::Thread* cur = self;
- do {
- cur->joinedRV = false;
- cur->doYield = true;
- cur = (mvm::Thread*)cur->next();
- } while (cur != self);
-
- // Lookup currently blocked threads.
- for (cur = (mvm::Thread*)self->next(); cur != self;
- cur = (mvm::Thread*)cur->next()) {
- if (cur->getLastSP()) {
- another_mark();
- cur->joinedRV = true;
- }
- }
-
- } else {
- mvm::Thread* self = mvm::Thread::get();
- self->joinedRV = false;
- assert(self && "No thread local data for this thread");
-
- for (mvm::Thread* cur = (mvm::Thread*)self->next(); cur != self;
- cur = (mvm::Thread*)cur->next()) {
- cur->joinedRV = false;
- cur->killForRendezvous();
+ mvm::Thread* cur = self;
+ do {
+ assert(!cur->doYield);
+ cur->doYield = true;
+ assert(!cur->joinedRV);
+ cur = (mvm::Thread*)cur->next();
+ } while (cur != self);
+
+ self->joinedRV = true;
+ // Lookup currently blocked threads.
+ for (cur = (mvm::Thread*)self->next(); cur != self;
+ cur = (mvm::Thread*)cur->next()) {
+ if (cur->getLastSP()) {
+ nbJoined++;
+ cur->joinedRV = true;
}
-
}
// And wait for other threads to finish.
waitRV();
+
+ // Unlock, so that threads in uncooperative code that go back to cooperative
+ // code can set back their lastSP.
+ unlockRV();
+}
+
+void UncooperativeCollectionRV::synchronize() {
+ assert(nbJoined == 0);
+ mvm::Thread* self = mvm::Thread::get();
+ // Lock thread lock, so that we can traverse the thread list safely. This will
+ // be released on finishRV.
+ self->MyVM->ThreadLock.lock();
+
+ for (mvm::Thread* cur = (mvm::Thread*)self->next(); cur != self;
+ cur = (mvm::Thread*)cur->next()) {
+ cur->killForRendezvous();
+ }
+
+ // And wait for other threads to finish.
+ waitRV();
+
+ // Unlock, so that threads in uncooperative code that go back to cooperative
+ // code can set back their lastSP.
unlockRV();
}
-void CollectionRV::join() {
+
+void UncooperativeCollectionRV::join() {
mvm::Thread* th = mvm::Thread::get();
th->inRV = true;
- bool changed = false;
-
+
lockRV();
+ void* old = th->getLastSP();
+ th->setLastSP(FRAME_PTR());
+ another_mark();
+ waitEndOfRV();
+ th->setLastSP(old);
+ unlockRV();
- if (isCooperative() && !th->doYield) {
- // I was previously blocked, and I'm running late: someone else collected
- // my stack, and the GC has finished already. Just unlock and return.
- unlockRV();
- th->inRV = false;
- return;
- }
-
- // I woke up while a GC was happening, and no-one has listed me yet.
- if (!th->joinedRV) {
- another_mark();
- th->joinedRV = true;
- }
-
- // lastSP may not be set in two cases:
- // (1) The thread was interrupted while executing regular code (ie cooperative
- // code).
- // (2) The thread left uncooperative code and has just cleared lastSP.
- if (!th->getLastSP()) {
- changed = true;
- th->setLastSP(FRAME_PTR());
- }
+ th->inRV = false;
+}
- assert(th->getLastSP() && "Joined without giving a SP");
-
- do {
- // Wait for the rendezvous to finish.
- waitEndOfRV();
- // If we wake up here and doYield is set, this means that a new GC is
- // happening, so join it.
- } while (th->doYield);
+void CooperativeCollectionRV::join() {
+ mvm::Thread* th = mvm::Thread::get();
+ assert(th->doYield && "No yield");
+ assert((th->getLastSP() == NULL) && "SP present in cooperative code");
+
+ th->inRV = true;
- if (changed) th->setLastSP(0);
-
- // Unlock after modifying lastSP, because lastSP is also read by the
- // rendezvous initiator.
+ lockRV();
+ th->setLastSP(FRAME_PTR());
+ th->joinedRV = true;
+ another_mark();
+ waitEndOfRV();
+ th->setLastSP(0);
unlockRV();
- // The rendezvous is finished. Set inRV to false.
th->inRV = false;
+}
+
+void CooperativeCollectionRV::joinBeforeUncooperative() {
+ mvm::Thread* th = mvm::Thread::get();
+ assert((th->getLastSP() != NULL) &&
+ "SP not set before entering uncooperative code");
+
+ th->inRV = true;
+ lockRV();
+ if (th->doYield) {
+ if (!th->joinedRV) {
+ th->joinedRV = true;
+ another_mark();
+ }
+ waitEndOfRV();
+ }
+ unlockRV();
+
+ th->inRV = false;
+}
+
+void CooperativeCollectionRV::joinAfterUncooperative() {
+ mvm::Thread* th = mvm::Thread::get();
+ assert((th->getLastSP() == NULL) &&
+ "SP set after entering uncooperative code");
+
+ th->inRV = true;
+
+ lockRV();
+ if (th->doYield) {
+ th->setLastSP(FRAME_PTR());
+ if (!th->joinedRV) {
+ th->joinedRV = true;
+ another_mark();
+ }
+ waitEndOfRV();
+ th->setLastSP(NULL);
+ }
+ unlockRV();
+
+ th->inRV = false;
}
extern "C" void conditionalSafePoint() {
@@ -136,21 +179,42 @@
th->MyVM->rendezvous.join();
}
-void CollectionRV::finishRV() {
+void CooperativeCollectionRV::finishRV() {
+ lockRV();
- mvm::Thread* self = mvm::Thread::get();
- if (cooperative) {
- mvm::Thread* initiator = mvm::Thread::get();
- mvm::Thread* cur = initiator;
- do {
- cur->doYield = false;
- cur = (mvm::Thread*)cur->next();
- } while (cur != initiator);
- }
+ mvm::Thread* initiator = mvm::Thread::get();
+ mvm::Thread* cur = initiator;
+ do {
+ assert(cur->doYield && "Inconsistent state");
+ assert(cur->joinedRV && "Inconsistent state");
+ cur->doYield = false;
+ cur->joinedRV = false;
+ cur = (mvm::Thread*)cur->next();
+ } while (cur != initiator);
+ assert(nbJoined == initiator->MyVM->NumberOfThreads && "Inconsistent state");
nbJoined = 0;
- rendezvousNb++;
+ initiator->MyVM->ThreadLock.unlock();
condEndRV.broadcast();
- self->inRV = false;
- self->MyVM->ThreadLock.unlock();
+ unlockRV();
+ initiator->inRV = false;
+}
+
+void UncooperativeCollectionRV::finishRV() {
+ lockRV();
+ mvm::Thread* initiator = mvm::Thread::get();
+ assert(nbJoined == initiator->MyVM->NumberOfThreads && "Inconsistent state");
+ nbJoined = 0;
+ initiator->MyVM->ThreadLock.unlock();
+ condEndRV.broadcast();
+ unlockRV();
+ initiator->inRV = false;
+}
+
+void UncooperativeCollectionRV::joinAfterUncooperative() {
+ UNREACHABLE();
+}
+
+void UncooperativeCollectionRV::joinBeforeUncooperative() {
+ UNREACHABLE();
}
Modified: vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp?rev=109688&r1=109687&r2=109688&view=diff
==============================================================================
--- vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp (original)
+++ vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp Wed Jul 28 18:04:40 2010
@@ -41,13 +41,19 @@
void Thread::yield(void) {
Thread* th = mvm::Thread::get();
if (th->isMvmThread()) {
- if (th->doYield && !th->inRV) th->joinRV();
+ if (th->doYield && !th->inRV) {
+ th->MyVM->rendezvous.join();
+ }
}
sched_yield();
}
-void Thread::joinRV() {
- MyVM->rendezvous.join();
+void Thread::joinRVBeforeEnter() {
+ MyVM->rendezvous.joinBeforeUncooperative();
+}
+
+void Thread::joinRVAfterLeave() {
+ MyVM->rendezvous.joinAfterUncooperative();
}
void Thread::startKnownFrame(KnownFrame& F) {
More information about the vmkit-commits
mailing list