I implement user threads on top of the kernel and threads and notice that when a user thread migrates between kernel threads, the variables are thread_localread from the previous kernel location, even when the variables are also marked as volatile.
Because the compiler simply sees the swapcontextuser level as a function call, the following example demonstrates the problem with a simple function call.
#include <stdio.h>
struct Foo {
int x;
int y;
};
__thread Foo* volatile foo;
void bar() {
asm("nop");
}
void f() {
foo->x = 5;
bar();
asm volatile("":::"memory");
foo->y = 7;
}
int main(){
foo = new Foo;
f();
delete foo;
}
. , -fPIC , , . , TL.cc
g++ -std=c++11 -O3 -fPIC -Wall -g TL.cc -o TL
objdump -d TL
f().
400760: 53 push %rbx
400761: 64 48 8b 04 25 00 00 mov %fs:0x0,%rax
400768: 00 00
40076a: 48 8d 80 f8 ff ff ff lea -0x8(%rax),%rax
400771: 48 89 c3 mov %rax,%rbx
400774: 48 8b 00 mov (%rax),%rax
400777: c7 00 05 00 00 00 movl $0x5,(%rax)
40077d: e8 ce ff ff ff callq 400750 <_Z3barv>
400782: 48 8b 03 mov (%rbx),%rax
400785: c7 40 04 07 00 00 00 movl $0x7,0x4(%rax)
40078c: 5b pop %rbx
40078d: c3 retq
40078e: 66 90 xchg %ax,%ax
, rax , bar().
fs?
gcc- , .
g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.