RFR (M) 8195099: Concurrent safe-memory-reclamation mechanism

Robbin Ehn robbin.ehn at oracle.com
Wed Apr 11 11:38:19 UTC 2018


Hi,

On 04/11/2018 12:57 PM, David Holmes wrote:
> 
> Sorry no, I don't understand what this counter is doing at all. I feel I need to 
> see what is between the begin/end critical section for this to make any sense to 
> me. And to see what the writer actually does.

 From gtest:
Read side do:
   49       GlobalCounter::critical_section_begin(this);
   50       volatile TestData* test = OrderAccess::load_acquire(_test);
   51       long value = OrderAccess::load_acquire(&test->test_value);
   52       ASSERT_EQ(value, GOOD);
   53       GlobalCounter::critical_section_end(this);
Write side do:
  101         volatile TestData* free_tmp = test;
  102         tmp = new TestData();
  103         tmp->test_value = GOOD;
  104         OrderAccess::release_store(&test, tmp);
  105         GlobalCounter::write_synchronize();
  106         free_tmp->test_value = BAD;
  107         delete free_tmp;

If a reader is context switch between line 50 and 51, it will have a cached 
value of the pointer "_test", thus no one should free it.

Before freeing the writer calls write_synchronize which guarantees that no 
reader can see the old pointer and can then free it.

If the reader is context switch inside critical_section_begin this does not 
matter since the fence in critical_section_begin prohibits the load of test 
pointer from floating up. If write_synchronize is done before this reader gets 
back on CPU it will see the new value but have an counter of an old generation.
If it gets back on CPU before write_synchronize I will see the old pointer.

If we call the pointer values TEST_gen_1, TEST_gen_2, ...
test_pointer starts equal to TEST_gen_1 and generation starts at 1.

Writer: tmp_pointer = test_pointer
Writer: test_pointer = TEST_gen_2
Reader: load global counter (fetches 1)
Reader: context switched out
Writer: write_synchronized generation = 2, and do not see the reader.
Reader: store local counter to 1 // critical section begin
Reader: load test_pointer (TEST_gen_2) // This load will always happen *after* 
the store to local counter
Writer: free tmp_pointer (TEST_gen_1) // ABA safe

Writer: tmp_pointer = test_pointer
Writer: test_pointer = TEST_gen_3
Writer: write_synchronized generation = 3, and _sees_ on old reader => wait.
Reader: store local counter OFF // critical section end
Writer: write_synchronized now finishes.
Writer: free tmp_pointer (TEST_gen_2) // ABA safe

/Robbin

> 
> David
> -----


More information about the hotspot-dev mailing list