10

I am trying to understand how exactly thread_local qualifier works and where the actual variable gets stored? This is on C++.

Say I have a class with multiple member variables. An objet of the class is instantiated on heap and the object is shared between 2 threads. Appropriate locking mechanism is used to ensure two threads are not stomping on a member variable at same time.

There is a need for threads to keep track of few thread specific items. So I am thinking to create a thread_local variable in same header file as the Class declaration. As I understand, both threads will get their own copy of this variable, correct? Where exactly is the thread local variable stored in memory? If data segment, how exactly does the right variable gets picked up during execution?

Ben Connor
  • 103
  • 1
  • 6
  • 4
    I think this is implementation defined. – drescherjm Aug 23 '17 at 19:04
  • 3
    As with where _any_ variables are stored, it's implementation specific. –  Aug 23 '17 at 19:04
  • 5
    What do common implementations do? Say gcc. In general, we can consider dynamic allocations using malloc/new to be on heap, local variables and function arguments to be on stack. Most implementations stick to this. Given this context, where do thread_local variables go? – Ben Connor Aug 23 '17 at 19:10
  • 1
    @Ben Thread local variables are very implementation specific because the underlying OS thread facilities are different (cf Windows, POSIX). –  Aug 23 '17 at 19:20
  • It works by magic. Imagine there's a plain global (mutexed-off or otherwise protected from races) `std::map TLS` somewhere. You can retrieve your TLS with `TLS[std::this_thread::get_id()]`. Actually implementations on x86 use `%fs` (or `%gs` on 32 bits) as the base for the TLS segment. Is that really important? – n. m. could be an AI Aug 23 '17 at 21:45

3 Answers3

8

1. As I understand, both threads will get their own copy of this variable, correct?
Yes. Each thread gets its own copy of the thread_local variable.
2. Where exactly is the thread local variable stored in memory? If data segment, how exactly does the right variable gets picked up during execution?
thread_local is the implementation of the Thread Local Storage concept. TLS is implemented as a table of slots withing each thread object. Each thread having its own copy of the table. For e.g in Windows implementation of TLS this table is within the Thread Information Block of a thread. When a global/static variable is declared as thread_local, it would get associated with a table slot of each thread at the same offset. When the thread_local variable is accessed by a thread then using the current thread context, the thread's own copy of the variable associated with the table slot within this thread object is accessed. Please check this link for more detail on TLS implementation. https://en.wikipedia.org/wiki/Thread-local_storage

Amit Rastogi
  • 926
  • 2
  • 12
  • 22
  • 2
    Is the data stored in the actual table itself? That seems odd, as if you have different sized thread_local objects, there's not a consistent "slot" size. If the table doesn't store the objects themselves, but instead just pointers to the objects, where are the objects themselves being allocated? In either case, where/how is the table itself being allocated in memory, such that it can handle the widely varying number (and size?) of potential thread_local objects? – R.M. Oct 05 '17 at 03:09
7

In the case of 64 bit Windows, the TLS can be accessed via the GS selector register, using a separate physical address space per thread (allocated during CreateThread()), although Visual Studio may map the TLS into a process / thread virtual address space, with each thread getting a different virtual address, since it's a different physical address for each thread. You can look at the disassembled code by stepping into rand() with a debugger to see how it accesses the seed, which is a TLS variable.

rcgldr
  • 27,407
  • 3
  • 36
  • 61
-1

Your descriptions sounds that you want to mark some non-static member var as thread_local. This is not allowed.

thread_local is somewhat like static (global), but specific for each thread while static is shared across all threads

Each thread holds own memory ranges. for example an own stack.

http://en.cppreference.com/w/cpp/language/storage_durationReferen

stefan bachert
  • 9,413
  • 4
  • 33
  • 40
  • 1
    Sorry, if not clear. I want to make a global variable (just declared in same header as of Class declaration) as thread_lcoal. Also, its the same object instance being used by both threads. So member variables are anyway same, hence guarded using locks. – Ben Connor Aug 23 '17 at 19:37
  • 2
    When all threads share the same object, you don't need thread_local. If some threads share an object, you have to pass that information, at thread creation time for example, and you need a thread_local pointer to that object. – stefan bachert Aug 23 '17 at 20:09
  • The object pointer is being passed as you said. No thread_lcoal declaration on that pointer. Few member functions need to know which thread they are being called from. Hence thinking of a thread_local global variable in the header file. – Ben Connor Aug 23 '17 at 20:15