Compartir a través de


Acceso a la información de estado compartido

Use las siguientes directrices generales para diseñar y escribir rutinas synchCritSection que mantienen el estado:

  • Para acceder a los datos a los que también accede un ISR, una rutina de controlador debe llamar a una rutina SynchCritSection . El código de sección no crítico se puede interrumpir. Recuerde que no es suficiente simplemente adquirir un bloqueo de número para proteger los datos a los que también acceden los ISR, ya que los ISR se ejecutan en DIRQL y adquieren un bloqueo de número (KeAcquireSpinLock) solo genera IRQL para DISPATCH_LEVEL, lo que permite una interrupción para invocar el ISR en el procesador actual.

  • Asigne cada rutina SynchCritSection que mantenga la responsabilidad de la información de estado de un conjunto discreto de variables de estado. Es decir, evite escribir rutinas SynchCritSection que mantengan información de estado superpuesta.

    Esto evita la contención y, posiblemente, las condiciones de carrera, entre las rutinas SynchCritSection (y el ISR) que intentan acceder al mismo estado simultáneamente.

    Esto también garantiza que cada rutina SynchCritSection devuelva el control lo más rápido posible porque una rutina SynchCritSection nunca tiene que esperar a que otra que actualice parte de la misma información de estado para devolver el control.

  • Evite escribir una rutina SynchCritSection única y grande de uso general que realice más pruebas de condiciones para determinar qué hacer que hacer realmente trabajo útil. Por otro lado, evite tener muchas rutinas SynchCritSection que nunca ejecuten una instrucción condicional porque cada una actualiza solo un byte de información de estado.

  • Cada rutina SynchCritSection debe devolver el control lo antes posible, ya que la ejecución de cualquier rutina SynchCritSection impide que se ejecute el ISR del controlador.

A continuación se muestra una técnica para mantener un contador de temporizador en una extensión de dispositivo. Supongamos que el controlador usa el contador para determinar si una operación de E/S ha agotado el tiempo de espera. Suponga también que el controlador no se superpone a las operaciones de E/S.

  • La rutina StartIo del controlador inicializa el contador del temporizador en algún valor inicial para cada solicitud de E/S. A continuación, el controlador agrega un segundo a su valor de tiempo de espera del dispositivo, en caso de que su rutina ioTimer acaba de devolver el control.

  • El ISR del controlador debe establecer este contador de temporizador en menos uno.

  • Se llama a la rutina IoTimer del controlador una vez por segundo para leer el contador de tiempo y determinar si el ISR ya lo ha establecido en menos uno. Si no es así, la rutina IoTimer disminuye el contador mediante KeSynchronizeExecution para llamar a una rutina de SynchCritSection_1.

    Si el contador va a cero, lo que indica que se agota el tiempo de espera de la solicitud, la rutina SynchCritSection_1 llama a una rutina de SynchCritSection_2 para programar una operación de restablecimiento del dispositivo. Si el contador es menos uno, la rutina IoTimer simplemente devuelve.

  • Si la rutina DpcForIsr del controlador debe volver a programar el dispositivo para iniciar una operación de transferencia parcial, debe reinicializar el contador del temporizador como hizo la rutina StartIo .

    La rutina DpcForIsr también debe usar KeSynchronizeExecution para llamar a la rutina SynchCritSection_2, o posiblemente una rutina de SynchCritSection_3, para programar el dispositivo para otra operación de transferencia.

En este escenario, el controlador tiene más de una rutina SynchCritSection , cada una con responsabilidades discretas y específicas; uno para mantener su contador de temporizador, y uno o varios otros para programar el dispositivo. Cada rutina SynchCritSection puede devolver el control rápidamente porque realiza una sola tarea discreta.

Tenga en cuenta que el controlador tiene una única rutina de SynchCritSection_1 que, junto con el ISR del controlador, mantiene el estado en el contador del temporizador. Por lo tanto, no hay contención para el acceso al contador de temporizador entre varias rutinas SynchCritSection y el ISR.