Michael Schnell schrieb:

Do you mean segment or general-purpose register(s)?
This depends on the arch. X86 does not really have general-purpose registers, while NIOS, ARM MIPS (and supposedly X86/64) has almost only general-purpose registers.

M68K has distinct address and data registers, x86 has segment and data registers, not to mention other special registers (flags...) in every architecture.

How is that different from WinAPI?
The whole discussion here is that X86/32-WinAPI in fact uses a segment register for this purpose but it's nowhere decently documented. Moreover (bus not a problem) I understand that gnu C on X86/32 Linux uses a segment register as a pointer to the threadvar area, while the non-documented WinAPI uses a segment register as a pointer to a thread-dedicated structure that again contains a pointer to the threadvar area.

I see no difference here. IMO the segment register is used implicitly in thread API calls, with no further use by application code. Every thread has one "slot" reserved in the OS-maintained data structure, where it can store one private value. In the "Using Thread Local Storage" entry in the MSDN library this value is the handle of a memory block, created with LocalAlloc. It could be the handle of an local heap as well, created with HeapCreate, when special handling of threadvars shall be implemented in the RTL. No special segment register seems to be involved in the subsequent use of that allocated memory (flat memory model).


When we consider threads created in a DLL/.so, too, then the platform has to establish such conventions, for the entire app<->library ABI.
Not really.

I found the Windows conventions in "Register Usage" in the MSDN Library, telling which registers are considered (non-)volatile.

The main executable can create a thread and a function called in the thread can internally declare and use a static threadvar. So the ABI needs to document how the (ASM) function is supposed to access the threadvar it internally defines. As it needs to use a register for this, the ABI needs to define that the alee is to use exactly this register and (supposedly) that the callee is not supposed to modify it when it returns.

Application code can use any non-volatile register for (thread...) communication purposes. When an application and a shared library shall work together, they must use the same convention about the use of such registers.


How else should it be done, in a practical way? Registers are not a solution, since: Assume you have 10 units, each of which declares only one threadvar - then you would have to reserve 10 registers for these threadvars, application-wide!
Sorry but here you are decently wrong.

With most archs all static variables (such as globals and threadvars) always are accessed relative to a register. With X86/32 globals and statics are allocated relative to DS,

Here the segment register is somewhat irrelevant, since each maps to the entire 4 GB process address space. All 32 bit "pointers" simply are offsets into that address space, like in any other unsegmented architecture. The only difference may be access rights (CS: executable, read-only).

with X86/32-Linux, threadvars are allocated relative to FS.

FS and GS may be used for special (OS, SEH and TLS) management, they are useless in application code.


The archs i know, that don't have segment registers use "address"- or "general purpose" registers for this. So we have two "basic data pointers": one for the normal static vars and one for the threadvars. Both are safe regarding preemption. The basic pointer for normal static vars is initialized at the program start and never changed within the application, the pointer to the threadvars is initialized when a thread starts and - because it is preemption save just like any other register - its never changed when this thread is running.

On Windows such base-pointers should reside in non-volatile registers, otherwise no difference in their use. As long as the base values are immutable, the equivalent absolute addresses can be used instead (in contrast to PIC).


Moreover the point with threadvars is that threads that use the same code see different values in the same threadvar. These threads of course can't use different registers to access them as the run the same code.

Consider a threadvar as a field of a related thread object (instance).

DoDi

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

Reply via email to