Wednesday, February 20, 2008

TLS(Thread Local Storage)

Thread-local storage (TLS) as the name indicate is a method to make static or global memory local to a thread.
Separate copies of thread-local data that have been allocated at compile-time, must be associated with individual threads of execution.
This is sometimes needed because all threads in a process share the same address space. In other words,data in a static or global variable is normally always located at the same memory location, when referred to by threads from the same process.
Local Variables are already local to threads, because each thread has its own stack, residing in a different memory location.So TLS is not applicable to local variables.

Take an example how two threads worked and update a common global variable:
If thread A sets the thread local variable to 1, and thread B then sets it to 2, then code running in thread A will continue to see the value 1 for the variable while code running in thread B sees the value 2. In Posix threads this type of variable can be created via pthread_key_create() and accessed via pthread_getspecific() and pthread_setspecific().

These functions work well , but making a function call for each access is awkward and inconvenient. It would be more useful if you could just declare a regular global variable and mark it as thread local. That is the idea of Thread Local Storage (TLS).On a system which supports TLS, any global (or static) variable may be annotated with __thread. The variable is then thread local.

To create and use TLS requires following supports:
1. The compiler.
2. Program linker(Static linker)
3. dynamic linker(Run Time Linker) and some kernel support is also needed(thread library).

The design of TLS on ELF systems fully supports shared libraries, including having multiple shared libraries, and the executable itself, use the same name to refer to a single TLS variable. TLS variables can be initialized. Programs can take the address of a TLS variable, and pass the pointers between threads, so the address of a TLS variable is a dynamic value and must be globally unique.


Following are some Compilers list that are able to create TLS:
Sun Studio C/C++, IBM XL C/C++, GNU C & Intel C/C++
all the aboove compilers uses __thread keyword to create thread local storgae.
Variables are declared thread-local using the __thread keyword, as in the following examples:
__thread int i;
__thread static int j;
__thread char *ptr;




Thread-Local Storage Access Models
---------------------------------------------
Each TLS reference follows one of the following access models.
Defining different storage models for TLS variables.

* Local Executable(Staic TLS): Permits access to TLS variables defined in the executable itself.
This model can only reference TLS variables which are part of the TLS block of the dynamic
executable. The link-editor calculates the thread pointer-relative offsets statically, without the
need for dynamic relocations, or the extra reference to the GOT. This model can not be used to
reference variables outside of the dynamic executable.

* Initial Executable: Permits access to a variable which is known to be part of the TLS image of the executable.
This is true for all TLS variables defined in the executable itself, and for all TLS variables in shared libraries explicitly linked with the executable. This is not true for accesses from a shared library, nor for accesses to TLS variables defined in shared libraries opened by dlopen.

* General(Global) Dynamic: Fully general access to TLS variables from an executable or a shared object.

* Local Dynamic: Permits access to a variable which is bound locally within the executable or shared object from which it is referenced. This is true for all static TLS variables, for example. It is also true for protected symbols.

Following examples shows how to make executable and shared object using these models
1. Local Exec model

Example:
--------

//executable itself
__thread int i;

int
foo()
{
return(i);
}

int
main()
{
foo();
}

2.Initial Exec model

Example:can be in executable or in shared object
-------
extern __thread int i;

int
foo()
{
retun i;
}


3.General (Global)Dynamic

Example:
--------

__thread int i;

int
foo()
{
return(i);
}

4.Local Dynamic

Example:
--------

static __thread int i,j;

int
foo()
{
return (i + j);
}

-----------


For more information Please read:
http://docs.sun.com/app/docs/doc/817-1984/chapter8-1?a=view

No comments: