|
|||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object org.jikesrvm.scheduler.SpinLock
public final class SpinLock
Alternative (to Java monitors) light-weight synchronization
mechanism to implement Java monitors Lock
. These locks
should not be used where Java monitors would suffice, or where
an adaptive mutex is required. They are
intended to be held only briefly!
Normally, contending RVMThread
s will spin on
this processor lock's latestContender
field. If
MCS_Locking
is set, the processors spin on processor
local data. This is loosely based on an idea in Mellor-Crummey and
Scott's paper in ASPLOS-IV (1991).
1. Possible project: determine those conditions under which MCS
locking performs better than spinning on a global address.
Acquiring or releasing a lock involves atomically reading and
setting the lock's latestContender
field. If this
field is null, the lock is unowned. Otherwise, the field points to
the virtual processor that owns the lock, or, if MCS locking is
being used, to the last vp on a circular queue of virtual
processors spinning until they get the lock, or, if MCS locking is
being used and the circular spin queue is being updated, to
IN_FLUX
.
Contention is best handled by doing something else. To support
this, tryLock
obtains the lock (and returns true) if
the lock is unowned (and there is no spurious microcontention).
Otherwise, it returns false.
Only when "doing something else" is not an attractive option (locking global thread queues, unlocking a thick lock with threads waiting, avoiding starvation on a thread that has issued several tryLocks, etc.) should lock() be called. Here, any remaining contention is handled by spinning on a local flag.
To add itself to the circular waiting queue, a processor must succeed in setting the latestContender field to IN_FLUX. A backoff strategy is used to reduce contention for this field. This strategy has both a pseudo-random (to prevent two or more virtual processors from backing off in lock step) and an exponential component (to deal with really high contention).
Releasing a lock entails either atomically setting the latestContender field to null (if this processor is the latestContender), or releasing the first virtual processor on the circular spin queue. In the latter case, the latestContender field must be set to IN_FLUX. To give unlock() priority over lock(), the backoff strategy is not used for unlocking: if a vp fails to set set the field to IN_FLUX, it tries again immediately.
Usage: system locks should only be used when synchronized methods cannot. Do not do anything, (such as trigger a type cast, allocate an object, or call any method of a class that does not implement Uninterruptible) that might allow a thread switch or trigger a garbage collection between lock and unlock.
RVMThread
,
Monitor
,
Lock
Field Summary | |
---|---|
private static int |
delayBase
|
private static int[] |
delayCount
|
private static int |
delayIndex
|
private static int |
delayMultiplier
|
private static Address |
IN_FLUX
For MCS locking, indicates that another processor is changing the state of the circular waiting queue. |
(package private) RVMThread |
latestContender
The state of the processor lock. |
private static boolean |
MCS_Locking
Should contending RVMThread s spin on thread local addresses (true)
or on a globally shared address (false). |
Fields inherited from interface org.jikesrvm.Constants |
---|
NOT_REACHED, REFLECTION_FPRS_BITS, REFLECTION_FPRS_MASK, REFLECTION_GPRS_BITS, REFLECTION_GPRS_MASK |
Fields inherited from interface org.jikesrvm.objectmodel.ThinLockConstants |
---|
TL_DEDICATED_U16_OFFSET, TL_DEDICATED_U16_SHIFT, TL_LOCK_COUNT_MASK, TL_LOCK_COUNT_SHIFT, TL_LOCK_COUNT_UNIT, TL_LOCK_ID_MASK, TL_LOCK_ID_SHIFT, TL_NUM_BITS_RC, TL_NUM_BITS_STAT, TL_NUM_BITS_TID, TL_STAT_BIASABLE, TL_STAT_FAT, TL_STAT_MASK, TL_STAT_SHIFT, TL_STAT_THIN, TL_THREAD_ID_MASK, TL_THREAD_ID_SHIFT, TL_UNLOCK_MASK |
Fields inherited from interface org.jikesrvm.objectmodel.TIBLayoutConstants |
---|
IMT_METHOD_SLOTS, NEEDS_DYNAMIC_LINK, TIB_ARRAY_ELEMENT_TIB_INDEX, TIB_DOES_IMPLEMENT_INDEX, TIB_FIRST_SPECIALIZED_METHOD_INDEX, TIB_FIRST_VIRTUAL_METHOD_INDEX, TIB_INTERFACE_DISPATCH_TABLE_INDEX, TIB_SUPERCLASS_IDS_INDEX, TIB_TYPE_INDEX |
Fields inherited from interface org.jikesrvm.HeapLayoutConstants |
---|
BAD_MAP_COMPRESSION, BOOT_IMAGE_CODE_END, BOOT_IMAGE_CODE_SIZE, BOOT_IMAGE_CODE_START, BOOT_IMAGE_DATA_END, BOOT_IMAGE_DATA_SIZE, BOOT_IMAGE_DATA_START, BOOT_IMAGE_END, BOOT_IMAGE_RMAP_END, BOOT_IMAGE_RMAP_START, MAX_BOOT_IMAGE_RMAP_SIZE, MAXIMUM_MAPPABLE |
Constructor Summary | |
---|---|
SpinLock()
|
Method Summary | |
---|---|
private void |
handleMicrocontention(int n)
An attempt to lock or unlock a processor lock has failed, presumably due to contention with another processor. |
void |
lock()
Acquire a processor lock. |
void |
lock(String s)
|
boolean |
lockHeld()
|
boolean |
tryLock()
Conditionally acquire a processor lock. |
void |
unlock()
Release a processor lock. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
private static final boolean MCS_Locking
RVMThread
s spin on thread local addresses (true)
or on a globally shared address (false).
RVMThread latestContender
null
, if the lock is not owned;
IN_FLUX
, if the circular chain is being edited.
private static final int delayMultiplier
private static final int delayBase
private static int delayIndex
private static final int[] delayCount
private static final Address IN_FLUX
Constructor Detail |
---|
public SpinLock()
Method Detail |
---|
public boolean lockHeld()
public void lock(String s)
public void lock()
public boolean tryLock()
public void unlock()
private void handleMicrocontention(int n)
|
|||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |