Compiler Multi-processing support

The compiler implements various intrinsic functions useful inmultiprocessing. These functions generate inline machine code rather than a procedurecall. These functions perform atomic operations in a multiprocessing environment.This means that the processor executing these functions has exclusive access to thedata being operated on.

These functions are exported from the System module/package.The sample source code and runtime library have examples of using these functions.

Atomic compare and exchange

Modula-2

PROCEDURE ATOMIC_CMPXCHG(VAR INOUT data : SomeType; compare, source: SomeType) : SomeType;

where SomeType can be CARDINAL, INTEGER, DWORD or ADDRESS. Rememberthat pointers are compatible with ADDRESS parameter types.

Ada95

function ATOMIC_CMPXCHG(data : in out SomeType; compare, source :SomeType) return SomeType;

where SomeType can be any Integer type, modular type, accesstype or System.Address.

This procedure compares the value in data with the value in compareand if equal, then the value in source is assigned to data. The function result isthe value previously held in data. Only the variable data is atomically accessed.This function makes the new value written in data visible to other processors beforereturning.

Note: This intrinsic is not available for 386 processors.

Note: The return value may not be the same as the valuein data, because another processor may have altered the value one processor cycleafter this function alters the value.

Atomic exchange

Modula-2

PROCEDURE ATOMIC_XCHG(VAR INOUT data : SomeType; source : SomeType): SomeType;

where SomeType can be CARDINAL, INTEGER, DWORD or ADDRESS. Rememberthat pointers are compatible with ADDRESS parameter types.

Ada95

function ATOMIC_XCHG(data : in out SomeType; source : SomeType) returnSomeType;

where SomeType can be any Integer type, modular type, accesstype or System.Address.

This procedure performs an atomic exchange of the value in datawith the value in source. The function result is the value previously held in data.Only the variable data is atomically accessed. This function makes the new valuewritten in data visible to other processors before returning. This operation maybe used as a function or as a statement ignoring the return value.

Note: The return value may not be the same as the valuein data, because another processor may have altered the value one processor cycleafter this function alters the value.

Atomic add

Modula-2

PROCEDURE ATOMIC_ADD(VAR INOUT data : SomeType; constantValue : INTEGER): SomeType;

where SomeType can be CARDINAL or INTEGER.

Ada95

function ATOMIC_ADD(data : in out SomeType; constantValue : Integer)return SomeType;

where SomeType can be Integer, Natural or Positive.

constantValue must be in the range

-128..127 for IA32

-4096..4095 for SPARC

This procedure adds the value in constantValue with the valuein data. Positive numbers perform addition and negative numbers perform subtraction.The function result is the result of the addition/subtraction to data. Only the variabledata is atomically accessed. This function makes the new value written in data visibleto other processors before returning. This operation may be used as a function oras a statement ignoring the return value.

Note: This intrinsic is not available for 386 processors whenused as a function.

Note: The return value may not be the same as the value in data,because another processor may have altered the value one processor cycle after thisfunction alters the value.

Memory fence/barrier

Modula-2 and Ada95

PROCEDURE MEMORY_FENCE;

Note: This procedure is not necessary and does not perform anyactions on IA-32 architecture processors (x86 processor family) since these processorssupport strong write ordering.

Note: You do not need to use a memory fence with any synchronizationobjects supported by the runtime library or the operating system, as they will takenecessary actions.

This procedure generates a memory fence or barrier, and is necessaryon processors that do not guarantee memory access order.

The procedure guarantees that all subsequent loads or storeswill not access memory until after all previous loads and stores have accessed memory,as observed by other processors. The following pseudo code describes this further

1) <Acquire lock>
2) MEMORY_FENCE
3) critical section code
4) MEMORY_FENCE
5) <release lock>

The first memory fence stops the processor from looking aheadand pre-fetching any data used in the critical section. The second memory fence makessure that any data written in the critical section is made visible to other processorsbefore the write that releases the software lock. The memory fence is generally onlyused when implementing spinlocks.