# Protocolos de coerência

Problemas de coerência de cache aparecem mais comumente em sistemas que possuem mais de um processador. Nesses sistemas, cada processador conta com uma cache privada, que pode conter dados que também aparecem em outras caches privadas de outros processadores. Se um processador realizar alguma alteração neste dado compartilhado, as informações armazenadas nas outras caches tornam-se inválidas. A mesma situação vista de outro ângulo: se uma leitura de um dado realizada por um processador é executada após uma escrita (no mesmo dado) realizada por outro processador, esta leitura deve retornar o valor recém-escrito – e não o valor da cache local.
Mecanismos de manutenção da coerência de cache são utilizados tanto em software quanto em hardware. Cada protocolo possui seu escopo de atuação e seu custo de implementação. Os protocolos baseados em software costumam ser mais baratos e mais versáteis, assim como menos complexos do que as implementações em hardware, mas geralmente exigem suporte por parte das aplicações. Os protocolos baseados em hardware são consideravelmente mais eficientes, e de sobremaneira mais complexos do que abordagens em software; são os esquemas mais utilizados em sistemas multiprocessados comerciais devido à sua eficiência e à sua transparência com relação às aplicações.

## Version-control

Um exemplo de esquema estático é o Version-control, que faz a manutenção da coerência através de versionamento do conteúdo. As versões correntes nos processadores são geradas e têm seu número identificador incrementado sempre que ocorre uma escrita em um dado compartilhado, e um número de versão é atribuído a cada linha da cache, para cada alocação feita. Quando uma leitura do dado compartilhado é feita, checa-se se o número da versão corrente do processador é maior que o da versão na cache. Em caso afirmativo, o dado foi encontrado corretamente.

## One-time Identifier

Já o esquema One-time Identifier é um exemplo de esquema que roda em tempo de execução (dinâmico). Nele, as páginas compartilhadas possuem um campo para identificador único (one-time identifier) que é adicionado tanto na cache quanto nas entradas da TLB - Translation Lookaside Buffer. Na primeira vez que o dado compartilhado é lido, o identificador na cache recebe o valor do identificador da entrada na TLB. Os acessos a um dado compartilhado realizam comparações entre o valor do identificador da entrada da TLB com o valor do identificador da entrada da cache, indicando erro caso estes sejam diferentes.

## Modelos de Coerência

Existem vários modelos e protocolos diferentes para a manutenção da coerência de cache. Eles podem diferir em performance e escalabilidade, sendo a escolha de qual modelo empregar dependente do design do sistema. Alguns exemplos são os protocolos MSI, MESI, MOSI e MOESI, onde as letras que formam os nomes dos protocolos identificam os possíveis estados em que cada linha da cache pode se encontrar. Estes estados são:
* Modified: indica que o bloco foi modificado na cache.
* Shared: o bloco pode estar armazenado em outras caches, e corresponde a cópia contida na memória principal.
* Invalid: bloco inválido, deve ser trazido da memória ou de outra cache para ser guardado nesta cache.
* Exclusive: a linha de cache está presente apenas na cache corrente, sem modificações (correspondendo ao que está na memória principal).
* Owned: é similar ao estado shared, porém a cópia contida na memória principal pode estar incorreta. Apenas um processador pode conter dados neste estado.