Multithreading, Tracing Garbage Collectors and Native C APIs

Viewed 47

Many programming languages native C APIs with tracing garbage collectors have a root and unroot functions to protect temporary values from being collected.

In a multithreaded environment, if a native function unroot all of its objects and then return one of said objects, what happens if between unrooting and returning, another thread allocates causing a collection? Will the value that I'm trying to return be collected as well?

I've looked at Ruby, Julia, Janet and V8 for solutions, but I couldn't find nothing obvious regarding this. Is it safe to just to just use pairs of root and unroot functions in a multithreaded environment?

I'm trying to build a simple stop the world mark and sweep garbage collector for my scripting language, and I'm trying to make everything that needs to be thread safe, safe. Currently my garbage collector has two singly linked lists, one for allocated objects and the other for roots, protected by a global mutex.

1 Answers

If all objects are removed from the set of root objects, then all object can be garbage collected (possibly from another thread). This include the returned object. This is true even if it is for a very short period of time, unless one ensures that the garbage collector does not pass by during that portion of time (this is hard to ensure in a parallel context).

There are many different implementation of tracing garbage collectors. AFAIK, many store the returned object in a stack (possibly the system stack or a manual one) tracked by the garbage collector. This stack typically hold (a part of) the root object set. The stack can be automatically managed or manually. There are callee/caller conventions so that returned objects can never unsafely be "unrooted" and collected. There is also possibly another data structure for global object references. This is the case of the GC of R for example which is pretty simple (see here). Java use a similar concept based on thread-local stack frames (with an automatic storage duration) for local references. Global references are implicitly created but explicitly manually deleted inside low-level codes (eg. JNI). You can find more information here.

Related