At 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:
tlsoffset1 = round(tlssize1, align1)
tlsoffsetm+1 = round(tlsoffsetm + tlssizem+1, alignm+1)
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:
A pointer to the TLS initialization image.
The size of the TLS initialization image.
The tlsoffsetm of the object.
A flag indicating whether the object uses a static TLS model.
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.