0001 .. include:: ../disclaimer-ita.rst
0002
0003 :Original: :ref:`Documentation/process/volatile-considered-harmful.rst <volatile_considered_harmful>`
0004 :Translator: Federico Vaga <federico.vaga@vaga.pv.it>
0005
0006 .. _it_volatile_considered_harmful:
0007
0008 Perché la parola chiave "volatile" non dovrebbe essere usata
0009 ------------------------------------------------------------
0010
0011 Spesso i programmatori C considerano volatili quelle variabili che potrebbero
0012 essere cambiate al di fuori dal thread di esecuzione corrente; come risultato,
0013 a volte saranno tentati dall'utilizzare *volatile* nel kernel per le
0014 strutture dati condivise. In altre parole, gli è stato insegnato ad usare
0015 *volatile* come una variabile atomica di facile utilizzo, ma non è così.
0016 L'uso di *volatile* nel kernel non è quasi mai corretto; questo documento ne
0017 descrive le ragioni.
0018
0019 Il punto chiave da capire su *volatile* è che il suo scopo è quello di
0020 sopprimere le ottimizzazioni, che non è quasi mai quello che si vuole.
0021 Nel kernel si devono proteggere le strutture dati condivise contro accessi
0022 concorrenti e indesiderati: questa è un'attività completamente diversa.
0023 Il processo di protezione contro gli accessi concorrenti indesiderati eviterà
0024 anche la maggior parte dei problemi relativi all'ottimizzazione in modo più
0025 efficiente.
0026
0027 Come *volatile*, le primitive del kernel che rendono sicuro l'accesso ai dati
0028 (spinlock, mutex, barriere di sincronizzazione, ecc) sono progettate per
0029 prevenire le ottimizzazioni indesiderate. Se vengono usate opportunamente,
0030 non ci sarà bisogno di utilizzare *volatile*. Se vi sembra che *volatile* sia
0031 comunque necessario, ci dev'essere quasi sicuramente un baco da qualche parte.
0032 In un pezzo di codice kernel scritto a dovere, *volatile* può solo servire a
0033 rallentare le cose.
0034
0035 Considerate questo tipico blocco di codice kernel::
0036
0037 spin_lock(&the_lock);
0038 do_something_on(&shared_data);
0039 do_something_else_with(&shared_data);
0040 spin_unlock(&the_lock);
0041
0042 Se tutto il codice seguisse le regole di sincronizzazione, il valore di un
0043 dato condiviso non potrebbe cambiare inaspettatamente mentre si trattiene un
0044 lock. Un qualsiasi altro blocco di codice che vorrà usare quel dato rimarrà
0045 in attesa del lock. Gli spinlock agiscono come barriere di sincronizzazione
0046 - sono stati esplicitamente scritti per agire così - il che significa che gli
0047 accessi al dato condiviso non saranno ottimizzati. Quindi il compilatore
0048 potrebbe pensare di sapere cosa ci sarà nel dato condiviso ma la chiamata
0049 spin_lock(), che agisce come una barriera di sincronizzazione, gli imporrà di
0050 dimenticarsi tutto ciò che sapeva su di esso.
0051
0052 Se il dato condiviso fosse stato dichiarato come *volatile*, la
0053 sincronizzazione rimarrebbe comunque necessaria. Ma verrà impedito al
0054 compilatore di ottimizzare gli accessi al dato anche _dentro_ alla sezione
0055 critica, dove sappiamo che in realtà nessun altro può accedervi. Mentre si
0056 trattiene un lock, il dato condiviso non è *volatile*. Quando si ha a che
0057 fare con dei dati condivisi, un'opportuna sincronizzazione rende inutile
0058 l'uso di *volatile* - anzi potenzialmente dannoso.
0059
0060 L'uso di *volatile* fu originalmente pensato per l'accesso ai registri di I/O
0061 mappati in memoria. All'interno del kernel, l'accesso ai registri, dovrebbe
0062 essere protetto dai lock, ma si potrebbe anche desiderare che il compilatore
0063 non "ottimizzi" l'accesso ai registri all'interno di una sezione critica.
0064 Ma, all'interno del kernel, l'accesso alla memoria di I/O viene sempre fatto
0065 attraverso funzioni d'accesso; accedere alla memoria di I/O direttamente
0066 con i puntatori è sconsigliato e non funziona su tutte le architetture.
0067 Queste funzioni d'accesso sono scritte per evitare ottimizzazioni indesiderate,
0068 quindi, di nuovo, *volatile* è inutile.
0069
0070 Un'altra situazione dove qualcuno potrebbe essere tentato dall'uso di
0071 *volatile*, è nel caso in cui il processore è in un'attesa attiva sul valore
0072 di una variabile. Il modo giusto di fare questo tipo di attesa è il seguente::
0073
0074 while (my_variable != what_i_want)
0075 cpu_relax();
0076
0077 La chiamata cpu_relax() può ridurre il consumo di energia del processore
0078 o cedere il passo ad un processore hyperthreaded gemello; funziona anche come
0079 una barriera per il compilatore, quindi, ancora una volta, *volatile* non è
0080 necessario. Ovviamente, tanto per puntualizzare, le attese attive sono
0081 generalmente un atto antisociale.
0082
0083 Ci sono comunque alcune rare situazioni dove l'uso di *volatile* nel kernel
0084 ha senso:
0085
0086 - Le funzioni d'accesso sopracitate potrebbero usare *volatile* su quelle
0087 architetture che supportano l'accesso diretto alla memoria di I/O.
0088 In pratica, ogni chiamata ad una funzione d'accesso diventa una piccola
0089 sezione critica a se stante, e garantisce che l'accesso avvenga secondo
0090 le aspettative del programmatore.
0091
0092 - I codice *inline assembly* che fa cambiamenti nella memoria, ma che non
0093 ha altri effetti espliciti, rischia di essere rimosso da GCC. Aggiungere
0094 la parola chiave *volatile* a questo codice ne previene la rimozione.
0095
0096 - La variabile jiffies è speciale in quanto assume un valore diverso ogni
0097 volta che viene letta ma può essere lette senza alcuna sincronizzazione.
0098 Quindi jiffies può essere *volatile*, ma l'aggiunta ad altre variabili di
0099 questo è sconsigliata. Jiffies è considerata uno "stupido retaggio"
0100 (parole di Linus) in questo contesto; correggerla non ne varrebbe la pena e
0101 causerebbe più problemi.
0102
0103 - I puntatori a delle strutture dati in una memoria coerente che potrebbe
0104 essere modificata da dispositivi di I/O può, a volte, essere legittimamente
0105 *volatile*. Un esempio pratico può essere quello di un adattatore di rete
0106 che utilizza un puntatore ad un buffer circolare, questo viene cambiato
0107 dall'adattatore per indicare quali descrittori sono stati processati.
0108
0109 Per la maggior parte del codice, nessuna delle giustificazioni sopracitate può
0110 essere considerata. Di conseguenza, l'uso di *volatile* è probabile che venga
0111 visto come un baco e porterà a verifiche aggiuntive. Gli sviluppatori tentati
0112 dall'uso di *volatile* dovrebbero fermarsi e pensare a cosa vogliono davvero
0113 ottenere.
0114
0115 Le modifiche che rimuovono variabili *volatile* sono generalmente ben accette
0116 - purché accompagnate da una giustificazione che dimostri che i problemi di
0117 concorrenza siano stati opportunamente considerati.
0118
0119 Riferimenti
0120 ===========
0121
0122 [1] http://lwn.net/Articles/233481/
0123
0124 [2] http://lwn.net/Articles/233482/
0125
0126 Crediti
0127 =======
0128
0129 Impulso e ricerca originale di Randy Dunlap
0130
0131 Scritto da Jonathan Corbet
0132
0133 Migliorato dai commenti di Satyam Sharma, Johannes Stezenbach, Jesper
0134 Juhl, Heikki Orsila, H. Peter Anvin, Philipp Hahn, e Stefan Richter.