Condividi tramite


Multiprocessor-Safe

Il sistema operativo basato su Microsoft Windows NT è progettato per essere eseguito in modo uniforme su piattaforme uniprocessore e multiprocessore simmetrico (SMP) e i driver in modalità kernel devono essere progettati per eseguire allo stesso modo.

In qualsiasi piattaforma multiprocessore Windows esistono le condizioni seguenti:

  • Tutte le CPU sono identiche e tutti o nessuno dei processori deve avere coprocessori identici.

  • Tutte le CPU condividono la memoria e hanno accesso uniforme alla memoria.

  • In una piattaforma simmetrica ogni CPU può accedere alla memoria, eseguire un interrupt e accedere ai registri di controllo di I/O. (Al contrario, in un computer multiprocessore asimmetrico, una CPU gestisce tutti gli interrupt per un insieme di CPU subordinate.)

Per essere eseguito in modo sicuro su una piattaforma SMP, un sistema operativo deve garantire che il codice eseguito su un processore non acceda e non modifichi contemporaneamente i dati che un altro processore sta accedendo e modificando. Ad esempio, se l'ISR di un driver di livello più basso gestisce un interrupt del dispositivo in un processore, deve avere accesso esclusivo ai registri dei dispositivi o ai dati critici definiti dal driver, nel caso in cui il dispositivo interrompa contemporaneamente su un altro processore.

Inoltre, le operazioni di I/O dei driver serializzate in un computer uniprocessore possono essere sovrapposte in un computer SMP. Ovvero, la routine di un driver che elabora le richieste di I/O in ingresso può essere eseguita su un processore mentre un'altra routine che comunica con il dispositivo viene eseguita simultaneamente su un altro processore. Se i driver in modalità kernel vengono eseguiti in un computer uniprocessore o multiprocessore simmetrico, devono sincronizzare l'accesso a qualsiasi risorsa fornita dal driver o dati definiti dal driver condivisi tra routine del driver e sincronizzare l'accesso al dispositivo fisico, se presente.

Il componente kernel di Windows NT esporta un meccanismo di sincronizzazione, denominato blocco spin, che i driver possono usare per proteggere i dati condivisi (o i registri dei dispositivi) dall'accesso simultaneo da una o più routine in esecuzione simultaneamente su una piattaforma multiprocessore simmetrica. Il kernel applica due criteri relativi all'uso degli spinlock:

  • Solo una routine può tenere un determinato spin lock in un dato momento. Prima di accedere ai dati condivisi, ogni routine che deve accedere ai dati deve prima tentare di acquisire lo spinlock dei dati. Per accedere agli stessi dati, un'altra routine deve acquisire il blocco di selezione, ma il blocco di selezione non può essere acquisito fino a quando il titolare corrente non lo rilascia.

  • Il kernel assegna un valore IRQL a ogni spinlock nel sistema. Una routine in modalità kernel può acquisire uno spin lock specifico solo quando la routine viene eseguita al livello IRQL assegnato allo spin lock.

Questi criteri impediscono che una routine del driver, che di solito viene eseguita a un livello di richiesta di interrupt inferiore ma attualmente detiene uno spinlock, venga preempted da una routine del driver con priorità più alta che sta tentando di acquisire lo stesso spinlock. Pertanto, viene evitato un deadlock.

L'IRQL associato a uno spinlock è generalmente quello della routine con il più alto IRQL che può acquisire lo spinlock.

Ad esempio, l'ISR di un driver di livello più basso condivide spesso un'area di stato con la routine DPC del driver. La routine DPC chiama una routine di sezione critica fornita dal driver per accedere all'area condivisa. Il spinlock che protegge l'area condivisa ha un IRQL uguale al DIRQL a cui il dispositivo interrompe. Se la routine della sezione critica detiene lo spin lock e accede all'area condivisa in DIRQL, l'ISR non può essere eseguito in una macchina, sia essa uniprocessore che SMP.

  • L'ISR non può essere eseguito in un computer uniprocessore perché l'interrupt del dispositivo è mascherato, come descritto in Always Preemptible e Always Interruptible.

  • In un computer SMP, l'ISR non può acquisire il blocco di selezione che protegge i dati condivisi mentre la routine di sezione critica contiene il blocco di selezione e accede ai dati condivisi in DIRQL.

Un set di thread in modalità kernel può sincronizzare l'accesso a dati o risorse condivise aspettando uno degli oggetti dispatcher del kernel: un evento, un mutex, un semaforo, un timer o un altro thread. Tuttavia, la maggior parte dei driver non configura i propri thread perché hanno prestazioni migliori quando evitano cambi di contesto del thread. Ogni volta che la modalità kernel critica supporta routine e driver eseguiti in IRQL = DISPATCH_LEVEL o in DIRQL, è necessario usare i blocchi spin del kernel per sincronizzare l'accesso ai dati o alle risorse condivise.

Per altre informazioni, vedere Spin Locks, Managing Hardware Priorities e Kernel Dispatcher Objects.