sourcecode

휘발성 구조의 부재를 분리하기 위한 쓰기 순서는 보존이 보장됩니까?

copyscript 2023. 10. 21. 10:40
반응형

휘발성 구조의 부재를 분리하기 위한 쓰기 순서는 보존이 보장됩니까?

내가 다음과 같은 구조를 가지고 있다고 가정합니다.

volatile struct { int foo; int bar; } data;
data.foo = 1;
data.bar = 2;
data.foo = 3;
data.bar = 4;

과제는 전부 순서가 변경되지 않도록 보장이 되어 있습니까?

예를 들어 휘발성이 없는 경우 컴파일러는 다음과 같이 다른 순서로 두 개의 명령어로 최적화할 수 있습니다.

data.bar = 4;
data.foo = 3;

하지만 휘발성이 있는 상황에서 컴파일러는 이런 일을 하지 말아야 할까요?

data.foo = 1;
data.foo = 3;
data.bar = 2;
data.bar = 4;

(예를 들어 멤버를 서로 관련이 없는 휘발성 개체로 취급하고 foobar가 페이지 경계에 있는 경우 참조의 지역성을 개선하려고 할 수 있습니다.)

또한 C와 C++ 표준의 현재 버전에 대한 답변이 일치합니까?

순서가 변경되지 않습니다.

C176.5.2.3(3)은 다음과 같이 말합니다.

. 연산자와 식별자 뒤에 나오는 후 수정 식은 구조 또는 조합 개체의 멤버를 나타냅니다.값은 명명된 부재의 값, 97)이며 첫 번째 식을 l 값이면 l 값입니다.첫 번째 식에 정규화된 유형이 있으면 지정된 구성원 유형의 정규화된 버전이 결과에 나타납니다.

부터.data가지다volatile-자격형도 마찬가지입니다.data.bar그리고.data.foo. 따라서 당신은 다음과 같은 두 가지 과제를 수행하고 있습니다.volatile int물건들.그리고 6.7.3 각주 136에 의해,

다음과 같이 선언된 개체에 대한 작업volatile 합니다 표현식 평가 규칙이 허용하는 경우를 제외하고는 구현에 의해 "최적화"되거나 재정렬되지 않아야 합니다.

좀 더 미묘한 질문은 컴파일러가 하나의 명령어로 둘 다 할당할 수 있는지 여부입니다. 예를 들어 연속적인 32비트 값일 경우 64비트 저장소를 사용하여 둘 다 설정할 수 있는지 여부입니다.나는 아니라고 생각할 것이고, 적어도 GCC와 Clang은 시도하지 않을 것입니다.

여러 스레드에서 이를 사용하려면 한 가지 중요한 게 있습니다.

컴파일러가 쓰기 순서를 변경하지 않는 동안volatile변수(Nate Eldredge의 답변에서 설명한 바와 같이) 쓰기 순서 변경이 발생할 수 있는 지점이 하나 더 있으며, 그것은 CPU 자체입니다.이는 CPU 아키텍처에 따라 다르며 다음과 같은 몇 가지 예가 있습니다.

인텔 64

Intel® 64 Architecture Memory Ordering 백서를 참조하십시오.

스토어 지침 자체를 재정렬하지는 않지만(2.2):

  1. 매장은 다른 매장과 재배열되지 않습니다.

CPU마다 다른 순서(2.4)로 표시될 수 있습니다.

Intel 64 메모리 주문을 통해 두 개의 프로세서가 서로 다른 순서로 저장소를 볼 수 있습니다.

AMD 64

AMD 64(일반적인 x64)는 사양에서 유사한 동작을 합니다.

일반적으로 잘못된 쓰기는 허용되지 않습니다.순서에 맞지 않게 실행된 쓰기 명령은 모든 이전 명령이 프로그램 순서에 따라 완료될 때까지 결과를 메모리에 커밋(쓰기)할 수 없습니다.그러나 프로세서는 잘못된 쓰기 명령의 결과를 메모리에 커밋할 수 있을 때까지 개인 버퍼(소프트웨어에 보이지 않음)에 보관할 수 있습니다.

파워PC

파워PC CPU를 사용한 Xbox 360에서 주의해야 했던 것으로 기억합니다.

Xbox 360 CPU는 명령어를 재정렬하지는 않지만, 명령어 이후에 완료되는 쓰기 작업을 재정렬합니다.이러한 쓰기 재정렬은 특히 Power에서 허용합니다.PC 메모리 모델

휴대용 방식으로 CPU 순서를 변경하지 않으려면 C++11 std::atomic_thread_fence 또는 C11 atomic_thread_fence와 같은 메모리 펜스를 사용해야 합니다.이 파일이 없으면 다른 스레드에서 볼 수 있는 쓰기 순서가 다를 수 있습니다.

참고: C++11은 표준화된 메모리 모델을 소개했습니다. 그게 무슨 뜻입니까? 그리고 C++ 프로그래밍에 어떤 영향을 미칠까요?

이는 위키피디아 메모리 장벽 기사에도 나와 있습니다.

또한 캐싱, 캐시 코히어런스 프로토콜 및 완화된 메모리 순서 때문에 휘발성 읽기 및 쓰기가 다른 프로세서 또는 코어에 의해 동일한 순서로 표시된다는 보장은 없습니다. 즉 휘발성 변수만으로는 스레드 간 플래그 또는 음소거로 작동하지 않을 수도 있습니다.

언급URL : https://stackoverflow.com/questions/65295907/is-the-order-of-writes-to-separate-members-of-a-volatile-struct-guaranteed-to-be

반응형