Se davvero davvero bisogno di essere in grado di fare questo per qualche motivo, si dovrebbe accedere a una variabile thread-locale dal linguaggio assembly per il precaricamento il suo indirizzo in C, in questo modo:
__thread unsigned val;
void incval(void)
{
unsigned *vp = &val;
asm ("incl\t%0" : "+m" (*vp));
}
Questo perché la sequenza di codice richiesta per accedere a una variabile locale del thread è diversa per quasi ogni combinazione di SO e CPU supportata da GCC e varia anche se si sta compilando per una libreria condivisa anziché un eseguibile (ovvero con -fPIC
). Il costrutto sopra permette al compilatore di emettere la sequenza di codice corretta per te. Nei casi in cui è possibile accedere alla variabile locale del thread senza istruzioni aggiuntive, la generazione dell'indirizzo verrà piegata nell'operazione di assemblaggio. A titolo di esempio, ecco come gcc 4.7 per x86/Linux compila il sopra in diversi modi possibili diversi (ho spogliato fuori un mucchio di direttive assembler in tutti i casi, per chiarezza) ...
# -S -O2 -m32 -fomit-frame-pointer
incval:
incl %gs:[email protected]
ret
# -S -O2 -m64
incval:
incl %fs:[email protected]
ret
# -S -O2 -m32 -fomit-frame-pointer -fpic
incval:
pushl %ebx
call __x86.get_pc_thunk.bx
addl $_GLOBAL_OFFSET_TABLE_, %ebx
leal [email protected](,%ebx,1), %eax
call [email protected]
incl (%eax)
popl %ebx
ret
# -S -O2 -m64 -fpic
incval:
.byte 0x66
leaq [email protected](%rip), %rdi
.value 0x6666
rex64
call [email protected]
incl (%rax)
ret
Rendetevi conto che i tutti e quattro gli esempi sarebbero diversi se avessi compilato per x86/OSX e diverso ancora per x86/Windows.
1) Perché non è possibile scrivere "val + = 1;" invece? 2) Scriverlo, compilarlo con '-O2 -S' ed esaminare l'output dell'assembly; scoprirai che ti stai sbagliando su come accedere alle variabili di '__thread'. – zwol
@Zack puoi scrivere una risposta a riguardo? – 0x90
val ++ si traduce in movl $ 0x1,% gs: 0xfffffffc, ma quando eseguo asm ("movl $ 1,% gs: val") manualmente si traduce in movl $ 0x1,% gs: 0x8049f14. Come ottenere l'indirizzo 0xfffffffc nel mio programma. – Yogi