Chapter 4. Data Layout #pragma Directives

Table 4-1 lists the #pragma directives discussed in this chapter, along with a short description of each and the compiler versions in which the directive is supported.

Table 4-1. Data Layout #pragma Directives

#pragma

Short Description

Compiler Versions

#pragma align_symbol

Specifies alignment of user variables, typically at cache-line or page boundaries.

7.2 and later

#pragma fill_symbol

Tells the compiler to insert any necessary padding to ensure that the user variable does not share a cache-line or page with any other symbol.

7.2 and later

#pragma pack

Controls the layout of structure offsets, such that the strictest alignment for any structure member will be n bytes, where n is 0, 1, 2, 4, 8, or 16. When n is 0, the compiler returns to default alignment for any subsequent struct definitions.

7.0 and later


#pragma align_symbol

The #pragma align_symbol directive specifies the alignment of user variables, typically at cache-line or page boundaries.

The syntax of the #pragma align_symbol directive is as follows:

#pragma align_symbol [symbol, size]

The first argument to this directive is a symbol. The symbol can be a global or automatic variable, but it cannot be a formal parameter to a function, or an element of a structured type such as a structure or array.

The second argument, size, can be any one of the following:

  • L1cacheline, a machine-specific first-level cache-line size, typically 32 bytes

  • L2cacheline, a machine-specific second-level cache-line size, typically 128 bytes

  • page, a machine specific page size, typically 16 Kilobytes

  • a user-specified value, which must be a power of two

The #pragma align_symbol directive aligns the start of symbol at the specified alignment boundary.

For global variables, this directive must be specified where the variable is defined. The directive is optional where the variable is declared.


Caution: When using the #pragma align_symbol directive, there are two points to keep in mind:

  • The #pragma align_symbol directive is ineffective for local variables of fixed-size symbols, such as simple scalars or arrays of known size. Theis directive is most effective for stack-allocated arrays of dynamically determined size.

  • A variable cannot have both #pragma fill_symbol and #pragma align_symbol directives applied to it.



Example 4-1. #pragma align_symbol

The following code fragment illustrates the use of the #pragma align_symbol directive:

int x;                         
/* x is a global variable */

#pragma align_symbol (x, 32)   
/* x will start at a 32-byte boundary */

#pragma align_symbol (x, 2)    
/* Error: cannot request an alignment 
lower than the natural alignment of the symbol. */


#pragma fill_symbol

The #pragma fill_symbol directive instructs the compiler to insert any necessary padding to ensure that the user variable does not share a cache-line, page, or other specified block of memory with any other symbol.

The syntax of the fill_symbol pragma is as follows:

#pragma fill_symbol [symbol, size]

The first argument to this pragma is a symbol. The symbol can be a global or automatic variable, but it cannot be a formal parameter to a function, or an element of a structured type such as a structure or array.

The second argument can be any one of the following:

  • L1cacheline, a machine-specific first-level cache-line size, typically 32 bytes

  • L2cacheline, a machine-specific second-level cache-line size, typically 128 bytes

  • page, a machine specific page size, typically 16 kilobytes

  • a user-specified value that must be a power of two

The #pragma fill_symbol directive pads the named symbol with additional storage so that the symbol is assured not to overlap with any other data item within the storage of the specified size. The additional padding required is heuristically divided between each end of the specified variable.

For instance, a #pragma fill_symbol directive for the L1cacheline guarantees that the specified symbol will not suffer from false-sharing (multiple, unrelated symbols sharing the same cache line) between multiple processors for the L1 cache line.

For global variables, this directive must be specified where the variable is defined. The directive is optional where the variable is declared.

A variable cannot have both #pragma fill_symbol and #pragma align_symbol directives applied to it.

Example 4-2. #pragma fill_symbol

The following code fragment illustrates the use of #pragma fill_symbol:

double y;                             
/* y is a global or local variable */
#pragma fill_symbol (y, L2cacheline)  
/* Allocates extra storage 
   both before and after y so that 
   y is within an L2cacheline (128 
   bytes) all by itself. */


#pragma pack

The #pragma pack directive controls the layout of structure offsets. The strictest alignment for any structure member is the specified number of bytes (1, 2, 4, 8, or 16).

The syntax of the #pragma pack directive is as follows:

#pragma pack [n]

The #pragma pack directive works according to the following rules:

  • A struct type defined in the scope of a #pragma pack has up to n bytes of alignment, where n is 0, 1, 2, 4, 8, or 16. When n is 0, the compiler returns to default alignment for any subsequent structure definitions.

  • The packed characteristics of the type apply wherever the type is used, even outside the scope of the pragma in which the type was declared.

  • The scope of a #pragma pack ends with the next #pragma pack, hence this pragma does not nest. There is no way to “return” from one instance of the directive to a lexically earlier instance of the directive.


Caution:

  • SGI strongly discourages the use of #pragma pack , because it is a nonportable feature and the semantics of this directive may change in future compiler releases.

  • A structure declaration must be subjected to identical instances of a #pragma pack directive in all files, or else misaligned memory accesses and erroneous structure member dereferencing may ensue.

  • References to fields in packed structures may be less efficient than references to fields in unpacked structures.

  • The #pragma pack directive is not supported for C++ in -n32 and -64 modes.