[cxx-abi-dev] thread_local CONstructors

Jason Merrill jason at redhat.com
Tue Sep 25 03:49:52 UTC 2012


On 09/24/2012 11:57 AM, Jason Merrill wrote:
> And I guess this means that we can't treat thread_local and __thread as
> equivalent; __thread will still need to require static initialization
> for C compatibility.

Jakub and I discussed this more on IRC today.  It occurred to me that if 
we use a weak reference to the initialization function we can avoid 
breaking compatibility with C code that uses __thread, at least for 
variables that are statically initialized.  So a declaration

extern thread_local int i;

implies

extern void i_init() __attribute__ ((weak));
inline int& i_wrapper()
{
   if (i_init) i_init();
   return i;
}

so uses of i are replaced with calls to i_wrapper, and when i is defined 
we emit i_init iff i has a dynamic initializer.  For a statically 
initialized variable, the runtime penalty is small (just comparing the 
address of a symbol to zero).

Jakub suggested that it would be more efficient for variables that do 
need dynamic initialization to have the wrapper check a guard variable 
before calling the init function rather than from within the init 
function.  We could do that, too:

extern void i_init() __attribute ((weak));
extern thread_local bool i_done __attribute ((weak));
inline int& i_wrapper()
{
   if (i_init && !i_done) i_init();
   return i;
}

Note that we can't test the address of i_done to see if it's defined 
because undefined weak TLS variables resolve to a non-null pointer 
value.  So we test the address of i_init instead.

Either of these maintains link-compatibility with __thread for 
statically initialized variables (and even dynamically-initialized ones 
as long as they are initialized before the C code tries to use them).

Jason



More information about the cxx-abi-dev mailing list