OK, say that I have
__thread int myVar;
And I then pass &myVar from one thread to another ... If the data is truly "local", then the TLS storage of 1 thread may not be mapped into the other threads address space, and in fact, you could argue that it shouldn't be. This would result in a SIGSEGV or something. However, the system could just map the same address to a different page. Is this what Linux does with .tbss/.tdata? In that case, passing the address of a variable would give you the address of the wrong variable! You'd get your own local copy and not the copy you tried to pass. Or, is everything shared and mapped to different virtual addresses - allowing you to pass around addresses of __thread vars?
Obviously, one should be beaten and flogged for trying to pass thread local storage to another thread by passing its address. There are a million other ways - copying to any other variable for example! But, I was curious if anyone knew ..
- The official described behavior in this situation
- The current GCC/Linux implementation details
-- Evan
For x86 at least, TLS is performed using segment registers. The default segment register %ds
is implicit in instructions that address memory. When accessing TLS, a thread uses another segment register - %gs
for i386 and %fs
for x86-64 - which is saved/restored when a thread is scheduled, just as other registers are in a context switch.
So a process-wide variable might be accessed with something like:
mov (ADDR) -> REG ; load memory `myVar` to REG.
which is implicitly:
mov %DS:(ADDR) -> REG
For TLS, the compiler generates:
mov %FS:(ADDR) -> REG ; load thread-local address `myVar` to REG.
In effect, even if the address of the variable appears to be the same in different threads, e.g.,
fprintf(stdout, "%p\n", & myVar); /* in separate threads... */
the fact each thread is using a different value for the segment register, means that they map to different regions of physical memory. If you were to pass an address from one thread to another, you couldn't access the memory it represents in the first thread - a different segment register value is in effect in the second thread.
The same scheme is used by Windows (it may interchange the roles of %fs
and %gs
- not sure), and OS X. As for other architectures, there's an in-depth technical guide to TLS for the ELF ABI. It's missing a discussion of the ARM architecture, and has details on IA-64 and Alpha, so it's showing its age.
来源:https://stackoverflow.com/questions/24793556/addresses-of-thread-local-storage-variables