Программирование драйверов Windows


Интервалы ожидания для отдельного потока - часть 6


#define MY_INTERRUPT_TIMEOUT (10)

VOID StartIo( IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp ) { PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION) pDevObj-&#62DeviceExtension; . . . InterlockedExchange(&pDevExt-&#62Remaining, MY_INTERRUPT_TIMEOUT); // Старт устройства: MyTransmitDataRoutine(pDevObj, pIrp); . . . }

Перед физическим стартом устройства необходимо инициализировать счетчик срабатываний таймера. Значение MY_INTERRUPT_TIMEOUT следует выбирать из тех соображений, что устройство может использоваться впервые в данном сеансе либо имело длительный простой перед данным вызовом. При выборе этого значения необходимо учесть все виды внутренних задержек в устройстве (прогрев, самодиагностику и т.п.).

Процедура ISR по прибытии ожидаемого прерывания устанавливает соответствующее значение счетчика секунд ожидания. В случае, если нет работы (все операции ввода/вывода завершены), логично установить значение счетчика -1.

BOOLEAN OnInterrupt ( IN PKINTERRUPT pInterruptObject, IN PVOID pContext ) { PDEVICE_EXTENSION pDeviceExt = (PDEVICE_EXTENSION)pContext; . . . // В случае, если остались еще данные для передачи, то // обновить счетчик if( IHaveTransmitBytes( pDeviceExt ) ) InterlockedExchange( &pDeviceExt-&#62Remaining, MY_INTERRUPT_TIMEOUT ); else // иначе - очистить счетчик InterlockedExchange ( &pDevExt-&#62Remaining, -1 ); . . . }

Наконец, callback-функция MyIoTimerRoutine, которая вызывается всякий раз по срабатыванию таймера (каждую секунду), как только он запущен. В том случае, если данная процедура установила, что время ожидания активности устройства истекло, то она посредством процедуры DpcForIsr завершает работу над текущим IRP пакетом, объявляя его невыполненным.

VOID MyIoTimerRoutine( IN PDEVICE_OBJECT pDeviceObj, IN PVOID pContext ) { PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION) pContext; // Проверить время ожидания if( (pDevExt-&#62Remaining,-1) &#60 0 ) return; // значение счетчика не важно (поскольку -1) if( InterlockedDecrement(&pDevExt-&#62Remaining) == 0 ) { // Время ожидания истекло InterlockedExchange( &pDevExt-&#62Remaining, (-1) ); PIRP pCurrentIrp = pDeviceObj-&#62CurrentIrp; pCurrentIrp-&#62IoStatus.Status = STATUS_IO_TIMEOUT; pCurrentIrp-&#62IoStatus.Information = 0; IoRequestDpc( pDeviceObj, pCurrentIrp, NULL ) // Некоторые делают совсем "просто": // MyDpcForIsr(NULL, pDeviceObj, pCurrentIrp, pDevExt); } return; }




Начало  Назад  Вперед