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