From GridLAB-D Wiki
Jump to: navigation, search

 TECHNICAL MANUAL Locking - Memory locking

Synopsis

Prior to Hassayampa (Version 3.0)

Core:

lock(unsigned int *lock);
unlock(unsigned int *lock);

Modules:

LOCK(unsigned int *lock);
UNLOCK(unsigned int *lock);
LOCK_OBJECT(object *obj);
UNLOCK_OBJECT(object *obj);
Hassayampa (Version 3.0) and later

Core:

wlock(unsigned int *lock);
rlock(unsigned int *lock);
unlock(unsigned int *lock);

Modules:

READLOCK(unsigned int *lock);
WRITELOCK(unsigned int *lock);
UNLOCK(unsigned int *lock);
READLOCK_OBJECT(object *obj);
WRITELOCK_OBJECT(object *obj);
UNLOCK_OBJECT(object *obj);
LOCKED(object *obj,(command-list));

Description

Memory locking is used to prevent non-atomic memory access operations from allowing read/write mishaps, such as illustrated by the following simple example.

CPU 0 CPU 1 X Remark
read X 0
read X 0
write X+1 1 CPU 0 adds 1 to its value of X
write X+1 1 CPU 1 adds 1 to its value of X
read X 1 value of X is not 2 as expected
read X 1 value of X is not 2 as expected

Prior to Hassayampa (Version 3.0) the problem is addressed by restricting access to memory using a spin lock:

CPU 0 CPU 1 X Remark
0 Initial state
lock X 0 CPU 0 lock ok
read X 0
lock X 0 CPU 1 blocked
write X+1 1 CPU 0 adds 1 to its value of X
unlock X 1 CPU 1 lock ok
lock X 1 CPU 0 blocked
read X 1
write X+1 2 CPU 1 adds 1 to its value of X
unlock X 2 CPU 0 lock ok
lock X 2 CPU 1 blocked
read X 2 value of X is 2 as expected
unlock X 2 CPU 1 lock ok
read X 2 value of X is 2 as expected
unlock X 2

As of Hassayampa (Version 3.0) the problem is addressed by restricting access to memory using a R/W lock:

CPU 0 CPU 1 X Remark
0 Initial state
wlock X 0 CPU 0 lock ok
read X 0
wlock X 0 CPU 1 blocked
write X+1 1 CPU 0 adds 1 to its value of X
unlock X 1 CPU 1 lock ok
rlock X 1 CPU 0 blocked
read X 1
write X+1 2 CPU 1 adds 1 to its value of X
unlock X 2 CPU 0 lock ok
rlock X 2 CPU 1 lock ok
read X 2 value of X is 2 as expected
read X 2 value of X is 2 as expected
unlock X 2
unlock X 2

The advantage of R/W locking is that when only reads are being performed, they are not blocked. Blocking only occurs when a write is being performed. In addition, as of Hassayampa (Version 3.0) the gl_get() and gl_set() routines automatically implement the appropriate locking mechanism for the type of run being performed. In the case of single threaded simulation, no locking is performed. For multithreaded simulations, r/w locking is used for all memory access between objects.

Note
As of Hassayampa (Version 3.0) lock() is implemented as wlock().

Examples

The following examples illustrate good coding practice when using locks.

Coherence locks
Be sure to operate on data that needs to remain coherent using a single lock instead of multiple locks. For example, you should use
READLOCK(x_lock);
complex t[] = {x[0], x[1] x[2]};
UNLOCK(x_lock);
rather than using three separately locked data copy operations.
Calculation locks
Avoid lengthy calculations while using locks. For example, you should use
READLOCK(x_lock);
complex t = A*x;
UNLOCK(x_key);
WRITELOCK(y_lock);
y = t;
UNLOCK(y_lock);
rather than embedding the calculation inside the safe code region.
Nested locks
Although you should avoid nested lock because of possible race conditions, if you must use a nested lock try to put the write lock outside the read lock. For example, you should use
WRITELOCK(y_lock);
READLOCK(x_lock);
x = A*x + B*y;
UNLOCK(x_lock);
UNLOCK(y_lock);
rather than taking the read lock out first because write locks can take much longer to obtain than read locks.

See also