![]() |
![]() |
| |||||||||||||||||
Chapter 8Thread-Local StorageThe compilation environment supports the declaration of thread-local data. This data is sometime referred to as thread-specific, or thread-private data, but more typically by the acronym TLS. By declaring variables to be thread-local, the compiler automatically arranges for these variables to be allocated on a per-thread basis. The built-in support for this feature serves three purposes:
C/C++ Programming InterfaceVariables are declared thread-local using the __thread keyword, as in the following examples:
During loop optimizations, the compiler may choose to create thread-local temporaries as needed.
Thread-Local Storage SectionSeparate copies of thread-local data, allocated at compile-time, must be associated with individual threads of execution. To provide this data, TLS sections are used to specify the size and initial contents. The compilation environment allocates TLS in sections identified with the SHF_TLS flag. These sections provide initialized and uninitialized TLS based on how the storage is declared:
The uninitialized section is allocated immediately following any initialized sections, subject to padding for proper alignment. Together, the combined sections form a TLS template that is used to allocate TLS whenever a new thread is created. The initialized portion of this template is called the TLS initialization image. All relocations generated as a result of initialized thread-local variables are applied to this template. These relocated values are then used when a new thread requires the initial values. TLS symbols have the symbol type STT_TLS. These symbols are assigned offsets relative to the beginning of the TLS template. The actual virtual address associated with these symbols is irrelevant. The address refers only to the template, and not to the per-thread copy of each data item. In dynamic executables and shared objects, the st_value field of a STT_TLS symbol contains the assigned offset for defined symbols, or zero for undefined symbols. Several relocations are defined to support access to TLS. See SPARC: Thread-Local Storage Relocation Types and x86: Thread-Local Storage Relocation Types. Symbols of type STT_TLS are only referenced by TLS relocations. TLS relocations only reference symbols of type STT_TLS. In dynamic executables and shared objects, a PT_TLS program entry describes a TLS template, and has the following members: Table 8-1 ELF PT_TLS Program Header Entry
Runtime Allocation of Thread-Local StorageTLS is created at three occasions during the lifetime of a program:
Thread-local data storage is layed out at runtime as illustrated in Figure 8-1. Figure 8-1 Runtime Storage Layout of Thread-Local Storage ![]() Program StartupAt program startup, the runtime system creates TLS for the main thread. First, the runtime linker logically combines the TLS templates for all loaded dynamic objects, including the dynamic executable, into a single static template. Each dynamic objects's TLS template is assigned an offset within the combined template, tlsoffsetm, as follows:
tlssizem+1 and alignm+1 are the size and alignment, respectively, for the allocation template for dynamic object m (1 <= m <= M, where M is the total number of loaded dynamic objects). The round(offset, align) function returns an offset rounded up to the next multiple of align. The TLS template is placed immediately preceding the thread pointer tpt. Accesses to the TLS data are based off of subtractions from tpt. Next, the runtime linker computes the total startup TLS allocation size, tlssizeS, which is equal to tlsoffsetM. The runtime linker then constructs a linked list of initialization records. Each record in this list describes the TLS initialization image for one loaded dynamic object, and contains the following fields:
The thread library uses this information to allocate storage for the initial thread. This storage is initialized, and a dynamic TLS vector for the initial thread is created. | |||||||||||||||||
| |||||||||||||||||