On the one side, the OpenMP specification intentionally omits any specifications concerning interoperability with other programming paradigms and any mixing of C++11 threading with OpenMP is non-standard and vendor-specific. On the other side, compilers (at least GCC) tend to use the same underlying TLS mechanism to implement OpenMP's #pragma omp threadprivate
, C++11's thread_local
and the various compiler-specific storage classes like __thread
.
For example, GCC implements its OpenMP runtime (libgomp) entirely on top of the POSIX threads API and implements OpenMP threadprivate
by placing the variables on the ELF TLS storage. This interoperates with GNU's C++11 implementation that also uses POSIX threads and places thread_local
variables on the ELF TLS storage. Ultimately this interoperates with code that uses the __thread
keyword to specify thread-local storage class and explicit POSIX threads API calls. For example, the following code:
int foo;
#pragma omp threadprivate(foo)
__thread int bar;
thread_local int baz;
int func(void)
{
return foo + bar + baz;
}
compiles into:
.globl foo
.section .tbss,"awT",@nobits
.align 4
.type foo, @object
.size foo, 4
foo:
.zero 4
.globl bar
.align 4
.type bar, @object
.size bar, 4
bar:
.zero 4
.globl baz
.align 4
.type baz, @object
.size baz, 4
baz:
.zero 4
movl %fs:foo@tpoff, %edx
movl %fs:bar@tpoff, %eax
addl %eax, %edx
movl %fs:baz@tpoff, %eax
Here the .tbss
ELF section is the thread-local BSS (uninitialised data). All three variables are created and accessed in the same way.
Interoperability is of less concern right now with other compilers. Intel does not implement thread_local
while Clang still misses OpenMP support.