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