RFR (M) 8195099: Concurrent safe-memory-reclamation mechanism
Robbin Ehn
robbin.ehn at oracle.com
Wed Apr 11 12:35:16 UTC 2018
On 04/11/2018 02:03 PM, David Holmes wrote:
> On 11/04/2018 9:38 PM, Robbin Ehn wrote:
>> 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:
>
> Thanks for that. Okay I have a better sense of how the access to the data
> completes the handshake.
>
Great!
> Does the naming/terminology come from some existing mechanism? I find it
> somewhat odd and not really descriptive of the operation..
There several of different versions but they follow the same naming scheme.
E.g. such as smr_begin, smr_end, synchronize
Thanks, Robbin
>
> Thanks,
> David
>
>> 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