Почему барьер приобретения не может остановить переупорядочение вокруг филиала?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Почему барьер приобретения не может остановить переупорядочение вокруг филиала?

Сообщение Anonymous »

Я проверял поведение контрольных зависимостей в барьеры памяти ядра Linux и имел проблему с местоположением забора.
Я тестировал это на Aarch64 на Qualcomm Snapdragon 835, с ARM64 GCC 9.3 и -О3 on.
preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: pre neppet: pre neppet: p> preptet: pre neppet: p> preptet: pre -spipt: pre -spipt: pre -spipt. class = "lang-cpp prettyprint-override">

Код: Выделить всё

std::atomic x;
std::atomic y;

int r1;
int r2;

void thread1_func() {
r1 = x.load(std::memory_order_relaxed);
if (r1) {
r2 = y.load(std::memory_order_relaxed);
}
}

void thread2_func() {
y.store(42, std::memory_order_relaxed);
x.store(1, std::memory_order_release);
}

void thread3_func() {
if (r2 == 0) {
return;
}
if (r1 == 0) {
printf("r2: %d\n", r2);
}
}

int main() {
while (1) {
// reset
x.store(0);
y.store(0);
r1 = 0;
r2 = 0;

std::thread t1(thread1_func);
std::thread t2(thread2_func);
std::thread t3(thread3_func);

t1.join();
t2.join();
t3.join();
}
return 0;
}
thread3_func введет ветвь if (r1 == 0) (мы будем ссылаться на его как ветвь печати ниже), что не то, что я хочу (Thread3 видел побочный эффект thread1 загрузки y r2 с помощью филиала или чего -то). ниже. < /p>
Неправильный забор < /h3>

Код: Выделить всё

void thread1_func() {
r1 = x.load(std::memory_order_acquire);
if (r1) {
r2 = y.load(std::memory_order_relaxed);
}
}
< /code>
или < /p>
void thread1_func() {
r1 = x.load(std::memory_order_relaxed);
if (r1) {
std::atomic_thread_fence(std::memory_order_acquire);
r2 = y.load(std::memory_order_relaxed);
}
}
< /code>
Но эти 2 примера не сработали! < /p>
 'Правильный' Fence < /h3>
, пока я не попробую забор ниже: < /p>
void thread1_func() {
r1 = x.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
if (r1) {
r2 = y.load(std::memory_order_relaxed);
}
}
< /code>
На это время thread3_func < /code> никогда не войдет в ветвь печати. Atomic  
) Пример 1:

Код: Выделить всё

void thread1_func() {
r1.store(x.load(std::memory_order_acquire), std::memory_order_relaxed);
if (r1.load(std::memory_order_relaxed)) {
r2.store(y.load(std::memory_order_relaxed), std::memory_order_relaxed);
}
}

void thread2_func() {
y.store(42, std::memory_order_relaxed);
x.store(1, std::memory_order_release);
}

void thread3_func() {
if (r2.load(std::memory_order_relaxed) == 0) {
return;
}
if (r1.load(std::memory_order_relaxed) == 0) {
printf("r2: %d\n", r2.load(std::memory_order_relaxed));
}
}
Пример 2 просто отличается от thread1_func :
void thread1_func() {
r1.store(x.load(std::memory_order_relaxed), std::memory_order_relaxed);
if (r1.load(std::memory_order_relaxed)) {
std::atomic_thread_fence(std::memory_order_acquire);
r2.store(y.load(std::memory_order_relaxed), std::memory_order_relaxed);
}
}
< /code>
И они оба никогда (5 000 000 итерально, кажется, достаточно, чтобы доказать это) введите ветвь печати, почему атомная версия примера 1,2 никогда не печатает, а неатомная версия делает? Их ASM выглядит ничем не по-меняему.>

Подробнее здесь: https://stackoverflow.com/questions/797 ... d-a-branch
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»