Использование подпрограммы CustomTimerDpc
Чтобы отключить ранее заданный объект таймера, драйвер вызывает KeCancelTimer. Эта подпрограмма удаляет объект таймера из очереди таймера системы. Как правило, для объекта таймера не задано состояние сигнала, а подпрограмма CustomTimerDpc не помещается в очередь для выполнения. Однако если срок действия таймера скоро истечет при вызове KeCancelTimer , срок действия может произойти до того, как KeCancelTimer получит возможность получить доступ к очереди времени, в этом случае произойдет сигнализация и очередь DPC.
Отзыв KeSetTimer или KeSetTimerEx с ранее заданными указателями Timer и Dpc до истечения указанного ранее интервала приводит к следующим последствиям.
Ядро удаляет объект таймера из очереди таймера, не устанавливая для объекта состояние сигнала или не помещая в очередь подпрограмму CustomTimerDpc .
Ядро повторно встраивает объект таймера в очередь таймера, используя новое значение DueTime .
Использование одного и того же объекта таймера для различных целей может привести к состоянию гонки или серьезным ошибкам водителя. Например, предположим, что драйвер указывает один объект таймера как для настройки вызова подпрограммы CustomTimerDpc , так и для настройки ожиданий в выделенном драйвером потоке. Когда выделенный драйвером поток вызывает KeSetTimer, KeSetTimerEx или KeCancelTimer для общего объекта таймера, поток отменяет вызовы подпрограммы CustomTimerDpc , если объект таймера уже поставлен в очередь для вызова CustomTimerDpc .
Если драйвер имеет подпрограммы CustomTimerDpc , а также ожидает объекты таймера в контексте неарбитрарного потока, он должен:
Никогда не используйте объект таймера, зависящий от контекста потока, или наоборот.
Выделите отдельный объект таймера для каждой подпрограммы CustomTimerDpc . Каждый набор потоков драйвера или подпрограмм драйвера, вызываемых в контексте неарбитарных потоков, должен иметь собственный набор объектов таймера, доступных для ожидания.
Если вы используете подпрограмму CustomTimerDpc , тщательно выберите интервал, который драйвер передает в вызовах KeSetTimer или KeSetTimerEx. Кроме того, рассмотрите все возможные последствия вызова KeCancelTimer с тем же объектом таймера из любой подпрограммы драйвера, которая выполняет этот вызов, особенно на платформах SMP.
Помните о подпрограммах CustomTimerDpc :
В любой момент можно поместить в очередь для выполнения только один экземпляр объекта DPC, представляющего определенную подпрограмму DPC.
Если вторая подпрограмма драйвера вызывает KeSetTimer или KeSetTimerEx для выполнения той же подпрограммы CustomTimerDpc до истечения интервала , указанного первым вызывающим объектом, подпрограмма CustomTimerDpc запускается только после истечения интервала, указанного вторым вызывающим объектом. В таких случаях CustomTimerDpc не выполняет никаких действий, для которых первая подпрограмма называется KeSetTimer или KeSetTimerEx.
Для драйверов, которые имеют подпрограммы CustomTimerDpc и используют периодические таймеры:
Драйвер не может освободить периодический таймер из подпрограммы DPC. Драйверы могут освободить только непериодические таймеры из подпрограммы DPC.
Рассмотрим следующее руководство по проектированию для драйверов с подпрограммами CustomDpc и CustomTimerDpc :
Чтобы предотвратить состояние гонки, никогда не передайте один и тот же указатель Dpc на KeSetTimer или KeSetTimerEx и KeInsertQueueDpc.
Иными словами, предположим, что подпрограмма StartIo драйвера вызывает KeSetTimer или KeSetTimerEx для постановки в очередь подпрограммы CustomTimerDpc , а ISR драйвера вызывает KeInsertQueueDpc одновременно из другого процессора с тем же указателем Dpc . Эта подпрограмма DPC будет выполняться, когда IRQL на процессоре опускается ниже DISPATCH_LEVEL или истекает интервал таймера, в зависимости от того, что произойдет раньше. Что бы ни было первым, некоторые важные работы для StartIo или ISR будут просто удалены процедурой DPC.
Кроме того, DPC, используемый двумя стандартными подпрограммами драйвера с очень разными функциями, будет иметь более низкие характеристики производительности, чем отдельные процедуры CustomTimerDpc и CustomDpc . DPC должен определить, какие операции выполнять, в зависимости от условий, из-за которых подпрограмма StartIo или ISR помещали ее в очередь. При тестировании этих условий в DPC будут использоваться дополнительные циклы ЦП.