Ada Programming/Pragmas/Atomic:3

From Wikibooks, open books for an open world
Jump to: navigation, search

It is almost always incorrect to use atomic or volatile variables for tasking.[1] When an object is atomic it just means that it will be read from or written to memory atomically. The compiler will not generate atomic instructions or memory barriers when accessing to that object, it will just:

  • check that the architecture guarantees atomic memory loads and stores,
  • disallow some compiler optimizations, like reordering or suppressing redundant accesses to the object.

For example, the following code, where A is an atomic object can be misunderstood:

A := A + 1;  -- Not an atomic increment!

The compiler will not (and is not allowed by the Standard to) generate an atomic increment instruction to directly increment and update from memory the variable A.[2] This is the code generated by the compiler:

  A := A + 1;
804969f:        a1 04 95 05 08          mov    0x8059504,%eax
80496a4:        40                      inc    %eax
80496a5:        a3 04 95 05 08          mov    %eax,0x8059504

As can be seen, no atomic increment instruction or test-and-set opcode will be generated. Like in other programming languages, if these specific instructions are required in the program they must be written explicitly using machine code insertions.[3]

The above code snippet is equivalent to the following code (both code sequences generates exactly the same object code), where T is a (non-atomic) temporary variable:

T := A;      -- A is copied atomically to local variable T
T := T + 1;  -- local variable T is incremented
A := T;      -- A is stored atomically

Thus it is incorrect to modify an atomic variable at the same time from multiple tasks. For example, two tasks incrementing a counter in parallel. Even in an uniprocessor, other Ada tasking features like a protected object should be used instead. In multiprocessors, depending on the memory consistency model, using various atomic or volatile variables for task communication can have surprising consequences.[2][4] Therefore, extreme care should be taken when using atomic objects for task data sharing or synchronization, specially in a multiprocessor.


Personal tools
Namespaces
Variants
Actions
Navigation
Community
Toolbox
Sister projects
Print/export