Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Om du minimerar tiden som en drivrutin håller i spinnlås kan du avsevärt förbättra både drivrutinens och systemets prestanda överlag. Tänk till exempel på följande bild, som visar hur ett avbrottsspinnlås skyddar enhetsspecifika data som måste delas mellan en ISR och rutinerna StartIo och DpcForIsr på en SMP-dator.
Medan drivrutinens ISR körs på DIRQL på en processor, körs dess StartIo-rutin på DISPATCH_LEVEL på en andra processor. Kernel-avbrottshanteraren innehåller InterruptSpinLock för drivrutinens ISR, som har åtkomst till skyddade, enhetsspecifika data, till exempel tillstånd eller pekare till enhetsregister (SynkroniseraContext), i drivrutinens enhetstillägg. StartIo-rutinen, som är redo att komma åt SyncContext, anropar KeSynchronizeExecution, skickar en pekare till associerade avbrottsobjekt, den delade SyncContext och drivrutinens SynchCritSection-rutin (AccessDevice i föregående bild).
Tills ISR återkommer, och därmed frigör drivrutinens InterruptSpinLock, snurrar KeSynchronizeExecution på den andra processorn, vilket hindrar AccessDevice från att röra SynchronizeContext. KeSynchronizeExecution höjer dock även IRQL på den andra processorn till SynchronizeIrql för avbrottsobjekten, vilket förhindrar att ett annat enhetsavbrott inträffar på den processorn så att AccessDevice kan köras på DIRQL så snart ISR returnerar. Högre DIRQL-avbrott för andra enheter, klockavbrott och strömavbrott kan dock fortfarande inträffa på någon av processorerna.
När ISR köar drivrutinen DpcForIsr och returnerar, körs AccessDevice på den andra processorn vid SynchronizeIrql för de associerade avbrottsobjekten och kommer åt SynchronizeContext. Under tiden körs DpcForIsr på en annan processor på DISPATCH_LEVEL IRQL. DpcForIsr är också redo att komma åt SyncContext, så den anropar KeSynchronizeExecution med samma parametrar som StartIo-rutinen gjorde i steg 1.
När KeSynchronizeExecution erhåller spinlåset och kör AccessDevice för StartIo-rutinen, får den av drivrutinen tillhandahållna synkroniseringsrutinen AccessDevice exklusiv åtkomst till SynchronizeContext. Eftersom AccessDevice körs på SynchronizeIrql kan drivrutinens ISR inte hämta spinnlåset och komma åt samma område förrän spinnlåset har släppts, även om enheten avbryter på en annan processor medan AccessDevice körs.
AccessDevice returnerar och frigör spinnlåset. StartIo-rutinen återupptas vid DISPATCH_LEVEL på den andra processorn. KeSynchronizeExecution kör nu AccessDevice på den tredje processorn, så att den kan komma åt SyncContext för DpcForIsr. Men om ett enhetsavbrott hade inträffat före DpcForIsr med namnet KeSynchronizeExecution i steg 2, kan ISR köras på en annan processor innan KeSynchronizeExecution kunde hämta spinnlåset och köra AccessDevice på den tredje processorn.
Som föregående bild visar, medan en rutin som körs på en processor har ett spinnlås, får alla andra rutiner som försöker hämta det spinnlåset inget arbete gjort. Varje rutin som försöker ta ett redan upptaget spinnlås snurrar helt enkelt på den aktuella processorn tills innehavaren släpper spinnlåset. När ett spinnlås släpps kan en och endast en rutin förvärva det. Alla andra rutiner som för närvarande försöker förvärva samma spinnlås fortsätter att spinna.
Innehavaren av ett spinnlås körs vid en upphöjd IRQL: antingen vid DISPATCH_LEVEL för ett executive spin lock eller vid en DIRQL för ett avbrottsspinnlås. Uppringare av KeAcquireSpinLock och KeAcquireInStackQueuedSpinLock körs på DISPATCH_LEVEL tills de anropar KeReleaseSpinLock eller KeReleaseInStackQueuedSpinLock för att släppa låset. Uppringare av KeSynchronizeExecution höjer automatiskt IRQL på den aktuella processorn till SyncIrql för avbrottsobjekten tills synchCritSection-rutinen avslutas och KeSynchronizeExecution returnerar kontrollen. Mer information finns i Samtalssupportrutiner som använder spinnlås.
Tänk på följande om hur du använder spinnlås:
All kod som körs på en lägre IRQL kan inte utföra något arbete på den uppsättning processorer som upptas av en spinlock-innehavare och av andra rutiner som försöker förvärva samma spinnlås.
Att minimera den tid som en förare håller spinnlås ger därför betydligt bättre prestandaförbättring och bidrar avsevärt till bättre övergripande systemprestanda.
Som föregående bild visar kör kernelavbrottshanteraren rutiner som körs på samma IRQL i en dator med flera processorer enligt först till kvarn-principen. Kerneln gör också följande:
När en drivrutin anropar KeSynchronizeExecution gör kerneln att drivrutinens SynchCritSection-rutin körs på samma processor som anropet till KeSynchronizeExecution inträffade från (se steg 1 och 3).
När en drivrutins ISR köar sin DpcForIsr får kerneln DPC att köras på den första tillgängliga processorn där IRQL understiger DISPATCH_LEVEL. Detta är inte nödvändigtvis samma processor som IoRequestDpc-anropet inträffade från (se steg 2).
En drivrutins avbrottsdrivna I/O-åtgärder kan tendera att serialiseras på en enprocessordator, men samma åtgärder kan vara verkligt asynkrona på en SMP-dator. Som föregående bild visar kan en drivrutins ISR köras på CPU4 på en SMP-dator innan dess DpcForIsr börjar processa en IRP för vilken ISR redan har hanterat ett enhetsavbrott på CPU1.
Med andra ord bör du inte anta att ett avbrottsspinnlås kan skydda åtgärdsspecifika data som ISR sparar när den körs på en processor från att skrivas över av ISR när ett enhetsavbrott inträffar på en annan processor innan DpcForIsr - eller CustomDpc-rutinen körs.
Även om en drivrutin kan försöka serialisera alla avbrottsdrivna I/O-åtgärder för att bevara data som samlas in av ISR, skulle drivrutinen inte köras mycket snabbare på en SMP-dator än på en enprocessordator. För att få bästa möjliga drivrutinsprestanda samtidigt som de förblir bärbara på uniprocessor- och multiprocessorplattformar bör drivrutiner använda någon annan teknik för att spara åtgärdsspecifika data som hämtas av ISR för efterföljande bearbetning av DpcForIsr.
En ISR kan till exempel spara åtgärdsspecifika data i den IRP som den skickar till DpcForIsr. En förfining av den här tekniken är att implementera en DpcForIsr som konsulterar en ISR-utökad räknare, bearbetar räknarens antal av IRP:er med ISR-levererade data och återställer räknaren till noll innan den returneras. Naturligtvis måste antalet skyddas av förarens avbrottsspinnlås eftersom dess ISR och en SynchCritSection skulle behålla sitt värde dynamiskt.