18c2ecf20Sopenharmony_ci.. include:: ../disclaimer-ita.rst
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci:Original: :ref:`Documentation/process/volatile-considered-harmful.rst <volatile_considered_harmful>`
48c2ecf20Sopenharmony_ci:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci.. _it_volatile_considered_harmful:
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ciPerché la parola chiave "volatile" non dovrebbe essere usata
98c2ecf20Sopenharmony_ci------------------------------------------------------------
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ciSpesso i programmatori C considerano volatili quelle variabili che potrebbero
128c2ecf20Sopenharmony_ciessere cambiate al di fuori dal thread di esecuzione corrente; come risultato,
138c2ecf20Sopenharmony_cia volte saranno tentati dall'utilizzare *volatile* nel kernel per le
148c2ecf20Sopenharmony_cistrutture dati condivise.  In altre parole, gli è stato insegnato ad usare
158c2ecf20Sopenharmony_ci*volatile* come una variabile atomica di facile utilizzo, ma non è così.
168c2ecf20Sopenharmony_ciL'uso di *volatile* nel kernel non è quasi mai corretto; questo documento ne
178c2ecf20Sopenharmony_cidescrive le ragioni.
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ciIl punto chiave da capire su *volatile* è che il suo scopo è quello di
208c2ecf20Sopenharmony_cisopprimere le ottimizzazioni, che non è quasi mai quello che si vuole.
218c2ecf20Sopenharmony_ciNel kernel si devono proteggere le strutture dati condivise contro accessi
228c2ecf20Sopenharmony_ciconcorrenti e indesiderati: questa è un'attività completamente diversa.
238c2ecf20Sopenharmony_ciIl processo di protezione contro gli accessi concorrenti indesiderati eviterà
248c2ecf20Sopenharmony_cianche la maggior parte dei problemi relativi all'ottimizzazione in modo più
258c2ecf20Sopenharmony_ciefficiente.
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ciCome *volatile*, le primitive del kernel che rendono sicuro l'accesso ai dati
288c2ecf20Sopenharmony_ci(spinlock, mutex, barriere di sincronizzazione, ecc) sono progettate per
298c2ecf20Sopenharmony_ciprevenire le ottimizzazioni indesiderate.  Se vengono usate opportunamente,
308c2ecf20Sopenharmony_cinon ci sarà bisogno di utilizzare *volatile*.  Se vi sembra che *volatile* sia
318c2ecf20Sopenharmony_cicomunque necessario, ci dev'essere quasi sicuramente un baco da qualche parte.
328c2ecf20Sopenharmony_ciIn un pezzo di codice kernel scritto a dovere, *volatile* può solo servire a
338c2ecf20Sopenharmony_cirallentare le cose.
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ciConsiderate questo tipico blocco di codice kernel::
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci    spin_lock(&the_lock);
388c2ecf20Sopenharmony_ci    do_something_on(&shared_data);
398c2ecf20Sopenharmony_ci    do_something_else_with(&shared_data);
408c2ecf20Sopenharmony_ci    spin_unlock(&the_lock);
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ciSe tutto il codice seguisse le regole di sincronizzazione, il valore di un
438c2ecf20Sopenharmony_cidato condiviso non potrebbe cambiare inaspettatamente mentre si trattiene un
448c2ecf20Sopenharmony_cilock.  Un qualsiasi altro blocco di codice che vorrà usare quel dato rimarrà
458c2ecf20Sopenharmony_ciin attesa del lock.  Gli spinlock agiscono come barriere di sincronizzazione
468c2ecf20Sopenharmony_ci- sono stati esplicitamente scritti per agire così - il che significa che gli
478c2ecf20Sopenharmony_ciaccessi al dato condiviso non saranno ottimizzati.  Quindi il compilatore
488c2ecf20Sopenharmony_cipotrebbe pensare di sapere cosa ci sarà nel dato condiviso ma la chiamata
498c2ecf20Sopenharmony_cispin_lock(), che agisce come una barriera di sincronizzazione, gli imporrà di
508c2ecf20Sopenharmony_cidimenticarsi tutto ciò che sapeva su di esso.
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ciSe il dato condiviso fosse stato dichiarato come *volatile*, la
538c2ecf20Sopenharmony_cisincronizzazione rimarrebbe comunque necessaria.  Ma verrà impedito al
548c2ecf20Sopenharmony_cicompilatore di ottimizzare gli accessi al dato anche _dentro_ alla sezione
558c2ecf20Sopenharmony_cicritica, dove sappiamo che in realtà nessun altro può accedervi.  Mentre si
568c2ecf20Sopenharmony_citrattiene un lock, il dato condiviso non è *volatile*.  Quando si ha a che
578c2ecf20Sopenharmony_cifare con dei dati condivisi, un'opportuna sincronizzazione rende inutile
588c2ecf20Sopenharmony_cil'uso di *volatile* - anzi potenzialmente dannoso.
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ciL'uso di *volatile* fu originalmente pensato per l'accesso ai registri di I/O
618c2ecf20Sopenharmony_cimappati in memoria.  All'interno del kernel, l'accesso ai registri, dovrebbe
628c2ecf20Sopenharmony_ciessere protetto dai lock, ma si potrebbe anche desiderare che il compilatore
638c2ecf20Sopenharmony_cinon "ottimizzi" l'accesso ai registri all'interno di una sezione critica.
648c2ecf20Sopenharmony_ciMa, all'interno del kernel, l'accesso alla memoria di I/O viene sempre fatto
658c2ecf20Sopenharmony_ciattraverso funzioni d'accesso; accedere alla memoria di I/O direttamente
668c2ecf20Sopenharmony_cicon i puntatori è sconsigliato e non funziona su tutte le architetture.
678c2ecf20Sopenharmony_ciQueste funzioni d'accesso sono scritte per evitare ottimizzazioni indesiderate,
688c2ecf20Sopenharmony_ciquindi, di nuovo, *volatile* è inutile.
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ciUn'altra situazione dove qualcuno potrebbe essere tentato dall'uso di
718c2ecf20Sopenharmony_ci*volatile*, è nel caso in cui il processore è in un'attesa attiva sul valore
728c2ecf20Sopenharmony_cidi una variabile.  Il modo giusto di fare questo tipo di attesa è il seguente::
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci    while (my_variable != what_i_want)
758c2ecf20Sopenharmony_ci        cpu_relax();
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ciLa chiamata cpu_relax() può ridurre il consumo di energia del processore
788c2ecf20Sopenharmony_cio cedere il passo ad un processore hyperthreaded gemello; funziona anche come
798c2ecf20Sopenharmony_ciuna barriera per il compilatore, quindi, ancora una volta, *volatile* non è
808c2ecf20Sopenharmony_cinecessario.  Ovviamente, tanto per puntualizzare, le attese attive sono
818c2ecf20Sopenharmony_cigeneralmente un atto antisociale.
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ciCi sono comunque alcune rare situazioni dove l'uso di *volatile* nel kernel
848c2ecf20Sopenharmony_ciha senso:
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci  - Le funzioni d'accesso sopracitate potrebbero usare *volatile* su quelle
878c2ecf20Sopenharmony_ci    architetture che supportano l'accesso diretto alla memoria di I/O.
888c2ecf20Sopenharmony_ci    In pratica, ogni chiamata ad una funzione d'accesso diventa una piccola
898c2ecf20Sopenharmony_ci    sezione critica a se stante, e garantisce che l'accesso avvenga secondo
908c2ecf20Sopenharmony_ci    le aspettative del programmatore.
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci  - I codice *inline assembly* che fa cambiamenti nella memoria, ma che non
938c2ecf20Sopenharmony_ci    ha altri effetti espliciti, rischia di essere rimosso da GCC.  Aggiungere
948c2ecf20Sopenharmony_ci    la parola chiave *volatile* a questo codice ne previene la rimozione.
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci  - La variabile jiffies è speciale in quanto assume un valore diverso ogni
978c2ecf20Sopenharmony_ci    volta che viene letta ma può essere lette senza alcuna sincronizzazione.
988c2ecf20Sopenharmony_ci    Quindi jiffies può essere *volatile*, ma l'aggiunta ad altre variabili di
998c2ecf20Sopenharmony_ci    questo è sconsigliata.  Jiffies è considerata uno "stupido retaggio"
1008c2ecf20Sopenharmony_ci    (parole di Linus) in questo contesto; correggerla non ne varrebbe la pena e
1018c2ecf20Sopenharmony_ci    causerebbe più problemi.
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci  - I puntatori a delle strutture dati in una memoria coerente che potrebbe
1048c2ecf20Sopenharmony_ci    essere modificata da dispositivi di I/O può, a volte, essere legittimamente
1058c2ecf20Sopenharmony_ci    *volatile*.  Un esempio pratico può essere quello di un adattatore di rete
1068c2ecf20Sopenharmony_ci    che utilizza un puntatore ad un buffer circolare, questo viene cambiato
1078c2ecf20Sopenharmony_ci    dall'adattatore per indicare quali descrittori sono stati processati.
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ciPer la maggior parte del codice, nessuna delle giustificazioni sopracitate può
1108c2ecf20Sopenharmony_ciessere considerata.  Di conseguenza, l'uso di *volatile* è probabile che venga
1118c2ecf20Sopenharmony_civisto come un baco e porterà a verifiche aggiuntive.  Gli sviluppatori tentati
1128c2ecf20Sopenharmony_cidall'uso di *volatile* dovrebbero fermarsi e pensare a cosa vogliono davvero
1138c2ecf20Sopenharmony_ciottenere.
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ciLe modifiche che rimuovono variabili *volatile* sono generalmente ben accette
1168c2ecf20Sopenharmony_ci- purché accompagnate da una giustificazione che dimostri che i problemi di
1178c2ecf20Sopenharmony_ciconcorrenza siano stati opportunamente considerati.
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ciRiferimenti
1208c2ecf20Sopenharmony_ci===========
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci[1] http://lwn.net/Articles/233481/
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci[2] http://lwn.net/Articles/233482/
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ciCrediti
1278c2ecf20Sopenharmony_ci=======
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ciImpulso e ricerca originale di Randy Dunlap
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ciScritto da Jonathan Corbet
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ciMigliorato dai commenti di Satyam Sharma, Johannes Stezenbach, Jesper
1348c2ecf20Sopenharmony_ciJuhl, Heikki Orsila, H. Peter Anvin, Philipp Hahn, e Stefan Richter.
135