Compiling the fragment struct A { A() {} }; extern A a; #pragma omp threadprivate(a) A a; with svn from yesterday yields LANG=C g++-4.2 -fopenmp -c x.cpp -o x.o x.cpp:6: error: 'a' cannot be thread-local because it has non-POD type 'A' x.cpp:6: error: 'a' is thread-local and so cannot be dynamically initialized It works if I remove the definition of a (last line). I could not find anything in the OpenMP spec (version 2.5) stating that non-POD threadprivate variables are not allowed. If I change the above to struct A { A() {} }; A a; #pragma omp threadprivate(a) I get LANG=C g++-4.2 -fopenmp -c x.cpp -o x.o x.cpp:5: error: 'a' declared 'threadprivate' after first use I believe that both variants are allowed by the OpenMP spec (version 2.5) and they compile fine with icc 8.1. The spec says something about non-POD variaables with explicit initializers in section 2.8.2 on page 69, but that does not apply here. Please correct me if I am wrong.
Guess the message should be sorry rather than error. Without glibc and binutils support for .tinit_array/.tfini_array this really isn't fixable.
Yes, I think that would be good. Then you know that you are not doing something wrong but that it is a tool chain limitation.
Confirmed.
*** Bug 34303 has been marked as a duplicate of this bug. ***
*** Bug 35246 has been marked as a duplicate of this bug. ***
It appears that this underlying issue will also affect C++0x support for thread-local storage, assuming that it also allows non-POD thread-local objects. (See links from http://gcc.gnu.org/projects/cxx0x.html.) This is also looking like it's going to be a significant problem for us in the near future in using OpenMP. Are there GLIBC and binutils issues filed for the necessary underlying functionality that Jakub mentions in comment 1? If so, what are they? If not, what additional information is needed to file a coherent and accurate feature request there?
The first fragment will be supported in GCC 4.8.
The glibc community is aware of this issue. I've added it to our generic todo list from which developers can help coordinate an implementation. http://sourceware.org/glibc/wiki/Development_Todo/Generic
GCC 4.8.0 is being released, adjusting target milestone.
GCC 4.8.1 has been released.
I had added __cxa_thread_atexit_impl to glibc earlier this year to support c++11 thread_local destructors[1][2]. Wouldn't that be good enough support from glibc for openmp too? [1] http://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables [2] http://sourceware.org/git/?p=glibc.git;a=commit;h=ba384f6ed9275f3966505f2375b56d169e3dc588
GCC 4.8.2 has been released.
Hi, this is still broken in the latest git version of gcc. What are the hurdles which need to be accomplished to get this bug fixed?
I spoke to Jason last week and have now confirmed that the first fragment indeed works correctly with 4.8. Declaring a variable threadprivate *after* it is defined is not yet supported, but it should not be very difficult to work around that limitation. I also have confirmation that the glibc support in place for threadprivate/thread_local is sufficient and complete, so I'm closing out the glibc TODO item.
I can now confirm what siddhesh says. with 4.8 the first fragment succeeds, while the second fails. I also tested the git gcc and git glibc, and the first fragment succeeds, while the second fragment still fails.
I've just checked this bug again with ubuntu 14.10. This is with glibc 2.19, and with the master branch of gcc (commit 3c4e189973c43b7f3c2ebb27abf32e9cb175ba82). The first fragment succeeds, but the second fragment still fails.
The second fragment still fails in gcc 5.3.1 (OpenSuse 13.2). I noticed that the C++11 version succeeds: struct A { A() {} }; thread_local A a; Is it possible to migrate this to the OpenMP implementation as well?
As mentioned by Sameer, thread_local now works, but the threadprivate OpenMP directive still fails with a "declared 'threadprivate' after first use" error. My test fragment, is as follows. It should only print a single "ctor" and twice the same set of distinct pointers: #include <cstdio> #include <omp.h> struct Foo { Foo() {puts("ctor");} int a; }; int bar() { int sum=0; // // alternative to omp threadprivate, works with gcc // thread_local Foo local; #pragma omp parallel reduction(+:sum) { static Foo local; #pragma omp threadprivate(local) local.a = omp_get_thread_num(); printf("%p\n", &local); sum += local.a; } printf("%d\n", sum); return sum; } int main(int argc, char** argv) { bar(); bar(); return 0; }
The OpenMP aspect of this is still present in GCC 10, so this bug has beena round for almost *15 years*! Other compilers (LLVM, Intel, ...) happily compile such code. Given that the underlying mechanisms now exist, a fix for the OpenMP aspect really shouldn't be too hard, should it? I really don't want to have to write #if (__GNUC__) // Work around GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27557 // (Scroll near the end...) static thread_local fileStats threadRes; #else static fileStats threadRes; #pragma omp threadprivate (threadRes) #endif in all of my code examples and blog posts, since it just makes GCC look poor.
It actually is hard, otherwise it would be done sooner. There is easy workaround, one can declare the var before actually defining, extern whatever var; #pragma omp threadprivate(var) whatever var; or once OpenMP 5.1 C++ attributes are implemented through whatever var [[omp::directive(threadprivate(var))]]; because in that case threadprivate is visible right on the var definition. The problem is that right now the construction of vars acts as a variable use and it is impossible to distinguish between such definition and some other uses of the variable in between its definition and the threadprivate directive.
Thanks for the workaround, Jakub; it's somewhat perverse, but better than the alternatives!