Después de mirar un montón de otras preguntas y sus respuestas , tengo la impresión de que no hay un acuerdo generalizado sobre lo que significa exactamente la palabra clave "volátil" en C
Incluso el estándar en sí no parece ser lo suficientemente claro como para que todos estén de acuerdo en lo que significa .
Entre otros problemas:
- Parece proporcionar diferentes garantías dependiendo de su hardware y de su compilador.
- Afecta las optimizaciones del compilador pero no las optimizaciones de hardware, por lo que en un procesador avanzado que realiza sus propias optimizaciones de tiempo de ejecución, ni siquiera está claro si el compilador puede evitar cualquier optimización que desee evitar. (Algunos compiladores generan instrucciones para evitar algunas optimizaciones de hardware en algunos sistemas, pero esto no parece estar estandarizado de ninguna manera).
Para resumir el problema, parece (después de leer mucho) que "volátil" garantiza algo como: El valor se leerá / escribirá no solo desde / a un registro, sino al menos a la caché L1 del núcleo, en el mismo orden que las lecturas / escrituras aparecen en el código. Pero esto parece inútil, ya que leer / escribir desde / a un registro ya es suficiente dentro del mismo hilo, mientras que coordinar con la caché L1 no garantiza nada más con respecto a la coordinación con otros hilos. No puedo imaginar cuándo podría ser importante sincronizar solo con caché L1.
USO 1
El único uso ampliamente aceptado de volátil parece ser para sistemas antiguos o integrados donde ciertas ubicaciones de memoria están asignadas por hardware a funciones de E / S, como un bit en la memoria que controla (directamente, en el hardware) una luz , o un bit en la memoria que le indica si una tecla del teclado está presionada o no (porque está conectada directamente por el hardware a la tecla).
Parece que el "uso 1" no ocurre en el código portátil cuyos objetivos incluyen sistemas multi-core.
USE 2
No es muy diferente de "use 1" es la memoria que un manejador de interrupciones puede leer o escribir en cualquier momento (que puede controlar una luz o almacenar información de una tecla). Pero ya para esto tenemos el problema de que, dependiendo del sistema, el controlador de interrupciones podría ejecutarse en un núcleo diferente con su propia memoria caché , y "volátil" no garantiza la coherencia de la memoria caché en todos los sistemas.
Así que "usar 2" parece estar más allá de lo que puede ofrecer "volátil".
USO 3
El único otro uso indiscutible que veo es evitar la optimización incorrecta de los accesos a través de diferentes variables que apuntan a la misma memoria que el compilador no se da cuenta de que es la misma memoria. Pero esto probablemente solo sea indiscutible porque la gente no está hablando de eso, solo vi una mención al respecto. Y pensé que el estándar C ya reconocía que los punteros "diferentes" (como diferentes argumentos para una función) podrían apuntar al mismo elemento o elementos cercanos, y ya especifiqué que el compilador debe producir código que funcione incluso en tales casos. Sin embargo, no pude encontrar rápidamente este tema en el último estándar (¡500 páginas!).
¿Entonces "usar 3" tal vez no existe ?
De ahí mi pregunta:
¿"Volátil" garantiza algo en absoluto en el código C portátil para sistemas de múltiples núcleos?
EDITAR - actualizar
Después de examinar el último estándar , parece que la respuesta es al menos un sí muy limitado:
1. El estándar especifica repetidamente un tratamiento especial para el tipo específico "volatile sig_atomic_t". Sin embargo, el estándar también dice que el uso de la función de señal en un programa multiproceso da como resultado un comportamiento indefinido. Por lo tanto, este caso de uso parece limitado a la comunicación entre un programa de subproceso único y su controlador de señal.
2. La norma también especifica un significado claro para "volátil" en relación con setjmp / longjmp. (El código de ejemplo donde importa se da en otras preguntas y respuestas ).
Entonces, la pregunta más precisa es:
¿"volátil" garantiza algo en absoluto en el código C portátil para sistemas de múltiples núcleos, aparte de (1) permitir que un programa de un solo subproceso reciba información de su controlador de señal, o (2) permitir setjmp código para ver variables modificadas entre setjmp y longjmp?
Esta sigue siendo una pregunta de sí / no.
En caso afirmativo, sería genial si pudiera mostrar un ejemplo de código portátil sin errores que se vuelve defectuoso si se omite "volátil". Si "no", entonces supongo que un compilador es libre de ignorar "volátil" fuera de estos dos casos muy específicos, para objetivos de múltiples núcleos.
volatile
específicamente, lo cual creo que es necesario.
volatile
para informar al programa que puede cambiar de forma asincrónica.