The Question is:
In a previous question (wiz_1661.html) the Wizard said
>> On Alpha, failure to use the memory barrier operators (when
>> necessary) to ensure consistent memory contents -- memory
>> barriers are used to properly control the (expected) read
>> and write reordering normally found on Alpha. The barrier
>> will block execution until all pending memory operations
>> have completed.
Could you please explain Memory Barriers a little further
1 - What Are They ... User Mode and/or Elevated Mode ?
2 - When to use them
3 - How to use them, ie what function calls
4 - A code example, showing how code would
NOT or probably NOT work, follwed by same code,
with correct usage of memory barrier, so
code will work.
The Answer is :
The OpenVMS Wizard would strongly encourage you to read the information
on memory barriers present in the Alpha Architecture Handbook.
You can order this document, or you can download it from a pointer
in the OpenVMS FAQ.
A memory barrier is an Alpha instruction, and this instruction can
be used in any processor privilege mode and at any time.
There are two general types of memory barrier, those that involve
synchornizing completion of loads and stores to memory, and the IMB
PALcode routine that must be used after modifications are made to the
instruction stream. (The IMB PALcode call is logically equivilent to
the execution of the REI instruction required on VAX systems after an
instruction stream modification.)
You must use memory barriers when you want to guarantee the ordering
of completion of memory operations. The Alpha Architecture permits
the processor to re-order loads and stores; thus memory may be read or
written in a different order than that specified by the programmer.
This reordering is done to improve system performance, but it can
occasionally also introduce undesirable side effects. The memory
barrier instructions (MB and WMB) permit the programmer to explicitly
synchronize the continued execution of the application with the
necessary completion of all memory load and store operations currently
outstanding. Using other terminology, a memory barrier is a
synchronization point for memory.
For a general example of the need for memory barriers, assume the
following -- be aware of the distinction made between processes and
processors in this discussion. Assume you have a shared memory global
section containing a data structure. This data structure is protected
by a lock cell that is stored in the shared memory. A process must
acquire ownership of the data structure by setting the lock cell to a
non-zero value (say, to the Process Id of the accessor) when it plans
to write or update the contents of the data structure. All other
processes will be prevented from accessing the structure when it is
found locked, and will spin or otherwise defer access waiting for the
lock cell to be cleared. Once the process holding the lock completes
the necessary writes or modifications, it then clears the value in the
lock cell by writing a zero back to the lock cell location.
The Alpha processor -- because it may re-order loads and stores -- may
choose to reorder the operations and write the lock cell location before
it performs the updates on the contents of the data structure. Because
of this reordering, other processes on other processors will then see the
lock cell become zero and then (one process can) acquire the lock and may
then read the same structure field(s) before the first processor has
written the updated data to the field(s), thereby acquiring erronous
(stale) data. While the programmer wrote the data to memory in the
appopriate order, the Alpha processor reordered the memory access(es).
The mechanism used to control this involves the execution of a MB
instruction after the update to the structure field and prior to
releasing the lock, and inserting another MB after releasing the lock.
This will guarantee the ordering of the writes, and will ensures that
all processes will see the correct data.
Memory barriers are also used to control how an Alpha processor
aggregates memory writes -- an Alpha processor may cache a memory write
for some relatively long interval, before actually completing the write
to memory. Until the data is written to memory, it is not visible to
other Alpha processors in the system. Most of the time, this behaviour
is entirely benign -- it often improves performance by permitting a
processor to aggregate multiple write operations into a single memory
bus transaction, caching and then sending multiple write operations out
to memory together. There are cases where a programmer wants a write
visible immediately, and the MB and the WMB instruction can be used to
PALcode calls will contain memory barriers when appropriate, but an
OpenVMS programmer should not assume that any particular intervening
PALcode or OpenVMS system service call will contain a memory barrier
operation. If a memory barrier is required for a particular series of
memory operations, explicitly include the memory barrier in the code.
How you write code that uses memory barriers depends on the language.
Using Compaq C for OpenVMS Alpha, you can use the __MB builtin and the
asm() directive. Please see the Compaq C User's Guide for OpenVMS Systems
for additional details, or the user's guide for your particular language.
The OpenVMS Alpha Macro32 compiler provides various built-ins, including
the EVAX_IMB built-in.
Examples of using memory barriers are included in the Alpha Architecture
Handbook, and additional information on memory barriers is also present
in the OpenVMS manual set. Please see these documents for additional
The OpenVMS Wizard will leave the question of how to reliably deal with
bitlocks, and how to spin appropriately, for topic (6984).