4.6. Master and Synchronization Directives

The following sections describe the:

4.6.1. master Construct

The master directive identifies a construct that specifies a structured block that is executed by the master thread of the team. The syntax of the master directive is as follows:

#pragma omp master new-line 
           structured-block

Other threads in the team do not execute the associated structured block. There is no implied barrier either on entry to or exit from the master construct.

4.6.2. critical Construct

The critical directive identifies a construct that restricts execution of the associated structured block to a single thread at a time. The syntax of the critical directive is as follows:

#pragma omp critical [(name)] new-line 
           structured-block

An optional name may be used to identify the critical region. Identifiers used to identify a critical region have external linkage and are in a name space which is separate from the name spaces used by labels, tags, members, and ordinary identifiers.

A thread waits at the beginning of a critical region until no other thread is executing a critical region (anywhere in the program) with the same name. All unnamed critical directives map to the same unspecified name.

4.6.3. barrier Directive

The barrier directive synchronizes all the threads in a team. When encountered, each thread in the team waits until all of the others have reached this point. The syntax of the barrier directive is as follows:

#pragma omp barrier new-line

After all threads in the team have encountered the barrier, each thread in the team begins executing the statements after the barrier directive in parallel.

Note that because the barrier directive does not have a C language statement as part of its syntax, there are some restrictions on its placement within a program. The example below illustrates these restrictions.


/* ERROR - The barrier directive cannot be the immediate
 * substatement of an if statement
 */
if (x!=0) 
         #pragma omp barrier
... 
/* OK - The barrier directive is enclosed in a 
 * compound statement. 
 */ 
if (x!=0) { 
         #pragma omp barrier 
}

4.6.4. atomic Construct

The atomic directive ensures that a specific memory location is updated atomically, rather than exposing it to the possibility of multiple, simultaneous writing threads. The syntax of the atomic directive is as follows:

#pragma omp atomic new-line
     expression-stmt

The expression statement must have one of the following forms:

In the preceding expressions:

Although it is implementation-defined whether an implementation replaces all atomic directives with critical directives that have the same unique name, the atomic directive permits better optimization. Often hardware instructions are available that can perform the atomic update with the least overhead.

Only the load and store of the object designated by x are atomic; the evaluation of expr is not atomic. To avoid race conditions, all updates of the location in parallel should be protected with the atomic directive, except those that are known to be free of race conditions.

Restrictions to the atomic directive are as follows:

Examples:

extern float a[], *p = a, b;
/* Protect against races among multiple updates. */
#pragma omp atomic
a[index[i]] += b;
/* Protect against races with updates through a. */
#pragma omp atomic
p[i] -= 1.0f;

extern union {int n; float x;} u;
/* ERROR - References through incompatible types. */
#pragma omp atomic
u.n++;
#pragma omp atomic
u.x -= 1.0f;

4.6.5. flush Directive

The flush directive, whether explicit or implied, specifies a cross-thread sequence point at which the implementation is required to ensure that all threads in a team have a consistent view of certain objects (specified below) in memory. This means that previous evaluations of expressions that reference those objects are complete and subsequent evaluations have not yet begun. For example, compilers must restore the values of the objects from registers to memory, and hardware may need to flush write buffers to memory and reload the values of the objects from memory.

The syntax of the flush directive is as follows:

#pragma omp flush [(variable-list)]] new-line

If the objects that require synchronization can all be designated by variables, then those variables can be specified in the optional variable-list. If a pointer is present in the variable-list, the pointer itself is flushed, not the object the pointer refers to.

A flush directive without a variable-list synchronizes all shared objects except inaccessible objects with automatic storage duration. (This is likely to have more overhead than a flush with a variable-list.) A flush directive without a variable-list is implied for the following directives:

The directive is not implied if a nowait clause is present. It should be noted that the flush directive is not implied for any of the following:

A reference that accesses the value of an object with a volatile-qualified type behaves as if there were a flush directive specifying that object at the previous sequence point. A reference that modifies the value of an object with a volatile-qualified type behaves as if there were a flush directive specifying that object at the subsequent sequence point.

Note that because the flush directive does not have a C language statement as part of its syntax, there are some restrictions on its placement within a program. The example below illustrates these restrictions.

/* ERROR - The flush directive cannot be the immediate
 * substatement of an if statement.
 */
if (x!=0) 
        #pragma omp flush (x)
...
/* OK - The flush directive is enclosed in a
 * compound statement
 */
if (x!=0) {
        #pragma omp flush (x)
}

Restrictions to the flush directive are as follows:

4.6.6. ordered Construct

The structured block following an ordered directive is executed in the order in which iterations would be executed in a sequential loop. The syntax of the ordered directive is as follows:

#pragma omp ordered new-line
     structured-block

An ordered directive must be within the dynamic extent of a for or parallel for construct. The for or parallel for directive to which the ordered construct binds must have an ordered clause specified as described in Section 4.4.1. In the execution of a for or parallel for construct with an ordered clause, ordered constructs are executed strictly in the order in which they would be executed in a sequential execution of the loop.

There is one restriction to the ordered directive. An iteration of a loop with a for construct must not execute the same ordered directive more than once, and it must not execute more than one ordered directive.