Write barrier for G1GC SATB wasn't atomic?

Igor Veresov igor.veresov at oracle.com
Wed Mar 23 07:00:43 UTC 2011

That's ok. The goal of SATB is to snapshot the object graph and track 
the changes to it. So, in your example, obj0 was the contents of the 
field before the snapshot. It doesn't matter if we capture it multiple 
times or values that were stored to the field after the snapshot - all 
of this will be filtered later. The important part is that we captured 
the value that was before the snapshot at least once.

On 3/22/11 11:11 PM, Narihiro Nakamura wrote:
> Hi, all.
> I read G1GC by a hobby.
> I have one question about write barrier for SATB.
> I think that satb write barrier is defined in the following points:
> - cpu/sparc/vm/assembler_sparc.cpp: MacroAssembler::g1_write_barrier_pre()
> - cpu/x86/vm/assembler_x86.cpp: MacroAssembler::g1_write_barrier_pre()
> - share/vm/opto/graphKit.cpp: GraphKit::g1_write_barrier_pre()

There are also C1 versions in c1_LIRGeneration.cpp, c1_CodeStubs_*.cpp, 

> I read their code.
> I think that the pseudo-cord of "satb write barrier" is as follows:
> 1: def satb_write_barrier(field, newobj):
> 2:     oldobj = *field   // (a)
> 3:     if $gc_phase == GC_CONCURRENT_MARK and oldobj != Null:
> 4:         enqueue($current_thread.stab_mark_queue, oldobj) // (b)
> 5:     *field = newobj   // (c)

It actually checks if marking is in progress first, then loads the 
previous value. More importantly, the the marking flag can be set only 
during a safepoint, so from that point of view, barriers are "atomic" 
with respect to safepoints, a thread won't enter a safepoint while in 
the barrier.

> This code doesn't look like in atomic operation from (a) to (b).
> In that case, when mutator more than 2 try to write *field at the
> same time, the reference that should record may leak out to satb
> mark queue.
> For example.
> 1. *field == obj0 address
> 2. t1(Thread1) try to write obj1 address to *field.
> 3. t2(Thread2) try to write obj2 address to *field.
> 4. t1 at (a): oldobj = obj0
> 5. t2 at (a): oldobj = obj0
> 6. t1 at (b): enqueue obj0 to satb mark queue
> 7. t2 at (b): enqueue obj0 to satb mark queue
> 8. t1 at (c): *field = obj1
> 9. t2 at (c): *field = obj2
> In this example, obj1 that should enqueue satb mark queue is leaked.

Yes, we're not interested in obj1 at all. We're only interested in the 
contents of the field that were there before the marking started.


> Is this intended behavior? Or, Is it my misunderstanding?
> Thanks.

More information about the hotspot-gc-dev mailing list