No, no creo que alguna vez pueda esperar que ++volatile_var
sea atómico, incluso si no tiene la asignación. Usa una primitiva atómica apropiada para eso. Si su compilador no proporciona dicha extensión, puede encontrar fácilmente un ensamblador en línea corto para eso en la web. Las instrucciones del ensamblador son llamadas ldrex
y strex
para intercambio atómico en el brazo, creo.
Editar: Parece que el tipo de procesador específico que se solicita en la pregunta no implementa estas instrucciones.
Editar: Lo siguiente debería funcionar con gcc, para otro compilador probablemente uno tenga que adaptar las partes __asm__
.
inline
size_t arm_ldrex(size_t volatile*ptr) {
size_t ret;
__asm__ volatile ("ldrex %0,[%1]\[email protected] 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]\[email protected] 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;
}
}
Gracias unixsmurf. – JoeSlav
Puede mezclar 'swpb' con' swp' en ARM anteriores para patrones múltiples/únicos. Es decir, ** múltiples indicadores de bandera ** y ** bandera única clara **. Están disponibles hasta cuatro 'bytes' o ** estados **. –