|
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.