[vmkit-commits] [vmkit] r111781 - in /vmkit/trunk: include/mvm/Threads/Locks.h lib/Mvm/CommonThread/ctlock.cpp

Nicolas Geoffray nicolas.geoffray at lip6.fr
Sun Aug 22 10:46:47 PDT 2010


Author: geoffray
Date: Sun Aug 22 12:46:47 2010
New Revision: 111781

URL: http://llvm.org/viewvc/llvm-project?rev=111781&view=rev
Log:
Re-organize the thin lock code for better readability and race fixes.


Modified:
    vmkit/trunk/include/mvm/Threads/Locks.h
    vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp

Modified: vmkit/trunk/include/mvm/Threads/Locks.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Threads/Locks.h?rev=111781&r1=111780&r2=111781&view=diff
==============================================================================
--- vmkit/trunk/include/mvm/Threads/Locks.h (original)
+++ vmkit/trunk/include/mvm/Threads/Locks.h Sun Aug 22 12:46:47 2010
@@ -213,8 +213,6 @@
   /// lock.
   static bool owner(gc* object);
 
-  static mvm::Thread* getOwner(gc* object);
-
   /// getFatLock - Get the fat lock is the lock is a fat lock, 0 otherwise.
   static FatLock* getFatLock(gc* object);
 };

Modified: vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp?rev=111781&r1=111780&r2=111781&view=diff
==============================================================================
--- vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp (original)
+++ vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp Sun Aug 22 12:46:47 2010
@@ -189,13 +189,18 @@
   return res;
 }
 
-
 void ThinLock::overflowThinLock(gc* object) {
   llvm_gcroot(object, 0);
   FatLock* obj = Thread::get()->MyVM->allocateFatLock(object);
   obj->acquireAll(object, (ThinCountMask >> ThinCountShift) + 1);
-  uintptr_t oldLock = object->header;
-  object->header = obj->getID() | (oldLock & NonLockBitsMask);
+  uintptr_t oldValue = 0;
+  uintptr_t newValue = 0;
+  uintptr_t yieldedValue = 0;
+  do {
+    oldValue = object->header;
+    newValue = obj->getID() | (oldValue & NonLockBitsMask);
+    yieldedValue = __sync_val_compare_and_swap(&(object->header), oldValue, newValue);
+  } while (yieldedValue != oldValue);
 }
  
 /// initialise - Initialise the value of the lock.
@@ -218,8 +223,14 @@
     FatLock* obj = Thread::get()->MyVM->allocateFatLock(object);
     uint32 count = (object->header & ThinCountMask) >> ThinCountShift;
     obj->acquireAll(object, count + 1);
