Initializing D runtime and executing module and TLS ctors for D libraries

IGotD- nise at nise.com
Sun Jan 24 01:18:43 UTC 2021


On Sunday, 24 January 2021 at 00:24:55 UTC, Ali Çehreli wrote:
>
> One question I have is, does rt_init already do 
> thread_attachThis? I ask because I have a library that is 
> loaded by Python and things work even *without* calling 
> thread_attachThis.
>

During rt_init in the main thread, thread_attachThis is performed 
what I have seen.

>
> Another question: Are TLS ctors executed when I do loadLibrary?
>
> And when they are executed, which modules are involved? The 
> module that is calling rt_moduleTlsCtor or all modules? What 
> are "all modules"?

The TLS standard (at least the ELF standard) does not have ctors. 
Only simple initialization are allowed meaning the initial data 
is stored as .tdata which is copied to the specific memory area 
for each thread. There is also a .tbss which is zero memory just 
like the .bss section. Actual ctor code that runs for each TLS 
thread is language specific and not part of the ELF standard 
therefore no such TLS ctor code are being run in the lower level 
API. The initialization (only copy and zeroing) of TLS data is 
being done when each thread starts. This can even be done in a 
lazy manner when the first TLS variable is being accessed.

>
> I have questions regarding thread_attachThis and 
> thread_detachThis: When should they be called? Should the 
> library expose a function that the users must call from *each 
> thread* that they will be using? This may not be easy because a 
> user may not know what thread they are running on. For example, 
> the user of our library may be on a framework where threads may 
> come and go, where the user may not have an opportunity to call 
> thread_detachThis when a thread goes away. For example, the 
> user may provide callback functions (which call us) to a 
> framework that is running on a thread pool.
>

I call thread_attachThis as soon the thread is supposed to call a 
D function. For example a callback from a thread in a thread 
pool. This usually happens when there is a function or delegate 
involved as any jump to D code would use them. I have to make a 
generic API and then a D API on top of that. In practice this 
means there is a trampoline function involved where and 
thread_attachThis and thread_detachThis is being called. Also 
this is where I call TLS ctors/dtors. It is an effect that 
delegates is language specific and it falls natural that way. 
Avoid extern(C) calls directly into D code.

In practice you can do this for any thread even if there are 
several delegates during the thread lifetime. You can simply have 
a TLS bool variable telling if the thread_attachThis and 
rt_moduleTlsCtor have already been run.

>
> More questions: Can I thread_detachThis the thread that called 
> rt_init? Can I call rt_moduleTlsCtor more than once? I guess it 
> depends on each module. It will be troubling if a TLS ctor 
> reinitializes an module state. :/
>

I have brought up this question before because like it is right 
now I haven't seen any "rt_uninit" or "rt_close" function. This 
is bit limiting for me as the main thread can exit while the 
process lives on. In general the main thread that goes into main 
must also be the last one returning the entire line of functions 
that was called during entry of the process. What will happen is 
that you possibly do a thread_detachThis twice.

Short answer is just park the main thread while the bulk is being 
done by other threads. Unfortunately that's how many libraries 
work today.




More information about the Digitalmars-d-learn mailing list