[vmkit-commits] [vmkit] r117221 - in /vmkit/branches/precise: Makefile.rules include/mvm/Threads/Locks.h include/mvm/Threads/ObjectLocks.h include/mvm/VirtualMachine.h lib/J3/Classpath/ClasspathVMThread.inc lib/J3/VMCore/JavaLocks.cpp lib/J3/VMCore/JavaLocks.h lib/J3/VMCore/JavaObject.cpp lib/J3/VMCore/JavaObject.h lib/J3/VMCore/JavaThread.cpp lib/J3/VMCore/JavaThread.h lib/J3/VMCore/Jnjvm.cpp lib/J3/VMCore/Jnjvm.h lib/J3/VMCore/VirtualTables.cpp lib/Mvm/CommonThread/ObjectLocks.cpp lib/Mvm/CommonThread/ctlock.cpp
Nicolas Geoffray
nicolas.geoffray at lip6.fr
Sun Oct 24 04:00:06 PDT 2010
Author: geoffray
Date: Sun Oct 24 06:00:06 2010
New Revision: 117221
URL: http://llvm.org/viewvc/llvm-project?rev=117221&view=rev
Log:
Refactor locking code, to put ThinLock/FatLock in CommonThread instead of J3.
Added:
vmkit/branches/precise/include/mvm/Threads/ObjectLocks.h
vmkit/branches/precise/lib/Mvm/CommonThread/ObjectLocks.cpp
Modified:
vmkit/branches/precise/Makefile.rules
vmkit/branches/precise/include/mvm/Threads/Locks.h
vmkit/branches/precise/include/mvm/VirtualMachine.h
vmkit/branches/precise/lib/J3/Classpath/ClasspathVMThread.inc
vmkit/branches/precise/lib/J3/VMCore/JavaLocks.cpp
vmkit/branches/precise/lib/J3/VMCore/JavaLocks.h
vmkit/branches/precise/lib/J3/VMCore/JavaObject.cpp
vmkit/branches/precise/lib/J3/VMCore/JavaObject.h
vmkit/branches/precise/lib/J3/VMCore/JavaThread.cpp
vmkit/branches/precise/lib/J3/VMCore/JavaThread.h
vmkit/branches/precise/lib/J3/VMCore/Jnjvm.cpp
vmkit/branches/precise/lib/J3/VMCore/Jnjvm.h
vmkit/branches/precise/lib/J3/VMCore/VirtualTables.cpp
vmkit/branches/precise/lib/Mvm/CommonThread/ctlock.cpp
Modified: vmkit/branches/precise/Makefile.rules
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/Makefile.rules?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/Makefile.rules (original)
+++ vmkit/branches/precise/Makefile.rules Sun Oct 24 06:00:06 2010
@@ -134,7 +134,7 @@
$(Verb) $(ANT) -buildfile $(PROJ_OBJ_ROOT)/mmtk/java/build.xml
$(Echo) Building $(BuildMode) $(JARNAME).jar $(notdir $@)
$(Verb) $(LOPT) -load=$(LibDir)/JITGCPass$(SHLIBEXT) -std-compile-opts -JITGCPass -f $(LibDir)/MMTKAlloc.bc -o $(LibDir)/MMTKAlloc.bc
- $(Verb) $(VMJC) -std-compile-opts $(ADDITIONAL_ARGS) -load=$(LibDir)/MMTKMagic$(SHLIBEXT) -LowerMagic -verify $(PROJ_OBJ_ROOT)/mmtk/java/$(JARNAME).jar -disable-exceptions -disable-cooperativegc -with-clinit=org/mmtk/vm/VM,org/mmtk/utility/*,org/mmtk/policy/*,org/j3/config/* -Dmmtk.hostjvm=org.j3.mmtk.Factory -o $(JARNAME).bc -Dmmtk.properties=$(PROJ_SRC_ROOT)/mmtk/java/vmkit.properties -disable-stubs -assume-compiled -llvm-lazy
+ $(Verb) $(VMJC) -std-compile-opts $(ADDITIONAL_ARGS) -load=$(LibDir)/MMTKMagic$(SHLIBEXT) -LowerMagic $(PROJ_OBJ_ROOT)/mmtk/java/$(JARNAME).jar -disable-exceptions -disable-cooperativegc -with-clinit=org/mmtk/vm/VM,org/mmtk/utility/*,org/mmtk/policy/*,org/j3/config/* -Dmmtk.hostjvm=org.j3.mmtk.Factory -o $(JARNAME).bc -Dmmtk.properties=$(PROJ_SRC_ROOT)/mmtk/java/vmkit.properties -disable-stubs -assume-compiled -llvm-lazy
$(Verb) $(LOPT) -load=$(LibDir)/MMTKMagic$(SHLIBEXT) -std-compile-opts -LowerJavaRT -f $(JARNAME).bc -o $(JARNAME)-optimized.bc
$(Verb) $(LLVMLD) -r -o $(LibDir)/FinalMMTk.bc $(LibDir)/MMTKAlloc.bc $(JARNAME)-optimized.bc $(LibDir)/MMTKRuntime.bc
$(Verb) $(LOPT) -std-compile-opts $(LibDir)/FinalMMTk.bc -o $(LibDir)/FinalMMTk.bc
Modified: vmkit/branches/precise/include/mvm/Threads/Locks.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/include/mvm/Threads/Locks.h?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/include/mvm/Threads/Locks.h (original)
+++ vmkit/branches/precise/include/mvm/Threads/Locks.h Sun Oct 24 06:00:06 2010
@@ -188,36 +188,6 @@
void lockAll(int count);
};
-class ThinLock {
-public:
-
- /// initialise - Initialise the value of the lock.
- ///
- static void initialise(gc* object);
-
- /// overflowThinlock - Change the lock of this object to a fat lock because
- /// we have reached 0xFF locks.
- static void overflowThinLock(gc* object);
-
- /// changeToFatlock - Change the lock of this object to a fat lock. The lock
- /// may be in a thin lock or fat lock state.
- static FatLock* changeToFatlock(gc* object);
-
- /// acquire - Acquire the lock.
- static void acquire(gc* object);
-
- /// release - Release the lock.
- static void release(gc* object);
-
- /// owner - Returns true if the curren thread is the owner of this object's
- /// lock.
- static bool owner(gc* object);
-
- /// getFatLock - Get the fat lock is the lock is a fat lock, 0 otherwise.
- static FatLock* getFatLock(gc* object);
-};
-
-
/// SpinLock - This class implements a spin lock. A spin lock is OK to use
/// when it is held during short period of times. It is CPU expensive
/// otherwise.
Added: vmkit/branches/precise/include/mvm/Threads/ObjectLocks.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/include/mvm/Threads/ObjectLocks.h?rev=117221&view=auto
==============================================================================
--- vmkit/branches/precise/include/mvm/Threads/ObjectLocks.h (added)
+++ vmkit/branches/precise/include/mvm/Threads/ObjectLocks.h Sun Oct 24 06:00:06 2010
@@ -0,0 +1,183 @@
+//===----------- ObjectLocks.h - Object based locks -----------------------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MVM_OBJECT_LOCKS_H
+#define MVM_OBJECT_LOCKS_H
+
+#include "ObjectHeader.h"
+#include "mvm/Allocator.h"
+#include "mvm/Threads/Cond.h"
+#include "mvm/Threads/Locks.h"
+#include "mvm/Threads/Thread.h"
+
+namespace mvm {
+
+class FatLock;
+class LockSystem;
+
+class LockingThread {
+public:
+ /// varcond - Condition variable when the thread needs to be awaken from
+ /// a wait.
+ ///
+ mvm::Cond varcond;
+
+ /// interruptFlag - Has this thread been interrupted?
+ ///
+ uint32 interruptFlag;
+
+ /// nextWaiting - Next thread waiting on the same monitor.
+ ///
+ LockingThread* nextWaiting;
+
+ /// prevWaiting - Previous thread waiting on the same monitor.
+ ///
+ LockingThread* prevWaiting;
+
+ /// waitsOn - The lock on which the thread is waiting on.
+ ///
+ FatLock* waitsOn;
+
+ static const unsigned int StateRunning = 0;
+ static const unsigned int StateWaiting = 1;
+ static const unsigned int StateInterrupted = 2;
+
+ /// state - The current state of this thread: Running, Waiting or Interrupted.
+ uint32 state;
+
+ LockingThread() {
+ interruptFlag = 0;
+ nextWaiting = NULL;
+ prevWaiting = NULL;
+ waitsOn = NULL;
+ state = StateRunning;
+ }
+
+ bool wait(gc* object, LockSystem& table, struct timeval* info, bool timed);
+ void notify(gc* object, LockSystem& table);
+ void notifyAll(gc* object, LockSystem& table);
+};
+
+
+class FatLock : public mvm::PermanentObject {
+private:
+ mvm::LockRecursive internalLock;
+ mvm::SpinLock spinLock;
+ uint32_t waitingThreads;
+ uint32_t lockingThreads;
+ LockingThread* firstThread;
+ gc* associatedObject;
+ uint32_t index;
+ FatLock* nextFreeLock;
+public:
+ FatLock(uint32_t index, gc* object);
+ uintptr_t getID();
+ int tryAcquire() { return internalLock.tryLock(); }
+ bool acquire(gc* object);
+ void acquireAll(gc* object, uint32_t count);
+ void release(gc* object, LockSystem& table);
+ mvm::Thread* getOwner();
+ bool owner();
+ gc* getAssociatedObject() { return associatedObject; }
+ gc** getAssociatedObjectPtr() { return &associatedObject; }
+
+ friend class LockSystem;
+ friend class LockingThread;
+};
+
+
+/// LockSystem - This class manages all Java locks used by the applications.
+/// Each JVM must own an instance of this class and allocate Java locks
+/// with it.
+///
+class LockSystem {
+ friend class FatLock;
+public:
+
+ // Fixed values. With these values, an index is on 18 bits.
+ static const uint32_t GlobalSize = 128;
+ static const uint32_t BitIndex = 11;
+ static const uint32_t IndexSize = 1 << BitIndex;
+ static const uint32_t BitMask = IndexSize - 1;
+ static const uint32_t MaxLocks = GlobalSize * IndexSize;
+
+ mvm::BumpPtrAllocator& allocator;
+
+ /// LockTable - The global table that will hold the locks. The table is
+ /// a two-dimensional array, and only one entry is created, so that
+ /// the lock system does not eat up all memory on startup.
+ ///
+ FatLock* ** LockTable;
+
+ /// currentIndex - The current index in the tables. Always incremented,
+ /// never decremented.
+ ///
+ uint32_t currentIndex;
+
+ /// freeLock - The list of locks that are allocated and available.
+ ///
+ FatLock* freeLock;
+
+ /// threadLock - Spin lock to protect the currentIndex field.
+ ///
+ mvm::SpinLock threadLock;
+
+ /// allocate - Allocate a FatLock.
+ ///
+ FatLock* allocate(gc* obj);
+
+ /// deallocate - Put a lock in the free list lock.
+ ///
+ void deallocate(FatLock* lock);
+
+ /// LockSystem - Default constructor. Initialize the table.
+ ///
+ LockSystem(mvm::BumpPtrAllocator& allocator);
+
+ /// getLock - Get a lock from an index in the table.
+ ///
+ FatLock* getLock(uint32_t index) {
+ return LockTable[index >> BitIndex][index & BitMask];
+ }
+
+ FatLock* getFatLockFromID(uintptr_t ID);
+};
+
+class ThinLock {
+public:
+
+ /// initialise - Initialise the value of the lock.
+ ///
+ static void initialise(gc* object, LockSystem& table);
+
+ /// overflowThinlock - Change the lock of this object to a fat lock because
+ /// we have reached 0xFF locks.
+ static void overflowThinLock(gc* object, LockSystem& table);
+
+ /// changeToFatlock - Change the lock of this object to a fat lock. The lock
+ /// may be in a thin lock or fat lock state.
+ static FatLock* changeToFatlock(gc* object, LockSystem& table);
+
+ /// acquire - Acquire the lock.
+ static void acquire(gc* object, LockSystem& table);
+
+ /// release - Release the lock.
+ static void release(gc* object, LockSystem& table);
+
+ /// owner - Returns true if the curren thread is the owner of this object's
+ /// lock.
+ static bool owner(gc* object, LockSystem& table);
+
+ /// getFatLock - Get the fat lock is the lock is a fat lock, 0 otherwise.
+ static FatLock* getFatLock(gc* object, LockSystem& table);
+};
+
+} // end namespace mvm
+
+#endif // MVM_OBJECT_LOCKS_H
Modified: vmkit/branches/precise/include/mvm/VirtualMachine.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/include/mvm/VirtualMachine.h?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/include/mvm/VirtualMachine.h (original)
+++ vmkit/branches/precise/include/mvm/VirtualMachine.h Sun Oct 24 06:00:06 2010
@@ -122,17 +122,6 @@
void scan(VirtualMachine* vm, uintptr_t closure);
};
-class FatLock : public mvm::PermanentObject {
-public:
- virtual void deallocate() = 0;
- virtual uintptr_t getID() = 0;
- virtual bool acquire(gc* object) = 0;
- virtual void acquireAll(gc* object, uint32_t count) = 0;
- virtual void release(gc* object) = 0;
- virtual mvm::Thread* getOwner() = 0;
- virtual bool owner() = 0;
-};
-
/// VirtualMachine - This class is the root of virtual machine classes. It
/// defines what a VM should be.
///
@@ -237,9 +226,6 @@
/// waitForExit - Wait until the virtual machine stops its execution.
virtual void waitForExit() = 0;
- virtual FatLock* allocateFatLock(gc* object) = 0;
- virtual FatLock* getFatLockFromID(uintptr_t header) = 0;
-
static j3::JnjvmClassLoader* initialiseJVM(j3::JavaCompiler* C,
bool dlLoad = true);
static VirtualMachine* createJVM(j3::JnjvmClassLoader* C = 0);
Modified: vmkit/branches/precise/lib/J3/Classpath/ClasspathVMThread.inc
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/Classpath/ClasspathVMThread.inc?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/Classpath/ClasspathVMThread.inc (original)
+++ vmkit/branches/precise/lib/J3/Classpath/ClasspathVMThread.inc Sun Oct 24 06:00:06 2010
@@ -112,13 +112,13 @@
mvm::Thread::yield();
JavaThread* th = (JavaThread*)field->getInstanceObjectField(vmthread);
- th->interruptFlag = 1;
- JavaLock* lock = th->waitsOn;
+ th->lockingThread.interruptFlag = 1;
+ mvm::FatLock* lock = th->lockingThread.waitsOn;
// 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;
+ if (lock && th->lockingThread.nextWaiting) {
+ th->lockingThread.state = mvm::LockingThread::StateInterrupted;
// Make sure the thread is waiting.
uint32 locked = 0;
@@ -130,10 +130,10 @@
}
// Interrupt the thread.
- th->varcond.signal();
+ th->lockingThread.varcond.signal();
// Release the lock if we acquired it.
- if (locked) lock->release(lock->getAssociatedObject());
+ if (locked) lock->release(lock->getAssociatedObject(), vm->lockSystem);
}
// Here we could also raise a signal for interrupting I/O
@@ -150,8 +150,8 @@
#endif
) {
JavaThread* th = JavaThread::get();
- uint32 interrupt = th->interruptFlag;
- th->interruptFlag = 0;
+ uint32 interrupt = th->lockingThread.interruptFlag;
+ th->lockingThread.interruptFlag = 0;
return (jboolean)interrupt;
}
@@ -168,7 +168,7 @@
Jnjvm* vm = JavaThread::get()->getJVM();
JavaField* field = vm->upcalls->vmdataVMThread;
JavaThread* th = (JavaThread*)field->getInstanceObjectField(vmthread);
- return (jboolean)th->interruptFlag;
+ return (jboolean)th->lockingThread.interruptFlag;
}
// Never throws.
Modified: vmkit/branches/precise/lib/J3/VMCore/JavaLocks.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/VMCore/JavaLocks.cpp?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/VMCore/JavaLocks.cpp (original)
+++ vmkit/branches/precise/lib/J3/VMCore/JavaLocks.cpp Sun Oct 24 06:00:06 2010
@@ -13,121 +13,3 @@
using namespace j3;
-JavaLock* Jnjvm::allocateFatLock(gc* obj) {
- llvm_gcroot(obj, 0);
- JavaLock* res = lockSystem.allocate((JavaObject*)obj);
- return res;
-}
-
-void JavaLock::deallocate() {
- Jnjvm* vm = JavaThread::get()->getJVM();
- vm->lockSystem.deallocate(this);
-}
-
-JavaLock* LockSystem::allocate(JavaObject* obj) {
-
- llvm_gcroot(obj, 0);
- JavaLock* res = 0;
- threadLock.lock();
-
- // Try the freeLock list.
- if (freeLock != NULL) {
- res = freeLock;
- freeLock = res->nextFreeLock;
- res->nextFreeLock = 0;
- assert(res->associatedObject == NULL);
- threadLock.unlock();
- res->associatedObject = obj;
- } else {
- // Get an index.
- uint32_t index = currentIndex++;
- if (index == MaxLocks) {
- fprintf(stderr, "Ran out of space for allocating locks");
- abort();
- }
-
- JavaLock** tab = LockTable[index >> BitIndex];
-
- if (tab == NULL) {
- tab = (JavaLock**)associatedVM->allocator.Allocate(
- IndexSize * sizeof(JavaLock*), "Index LockTable");
- }
- threadLock.unlock();
-
- // Allocate the lock.
- res = new(associatedVM->allocator, "Lock") JavaLock(index, obj);
-
- // Add the lock to the table.
- uint32_t internalIndex = index & BitMask;
- tab[internalIndex] = res;
- }
-
- // Return the lock.
- return res;
-}
-
-void LockSystem::deallocate(JavaLock* lock) {
- lock->associatedObject = NULL;
- threadLock.lock();
- lock->nextFreeLock = freeLock;
- freeLock = lock;
- threadLock.unlock();
-}
-
-LockSystem::LockSystem(Jnjvm* vm) {
- associatedVM = vm;
- LockTable = (JavaLock* **)
- vm->allocator.Allocate(GlobalSize * sizeof(JavaLock**), "Global LockTable");
- LockTable[0] = (JavaLock**)
- vm->allocator.Allocate(IndexSize * sizeof(JavaLock*), "Index LockTable");
- currentIndex = 0;
- freeLock = NULL;
-}
-
-uintptr_t JavaLock::getID() {
- return (index << mvm::NonLockBits) | mvm::FatMask;
-}
-
-JavaLock* Jnjvm::getFatLockFromID(uintptr_t ID) {
- if (ID & mvm::FatMask) {
- uint32_t index = (ID & ~mvm::FatMask) >> mvm::NonLockBits;
- JavaLock* res = lockSystem.getLock(index);
- return res;
- } else {
- return NULL;
- }
-}
-
-void JavaLock::release(gc* obj) {
- llvm_gcroot(obj, 0);
- assert(associatedObject && "No associated object when releasing");
- assert(associatedObject == obj && "Mismatch object in lock");
- if (!waitingThreads && !lockingThreads &&
- internalLock.recursionCount() == 1) {
- mvm::ThinLock::initialise(associatedObject);
- deallocate();
- }
- internalLock.unlock();
-}
-
-/// acquire - Acquires the internalLock.
-///
-bool JavaLock::acquire(gc* obj) {
- llvm_gcroot(obj, 0);
-
- spinLock.lock();
- lockingThreads++;
- spinLock.unlock();
-
- internalLock.lock();
-
- spinLock.lock();
- lockingThreads--;
- spinLock.unlock();
-
- if (associatedObject != obj) {
- internalLock.unlock();
- return false;
- }
- return true;
-}
Modified: vmkit/branches/precise/lib/J3/VMCore/JavaLocks.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/VMCore/JavaLocks.h?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/VMCore/JavaLocks.h (original)
+++ vmkit/branches/precise/lib/J3/VMCore/JavaLocks.h Sun Oct 24 06:00:06 2010
@@ -20,140 +20,6 @@
namespace j3 {
-class JavaObject;
-class JavaThread;
-class Jnjvm;
-
-class JavaLock : public mvm::FatLock {
-
-friend class JavaObject;
-friend class LockSystem;
-
-private:
- mvm::LockRecursive internalLock;
- mvm::SpinLock spinLock;
- uint32_t waitingThreads;
- uint32_t lockingThreads;
- JavaThread* firstThread;
- JavaObject* associatedObject;
- uint32_t index;
- JavaLock* nextFreeLock;
-
-public:
-
- JavaObject* getAssociatedObject() {
- return associatedObject;
- }
-
- JavaObject** getAssociatedObjectPtr() {
- return &associatedObject;
- }
-
- /// acquire - Acquires the internalLock.
- ///
- bool acquire(gc* obj);
-
- /// tryAcquire - Tries to acquire the lock.
- ///
- int tryAcquire() {
- return internalLock.tryLock();
- }
-
-
- /// acquireAll - Acquires the lock nb times.
- void acquireAll(gc* obj, uint32 nb) {
- internalLock.lockAll(nb);
- }
-
- /// release - Releases the internalLock.
- ///
- void release(gc* obj);
-
- /// owner - Returns if the current thread owns this internalLock.
- ///
- bool owner() {
- return internalLock.selfOwner();
- }
-
- /// getOwner - Get the owner of this internalLock.
- ///
- mvm::Thread* getOwner() {
- return internalLock.getOwner();
- }
-
- /// JavaLock - Default constructor.
- JavaLock(uint32_t i, JavaObject* a) {
- llvm_gcroot(a, 0);
- firstThread = 0;
- index = i;
- associatedObject = a;
- waitingThreads = 0;
- lockingThreads = 0;
- nextFreeLock = NULL;
- }
-
- void deallocate();
-
- uintptr_t getID();
-};
-
-/// LockSystem - This class manages all Java locks used by the applications.
-/// Each JVM must own an instance of this class and allocate Java locks
-/// with it.
-///
-class LockSystem {
- friend class JavaLock;
-public:
-
- // Fixed values. With these values, an index is on 18 bits.
- static const uint32_t GlobalSize = 128;
- static const uint32_t BitIndex = 11;
- static const uint32_t IndexSize = 1 << BitIndex;
- static const uint32_t BitMask = IndexSize - 1;
- static const uint32_t MaxLocks = GlobalSize * IndexSize;
-
- /// LockTable - The global table that will hold the locks. The table is
- /// a two-dimensional array, and only one entry is created, so that
- /// the lock system does not eat up all memory on startup.
- ///
- JavaLock* ** LockTable;
-
- /// currentIndex - The current index in the tables. Always incremented,
- /// never decremented.
- ///
- uint32_t currentIndex;
-
- /// freeLock - The list of locks that are allocated and available.
- ///
- JavaLock* freeLock;
-
- /// threadLock - Spin lock to protect the currentIndex field.
- ///
- mvm::SpinLock threadLock;
-
- /// associatedVM - The JVM associated with this lock system.
- ///
- Jnjvm* associatedVM;
-
- /// allocate - Allocate a JavaLock.
- ///
- JavaLock* allocate(JavaObject* obj);
-
- /// deallocate - Put a lock in the free list lock.
- ///
- void deallocate(JavaLock* lock);
-
- /// LockSystem - Default constructor. Initialize the table.
- ///
- LockSystem(Jnjvm* vm);
-
- /// getLock - Get a lock from an index in the table.
- ///
- JavaLock* getLock(uint32_t index) {
- return LockTable[index >> BitIndex][index & BitMask];
- }
-};
-
}
#endif
Modified: vmkit/branches/precise/lib/J3/VMCore/JavaObject.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/VMCore/JavaObject.cpp?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/VMCore/JavaObject.cpp (original)
+++ vmkit/branches/precise/lib/J3/VMCore/JavaObject.cpp Sun Oct 24 06:00:06 2010
@@ -17,6 +17,7 @@
#include "Jnjvm.h"
#include <jni.h>
+#include "debug.h"
using namespace j3;
@@ -63,103 +64,20 @@
void JavaObject::waitIntern(
JavaObject* self, struct timeval* info, bool timed) {
llvm_gcroot(self, 0);
- JavaLock* l = 0;
+ JavaThread* thread = JavaThread::get();
+ mvm::LockSystem& table = thread->getJVM()->lockSystem;
- if (owner(self)) {
- l = (JavaLock*)mvm::ThinLock::changeToFatlock(self);
- JavaThread* thread = JavaThread::get();
- thread->waitsOn = l;
- mvm::Cond& varcondThread = thread->varcond;
-
- if (thread->interruptFlag != 0) {
- thread->interruptFlag = 0;
- thread->waitsOn = 0;
- thread->getJVM()->interruptedException(self);
- } else {
- thread->state = JavaThread::StateWaiting;
- if (l->firstThread) {
- assert(l->firstThread->prevWaiting && l->firstThread->nextWaiting &&
- "Inconsistent list");
- if (l->firstThread->nextWaiting == l->firstThread) {
- l->firstThread->nextWaiting = thread;
- } else {
- l->firstThread->prevWaiting->nextWaiting = thread;
- }
- thread->prevWaiting = l->firstThread->prevWaiting;
- thread->nextWaiting = l->firstThread;
- l->firstThread->prevWaiting = thread;
- } else {
- l->firstThread = thread;
- thread->nextWaiting = thread;
- thread->prevWaiting = thread;
- }
- assert(thread->prevWaiting && thread->nextWaiting && "Inconsistent list");
- assert(l->firstThread->prevWaiting && l->firstThread->nextWaiting &&
- "Inconsistent list");
-
- bool timeout = false;
-
- l->waitingThreads++;
-
- while (!thread->interruptFlag && thread->nextWaiting) {
- if (timed) {
- timeout = varcondThread.timedWait(&l->internalLock, info);
- if (timeout) break;
- } else {
- varcondThread.wait(&l->internalLock);
- }
- }
-
- l->waitingThreads--;
-
- assert((!l->firstThread || (l->firstThread->prevWaiting &&
- l->firstThread->nextWaiting)) && "Inconsistent list");
-
- bool interrupted = (thread->interruptFlag != 0);
-
- if (interrupted || timeout) {
-
- if (thread->nextWaiting) {
- assert(thread->prevWaiting && "Inconsistent list");
- if (l->firstThread != thread) {
- thread->nextWaiting->prevWaiting = thread->prevWaiting;
- thread->prevWaiting->nextWaiting = thread->nextWaiting;
- assert(l->firstThread->prevWaiting &&
- l->firstThread->nextWaiting && "Inconsistent list");
- } else if (thread->nextWaiting == thread) {
- l->firstThread = 0;
- } else {
- l->firstThread = thread->nextWaiting;
- l->firstThread->prevWaiting = thread->prevWaiting;
- thread->prevWaiting->nextWaiting = l->firstThread;
- assert(l->firstThread->prevWaiting &&
- l->firstThread->nextWaiting && "Inconsistent list");
- }
- thread->nextWaiting = 0;
- thread->prevWaiting = 0;
- } else {
- assert(!thread->prevWaiting && "Inconstitent state");
- // Notify lost, notify someone else.
- notify(self);
- }
- } else {
- assert(!thread->prevWaiting && !thread->nextWaiting &&
- "Inconsistent state");
- }
-
- thread->state = JavaThread::StateRunning;
- thread->waitsOn = 0;
-
- if (interrupted) {
- thread->interruptFlag = 0;
- thread->getJVM()->interruptedException(self);
- }
- }
- } else {
- JavaThread::get()->getJVM()->illegalMonitorStateException(self);
+ if (!owner(self)) {
+ thread->getJVM()->illegalMonitorStateException(self);
+ UNREACHABLE();
+ }
+
+ bool interrupted = thread->lockingThread.wait(self, table, info, timed);
+
+ if (interrupted) {
+ thread->getJVM()->interruptedException(self);
+ UNREACHABLE();
}
-
- assert(owner(self) && "Not owner after wait");
}
void JavaObject::wait(JavaObject* self) {
@@ -174,72 +92,46 @@
void JavaObject::notify(JavaObject* self) {
llvm_gcroot(self, 0);
- JavaLock* l = 0;
+ JavaThread* thread = JavaThread::get();
+ mvm::LockSystem& table = thread->getJVM()->lockSystem;
- if (owner(self)) {
- l = (JavaLock*)mvm::ThinLock::getFatLock(self);
- if (l) {
- JavaThread* cur = l->firstThread;
- if (cur) {
- do {
- if (cur->interruptFlag != 0) {
- cur = cur->nextWaiting;
- } else {
- assert(cur->javaThread && "No java thread");
- assert(cur->prevWaiting && cur->nextWaiting &&
- "Inconsistent list");
- if (cur != l->firstThread) {
- cur->prevWaiting->nextWaiting = cur->nextWaiting;
- cur->nextWaiting->prevWaiting = cur->prevWaiting;
- assert(l->firstThread->prevWaiting &&
- l->firstThread->nextWaiting && "Inconsistent list");
- } else if (cur->nextWaiting == cur) {
- l->firstThread = 0;
- } else {
- l->firstThread = cur->nextWaiting;
- l->firstThread->prevWaiting = cur->prevWaiting;
- cur->prevWaiting->nextWaiting = l->firstThread;
- assert(l->firstThread->prevWaiting &&
- l->firstThread->nextWaiting && "Inconsistent list");
- }
- cur->prevWaiting = 0;
- cur->nextWaiting = 0;
- cur->varcond.signal();
- break;
- }
- } while (cur != l->firstThread);
- }
- }
- } else {
- JavaThread::get()->getJVM()->illegalMonitorStateException(self);
+ if (!owner(self)) {
+ thread->getJVM()->illegalMonitorStateException(self);
+ UNREACHABLE();
}
- assert(owner(self) && "Not owner after notify");
+ thread->lockingThread.notify(self, table);
}
void JavaObject::notifyAll(JavaObject* self) {
llvm_gcroot(self, 0);
- JavaLock* l = 0;
-
- if (owner(self)) {
- l = (JavaLock*)mvm::ThinLock::getFatLock(self);
- if (l) {
- JavaThread* cur = l->firstThread;
- if (cur) {
- do {
- JavaThread* temp = cur->nextWaiting;
- cur->prevWaiting = 0;
- cur->nextWaiting = 0;
- cur->varcond.signal();
- cur = temp;
- } while (cur != l->firstThread);
- l->firstThread = 0;
- }
- }
- } else {
- JavaThread::get()->getJVM()->illegalMonitorStateException(self);
+ JavaThread* thread = JavaThread::get();
+ mvm::LockSystem& table = thread->getJVM()->lockSystem;
+
+ if (!owner(self)) {
+ thread->getJVM()->illegalMonitorStateException(self);
+ UNREACHABLE();
}
+ thread->lockingThread.notifyAll(self, table);
+}
+
+void JavaObject::overflowThinLock(JavaObject* self) {
+ llvm_gcroot(self, 0);
+ mvm::ThinLock::overflowThinLock(self, JavaThread::get()->getJVM()->lockSystem);
+}
- assert(owner(self) && "Not owner after notifyAll");
+void JavaObject::acquire(JavaObject* self) {
+ llvm_gcroot(self, 0);
+ mvm::ThinLock::acquire(self, JavaThread::get()->getJVM()->lockSystem);
+}
+
+void JavaObject::release(JavaObject* self) {
+ llvm_gcroot(self, 0);
+ mvm::ThinLock::release(self, JavaThread::get()->getJVM()->lockSystem);
+}
+
+bool JavaObject::owner(JavaObject* self) {
+ llvm_gcroot(self, 0);
+ return mvm::ThinLock::owner(self, JavaThread::get()->getJVM()->lockSystem);
}
void JavaObject::decapsulePrimitive(JavaObject* obj, Jnjvm *vm, jvalue* buf,
Modified: vmkit/branches/precise/lib/J3/VMCore/JavaObject.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/VMCore/JavaObject.h?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/VMCore/JavaObject.h (original)
+++ vmkit/branches/precise/lib/J3/VMCore/JavaObject.h Sun Oct 24 06:00:06 2010
@@ -244,6 +244,10 @@
llvm_gcroot(self, 0);
return ((JavaVirtualTable*)self->getVirtualTable())->cl;
}
+
+ /// instanceOf - Is this object's class of type the given class?
+ ///
+ static bool instanceOf(JavaObject* self, UserCommonClass* cl);
/// wait - Java wait. Makes the current thread waiting on a monitor.
///
@@ -264,35 +268,19 @@
///
static void notifyAll(JavaObject* self);
- /// overflowmvm::ThinLock - Notify that the thin lock has overflowed.
- ///
- static void overflowThinLock(JavaObject* self) {
- llvm_gcroot(self, 0);
- mvm::ThinLock::overflowThinLock(self);
- }
-
- /// instanceOf - Is this object's class of type the given class?
+ /// overflowThinLock - Notify that the thin lock has overflowed.
///
- static bool instanceOf(JavaObject* self, UserCommonClass* cl);
+ static void overflowThinLock(JavaObject* self);
/// acquire - Acquire the lock on this object.
- static void acquire(JavaObject* self) {
- llvm_gcroot(self, 0);
- mvm::ThinLock::acquire(self);
- }
+ static void acquire(JavaObject* self);
/// release - Release the lock on this object
- static void release(JavaObject* self) {
- llvm_gcroot(self, 0);
- mvm::ThinLock::release(self);
- }
+ static void release(JavaObject* self);
/// owner - Returns true if the current thread is the owner of this object's
/// lock.
- static bool owner(JavaObject* self) {
- llvm_gcroot(self, 0);
- return mvm::ThinLock::owner(self);
- }
+ static bool owner(JavaObject* self);
#ifdef SIGSEGV_THROW_NULL
#define verifyNull(obj) {}
@@ -301,12 +289,6 @@
if (obj == NULL) JavaThread::get()->getJVM()->nullPointerException();
#endif
- /// lockObj - Get the LockObj if the lock is a fat lock.
- static JavaLock* lockObj(JavaObject* self) {
- llvm_gcroot(self, 0);
- return (JavaLock*)mvm::ThinLock::getFatLock(self);
- }
-
/// decapsulePrimitive - Based on the signature argument, decapsule
/// obj as a primitive and put it in the buffer.
///
Modified: vmkit/branches/precise/lib/J3/VMCore/JavaThread.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/VMCore/JavaThread.cpp?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/VMCore/JavaThread.cpp (original)
+++ vmkit/branches/precise/lib/J3/VMCore/JavaThread.cpp Sun Oct 24 06:00:06 2010
@@ -19,10 +19,6 @@
using namespace j3;
-const unsigned int JavaThread::StateRunning = 0;
-const unsigned int JavaThread::StateWaiting = 1;
-const unsigned int JavaThread::StateInterrupted = 2;
-
JavaThread::JavaThread(JavaObject* thread, JavaObject* vmth, Jnjvm* isolate)
: MutatorThread() {
llvm_gcroot(thread, 0);
@@ -31,8 +27,6 @@
javaThread = thread;
vmThread = vmth;
MyVM = isolate;
- interruptFlag = 0;
- state = StateRunning;
pendingException = 0;
jniEnv = isolate->jniEnv;
localJNIRefs = new JNILocalReferences();
Modified: vmkit/branches/precise/lib/J3/VMCore/JavaThread.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/VMCore/JavaThread.h?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/VMCore/JavaThread.h (original)
+++ vmkit/branches/precise/lib/J3/VMCore/JavaThread.h Sun Oct 24 06:00:06 2010
@@ -13,6 +13,7 @@
#include "mvm/Object.h"
#include "mvm/Threads/Cond.h"
#include "mvm/Threads/Locks.h"
+#include "mvm/Threads/ObjectLocks.h"
#include "mvm/Threads/Thread.h"
#include "MutatorThread.h"
@@ -84,33 +85,7 @@
///
JavaObject* vmThread;
- /// varcond - Condition variable when the thread needs to be awaken from
- /// a wait.
- ///
- mvm::Cond varcond;
-
- /// interruptFlag - Has this thread been interrupted?
- ///
- uint32 interruptFlag;
-
- /// nextWaiting - Next thread waiting on the same monitor.
- ///
- JavaThread* nextWaiting;
-
- /// prevWaiting - Previous thread waiting on the same monitor.
- ///
- JavaThread* prevWaiting;
-
- /// waitsOn - The monitor on which the thread is waiting on.
- ///
- JavaLock* waitsOn;
-
- static const unsigned int StateRunning;
- static const unsigned int StateWaiting;
- static const unsigned int StateInterrupted;
-
- /// state - The current state of this thread: Running, Waiting or Interrupted.
- uint32 state;
+ mvm::LockingThread lockingThread;
/// currentAddedReferences - Current number of added local references.
///
Modified: vmkit/branches/precise/lib/J3/VMCore/Jnjvm.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/VMCore/Jnjvm.cpp?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/VMCore/Jnjvm.cpp (original)
+++ vmkit/branches/precise/lib/J3/VMCore/Jnjvm.cpp Sun Oct 24 06:00:06 2010
@@ -1402,7 +1402,7 @@
}
Jnjvm::Jnjvm(mvm::BumpPtrAllocator& Alloc, JnjvmBootstrapLoader* loader) :
- VirtualMachine(Alloc), lockSystem(this) {
+ VirtualMachine(Alloc), lockSystem(Alloc) {
classpath = getenv("CLASSPATH");
if (!classpath) classpath = ".";
Modified: vmkit/branches/precise/lib/J3/VMCore/Jnjvm.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/VMCore/Jnjvm.h?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/VMCore/Jnjvm.h (original)
+++ vmkit/branches/precise/lib/J3/VMCore/Jnjvm.h Sun Oct 24 06:00:06 2010
@@ -19,8 +19,8 @@
#include "mvm/VirtualMachine.h"
#include "mvm/Threads/Cond.h"
#include "mvm/Threads/Locks.h"
+#include "mvm/Threads/ObjectLocks.h"
-#include "JavaLocks.h"
#include "JnjvmConfig.h"
#include "JNIReferences.h"
#include "LockedMap.h"
@@ -202,7 +202,7 @@
/// lockSystem - The lock system to allocate and manage Java locks.
///
- LockSystem lockSystem;
+ mvm::LockSystem lockSystem;
/// argumentsInfo - The command line arguments given to the vm
///
@@ -341,9 +341,6 @@
///
virtual void waitForExit();
- virtual JavaLock* allocateFatLock(gc*);
- virtual JavaLock* getFatLockFromID(uintptr_t val);
-
private:
/// internalRemoveMethodsInFunctionMap - Removes all methods compiled by this
/// class loader from the function map.
@@ -357,7 +354,7 @@
void removeMethodsInFunctionMaps(JnjvmClassLoader* loader);
/// loadBootstrap - Bootstraps the JVM, getting the class loader, initializing
- /// bootstrap classes (e.g. java/lang/Class, java/lang/*Exception) and
+ /// bootstrap classes (e.g. java/lang/Class, java/lang/Exception) and
/// mapping the initial thread.
///
void loadBootstrap();
Modified: vmkit/branches/precise/lib/J3/VMCore/VirtualTables.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/J3/VMCore/VirtualTables.cpp?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/lib/J3/VMCore/VirtualTables.cpp (original)
+++ vmkit/branches/precise/lib/J3/VMCore/VirtualTables.cpp Sun Oct 24 06:00:06 2010
@@ -291,20 +291,20 @@
}
uint32 i = 0;
- for (; i < LockSystem::GlobalSize; i++) {
- JavaLock** array = lockSystem.LockTable[i];
+ for (; i < mvm::LockSystem::GlobalSize; i++) {
+ mvm::FatLock** array = lockSystem.LockTable[i];
if (array == NULL) break;
uint32 j = 0;
- for (; j < LockSystem::IndexSize; j++) {
+ for (; j < mvm::LockSystem::IndexSize; j++) {
if (array[j] == NULL) break;
- JavaLock* lock = array[j];
+ mvm::FatLock* lock = array[j];
mvm::Collector::markAndTraceRoot(lock->getAssociatedObjectPtr(), closure);
}
- for (j = j + 1; j < LockSystem::IndexSize; j++) {
+ for (j = j + 1; j < mvm::LockSystem::IndexSize; j++) {
assert(array[j] == NULL);
}
}
- for (i = i + 1; i < LockSystem::GlobalSize; i++) {
+ for (i = i + 1; i < mvm::LockSystem::GlobalSize; i++) {
assert(lockSystem.LockTable[i] == NULL);
}
#if defined(ISOLATE_SHARING)
Added: vmkit/branches/precise/lib/Mvm/CommonThread/ObjectLocks.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/Mvm/CommonThread/ObjectLocks.cpp?rev=117221&view=auto
==============================================================================
--- vmkit/branches/precise/lib/Mvm/CommonThread/ObjectLocks.cpp (added)
+++ vmkit/branches/precise/lib/Mvm/CommonThread/ObjectLocks.cpp Sun Oct 24 06:00:06 2010
@@ -0,0 +1,489 @@
+//===--------- ObjectLocks.cpp - Object-based locks -----------------------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cassert>
+
+#include "mvm/Threads/Cond.h"
+#include "mvm/Threads/Locks.h"
+#include "mvm/Threads/ObjectLocks.h"
+#include "mvm/Threads/Thread.h"
+#include "mvm/VirtualMachine.h"
+#include "MvmGC.h"
+#include "cterror.h"
+#include <cerrno>
+#include <sys/time.h>
+#include <pthread.h>
+
+
+using namespace mvm;
+
+void ThinLock::overflowThinLock(gc* object, LockSystem& table) {
+ llvm_gcroot(object, 0);
+ FatLock* obj = table.allocate(object);
+ obj->acquireAll(object, (ThinCountMask >> ThinCountShift) + 1);
+ 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.
+///
+void ThinLock::initialise(gc* object, LockSystem& table) {
+ llvm_gcroot(object, 0);
+ uintptr_t oldValue = 0;
+ uintptr_t newValue = 0;
+ uintptr_t yieldedValue = 0;
+ do {
+ oldValue = object->header;
+ newValue = oldValue & NonLockBitsMask;
+ yieldedValue = __sync_val_compare_and_swap(&object->header, oldValue, newValue);
+ } while (yieldedValue != oldValue);
+}
+
+FatLock* ThinLock::changeToFatlock(gc* object, LockSystem& table) {
+ llvm_gcroot(object, 0);
+ if (!(object->header & FatMask)) {
+ FatLock* obj = table.allocate(object);
+ uint32 count = (object->header & ThinCountMask) >> ThinCountShift;
+ obj->acquireAll(object, count + 1);
+ 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 = table.getFatLockFromID(object->header);
+ assert(res && "Lock deallocated while held.");
+ return res;
+ }
+}
+
+void ThinLock::acquire(gc* object, LockSystem& table) {
+ llvm_gcroot(object, 0);
+ uint64_t id = mvm::Thread::get()->getThreadID();
+ 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, table) && "Not owner after quitting acquire!");
+ return;
+ }
+
+ if ((yieldedValue & Thread::IDMask) == id) {
+ assert(owner(object, table) && "Inconsistent lock");
+ if ((yieldedValue & ThinCountMask) != ThinCountMask) {
+ do {
+ oldValue = object->header;
+ newValue = oldValue + ThinCountAdd;
+ yieldedValue = __sync_val_compare_and_swap(&(object->header), oldValue, newValue);
+ } while (oldValue != yieldedValue);
+ } else {
+ overflowThinLock(object, table);
+ }
+ assert(owner(object, table) && "Not owner after quitting acquire!");
+ return;
+ }
+
+ while (true) {
+ if (object->header & FatMask) {
+ FatLock* obj = table.getFatLockFromID(object->header);
+ if (obj != NULL) {
+ if (obj->acquire(object)) {
+ break;
+ }
+ }
+ }
+
+ while (object->header & ~NonLockBitsMask) {
+ if (object->header & FatMask) {
+ break;
+ } else {
+ mvm::Thread::yield();
+ }
+ }
+
+ if ((object->header & ~NonLockBitsMask) == 0) {
+ FatLock* obj = table.allocate(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, table) != obj) && "Inconsistent lock");
+ table.deallocate(obj);
+ } else {
+ assert((getFatLock(object, table) == obj) && "Inconsistent lock");
+ }
+ assert(!owner(object, table) && "Inconsistent lock");
+ }
+ }
+
+ assert(owner(object, table) && "Not owner after quitting acquire!");
+}
+
+/// release - Release the lock.
+void ThinLock::release(gc* object, LockSystem& table) {
+ llvm_gcroot(object, 0);
+ assert(owner(object, table) && "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) {
+ 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 = table.getFatLockFromID(object->header);
+ assert(obj && "Lock deallocated while held.");
+ obj->release(object, table);
+ } else {
+ 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);
+ }
+}
+
+/// owner - Returns true if the curren thread is the owner of this object's
+/// lock.
+bool ThinLock::owner(gc* object, LockSystem& table) {
+ llvm_gcroot(object, 0);
+ if (object->header & FatMask) {
+ FatLock* obj = table.getFatLockFromID(object->header);
+ if (obj != NULL) return obj->owner();
+ } else {
+ uint64 id = mvm::Thread::get()->getThreadID();
+ if ((object->header & Thread::IDMask) == id) return true;
+ }
+ return false;
+}
+
+/// getFatLock - Get the fat lock is the lock is a fat lock, 0 otherwise.
+FatLock* ThinLock::getFatLock(gc* object, LockSystem& table) {
+ llvm_gcroot(object, 0);
+ if (object->header & FatMask) {
+ return table.getFatLockFromID(object->header);
+ } else {
+ return NULL;
+ }
+}
+
+void FatLock::acquireAll(gc* obj, uint32 nb) {
+ internalLock.lockAll(nb);
+}
+
+bool FatLock::owner() {
+ return internalLock.selfOwner();
+}
+
+mvm::Thread* FatLock::getOwner() {
+ return internalLock.getOwner();
+}
+
+FatLock::FatLock(uint32_t i, gc* a) {
+ llvm_gcroot(a, 0);
+ firstThread = NULL;
+ index = i;
+ associatedObject = a;
+ waitingThreads = 0;
+ lockingThreads = 0;
+ nextFreeLock = NULL;
+}
+
+uintptr_t FatLock::getID() {
+ return (index << mvm::NonLockBits) | mvm::FatMask;
+}
+
+void FatLock::release(gc* obj, LockSystem& table) {
+ llvm_gcroot(obj, 0);
+ assert(associatedObject && "No associated object when releasing");
+ assert(associatedObject == obj && "Mismatch object in lock");
+ if (!waitingThreads && !lockingThreads &&
+ internalLock.recursionCount() == 1) {
+ mvm::ThinLock::initialise(associatedObject, table);
+ table.deallocate(this);
+ }
+ internalLock.unlock();
+}
+
+/// acquire - Acquires the internalLock.
+///
+bool FatLock::acquire(gc* obj) {
+ llvm_gcroot(obj, 0);
+
+ spinLock.lock();
+ lockingThreads++;
+ spinLock.unlock();
+
+ internalLock.lock();
+
+ spinLock.lock();
+ lockingThreads--;
+ spinLock.unlock();
+
+ if (associatedObject != obj) {
+ internalLock.unlock();
+ return false;
+ }
+ return true;
+}
+
+
+void LockSystem::deallocate(FatLock* lock) {
+ lock->associatedObject = NULL;
+ threadLock.lock();
+ lock->nextFreeLock = freeLock;
+ freeLock = lock;
+ threadLock.unlock();
+}
+
+LockSystem::LockSystem(mvm::BumpPtrAllocator& all) : allocator(all) {
+ LockTable = (FatLock* **)
+ allocator.Allocate(GlobalSize * sizeof(FatLock**), "Global LockTable");
+ LockTable[0] = (FatLock**)
+ allocator.Allocate(IndexSize * sizeof(FatLock*), "Index LockTable");
+ currentIndex = 0;
+ freeLock = NULL;
+}
+
+FatLock* LockSystem::allocate(gc* obj) {
+ llvm_gcroot(obj, 0);
+ FatLock* res = 0;
+ threadLock.lock();
+
+ // Try the freeLock list.
+ if (freeLock != NULL) {
+ res = freeLock;
+ freeLock = res->nextFreeLock;
+ res->nextFreeLock = 0;
+ assert(res->associatedObject == NULL);
+ threadLock.unlock();
+ res->associatedObject = obj;
+ } else {
+ // Get an index.
+ uint32_t index = currentIndex++;
+ if (index == MaxLocks) {
+ fprintf(stderr, "Ran out of space for allocating locks");
+ abort();
+ }
+
+ FatLock** tab = LockTable[index >> BitIndex];
+
+ VirtualMachine* vm = mvm::Thread::get()->MyVM;
+ if (tab == NULL) {
+ tab = (FatLock**)vm->allocator.Allocate(
+ IndexSize * sizeof(FatLock*), "Index LockTable");
+ }
+ threadLock.unlock();
+
+ // Allocate the lock.
+ res = new(vm->allocator, "Lock") FatLock(index, obj);
+
+ // Add the lock to the table.
+ uint32_t internalIndex = index & BitMask;
+ tab[internalIndex] = res;
+ }
+
+ // Return the lock.
+ return res;
+}
+
+
+FatLock* LockSystem::getFatLockFromID(uintptr_t ID) {
+ if (ID & mvm::FatMask) {
+ uint32_t index = (ID & ~mvm::FatMask) >> mvm::NonLockBits;
+ FatLock* res = getLock(index);
+ return res;
+ } else {
+ return NULL;
+ }
+}
+
+
+
+bool LockingThread::wait(
+ gc* self, LockSystem& table, struct timeval* info, bool timed) {
+ llvm_gcroot(self, 0);
+ FatLock* l = 0;
+
+ assert(mvm::ThinLock::owner(self, table));
+ l = mvm::ThinLock::changeToFatlock(self, table);
+ this->waitsOn = l;
+ mvm::Cond& varcondThread = this->varcond;
+
+ if (this->interruptFlag != 0) {
+ this->interruptFlag = 0;
+ this->waitsOn = 0;
+ return true;
+ } else {
+ this->state = LockingThread::StateWaiting;
+ if (l->firstThread) {
+ assert(l->firstThread->prevWaiting && l->firstThread->nextWaiting &&
+ "Inconsistent list");
+ if (l->firstThread->nextWaiting == l->firstThread) {
+ l->firstThread->nextWaiting = this;
+ } else {
+ l->firstThread->prevWaiting->nextWaiting = this;
+ }
+ this->prevWaiting = l->firstThread->prevWaiting;
+ this->nextWaiting = l->firstThread;
+ l->firstThread->prevWaiting = this;
+ } else {
+ l->firstThread = this;
+ this->nextWaiting = this;
+ this->prevWaiting = this;
+ }
+ assert(this->prevWaiting && this->nextWaiting && "Inconsistent list");
+ assert(l->firstThread->prevWaiting && l->firstThread->nextWaiting &&
+ "Inconsistent list");
+
+ bool timeout = false;
+
+ l->waitingThreads++;
+
+ while (!this->interruptFlag && this->nextWaiting) {
+ if (timed) {
+ timeout = varcondThread.timedWait(&l->internalLock, info);
+ if (timeout) break;
+ } else {
+ varcondThread.wait(&l->internalLock);
+ }
+ }
+
+ l->waitingThreads--;
+
+ assert((!l->firstThread || (l->firstThread->prevWaiting &&
+ l->firstThread->nextWaiting)) && "Inconsistent list");
+
+ bool interrupted = (this->interruptFlag != 0);
+
+ if (interrupted || timeout) {
+
+ if (this->nextWaiting) {
+ assert(this->prevWaiting && "Inconsistent list");
+ if (l->firstThread != this) {
+ this->nextWaiting->prevWaiting = this->prevWaiting;
+ this->prevWaiting->nextWaiting = this->nextWaiting;
+ assert(l->firstThread->prevWaiting &&
+ l->firstThread->nextWaiting && "Inconsistent list");
+ } else if (this->nextWaiting == this) {
+ l->firstThread = NULL;
+ } else {
+ l->firstThread = this->nextWaiting;
+ l->firstThread->prevWaiting = this->prevWaiting;
+ this->prevWaiting->nextWaiting = l->firstThread;
+ assert(l->firstThread->prevWaiting &&
+ l->firstThread->nextWaiting && "Inconsistent list");
+ }
+ this->nextWaiting = NULL;
+ this->prevWaiting = NULL;
+ } else {
+ assert(!this->prevWaiting && "Inconstitent state");
+ // Notify lost, notify someone else.
+ notify(self, table);
+ }
+ } else {
+ assert(!this->prevWaiting && !this->nextWaiting &&
+ "Inconsistent state");
+ }
+
+ this->state = LockingThread::StateRunning;
+ this->waitsOn = 0;
+
+ if (interrupted) {
+ this->interruptFlag = 0;
+ return true;
+ }
+ }
+
+ assert(mvm::ThinLock::owner(self, table) && "Not owner after wait");
+ return false;
+}
+
+void LockingThread::notify(gc* self, LockSystem& table) {
+ llvm_gcroot(self, 0);
+ assert(mvm::ThinLock::owner(self, table));
+ FatLock* l = mvm::ThinLock::getFatLock(self, table);
+ if (l) {
+ LockingThread* cur = l->firstThread;
+ if (cur) {
+ do {
+ if (cur->interruptFlag != 0) {
+ cur = cur->nextWaiting;
+ } else {
+ assert(cur->prevWaiting && cur->nextWaiting &&
+ "Inconsistent list");
+ if (cur != l->firstThread) {
+ cur->prevWaiting->nextWaiting = cur->nextWaiting;
+ cur->nextWaiting->prevWaiting = cur->prevWaiting;
+ assert(l->firstThread->prevWaiting &&
+ l->firstThread->nextWaiting && "Inconsistent list");
+ } else if (cur->nextWaiting == cur) {
+ l->firstThread = 0;
+ } else {
+ l->firstThread = cur->nextWaiting;
+ l->firstThread->prevWaiting = cur->prevWaiting;
+ cur->prevWaiting->nextWaiting = l->firstThread;
+ assert(l->firstThread->prevWaiting &&
+ l->firstThread->nextWaiting && "Inconsistent list");
+ }
+ cur->prevWaiting = 0;
+ cur->nextWaiting = 0;
+ cur->varcond.signal();
+ break;
+ }
+ } while (cur != l->firstThread);
+ }
+ }
+
+ assert(mvm::ThinLock::owner(self, table) && "Not owner after notify");
+}
+
+void LockingThread::notifyAll(gc* self, LockSystem& table) {
+ llvm_gcroot(self, 0);
+ assert(mvm::ThinLock::owner(self, table));
+ FatLock* l = mvm::ThinLock::getFatLock(self, table);
+ if (l) {
+ LockingThread* cur = l->firstThread;
+ if (cur) {
+ do {
+ LockingThread* temp = cur->nextWaiting;
+ cur->prevWaiting = 0;
+ cur->nextWaiting = 0;
+ cur->varcond.signal();
+ cur = temp;
+ } while (cur != l->firstThread);
+ l->firstThread = 0;
+ }
+ }
+
+ assert(mvm::ThinLock::owner(self, table) && "Not owner after notifyAll");
+}
Modified: vmkit/branches/precise/lib/Mvm/CommonThread/ctlock.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/branches/precise/lib/Mvm/CommonThread/ctlock.cpp?rev=117221&r1=117220&r2=117221&view=diff
==============================================================================
--- vmkit/branches/precise/lib/Mvm/CommonThread/ctlock.cpp (original)
+++ vmkit/branches/precise/lib/Mvm/CommonThread/ctlock.cpp Sun Oct 24 06:00:06 2010
@@ -188,176 +188,3 @@
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 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.
-///
-void ThinLock::initialise(gc* object) {
- llvm_gcroot(object, 0);
- uintptr_t oldValue = 0;
- uintptr_t newValue = 0;
- uintptr_t yieldedValue = 0;
- do {
- oldValue = object->header;
- newValue = oldValue & NonLockBitsMask;
- yieldedValue = __sync_val_compare_and_swap(&object->header, oldValue, newValue);
- } while (yieldedValue != oldValue);
-}
-
-FatLock* ThinLock::changeToFatlock(gc* object) {
- llvm_gcroot(object, 0);
- if (!(object->header & FatMask)) {
- FatLock* obj = Thread::get()->MyVM->allocateFatLock(object);
- uint32 count = (object->header & ThinCountMask) >> ThinCountShift;
- obj->acquireAll(object, count + 1);
- 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);
- assert(res && "Lock deallocated while held.");
- return res;
- }
-}
-
-void ThinLock::acquire(gc* object) {
- llvm_gcroot(object, 0);
- uint64_t id = mvm::Thread::get()->getThreadID();
- 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 = oldValue + ThinCountAdd;
- yieldedValue = __sync_val_compare_and_swap(&(object->header), oldValue, newValue);
- } while (oldValue != yieldedValue);
- } else {
- 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 != NULL) {
- if (obj->acquire(object)) {
- break;
- }
- }
- }
-
- while (object->header & ~NonLockBitsMask) {
- if (object->header & FatMask) {
- break;
- } else {
- 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!");
-}
-
-/// release - Release the lock.
-void ThinLock::release(gc* object) {
- 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) {
- 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 {
- 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);
- }
-}
-
-/// owner - Returns true if the curren thread is the owner of this object's
-/// lock.
-bool ThinLock::owner(gc* object) {
- llvm_gcroot(object, 0);
- if (object->header & FatMask) {
- FatLock* obj = Thread::get()->MyVM->getFatLockFromID(object->header);
- if (obj != NULL) return obj->owner();
- } else {
- uint64 id = mvm::Thread::get()->getThreadID();
- if ((object->header & Thread::IDMask) == id) return true;
- }
- return false;
-}
-
-/// getFatLock - Get the fat lock is the lock is a fat lock, 0 otherwise.
-FatLock* ThinLock::getFatLock(gc* object) {
- llvm_gcroot(object, 0);
- if (object->header & FatMask) {
- return Thread::get()->MyVM->getFatLockFromID(object->header);
- } else {
- return NULL;
- }
-}
More information about the vmkit-commits
mailing list