Condividi tramite


Introduzione ai blocchi di rotazione

I spinlock sono meccanismi di sincronizzazione definiti dal kernel e funzionanti esclusivamente in modalità kernel, esportati come tipo opaco: KSPIN_LOCK. È possibile usare un blocco di selezione per proteggere i dati condivisi o le risorse dall'accesso simultaneo. Durante l'esecuzione in IRQL <= DISPATCH_LEVEL, un driver può usare KeAcquireInStackQueuedSpinLock e KeReleaseInStackQueuedSpinLock per acquisire e rilasciare lo spin lock come spin lock in coda.

In alternativa, gli chiamanti in esecuzione in IRQL >= DISPATCH_LEVEL possono chiamare KeAcquireSpinLockAtDpcLevel e KeReleaseSpinLockFromDpcLevel per migliorare le prestazioni del driver.

Molti componenti usano spinlock, inclusi i driver. Qualsiasi tipo di driver può usare uno o più blocchi di rotazione esecutivi. Ad esempio, la maggior parte dei file system utilizza una coda di lavoro bloccata nell'estensione del dispositivo del driver del file system (FSD) per archiviare gli IRP elaborati sia dalle routine di callback del thread di lavoro del file system che dall'FSD. Una coda di lavoro bloccata è protetta da uno spin lock esecutivo, che risolve la contesa tra gli FSD che cercano di inserire i pacchetti di richiesta I/O nella coda e tutti i thread che tentano simultaneamente di rimuoverli. Un altro esempio è che il driver del controller floppy di sistema utilizza due spin lock esecutivi. Un spin lock esecutivo protegge una coda di lavoro agganciata condivisa con il thread dedicato al dispositivo del driver; l'altro protegge un oggetto timer condiviso da tre routine del driver.

I blocchi di spin in coda offrono prestazioni migliori rispetto ai normali spin lock per blocchi a elevata contesa nei computer multiprocessore. Per ulteriori informazioni, vedere blocchi di spin accodati. I driver possono anche usare KeAcquireSpinLock e KeReleaseSpinLock per acquisire e rilasciare uno spinlock come un normale spinlock.

Per sincronizzare l'accesso a strutture di dati semplici, i driver possono usare qualsiasi routine ExInterlockedXxx per garantire l'accesso atomico alla struttura dei dati. I driver che usano queste routine non devono acquisire o rilasciare lo spin lock in modo esplicito.

Ogni driver con ISR usa uno spin lock per interrupt per proteggere i dati o l'hardware condivisi tra le sue routine ISR e SynchCritSection chiamate dalle sue routine StartIo e DpcForIsr. Un blocco di selezione interrupt è associato al set di oggetti interrupt creati quando il driver chiama IoConnectInterrupt, come descritto in Registrazione di un ISR.

Seguire queste linee guida per l'uso degli spinlock nei driver:

  • Fornire lo spazio di archiviazione per i dati o le risorse protette da un spinlock e per lo spinlock corrispondente nella memoria di sistema residente (pool non paginato, come illustrato nella figura Spazi di memoria virtuale e memoria fisica). Un driver deve fornire lo spazio di archiviazione per qualsiasi spin lock esecutivo usato. Tuttavia, un driver di dispositivo non deve fornire lo spazio di archiviazione per uno spin lock di interrupt, a meno che non abbia un ISR multivettore o abbia più ISR, come descritto in Registrazione di un ISR.

  • Chiamare KeInitializeSpinLock per inizializzare ogni spin lock per cui il driver fornisce archiviazione prima di usarlo per sincronizzare l'accesso ai dati o alle risorse condivisi che protegge.

  • Chiamare ogni routine di supporto che usa un blocco di rotazione in corrispondenza di un IRQL appropriato, in genere in <= DISPATCH_LEVEL per i blocchi di rotazione esecutivi o in = <DIRQL per un blocco di rotazione di interrupt associato agli oggetti interrupt del driver.

  • Implementare routine per l'esecuzione il più rapidamente possibile mentre si tiene premuto un blocco di selezione. Nessuna routine deve contenere un blocco a rotazione per più di 25 microsecondi.

  • Non implementare mai routine che eseguono una delle operazioni seguenti tenendo premuto un blocco di selezione:

    • Causa eccezioni hardware o genera eccezioni software.

    • Tentare di accedere alla memoria paginabile.

    • Effettuare una chiamata ricorsiva che potrebbe provocare un deadlock o causare un blocco di rotazione mantenuto per più di 25 microsecondi.

    • Tenta di acquisire un altro spin lock se ciò potrebbe causare un deadlock.

    • Chiamare una routine esterna che viola una delle regole precedenti.