2016-07-26 3 views
6

코드베이스는 COMPILER_BARRIER 매크로가 __asm__ volatile("" ::: "memory")으로 정의됩니다. 매크로의 목적은 컴파일러가 장벽을 가로 질러 읽기 및 쓰기를 다시 정렬하지 못하게하는 것입니다. 이것은 명시 적으로 컴파일러 장벽이며 이 아니며 프로세서 레벨 메모리 장벽이이 아닙니다.C++ 11 atomic API는```__asm__ volatile (""::: "memory")와 같습니다.

사실, 어셈블러 템플릿에는 실제 어셈블리 지침이 없으므로 이식성이 뛰어납니다. volatilememory 등이 있습니다. 컴파일러가 GCC Extended Asm 구문을 존중하는 한 잘 작동합니다. 여전히, 나는 이것을 표현하는 올바른 방법이 가능하다면 C++ 11 atomics API에 무엇이 될지 궁금하다.

다음과 같이 생각하면 올바른 생각 일 수 있습니다. atomic_signal_fence(memory_order_acq_rel);. 그 인

내 추론은 다음 <atomic> API를

  • atomic_signal_fenceatomic_thread_fence가 작동하는에 대한 메모리 주소를 필요로하지 않습니다.
  • atomic_thread_fence은 메모리 순서 지정에 영향을 미치며 컴파일러 장벽에는 필요하지 않습니다.
  • 확장 Asm 버전에있는 memory은 읽기와 쓰기를 구별하지 않으므로 취득 의미와 릴리스 의미가 모두 필요하므로 최소한 memory_order_acq_rel이 필요합니다.
  • memory_order_seq_cst은 불필요한 것처럼 보입니다. 스레드간에 전체 주문이 필요하지 않으므로 현재 스레드 내에서 명령 순서 지정에만 관심이 있습니다.

__asm__ volatile("" ::: "memory")과 동등한 것을 C++ 11 atomics API로 이식 할 수 있습니까? 그렇다면 atomic_signal_fence 올바른 API를 사용할 수 있습니까? 그렇다면, 여기에 적절한 메모리 순서 인수는 무엇입니까?

아니면 여기서 잡초를 제거해도 좋을까요? 더 좋은 방법이 있습니까?

+1

'atomic_signal_fence '는 동일한 스레드에서 실행중인 신호 처리기와 스레드 사이의 순서 만을 보장합니다. 비슷하게'atomic_thread_fence'는 쓰레드 간의 정렬에만 적용됩니다. 두 개의 다른 컨텍스트 사이에서 순서를 보장하려고한다면 둘 다 이식성이 없습니다. 예를 들어 Windows에서'atomic_signal_fence'는 Windows가 비동기 신호를 지원하지 않기 때문에 아무 것도 할 필요가 없습니다. –

+0

@RossRidge - atomic_signal_fence를 사용하는 것에 약간 이상하다고 느꼈습니다. 왜냐하면, 여러분이 지적했듯이, 여기에는 신호가 없습니다. 그러나 위의 개요에 따르면 "일한"것이 유일한 것입니다. 구현에 비동기 신호가 없으면 atomic_signal_fence 호출을 생략 할 수 있지만 표준에서 어떤 언어도 보지 못했습니다. C++ 14 표준의 28.9.7에서 "컴파일러 최적화 및로드 및 저장 순서 재 지정이 atomic_thread_fence와 같은 방식으로 금지되지만 하드웨어 펜스 명령어는 방출되지 않습니다."라고 명시되어 있습니다. – acm

+0

이것은 유익한 (비표준적인) 주석이며, 구현에 제약을 두지 않습니다. 이 표준은 "atomic_thread_fence (order)와 동등한 것"이 아닌 다른 것에 의존 할 수있는 언어를 제공하지 않는다. 단, 결과적으로 발생하는 순서 제약 조건은 스레드와 동일한 스레드에서 실행되는 신호 처리기 사이에서만 설정된다는 점만 다르다. . 'atomic_thread_fence'는 표준에 정의 된 원자 객체에 대한 원자 연산으로 정의됩니다. 따라서'std :: atomic' 타입을 사용하지 않는다면 어느 함수도 작동하지 않을 것입니다. –

답변

3

__asm__ volatile("" ::: "memory")도 완벽한 컴파일러 장벽이 아닙니다. asm 블록에 잠재적으로 액세스 할 수있는 주소를 가진 객체에 대한로드/저장소의 순서 지정 만 강제합니다. 컴파일러가 주소가 누출되지 않는다고 추적 할 수있는 로컬 변수는 포함하지 않습니다. 예를 들어 memset(password, 0, len); 다음에 __asm__ volatile("" ::: "memory");password[]이 사용하는 메모리를 실제로 0으로 만들지 못할 수 있습니다.

이것은 입력과 같은 객체의 주소를 asm 블록에 전달하여 해결할 수 있지만 atomic_signal_fence과 완벽하게 일치하는 것을 볼 수 없습니다. 아마도 가장 가까운 포인터는 객체의 주소를 외부 연결 고리 volatile 포인터 객체에 저장하는 것입니다 (포인터가 아닌 포인터를 만드는 데주의해야합니다. volatile -qualified). 그런 다음 atomic_signal_fence은 다음과 같이 가정해야합니다. 신호 처리기에서 액세스 할 수 있습니다.

+0

이것은 매우 유용한 관찰입니다. 매크로가 실제로 의도 한대로 매크로가 작동하는지 궁금해합니다. – acm

관련 문제