[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