How to declare a variable as thread local portably? - c

C11 introduces the _Thread_local storage class specifier that can be used in combination with the static and extern storage class specifiers to declare a variable as thread local. The GNU C compiler suite implements a storage class specifier __thread with the same same semantics.
Unfortunately I did not find any compiler (I tried gcc, clang and SUN studio) that actually implements the _Thread_local keywords. I currently use the following construct to declare a keyword thread_local:
/* gcc doesn't know _Thread_local from C11 yet */
#ifdef __GNUC__
# define thread_local __thread
#elif __STDC_VERSION__ >= 201112L
# define thread_local _Thread_local
#else
# error Don't know how to define thread_local
#endif
I know that this probably does not work with MSVC and other compilers. Can anybody suggest me a better method to declare thread_local in a way that it works in as many compilers as possible?
Edit
Christoph suggested that Microsoft Visual C allows __declspec(thread). This is the updated macro definition:
/* gcc doesn't know _Thread_local from C11 yet */
#ifdef __GNUC__
# define thread_local __thread
#elif __STDC_VERSION__ >= 201112L
# define thread_local _Thread_local
#elif defined(_MSC_VER)
# define thread_local __declspec(thread)
#else
# error Cannot define thread_local
#endif

Combining information from Wikipedia with this list of compiler macros, I came up with the following (untested) version:
#ifndef thread_local
# if __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__
# define thread_local _Thread_local
# elif defined _WIN32 && ( \
defined _MSC_VER || \
defined __ICL || \
defined __DMC__ || \
defined __BORLANDC__ )
# define thread_local __declspec(thread)
/* note that ICC (linux) and Clang are covered by __GNUC__ */
# elif defined __GNUC__ || \
defined __SUNPRO_C || \
defined __xlC__
# define thread_local __thread
# else
# error "Cannot define thread_local"
# endif
#endif

Related

How can I find out without using AUTOCONF exactly what specifier (if any) is supported by a C compiler: inline, __inline__ or __inline?

Our project uses a lot of small one-line inline functions for simple arithmetical calculations. How can we find out exactly what inline specifier is used by user's C compiler: inline, __inline or __inline__?
We looked at how GLIB library does it. The fragment is given below:
/* inlining hassle. for compilers that don't allow the `inline' keyword,
* mostly because of strict ANSI C compliance or dumbness, we try to fall
* back to either `__inline__' or `__inline'.
* we define G_CAN_INLINE, if the compiler seems to be actually
* *capable* to do function inlining, in which case inline function bodys
* do make sense. we also define G_INLINE_FUNC to properly export the
* function prototypes if no inlining can be performed.
* we special case most of the stuff, so inline functions can have a normal
* implementation by defining G_INLINE_FUNC to extern and G_CAN_INLINE to 1.
*/
#ifndef G_INLINE_FUNC
# define G_CAN_INLINE 1
#endif
#ifdef G_HAVE_INLINE // compiler supports the __inline__ specifier
# if defined (__GNUC__) && defined (__STRICT_ANSI__)
# undef inline
# define inline __inline__
# endif
#else /* !G_HAVE_INLINE */
# undef inline
# if defined (G_HAVE___INLINE__)
# define inline __inline__
# else /* !inline && !__inline__ */
# if defined (G_HAVE___INLINE) // compiler supports the __inline specifier
# define inline __inline
# else /* !inline && !__inline__ && !__inline */
# define inline /* don't inline, then */
# ifndef G_INLINE_FUNC
# undef G_CAN_INLINE
# endif
# endif
# endif
#endif
#ifndef G_INLINE_FUNC
# ifdef __GNUC__
# ifdef __OPTIMIZE__
# define G_INLINE_FUNC extern inline
# else
# undef G_CAN_INLINE
# define G_INLINE_FUNC extern
# endif
# else /* !__GNUC__ */
# ifdef G_CAN_INLINE
# define G_INLINE_FUNC static inline
# else
# define G_INLINE_FUNC extern
# endif
# endif /* !__GNUC__ */
#endif /* !G_INLINE_FUNC */
They seem to set G_HAVE_INLINE and G_HAVE__INLINE_ in their very complicated configure file. Is there any way to do it in code without using autotools?
AC_C_INLINE, with this autoconf macro, you can use inline in all cases, provided you include config.h (usual name for the autoconf generated header).

Redundant __thread and omp threadlocal declaration

