Is there any way to determine whether -c11 was passed to the compiler or, better yet, whether TLS is supported? It would also be acceptable to use a PGI-specific construct, if one exists (preferable, even, if it doesn't require a special flag). Basically, I'm trying to port something like this to PGI:
Code: Select all
#if defined(_Thread_local) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) # define THREAD_LOCAL _Thread_local #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__) # define THREAD_LOCAL __thread #elif defined(_WIN32) # define THREAD_LOCAL __declspec(thread) #else # error No TLS implementation found. #endif
__STDC_VERSION__ is defined as 199901L even if -c11 is passed, so my current code emits an error. I can understand that; PGI's C11 support is still incomplete, so advertising it in __STDC_VERSION__ would be premature. Unfortunately, though, it puts me in a tough spotâ€¦ AFAICT there is no way to tell in the preprocessor whether the compiler supports _Thread_local.
Normally I would use __PGIC__, __PGIC_MINOR__, and __PGIC_PATCHLEVEL__ to check for support (and ignore __STDC_VERSION__), but since TLS only works in C11 mode (unlike other compilers) that doesn't do much good. I've also tried using C11 macros like __STDC_NO_THREADS__ and __STDC_NO_ATOMICS__ in hopes of detecting whether PGI is in C11 mode, but unlike _Thread_local they're defined in PGI's C99 mode, too.
As for atomics, is there some variant of atomics which PGI supports that I'm missing? I already have support for
* Old GCC-style (__sync_*)
* New GCC-style (__atomic_*)
* clang-style (__c11_*)
* C11-style (stdatomic.h)
* MS-style (Interlocked*)
I'm happy to add another method, but I can't seem to figure out how to do atomics in PGI. So far my best guess is to require OpenACC or maybe OpenMP, but that's some pretty significant overhead and I'd strongly prefer something which doesn't require a compiler flag; this is for a reusable header which you can currently just drop into any C project and be done with it.
Also, I have a PRNG which requires CAS (or a lock), but I don't see a way to do an atomic compare and swap with OpenACC. This seems like an odd omissionâ€¦ am I missing something, or should I just fall back on a spinlock for OpenACC?