2015-10-22 2 views
4

Я использую C11 * atomics для управления перечислением состояний между несколькими потоками. Код напоминает следующее:C11 и C++ 11 atomics: семантика семантики получения и памяти

static _Atomic State state; 

void setToFoo(void) 
{ 
    atomic_store_explicit(&state, STATE_FOO, memory_order_release); 
} 

bool stateIsBar(void) 
{ 
    return atomic_load_explicit(&state, memory_order_acquire) == STATE_BAR; 
} 

This монтирует (для ARM Cortex-M4) в:

<setToFoo>: 
    ldr r3, [pc, #8] 
    dmb sy ; Memory barrier 
    movs r2, #0 
    strb r2, [r3, #0] ; store STATE_FOO 
    bx lr 
    .word 0x00000000 

<stateIsBar>: 
    ldr r3, [pc, #16] 
    ldrb r0, [r3, #0] ; load state 
    dmb sy ; Memory barrier 
    sub.w r0, r0, #2 ; Comparison and return follows 
    clz r0, r0 
    lsrs r0, r0, #5 
    bx lr 
    .word 0x00000000 

Почему заборы, помещенные до выпуск и после приобретаемой? Моя ментальная модель предполагала, что после после будет выпущен барьер (для «распространения» сохраняемой переменной и всех других магазинов в другие потоки) и до приобретать (получать все предыдущие магазины из других потоков).


* В то время как этот конкретный пример приведен в С11, ситуация идентична в C++ 11, так как два одни и те же понятия (и даже те же перечислений), когда речь идет о заказе памяти. gcc и g++ испускают тот же машинный код в этой ситуации. См. http://en.cppreference.com/w/c/atomic/memory_order и http://en.cppreference.com/w/cpp/atomic/memory_order

+0

В 'stateIsBar (аннулируются)', вы имели в виду, чтобы 'return' это выражение? Потому что, как написано, это функция без оператора return, которая не возвращает void. Он должен скомпилировать одну команду возврата (на самом деле, требуется еще и барьер памяти, но не нагрузка). –

+0

Правильно - спасибо за ловушку опечатки. –

ответ

5

Забор памяти перед магазином должен гарантировать, что магазин не заказан перед любыми предыдущими магазинами. Аналогично, забор памяти после считывания гарантирует, что чтение не упорядочено после любого последующего чтения. Когда вы объединяете два, он создает связь с отношением между сообщениями и чтениями.

T1: on-deps(A) -> fence -> write(A) 

T2: read(A) -> fence -> deps-on(A) 

чтения (A) происходит до Deps-на (А)

записи (A) происходит после по-DEPS (A)

Если изменить порядок либо забор, последовательность , что, очевидно, приведет к непоследовательным результатам (например, условиям гонки).

Некоторые более возможным чтение ...

Смежные вопросы