I am trying to write some library code that may be used by people who have pthreads enabled (or not), and by people who have openmp support (or not). I have some variable that I really want to be in thread-local storage. Is there any potential harm in specifying this twice, for example
#ifdef __GNUC__
# define PREFIX __thread
#elif __STDC_VERSION__ >= 201112L
# define PREFIX _Thread_local
#elif defined(_MSC_VER)
# define PREFIX __declspec(thread)
#else
# define PREFIX
#endif
PREFIX int var = 10;
#pragma omp threadprivate(var)
(Note, the business to figure out the TLS prefix is taken from How to declare a variable as thread local portably?)
I know this works on my system (Debian with recent gcc) but it's hard to know whether things could go wrong elsewhere since these compiler-specific declarations are not part of the OpenMP standard.
What about:
#if __STDC_VERSION__ >= 201112L
# define PREFIX _Thread_local
#elif defined(__GNUC__)
# define PREFIX __thread
#elif defined(_MSC_VER)
# define PREFIX __declspec(thread)
#else
# define PREFIX
#endif
PREFIX int var = 10;
#if !PREFIX
#ifdef _OPENMP
#pragma omp threadprivate(var)
#else
#error "Failure to put variable into TLS"
#endif
#endif
GCC doesn't mind the over-specifying because __thread is an implicit #pragma omp threadprivate anyway.
Instead of worrying about compilers where this might not be the case, just use OpenMP's threadprivate conditionally.

Function name macros which work accross compilers

