Verrous de rotation mis en file d’attente
Les verrous de rotation mis en file d’attente sont une variante des verrous de rotation qui fonctionnent bien pour les verrous hautement soutenus. Les verrous de rotation traditionnels et non mis en file d’attente sont un meilleur choix pour les verrous légèrement soutenus ou plus courts.
Les avantages de l’utilisation d’un verrou de rotation en file d’attente sont les suivants :
Contention réduite du processeur : les verrous de rotation traditionnels peuvent entraîner une contention significative du processeur lorsque plusieurs threads tentent d’acquérir le verrou simultanément, car ils effectuent une boucle continue (ou « spin ») case activée l’état du verrou. Cela peut dégrader les performances du système, en particulier sur les systèmes multiprocesseurs. Les verrous de rotation mis en file d’attente atténuent ce problème en organisant des threads dans une file d’attente. Lorsqu’un thread acquiert un verrou, seul le suivant en ligne tourne activement, en attendant d’acquérir le verrou. Cela réduit les cycles d’UC gaspillent sur l’épinglage, en particulier lorsque le verrou est conservé pendant des durées plus longues.
L’équité et l’évitement de la famine : l’un des problèmes liés aux verrous de rotation de base est le manque d’équité ; un thread peut être affamé et n’acquérir jamais le verrou si d’autres threads l’acquiert et le libèrent en continu. Les verrous de rotation mis en file d’attente s’adressent à ceci en s’assurant que les threads obtiennent le verrou dans l’ordre dans lequel ils ont tenté. Cette gestion séquentielle empêche la faim et garantit que tous les threads sont pris en charge au fil du temps.
Scalabilité : à mesure que le nombre de processeurs ou de cœurs augmente dans un système, l’efficacité des mécanismes de synchronisation devient essentielle pour les performances. Les verrous de rotation mis en file d’attente sont plus évolutifs que les verrous de rotation traditionnels, car ils réduisent la surcharge sur les processeurs en réduisant la rotation active sur tous les cœurs. Cela est particulièrement important dans les systèmes multicœurs hautes performances, où l’efficacité du pilote peut avoir un impact direct sur les performances globales du système.
Utilisation efficace des ressources système : en réduisant l’épinglage inutile du processeur, les verrous de rotation mis en file d’attente permettent au système d’utiliser ses ressources plus efficacement. Cela améliore non seulement les performances du pilote de périphérique, mais a également un impact positif sur la réactivité globale et la consommation d’énergie du système, qui est particulièrement bénéfique dans les environnements sensibles à l’alimentation.
Simplicité et fiabilité : malgré leurs avantages en réduisant la contention et en améliorant l’équité, les verrous de rotation mis en file d’attente éliminent la complexité du développeur. Ils fournissent un mécanisme simple et fiable pour protéger les ressources partagées sans que le développeur ait à implémenter une logique de verrouillage complexe. Cette simplicité réduit la probabilité de bogues liés à la gestion incorrecte des verrous, améliorant ainsi la fiabilité du pilote.
Vous trouverez ci-dessous un extrait de code simplifié illustrant les opérations décrites avec un verrou de rotation en file d’attente dans un pilote en mode noyau Windows. Cet exemple montre comment déclarer et initialiser un verrou de spin à l’aide de KeInitializeSpinLock, puis acquérir et libérer le verrou à l’aide de KeAcquireInStackQueuedSpinLock et KeReleaseInStackQueuedSpinLock, respectivement.
KSPIN_LOCK SpinLock;
KLOCK_QUEUE_HANDLE LockHandle;
// Initialize the spin lock
KeInitializeSpinLock(&SpinLock);
// Assume this function is called in some kind of context where
// the below operations make sense, e.g., in a device I/O path
// Acquire the queued spin lock
KeAcquireInStackQueuedSpinLock(&SpinLock, &LockHandle);
// At this point, the current thread holds the spin lock.
// Perform thread-safe operations here.
// ...
// Release the queued spin lock
KeReleaseInStackQueuedSpinLock(&LockHandle);
Le pilote alloue une structure KLOCK_QUEUE_HANDLE qu’il passe par pointeur vers KeAcquireInStackQueuedSpinLock. Le pilote passe la même structure par pointeur vers KeReleaseInStackQueuedSpinLock lorsqu’il libère le verrou de rotation.
Les pilotes doivent normalement allouer la structure sur la pile chaque fois qu’ils obtiennent le verrou. Un pilote ne doit pas allouer la structure dans le cadre de son contexte d’appareil, puis partager la même structure à partir de plusieurs threads.
Les pilotes ne doivent pas mélanger les appels aux routines de verrouillage de spin en file d’attente et les routines Ke Xxx SpinLock ordinaires sur le même verrou derotation.
Si le pilote est déjà à IRQL = DISPATCH_LEVEL, il peut appeler KeAcquireInStackQueuedSpinLockAtDpcLevel et KeReleaseInStackQueuedSpinLockFromDpcLevel à la place.