[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