Atomic Variables and Optimization (GNAT User’s Guide for Native Platforms)

#### 6.3.1.11 Atomic Variables and Optimization ¶

You need to take two things into consideration with regard to performance when you use atomic variables.

First, the RM only guarantees that access to atomic variables be atomic, but has nothing to say about how this is achieved, though there is a strong implication that this should not be achieved by explicit locking code. Indeed, GNAT never generates any locking code for atomic variable access; it will simply reject any attempt to make a variable or type atomic if the atomic access cannot be achieved without such locking code.

That being said, it’s important to understand that you cannot assume the the program will always access the entire variable. Consider this example:

>     type R is record
>        A,B,C,D : Character;
>     end record;
>     for R'Size use 32;
>     for R'Alignment use 4;

>     RV : R;
>     pragma Atomic (RV);
>     X : Character;
>     ...
>     X := RV.B;

You cannot assume that the reference to `RV.B` will read the entire 32-bit variable with a single load instruction. It is perfectly legitimate, if the hardware allows it, to do a byte read of just the `B` field. This read is still atomic, which is all the RM requires. GNAT can and does take advantage of this, depending on the architecture and optimization level. Any assumption to the contrary is non-portable and risky. Even if you examine the assembly language and see a full 32-bit load, this might change in a future version of the compiler.

If your application requires that all accesses to `RV` in this example be full 32-bit loads, you need to make a copy for the access as in:

>     declare
>        RV_Copy : constant R := RV;
>     begin
>        X := RV_Copy.B;
>     end;

Now the reference to `RV` must read the whole variable. Actually, one can imagine some compiler which figures out that the whole copy is not required (because only the `B` field is actually accessed), but GNAT certainly won’t do that, and we don’t know of any compiler that would not handle this right, and the above code will in practice work portably across all architectures (that permit the Atomic declaration).

The second issue with atomic variables has to do with the possible requirement of generating synchronization code. For more details on this, consult the sections on the pragmas Enable/Disable_Atomic_Synchronization in the :title:`GNAT Reference Manual`. If performance is critical, and such synchronization code is not required, you may find it useful to disable it.