Verwenden einer CustomTimerDpc-Routine

Um ein zuvor festgelegtes Timerobjekt zu deaktivieren, ruft ein Treiber KeCancelTimer auf. Diese Routine entfernt das Timerobjekt aus der Timerwarteschlange des Systems. Im Allgemeinen ist das Timerobjekt nicht auf den signalierten Zustand festgelegt, und die CustomTimerDpc-Routine wird für die Ausführung nicht in die Warteschlange gestellt. Wenn der Timer jedoch abläuft, wenn KeCancelTimer aufgerufen wird, kann der Ablauf auftreten, bevor KeCancelTimer die Möglichkeit hat, auf die Zeitwarteschlange zuzugreifen. In diesem Fall treten Signalisierung und DPC-Warteschlangen auf.

Das Abrufen von KeSetTimer oder KeSetTimerEx mit zuvor angegebenen Timer - und DPC-Zeigern , bevor das zuvor angegebene Intervall abläuft, hat die folgenden Auswirkungen:

  • Der Kernel entfernt das Timerobjekt aus der Timerwarteschlange, ohne das Objekt auf den signalierten Zustand festzulegen oder die CustomTimerDpc-Routine anzustellen.

  • Der Kernel setzt das Timerobjekt mithilfe des neuen DueTime-Werts in der Timerwarteschlange erneut ein.

Die Verwendung desselben Timerobjekts für verschiedene Zwecke kann zu Rennbedingungen oder schwerwiegenden Fahrerfehlern führen. Angenommen, ein Treiber gibt ein einzelnes Timerobjekt an, sowohl zum Einrichten eines Aufrufs einer CustomTimerDpc-Routine als auch zum Einrichten von Wartezeiten in einem dedizierten Treiberthread. Wenn der treiberde dedizierte Thread KeSetTimer, KeSetTimerEx oder KeCancelTimer für das allgemeine Timerobjekt aufruft, würde der Thread Aufrufe der CustomTimerDpc-Routine abbrechen, wenn das Timerobjekt bereits für einen CustomTimerDpc-Aufruf in die Warteschlange gestellt wurde.

Wenn ein Treiber über CustomTimerDpc-Routinen verfügt und auch timer-Objekte in einem nichtarbiträren Threadkontext wartet, sollte er Folgendes ausführen:

  • Verwenden Sie niemals ein threadkontextsensitives Timerobjekt in einem nichtarbiträren Threadkontext oder umgekehrt.

  • Ordnen Sie für jede CustomTimerDpc-Routine ein separates Timerobjekt zu. Jeder Satz von Treiberthreads oder Treiberroutinen, die in einem nichtarbiträren Threadkontext aufgerufen werden, sollte über einen eigenen Satz von "wartebaren" Timerobjekten verfügen.

Wenn Sie eine CustomTimerDpc-Routine verwenden, wählen Sie sorgfältig das Intervall aus, das der Treiber in Aufrufen von KeSetTimer oder KeSetTimerEx übergibt. Berücksichtigen Sie darüber hinaus alle möglichen Auswirkungen eines Aufrufs von KeCancelTimer mit demselben Timerobjekt von jeder Treiberroutine, die diesen Aufruf vornimmt, insbesondere auf SMP-Plattformen.

Beachten Sie die folgende Tatsache zu CustomTimerDpc-Routinen :

Nur eine Instanziierung eines DPC-Objekts, das eine bestimmte DPC-Routine darstellt, kann zu einem bestimmten Zeitpunkt für die Ausführung in die Warteschlange gestellt werden.

Wenn eine zweite Treiberroutine KeSetTimer oderKeSetTimerEx aufruft, um dieselbe CustomTimerDpc-Routine auszuführen, bevor das vom ersten Aufrufer angegebene Intervall abläuft, wird die CustomTimerDpc-Routine nur ausgeführt, nachdem das vom zweiten Aufrufer angegebene Intervall abläuft. Unter diesen Umständen übernimmt customTimerDpc keine der Aufgaben, für die die erste Routine KeSetTimer oder KeSetTimerEx genannt wurde.

Für Treiber mit CustomTimerDpc-Routinen und regelmäßigen Timern:

Ein Treiber kann keine Zuordnung eines regelmäßigen Timers aus einer DPC-Routine verarbeiten. Treiber können nur nichtperiodische Timer aus einer DPC-Routine zugeordnet werden.

Betrachten Sie die folgenden Entwurfsrichtlinien für Treiber, die sowohl CustomDpc - als auch CustomTimerDpc-Routinen haben:

Um Racebedingungen zu verhindern, übergeben Sie niemals denselben DPC-Zeiger an KeSetTimer oder KeSetTimerEx und KeInsertQueueDpc.

Angenommen, die StartIo-Routine eines Treibers ruft KeSetTimer oder KeSetTimerEx auf, um eine CustomTimerDpc-Routine in die Warteschlange zu stellen, und der ISR des Treibers ruft KeInsertQueueDpc gleichzeitig von einem anderen Prozessor mit demselben DPC-Zeiger auf. Diese DPC-Routine wird ausgeführt, wenn IRQL auf einem Prozessor unter DISPATCH_LEVEL fällt oder das Timerintervall abläuft, je nachdem, was zuerst eintritt. Was auch immer zuerst kommt, einige wichtige Arbeiten für startIo oder ISR würden einfach von der DPC-Routine gelöscht.

Darüber hinaus hätte ein DPC, der von zwei Standardtreiberroutinen mit sehr unterschiedlichen Funktionen verwendet wird, schlechtere Leistungsmerkmale als separate CustomTimerDpc - und CustomDpc-Routinen . Der DPC müsste abhängig von den Bedingungen, die dazu geführt haben, dass die StartIo-Routine oder der ISR in die Warteschlange gestellt wurde, welche Vorgänge ausgeführt werden sollen. Tests auf diese Bedingungen im DPC würden zusätzliche CPU-Zyklen verwenden.