Introdução aos objetos do Kernel Dispatcher
O kernel define um conjunto de tipos de objeto chamados objetos dispatcher de kernel ou apenas objetos dispatcher. Os objetos dispatcher incluem objetos de temporizador, objetos de evento, objetos semáforos, objetos mutex e objetos thread.
Os drivers podem usar objetos dispatcher como mecanismos de sincronização em um contexto de thread nonarbitrary enquanto executam em IRQL igual a PASSIVE_LEVEL.
Estados do objeto Dispatcher
Cada tipo de objeto dispatcher definido pelo kernel tem um estado definido como Signaled ou definido como Não Sinalizado.
Um grupo de threads poderá sincronizar suas operações se um ou mais threads chamarem KeWaitForSingleObject, KeWaitForMutexObject ou KeWaitForMultipleObjects. Essas funções tomam ponteiros de objeto dispatcher como entrada e esperam até que outra rotina ou thread defina um ou mais objetos dispatcher para o estado Sinalizado.
Quando um thread chama o KeWaitForSingleObject para aguardar um objeto dispatcher (ou KeWaitForMutexObject para um mutex), o thread é colocado em um estado de espera até que o objeto dispatcher seja definido como o estado Sinalizado. Um thread pode chamar KeWaitForMultipleObjects para aguardar qualquer um, ou para todos, de um conjunto de objetos dispatcher a ser definido como Signaled.
Sempre que um objeto dispatcher é definido como o estado Sinalizado, o kernel altera o estado de qualquer thread aguardando que esse objeto esteja pronto. (Temporizadores de sincronização e eventos de sincronização são exceções a essa regra; quando um evento de sincronização ou temporizador é sinalizado, apenas um thread de espera é definido como o estado pronto. Para obter mais informações, consulte Objetos de temporizador e DPCs e objetos de evento.) Um thread no estado pronto será agendado para ser executado de acordo com sua prioridade atual de thread em tempo de execução e a disponibilidade atual de processadores para qualquer thread com essa prioridade.
Quando os drivers podem esperar por objetos Dispatcher?
Em geral, os drivers podem aguardar que os objetos do dispatcher sejam definidos somente se pelo menos uma das seguintes circunstâncias for verdadeira:
O driver está sendo executado em um contexto de thread nonarbitrary.
Ou seja, você pode identificar o thread que entrará em um estado de espera. Na prática, as únicas rotinas de driver executadas em um contexto de thread nonarbitrary são as rotinas DriverEntry, AddDevice, Reinitialize e Unload de qualquer driver, além das rotinas de expedição dos drivers de nível mais alto. Todas essas rotinas são chamadas diretamente pelo sistema.
O driver está executando uma solicitação de E/S completamente síncrona.
Ou seja, nenhum driver enfileira nenhuma operação durante o tratamento da solicitação de E/S e nenhum driver retorna até que o driver abaixo tenha terminado de lidar com a solicitação.
Além disso, um driver não poderá inserir um estado de espera se estiver executando em OU acima de IRQL igual a DISPATCH_LEVEL.
Com base nessas limitações, você deve usar as seguintes regras:
As rotinas DriverEntry, AddDevice, Reinitialize e Unload de qualquer driver podem aguardar objetos dispatcher.
As rotinas de expedição de um driver de nível mais alto podem esperar por objetos dispatcher.
As rotinas de expedição de drivers de nível inferior podem aguardar por objetos de expedição, se a operação de E/S for síncrona, como operações de criação, liberação, desligamento e fechamento, algumas operações de controle de E/S do dispositivo e algumas operações de PnP e energia.
As rotinas de expedição de drivers de nível inferior não podem esperar por um objeto dispatcher para a conclusão de operações de E/S assíncronas.
Uma rotina de driver que está sendo executada em ou acima do IRQL DISPATCH_LEVEL não deve esperar que um objeto dispatcher seja definido como o estado Sinalizado.
Um driver não deve tentar aguardar que um objeto dispatcher seja definido como o estado Sinalizado para a conclusão de uma operação de transferência de ou para um dispositivo de paginação.
As rotinas de expedição do driver que atendem solicitações de leitura/gravação geralmente não podem esperar que um objeto dispatcher seja definido como o estado Sinalizado.
Uma rotina de expedição para uma solicitação de controle de E/S do dispositivo pode aguardar que um objeto dispatcher seja definido como o estado Sinalizado somente se o tipo de transferência do código de controle de E/S for METHOD_BUFFERED.
Os drivers de miniport do SCSI não devem usar objetos de dispatcher de kernel. Os drivers de miniporto SCSI devem chamar apenas rotinas de biblioteca de portas SCSI.
Todas as outras rotinas de driver padrão são executadas em um contexto de thread arbitrário: a de qualquer thread atual quando a rotina do driver é chamada para processar uma operação enfileirada ou para lidar com uma interrupção de dispositivo. Além disso, a maioria das rotinas de driver padrão é executada em um IRQL gerado, em DISPATCH_LEVEL ou para drivers de dispositivo, no DIRQL.
Se necessário, um driver pode criar um thread dedicado ao dispositivo, que pode aguardar por outras rotinas do driver (exceto uma rotina ISR ou SynchCritSection ) para definir um objeto dispatcher para o estado Sinalizado e redefinir para o estado Not-Signaled.
Como diretriz geral, se você espera que seu novo driver de dispositivo geralmente precise parar por mais de 50 microssegundos enquanto aguarda as alterações de estado do dispositivo durante as operações de E/S, considere implementar um driver com um thread dedicado ao dispositivo. Se o driver de dispositivo também for um driver de nível mais alto, considere usar threads de trabalho do sistema e implementar uma ou mais rotinas de retorno de chamada de thread de trabalho. Consulte PsCreateSystemThread e Gerenciando filas interligadas com um thread de Driver-Created.