<p dir="auto">This issue is for discussing how to make the new GC (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="45978605" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/8699" data-hovercard-type="pull_request" data-hovercard-url="/JuliaLang/julia/pull/8699/hovercard" href="https://github.com/JuliaLang/julia/pull/8699">#8699</a>) thread-safe.  A GC expert should check the arguments here.  For background, see the elegant state transition diagram in <a href="https://github.com/JuliaLang/julia/blob/master/src/gc.c#L216"><code class="notranslate">src/gc.c</code></a>.</p>
<p dir="auto">I'm assuming that garbage collection operates in stop-the-world mode, and for now, that the mark/sweep phase is single-threaded.  Each thread can have its own thread-local <code class="notranslate">remset</code>, with occasional duplication across the sets because of the race described below.</p>
<p dir="auto"><strong>Key question</strong>: what state transitions can race against each other?  If I understand the GC correctly, the only racy transitions  arise from a write barrier for the same parent, and that transition is <code class="notranslate">GC_MARKED --&gt; GC_QUEUED</code>, which changes the low two bits of the memory location from 01 to 10.  If this is indeed the only racy transition, then a plain load, modify, plain store sequence will suffice, since all racing participants will be attempting to write the same value to the location.   To be portable C11, we should use relaxed atomic loads/stores instead of the current assignments into bitfields, but that's a purist nitpick.</p>
<p dir="auto">The possibility of a race will require lightening up on assertions that check for duplicate enqueuing of roots.  There will need to be a <code class="notranslate">memory_order_acq_rel</code> fence between normal operation and garbage collection, but that's probably already implied by synchronization between normal operation and garbage collection.</p>
<p dir="auto"><strong>Possible problem</strong>: <code class="notranslate">gc_wb_buf</code> appears to engaging in other transitions.  If so, which of these might race against each other?  Are these transitions always on different <code class="notranslate">gc_bits</code> than the ones affected by <code class="notranslate">gc_wb</code>?</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ julia                      -e 'reinterpret(Nothing, nothing)'                               
                                               
$ julia --code-coverage=user -e 'reinterpret(Nothing, nothing)'                                                         
ERROR: bitcast: target type not a leaf primitive type
Stacktrace:
 [1] reinterpret(::Type{Nothing}, ::Nothing) at ./essentials.jl:413
 [2] top-level scope at none:1"><pre class="notranslate"><code class="notranslate">$ julia                      -e 'reinterpret(Nothing, nothing)'                               
                                               
$ julia --code-coverage=user -e 'reinterpret(Nothing, nothing)'                                                         
ERROR: bitcast: target type not a leaf primitive type
Stacktrace:
 [1] reinterpret(::Type{Nothing}, ::Nothing) at ./essentials.jl:413
 [2] top-level scope at none:1
</code></pre></div>
<p dir="auto">Started behaving differently with 1.1, on 1.0 both fail. Arguably this use of <code class="notranslate">reinterpret</code> should be allowed, but the change in behavior based on code coverage had me stumped for a while.</p>