Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I force g++ on Linux to update the thread pointer (for TLS) when a coroutine switches threads?

I'm using a custom implementation of coroutines in C++ (compiler g++, on ARM). The coroutines might migrate from one thread to another by calling a move_to_thread function (or other ways, but this will let me make my point). I'm oversimplifying, but it's kind of like this:

__thread int x = 0;

void f() {
    x = 5;
    // do some more work on current thread (thread 1, say)
    move_to_thread(2);
    // do more work, now on thread 2
    int y = x; // with optimization, I'm getting the wrong x
}

The problem I'm having is that the work done before and after calling move_to_thread uses thread-local variables (using __thread). When compiling with optimization, the code running on thread 2 still accesses thread 1's thread-local variables instead of its own. It's because an access to a thread-local variable does the following:

  1. Look up the TLS thread pointer for the current thread
  2. Add x's TLS offset to the thread pointer
  3. Use the memory at this address as x

However, with optimization enabled, (1) and maybe (2) are being optimized away for the second access, since the compiler assumes a function that begins running on a particular thread will stay on that thread. This assumption is not true for my code.

How can I get the compiler to look at the correct thread-local storage both before and after the call to move_to_thread, without doing away with optimizations completely?

like image 719
davidthomas Avatar asked Oct 21 '22 21:10

davidthomas


1 Answers

What happens if you try declaring your variable as follows:

__thread int volatile x = 0;

That should prevent the compiler from caching the value (though I'm not sure how volatile interacts with __thread).

like image 116
coffeemug Avatar answered Oct 23 '22 19:10

coffeemug