[fpc-devel] OO rewrite - technical questions
Michael Schnell
mschnell at lumino.de
Fri Jul 23 12:11:57 CEST 2010
On 07/21/2010 04:23 PM, Hans-Peter Diettrich wrote:
> . And since the segment registers are only changed on process/thread
> switches, the resulting overhead is kept to the absolute minimum.
Same with using a segment registers the base for the threadvar area.
This only needs to be initiated when a thread is created. This is a
quite rare occasion, as you will use a thread-pool if a threaded
application needs to switch between multiple active/passive threads, anyway.
>
> Apart from that, I've heard that segment registers have no special
> effect in 64 bit mode at all? How can these registers ever be used, in
> 64 bit code? Safe bet: don't touch them ever, use only as documented
> (for FS/GS).
I did not do any research yet regarding X86/64 :(.
>
> When an OS does not provide an API to create segments (in a 32 bit
> flat model), there exist no values (segment selectors) that can be
> loaded into a segment register at all, by application code.
If the OS does not provide an API that defines the use of the registers
and the OS manufacturer does not provide a documentation that tells us
otherwise, I think we are allowed to presume that these registers are
"just registers" that work as documented in the way the hardware
documentation describes and thus a user application is free to use them
anywhere and the OS guaranteed that they are save regarding preemption.
AFAIK, this is commonly done with ES, and so I don't see why it's not
true with GS. It seems that on thread start in Windows, FS is predefined
with a pointer to some Windows specific thread information, but that
does not mean that it's not allowed to assign some other value to FS and
that it will not be safe.
>
> Of course this would be nice, but till then it's simply wise to not
> use such undocumented registers at all, neither in compiler created
> code, nor in ASM.
Hmm, is BX explicitly documented ?
>
> IMO the OS provides means to allocate an thread-local memory block
> (Thread Local Storage), whose content *can* be used for threadvars.
AFAI understand, in Linux (any architecture) the OS just preserves a
count of registers and the (e.g. C) compiler just uses one of them as a
pointer to the threadvars. When creating a thread the thread library
(e.g. libc) creates the threadvar block and assigns the pointer to the
said register.
> It's not up to the API or ABI to bother with the "record" layout of
> that TLS memory block, that's all application/compiler specific.
The way how threadvars are don _is_ compiler specific. Of course it does
make sense if all compilers working for a certain OS use the same
paradigm here, so the OS _should_ provide a documentation how they
should do it,. In Linux of course the gnu C compiler team takes care of
all this.
> A threadvar simply is a member of that record, and the API specified
> register contains the (direct or indirect) address of the TLS.
I suppose this is the Windows specific way....
>
> IMO also no physical/logical separation exists, between application
> (main thread) and other thread memory, everything exists in the
> overall process memory. It's up to the compiler/coder, to prevent
> unsynchronized access to memory locations that could be updated
> concurrently by multiple threads.
Of course this is correct. But the compiler only has two options to do
this. Either do an OS API call foe each access to a global threadvar
(very slow) or dedicate a register a a pointer to the block of
global threadvars. I know that e.g. NIOS (that is similar to ARM or
MIPS) just uses one of it's 32 general purpose registers for this.
X86/32 does not have many registers, so it's a good idea to use a
segment register. This is what Linux GNUC is officially documented to
do and what the "unsafe" documentation mentioned in this thread states
for Windows as well (here in fact maybe as a pointer to a pointer to the
threadvar block).
>
> BTW, the definition of "threadvar" is not a very practical one. In
> practice it should be possible to assign threadvars to *specific*
> threads, otherwise *every* thread has to allocate an TLS containing
> *all* the threadvars of the entire application. Furthermore it would
> be sufficient to have all "threadvars" in the specific TThread-derived
> classes, eliminating the need for any additional TLS.
The programmer is free to do this by using just another indirection. You
may use a single global threadvar that holds the address of an Object
(or record) that a thread allocates on the heap when it starts. The
Object or Record now can hold any thread specific information.
Many global threadvars only make sense if you start the same code in
many threads.
-Michael
More information about the fpc-devel
mailing list