[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