Usando bloqueios de estrutura
Às vezes, os drivers devem fornecer sincronização específica do driver de funções de retorno de chamada relacionadas à solicitação de E/S, além de ou como uma substituição para a sincronização fornecida pela estrutura. Os drivers podem usar bloqueios de sincronização de retorno de chamada, bloqueios de rotação, bloqueios de espera e bloqueios de interrupção para sincronizar o código do driver.
Bloqueios de sincronização de retorno de chamada
Se você configurou o driver para usar a funcionalidade de sincronização automática da estrutura, a estrutura adquire um bloqueio de sincronização antes de chamar as funções de retorno de chamada de evento relacionadas à solicitação de E/S do driver.
Esses bloqueios de sincronização de retorno de chamada, associados a objetos de dispositivo de estrutura e objetos de fila, também podem ser adquiridos por drivers. Para adquirir um bloqueio de sincronização, um driver chama WdfObjectAcquireLock. Para liberar o bloqueio, o driver chama WdfObjectReleaseLock.
Talvez você queira que o driver use os bloqueios de sincronização de retorno de chamada se o driver usar a sincronização no nível do dispositivo ou na fila da estrutura de funções de retorno de chamada relacionadas à solicitação de E/S, mas precisar sincronizar algum código executado em IRQL = PASSIVE_LEVEL com funções de retorno de chamada executadas em IRQL = DISPATCH_LEVEL. Isso ocorre porque os drivers podem usar a sincronização automática somente para funções de retorno de chamada executadas no mesmo IRQL.
Por exemplo, um driver pode usar a sincronização automática para um objeto de item de trabalho somente se o nível de execução do pai do objeto do item de trabalho for WdfExecutionLevelPassive (porque a função de retorno de chamada de um item de trabalho sempre é executada em IRQL= PASSIVE_LEVEL). Portanto, se um driver especificar WdfExecutionLevelDispatch no membro ExecutionLevel da estrutura WDF_OBJECT_ATTRIBUTES de um objeto de dispositivo, o driver não poderá definir o membro AutomaticSerialization da estrutura de configuração de um objeto de item de trabalho filho. Em vez disso, o driver deve adquirir um bloqueio de sincronização de retorno de chamada para sincronizar as funções de retorno de chamada EvtWorkItem com as funções de retorno de chamada do objeto de dispositivo pai.
Bloqueios de espera da estrutura
Use bloqueios de espera da estrutura para sincronizar o acesso aos dados do driver do código executado em IRQL = PASSIVE_LEVEL. Antes que um driver possa usar um bloqueio de espera de estrutura, ele deve chamar WdfWaitLockCreate para criar um objeto de bloqueio de espera. Em seguida, o driver pode chamar WdfWaitLockAcquire para adquirir o bloqueio e WdfWaitLockRelease para liberá-lo.
Bloqueios de rotação de estrutura
Use bloqueios de rotação de estrutura para sincronizar o acesso aos dados do driver do código executado em IRQL <= DISPATCH_LEVEL. Quando um thread de driver adquire um bloqueio de rotação, o sistema define o IRQL do thread como DISPATCH_LEVEL. Quando o thread libera o bloqueio, o sistema restaura o IRQL do thread para o nível anterior.
Um driver que não está usando a sincronização automática de estrutura pode usar um bloqueio de rotação para sincronizar o acesso ao espaço de contexto de um objeto de dispositivo, se o espaço de contexto for gravável e se mais de uma das funções de retorno de chamada de evento do driver acessarem o espaço.
Antes que um driver possa usar um bloqueio de rotação de estrutura, ele deve chamar WdfSpinLockCreate para criar um objeto spin-lock. Em seguida, o driver pode chamar WdfSpinLockAcquire para adquirir o bloqueio e WdfSpinLockRelease para liberá-lo.
Para obter um exemplo de uso de bloqueios de rotação, consulte Sincronizando o cancelamento de solicitações enviadas.
Bloqueios de interrupção da estrutura
Para objetos de interrupção que dão suporte ao tratamento de interrupções DIRQL, os bloqueios de interrupção da estrutura são bloqueios de rotação. Depois que o driver adquire um bloqueio de rotação de interrupção, o driver é executado no DIRQL do dispositivo até liberar o bloqueio. Para obter mais informações sobre como usar bloqueios de interrupção, consulte Sincronizando código de interrupção.
Para objetos de interrupção que dão suporte ao tratamento de nível passivo, os bloqueios de interrupção da estrutura são bloqueios de espera. Depois que o driver adquire um bloqueio de espera de interrupção, o driver é executado em IRQL = PASSIVE_LEVEL até liberar o bloqueio. Para obter mais informações sobre o tratamento de nível passivo, consulte Suporte a interrupções de nível passivo.