views:

166

answers:

3

How does c++ complier implement thread local storage in C++0x

I have searched this in google. But I can't find anything about this.

Does anyone have any material about this ??

+10  A: 

Have a read of the Wikipedia entry.

Thread-local storage isn't something that's particular to C++. Sometimes it goes by different names, like "TLS" (just an abbreviation of thread-local storage), or "thread-specific storage" (TSS).

Most operating systems provide APIs to access per-thread storage. For example, Windows has a bunch of API functions starting with "TLS". Under the hood, Win32 reserves a special area for a variety of per-thread data, including user thread-local storage, accessible through a particular CPU register (FS on x86). Linux provides thread-specific storage through the pthread APIs, with names like pthread_key_create, and these are generally implemented using a similar technique.

It's possible that an OS doesn't provide any support at all. However, if the OS provides a process-unique thread ID through an API, then the C++ runtime library could maintain something conceptually like a std::map<thread_id, per_thread_storage> internally. Of course, then there's a problem of what per_thread_storage is. If a program was statically linked, it could just be something like a pointer to a big struct with all the thread-local storage variables declared in the program as elements. This is an oversimplification, but you get the general idea.

Accessing thread-local storage variables obviously isn't just a straight memory read or write. It's potentially quite a bit more involved than that. If you are going to use thread-local/specific storage a lot in a particular function, I'd recommend that you copy the thread-local storage pointer into a local variable first.

Doug
You have answered how an application developer can implement TLS but not how the compiler and loader handle the C++0x thread_local key word
doron
@doron: The compiler and loader either use the operating-system provided APIs, or they do something equivalent to map technique themselves, without the application programmer having to write any code.
Doug
+2  A: 

Global variables (or writable static data - WSD) are normally stored in a memory block separate from the stack, heap and code. The WSD block is created and initialised before the executable's code begins to run.

C++0x introduces the thread_local keyword which ensures that a separate instance of the global variable is created per thread. The problem is that a different block needs to be loaded per thread.

The next difficulty is that the address of the variable is not fixed at link time and is different for each thread.

There are two ways round this issue. One is to for the compiler to generate a function call to obtain the correct block while the other is to change the ABI to store the TLS block in one of the processor registers. This can then be used with offsets to access the correct thread_local variable.

This is different from library support where the OS stores a single void* value that can be used store a pointer to a thread local block that has been allocated on the process heap.

If you want the gory details look here.

doron
A: 

You can use boost::thread to portably handle TLS on different platforms. The implementation on each is in the code and should help you understand how different systems handle this area.

Steve Townsend
In C++0x the compiler does support TLS with the thread_local keyword
doron
Using boost's fine, but for the record some compilers have indeed bought into the problem space. http://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Thread-Local.html
Tony
You're right, I'll update this.
Steve Townsend
and C++0x creates a new keyword thread_local which does exactly the same thing as gcc's __thread
doron