[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