[foreign-memaccess] [Rev 01] RFR: Alternative scalable MemoryScope
Maurizio Cimadamore
mcimadamore at openjdk.java.net
Tue May 5 10:10:11 UTC 2020
On Tue, 5 May 2020 07:35:11 GMT, Peter Levart <plevart at openjdk.org> wrote:
>> src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryScope.java line 136:
>>
>>> 135: private static final class Root extends MemoryScope {
>>> 136: private final LongAdder acquires;
>>> 137: private final LongAdder releases;
>>
>> Did you consider collapsing into just one `LongAdder` using `increment` (for acquiring), `decrement` (for releasing),
>> and `sum` (checking a zero sum for closing)? Perhaps it was discussed already, i lost track of all the discussion.
>
> No, it was not discussed yet. I'm happy you brought it up. That would not work. LongAdder.sum() is not an atomic
> operation. Consider the following scenario:
> - precondition: adder.sum() == 0
> - thread A1 successfully acquires child segment: adder.sum() == 1
> - thread C calls close() on root segment
> * sets state = CLOSING
> * calls adder.sum() which starts summing LongAdder cells and just misses adder.increment() of thread A2...
> - thread A2 tries to acquire child segment and so it 1st does adder.increment()
> - thread A2 reads state == CLOSING and therefore undoes previous increment with adder.decrement() and fails, but...
> - thread C that just missed A2's adder.increment() does see A2's adder.decrement() because it is performed on a different
> LongAdder cell which C reads after it is incremented, so what C gets as a result of adder.sum() is 0, it completes
> closing the root segment by setting state = CLOSED and executing cleanup, but thread A1 still has access to the child
> segment and BOOM!!!
>
> Having two LongAdders (acquires, releases) and doing the sum() per-partes sequentially: 1st releases.sum(), then
> acquires.sum() we guarantee that we never miss an acquiring thread's acquires.increment() but see the thread's
> releases.increment(), so above scenario is not possible.
I agree with Peter that using a single long would misses update and you could see 'zero' when in reality something has
happened but `sum` didn't get the memo. The entire approach, as far as I understand, relies on subtle happens-before
relationship which arise precisely because of the use of the two counters (and the fact that one counter is always
updated before the other).
-------------
PR: https://git.openjdk.java.net/panama-foreign/pull/142
More information about the panama-dev
mailing list