Compartilhar via


Sempre Preemptível e Sempre Interrompível

A meta do design preemptível e interruptível do sistema operacional é maximizar o desempenho do sistema. Qualquer thread pode ser preemptado por um thread com prioridade mais alta, e a rotina de serviço de interrupção (ISR) de qualquer driver pode ser interrompida por uma rotina que é executada em um nível de solicitação de interrupção mais alto (IRQL).

O componente kernel determina quando uma sequência de código é executada, de acordo com um destes critérios de priorização:

  • O esquema de prioridade de tempo de execução definido pelo kernel para threads.

    Cada thread no sistema tem um atributo de prioridade associado. Em geral, a maioria dos threads tem atributos de prioridade variável: eles são sempre preemptíveis e são agendados para executar round-robin com todos os outros threads que estão atualmente no mesmo nível de prioridade. Alguns threads têm atributos de prioridade em tempo real: esses threads críticos de tempo são executados até a conclusão, a menos que sejam preemptados por outro thread com um atributo de prioridade em tempo real mais alto. A arquitetura do Microsoft Windows não fornece um sistema inerentemente em tempo real.

    Seja qual for seu atributo de prioridade, qualquer thread no sistema pode ser preempcionado quando ocorrem interrupções de hardware e certos tipos de interrupções de software.

  • O IRQL ( nível de solicitação de interrupção ) definido pelo kernel ao qual um vetor de interrupção específico é atribuído em uma determinada plataforma.

    O kernel prioriza interrupções de hardware e software para que parte do código do modo kernel, incluindo a maioria dos drivers, seja executado em IRQLs mais altos, dando-lhe, assim, uma prioridade de agendamento maior do que outras threads no sistema. O IRQL específico no qual uma parte do código de driver do modo kernel é executada é determinada pela prioridade de hardware de seu dispositivo subjacente.

    O código do modo kernel é sempre interruptível: uma interrupção com um valor IRQL mais alto pode ocorrer a qualquer momento, fazendo com que outra parte do código do modo kernel que tenha um IRQL atribuído ao sistema mais alto seja executada imediatamente nesse processador. No entanto, quando uma parte do código é executada em um determinado IRQL, o kernel mascara todos os vetores de interrupção com um valor IRQL menor ou igual no processador.

O nível de IRQL mais baixo é chamado de PASSIVE_LEVEL. Nesse nível, nenhum vetor de interrupção é mascarado. Os threads geralmente são executados em IRQL=PASSIVE_LEVEL. Os próximos níveis de IRQL mais altos são para interrupções de software. Esses níveis incluem APC_LEVEL, DISPATCH_LEVEL ou, para depuração de kernel, WAKE_LEVEL. As interrupções de dispositivo têm valores IRQL ainda mais altos. O kernel reserva os valores mais altos de IRQL para interrupções críticas do sistema, como aquelas provenientes do relógio do sistema ou de erros de barramento.

Algumas rotinas de suporte do sistema são executadas em IRQL=PASSIVE_LEVEL, porque são implementadas como código paginável ou acessam dados pagináveis ou porque alguns componentes do modo kernel configuram seus próprios threads.

Da mesma forma, algumas rotinas padrão de driver geralmente são executadas em IRQL=PASSIVE_LEVEL. No entanto, várias rotinas de driver padrão são executadas em IRQL=DISPATCH_LEVEL ou, para um driver de nível mais baixo, no IRQL do dispositivo (também chamado dirql). Para obter mais informações sobre IRQLs, consulte Gerenciando prioridades de hardware.

Cada rotina em um driver é interruptível. Isso inclui qualquer rotina em execução em um IRQL maior do que PASSIVE_LEVEL. Qualquer rotina em execução em um IRQL específico mantém o controle do processador somente se nenhuma interrupção para um IRQL maior ocorrer enquanto essa rotina estiver em execução.

Ao contrário dos drivers em alguns sistemas operacionais de computadores pessoais mais antigos, o ISR de um driver do Microsoft Windows nunca é uma rotina grande e complexa que faz a maior parte do processamento de E/S do driver. Isso ocorre porque a ISR (rotina de serviço de interrupção) de qualquer driver pode ser interrompida por outra rotina (por exemplo, por uma rotina de serviço de interrupção de outro driver) que é executada em um IRQL mais alto. Assim, o ISR do driver não retém necessariamente o controle de uma CPU, ininterruptamente, do início ao fim de sua execução.

Em drivers do Windows, um ISR normalmente salva informações de estado de hardware, enfileira uma DPC ( chamada de procedimento adiado ) e sai rapidamente. Posteriormente, o sistema desativa o DPC do driver para que o driver possa concluir as operações de E/S em um IRQL inferior (DISPATCH_LEVEL). Para um bom desempenho geral do sistema, todas as rotinas executadas em IRQLs altas devem renunciar rapidamente ao controle da CPU.

No Windows, todos os threads têm um contexto de thread. Esse contexto consiste em informações que identificam o processo que possui o thread, além de outras características, como os direitos de acesso do thread.

Em geral, apenas o driver de nível mais alto é chamado no contexto do thread que está solicitando a operação de E/S atual do driver. Um driver de nível intermediário ou de nível mais baixo nunca pode assumir que está sendo executado no contexto do thread que solicitou sua operação de E/S atual.

Consequentemente, as rotinas de driver geralmente são executadas em um contexto de thread arbitrário — o contexto de qualquer thread atual quando uma rotina de driver padrão é chamada. Por motivos de desempenho (para evitar mudanças de contexto), pouquíssimos drivers configuram seus próprios threads.