1 .. include:: ../disclaimer-ita.rst 2 3 :Original: :ref:`Documentation/process/volatile-considered-harmful.rst <volatile_considered_harmful>` 4 :Translator: Federico Vaga <federico.vaga@vaga.pv.it> 5 6 .. _it_volatile_considered_harmful: 7 8 Perché la parola chiave "volatile" non dovrebbe essere usata 9 ------------------------------------------------------------ 10 11 Spesso i programmatori C considerano volatili quelle variabili che potrebbero 12 essere cambiate al di fuori dal thread di esecuzione corrente; come risultato, 13 a volte saranno tentati dall'utilizzare *volatile* nel kernel per le 14 strutture dati condivise. In altre parole, gli è stato insegnato ad usare 15 *volatile* come una variabile atomica di facile utilizzo, ma non è così. 16 L'uso di *volatile* nel kernel non è quasi mai corretto; questo documento ne 17 descrive le ragioni. 18 19 Il punto chiave da capire su *volatile* è che il suo scopo è quello di 20 sopprimere le ottimizzazioni, che non è quasi mai quello che si vuole. 21 Nel kernel si devono proteggere le strutture dati condivise contro accessi 22 concorrenti e indesiderati: questa è un'attività completamente diversa. 23 Il processo di protezione contro gli accessi concorrenti indesiderati eviterà 24 anche la maggior parte dei problemi relativi all'ottimizzazione in modo più 25 efficiente. 26 27 Come *volatile*, le primitive del kernel che rendono sicuro l'accesso ai dati 28 (spinlock, mutex, barriere di sincronizzazione, ecc) sono progettate per 29 prevenire le ottimizzazioni indesiderate. Se vengono usate opportunamente, 30 non ci sarà bisogno di utilizzare *volatile*. Se vi sembra che *volatile* sia 31 comunque necessario, ci dev'essere quasi sicuramente un baco da qualche parte. 32 In un pezzo di codice kernel scritto a dovere, *volatile* può solo servire a 33 rallentare le cose. 34 35 Considerate questo tipico blocco di codice kernel:: 36 37 spin_lock(&the_lock); 38 do_something_on(&shared_data); 39 do_something_else_with(&shared_data); 40 spin_unlock(&the_lock); 41 42 Se tutto il codice seguisse le regole di sincronizzazione, il valore di un 43 dato condiviso non potrebbe cambiare inaspettatamente mentre si trattiene un 44 lock. Un qualsiasi altro blocco di codice che vorrà usare quel dato rimarrà 45 in attesa del lock. Gli spinlock agiscono come barriere di sincronizzazione 46 - sono stati esplicitamente scritti per agire così - il che significa che gli 47 accessi al dato condiviso non saranno ottimizzati. Quindi il compilatore 48 potrebbe pensare di sapere cosa ci sarà nel dato condiviso ma la chiamata 49 spin_lock(), che agisce come una barriera di sincronizzazione, gli imporrà di 50 dimenticarsi tutto ciò che sapeva su di esso. 51 52 Se il dato condiviso fosse stato dichiarato come *volatile*, la 53 sincronizzazione rimarrebbe comunque necessaria. Ma verrà impedito al 54 compilatore di ottimizzare gli accessi al dato anche _dentro_ alla sezione 55 critica, dove sappiamo che in realtà nessun altro può accedervi. Mentre si 56 trattiene un lock, il dato condiviso non è *volatile*. Quando si ha a che 57 fare con dei dati condivisi, un'opportuna sincronizzazione rende inutile 58 l'uso di *volatile* - anzi potenzialmente dannoso. 59 60 L'uso di *volatile* fu originalmente pensato per l'accesso ai registri di I/O 61 mappati in memoria. All'interno del kernel, l'accesso ai registri, dovrebbe 62 essere protetto dai lock, ma si potrebbe anche desiderare che il compilatore 63 non "ottimizzi" l'accesso ai registri all'interno di una sezione critica. 64 Ma, all'interno del kernel, l'accesso alla memoria di I/O viene sempre fatto 65 attraverso funzioni d'accesso; accedere alla memoria di I/O direttamente 66 con i puntatori è sconsigliato e non funziona su tutte le architetture. 67 Queste funzioni d'accesso sono scritte per evitare ottimizzazioni indesiderate, 68 quindi, di nuovo, *volatile* è inutile. 69 70 Un'altra situazione dove qualcuno potrebbe essere tentato dall'uso di 71 *volatile*, è nel caso in cui il processore è in un'attesa attiva sul valore 72 di una variabile. Il modo giusto di fare questo tipo di attesa è il seguente:: 73 74 while (my_variable != what_i_want) 75 cpu_relax(); 76 77 La chiamata cpu_relax() può ridurre il consumo di energia del processore 78 o cedere il passo ad un processore hyperthreaded gemello; funziona anche come 79 una barriera per il compilatore, quindi, ancora una volta, *volatile* non è 80 necessario. Ovviamente, tanto per puntualizzare, le attese attive sono 81 generalmente un atto antisociale. 82 83 Ci sono comunque alcune rare situazioni dove l'uso di *volatile* nel kernel 84 ha senso: 85 86 - Le funzioni d'accesso sopracitate potrebbero usare *volatile* su quelle 87 architetture che supportano l'accesso diretto alla memoria di I/O. 88 In pratica, ogni chiamata ad una funzione d'accesso diventa una piccola 89 sezione critica a se stante, e garantisce che l'accesso avvenga secondo 90 le aspettative del programmatore. 91 92 - I codice *inline assembly* che fa cambiamenti nella memoria, ma che non 93 ha altri effetti espliciti, rischia di essere rimosso da GCC. Aggiungere 94 la parola chiave *volatile* a questo codice ne previene la rimozione. 95 96 - La variabile jiffies è speciale in quanto assume un valore diverso ogni 97 volta che viene letta ma può essere lette senza alcuna sincronizzazione. 98 Quindi jiffies può essere *volatile*, ma l'aggiunta ad altre variabili di 99 questo è sconsigliata. Jiffies è considerata uno "stupido retaggio" 100 (parole di Linus) in questo contesto; correggerla non ne varrebbe la pena e 101 causerebbe più problemi. 102 103 - I puntatori a delle strutture dati in una memoria coerente che potrebbe 104 essere modificata da dispositivi di I/O può, a volte, essere legittimamente 105 *volatile*. Un esempio pratico può essere quello di un adattatore di rete 106 che utilizza un puntatore ad un buffer circolare, questo viene cambiato 107 dall'adattatore per indicare quali descrittori sono stati processati. 108 109 Per la maggior parte del codice, nessuna delle giustificazioni sopracitate può 110 essere considerata. Di conseguenza, l'uso di *volatile* è probabile che venga 111 visto come un baco e porterà a verifiche aggiuntive. Gli sviluppatori tentati 112 dall'uso di *volatile* dovrebbero fermarsi e pensare a cosa vogliono davvero 113 ottenere. 114 115 Le modifiche che rimuovono variabili *volatile* sono generalmente ben accette 116 - purché accompagnate da una giustificazione che dimostri che i problemi di 117 concorrenza siano stati opportunamente considerati. 118 119 Riferimenti 120 =========== 121 122 [1] https://lwn.net/Articles/233481/ 123 124 [2] https://lwn.net/Articles/233482/ 125 126 Crediti 127 ======= 128 129 Impulso e ricerca originale di Randy Dunlap 130 131 Scritto da Jonathan Corbet 132 133 Migliorato dai commenti di Satyam Sharma, Johannes Stezenbach, Jesper 134 Juhl, Heikki Orsila, H. Peter Anvin, Philipp Hahn, e Stefan Richter.
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.