-    uintptr_t oldLock = object->header;
-    object->header = obj->getID() | (oldLock & NonLockBitsMask);
+    uintptr_t oldValue = 0;
+    uintptr_t newValue = 0;
+    uintptr_t yieldedValue = 0;
+    do {
+      oldValue = object->header;
+      newValue = obj->getID() | (oldValue & NonLockBitsMask);
+      yieldedValue = __sync_val_compare_and_swap(&(object->header), oldValue, newValue);
+    } while (yieldedValue != oldValue);
     return obj;
   } else {
     FatLock* res = Thread::get()->MyVM->getFatLockFromID(object->header);
@@ -230,51 +241,70 @@
 
 void ThinLock::acquire(gc* object) {
   llvm_gcroot(object, 0);
-start:
   uint64_t id = mvm::Thread::get()->getThreadID();
-  uintptr_t oldValue = object->header;
-  uintptr_t newValue = id | (oldValue & NonLockBitsMask);
-  uintptr_t val = __sync_val_compare_and_swap(&object->header, oldValue & NonLockBitsMask,
-                                              newValue);
-
-  if (val != (oldValue & NonLockBitsMask)) {
-    //fat!
-    if (!(val & FatMask)) {
-      if ((val & Thread::IDMask) == id) {
-        if ((val & ThinCountMask) != ThinCountMask) {
-          object->header += ThinCountAdd;
-        } else {
-          overflowThinLock(object);
-        }
-      } else {
-        FatLock* obj = Thread::get()->MyVM->allocateFatLock(object);
-        uintptr_t val = obj->getID();
-loop:
-        while (object->header & ~NonLockBitsMask) {
-          if (object->header & FatMask) {
-            obj->deallocate();
-            goto end;
-          }
-          else mvm::Thread::yield();
-        }
-        
+  uintptr_t oldValue = 0;
+  uintptr_t newValue = 0;
+  uintptr_t yieldedValue = 0;
+  do {
+    oldValue = object->header & NonLockBitsMask;
+    newValue = oldValue | id;
+    yieldedValue = __sync_val_compare_and_swap(&(object->header), oldValue, newValue);
+  } while ((object->header & ~NonLockBitsMask) == 0);
+
+  if (yieldedValue == oldValue) {
+    assert(owner(object) && "Not owner after quitting acquire!");
+    return;
+  }
+  
+  if ((yieldedValue & Thread::IDMask) == id) {
+    assert(owner(object) && "Inconsistent lock");
+    if ((yieldedValue & ThinCountMask) != ThinCountMask) {
+      do {
         oldValue = object->header;
-        newValue = val | (oldValue & NonLockBitsMask);
-        uintptr_t test = __sync_val_compare_and_swap(&object->header,
-                                                     oldValue & NonLockBitsMask,
-                                                      newValue);
-        if (test != (oldValue & NonLockBitsMask)) goto loop;
-        if (!obj->acquire(object)) goto start;
-      }
+        newValue = oldValue + ThinCountAdd;
+        yieldedValue = __sync_val_compare_and_swap(&(object->header), oldValue, newValue);
+      } while (oldValue != yieldedValue);
     } else {
-end:
+      overflowThinLock(object);
+    }
+    assert(owner(object) && "Not owner after quitting acquire!");
+    return;
+  }
+      
+  while (true) {
+    if (object->header & FatMask) {
       FatLock* obj = Thread::get()->MyVM->getFatLockFromID(object->header);
-      if (obj) {
-        if (!obj->acquire(object)) goto start;
+      if (obj != NULL) {
+        if (obj->acquire(object)) {
+          break;
+        }
+      }
+    }
+    
+    while (object->header & ~NonLockBitsMask) {
+      if (object->header & FatMask) {
+        break;
       } else {
-        goto start;
+        mvm::Thread::yield();
       }
     }
+    
+    if ((object->header & ~NonLockBitsMask) == 0) {
+      FatLock* obj = Thread::get()->MyVM->allocateFatLock(object);
+      do {
+        oldValue = object->header & NonLockBitsMask;
+        newValue = oldValue | obj->getID();
+        yieldedValue = __sync_val_compare_and_swap(&object->header, oldValue, newValue);
+      } while ((object->header & ~NonLockBitsMask) == 0);
+
+      if (oldValue != yieldedValue) {
+        assert((getFatLock(object) != obj) && "Inconsistent lock");
+        obj->deallocate();
+      } else {
+        assert((getFatLock(object) == obj) && "Inconsistent lock");
+      }
+      assert(!owner(object) && "Inconsistent lock");
+    }
   }
 
   assert(owner(object) && "Not owner after quitting acquire!");
@@ -285,14 +315,26 @@
   llvm_gcroot(object, 0);
   assert(owner(object) && "Not owner when entering release!");
   uint64 id = mvm::Thread::get()->getThreadID();
+  uintptr_t oldValue = 0;
+  uintptr_t newValue = 0;
+  uintptr_t yieldedValue = 0;
   if ((object->header & ~NonLockBitsMask) == id) {
-    object->header = object->header & NonLockBitsMask;
+    do {
+      oldValue = object->header;
+      newValue = oldValue & NonLockBitsMask;
+      yieldedValue = __sync_val_compare_and_swap(&object->header, oldValue, newValue);
+    } while (yieldedValue != oldValue);
   } else if (object->header & FatMask) {
     FatLock* obj = Thread::get()->MyVM->getFatLockFromID(object->header);
     assert(obj && "Lock deallocated while held.");
     obj->release(object);
   } else {
-    object->header -= ThinCountAdd;
+    assert(((object->header & ThinCountMask) > 0) && "Inconsistent state");    
+    do {
+      oldValue = object->header;
+      newValue = oldValue - ThinCountAdd;
+      yieldedValue = __sync_val_compare_and_swap(&(object->header), oldValue, newValue);
+    } while (yieldedValue != oldValue);
   }
 }
 
@@ -302,7 +344,7 @@
   llvm_gcroot(object, 0);
   if (object->header & FatMask) {
     FatLock* obj = Thread::get()->MyVM->getFatLockFromID(object->header);
-    if (obj) return obj->owner();
+    if (obj != NULL) return obj->owner();
   } else {
     uint64 id = mvm::Thread::get()->getThreadID();
     if ((object->header & Thread::IDMask) == id) return true;
@@ -310,17 +352,6 @@
   return false;
 }
 
-mvm::Thread* ThinLock::getOwner(gc* object) {
-  llvm_gcroot(object, 0);
-  if (object->header & FatMask) {
-    FatLock* obj = Thread::get()->MyVM->getFatLockFromID(object->header);
-    if (obj) return obj->getOwner();
-    return 0;
-  } else {
-    return (mvm::Thread*)(object->header & mvm::Thread::IDMask);
-  }
-}
-
 /// getFatLock - Get the fat lock is the lock is a fat lock, 0 otherwise.
 FatLock* ThinLock::getFatLock(gc* object) {
   llvm_gcroot(object, 0);





More information about the vmkit-commits mailing list