Uso de una rutina de IoTimer

Mientras el temporizador del objeto de dispositivo asociado está habilitado, se llama a la rutina IoTimer aproximadamente una vez por segundo. Sin embargo, dado que los intervalos a los que se llama a cada rutina de IoTimer dependen de la resolución del reloj del sistema, no suponga que se llamará a una rutina de IoTimer con precisión en un límite de un segundo.

Nota Una rutina de IoTimer , como todas las rutinas de DPC, se llama en IRQL = DISPATCH_LEVEL. Mientras se ejecuta una rutina DPC, se impide que todos los subprocesos se ejecuten en el mismo procesador. Los desarrolladores de controladores deben diseñar cuidadosamente sus rutinas de IoTimer para que se ejecuten durante un breve período de tiempo.

Quizás el uso más común de una rutina de IoTimer es el tiempo de espera de las operaciones de E/S del dispositivo para un IRP. Considere el siguiente escenario para usar una rutina de IoTimer como temporizador en ejecución dentro de un controlador de dispositivo:

  1. Cuando inicia el dispositivo, el controlador inicializa un contador de temporizador en la extensión del dispositivo en -1, lo que indica que no hay operaciones de E/S de dispositivo actuales y llama a IoStartTimer justo antes de que devuelva STATUS_SUCCESS.

    Cada vez que se llama a la rutina IoTimer , comprueba si el contador de temporizador es -1 y, si es así, devuelve el control.

  2. La rutina StartIo del controlador inicializa el contador de temporizador de la extensión del dispositivo en un límite superior, más un segundo adicional en caso de que la rutina IoTimer se haya ejecutado. A continuación, usa KeSynchronizeExecution para llamar a una rutina SynchCritSection_1, que programa el dispositivo físico para la operación solicitada por el IRP actual.

  3. El ISR del controlador restablece el contador de temporizador a -1 antes de poner en cola la rutina DpcForIsr del controlador o una rutina CustomDpc .

  4. Cada vez que se llama a la rutina IoTimer , comprueba si el ISR ha restablecido el contador de temporizador a -1 y, si es así, devuelve el control. Si no es así, la rutina IoTimer usa KeSynchronizeExecution para llamar a una rutina SynchCritSection_2 , que ajusta el contador de temporizador en un número determinado de segundos por el controlador.

  5. La SynchCritSection_2 de datos devuelve TRUE a la rutina IoTimer siempre y cuando la solicitud actual aún no haya pasado el tiempo de espera. Si el contador de temporizador va a cero, la rutina de SynchCritSection_2 restablece el contador de temporizador a un valor de tiempo de espera de restablecimiento determinado por el controlador, establece una marca de restablecimiento esperado para sí mismo (y para DpcForIsr) en su área de contexto, intenta restablecer el dispositivo y devuelve TRUE.

    Se volverá SynchCritSection_2 a la rutina de restablecimiento si su operación de restablecimiento también se encuentra en el dispositivo, cuando devuelve FALSE. Si el restablecimiento se realiza correctamente, la rutina DpcForIsr determina que el dispositivo se ha restablecido desde la marca esperada de restablecimiento y vuelve a indar la solicitud, repitiendo las acciones de la rutina StartIo como se describe en el paso 2.

  6. Si la SynchCritSection_2 devuelve FALSE, la rutina IoTimer supone que el dispositivo físico está en un estado desconocido porque ya se ha dado error al intentar restablecerlo. En estas circunstancias, la rutina IoTimer pone en cola una rutina CustomDpc y devuelve . Esta rutina CustomDpc registra un error de E/S de dispositivo, llama a IoStartNextPacket, produce un error en el IRP actual y devuelve.

Si el ISR de este controlador de dispositivo restablece el contador de temporizador compartido a -1, como se describe en el paso 3, la rutina DpcForIsr del controlador completa el procesamiento de E/S controlada por interrupciones de la IRP actual. El contador de temporizador de restablecimiento indica que esta operación de E/S del dispositivo no ha pasado el tiempo de espera, por lo que la rutina IoTimer no necesita cambiar el contador de temporizador.

En la mayoría de los casos, la rutina SynchCritSection_2 anterior simplemente disminuye el contador de temporizador. La SynchCritSection_2 rutina intenta restablecer el dispositivo solo si se ha pasado el tiempo de espera de la operación de E/S actual, lo que se indica cuando el contador de temporizador va a cero. Y solo si un intento de restablecer el dispositivo ya ha dado error, la rutina SynchCritSection_2 devuelve FALSEa la rutina IoTimer.

Por lo tanto, tanto la rutina de IoTimer anterior como su asistente SynchCritSection_2 la rutina tardar muy poco tiempo en ejecutarse en circunstancias normales. Mediante el uso de una rutina de IoTimer de esta manera, un controlador de dispositivo garantiza que cada solicitud de E/S de dispositivo válida se pueda reintente, si es necesario, y que una rutina CustomDpc producirá un error en un IRP solo si un error de hardware no se puede corregir impide que se satisface la IRP. Además, el controlador proporciona esta funcionalidad con muy poco costo en tiempo de ejecución.

La simplicidad del escenario anterior depende de un dispositivo que solo realiza una operación a la vez y de un controlador que normalmente no se superpone a las operaciones de E/S. Un controlador que lleva a cabo operaciones de E/S de dispositivo superpuestas o un controlador de nivel superior que usa una rutina de IoTimer para agotar el tiempo de espera de un conjunto de IRP asignados por el controlador enviados a más de una cadena de controladores inferiores, tendría escenarios de tiempo de espera más complejos para administrar.