Uso de bloqueos de marco
A veces, los controladores deben proporcionar sincronización específica del controlador de las funciones de devolución de llamada relacionadas con la solicitud de E/S, ya sea además de o como reemplazo de la sincronización proporcionada por el marco. Los controladores pueden usar bloqueos de sincronización de devolución de llamada, bloqueos de número, bloqueos de espera y bloqueos de interrupción para sincronizar el código del controlador.
Si ha configurado el controlador para usar la funcionalidad de sincronización automática del marco, el marco adquiere un bloqueo de sincronización antes de llamar a las funciones de devolución de llamada de eventos relacionadas con la solicitud de E/S del controlador.
Estos bloqueos de sincronización de devolución de llamada, que están asociados a objetos de dispositivo de marco y objetos de cola, también se pueden adquirir mediante controladores. Para adquirir un bloqueo de sincronización, un controlador llama a WdfObjectAcquireLock. Para liberar el bloqueo, el controlador llama a WdfObjectReleaseLock.
Es posible que quiera que el controlador use los bloqueos de sincronización de devolución de llamada si el controlador usa la sincronización de nivel de dispositivo o de cola del marco de funciones de devolución de llamada relacionadas con la solicitud de E/S, pero debe sincronizar algún código que se ejecuta en IRQL = PASSIVE_LEVEL con funciones de devolución de llamada que se ejecutan en IRQL = DISPATCH_LEVEL. Esto se debe a que los controladores solo pueden usar la sincronización automática para las funciones de devolución de llamada que se ejecutan en el mismo IRQL.
Por ejemplo, un controlador puede usar la sincronización automática para un objeto de elemento de trabajo solo si el nivel de ejecución del elemento de trabajo principal del objeto de elemento de trabajo es WdfExecutionLevelPassive (porque la función de devolución de llamada de un elemento de trabajo siempre se ejecuta en IRQL= PASSIVE_LEVEL). Por lo tanto, si un controlador especifica WdfExecutionLevelDispatch en el miembro ExecutionLevel de la estructura WDF_OBJECT_ATTRIBUTES de un objeto de dispositivo, el controlador no puede establecer el miembro AutomaticSerialization de la estructura de configuración de un objeto de elemento de trabajo secundario. En su lugar, el controlador debe adquirir un bloqueo de sincronización de devolución de llamada para sincronizar las funciones de devolución de llamada evtWorkItem con las funciones de devolución de llamada del objeto de dispositivo primario.
Use bloqueos de espera de marco para sincronizar el acceso a los datos del controlador desde el código que se ejecuta en IRQL = PASSIVE_LEVEL. Para que un controlador pueda usar un bloqueo de espera de marco, debe llamar a WdfWaitLockCreate para crear un objeto wait-lock. A continuación, el controlador puede llamar a WdfWaitLockAcquire para adquirir el bloqueo y WdfWaitLockRelease para liberarlo.
Use bloqueos de número de marco para sincronizar el acceso a los datos del controlador desde el código que se ejecuta en IRQL <= DISPATCH_LEVEL. Cuando un subproceso de controlador adquiere un bloqueo de número, el sistema establece irQL del subproceso en DISPATCH_LEVEL. Cuando el subproceso libera el bloqueo, el sistema restaura el IRQL del subproceso a su nivel anterior.
Un controlador que no usa la sincronización automática de marcos podría usar un bloqueo de número para sincronizar el acceso al espacio de contexto de un objeto de dispositivo, si el espacio de contexto se puede escribir y si más de una de las funciones de devolución de llamada de eventos del controlador acceden al espacio.
Para que un controlador pueda usar un bloqueo de número de marco, debe llamar a WdfSpinLockCreate para crear un objeto de bloqueo de número. A continuación, el controlador puede llamar a WdfSpinLockAcquire para adquirir el bloqueo y WdfSpinLockRelease para liberarlo.
Para obtener un ejemplo de uso de bloqueos de número, consulte Sincronización de la cancelación de solicitudes enviadas.
En el caso de los objetos de interrupción que admiten el control de interrupciones de DIRQL, los bloqueos de interrupción del marco son bloqueos de número. Una vez que el controlador adquiere un bloqueo de giro de interrupción, el controlador se ejecuta en el DIRQL del dispositivo hasta que libera el bloqueo. Para obtener más información sobre el uso de bloqueos de interrupción, vea Sincronizar código de interrupción.
Para los objetos de interrupción que admiten el control de nivel pasivo, los bloqueos de interrupción del marco son bloqueos de espera. Una vez que el controlador adquiere un bloqueo de espera de interrupción, el controlador se ejecuta en IRQL = PASSIVE_LEVEL hasta que libera el bloqueo. Para obtener más información sobre el control de nivel pasivo, consulte Compatibilidad con interrupciones de nivel pasivo.