Muchas plataformas tienen formas de actualizar atómicamente bits individuales dentro de un byte, pero lo consiguen de diferentes maneras. Aunque la norma permite el uso de campos de bits dentro de volatile
-el único contexto en el que sería útil sería cuando todas las escrituras en la estructura que contiene el campo de bits se realizan dentro del mismo "hilo" (o contexto de interrupción). Fuera de ese patrón de uso limitado, la única forma de conseguir la semántica conocida en la mayoría de las plataformas es utilizar la manipulación manual de bits junto con las formas específicas de las plataformas de conseguir la semántica requerida.
Por ejemplo, el Cortex-M3 admite instrucciones LDREX/STREX, que se asignan a intrínsecos del compilador. Si el código utiliza LDREX para leer una palabra, calcular un nuevo valor, y luego STREX para intentar escribir el nuevo valor en la misma palabra, el STREX tendrá éxito (e informará de éxito) si no se ha producido ninguna interrupción después del LDREX y nada podría haber perturbado la palabra en cuestión, o fallará (e informará de fallo) sin escribir nada. Si el código quiere poner el bit inferior en un uint32_t volatile foo
podría hacer algo como:
void set_bit_in_foo(void)
{
uint32_t old_value;
do
old_value = __LDREXW(&foo);
while(!__STREXW(old_value | 1, &foo));
}
Si nada accede a foo
entre el __LDREXW
y el __STREXW
y no se produce ninguna interrupción entre ellos, el nuevo valor se escribirá en foo
et __STREXW
devolverá 1. En caso contrario, __STREXW
devolverá 1 y el código lo intentará de nuevo utilizando un valor actualizado de foo
.
Otras plataformas tienen otras formas de permitir las actualizaciones atómicas. C11 intenta añadir características para actualizaciones atómicas para plataformas que las soportan, pero está pobremente especificado en algunos aspectos clave (una implementación que afirma ofrecer cualquier soporte para operaciones atómicas no puede rechazar programas que requieren funciones que la implementación no puede soportar de forma útil, sino que debe proporcionar implementaciones rotas para esas funciones).