Pourquoi ne pouvez-vous pas dormir tout en maintenant spinlock?
Dans le noyau linux, pourquoi ne pouvez-vous pas dormir tout en maintenant un spinlock?
Simplifiée à l'extrême: parce que vous avez verrouillé de tout le monde avec le spinlock, de sorte qu'ils ne peuvent pas calendrier, mais rien à votre fil de maintien.
Exemple: votre pilote est en cours d'exécution et a juste posé un verrou qui contrôle l'accès à son appareil. Alors que le verrou est détenu, l'appareil émet une interruption, ce qui provoque votre gestionnaire d'interruption à exécuter. Le gestionnaire d'interruption, avant d'accéder à l'appareil, doit également obtenir le verrou. Prendre un spinlock dans un gestionnaire d'interruption est légitime de le faire; c'est une des raisons qui spinlock opérations ne pas dormir. Mais qu'advient-il si la routine d'interruption s'exécute dans le même processeur que le code qui a pris la serrure à l'origine? Alors que le gestionnaire d'interruption est en rotation, le noninterrupt code ne sera pas en mesure d'exécuter pour libérer le verrou. Ce processeur va tourner pour toujours.
Ce n'est pas que vous ne peut pas dormir tout en maintenant un verrou de rotation. C'est un très très mauvais idée de le faire. Citant LDD:
Par conséquent, la base de la règle qui s'applique à spinlocks est que le code doit, tout en maintenant un spinlock, être atomique. Il ne peut pas dormir; en fait, il ne peut pas renoncer à son processeur pour une raison quelconque, sauf pour le service des interruptions (et parfois même pas à l'époque).
Un blocage comme mentionné ci-dessus peut entraîner un état irrécupérable. Une autre chose qui pourrait arriver est que le spinlock se bloque sur un seul PROCESSEUR, et puis quand le thread est en veille, il se réveille sur les autres CPU, entraînant une panique du noyau.
Répondre Bandicoot commentaire, dans un spin lock contexte, le droit de préemption est désactivé uniquement dans le cas d'un monoprocesseur pré-emptible noyau car la désactivation de préemption empêche efficacement les courses.
Si le noyau est compilé sans CONFIG_SMP, mais CONFIG_PREEMPT est définie, les spinlocks il suffit de désactiver la préemption, ce qui est suffisant pour empêcher les courses. Pour la plupart des fins, nous pouvons penser à de préemption comme équivalentes à des SMP, et vous inquiétez pas à ce sujet séparément.
Je suis en désaccord avec William réponse (son exemple). Il mélange deux concepts différents: la préemption et la synchronisation.
Une Interruption Contexte pourrait préempter un Contexte de Processus et donc si il y a une RESSOURCE partagée par les deux, nous avons besoin d'utiliser
spin_lock_irqsave()
(1) désactiver l'IRQ (2) acquérir le verrou. Par l'étape 1, on peut désactiver le système d'interruption de préemption.
Je pense que cette fil est beaucoup plus convaincante. Sleep() signifie un thread/processus donne le contrôle de la CPU et de changement de CONTEXTE à l'autre, sans relâcher le spinlock, c'est pourquoi c'est mauvais.
D'accord, si je ne me trompe pas William problème est résolu par l'aide de la spin_lock fonction pour désactiver l'interruption de préemption. Le problème de sommeil est différente, vous devez juste éviter de dormir dans le spinlock section critique, sinon, vous aurez une mauvaise performance ou d'une impasse.
Un processus ne peut pas être interrompu, ni dormir tout en maintenant un spinlock en raison des spinlocks comportement. Si un processus s'empare d'une spinlock et va dormir avant de le relâcher. Un second processus (ou un gestionnaire d'interruption) pour saisir le spinlock seront occupés à attendre. Sur une machine monoprocesseur le deuxième processus de verrouillage, le CPU ne permettant pas le premier à se réveiller et libérer le spinlock donc le deuxième processus peut se poursuivre, il est au fond d'une impasse.
En dehors de ce willtate a mentionné, supposons qu'un processus dort tout en maintenant un spilock. Si le nouveau processus qui est prévu essaie d'acquérir le même spinlock, il commence à tourner le verrou pour être disponible. Depuis que le nouveau processus continue de tourner, il n'est pas possible de programmer le premier processus et donc la serrure n'est jamais sorti en faisant le deuxième processus de spin pour toujours et nous avons une impasse.
Le point clé est dans le noyau de Linux, l'acquisition d'un verrou de rotation de désactiver la préemption. Donc dormir tout en maintenant un verrou de rotation pourrait potentiellement provoquer un blocage.
Par exemple, le thread A acquiert un verrou de rotation. Fil Une volonté de ne pas être retardé jusqu'à ce qu'il libère le verrou. Tant que le thread A rapidement fait son travail et libère le verrou, il n'y a pas de problème. Mais si Un thread dort tout en maintenant le verrou, le thread B peut être programmé pour s'exécuter depuis la fonction de veille appeler le planificateur. Et le fil B pourrait acquérir la même serrure. Le fil B désactive également la préemption et tente d'acquérir le verrou. Et un blocage se produit. Le fil B ne sera jamais le verrou depuis Un thread détient, de fil et d'Une volonté de ne jamais arriver à courir depuis le thread B désactive la préemption.
Et pourquoi la désactivation de préemption en premier lieu? Je suppose que c'est parce que nous ne voulons pas de discussions sur d'autres processeurs à attendre trop longtemps.
si la préemption est désactivé, peut thread B être programmé pour s'EXÉCUTER alors que les processus actuel d'Un dort-il? Le "sommeil" action va lancer le planificateur de bien que de préemption est désactivé.
total d'accord avec Nan Wang.
Je suppose que la plupart des concept le plus important est "préemption" & "planification" et comment arriver quand spinlock est acquis.
lorsque spinlock est acquis, la préemption est désactivé(vrai ou pas, je ne sais pas, mais suppose que c'est correct), cela signifie que la minuterie d'interruption ne peut pas préempter actuel spinlock titulaire, mais le spinlock tenir encore appel sleepable fonctions du noyau & activement invoquer planificateur & run "autre tâche".
si "autre tâche" qui est arrivé à vouloir acquérir la même spinlock comme la première spinlock titulaire, voici le problème: depuis la préemption est déjà désactivé par le premier spinlock titulaire, "une autre tâche" qui est invoquée par activement appel de planificateur en premier spinlock titulaire, ne peut pas être interrompu, de sorte que son filature toujours prendre le cpu, c'est pourquoi impasse arriver.
Exemple: votre pilote est en cours d'exécution et a juste posé un verrou qui contrôle l'accès à son appareil. Alors que le verrou est détenu, l'appareil émet une interruption, ce qui provoque votre gestionnaire d'interruption à exécuter. Le gestionnaire d'interruption, avant d'accéder à l'appareil, doit également obtenir le verrou. Prendre un spinlock dans un gestionnaire d'interruption est légitime de le faire; c'est une des raisons qui spinlock opérations ne pas dormir. Mais qu'advient-il si la routine d'interruption s'exécute dans le même processeur que le code qui a pris la serrure à l'origine? Alors que le gestionnaire d'interruption est en rotation, le noninterrupt code ne sera pas en mesure d'exécuter pour libérer le verrou. Ce processeur va tourner pour toujours.
Source: http://www.makelinux.net/ldd3/chp-5-sect-5.shtml
OriginalL'auteur Will Tate
Ce n'est pas que vous ne peut pas dormir tout en maintenant un verrou de rotation. C'est un très très mauvais idée de le faire. Citant LDD:
Un blocage comme mentionné ci-dessus peut entraîner un état irrécupérable. Une autre chose qui pourrait arriver est que le spinlock se bloque sur un seul PROCESSEUR, et puis quand le thread est en veille, il se réveille sur les autres CPU, entraînant une panique du noyau.
Répondre Bandicoot commentaire, dans un spin lock contexte, le droit de préemption est désactivé uniquement dans le cas d'un monoprocesseur pré-emptible noyau car la désactivation de préemption empêche efficacement les courses.
http://www.kernel.org/pub/linux/kernel/people/rusty/kernel-locking/index.html
OriginalL'auteur Omair
Je suis en désaccord avec William réponse (son exemple). Il mélange deux concepts différents: la préemption et la synchronisation.
Une Interruption Contexte pourrait préempter un Contexte de Processus et donc si il y a une RESSOURCE partagée par les deux, nous avons besoin d'utiliser
(1) désactiver l'IRQ (2) acquérir le verrou. Par l'étape 1, on peut désactiver le système d'interruption de préemption.
Je pense que cette fil est beaucoup plus convaincante. Sleep() signifie un thread/processus donne le contrôle de la CPU et de changement de CONTEXTE à l'autre, sans relâcher le spinlock, c'est pourquoi c'est mauvais.
OriginalL'auteur Qylin
Je pense que ce mail a une clarté réponse:
OriginalL'auteur Nan Xiao
Une autre explication possible est que, dans un spinlock contexte de préemption est désactivé.
OriginalL'auteur TheLoneJoker
En dehors de ce willtate a mentionné, supposons qu'un processus dort tout en maintenant un spilock. Si le nouveau processus qui est prévu essaie d'acquérir le même spinlock, il commence à tourner le verrou pour être disponible. Depuis que le nouveau processus continue de tourner, il n'est pas possible de programmer le premier processus et donc la serrure n'est jamais sorti en faisant le deuxième processus de spin pour toujours et nous avons une impasse.
OriginalL'auteur San
Le point clé est dans le noyau de Linux, l'acquisition d'un verrou de rotation de désactiver la préemption. Donc dormir tout en maintenant un verrou de rotation pourrait potentiellement provoquer un blocage.
Par exemple, le thread A acquiert un verrou de rotation. Fil Une volonté de ne pas être retardé jusqu'à ce qu'il libère le verrou. Tant que le thread A rapidement fait son travail et libère le verrou, il n'y a pas de problème. Mais si Un thread dort tout en maintenant le verrou, le thread B peut être programmé pour s'exécuter depuis la fonction de veille appeler le planificateur. Et le fil B pourrait acquérir la même serrure. Le fil B désactive également la préemption et tente d'acquérir le verrou. Et un blocage se produit. Le fil B ne sera jamais le verrou depuis Un thread détient, de fil et d'Une volonté de ne jamais arriver à courir depuis le thread B désactive la préemption.
Et pourquoi la désactivation de préemption en premier lieu? Je suppose que c'est parce que nous ne voulons pas de discussions sur d'autres processeurs à attendre trop longtemps.
Le "sommeil" action va lancer le planificateur de bien que de préemption est désactivé.
OriginalL'auteur Nan Wang
total d'accord avec Nan Wang.
Je suppose que la plupart des concept le plus important est "préemption" & "planification" et comment arriver quand spinlock est acquis.
lorsque spinlock est acquis, la préemption est désactivé(vrai ou pas, je ne sais pas, mais suppose que c'est correct), cela signifie que la minuterie d'interruption ne peut pas préempter actuel spinlock titulaire, mais le spinlock tenir encore appel sleepable fonctions du noyau & activement invoquer planificateur & run "autre tâche".
si "autre tâche" qui est arrivé à vouloir acquérir la même spinlock comme la première spinlock titulaire, voici le problème: depuis la préemption est déjà désactivé par le premier spinlock titulaire, "une autre tâche" qui est invoquée par activement appel de planificateur en premier spinlock titulaire, ne peut pas être interrompu, de sorte que son filature toujours prendre le cpu, c'est pourquoi impasse arriver.
OriginalL'auteur steve