전제 : 나는이 내장 된 ARM (거의 베어 메탈 (bare-metal)) 환경에서 일하고 있어요 어디하지 심지어이 C ++ 11 (와 std::atomic<int>
) 사용할 수, "같은 피하기 답변을 기쁘게 단지 ++ 표준 C를 사용하여std::atomic<int>
" 나는 할 수 없습니다 .
이 ARM 의 AtomicInt 구현 은 정확합니까? (ARM 아키텍처가 ARMv7-A 라고 가정 )
동기화 문제가 있습니까? 그것이 volatile
필요 / 유용?
// File: atomic_int.h
#ifndef ATOMIC_INT_H_
#define ATOMIC_INT_H_
#include <stdint.h>
class AtomicInt
{
public:
AtomicInt(int32_t init = 0) : atom(init) { }
~AtomicInt() {}
int32_t add(int32_t value); // Implement 'add' method in platform-specific file
int32_t sub(int32_t value) { return add(-value); }
int32_t inc(void) { return add(1); }
int32_t dec(void) { return add(-1); }
private:
volatile int32_t atom;
};
#endif
// File: arm/atomic_int.cpp
#include "atomic_int.h"
int32_t AtomicInt::add(int32_t value)
{
int32_t res, prev, tmp;
asm volatile(
"try: ldrex %1, [%3]\n" // prev = atom;
" add %0, %1, %4\n" // res = prev + value;
" strex %2, %0, [%3]\n" // tmp = outcome(atom = res); // may fail
" teq %2, #0\n" // if (tmp)
" bne try" // goto try; /* add failed: someone else modified atom -> retry */
: "=&r" (res), "=&r" (prev), "=&r" (tmp), "+mo" (atom) // output (atom is both in-out)
: "r" (value) // input
: "cc"); // clobbers (condition code register [CPSR] changed)
return prev; // safe return (local variable cannot be changed by other execution contexts)
}
또한 코드 재사용을 시도하고 있으므로 플랫폼 특정 코드 ( add()
메소드 내부 arm/atomic_int.cpp
) 에서 구현할 기본 함수를 하나만 분리했습니다 .
가 atomic_int.h
정말 휴대 가 서로 다른 플랫폼 / 아키텍처 / 컴파일러를 통해 그대로? 이 방법이 가능 합니까? (함께 가능한 내 말은 단지 구현하여 보증 자성에 대한 모든 플랫폼을위한 실현 가능한 add()
방법을 ).
다음 은 동일한 함수의 해당 ARM GCC 8.3.1 구현입니다. 명백하게 유일한 유일한 차이점은 dmb
전후 의 존재입니다 . 그들은 정말로 내 경우에 필요합니까? 왜? 내 AtomicInt
(없이 dmb
)가 실패 하는 예가 있습니까?
업데이트 : 고정 구현, get()
원 자성 및 정렬 문제를 해결하기 위해 메소드가 제거되었습니다 . 이제는 add()
표준처럼 동작합니다 fetchAndAdd()
.
__ATOMIC_INT_H_
)을 포함하는 이름과 밑줄로 시작하고 그 뒤에 대문자로 시작하는 이름은 구현에서 사용하도록 예약되어 있습니다. 코드에서 사용하지 마십시오.
atomic
혼동을 피하는 데 가장 적합하지 std::atomic
않지만 어쨌든 왜 그것을 사용하지 않는지 의문을 제기합니다.
__ATOMIC_INT_H_
식별자의 이름이 변경 되었습니다.
volatile
C ++의 키워드는 변수를 통해 최적화하지 않음을 의미합니다. 따라서get()
방법은 이점이 있습니다. 일반적으로 휘발성은 C ++에서 deprycates하려고합니다. 시스템이 내장 된 32 비트 데이터를 동기화 할 수없는 경우에는 뮤텍스를 사용하는 것이 가장 좋습니다.