web-dev-qa-db-fra.com

Comment fonctionne sig_atomic_t?

Comment le compilateur ou le système d'exploitation distingue-t-il le type sig_atomic_t d'une variable de type int normale et garantit-il que l'opération sera atomique? Les programmes utilisant les deux ont le même code assembleur. À quel point l’attention est-elle prise pour rendre l’opération atomique?

19
Chu

sig_atomic_t n'est pas un type de données atomique. C'est simplement le type de données que vous êtes autorisé à utiliser dans le contexte d'un gestionnaire de signal. Il vaut donc mieux lire le nom comme "atomique par rapport au traitement du signal".

Pour garantir la communication avec et depuis un gestionnaire de signal, une seule des propriétés des types de données atomiques est nécessaire, à savoir le fait que lecture et mise à jour verront toujours une valeur cohérente. D'autres types de données (tels que peut-être long long) pourraient être écrits avec plusieurs instructions d'assembleur pour la partie inférieure et supérieure, par exemple. sig_atomic_t est garanti pour être lu et écrit en une fois.

Ainsi, une plate-forme peut choisir un type de base entier comme sig_atomic_t pour lequel elle peut garantir que volatile sig_atomic_t peut être utilisé en toute sécurité dans les gestionnaires de signaux. De nombreuses plates-formes ont choisi int pour cela, car elles savent que pour elles, int est écrit avec une seule instruction.

La dernière norme C, C11, a des types atomiques, mais qui sont une chose complètement différente. Certains d'entre eux (ceux qui sont "lockfree") peuvent également être utilisés dans les gestionnaires de signaux, mais c'est encore une histoire complètement différente.

18
Jens Gustedt

Notez que sig_atomic_t n'est pas thread-safe, seulement async-signal safe.

L’atomique implique deux types de barrières:

  1. Barrière du compilateur. Il s'assure que le compilateur ne réorganise pas les lectures/écritures depuis/vers une variable atomique par rapport aux lectures et écritures vers d'autres variables. C'est ce que fait le mot clé volatile.
  2. Barrière de CPU et visibilité. Il s'assure que le processeur ne réorganise pas les lectures et les écritures. Sur x86, toutes les charges et tous les magasins dans lesquels le stockage aligné sur 1,2,4,8 octets sont atomiques. La visibilité garantit que les magasins deviennent visibles pour les autres threads. Là encore, sur les processeurs Intel, les magasins sont immédiatement visibles par les autres threads en raison de cohérence de cache et protocole de cohérence de mémoire MESI . Mais cela pourrait changer dans le futur. Voir §8.1 OPÉRATIONS ATOMIQUES VERROUILLÉES des architectures Intel® 64 et IA-32, Manuel du développeur logiciel, volume 3A, pour plus de détails.

Pour un traitement complet de la montre en question Armes atomiques: Le modèle de mémoire C++ et le matériel moderne .

10
Maxim Egorushkin

sig_atomic_t est souvent juste une typedef (à un type intégral spécifique au système, généralement int ou long). Et il est très important d'utiliser volatile sig_atomic_t (pas seulement sig_atomic_t seul).

Lorsque vous ajoutez le mot clé volatile, le compilateur doit éviter beaucoup d'optimisations.

Le récent C11 standard ajouté _Atomic et <stdatomic.h>. Vous avez besoin d’un très récent GCC (p. Ex. 4.9 ) pour que ce dernier soit pris en charge.

7

Les programmes utilisant les deux ont le même code assembleur. À quel point est-il nécessaire de rendre l'opération atomique?

Bien qu’il s’agisse d’une question ancienne, je pense que cela vaut toujours la peine d’aborder précisément cette partie de la question. Sous Linux, sig_atomic_t est fourni par glibc. sig_atomic_t dans glibc est un typedef pour int et n’a aucun traitement particulier (à la date de ce post). Les glibc docs adressent ceci:

En pratique, vous pouvez supposer que int est atomique. Vous pouvez également supposer Que les types de pointeurs sont atomiques; c'est très pratique. Ces deux hypothèses Sont vraies sur toutes les machines prises en charge par la GNU C Library Et sur tous les systèmes POSIX connus.

En d’autres termes, il se trouve que int satisfait déjà aux exigences de sig_atomic_t sur toutes les plates-formes prises en charge par glibc et qu’aucune assistance particulière n’est nécessaire. Néanmoins, les normes C et POSIX prescrivent sig_atomic_t car il peut exister une machine exotique sur laquelle nous voulons implémenter C et POSIX pour laquelle int ne répond pas aux exigences de sig_atomic_t.

0
Praxeolitic

Ce type de données semble être atomique. À partir d'ici: https://www.gnu.org/software/libc/manual/html_node/Atomic-Types.html

24.4.7.2 Types atomiques Pour éviter toute incertitude quant à l'interruption de l'accès à une variable, vous pouvez utiliser un type de données particulier pour lequel l'accès est Toujours atomique: sig_atomic_t. La lecture et l’écriture de ce type de données est garantie Dans une seule instruction. Il n’ya donc aucun moyen pour un gestionnaire De s’exécuter «au milieu» d’un accès.

Le type sig_atomic_t est toujours un type de données entier, mais le type Et le nombre de bits qu’il contient peuvent varier d’une machine à l’autre.

Type de données: sig_atomic_t Il s'agit d'un type de données entier. Les objets de ce type Sont toujours accessibles de manière atomique.

En pratique, vous pouvez supposer que int est atomique. Vous pouvez également supposer Que les types de pointeurs sont atomiques; c'est très pratique. Ces deux hypothèses Sont vraies sur toutes les machines prises en charge par la GNU C Library Et sur tous les systèmes POSIX connus.

0
jplozier