https://github.com/dlang/druntime/pull/2057 was merged without thread safety concerns being addressed.
The code needs to be checked carefully for its behaviour when several threads are accessing the GC before the ProtoGC has been swapped out with the real implementation (https://github.com/dlang/druntime/pull/2057#discussion_r168910433).
If threads are created using the standard "auto t = new Thread(...); […]" idiom, this is of course not going to be an issue, because the GC will already have been initialised when the child thread is spawned. However, it is conceivable that two independent C threads concurrently start to use D(runtime) code.
Comment #1 by schveiguy — 2018-03-01T16:31:19Z
A thought on a potential fix: once you detect ranges being added/removed from independent threads, then you initialize the GC.
You should be able to do this with an atomic read, and then CAS to a ProtoGC instance variable that stores the "main thread" id.
The atomic read should be negligible compared to manipulating the roots/ranges arrays.
Comment #2 by schveiguy — 2018-03-01T16:42:48Z
Hm.. actually that doesn't work, because one thread could be adding roots while the other one is initializing the GC, causing a race.
There may just have to be some sort of lock, even if it's a simple/spin lock.
Comment #3 by rdm — 2021-03-18T13:56:08Z
Example program that makes use of addRoots before anything is allocated.
The D following lib is called from multiple threads in C++.
```D
import std;
extern(C) {
void cFunc( ){
Foo foo;
foo.inc;
}
}
struct Foo{
Array!int impl;
void inc(){
impl.insertBefore(impl[], 0);
}
}
```
Comment #4 by robert.schadek — 2024-12-07T13:38:05Z