Freigeben über


Einführung in Spin Locks

Spinlocks sind vom Kernel definierte, ausschließlich im Kernelmodus verwendbare Synchronisationsmechanismen, die als opaker Typ exportiert werden: KSPIN_LOCK. Ein Spinlock kann verwendet werden, um gemeinsam genutzte Daten oder Ressourcen vor gleichzeitigem Zugriff zu schützen. Wenn ein Treiber auf einer IRQL <= DISPATCH_LEVEL ausgeführt wird, kann er KeAcquireInStackQueuedSpinLock und KeReleaseInStackQueuedSpinLock verwenden, um den Spinlock als Queued-Spinlock zu erwerben und freizugeben.

Alternativ können Aufrufer, die auf IRQL >= DISPATCH_LEVEL ausgeführt werden, KeAcquireSpinLockAtDpcLevel und KeReleaseSpinLockFromDpcLevel verwenden, um eine bessere Treiberleistung zu erzielen.

Viele Komponenten, einschließlich Treiber, verwenden Spinlocks. Jeder Treibertyp kann einen oder mehrere Executive-Spinlocks verwenden. Beispielsweise verwenden die meisten Dateisysteme eine interlocked-Arbeitswarteschlange in der Geräteerweiterung des Dateisystemtreibers (FSD), um IRPs zu speichern, die sowohl von den Worker-Thread-Callback-Routinen des Dateisystems als auch vom FSD verarbeitet werden. Eine interlocked-Arbeitswarteschlange wird durch einen Executive-Spinlock geschützt, der Konflikte zwischen dem FSD, das versucht, IRPs in die Warteschlange einzufügen, und Threads, die gleichzeitig versuchen, IRPs aus der Warteschlange zu entfernen, auflöst. Ein weiteres Beispiel ist der Systemfloppy-Controller-Treiber, der zwei Executive-Spinlocks verwendet. Ein Executive-Spinlock schützt eine interlocked-Arbeitswarteschlange, die mit dem gerätegebundenen Thread dieses Treibers gemeinsam genutzt wird; der andere schützt ein Timerobjekt, das von drei Treiberroutinen gemeinsam genutzt wird.

Queued-Spinlocks bieten eine bessere Leistung als gewöhnliche Spinlocks bei hoher Konfliktrate auf Multiprozessormaschinen. Weitere Informationen finden Sie unter Queued-Spinlocks. Treiber können auch KeAcquireSpinLock und KeReleaseSpinLock verwenden, um den Spinlock als gewöhnlichen Spinlock zu erwerben und freizugeben.

Um den Zugriff auf einfache Datenstrukturen zu synchronisieren, können Treiber eine der ExInterlockedXxx-Routinen verwenden, um den atomaren Zugriff auf die Datenstruktur sicherzustellen. Treiber, die diese Routinen verwenden, müssen den Spinlock nicht explizit erwerben oder freigeben.

Jeder Treiber mit einer ISR verwendet einen Interrupt-Spinlock, um Daten oder Hardware zu schützen, die zwischen seiner ISR und seinen SynchCritSection-Routinen gemeinsam genutzt werden, die von seinen StartIo- und DpcForIsr-Routinen aufgerufen werden. Ein Interrupt-Spinlock ist mit der Gruppe von Interrupt-Objekten verknüpft, die erstellt werden, wenn der Treiber IoConnectInterrupt aufruft, wie unter „Registrieren einer ISR“ beschrieben.

Richtlinien für die Verwendung von Spinlocks in Treibern:

  • Stellen Sie den Speicher für alle Daten oder Ressourcen, die durch einen Spinlock geschützt werden, sowie für den entsprechenden Spinlock im residenten Systemspeicher (Nicht-Auslagerungsspeicher, wie in der Abbildung Virtuelle Speicherbereiche und physischer Speicher gezeigt) bereit. Ein Treiber muss den Speicher für alle von ihm verwendeten Executive-Spinlocks bereitstellen. Ein Gerätetreiber muss jedoch keinen Speicher für einen Interrupt-Spinlock bereitstellen, es sei denn, er verfügt über eine Multivektor-ISR oder mehr als eine ISR, wie unter „Registrieren einer ISR“ beschrieben.

  • Rufen Sie KeInitializeSpinLock auf, um jeden Spinlock zu initialisieren, für den der Treiber Speicher bereitstellt, bevor Sie ihn verwenden, um den Zugriff auf die geschützten Daten oder Ressourcen zu synchronisieren.

  • Rufen Sie jede unterstützende Routine, die einen Spinlock verwendet, auf einer geeigneten IRQL auf, in der Regel auf <= DISPATCH_LEVEL für Executive-Spinlocks oder auf <= DIRQL für einen Interrupt-Spinlock, der mit den Interrupt-Objekten des Treibers verknüpft ist.

  • Implementieren Sie Routinen, die so schnell wie möglich ausgeführt werden, während sie einen Spinlock halten. Keine Routine sollte einen Spinlock länger als 25 Mikrosekunden halten.

  • Halten Sie keinen Spinlock, während eine Routine Folgendes ausführt:

    • Hardware-Ausnahmen verursachen oder Software-Ausnahmen auslösen.

    • Versuch, auf auslagerbaren Speicher zuzugreifen.

    • Rekursiver Aufruf, der eine Blockierung verursachen könnte oder dazu führen könnte, dass ein Spinlock länger als 25 Mikrosekunden gehalten wird.

    • Versuch, einen weiteren Spinlock zu erwerben, wenn dies eine Blockierung verursachen könnte.

    • Rufen Sie eine externe Routine auf, die gegen eine der vorherigen Regeln verstößt.