xref: /linux/Documentation/translations/pt_BR/process/volatile-considered-harmful.rst (revision 14c897740388216acd59477a382de327d5e27ba4)
1.. SPDX-License-Identifier: GPL-2.0
2
3Por que a classe de tipo "volatile" não deve ser usada
4--------------------------------------------------------
5
6Programadores C frequentemente interpretam volatile como uma indicação de
7que uma variável pode ser alterada fora da thread de execução atual; como
8resultado, às vezes são tentados a usá-la no código do kernel quando
9estruturas de dados compartilhadas estão sendo utilizadas. Em outras
10palavras, há quem trate tipos volatile como uma espécie de variável
11atômica simplificada, mas não são. O uso de volatile no código do
12kernel quase nunca é correto; este documento explica o porquê.
13
14O ponto-chave a entender sobre volatile é que seu propósito é suprimir
15otimizações, o que quase nunca é o que realmente se deseja fazer. No kernel,
16é necessário proteger estruturas de dados compartilhadas contra acessos
17concorrentes indesejados, o que é uma tarefa bastante diferente. O processo
18de proteção contra concorrência indesejada também evita, de forma mais
19eficiente, quase todos os problemas relacionados a otimizações.
20
21Assim como volatile, as primitivas do kernel que tornam seguro o acesso
22concorrente a dados (spinlocks, mutexes, barreiras de memória etc.) são
23projetadas para evitar otimizações indesejadas. Se forem usadas
24corretamente, também não haverá necessidade de usar volatile. Se
25volatile ainda for necessário, quase certamente há algum bug no código.
26Em código de kernel corretamente escrito, volatile só serve para deixar
27as coisas mais lentas.
28
29Considere um bloco típico de código do kernel::
30
31    spin_lock(&the_lock);
32    do_something_on(&shared_data);
33    do_something_else_with(&shared_data);
34    spin_unlock(&the_lock);
35
36Se todo o código seguir as regras de bloqueio, o valor de shared_data não
37poderá mudar inesperadamente enquanto the_lock estiver mantido. Qualquer
38outro código que queira manipular esses dados estará aguardando o bloqueio.
39As primitivas de spinlock atuam como barreiras de memória (são escritas
40explicitamente para isso), o que significa que os acessos aos dados não
41serão otimizados de forma a atravessar essas barreiras. Assim, o compilador
42até pode achar que sabe qual será o valor de shared_data, mas a chamada a
43spin_lock(), por atuar como barreira de memória, o forçará a esquecer tudo
44o que sabia. Não haverá problemas de otimização nos acessos a esses dados.
45
46Se shared_data fosse declarada volatile, o bloqueio ainda seria
47necessário. No entanto, o compilador também seria impedido de otimizar o
48acesso a shared_data _dentro_ da seção crítica, justamente quando sabemos
49que ninguém mais pode estar manipulando esses dados. Enquanto o bloqueio
50estiver mantido, shared_data não é volatile. Ao lidar com dados
51compartilhados, um bloqueio adequado torna volatile desnecessário e
52potencialmente prejudicial.
53
54A classe de armazenamento volatile foi originalmente concebida para
55registradores de E/S mapeados em memória. No kernel, os acessos a esses
56registradores também devem ser protegidos por bloqueios, mas também não se
57deseja que o compilador "otimize" esses acessos dentro de uma seção crítica.
58Contudo, no kernel, os acessos à memória de E/S são sempre feitos por meio de
59funções de acesso; acessar diretamente a memória de E/S via ponteiros é
60desencorajado e não funciona em todas as arquiteturas. Essas funções de
61acesso são implementadas de modo a impedir otimizações indesejadas e,
62portanto, mais uma vez, volatile é desnecessário.
63
64Outra situação em que se pode ser tentado a usar volatile é quando o
65processador fica em espera ocupada pelo valor de uma variável. A forma
66correta de realizar essa espera ocupada é::
67
68    while (my_variable != what_i_want)
69        cpu_relax();
70
71A chamada a cpu_relax() pode reduzir o consumo de energia da CPU ou ceder
72recursos a um processador lógico gêmeo hyperthreaded; ela também atua
73como barreira para o compilador e, portanto, mais uma vez, volatile é
74desnecessário. Naturalmente, a espera ocupada já é, por si só, uma prática
75geralmente antissocial.
76
77Ainda existem algumas situações raras em que volatile faz sentido no
78kernel:
79
80  - As funções de acesso mencionadas acima podem usar volatile em
81    arquiteturas nas quais o acesso direto à memória de E/S funciona.
82    Essencialmente, cada chamada a uma função de acesso torna-se uma
83    pequena seção crítica por si só e garante que o acesso ocorra conforme
84    esperado pelo programador.
85  - Código assembly inline que modifica memória, mas não tem outros
86    efeitos colaterais visíveis, corre o risco de ser removido pelo GCC.
87    Adicionar a palavra-chave volatile às instruções asm impede essa
88    remoção.
89  - A variável jiffies é especial, pois pode ter um valor diferente a cada
90    vez que é referenciada, mas pode ser lida sem qualquer bloqueio
91    especial. Portanto, jiffies pode ser volatile, mas a adição de
92    outras variáveis desse tipo é fortemente desencorajada. Nesse
93    sentido, jiffies é considerada um problema de "legado idiota" (nas
94    palavras de Linus); corrigi-la daria mais trabalho do que valeria a
95    pena.
96  - Ponteiros para estruturas de dados em memória coerente que possam ser
97    modificadas por dispositivos de E/S podem, às vezes, ser
98    legitimamente volatile. Um buffer circular usado por um adaptador
99    de rede, no qual esse adaptador altera ponteiros para indicar quais
100    descritores já foram processados, é um exemplo desse tipo de
101    situação.
102
103Na maior parte do código, nenhuma das justificativas acima para o uso de
104volatile se aplica. Como resultado, o uso de volatile provavelmente
105será considerado um bug e fará com que o código seja submetido a uma análise
106mais rigorosa. Desenvolvedores que se sintam tentados a usar volatile devem
107dar um passo atrás e pensar no que realmente estão tentando alcançar.
108
109Patches para remover variáveis volatile são, em geral, bem-vindos, desde
110que venham acompanhados de uma justificativa que demonstre que as questões
111de concorrência foram devidamente analisadas.
112
113
114Referências
115===========
116
117[1] https://lwn.net/Articles/233481/
118
119[2] https://lwn.net/Articles/233482/
120
121Créditos
122========
123
124Motivação original e pesquisa por Randy Dunlap
125
126Escrito por Jonathan Corbet
127
128Melhorias a partir de comentários de Satyam Sharma, Johannes Stezenbach,
129Jesper Juhl, Heikki Orsila, H. Peter Anvin, Philipp Hahn e Stefan
130Richter.
131