SPRAB89A September 2011 – March 2014
Thread-local variables are thread-specific and have static storage duration. They must be allocated similarly to global and static variables that are allocated in the .neardata or .fardata section if they are initialized and .bss if uninitialized. Global and static variables have only one copy per process, whereas thread-locals need a separate instance per thread.
Threads are created by a thread manager when a program calls for the creation of a thread. For example, a parallel region in an OpenMP application makes an OS thread library call to create worker threads; these worker threads will join/merge at the bottom of the parallel region.
During thread creation, the storage for thread-locals must be allocated and initialized. This means there needs to be an initialization image for use in initializing per thread TLS storage. The output of the static linker, the static link unit, must contain a TLS initialization image if thread-local storage is used. The static link unit is referred to as a module.
The TLS initialization image for a single module is called a TLS Image. TLS is allocated for each thread as part of the thread creation and is initialized with the data from the TLS Image. The memory allocated per thread for thread-local variables from a single module is called a TLS Block.
In the static executable model, the static linker produces an executable that is loaded and executed from the start address. RTOS and/or thread libraries are linked in as part of the executable. In this case, there is only one module and hence only one TLS Image and one TLS Block. This simplifies TLS access. The main thread is usually created at program initialization; other threads are created by the threads library. The main thread’s TLS Block should be allocated and initialized by the program loader (see Section 14.3). It is the responsibility of the thread library to allocate and initialize TLS for the threads it creates.
In a C6x Linux system, a program (process) is created by loading multiple modules: an executable and zero or more dynamic libraries. Each module can have a TLS Image. The program’s TLS Image consists of all the modules’ TLS Images. This is called a TLS Template. Normally, the executable and all dependent modules are loaded at process startup. These are called initially loaded modules. A Linux program can also load a dynamic library after startup by calling the dlopen() system function. Modules loaded after startup are called dlopened modules. During thread creation, TLS blocks are created based on the TLS Template. The run-time structure consisting of TLS Blocks from all modules is called TLS.
In the case of bare-metal dynamic linking, by default, there are only initially loaded modules and they can be consecutively placed to form the TLS Template.
See Chapter 14 for more information on C6x program loading and dynamic linking.