Я использую пользовательскую реализацию сопрограмм в C ++ (компилятор g ++, на ARM). Сопрограммы могут мигрировать из одного потока в другой, вызывая функцию move_to_thread (или другими способами, но это позволит мне высказать свое мнение). Я упрощаю, но это примерно так:
__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
}
У меня проблема в том, что работа, выполненная до и после вызова move_to_thread, использует локальные переменные потока (используя __thread
). При компиляции с оптимизацией код, выполняющийся в потоке 2, по-прежнему получает доступ к локальным переменным потока 1 вместо своих собственных. Это потому, что доступ к локальной переменной потока делает следующее:
Однако при включенной оптимизации (1) и, возможно, (2) оптимизируются для второго доступа, поскольку компилятор предполагает, что функция, которая начинает выполняться в определенном потоке, останется в этом потоке. Это предположение не верно для моего кода.
Как я могу заставить компилятор посмотреть на правильное локальное хранилище потока как до, так и после вызова move_to_thread, не покончив с оптимизацией полностью?
Что произойдет, если вы попытаетесь объявить свою переменную следующим образом:
__thread int volatile x = 0;
Это должно помешать компилятору кэшировать значение (хотя я не уверен, как volatile взаимодействует с __thread).
Других решений пока нет …