Condividi tramite


Accesso alle informazioni sullo stato condiviso

Usare le linee guida generali seguenti per la progettazione e la scrittura di routine SynchCritSection che mantengono lo stato:

  • Per accedere ai dati a cui accede anche un ISR, una routine del driver deve chiamare una routine SynchCritSection . Il codice di sezione non critico può essere interrotto. Tenere presente che non è sufficiente acquisire semplicemente un blocco spin per proteggere anche i dati a cui gli ISR accedono, perché gli ISR vengono eseguiti in DIRQL e l'acquisizione di un blocco spin (KeAcquireSpinLock) genera solo IRQL per DISPATCH_LEVEL, che consente di richiamare l'ISR nel processore corrente.

  • Assegnare a ogni routine SynchCritSection la responsabilità delle informazioni sullo stato per un set discreto di variabili di stato. Vale a dire, evitare di scrivere routine SynchCritSection che mantengono informazioni sullo stato sovrapposte.

    Ciò impedisce la contesa e possibilmente le race condition tra le routine SynchCritSection (e l'ISR) che tentano di accedere contemporaneamente allo stesso stato.

    Ciò garantisce inoltre che ogni routine SynchCritSection restituisca il controllo il più rapidamente possibile perché una routine SynchCritSection non deve mai attendere che un'altra aggiorni alcune delle stesse informazioni sullo stato per restituire il controllo.

  • Evitare di scrivere una singola routine SynchCritSection di grandi dimensioni che esegue più test delle condizioni per determinare cosa fare di più rispetto a eseguire operazioni utili. D'altra parte, evitare di avere molte routine SynchCritSection che non eseguono mai un'istruzione condizionale perché ogni singolo byte di informazioni sullo stato viene aggiornato.

  • Ogni routine SynchCritSection deve restituire il controllo il più rapidamente possibile, perché l'esecuzione di qualsiasi routine SynchCritSection impedisce l'esecuzione dell'ISR del driver.

Di seguito è riportata una tecnica per la gestione di un contatore timer in un'estensione del dispositivo. Si supponga che il driver usi il contatore per determinare se si è verificato un timeout di un'operazione di I/O. Si supponga inoltre che il driver non si sovrapponga alle operazioni di I/O.

  • La routine StartIo del driver inizializza il contatore timer su un valore iniziale per ogni richiesta di I/O. Il driver aggiunge quindi un secondo al valore di timeout del dispositivo, nel caso in cui la routine IoTimer abbia appena restituito il controllo.

  • L'ISR del driver deve impostare questo contatore timer su meno uno.

  • La routine IoTimer del driver viene chiamata una volta al secondo per leggere il contatore dell'ora e determinare se l'ISR l'ha già impostata su meno uno. In caso contrario, la routine IoTimer decrementa il contatore usando KeSynchronizeExecution per chiamare una routine SynchCritSection_1.

    Se il contatore passa a zero, a indicare che il timeout della richiesta, la routine SynchCritSection_1 chiama una routine SynchCritSection_2 per programmare un'operazione di reimpostazione del dispositivo. Se il contatore è meno uno, la routine IoTimer restituisce semplicemente .

  • Se la routine DpcForIsr del driver deve riprogrammare il dispositivo per avviare un'operazione di trasferimento parziale, deve reinizializzare il contatore timer come è stata eseguita la routine StartIo .

    La routine DpcForIsr deve anche usare KeSynchronizeExecution per chiamare la routine SynchCritSection_2, o eventualmente una routine SynchCritSection_3, per programmare il dispositivo per un'altra operazione di trasferimento.

In questo scenario, il driver ha più routine SynchCritSection , ognuna con responsabilità specifiche discrete; uno per mantenere il contatore timer e uno o più altri per programmare il dispositivo. Ogni routine SynchCritSection può restituire rapidamente il controllo perché esegue una singola attività discreta.

Si noti che il driver ha una singola routine SynchCritSection_1 che, insieme all'ISR del driver, mantiene lo stato del contatore timer. Pertanto, non esiste alcuna contesa per l'accesso al contatore timer tra diverse routine SynchCritSection e ISR.