Linux: ¿Por qué sig_atomic_t se define como int?

8 minutos de lectura

Linux: ¿Por qué sig_atomic_t se define como int?
smcdow

En mi caja de Linux, sig_atomic_t es un simple viejo int. Hacer ints posee una cualidad atómica especial?

$ gcc -v
Using built-in specs.
Target: x86_64-linux-gnu
...
Thread model: posix
gcc version 4.3.2 (Debian 4.3.2-1.1) 

$ echo '#include <signal.h>' | gcc -E - | grep atomic
typedef int __sig_atomic_t;
typedef __sig_atomic_t sig_atomic_t;

  • @chrisaycock: C? ¿No se aplicaría esto a cualquier idioma con acceso a sig_atomic_t variables? Podría haber usado con la misma facilidad g++.

    – smcdow

    7 de marzo de 2012 a las 18:55


  • los sig_atomic_t type es en realidad parte de la especificación C. También se encuentra en la especificación C++ (como la mayoría de las cosas), pero es más probable que obtenga buenas respuestas con una etiqueta C.

    -Dietrich Epp

    07/03/2012 a las 19:31

  • C no garantiza eso. Las CPU específicas tienen garantías específicas para la atomicidad de ciertos tipos. En particular, las CPU modernas utilizadas en los sistemas de escritorio tienden a garantizar la atomicidad al menos para alineados. ints (es decir, datos del tamaño de una palabra de plataforma). Este no es necesariamente el caso de las CPU más antiguas o de las CPU utilizadas en sistemas integrados.

    – ninjalj

    7 de marzo de 2012 a las 19:59

Linux: ¿Por qué sig_atomic_t se define como int?
zwol

C99 sig_atomic_t se ajusta sólo a una definición muy débil de “atomicidad”, porque C99 no tiene concepto de concurrencia, sólo interrumpibilidad. (C2011 agrega un modelo de concurrencia, y con él el _Atomic tipos que hacen garantías más fuertes; sin embargo, AFAIK sig_atomic_t no ha cambiado, ya que su razón de ser todavía hay comunicación con los manejadores de señales, no a través de subprocesos).

Esto es todo lo que dice C99 sobre sig_atomic_t:

(§7.14 <signal.h>párrafo 2) El tipo definido es sig_atomic_t, que es el tipo entero (posiblemente calificado como volátil) de un objeto al que se puede acceder como una entidad atómica, incluso en presencia de interrupciones asíncronas. (§7.14 <signal.h>Párrafo 2)

(§7.14p5) Si [a] la señal se produce de otra manera que no sea el resultado de llamar al abort o raise función, el comportamiento no está definido si el controlador de señal se refiere a cualquier objeto con duración de almacenamiento estático que no sea asignando un valor a un objeto declarado como volatile sig_atomic_t.

(§7.18.3 Límites de otros tipos de enteros, párrafo 3) Si sig_atomic_t (ver 7.14) se define como un tipo entero con signo, el valor de SIG_ATOMIC_MIN no será mayor que −127 y el valor de SIG_ATOMIC_MAX no será inferior a 127; de lo contrario, sig_atomic_t se define como un tipo entero sin signo, y el valor de SIG_ATOMIC_MIN será 0 y el valor de SIG_ATOMIC_MAX no será inferior a 255.

El término “entidad atómica” no se define en ninguna parte del estándar. Traduciendo de los estándares-ese, el intención es que la CPU puede actualizar completamente una variable de tipo sig_atomic_t en la memoria (“duración de almacenamiento estático”) con una instrucción de máquina. Por lo tanto, en la máquina abstracta C99 sin concurrencia y precisamente interrumpible, es imposible que un controlador de señal observe una variable de tipo sig_atomic_t a la mitad de una actualización. El lenguaje §7.18.3p3 permite que este tipo sea tan pequeño como char si necesario. Tenga en cuenta por favor el ausencia completa de cualquier idioma relacionado con la coherencia entre procesadores.

