/** * Recycles an unused heavy-weight lock. Locks are deallocated to processor specific lists, so * normally no synchronization is required to obtain or release a lock. */ protected static void free(Lock l) { l.active = false; RVMThread me = RVMThread.getCurrentThread(); if (me.cachedFreeLock == null) { if (trace) { VM.sysWriteln( "Lock.free: setting ", Magic.objectAsAddress(l), " as the cached free lock for Thread #", me.getThreadSlot()); } me.cachedFreeLock = l; } else { if (trace) { VM.sysWriteln( "Lock.free: returning ", Magic.objectAsAddress(l), " to the global freelist for Thread #", me.getThreadSlot()); } returnLock(l); } }
/** * Delivers up an unassigned heavy-weight lock. Locks are allocated from processor specific * regions or lists, so normally no synchronization is required to obtain a lock. * * <p>Collector threads cannot use heavy-weight locks. * * @return a free Lock; or <code>null</code>, if garbage collection is not enabled */ @UnpreemptibleNoWarn("The caller is prepared to lose control when it allocates a lock") static Lock allocate() { RVMThread me = RVMThread.getCurrentThread(); if (me.cachedFreeLock != null) { Lock l = me.cachedFreeLock; me.cachedFreeLock = null; if (trace) { VM.sysWriteln( "Lock.allocate: returning ", Magic.objectAsAddress(l), ", a cached free lock from Thread #", me.getThreadSlot()); } return l; } Lock l = null; while (l == null) { if (globalFreeLock != null) { lockAllocationMutex.lock(); l = globalFreeLock; if (l != null) { globalFreeLock = l.nextFreeLock; l.nextFreeLock = null; l.active = true; globalFreeLocks--; } lockAllocationMutex.unlock(); if (trace && l != null) { VM.sysWriteln( "Lock.allocate: returning ", Magic.objectAsAddress(l), " from the global freelist for Thread #", me.getThreadSlot()); } } else { l = new Lock(); // may cause thread switch (and processor loss) lockAllocationMutex.lock(); if (globalFreeLock == null) { // ok, it's still correct for us to be adding a new lock if (nextLockIndex >= MAX_LOCKS) { VM.sysWriteln("Too many fat locks"); // make MAX_LOCKS bigger? we can keep going?? VM.sysFail("Exiting VM with fatal error"); } l.index = nextLockIndex++; globalLocksAllocated++; } else { l = null; // someone added to the freelist, try again } lockAllocationMutex.unlock(); if (l != null) { if (l.index >= numLocks()) { /* We need to grow the table */ growLocks(l.index); } addLock(l); l.active = true; /* make sure other processors see lock initialization. * Note: Derek and I BELIEVE that an isync is not required in the other processor because the lock is newly allocated - Bowen */ Magic.sync(); } if (trace && l != null) { VM.sysWriteln( "Lock.allocate: returning ", Magic.objectAsAddress(l), ", a freshly allocated lock for Thread #", me.getThreadSlot()); } } } return l; }