Differences between revisions 2 and 3
Revision 2 as of 2012-10-10 14:52:47
Size: 2161
Comment:
Revision 3 as of 2013-02-19 04:41:48
Size: 2606
Comment: /* Update feature implementation page. */
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
{{{#!wiki caution
This page describes a proposed feature in glibc. It is not approved for inclusion yet.
}}}
== Files ==

 * stdlib/cxa_thread_atexit_impl.c

== Implementation ==
Line 13: Line 15:
             void *dso_handle);              void *dso_symbol);
Line 18: Line 20:
 * DTOR is the destructor to call,
 * OBJ is the object to pass as the first argument of DTOR,
 * DSO_HANDLE is a handle used to identify the DSO this object is defined in.
 * {{{dtor}}} is the destructor to call,
 * {{{obj}}} is the object to pass as the first argument of DTOR,
 * {{{dso_symbol}}} is an object defined within the DSO. This is usually the {{{__dso_handle}}} symbol linked in from {{{crtbegin.o}}} into every DSO.
Line 22: Line 24:
The DSO in which the dso_handle is defined is marked as {{{DF_1_NODELETE}}} so that the DSO is not unloaded on {{{dlclose}}}. {{{__cxa_thread_atexit_impl}}} is called by {{{libstdc++}}} on object construction. In this function, the DSO in which the {{{dso_symbol}}} is defined is marked as {{{DF_1_NODELETE}}} so that the DSO is not unloaded on {{{dlclose}}}. A reference counter is maintained for each DSO to keep track of the thread_local objects constructed or destroyed. That way, when all thread_local objects defined in a DSO are destroyed, the {{{DF_1_NODELETE}}} flag is cleared so that a subsequent {{{dlclose}}} unloads the DSO.
Line 24: Line 26:
The list of destructors of {{{thread_local}}} variables for the thread are maintained in a TLS variable (declared with the {{{__thread}}} keyword) and they are called before pthread thread-specific data is destroyed. As a result, pthread thread-specific data (specifically, destructors for the data) cannot use {{{thread_local}}} variables. The list of destructors of {{{thread_local}}} variables for the thread are maintained in a TLS variable (declared with the {{{__thread}}} keyword). The destructors are called before pthread thread-specific data is destroyed. As a result, pthread thread-specific data (specifically, destructors for the data) cannot use {{{thread_local}}} variables.

Files

  • stdlib/cxa_thread_atexit_impl.c

Implementation

C++11 introduces the thread_local scope for variables that have thread scope. These variables are similar to the TLS variables declared with __thread with a few added features. One of the key features is that they support non-trivial constructors and destructors that are called on first-use and thread exit respectively. Additionally, if the current thread results in a process exit, destructors for thread_local variables should be called for this thread as well.

The compiler can handle constructors, but destructors need more runtime context. It could be possible that a dynamically loaded library defines and constructs a thread_local variable, but is dlclose()'d before thread exit. The destructor of this variable will then have the rug pulled from under it and crash. As a result, the dynamic linker needs to be informed so as to not unload the DSO.

To implement this support, glibc defines __cxa_thread_atexit_impl exclusively for use by libstdc++ (which has the __cxa_thread_atexit to wrap around it), that registers destructors for thread_local variables in a list. Upon thread or process exit, the destructors are called in reverse order in which they were added. The function is defined as:

int __cxa_thread_atexit_impl (void (*dtor) (void *), void *obj,
                              void *dso_symbol);

where

  • dtor is the destructor to call,

  • obj is the object to pass as the first argument of DTOR,

  • dso_symbol is an object defined within the DSO. This is usually the __dso_handle symbol linked in from crtbegin.o into every DSO.

__cxa_thread_atexit_impl is called by libstdc++ on object construction. In this function, the DSO in which the dso_symbol is defined is marked as DF_1_NODELETE so that the DSO is not unloaded on dlclose. A reference counter is maintained for each DSO to keep track of the thread_local objects constructed or destroyed. That way, when all thread_local objects defined in a DSO are destroyed, the DF_1_NODELETE flag is cleared so that a subsequent dlclose unloads the DSO.

The list of destructors of thread_local variables for the thread are maintained in a TLS variable (declared with the __thread keyword). The destructors are called before pthread thread-specific data is destroyed. As a result, pthread thread-specific data (specifically, destructors for the data) cannot use thread_local variables.

None: Destructor support for thread_local variables (last edited 2013-02-19 04:41:48 by SiddheshPoyarekar)