THREADLOCAL
Purpose
You can use the THREADLOCAL directive to declare thread-specific common data. It is a possible method of ensuring that access to data that is contained within COMMON blocks is serialized.
In order to make use of this directive it is not necessary to specify the -qsmp compiler option, but the invocation command must be xlf_r, xlf_r7, xlf90_r, xlf90_r7, xlf95_r, xlf95_r7, xlf2003_r, or xlf2008_r to link the necessary libraries.
Syntax
Rules
You can only declare named blocks as THREADLOCAL. All rules and constraints that normally apply to named common blocks apply to common blocks that are declared as THREADLOCAL. See the COMMON statement for more information on the rules and constraints that apply to named common blocks.
The THREADLOCAL directive must appear in the specification_part of the scoping unit. If a common block appears in a THREADLOCAL directive, it must also be declared within a COMMON statement in the same scoping unit. The THREADLOCAL directive may occur before or after the COMMON statement. See Main program for more information on the specification_part of the scoping unit.
A common block cannot be given the THREADLOCAL attribute if it is declared within a PURE subprogram.
Members of a THREADLOCAL common block must not appear in NAMELIST statements.
A common block that is use-associated must not be declared as THREADLOCAL in the scoping unit that contains the USE statement.
Any pointers declared in a THREADLOCAL common block are not affected by the -qinit=f90ptr compiler option.
Objects within THREADLOCAL common blocks may be used in parallel loops and parallel sections. However, these objects are implicitly shared across the iterations of the loop, and across code blocks within parallel sections. In other words, within a scoping unit, all accessible common blocks, whether declared as THREADLOCAL or not, have the SHARED attribute within parallel loops and sections in that scoping unit.
- Explicitly, via pthreads library calls
- Implicitly by the compiler for parallel loop execution
- Implicitly by the compiler for parallel section execution.
If a common block is declared to be THREADLOCAL in one scoping unit, it must be declared to be THREADLOCAL in every scoping unit that declares the common block.
If a THREADLOCAL common block that does not have the SAVE attribute is declared within a subprogram, the members of the block become undefined at subprogram RETURN or END, unless there is at least one other scoping unit in which the common block is accessible that is making a direct or indirect reference to the subprogram.
You cannot specify the same common_block_name for both a THREADLOCAL directive and a THREADPRIVATE directive.
SUBROUTINE FORT_SUB(IARG)
INTEGER IARG
CALL LIBRARY_ROUTINE1()
CALL LIBRARY_ROUTINE2()
...
END SUBROUTINE FORT_SUB
SUBROUTINE LIBRARY_ROUTINE1()
COMMON /BLOCK/ R ! The SAVE attribute is required for the
SAVE /BLOCK/ ! common block because the program requires
! that the block remain defined after
!IBM* THREADLOCAL /BLOCK/ ! library_routine1 is invoked.
R = 1.0
...
END SUBROUTINE LIBRARY_ROUTINE1
SUBROUTINE LIBRARY_ROUTINE2()
COMMON /BLOCK/ R
SAVE /BLOCK/
!IBM* THREADLOCAL /BLOCK/
... = R
...
END SUBROUTINE LIBRARY_ROUTINE2
SUBROUTINE FORT_SUB()
COMMON /BLOCK/ J
INTEGER :: J
!IBM* THREADLOCAL /BLOCK/ ! Each thread executing FORT_SUB
! obtains its own copy of /BLOCK/
INTEGER A(10)
...
!IBM* INDEPENDENT
DO INDEX = 1,10
CALL ANOTHER_SUB(A(I))
END DO
...
END SUBROUTINE FORT_SUB
SUBROUTINE ANOTHER_SUB(AA) ! Multiple threads are used to execute ANOTHER_SUB
INTEGER AA
COMMON /BLOCK/ J ! Each thread obtains a new copy of the
INTEGER :: J ! common block /BLOCK/
!IBM* THREADLOCAL /BLOCK/
...
AA = J ! The value of 'J' is undefined.
END SUBROUTINE ANOTHER_SUB