Нет, я не думаю, что вы когда-либо можете ожидать, что ++volatile_var
будет атомарным, даже если у вас нет задания. Для этого используйте подходящий атомарный примитив. Если ваш компилятор не предоставляет такого расширения, вы легко найдете короткий встроенный ассемблер для этого в сети. Я думаю, что ассемблерные инструкции - ldrex
и strex
для атомного обмена на руке.
Редактировать: похоже, что конкретный тип процессора, который запрашивается в вопросе, не реализует эти инструкции.
Редактировать: Следующее должно работать с gcc, для другого компилятора, вероятно, придется адаптировать __asm__
части.
inline
size_t arm_ldrex(size_t volatile*ptr) {
size_t ret;
__asm__ volatile ("ldrex %0,[%1]\t@ load exclusive\n"
: "=&r" (ret)
: "r" (ptr)
: "cc", "memory"
);
return ret;
}
inline
_Bool arm_strex(size_t volatile*ptr, size_t val) {
size_t error;
__asm__ volatile ("strex %0,%1,[%2]\t@ store exclusive\n"
: "=&r" (error)
: "r" (val), "r" (ptr)
: "cc", "memory"
);
return !error;
}
inline
size_t atomic_add_fetch(size_t volatile *object, size_t operand) {
for (;;) {
size_t oldval = arm_ldrex(object);
size_t newval = oldval + operand;
if (arm_strex(object, newval)) return newval;
}
}