public final class Lock extends Object
This class may be decomposed into four sections:
Requirement 1: It must be possible to lock an object when allocations are not allowed.
Requirement 2: After a lock has been obtained, the code of this class must return without allowing a thread switch. The exception handler of the baseline compiler assumes that until lock() returns the lock has not been obtained.)
Section 1:
support for Object.notify()
, Object.notifyAll()
, and Object.wait()
.
When these methods are called, the indicated object must be locked
by the current thread.
Section 2: has two sections. Section 2a: locks (and unlocking) objects with heavy-weight locks associated with them. Section 2b: associates (and disassociates) heavy-weight locks with objects.
Section 3: Allocates (and frees) heavy weight locks consistent with Requirement 1.
Section 4: debugging and performance tuning stuff.
The following performance tuning issues have not yet been addressed adaquately:
SpinLock.tryLock()
method?
Once these questions, and the issue of using MCS locking in SpinLock
,
have been investigated, then a larger performance issue
comes into view. A number of different light-weight locking schemes have
been proposed over the years (see last several OOPSLA's). It should be
possible to implement each of them in RVM and compare their performance.
Modifier and Type | Class and Description |
---|---|
private static class |
Lock.AppRunStartMonitor
Initialize counts in preparation for gathering statistics
|
private static class |
Lock.ExitMonitor
Report statistics at the end of execution.
|
Modifier and Type | Field and Description |
---|---|
protected boolean |
active
Is this lock currently being used?
|
private static int |
chunksAllocated
The number of chunks in the spine that have been physically allocated
|
static int |
deflations
Number of deflations
|
(package private) ThreadQueue |
entering
Queue for entering the lock, guarded by mutex.
|
private static Lock |
globalFreeLock
A global lock free list head
|
private static int |
globalFreeLocks
the number of locks held on the global free list.
|
private static int |
globalLocksAllocated
the total number of allocation operations.
|
private static int |
globalLocksFreed
the total number of free operations.
|
protected int |
index
This lock's index in the lock table
|
protected static int |
INITIAL_CHUNKS
The number of chunks to allocate on startup
|
protected static int |
LOCK_CHUNK_MASK
The mask used to get the chunk-level index
|
protected static int |
LOCK_CHUNK_SIZE
The size of each chunk in the spine
|
protected static int |
LOCK_SPINE_SIZE
The (fixed) number of entries in the lock table spine
|
private static SpinLock |
lockAllocationMutex
Used during allocation of locks within the table.
|
protected Object |
lockedObject
The object being locked (if any).
|
static int |
lockOperations
Number of lock operations
|
private static Lock[][] |
locks
The table of locks.
|
protected static int |
LOG_LOCK_CHUNK_SIZE
The log size of each chunk in the spine
|
protected static int |
MAX_LOCKS
The maximum possible number of locks
|
SpinLock |
mutex
A spin lock to handle contention for the data structures of this lock.
|
private Lock |
nextFreeLock
The next free lock on the free lock list
|
private static int |
nextLockIndex
The number of locks allocated (these may either be in use, on a global
freelist, or on a thread's freelist.
|
protected int |
ownerId
The id of the thread that owns this lock (if any).
|
protected int |
recursionCount
The number of times the owning thread (if any) has acquired this lock.
|
static boolean |
STATS
Control the gathering of statistics
|
private static boolean |
tentativeMicrolocking
Should we give up or persist in the attempt to get a heavy-weight lock,
if its
mutex microlock is held by another procesor. |
protected static boolean |
trace
do debug tracing?
|
static int |
unlockOperations
Number of unlock operations
|
(package private) ThreadQueue |
waiting
Queue for waiting on a notify, guarded by mutex as well.
|
Constructor and Description |
---|
Lock()
A heavy weight lock to handle extreme contention and wait/notify
synchronization.
|
Modifier and Type | Method and Description |
---|---|
static void |
addLock(Lock l)
Add a lock to the lock table
|
(package private) static Lock |
allocate()
Delivers up an unassigned heavy-weight lock.
|
static void |
boot()
Set up callbacks to report statistics.
|
static int |
countLocksHeldByThread(int id)
Count number of locks held by thread
|
private void |
deflate(Object o,
Offset lockOffset)
Disassociates this heavy-weight lock from the indicated object.
|
private void |
dump()
Reports the state of a heavy-weight lock, via
VM.sysWrite(org.jikesrvm.classloader.Atom) . |
protected void |
dumpBlockedThreads()
Dump threads blocked trying to get this lock
|
static void |
dumpLocks()
Dump the lock table.
|
protected void |
dumpWaitingThreads()
Dump threads waiting to be notified on this lock
|
protected static void |
free(Lock l)
Recycles an unused heavy-weight lock.
|
static Lock |
getLock(int id)
Read a lock from the lock table by id.
|
Object |
getLockedObject() |
int |
getOwnerId() |
int |
getRecursionCount() |
static String |
getThreadState(RVMThread t)
scan lock queues for thread and report its state
|
(package private) static void |
growLocks(int id)
Grow the locks table by allocating a new spine chunk.
|
static void |
init()
Sets up the data structures for holding heavy-weight locks.
|
protected boolean |
isBlocked(RVMThread t) |
protected boolean |
isWaiting(RVMThread t) |
boolean |
lockHeavy(Object o)
Acquires this heavy-weight lock on the indicated object.
|
boolean |
lockHeavyLocked(Object o)
Completes the task of acquiring the heavy lock, assuming that the mutex
is already acquired (locked).
|
static int |
numLocks() |
private static void |
raiseIllegalMonitorStateException(String msg,
Object o) |
(package private) static void |
returnLock(Lock l) |
void |
setLockedObject(Object o)
Set the object that this lock is referring to.
|
void |
setOwnerId(int id)
Set the owner of a lock
|
void |
setRecursionCount(int c)
Update the lock's recursion count.
|
void |
unlockHeavy(Object o)
Releases this heavy-weight lock on the indicated object.
|
protected static final boolean trace
public static final boolean STATS
protected static final int LOCK_SPINE_SIZE
protected static final int LOG_LOCK_CHUNK_SIZE
protected static final int LOCK_CHUNK_SIZE
protected static final int LOCK_CHUNK_MASK
protected static final int MAX_LOCKS
protected static final int INITIAL_CHUNKS
private static final boolean tentativeMicrolocking
mutex
microlock is held by another procesor.private static final SpinLock lockAllocationMutex
private static int chunksAllocated
private static int nextLockIndex
private static Lock globalFreeLock
private static int globalFreeLocks
private static int globalLocksAllocated
private static int globalLocksFreed
public static int lockOperations
public static int unlockOperations
public static int deflations
protected Object lockedObject
protected int ownerId
protected int recursionCount
public final SpinLock mutex
protected boolean active
private Lock nextFreeLock
protected int index
ThreadQueue entering
ThreadQueue waiting
public Lock()
public boolean lockHeavy(Object o)
o
- the object to be lockedpublic boolean lockHeavyLocked(Object o)
o
- the object whose lock is to be acquiredprivate static void raiseIllegalMonitorStateException(String msg, Object o)
public void unlockHeavy(Object o)
o
- the object to be unlockedprivate void deflate(Object o, Offset lockOffset)
o
- the object from which this lock is to be disassociatedlockOffset
- the lock's offset from the objectpublic void setOwnerId(int id)
id
- The thread id of the owner.public int getOwnerId()
public void setRecursionCount(int c)
c
- new recursion countpublic int getRecursionCount()
public void setLockedObject(Object o)
o
- the new locked objectpublic Object getLockedObject()
protected void dumpBlockedThreads()
protected void dumpWaitingThreads()
private void dump()
VM.sysWrite(org.jikesrvm.classloader.Atom)
.protected boolean isBlocked(RVMThread t)
t
- a threadprotected boolean isWaiting(RVMThread t)
t
- a threadpublic static void init()
static Lock allocate()
Collector threads cannot use heavy-weight locks.
null
, if garbage collection is not enabledprotected static void free(Lock l)
l
- the unused lockstatic void returnLock(Lock l)
static void growLocks(int id)
id
- the lock's index in the tablepublic static int numLocks()
public static Lock getLock(int id)
id
- The lock idpublic static void addLock(Lock l)
l
- The lock objectpublic static void dumpLocks()
public static int countLocksHeldByThread(int id)
id
- the thread locking ID we're counting forpublic static String getThreadState(RVMThread t)
t
- the thread whose state is of interestpublic static void boot()