[jmm-dev] jdk9 APIs
Hans Boehm
boehm at acm.org
Tue Aug 25 00:01:25 UTC 2015
Some more comments:
I think the getAnd() operations also need to specify that the load part is
volatile, so that an earlier volatile store synchronizes with the call.
The "reordering"-based specifications are extremely problematic. They give
no hint that, for example, IRIW can produce non-SC results with LoadLoad or
Acquire fences. But I think that has to be allowed for anything other than
fullFence() to be useful.
Note that the use of "Relaxed" here is seriously weaker than in C & C++.
It doesn't promise cache-coherence. That's a sufficiently serious
difference that I'm not sure I would use the same word. For example, a
field that is only ever atomically incremented can appear to decrease,
where it can't in C or C++. Of course that term already has a long history
of not-very-consistent use in the hardware community, so maybe it's OK.
Is it intended to be possible to apply these methods to built-in types like
long? If so, does Relaxed provide word-tearing guarantees?
As you've probably gathered, I'm not volunteering to define semantics of
loadLoadFence() or storeStoreFence().
reachabilityFence:
"regardless of any prior actions of the program that might otherwise cause
the object to become unreachable" doesn't sound right to me. It really
revokes the compilers license to "misoptimize" the program normally given
by 12.6.1:
"Optimizing transformations of a program can be designed that reduce the
number of objects that are reachable to be less than those which would
naively be considered reachable."
The real guarantee seems to be that reachabilityFence(ref) happens before
ref is finalized or added to a java.lang.ref queue. Can we include that in
its definition?
This would normally mean that (1) either reachabilityFence(ref) or the next
safe point (or something in between) acts as a release operation for
compiler purposes, and (2) the next safe point synchronizes with any GC
that might reclaim ref. I can't think of a way to write a correct GC that
doesn't make (2) or some analogous condition true automatically. But I
think we need to be clear that (1) is expected.
Presumably it's too late to add an annotation? The simplest would probably
be an @FinalizationSensitive class annotation that causes the compiler to
insert a reachabilityFence at the end of the scope of every reference with
that static type or a subclass type. (Or after the current statement for
temporaries.)
ReachabilityFence() would help us for library code, but I doubt it's going
to get much use in user-written code. Especially the temporary case is
likely to be missed. You need to transform
nativeCall(foo.getFinalizableObj().nativePtr) to
T tmp = foo.getFinalizableObj();
nativeCall(tmp.nativePtr);
reachabilityFence(tmp);
Hans
On Mon, Aug 24, 2015 at 1:42 AM, Aleksey Shipilev <
aleksey.shipilev at oracle.com> wrote:
> On 08/21/2015 08:54 PM, Doug Lea wrote:
> > On 08/21/2015 09:54 AM, Aleksey Shipilev wrote:
> >>> T compareAndExchangeVolatile(Object owner, T expected, T val);
> >>> T compareAndExchangeAcquire(Object owner, T expected, T val);
> >>> T compareAndExchangeRelease(Object owner, T expected, T val);
> >>
> >> Um, I have a stupid question. What's the story with non-x86 processors
> >> here? Do we have any machines that do not have an explicit CAS, but only
> >> have LL/SC? Returning the failure witness does not seem doable with
> >> LL/SC-emulated CAS.
> >
> > With LL/SC, you loop until either compare-failure with the LL'ed value
> > or success of the SC. So either way there is a unique answer.
>
> Oh, right. I was under (false) impression that you do LL/SC without
> looping, but I guess that is not really viable for strong CAS emulation
> since SC may "spuriously" fail.
>
> Thanks,
> -Aleksey
>
>
>
More information about the jmm-dev
mailing list