qualifier - Por qué marcar el argumento de la función como volátil
volatile qualifier in c (5)
Actualmente estoy leyendo el código PostgreSql . Aquí hay un extracto del administrador de buffer:
static void WaitIO(volatile BufferDesc *buf);
static bool StartBufferIO(volatile BufferDesc *buf, bool forInput);
static void TerminateBufferIO(volatile BufferDesc *buf, bool clear_dirty,
Sé que la palabra clave volátil generalmente se usa para controladores de dispositivo y en sistemas integrados. Hay una explicación de la palabra clave.
Cuando se utiliza la palabra clave volátil en la definición de tipo, se está dando una indicación al compilador sobre cómo debe manejar la variable. Principalmente le está diciendo al compilador que el valor de la variable puede cambiar en cualquier momento como resultado de acciones externas al programa o la línea de ejecución actual. ( Fuente )
Entonces, ¿por qué ciertos argumentos de funciones se declaran como volátiles? No espero que DMA cambie la ubicación del puntero. Entonces, ¿qué pasa aquí?
No espero que DMA cambie la ubicación del puntero.
No la ubicación, pero tal vez el contenido. Y eso es exactamente de lo que se trata ...
DMA no es la única razón para usar "volátil". También es útil para aplicaciones de multiproceso y memoria compartida, donde otro hilo puede cambiar la memoria a la que hace referencia este código. Estoy seguro de que PostgreSql tiene varios subprocesos, por lo que esta es una posible razón por la cual se está utilizando volátil aquí.
La implementación de las bases de datos no depende de los búferes y memorias caché del sistema operativo al acceder a los archivos. Prefieren implementar su propio sistema de caché y obtener acceso directo al archivo en el disco físico , por cuestiones de confiabilidad: los datos DEBEN ser descargados al disco físico. (Usan la opción O_DIRECT para realizar acceso directo al disco físico).
Las 3 funciones que nos muestra nos hacen pensar en el manejo asíncrono de los datos provenientes del disco. (StartBufferIO (), TerminatedBufferIO () y así sucesivamente). Honestamente, no estoy seguro de cuál es su propósito, pero en base a lo que sé sobre la implementación de las bases de datos y los nombres de las funciones, diría que el contenido del buffer puede ser modificado por el "disco" mismo con datos del archivo en el disco (o cualquier dispositivo) y, por lo tanto, debe ser flagelado como volátil .
Esta hipótesis se une a su interpretación habitual de la palabra clave volátil que se utiliza habitualmente para los controladores de dispositivos.
Una cosa que suele hacer un compilador al optimizar es eliminar el código muerto, por lo que si realizas algunas operaciones con una variable que nunca lee y su resultado es inútil, el compilador probablemente solo lo elimine, además de eliminar el resto de las operaciones que lo afectan. . Ese comportamiento puede ser muy molesto cuando depura un código o estás realizando algún tipo de benchamrks. Si declara una variable volátil, alerta al compilador y podría ser utilizada por bibliotecas o programas externos, entre otras implicaciones que pueda tener la palabra clave. Entonces nunca debería tratarlo como código muerto.
volatile BufferDesc *buf
significa que los datos a los que apunta buf
son volátiles, no que el puntero contenido por buf
sea volátil. (Eso sería BufferDesc * volatile buf
.)
Desde la página a la que vinculó :
Por otro lado, si tiene una variable de puntero donde la dirección en sí misma era volátil pero la memoria señalada no era la siguiente, tenemos:
int * volatile x;
Actualización : Perdón, me perdí esta parte de su pregunta:
Entonces, ¿por qué ciertos argumentos de funciones se declaran como volátiles?
Presumiblemente porque los datos a los que apunta pueden cambiar de una manera que el compilador no necesariamente conocería. La palabra clave volatile
está ahí para evitar que el compilador aplique optimizaciones que asuman que los datos no cambian de una forma que desconoce.