Hay CPU reales que requieren más de una instrucción para escribir un valor mayor que char a la memoria También hay CPU reales que requieren más de una instrucción para escribir valores más pequeño que una palabra de máquina (a menudo, pero no necesariamente, lo mismo que int) a la memoria. El lenguaje en el manual de la biblioteca GNU C ahora es inexacto. Representa un deseo por parte de los autores originales de eliminar lo que vieron como una licencia innecesaria para que las implementaciones de C hicieran cosas raras que hacían la vida más difícil para los programadores de aplicaciones. Desafortunadamente, esa misma licencia es lo que hace posible tener C en algunas máquinas reales. Hay al menos un puerto Linux incorporado (al AVR) para el cual ninguno int ni los punteros se pueden escribir en la memoria en una instrucción. (La gente está trabajando para hacer que el manual sea más preciso, ver, por ejemplo, http://sourceware.org/ml/libc-alpha/2012-02/msg00651.htmlsig_atomic_t Sin embargo, parece haberse perdido en ese.)

  • Je, parece que no. Probablemente estaría mejor con algo más pequeño 🙂 Sin embargo, tiendo a pensar que Linux/AVR con cualquier biblioteca C es más probable que sea un objetivo de portabilidad relevante hoy en día que Hurd u otros sistemas operativos boutique pero no integrados.

    – zwol

    7 de marzo de 2012 a las 20:12


  • Ok, entonces asumiré que el manual de glibc no es inexacto. (Observe que dice: En la práctica y esto es cierto en todas las máquinas que admite la biblioteca GNU C)

    – ninjalj

    7 de marzo de 2012 a las 20:18

  • Tenga en cuenta que sig_atomic_t no hace nada para que las operaciones de lectura, modificación y escritura sean atómicas con respecto a las señales. En x86, las interrupciones no se pueden dividir dec dword [mem], por lo que es atómico en un núcleo Uniprocessor con respecto a las interrupciones, o un proceso de subproceso único con respecto a las señales de la segunda mitad de esta respuesta. Pero (AFAIK) no hay una forma ISO o GNU C11 de solicitar eso num-- compila a eso en lugar de insns de carga/almacenamiento separados, sin usar un atómico que compilará a lock dec dword [num]. Sin contar el asm en línea, por supuesto.

    – Peter Cordes

    9 sep 2016 a las 17:14

  • Solo para ser específicos sobre las limitaciones.: tampoco tiene control sobre el reordenamiento en tiempo de compilación, y el compilador asume que el objeto no se modifica de forma asíncrona. (Entonces while(updated_by_sig_handler == 0){} puede compilar a if(update_by_sig_handler == 0){ while(true); } en lugar de un bucle que vuelve a leer la memoria dentro del bucle, hasta que ve un valor escrito por un controlador de señal. O levante la carga de un bucle que hace algo mientras espera. Escribir bucles de espín usted mismo casi siempre es malo, incluso si usa átomos C11, pero es un ejemplo fácil).

    – Peter Cordes

    9 sep 2016 a las 17:22

  • Ah, claro, vi este idioma en el estándar, pero no me detuve para entenderlo. Y por supuesto tiene que ser volatile, derp, eso desencadena la suposición de modificación asíncrona. Gracias por la explicación, ahora veo lo que dice ese pasaje de jerga legal. Punto interesante que el _Atomic tiene que estar libre de bloqueo. Dado que es un controlador de señales en el mismo subproceso, crearía un punto muerto potencial para que el controlador de señales intente adquirir un bloqueo que a veces tiene el subproceso.

    – Peter Cordes

    9 sep 2016 a las 19:19

Ciertos tipos pueden requerir múltiples instrucciones para leer/escribir. int type siempre se lee/escribe atómicamente.

Tipo de datos: sig_atomic_t

Este es un tipo de datos entero. A los objetos de este tipo siempre se accede de forma atómica.

En la práctica, puede suponer que int y otros tipos de enteros no más largos que int son atómicos. También puede suponer que los tipos de punteros son atómicos; eso es muy conveniente. Ambos son ciertos en todas las máquinas compatibles con la biblioteca GNU C y en todos los sistemas POSIX que conocemos.

Referencia

  • Es generalmente el caso de que int siempre se lee y escribe atómicamente. El estándar C no garantiza esto específicamente. La implementación, definiendo sig_atomic_t como intpromete que ese es el caso para esa implementación. No debe asumir que es cierto para todas las implementaciones.

    –Keith Thompson

    07/03/2012 a las 18:40

  • una mas actual referencia. Solo para aclarar, ¿esto solo se aplica a la biblioteca GNU C? ¿Con o sin GCC? Nunca he oído hablar de un tipo simple que tenga acceso atómico en el estándar C (excluyendo los métodos atómicos normales y los mecanismos de bloqueo).

    – ioan

    7 de marzo de 2012 a las 18:42


  • @Ioan C99 no tiene un modelo de concurrencia, por lo que lo que significa “atómico” es algo muy débil en comparación con lo que probablemente esté pensando. Mira mi respuesta.

    – zwol

    7 de marzo de 2012 a las 19:28

¿Ha sido útil esta solución?