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