137 votes

Que sont exactement les "spin-locks" ?

Je me suis toujours demandé ce que c'était : chaque fois que j'en entends parler, des images d'appareils futuristes ressemblant à des volants d'inertie dansent (roulent ?) dans mon esprit...

Qu'est-ce que c'est ?

167voto

ssg Points 20321

Lorsque vous utilisez des verrous ordinaires (mutex, sections critiques, etc.), le système d'exploitation place votre thread dans l'état WAIT et préempte en programmant d'autres threads sur le même noyau. Les performances s'en ressentent si le temps d'attente est très court, car votre thread doit maintenant attendre une préemption pour recevoir à nouveau du temps CPU.

En outre, les objets du noyau ne sont pas disponibles dans tous les états du noyau, par exemple dans un gestionnaire d'interruption ou lorsque la pagination n'est pas disponible, etc.

Les spinlocks ne provoquent pas de préemption mais attendent dans une boucle ("spin") que l'autre noyau libère le verrou. Cela empêche le thread de perdre son quantique et continuer dès que le verrou est libéré. Le mécanisme simple des spinlocks permet à un noyau de les utiliser dans presque tous les états.

C'est pourquoi, sur une machine à un seul cœur, un spinlock est simplement un "disable interrupts" ou un "raise IRQL" qui empêche complètement l'ordonnancement des threads.

En fin de compte, les spinlocks permettent aux noyaux d'éviter les "Big Kernel Lock" (un verrou acquis lorsque le cœur entre dans le noyau et libéré à la sortie) et de disposer d'un verrouillage granulaire sur les primitives du noyau, ce qui permet un meilleur multitraitement sur les machines multi-cœurs et donc de meilleures performances.

EDIT : Une question a été posée : "Est-ce que cela signifie que je devrais utiliser des spinlocks partout où c'est possible ?" et je vais essayer d'y répondre :

Comme je l'ai mentionné, les Spinlocks ne sont utiles que dans les cas où le temps d'attente prévu est inférieur à un quantum (lire : millisecondes) et où la préemption n'a pas beaucoup de sens (par exemple, les objets du noyau ne sont pas disponibles).

Si le temps d'attente est inconnu, ou si vous êtes en mode utilisateur, les Spinlocks ne sont pas efficaces. Vous consommez 100% du temps CPU sur le cœur en attente pendant que vous vérifiez si un spinlock est disponible. Vous empêchez les autres threads de s'exécuter sur ce noyau jusqu'à l'expiration de votre quantum. Ce scénario n'est réalisable que pour de courtes rafales au niveau du noyau et il est peu probable que ce soit une option pour une application en mode utilisateur.

Voici une question sur SO qui traite de ce sujet : Les spinlocks, quelle est leur utilité ?

0 votes

Cela signifie-t-il que je devrais utiliser des verrous tournants (au lieu de mutex, critical-section, etc.) dans la mesure du possible ?

1 votes

Quelqu'un peut me corriger si j'ai tort, mais un spinlock ne désactive pas la préemption (c'est-à-dire le ré-ordonnancement). pour la simple raison que, si le spinlock attend une ressource verrouillée par un autre processus, alors ce second processus doit avoir une chance de s'exécuter et de libérer la ressource. ou, l'exécution du second processus nécessite de préempter le premier (spinning) processus.

0 votes

Ce que fait le spinlock à la place, c'est qu'il ne change pas l'état du processus de TASK_RUNNING en TASK_INTERRUPTIBLE (qui est un état de sommeil) et, donc, il ne sauver Au lieu de cela, le processus de rotation est préempté, mais il ne quitte jamais les processus "immédiatement programmables" : il est gardé en mémoire et les autres processus sont régulièrement exécutés jusqu'à ce que l'un d'entre eux libère la ressource que le processus de rotation attend : à ce moment-là, le spinlock revient simplement et le processus de rotation peut continuer. il attend dans un état toujours TASK_RUNNING.

37voto

codaddict Points 154968

Si une ressource est protégée par un verrou, un thread qui souhaite accéder à cette ressource doit d'abord acquérir le verrou. Si le verrou n'est pas disponible, le thread peut vérifier à plusieurs reprises si le verrou a été libéré. Pendant ce temps, le thread attend, vérifie le verrou, utilise le CPU, mais ne fait aucun travail utile. Un tel verrou est appelé verrou tournant.

2 votes

Bonne réponse ! +1

23voto

Oded Points 271275

Il s'agit plutôt d'une boucle qui se poursuit jusqu'à ce qu'une certaine condition soit remplie :

while(cantGoOn) {};

1 votes

Et/ou while(cantGoOn) { sleep(0) } ;

3 votes

@Jiminion si vous mettez un sleep(0) cela préempterait le thread, tuant le but de l'utilisation d'un spinlock en premier lieu. si vous avez besoin de céder à d'autres threads, vous devriez utiliser un verrou régulier. (je sais que votre commentaire est très ancien mais je voulais éviter que d'autres personnes ne voient cela comme une suggestion).

0 votes

"Une valeur de zéro fait en sorte que le thread cède le reste de sa tranche de temps à tout autre thread qui est prêt à s'exécuter. S'il n'y a pas d'autres threads prêts à s'exécuter, la fonction revient immédiatement, et le thread continue son exécution."

9voto

Luka Rahne Points 5479
 while(something != TRUE ){};
 // it happend
 move_on();

4voto

aJ. Points 17014

Les SpinLocks sont ceux dans lesquels le thread attend que le verrou soit disponible. Ceci sera normalement utilisé pour éviter les surcharges liées à l'obtention des objets du noyau lorsqu'il y a une possibilité d'acquérir l'objet du noyau dans une petite période de temps.

Ex :

While(SpinCount-- && Kernel Object is not free)
{}

try acquiring Kernel object

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X