There are preprocessor macros which define the name of a function inside it, __func__ for g++ and __FUNCTION__ for cl. (func is the c++ standard way of doing this (from dcl.fct.def.general) but it is not implmented everywhere)
For source which will be compiled by both of these compilers what should I do?
I have tried
#ifdef __func__
#define FUNCTION_NAME __func__
#else
#ifdef __FUNCTION__
#define FUNCTION_NAME __FUNCTION__
#else
#error "Function name macro not found"
#endif
#endif
but as it is not in a function the macros are not defined.
I have also tried
void implementation_detail() {
#ifdef __func__
#define FUNCTION_NAME __func__
#else
#ifdef __FUNCTION__
#define FUNCTION_NAME __FUNCTION__
#else
#error "Function name macro not found"
#endif
#endif
}
but that also gives an error.
How can I do this so it will work in multiple compliers?
I have found that there is a boost macro for this, BOOST_CURRENT_FUNCTION.
From looking at the source code here how this is implemented is they use an inline function like so.
inline void current_function_helper()
{
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__) || defined(__DMC__)`
...
(also it is declared in a namespace called detail which is very wise)
I will use this.
EDIT: implementing __func__ will be in the Visual Studio customer technology preview out now, see here.

Serial- / Socket IO and GCC nothrow attribute

I have functions which abstract serial- and socket IO (Linux / Windows) implemented in C.
All of them are marked as extern "C" because they may get called from C++ as well.
Is it safe to use __attribute__((__nothrow__)) (or MinGW Macro __MINGW_NOTHROW) here / can i assume no exceptions are thrown?
Called functions - Sockets:
(not all additions for WinSock listed)
socket
connect
send / recv
close (closesocket on Windows)
sendto / recvfrom
Called functions - Serial:
Since serial IO code differs to much between windows / linux not all are listed here
Linux (GNU)
open
tcgetattr
read / write
close
Windows (MinGW)
CreateFile
GetCommState / SetCommTimeouts
ReadFile / WriteFile
CloseHandle
Since ANSI C has no exceptions (please correct me if I'm wrong) they won't be thrown, but how about GCC extensions and OS API calls?
Documentation: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html (see nothrow).
C
GNU C (Linux) uses __THROW macro instead of __MINGW_NOTHROW.
While the MinGW one is __nothrow__ attribute only, __THROW contains __leaf__ attribute too.
C++
If you use C++, __THROW has another meaning: throw() - indicating that no exception is thrown (analog to __nothrow__; but defined in the C++ standard).
So it depends on whether you compile with C or C++, not on what you call the functions from (GNU C / C++ only!).
Example:
void f() __THROW;
Treated as ...
GNU C:
void f() __attribute__((__nothrow__, __leaf__))
GNU C++:
void f() throw()
Functions1) which are cancellation points, therefore not marked with
__THROW:
open()
read()
write()
close()
connect()
send()
recv()
close()
sendto()
recvfrom()
Functions1) marked with __THROW:
tcgetattr()
socket()
At least, these are save to __nothrow__.
In contrast, MinGW doesn't differ C from C++; in both cases the attribute is set.
Using example from above, __nothrow__ is set on C and C++:
void f() __attribute((__nothrow__))
Functions1) not marked with __MINGW_NOTHROW:
socket()
connect()
send()
recv()
closesocket()
sendto()
recvfrom()
CreateFile()
GetCommState()
SetCommTimeouts()
ReadFile()
WriteFile()
CloseHandle()
To make it short: none!
Compatibility
With C
C language code that is expecting to interoperate with C++ should be
compiled with -fexceptions. This will make debugging a C language
function called as part of C++-induced stack unwinding possible.
In particular, unwinding into a frame with no exception handling data
will cause a runtime abort. If the unwinder runs out of unwind info
before it finds a handler, std::terminate() is called.
Please note that most development environments should take care of
getting these details right. For GNU systems, all appropriate parts of
the GNU C library are already compiled with -fexceptions.
( source: http://gcc.gnu.org/onlinedocs/libstdc++/manual/using_exceptions.html )
So compiling with -fexceptions and there's no need for equivalent attribute. If you only can mark specific functions you have to / should use __nothrow__.
But while using __nothrow__ attribute looks save only on GNU C++, and some functions of GNU C on Linux, it's not that clear on Windows.
Addendum:
To avoid some parts of this problem, i've written a macro similar to __THROW but usable on MinGW too:
#if defined __GNUC__
#ifndef __THROW
#ifdef __cplusplus
#define __THROW throw()
#else
#define __THROW __attribute__((__nothrow__))
#endif
#endif
#else
#define __THROW
#endif
Note: __leaf__ is not included.
1) Talking only about those which are listed on my question.
take care of gcc version, nothrow has been introduced with gcc 3.3!
you can port __THROW from sys/cdefs.h to mingw:
/* skip this entire part on linux (= glibc available)*/
#if defined __GNUC__ && !defined __linux__
/********* port __GNUC_PREREQ macro to mingw *********/
# if !defined __GNUC_PREREQ
# if !defined __MINGW_H
# include <_mingw.h>
# define __GNUC_PREREQ(major, minor) __MINGW_GNUC_PREREQ(major, minor)
# else
# if defined (__GNUC_MINOR__)
# define __GNUC_PREREQ(major, minor) __GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
# else
# define __GNUC_PREREQ(major, minor) 0
# endif
# endif
#endif /* __GNUC_PREREQ */
/********* from gnu c blirary *********/
/* All functions, except those with callbacks or those that
synchronize memory, are leaf functions. */
# if __GNUC_PREREQ (4, 6) && !defined _LIBC
# define __LEAF , __leaf__
# define __LEAF_ATTR __attribute__ ((__leaf__))
# else
# define __LEAF
# define __LEAF_ATTR
# endif
/* GCC can always grok prototypes. For C++ programs we add throw()
to help it optimize the function calls. But this works only with
gcc 2.8.x and egcs. For gcc 3.2 and up we even mark C functions
as non-throwing using a function attribute since programs can use
the -fexceptions options for C code as well. */
# if !defined __cplusplus && __GNUC_PREREQ (3, 3)
# define __THROW __attribute__ ((__nothrow__ __LEAF))
# define __THROWNL __attribute__ ((__nothrow__))
# define __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct
# else
# if defined __cplusplus && __GNUC_PREREQ (2,8)
# define __THROW throw ()
# define __THROWNL throw ()
# define __NTH(fct) __LEAF_ATTR fct throw ()
# else
# define __THROW
# define __THROWNL
# define __NTH(fct) fct
# endif
# endif
#else /* Not GCC. */
# define __inline /* No inline functions. */
# define __THROW
# define __THROWNL
# define __NTH(fct) fct
#endif /* GCC. */
see glibc - sys/cdefs.h for full code.
edit: __GNUC_PREREQ can be replaced with __MINGW_GNUC_PREREQ(major, minor), then you don't have to redifine it as above.

Error C2491 on C source with Visual studio 8

i'm really noob in C. I just need to compile a ANSI C source to get a dll.
During compilation i get this error:
C2491: 'SelectML': definition of dllimport function not allowed
Where SelectML is a public function with this definition:
int CALLINGCONV SelectML(WORD fid, int nSlot)
{
WORD SW;
int x;
BYTE pSend[2];
pSend[0]=(BYTE)((fid&0xff00)>>8);
pSend[1]=(BYTE)(fid&0x00ff);
x=SendAPDUML(hCards[nSlot],APDU_SELECT,2,0,pSend,0,&SW);
if (x!=C_OK) return x;
if (SW!=0x9000) return SW;
return C_OK;
}
I'm sure the C source is good, maybe it is just a Visual Studio configuration...
This is another linked header:
#ifndef LIBSIAECARDT_H
#define LIBSIAECARDT_H
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(USE_STDCALL)
#define USE_STDCALL 1
#endif
#ifdef _WIN32
# if USE_STDCALL == 1
# define CALLINGCONV_1 _stdcall
# else
# define CALLINGCONV_1
# endif
# if defined(LIBSIAE_EXPORTS)
# define LIBSIAEAPI __declspec(dllexport)
# else
# define LIBSIAEAPI __declspec(dllimport)
# endif
# define CALLINGCONV LIBSIAEAPI CALLINGCONV_1
#else // ! _WIN32
# define CALLINGCONV
# define LIBSIAEAPI
# define CALLINGCONV_1
typedef unsigned int UINT;
#endif // _WIN32
It's common to have a macro like CALLINGCONV conditionally defined as __declspec(dllimport) or __declspec(dllexport) so that the same header file can be used in the library source and in the code using the library. Your build should probably define something that makes it use dllexport. Check how CALLINGCONV is defined or (preferably) consult any build documentation that came with the code.
Quoted in MSDN says it all. Do not define the function. Declaration is good. What you are doing here is defining SelectML which for sure is generating your C2491 Error.
Here's an alternative. Stop using MSVC. They explicitly dropped support for anything after C90. Use an actual C compiler for C code.

Resources