[fpc-devel] threadvar implementation
Michael Schnell
mschnell at lumino.de
Wed Aug 4 10:24:44 CEST 2010
On 08/04/2010 03:57 AM, Hans-Peter Diettrich wrote:
>
> Getting the linear address of a threadvar depends on the OS/FPC
> implementation.
Of course the compilker needs to adhere to what the OS provides.
As already said multiple times, Win32 for each thread provides a block
of user space memory that is addressed by FS and here the base address
(to be used via DS) of the threadvar area thus the threadvr itself is
rto be accessed using DS. OTOH, Linux X86 provides the address of the
threadvar area directly in GS, so that the threadvar needs to be
accessed using GS.
As Pascal (other than C) does not provide a means to define that a
pointer type is a pointer to a threadvar rather than to a normal var,
Pascal alway uses DS to access any variable.
As the user program only sees linear addresses (which have 32 Bit
offsets are different regarding to which segment register (or segment
register content is used) there are no means for the user land program
to calculate a DS-denoted offset (to be used by a pointer) from the
GS-denoted offset it knows for the threadvar.
> IMO FPC *should* allow to get the address of a threadvar by
> AddressOf(threadvar)
Usually It does - using DS (the default, thus not explicitly noting a
segment register in the ASM instruction).
Only with X86/32-Linux when not using a pointer it can't do this (in a
high-performance way), as the DS-based offset of the threadvar is not
known. In fact it does it "the slow way", doing a function call for any
access to a threadvar. As Lazarus does not provide a means to do single
setpping in ASM code, I was not able to find out what actually is done here.
> - test yourself. It may be possible to get that address also with an
> LEA instruction (untested).
I did the test.
lea eax, FS:[$34] resulst in EAX = $34, even though FS is $3B and
mov eax, FS:[$34] results in correctly loading ax from memory and
mov eax,[eax] with eax = $34 correctly results in an access violation
in fact I did not suppose that
lea eax, FS:[$34] would compile at all but it does
the code of lea eax, FS:[$34] is 64 8D 05 34 00 00 00, using the DS
prefix "64" while
the code of lea eax, $34] is 8D 05 34 00 00 00
I don't see what lea eax, FS:[$34] in fact is supposed to do.
> AFAIR Delphi obtains the address of the threadvar memory block via FS/GS,
Right via FS it gets the "thread management block" that contains the
(DS-based) offset of the threadvar block, (as stated before. and exactly
as M$ C does).
> so that it's possible to use the same instruction sequence,
This is what I tried to express in the beginning.
> except that finally not the value of the threadvar is retrieved,
Yep, this is as Win32 handles it (but other than Linux does )
> but its address (LEA instead of MOV).
Nope.
to read a normal var it needs to do
mov eax, normvar; (this is implicitely DS based)
to get the pointer to a normal var it needs to do
lea eax, normalvar; (this is implicitely DS based)
to read a threadvar, it needs to do
mov eax, FS:(threadmanagementblock+thrfeafvarblockoffset); (this
results in the DS-based address of the threadvar block)
mov eax, [eax+threadvar]
to get the pointer to a thrfeadvar it can do
mov eax, FS:(threadmanagementblock+thrfeafvarblockoffset); (this
results in the DS-based address of the threadvar block)
lea eax, [eax+threadvar]; (this results in the DS-based address of the
threadvar)
or
mov eax, FS:(threadmanagementblock+thrfeafvarblockoffset); (this
results in the DS-based address of the threadvar block)
add eax, offset (threadvar)]; (this results in the DS-based address of
the threadvar)
this can't be done in a single ASM instruction
-Michael
More information about the fpc-devel
mailing list