On 07/29/2010 09:41 PM, Hans-Peter Diettrich wrote:

What makes you think that this is different from x86?
With X86/32 Linux, the "application"address of a threadvar in the ASM instruction is the same for all threads. The ASM instruction is done with a "GS:" prefix, thus instead of the DS sector, (that is used without the prefix), GS is used as a selector. Now the 16 bit selector reads an entry in an OS-provided table and same is added to the address given in the instruction. The OS provides a different table for each thread and thus the resulting memory address is different, even though the GS selector value itself is the same for each thread.

With X86/32 Windows, the "application"address of a thread var in the ASM instruction is the same for all threads, as well. The access is done reading a structure that exists for each thread, using the "FS:" prefix in the ASM instruction (this results in using the appropriate thread's structure, as - like with Linux - the OS provides a different selecting table for each thread and thus the resulting memory address is different, even though the FS selector value itself is the same for each thread. Now the threadvar is accessed using this pointer and the standard DS selector. One indirection more than is Linux, slightly less efficient.

With NIOS (and supposedly similar with ARM), there is no "selector" hardware. Instead, one of the 32 registers (R26, called GP ("General Pointer") ) is used to address normal static and global variables. Now another register (R23) is used to address threadvars. Within a running application the value of R26 is always the same, while the value of R23 is different for each thread (of course all registers are preemption-safe).

Regarding pointers this yields:

With X86/32 Linux, with C you can define a pointer type "__thread int i*". So this pointer knows that is handles a threadvar and thus the compiler can generate code accessing the threadvar via GS even when a pointer is used (I did not test yet whether this really works). With Pascal this is not possible (AFAIK). So using a pointer, a value is always accessed via DS. AFAIK, when calculating the pointer value it's technically not possible to "rebase" the address from GS to DS, as the selector tables can't be read from user space. Catch 22.

With X86/32 Windows, The threadvar is finally accessed via DS anyway. So no problem here. If you save the address of a threadvar in a global variable, a different thread will be able to access the threadvar of the thread that saved the pointer. I should test if FP really gives thread specific address-values for pointers to threadvars in Windows but not in Linux. (IMHO different behavior would be erroneous.)

With NIOS (and supposedly similar with ARM), the pointer value for a threadvar will be calculated adding the offset to R23 creating a normal memory address. So no problem here. If you save the address of a threadvar in a global variable, a different thread will 'be able to access the threadvar of the thread that saved the pointer.

- Michael

PS.: maybe some might be willing to help enhancing this list with real ARM, X86/64 Linux and X86/64 Windows knowledge,

_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply via email to