From ajeffrey at mozilla.com Mon Apr 11 16:26:12 2016 From: ajeffrey at mozilla.com (Alan Jeffrey) Date: Mon, 11 Apr 2016 11:26:12 -0500 Subject: [jmm-dev] LICS 2016 paper "On Thin-Air Reads" Message-ID: Dear all, James Riely and I will have a paper at this year's Logic In Computer Science conference titled "On Thin Air Reads: Towards an Event Structures Model of Relaxed Memory". Some of the material was previously presented at the Cambridge workshop, but the formalization of thin-air is new. http://asaj.org/papers/lics16.pdf All comments welcome! Alan Jeffrey. From aleksey.shipilev at oracle.com Wed Apr 20 09:55:08 2016 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Wed, 20 Apr 2016 12:55:08 +0300 Subject: [jmm-dev] weakCompareAndSet memory semantics Message-ID: <571751FC.5010505@oracle.com> Hi, In VarHandles, and relevant intrinsics, we have: weakCompareAndSet (relaxed!) weakCompareAndSetAcquire weakCompareAndSetRelease Which means we miss the "volatile" form, or in other words, the sequentially consistent version. While this is consistent with the rest of java.util.concurrent, which does not advertise memory effects for weakCAS: "Additionally weakCompareAndSet does not provide ordering guarantees that are usually needed for synchronization control." https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html ...I see this deviates from C++11-ish compare_exchange_weak that defaults to memory_order_seq_cst. I think this deviation breaks replacing compareAndSet in busy loops with weakCompareAndSet, to benefit the platforms where CAS is emulated with LL/SC that can spuriously fail. void incr() { int v; do { v = ai.get(); } while (!compareAndSet(v, v + 1)); // loop inside for LL/SC } void incr() { int v; do { v = ai.get(); } while (!weakCompareAndSet(v, v + 1)); // single LL/SC } I wonder if that was the intended use for weakCAS in C++11, and if so, shouldn't we re-spec weakCAS in Java to have volatile/seq_cst memory effects? Thanks, -Aleksey From aph at redhat.com Wed Apr 20 10:03:47 2016 From: aph at redhat.com (Andrew Haley) Date: Wed, 20 Apr 2016 11:03:47 +0100 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <571751FC.5010505@oracle.com> References: <571751FC.5010505@oracle.com> Message-ID: <57175403.7060006@redhat.com> On 20/04/16 10:55, Aleksey Shipilev wrote: > I wonder if that was the intended use for weakCAS in C++11, and if so, > shouldn't we re-spec weakCAS in Java to have volatile/seq_cst memory > effects? Probably. Or, at least, we want a weakCompareAndSet which is sequentially consistent. As a general principle: we have an opportunity to make Java's operators consistent with those of C++, and we shouldn't mess that up. Andrew. From dl at cs.oswego.edu Wed Apr 20 11:56:06 2016 From: dl at cs.oswego.edu (Doug Lea) Date: Wed, 20 Apr 2016 07:56:06 -0400 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <57175403.7060006@redhat.com> References: <571751FC.5010505@oracle.com> <57175403.7060006@redhat.com> Message-ID: <57176E56.6000408@cs.oswego.edu> On 04/20/2016 06:03 AM, Andrew Haley wrote: > On 20/04/16 10:55, Aleksey Shipilev wrote: >> I wonder if that was the intended use for weakCAS in C++11, and if so, >> shouldn't we re-spec weakCAS in Java to have volatile/seq_cst memory >> effects? > > Probably. Or, at least, we want a weakCompareAndSet which is sequentially > consistent. As a general principle: we have an opportunity to make Java's > operators consistent with those of C++, and we shouldn't mess that up. > Yes. I'm not sure what happened to method weakCompareAndSetVolatile that was in early sketches but disappeared (probably my fault) without me or anyone else noticing. Aleksey and/or Paul: Can you add this? -Doug From aleksey.shipilev at oracle.com Wed Apr 20 12:58:41 2016 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Wed, 20 Apr 2016 15:58:41 +0300 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <57176E56.6000408@cs.oswego.edu> References: <571751FC.5010505@oracle.com> <57175403.7060006@redhat.com> <57176E56.6000408@cs.oswego.edu> Message-ID: <57177D01.6070106@oracle.com> On 04/20/2016 02:56 PM, Doug Lea wrote: > On 04/20/2016 06:03 AM, Andrew Haley wrote: >> On 20/04/16 10:55, Aleksey Shipilev wrote: >>> I wonder if that was the intended use for weakCAS in C++11, and if so, >>> shouldn't we re-spec weakCAS in Java to have volatile/seq_cst memory >>> effects? >> >> Probably. Or, at least, we want a weakCompareAndSet which is >> sequentially >> consistent. As a general principle: we have an opportunity to make >> Java's >> operators consistent with those of C++, and we shouldn't mess that up. >> > > Yes. I'm not sure what happened to method weakCompareAndSetVolatile > that was in early sketches but disappeared (probably my fault) without > me or anyone else noticing. Aleksey and/or Paul: Can you add this? Thanks, it's not too late to add. This raises the naming questions, which will be cast in stone in VarHandles public API: a) weakCompareAndSet (relaxed!) weakCompareAndSetAcquire weakCompareAndSetRelease weakCompareAndSetVolatile (This provides the symmetry against j.u.c, and does not require re-spec, just adding a new method) ...or b) weakCompareAndSet (volatile!) weakCompareAndSetAcquire weakCompareAndSetRelease weakCompareAndSetRelaxed/Plain (This provides the symmetry against default mem_ord in C++, and also new CompareAndExchange{epsilon, Acquire, Release}). Thanks, -Aleksey From dl at cs.oswego.edu Wed Apr 20 13:25:13 2016 From: dl at cs.oswego.edu (Doug Lea) Date: Wed, 20 Apr 2016 09:25:13 -0400 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <57177D01.6070106@oracle.com> References: <571751FC.5010505@oracle.com> <57175403.7060006@redhat.com> <57176E56.6000408@cs.oswego.edu> <57177D01.6070106@oracle.com> Message-ID: <57178339.9040100@cs.oswego.edu> On 04/20/2016 08:58 AM, Aleksey Shipilev wrote: > This raises the naming questions, which will be cast in stone in > VarHandles public API: > > a) > weakCompareAndSet (relaxed!) > weakCompareAndSetAcquire > weakCompareAndSetRelease > weakCompareAndSetVolatile > > (This provides the symmetry against j.u.c, and does not require re-spec, > just adding a new method) Let's do it this way. The only downside I can imagine is that some C++ programmer converting to Java using an an IDE with autocomplete might select it by mistake without reading the JavaDoc. -Doug > > ...or > > b) > > weakCompareAndSet (volatile!) > weakCompareAndSetAcquire > weakCompareAndSetRelease > weakCompareAndSetRelaxed/Plain > > (This provides the symmetry against default mem_ord in C++, and also new > CompareAndExchange{epsilon, Acquire, Release}). > > Thanks, > -Aleksey > > > > > > From paul.sandoz at oracle.com Wed Apr 20 13:27:55 2016 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 20 Apr 2016 15:27:55 +0200 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <57176E56.6000408@cs.oswego.edu> References: <571751FC.5010505@oracle.com> <57175403.7060006@redhat.com> <57176E56.6000408@cs.oswego.edu> Message-ID: <993E1BE3-2D36-4C24-9832-1995D7C35C54@oracle.com> > On 20 Apr 2016, at 13:56, Doug Lea
wrote: > > On 04/20/2016 06:03 AM, Andrew Haley wrote: >> On 20/04/16 10:55, Aleksey Shipilev wrote: >>> I wonder if that was the intended use for weakCAS in C++11, and if so, >>> shouldn't we re-spec weakCAS in Java to have volatile/seq_cst memory >>> effects? >> >> Probably. Or, at least, we want a weakCompareAndSet which is sequentially >> consistent. As a general principle: we have an opportunity to make Java's >> operators consistent with those of C++, and we shouldn't mess that up. >> > > Yes. I'm not sure what happened to method weakCompareAndSetVolatile > that was in early sketches but disappeared (probably my fault) without > me or anyone else noticing. Aleksey and/or Paul: Can you add this? > Yes. Aleksey and I propose: /* * Possibly atomically sets the value of a variable to the {@code newValue} * with the memory semantics of {@link #setVolatile} if the variable's * current value, referred to as the witness value, {@code ==} the * {@code expectedValue}, as accessed with the memory semantics of * {@link #getVolatile}. * *

This operation may fail spuriously (typically, due to memory * contention) even if the current value does match the expected value. ? */ public final native @MethodHandle.PolymorphicSignature @HotSpotIntrinsicCandidate boolean weakCompareAndSetVolatile(Object... args); We will follow up with notes on C++11 comparison later [1]. We have what might be reasonably considered a naming glitch. We have: - compareAndSet, with ?volatile" semantics - compareAndExchangeVolatile - the proposed weakCompareAndSetVolatile - and weakCompareAndSet, with ?plain? semantics. I suggest we assume by default CAS/CEA are all have ?volatile? semantics: - compareAndSet - compareAndExchange [2] - weakCompareAndSet [3] Then the existing weakCompareAndSet is renamed to: weakCompareAndSetPlain ? Paul. [1] https://bugs.openjdk.java.net/browse/JDK-8153875 [2] https://bugs.openjdk.java.net/browse/JDK-8154737 [3] https://bugs.openjdk.java.net/browse/JDK-8154755 From paul.sandoz at oracle.com Wed Apr 20 13:32:56 2016 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Wed, 20 Apr 2016 15:32:56 +0200 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <57178339.9040100@cs.oswego.edu> References: <571751FC.5010505@oracle.com> <57175403.7060006@redhat.com> <57176E56.6000408@cs.oswego.edu> <57177D01.6070106@oracle.com> <57178339.9040100@cs.oswego.edu> Message-ID: > On 20 Apr 2016, at 15:25, Doug Lea

wrote: > > On 04/20/2016 08:58 AM, Aleksey Shipilev wrote: > >> This raises the naming questions, which will be cast in stone in >> VarHandles public API: >> >> a) >> weakCompareAndSet (relaxed!) >> weakCompareAndSetAcquire >> weakCompareAndSetRelease >> weakCompareAndSetVolatile >> >> (This provides the symmetry against j.u.c, and does not require re-spec, >> just adding a new method) > > Let's do it this way. Ok. I?ll stick to the current naming convention. I was proposing b) in a previous email (before i read this email). Paul. > The only downside I can imagine is that some > C++ programmer converting to Java using an an IDE with autocomplete > might select it by mistake without reading the JavaDoc. > From jsampson at guidewire.com Wed Apr 20 19:59:38 2016 From: jsampson at guidewire.com (Justin Sampson) Date: Wed, 20 Apr 2016 19:59:38 +0000 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: References: <571751FC.5010505@oracle.com> <57175403.7060006@redhat.com> <57176E56.6000408@cs.oswego.edu> <57177D01.6070106@oracle.com> <57178339.9040100@cs.oswego.edu> Message-ID: Howdy, Some existing JDK methods named "compareAndSet" already allow spurious failure while providing volatile semantics on success, which has always struck me as entirely fine and desirable. Is documentation of those cases being worked into this wave of enhancements? See the thread "Varieties of CAS semantics (another doc fix request)" here: http://cs.oswego.edu/pipermail/concurrency-interest/2015-January/thread.html#13613 Cheers, Justin P.S. The existing compareAndSet methods I'm referring to are the ones on AtomicStampedReference and AtomicMarkableReference. From david.holmes at oracle.com Wed Apr 20 22:44:18 2016 From: david.holmes at oracle.com (David Holmes) Date: Thu, 21 Apr 2016 08:44:18 +1000 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <571751FC.5010505@oracle.com> References: <571751FC.5010505@oracle.com> Message-ID: <57180642.3050505@oracle.com> On 20/04/2016 7:55 PM, Aleksey Shipilev wrote: > Hi, > > In VarHandles, and relevant intrinsics, we have: > weakCompareAndSet (relaxed!) > weakCompareAndSetAcquire > weakCompareAndSetRelease > > Which means we miss the "volatile" form, or in other words, the > sequentially consistent version. While this is consistent with the rest > of java.util.concurrent, which does not advertise memory effects for > weakCAS: "Additionally weakCompareAndSet does not provide ordering > guarantees that are usually needed for synchronization control." > > https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html > > ...I see this deviates from C++11-ish compare_exchange_weak that > defaults to memory_order_seq_cst. I think this deviation breaks > replacing compareAndSet in busy loops with weakCompareAndSet, to benefit > the platforms where CAS is emulated with LL/SC that can spuriously fail. Side question: why would you replace compareAndSet with weakCompareAndSet when that would expose those ll/sc spurious failures? David ----- > void incr() { > int v; > do { > v = ai.get(); > } while (!compareAndSet(v, v + 1)); // loop inside for LL/SC > } > > void incr() { > int v; > do { > v = ai.get(); > } while (!weakCompareAndSet(v, v + 1)); // single LL/SC > } > > I wonder if that was the intended use for weakCAS in C++11, and if so, > shouldn't we re-spec weakCAS in Java to have volatile/seq_cst memory > effects? > > Thanks, > -Aleksey > From jsampson at guidewire.com Wed Apr 20 22:59:28 2016 From: jsampson at guidewire.com (Justin Sampson) Date: Wed, 20 Apr 2016 22:59:28 +0000 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <57180642.3050505@oracle.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> Message-ID: David Holmes wrote: > Side question: why would you replace compareAndSet with > weakCompareAndSet when that would expose those ll/sc spurious > failures? The spurious failures are irrelevant because the whole thing is wrapped in a retry loop anyway. Cheers, Justin From david.holmes at oracle.com Wed Apr 20 23:10:05 2016 From: david.holmes at oracle.com (David Holmes) Date: Thu, 21 Apr 2016 09:10:05 +1000 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> Message-ID: <57180C4D.9070707@oracle.com> On 21/04/2016 8:59 AM, Justin Sampson wrote: > David Holmes wrote: > >> Side question: why would you replace compareAndSet with >> weakCompareAndSet when that would expose those ll/sc spurious >> failures? > > The spurious failures are irrelevant because the whole thing is > wrapped in a retry loop anyway. And in the compareAndSet the spurious failures never escape because it also has a retry loop. So my question stands: why would you switch to weakCompareAndSet in "busy loops" and how would this be a benefit? Cheers, David > Cheers, > Justin > From aph at redhat.com Thu Apr 21 07:52:44 2016 From: aph at redhat.com (Andrew Haley) Date: Thu, 21 Apr 2016 08:52:44 +0100 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <57180C4D.9070707@oracle.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> Message-ID: <571886CC.5030209@redhat.com> On 21/04/16 00:10, David Holmes wrote: > On 21/04/2016 8:59 AM, Justin Sampson wrote: >> David Holmes wrote: >> >>> Side question: why would you replace compareAndSet with >>> weakCompareAndSet when that would expose those ll/sc spurious >>> failures? >> >> The spurious failures are irrelevant because the whole thing is >> wrapped in a retry loop anyway. > > And in the compareAndSet the spurious failures never escape because it > also has a retry loop. So my question stands: why would you switch to > weakCompareAndSet in "busy loops" and how would this be a benefit? Say you're incrementing a heavily-contended counter. There's no point spinning in a loop if the store fails or if there is a spurious failure. You want to do this: loop: ldax x0, [addr] add x0, x0, #1 stlx status, x0, [addr] cbnz status, loop You can simulate this with weakCompareAndSet. Andrew. From aleksey.shipilev at oracle.com Thu Apr 21 08:32:03 2016 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Thu, 21 Apr 2016 11:32:03 +0300 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <571886CC.5030209@redhat.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> Message-ID: <57189003.3030007@oracle.com> On 21.04.2016 10:52, Andrew Haley wrote: > On 21/04/16 00:10, David Holmes wrote: >> On 21/04/2016 8:59 AM, Justin Sampson wrote: >>> David Holmes wrote: >>> >>>> Side question: why would you replace compareAndSet with >>>> weakCompareAndSet when that would expose those ll/sc spurious >>>> failures? >>> >>> The spurious failures are irrelevant because the whole thing is >>> wrapped in a retry loop anyway. >> >> And in the compareAndSet the spurious failures never escape because it >> also has a retry loop. So my question stands: why would you switch to >> weakCompareAndSet in "busy loops" and how would this be a benefit? > > Say you're incrementing a heavily-contended counter. There's no point > spinning in a loop if the store fails or if there is a spurious failure. > > You want to do this: > > loop: > ldax x0, [addr] > add x0, x0, #1 > stlx status, x0, [addr] > cbnz status, loop > > You can simulate this with weakCompareAndSet. Yes, that seems to be the similar thing I was saying in my original note: void incr() { int v; do { v = ai.get(); } while (!weakCompareAndSet(v, v + 1)); // single LL/SC } IOW, there is no point in spinning inside CAS method to emulate strong CAS with LL/SC, when you can just retry in the upper loop -- and reap the benefits from it, because you will have an opportunity to come up with an *new* value to set, rather than busting the doors trying to put in the stale value. I think this is the reason why C++11 says: "The weak forms (1-2) of the functions are allowed to fail spuriously, that is, act as if *this != expected even if they are equal. When a compare-and-exchange is in a loop, the weak version will yield better performance on some platforms." http://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange Thanks, -Aleksey From aph at redhat.com Thu Apr 21 08:36:21 2016 From: aph at redhat.com (Andrew Haley) Date: Thu, 21 Apr 2016 09:36:21 +0100 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <57189003.3030007@oracle.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> Message-ID: <57189105.30903@redhat.com> On 21/04/16 09:32, Aleksey Shipilev wrote: > IOW, there is no point in spinning inside CAS method to emulate strong > CAS with LL/SC, when you can just retry in the upper loop -- and reap > the benefits from it, because you will have an opportunity to come up > with an *new* value to set, rather than busting the doors trying to put > in the stale value. Exactly so. That is the best explanation I have seen. We should save it somewhere. Or even add it to our docs! Andrew. From david.holmes at oracle.com Thu Apr 21 12:10:48 2016 From: david.holmes at oracle.com (David Holmes) Date: Thu, 21 Apr 2016 22:10:48 +1000 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <57189003.3030007@oracle.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> Message-ID: <5718C348.6090809@oracle.com> On 21/04/2016 6:32 PM, Aleksey Shipilev wrote: > On 21.04.2016 10:52, Andrew Haley wrote: >> On 21/04/16 00:10, David Holmes wrote: >>> On 21/04/2016 8:59 AM, Justin Sampson wrote: >>>> David Holmes wrote: >>>> >>>>> Side question: why would you replace compareAndSet with >>>>> weakCompareAndSet when that would expose those ll/sc spurious >>>>> failures? >>>> >>>> The spurious failures are irrelevant because the whole thing is >>>> wrapped in a retry loop anyway. >>> >>> And in the compareAndSet the spurious failures never escape because it >>> also has a retry loop. So my question stands: why would you switch to >>> weakCompareAndSet in "busy loops" and how would this be a benefit? >> >> Say you're incrementing a heavily-contended counter. There's no point >> spinning in a loop if the store fails or if there is a spurious failure. >> >> You want to do this: >> >> loop: >> ldax x0, [addr] >> add x0, x0, #1 >> stlx status, x0, [addr] >> cbnz status, loop >> >> You can simulate this with weakCompareAndSet. > > Yes, that seems to be the similar thing I was saying in my original note: > > void incr() { > int v; > do { > v = ai.get(); > } while (!weakCompareAndSet(v, v + 1)); // single LL/SC > } > > IOW, there is no point in spinning inside CAS method to emulate strong > CAS with LL/SC, when you can just retry in the upper loop -- and reap > the benefits from it, because you will have an opportunity to come up > with an *new* value to set, rather than busting the doors trying to put > in the stale value. How are you busting the doors if you get a _spurious_ failure? It means something unrelated directly to your CAS (so your value is not stale!) happened. The spurious failures from ll/sc are a result of implementation constraints so it has never made sense to me to have that exposed at a higher level. On the contrary many CAS-based algorithms expect that failure indicates some other thread made progress. David ----- > I think this is the reason why C++11 says: "The weak forms (1-2) of the > functions are allowed to fail spuriously, that is, act as if *this != > expected even if they are equal. When a compare-and-exchange is in a > loop, the weak version will yield better performance on some platforms." > http://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange > > Thanks, > -Aleksey > From aph at redhat.com Thu Apr 21 12:51:46 2016 From: aph at redhat.com (Andrew Haley) Date: Thu, 21 Apr 2016 13:51:46 +0100 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <5718C348.6090809@oracle.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> Message-ID: <5718CCE2.5060601@redhat.com> On 04/21/2016 01:10 PM, David Holmes wrote: > How are you busting the doors if you get a _spurious_ failure? It means > something unrelated directly to your CAS (so your value is not stale!) > happened. Although the architecture doesn't define it, the usual reasons that an exclusive store fails are the value is contended or your thread was interrupted. In either case your value may be stale, in which case you want to read it again: there's no point retrying the CAS in order to find out which it was. > The spurious failures from ll/sc are a result of implementation > constraints so it has never made sense to me to have that exposed at > a higher level. On the contrary many CAS-based algorithms expect > that failure indicates some other thread made progress. Sure, and those algorithms can spin. The point about ll/sc is that you have a choice. CAS is much more restrictive than ll/sc. Andrew. From paul.sandoz at oracle.com Thu Apr 21 16:21:51 2016 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Thu, 21 Apr 2016 18:21:51 +0200 Subject: [jmm-dev] RFR 8154755: Add a VarHandle weakCompareAndSet with volatile semantics Message-ID: <07EE4695-9AF3-4F50-ACAE-831BD508B657@oracle.com> Hi, Please review: http://cr.openjdk.java.net/~psandoz/jdk9/JDK-8154755-weak-cas-volatile/webrev/ This webrev adds a new VarHandle access mode method, weakCompareAndSetVolatile [*]. (I also fixed some doc errors regarding AccessMode enum names that i forgot to update in a previous issue). Aleksey noticed a discrepancy with the current set of weak CAS methods when comparing with C++ atomics. On hardware that supports LL/SC (e.g. ARM) the weak volatile variant may be more performant than the strong volatile variant (compareAndSet) when the CAS is performed in a loop. See the thread on the jmm-dev list for more details: http://mail.openjdk.java.net/pipermail/jmm-dev/2016-April/000239.html Implementations currently defer to the strong volatile Unsafe CAS. We will follow up with changes to Unsafe, hotspot, and updating the VH implementations as separate issues. Thanks, Paul. [*] /** * Possibly atomically sets the value of a variable to the {@code newValue} * with the memory semantics of {@link #setVolatile} if the variable's * current value, referred to as the witness value, {@code ==} the * {@code expectedValue}, as accessed with the memory semantics of * {@link #getVolatile}. * *

This operation may fail spuriously (typically, due to memory * contention) even if the witness value does match the expected value. * ... */ public final native @MethodHandle.PolymorphicSignature @HotSpotIntrinsicCandidate boolean weakCompareAndSetVolatile(Object... args); Paul. From david.holmes at oracle.com Thu Apr 21 23:38:05 2016 From: david.holmes at oracle.com (David Holmes) Date: Fri, 22 Apr 2016 09:38:05 +1000 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <5718CCE2.5060601@redhat.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> Message-ID: <5719645D.5030108@oracle.com> On 21/04/2016 10:51 PM, Andrew Haley wrote: > On 04/21/2016 01:10 PM, David Holmes wrote: >> How are you busting the doors if you get a _spurious_ failure? It means >> something unrelated directly to your CAS (so your value is not stale!) >> happened. > > Although the architecture doesn't define it, the usual reasons that an > exclusive store fails are the value is contended or your thread was > interrupted. In either case your value may be stale, in which case > you want to read it again: there's no point retrying the CAS in order > to find out which it was. Not aware of the "interrupted" case though I don't see how that would make the value stale. More general case is that there was an unrelated store into the same "region" of memory - again this doesn't make your value stale. Now obviously if there is high contention on the variable you are cas'ing then your value might be stale by the time you re-loop for the spurious failure, but that is a different scenario - and if contention is that high you are going to have issues regardless. David ----- >> The spurious failures from ll/sc are a result of implementation >> constraints so it has never made sense to me to have that exposed at >> a higher level. On the contrary many CAS-based algorithms expect >> that failure indicates some other thread made progress. > > Sure, and those algorithms can spin. The point about ll/sc is that > you have a choice. CAS is much more restrictive than ll/sc. > > Andrew. > From fivosz at gmail.com Fri Apr 22 01:03:17 2016 From: fivosz at gmail.com (Foivos S. Zakkak) Date: Fri, 22 Apr 2016 04:03:17 +0300 Subject: [jmm-dev] JDMM: a java memory model for non-cache-coherent memory architectures Message-ID: Dear all, I am a PhD student at the University of Crete and ICS-FORTH, and I am studying the implementation of Java on non-cache-coherent architectures. In ISMM '14, me and Polyvios Pratikakis presented "JDMM: a java memory model for non-cache-coherent memory architectures" a paper that I believe some of you might find of interest. The paper is available for download from ISMM's table of contents: http://ismm2014.cs.tufts.edu/toc.html I would be glad to discuss with anyone interested in our work more details, and we would appreciate any feedback. Kind regards, Foivos Zakkak -- Foivos S. Zakkak PhD Candidate Computer Science Department University of Crete PGP: 7B40 69D9 29BA AE91 C0B3 220A 0846 BFD1 03F0 4EA1 From aph at redhat.com Fri Apr 22 08:38:55 2016 From: aph at redhat.com (Andrew Haley) Date: Fri, 22 Apr 2016 09:38:55 +0100 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <5719645D.5030108@oracle.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> Message-ID: <5719E31F.9000109@redhat.com> On 22/04/16 00:38, David Holmes wrote: > On 21/04/2016 10:51 PM, Andrew Haley wrote: >> On 04/21/2016 01:10 PM, David Holmes wrote: >>> How are you busting the doors if you get a _spurious_ failure? It means >>> something unrelated directly to your CAS (so your value is not stale!) >>> happened. >> >> Although the architecture doesn't define it, the usual reasons that an >> exclusive store fails are the value is contended or your thread was >> interrupted. In either case your value may be stale, in which case >> you want to read it again: there's no point retrying the CAS in order >> to find out which it was. > > Not aware of the "interrupted" case though I don't see how that would > make the value stale. It makes the value old; the value is therefore more likely to be stale. > More general case is that there was an unrelated store into the same > "region" of memory - again this doesn't make your value stale. OK, that's another possibility. But a store exclusive failure caused by false sharing involves a delay, so the value is older, and again more likely to be stale. Also, I am assuming that anyone with enough expertise to use a weak CAS also has enough sense to try to prevent false sharing. > Now obviously if there is high contention on the variable you are > cas'ing then your value might be stale by the time you re-loop for > the spurious failure, but that is a different scenario - and if > contention is that high you are going to have issues regardless. In what sense is it a different scenario? If contention is low then it really doesn't much matter what you do: the CAS will usually sail straight through anyway. Andrew. From david.holmes at oracle.com Fri Apr 22 11:32:21 2016 From: david.holmes at oracle.com (David Holmes) Date: Fri, 22 Apr 2016 21:32:21 +1000 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <5719E31F.9000109@redhat.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> Message-ID: <571A0BC5.9020702@oracle.com> On 22/04/2016 6:38 PM, Andrew Haley wrote: > On 22/04/16 00:38, David Holmes wrote: >> On 21/04/2016 10:51 PM, Andrew Haley wrote: >>> On 04/21/2016 01:10 PM, David Holmes wrote: >>>> How are you busting the doors if you get a _spurious_ failure? It means >>>> something unrelated directly to your CAS (so your value is not stale!) >>>> happened. >>> >>> Although the architecture doesn't define it, the usual reasons that an >>> exclusive store fails are the value is contended or your thread was >>> interrupted. In either case your value may be stale, in which case >>> you want to read it again: there's no point retrying the CAS in order >>> to find out which it was. >> >> Not aware of the "interrupted" case though I don't see how that would >> make the value stale. > > It makes the value old; the value is therefore more likely to be stale. > >> More general case is that there was an unrelated store into the same >> "region" of memory - again this doesn't make your value stale. > > OK, that's another possibility. But a store exclusive failure caused > by false sharing involves a delay, so the value is older, and again > more likely to be stale. Also, I am assuming that anyone with enough > expertise to use a weak CAS also has enough sense to try to prevent > false sharing. > >> Now obviously if there is high contention on the variable you are >> cas'ing then your value might be stale by the time you re-loop for >> the spurious failure, but that is a different scenario - and if >> contention is that high you are going to have issues regardless. > > In what sense is it a different scenario? If contention is low then > it really doesn't much matter what you do: the CAS will usually sail > straight through anyway. I consider it a different scenario because it requires high contention. If you have low contention (CAS ideal case) the spurious failures are unlikely to make your data stale so jumping back out to the outer loop to re-fetch doesn't gain anything - potentially the opposite! Obviously this all depends on the exact circumstances - but that is why I question these blanket statements about weakCAS performing better on ll/sc systems. Given we're dealing with WORA Java code this may push people towards always using weakCAS just in case they run on a ll/sc system. Cheers, David > Andrew. > From aph at redhat.com Fri Apr 22 12:03:37 2016 From: aph at redhat.com (Andrew Haley) Date: Fri, 22 Apr 2016 13:03:37 +0100 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <571A0BC5.9020702@oracle.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> Message-ID: <571A1319.6050908@redhat.com> On 04/22/2016 12:32 PM, David Holmes wrote: > I consider it a different scenario because it requires high contention. > If you have low contention (CAS ideal case) the spurious failures are > unlikely to make your data stale so jumping back out to the outer loop > to re-fetch doesn't gain anything - potentially the opposite! Potentially? Maybe that would be true if spurious store exclusive failures were common, but they aren't. > Obviously this all depends on the exact circumstances - but that is why > I question these blanket statements about weakCAS performing better on > ll/sc systems. Given we're dealing with WORA Java code this may push > people towards always using weakCAS just in case they run on a ll/sc system. I just did 10^9 uncontended ldx/stx on my system here. Guess how many spurious failures there were? Zero. This is a tool for people who know what they're doing. Andrew. From david.holmes at oracle.com Fri Apr 22 12:45:43 2016 From: david.holmes at oracle.com (David Holmes) Date: Fri, 22 Apr 2016 22:45:43 +1000 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <571A1319.6050908@redhat.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> <571A1319.6050908@redhat.com> Message-ID: <571A1CF7.9040007@oracle.com> On 22/04/2016 10:03 PM, Andrew Haley wrote: > On 04/22/2016 12:32 PM, David Holmes wrote: >> I consider it a different scenario because it requires high contention. >> If you have low contention (CAS ideal case) the spurious failures are >> unlikely to make your data stale so jumping back out to the outer loop >> to re-fetch doesn't gain anything - potentially the opposite! > > Potentially? Maybe that would be true if spurious store exclusive > failures were common, but they aren't. If they aren't common you neither gain nor lose - so no motivation to use weakCAS. >> Obviously this all depends on the exact circumstances - but that is why >> I question these blanket statements about weakCAS performing better on >> ll/sc systems. Given we're dealing with WORA Java code this may push >> people towards always using weakCAS just in case they run on a ll/sc system. > > I just did 10^9 uncontended ldx/stx on my system here. Guess how many > spurious failures there were? Zero. This is a tool for people who > know what they're doing. I don't get your point. You could also write code that gets many spurious failures. We are saying "use weakCAS on ll/sc because it will be better if there are spurious failures". But now you are saying you won't get spurious failures anyway. So why even bother with weakCAS? David > Andrew. > From david.lloyd at redhat.com Fri Apr 22 13:52:09 2016 From: david.lloyd at redhat.com (David M. Lloyd) Date: Fri, 22 Apr 2016 08:52:09 -0500 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <571A1CF7.9040007@oracle.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> <571A1319.6050908@redhat.com> <571A1CF7.9040007@oracle.com> Message-ID: <571A2C89.8030209@redhat.com> On 04/22/2016 07:45 AM, David Holmes wrote: > On 22/04/2016 10:03 PM, Andrew Haley wrote: >> On 04/22/2016 12:32 PM, David Holmes wrote: >>> I consider it a different scenario because it requires high contention. >>> If you have low contention (CAS ideal case) the spurious failures are >>> unlikely to make your data stale so jumping back out to the outer loop >>> to re-fetch doesn't gain anything - potentially the opposite! >> >> Potentially? Maybe that would be true if spurious store exclusive >> failures were common, but they aren't. > > If they aren't common you neither gain nor lose - so no motivation to > use weakCAS. > >>> Obviously this all depends on the exact circumstances - but that is why >>> I question these blanket statements about weakCAS performing better on >>> ll/sc systems. Given we're dealing with WORA Java code this may push >>> people towards always using weakCAS just in case they run on a ll/sc >>> system. >> >> I just did 10^9 uncontended ldx/stx on my system here. Guess how many >> spurious failures there were? Zero. This is a tool for people who >> know what they're doing. > > I don't get your point. You could also write code that gets many > spurious failures. > > We are saying "use weakCAS on ll/sc because it will be better if there > are spurious failures". > > But now you are saying you won't get spurious failures anyway. > > So why even bother with weakCAS? I think it boils down to this: it's likely to be slightly faster in some situations. If it's not there, someone is going to ask for it, because they will want that slight bump, and it's in both C++ and C. It seems trivial to implement. So why *not* have it? -- - DML From aph at redhat.com Fri Apr 22 15:22:09 2016 From: aph at redhat.com (Andrew Haley) Date: Fri, 22 Apr 2016 16:22:09 +0100 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <571A1CF7.9040007@oracle.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> <571A1319.6050908@redhat.com> <571A1CF7.9040007@oracle.com> Message-ID: <571A41A1.2000209@redhat.com> On 04/22/2016 01:45 PM, David Holmes wrote: > On 22/04/2016 10:03 PM, Andrew Haley wrote: >> On 04/22/2016 12:32 PM, David Holmes wrote: >>> I consider it a different scenario because it requires high contention. >>> If you have low contention (CAS ideal case) the spurious failures are >>> unlikely to make your data stale so jumping back out to the outer loop >>> to re-fetch doesn't gain anything - potentially the opposite! >> >> Potentially? Maybe that would be true if spurious store exclusive >> failures were common, but they aren't. > > If they aren't common you neither gain nor lose - so no motivation to > use weakCAS. No, that is not right. See below. >>> Obviously this all depends on the exact circumstances - but that is why >>> I question these blanket statements about weakCAS performing better on >>> ll/sc systems. Given we're dealing with WORA Java code this may push >>> people towards always using weakCAS just in case they run on a ll/sc system. >> >> I just did 10^9 uncontended ldx/stx on my system here. Guess how many >> spurious failures there were? Zero. This is a tool for people who >> know what they're doing. > > I don't get your point. You could also write code that gets many > spurious failures. Only by doing something really stupid like false sharing. > We are saying "use weakCAS on ll/sc because it will be better if there > are spurious failures". That's not what it's about at all. It's about not retrying if the store exclusive fails. Except in the pathological case of false sharing, store exclusive failures probably aren't spurious. It's just that the caller gets to decide what to do if the store fails. Andrew. From aph at redhat.com Fri Apr 22 15:24:48 2016 From: aph at redhat.com (Andrew Haley) Date: Fri, 22 Apr 2016 16:24:48 +0100 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <571A2C89.8030209@redhat.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> <571A1319.6050908@redhat.com> <571A1CF7.9040007@oracle.com> <571A2C89.8030209@redhat.com> Message-ID: <571A4240.40407@redhat.com> On 04/22/2016 02:52 PM, David M. Lloyd wrote: > I think it boils down to this: it's likely to be slightly faster in some > situations. If it's not there, someone is going to ask for it, because > they will want that slight bump, and it's in both C++ and C. It seems > trivial to implement. So why *not* have it? There's also the case where you have a highly-contended counter -- think profiling -- and you want to increment it, you can't tolerate much of a delay. It's a disaster if that counter goes backwards but failing to increment it at a time of high contention is not so bad. So you try it once and continue. Andrew. From paulmck at linux.vnet.ibm.com Fri Apr 22 17:17:26 2016 From: paulmck at linux.vnet.ibm.com (Paul E. McKenney) Date: Fri, 22 Apr 2016 10:17:26 -0700 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <571A4240.40407@redhat.com> References: <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> <571A1319.6050908@redhat.com> <571A1CF7.9040007@oracle.com> <571A2C89.8030209@redhat.com> <571A4240.40407@redhat.com> Message-ID: <20160422171726.GG3756@linux.vnet.ibm.com> On Fri, Apr 22, 2016 at 04:24:48PM +0100, Andrew Haley wrote: > On 04/22/2016 02:52 PM, David M. Lloyd wrote: > > I think it boils down to this: it's likely to be slightly faster in some > > situations. If it's not there, someone is going to ask for it, because > > they will want that slight bump, and it's in both C++ and C. It seems > > trivial to implement. So why *not* have it? > > There's also the case where you have a highly-contended counter -- > think profiling -- and you want to increment it, you can't tolerate > much of a delay. It's a disaster if that counter goes backwards but > failing to increment it at a time of high contention is not so bad. > So you try it once and continue. Agreed. For example, you might keep a local counter, so that if the attempt to increment the global counter does not immediately succeed (for whatever reason), you increment the local counter. The next time around, you attempt to add the local counter to the global one. In this case, it is not helpful to retry a failed store-conditional, even if the failure was spurious. Thanx, Paul From david.holmes at oracle.com Fri Apr 22 22:28:44 2016 From: david.holmes at oracle.com (David Holmes) Date: Sat, 23 Apr 2016 08:28:44 +1000 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <571A4240.40407@redhat.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> <571A1319.6050908@redhat.com> <571A1CF7.9040007@oracle.com> <571A2C89.8030209@redhat.com> <571A4240.40407@redhat.com> Message-ID: <571AA59C.5020705@oracle.com> On 23/04/2016 1:24 AM, Andrew Haley wrote: > On 04/22/2016 02:52 PM, David M. Lloyd wrote: >> I think it boils down to this: it's likely to be slightly faster in some >> situations. If it's not there, someone is going to ask for it, because >> they will want that slight bump, and it's in both C++ and C. It seems >> trivial to implement. So why *not* have it? > > There's also the case where you have a highly-contended counter -- > think profiling -- and you want to increment it, you can't tolerate > much of a delay. It's a disaster if that counter goes backwards but > failing to increment it at a time of high contention is not so bad. > So you try it once and continue. Agreed - perfectly valid usecase for weakCAS, and weakCAS has a benefit over CAS. But that is not the inner-loop re-fetch versus outer-loop re-fetch that I was questioning from Aleksey's original email. But you are right that we don't say anything about this in the docs so not a concern. Cheers, David > Andrew. > From aleksey.shipilev at oracle.com Sat Apr 23 07:31:42 2016 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Sat, 23 Apr 2016 10:31:42 +0300 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <571AA59C.5020705@oracle.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> <571A1319.6050908@redhat.com> <571A1CF7.9040007@oracle.com> <571A2C89.8030209@redhat.com> <571A4240.40407@redhat.com> <571AA59C.5020705@oracle.com> Message-ID: <571B24DE.9050806@oracle.com> On 23.04.2016 01:28, David Holmes wrote: > Agreed - perfectly valid usecase for weakCAS, and weakCAS has a benefit > over CAS. But that is not the inner-loop re-fetch versus outer-loop > re-fetch that I was questioning from Aleksey's original email. So, it seems like you are questioning the remarks in C++11 standard, 29.6.5/25: "Remark: A weak compare-and-exchange operation may fail spuriously. That is, even when the contents of memory referred to by expected and object are equal, it may return false and store back to expected the same memory contents that were originally there. [ Note: This spurious failure enables implementation of compare-and-exchange on a broader class of machines, e.g., load-locked store-conditional machines. A consequence of spurious failure is that nearly all uses of weak compare- and-exchange will be in a loop. When a compare-and-exchange is in a loop, the weak version will yield better performance on some platforms. When a weak compare-and-exchange would require a loop and a strong one would not, the strong one is preferable. ? end note ]" Or, in more humane form: https://herbsutter.com/2012/08/31/reader-qa-how-to-write-a-cas-loop-using-stdatomics/ Under heavy contention (which *is* the use case, whether you want it or not), the CAS loop performance heavily depends on the width of the "collision window" for RMW operation. The wider the gap in-between R-M-W operations there, then more chances to fail the impending CAS. This is directly measurable even on modern heavily-pipelined x86: https://bugs.openjdk.java.net/browse/JDK-8141640 ...and looped emulation of strong CAS with LL/SC sets you in the similar position, where the excess work within the LL/SC -> CAS emulation widens the collision window. It is cheaper to retry in the main loop even on spurious failure, because it shortens the collision window. (This is the third way I can explain this issue.) Thanks, -Aleksey From martinrb at google.com Sun Apr 24 22:40:34 2016 From: martinrb at google.com (Martin Buchholz) Date: Sun, 24 Apr 2016 15:40:34 -0700 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <571B24DE.9050806@oracle.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> <571A1319.6050908@redhat.com> <571A1CF7.9040007@oracle.com> <571A2C89.8030209@redhat.com> <571A4240.40407@redhat.com> <571AA59C.5020705@oracle.com> <571B24DE.9050806@oracle.com> Message-ID: It's time for me to understand this. Perhaps by explaining it to others in public? On a LL/SC platform with spurious failures, strong cas has to be implemented in a loop boolean strong_cas(address, expect, update) { for (;;) { if (load_linked(address) != expect) return false; if (store_conditional(address, update)) return true; } } while weak cas can do the straightforward boolean weak_cas(address, expect, update) { return load_linked(address) == expect && store_conditional(address, update); } If the store_conditional in strong_cas fails, it's probably because of true contention and not a spurious failure, so the extra load_linked and compare on retry is very likely wasted effort. Especially because, unlike C++, we don't return the value we read to the caller, so they will probably uselessly re-read. Hotspot could optimize away the useless read, but I would be surprised if it does. So we should rewrite every cas loop to use weak cas! Except, to muddy the waters ... There's two kinds of weakness - spurious failure, and relaxed memory order. The "weak cas" methods in Unsafe.java have no documentation, so we don't know what kind of weakness! The old public methods in j.u.c.atomic have documentation, but they are weak in two different ways! """May fail spuriously and does not provide ordering guarantees""" https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicLong.html#weakCompareAndSet-long-long- but we (probably) want a variant that "may fail spuriously" but still provides sequential consistency, for use in our CAS loops. From david.holmes at oracle.com Mon Apr 25 01:35:23 2016 From: david.holmes at oracle.com (David Holmes) Date: Mon, 25 Apr 2016 11:35:23 +1000 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: <571B24DE.9050806@oracle.com> References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> <571A1319.6050908@redhat.com> <571A1CF7.9040007@oracle.com> <571A2C89.8030209@redhat.com> <571A4240.40407@redhat.com> <571AA59C.5020705@oracle.com> <571B24DE.9050806@oracle.com> Message-ID: <571D745B.5030201@oracle.com> On 23/04/2016 5:31 PM, Aleksey Shipilev wrote: > On 23.04.2016 01:28, David Holmes wrote: >> Agreed - perfectly valid usecase for weakCAS, and weakCAS has a benefit >> over CAS. But that is not the inner-loop re-fetch versus outer-loop >> re-fetch that I was questioning from Aleksey's original email. > > So, it seems like you are questioning the remarks in C++11 standard, > 29.6.5/25: > > "Remark: A weak compare-and-exchange operation may fail spuriously. That > is, even when the contents of memory referred to by expected and object > are equal, it may return false and store back to expected the same > memory contents that were originally there. [ Note: This spurious > failure enables implementation of compare-and-exchange on a broader > class of machines, e.g., load-locked store-conditional machines. A > consequence of spurious failure is that nearly all uses of weak compare- > and-exchange will be in a loop. When a compare-and-exchange is in a > loop, the weak version will yield better performance on some platforms. > When a weak compare-and-exchange would require a loop and a strong one > would not, the strong one is preferable. ? end note ]" > > Or, in more humane form: > > https://herbsutter.com/2012/08/31/reader-qa-how-to-write-a-cas-loop-using-stdatomics/ > > Under heavy contention (which *is* the use case, whether you want it or > not), the CAS loop performance heavily depends on the width of the > "collision window" for RMW operation. The wider the gap in-between R-M-W > operations there, then more chances to fail the impending CAS. This is > directly measurable even on modern heavily-pipelined x86: > https://bugs.openjdk.java.net/browse/JDK-8141640 > > ...and looped emulation of strong CAS with LL/SC sets you in the similar > position, where the excess work within the LL/SC -> CAS emulation widens > the collision window. It is cheaper to retry in the main loop even on > spurious failure, because it shortens the collision window. (This is the > third way I can explain this issue.) Thanks for expanding on that. David > Thanks, > -Aleksey > From david.holmes at oracle.com Mon Apr 25 01:54:56 2016 From: david.holmes at oracle.com (David Holmes) Date: Mon, 25 Apr 2016 11:54:56 +1000 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> <571A1319.6050908@redhat.com> <571A1CF7.9040007@oracle.com> <571A2C89.8030209@redhat.com> <571A4240.40407@redhat.com> <571AA59C.5020705@oracle.com> <571B24DE.9050806@oracle.com> Message-ID: <571D78F0.6000208@oracle.com> On 25/04/2016 8:40 AM, Martin Buchholz wrote: > It's time for me to understand this. Perhaps by explaining it to > others in public? > > On a LL/SC platform with spurious failures, strong cas has to be > implemented in a loop > > boolean strong_cas(address, expect, update) { > for (;;) { > if (load_linked(address) != expect) return false; > if (store_conditional(address, update)) return true; > } > } > > while weak cas can do the straightforward > > boolean weak_cas(address, expect, update) { > return load_linked(address) == expect && store_conditional(address, update); > } > > If the store_conditional in strong_cas fails, it's probably because of > true contention and not a spurious failure, so the extra load_linked > and compare on retry is very likely wasted effort. Especially Thanks Martin. I have completely overlooked the fact that we have to re-load and re-compare to distinguish be a spurious and real failure. David ----- > because, unlike C++, we don't return the value we read to the caller, > so they will probably uselessly re-read. Hotspot could optimize away > the useless read, but I would be surprised if it does. > > So we should rewrite every cas loop to use weak cas! Except, to muddy > the waters ... > There's two kinds of weakness - spurious failure, and relaxed memory order. > The "weak cas" methods in Unsafe.java have no documentation, so we > don't know what kind of weakness! > The old public methods in j.u.c.atomic have documentation, but they > are weak in two different ways! > """May fail spuriously and does not provide ordering guarantees""" > https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicLong.html#weakCompareAndSet-long-long- > but we (probably) want a variant that "may fail spuriously" but still > provides sequential consistency, for use in our CAS loops. > From jsampson at guidewire.com Mon Apr 25 21:58:37 2016 From: jsampson at guidewire.com (Justin Sampson) Date: Mon, 25 Apr 2016 21:58:37 +0000 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> <571A1319.6050908@redhat.com> <571A1CF7.9040007@oracle.com> <571A2C89.8030209@redhat.com> <571A4240.40407@redhat.com> <571AA59C.5020705@oracle.com> <571B24DE.9050806@oracle.com> Message-ID: Martin Buchholz wrote: > The old public methods in j.u.c.atomic have documentation, but > they are weak in two different ways! > """May fail spuriously and does not provide ordering guarantees""" > but we (probably) want a variant that "may fail spuriously" but > still provides sequential consistency, for use in our CAS loops. At the risk of annoyance-through-repetition, I'll just mention one last time that there's precedent for exactly that behavior, in the actual-but-undocumented semantics of compareAndSet on both AtomicStampedReference and AtomicMarkableReference. (Furthermore, weakCompareAndSet simply delegates to compareAndSet on both of those classes.) The attemptStamp/attemptMark methods are also essentially CAS operations, and their potential for spurious failure is actually documented. Their docs don't mention volatile ordering, but they do provide it (on success). The compareAndSet methods also don't mention volatile ordering in their own docs, but they're covered by the package docs. Cheers, Justin From jsampson at guidewire.com Tue Apr 26 01:03:39 2016 From: jsampson at guidewire.com (Justin Sampson) Date: Tue, 26 Apr 2016 01:03:39 +0000 Subject: [jmm-dev] weakCompareAndSet memory semantics References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> <571A1319.6050908@redhat.com> <571A1CF7.9040007@oracle.com> <571A2C89.8030209@redhat.com> <571A4240.40407@redhat.com> <571AA59C.5020705@oracle.com> <571B24DE.9050806@oracle.com> Message-ID: Sorry, on further thought, perhaps the potential for spurious failure in AtomicStampedReference and AtomicMarkableReference isn't actually observable in practice. Their compareAndSet methods use the same algorithm as their attemptStamp and attemptMark methods, which are documented to allow spurious failure. But in all of those cases (attemptStamp, attemptMark, _and_ compareAndSet on both classes), while it's true that the final casPair call can fail even if the current ref and stamp/mark are equal to the expected values at that moment, that will only happen if there was an intervening write with a _different_ ref or stamp/mark (an A-B-A situation), in which case the failure is semantically legitimate. Cheers, Justin -----Original Message----- From: Justin Sampson Sent: Monday, April 25, 2016 2:59 PM To: 'Martin Buchholz'; Aleksey Shipilev Cc: jmm-dev Subject: RE: [jmm-dev] weakCompareAndSet memory semantics Martin Buchholz wrote: > The old public methods in j.u.c.atomic have documentation, but > they are weak in two different ways! > """May fail spuriously and does not provide ordering guarantees""" > but we (probably) want a variant that "may fail spuriously" but > still provides sequential consistency, for use in our CAS loops. At the risk of annoyance-through-repetition, I'll just mention one last time that there's precedent for exactly that behavior, in the actual-but-undocumented semantics of compareAndSet on both AtomicStampedReference and AtomicMarkableReference. (Furthermore, weakCompareAndSet simply delegates to compareAndSet on both of those classes.) The attemptStamp/attemptMark methods are also essentially CAS operations, and their potential for spurious failure is actually documented. Their docs don't mention volatile ordering, but they do provide it (on success). The compareAndSet methods also don't mention volatile ordering in their own docs, but they're covered by the package docs. Cheers, Justin From aph at redhat.com Tue Apr 26 07:56:09 2016 From: aph at redhat.com (Andrew Haley) Date: Tue, 26 Apr 2016 08:56:09 +0100 Subject: [jmm-dev] weakCompareAndSet memory semantics In-Reply-To: References: <571751FC.5010505@oracle.com> <57180642.3050505@oracle.com> <57180C4D.9070707@oracle.com> <571886CC.5030209@redhat.com> <57189003.3030007@oracle.com> <5718C348.6090809@oracle.com> <5718CCE2.5060601@redhat.com> <5719645D.5030108@oracle.com> <5719E31F.9000109@redhat.com> <571A0BC5.9020702@oracle.com> <571A1319.6050908@redhat.com> <571A1CF7.9040007@oracle.com> <571A2C89.8030209@redhat.com> <571A4240.40407@redhat.com> <571AA59C.5020705@oracle.com> <571B24DE.9050806@oracle.com> Message-ID: <571F1F19.2070603@redhat.com> On 26/04/16 02:03, Justin Sampson wrote: > Sorry, on further thought, perhaps the potential for spurious > failure in AtomicStampedReference and AtomicMarkableReference isn't > actually observable in practice. Their compareAndSet methods use the > same algorithm as their attemptStamp and attemptMark methods, which > are documented to allow spurious failure. But in all of those cases > (attemptStamp, attemptMark, _and_ compareAndSet on both classes), > while it's true that the final casPair call can fail even if the > current ref and stamp/mark are equal to the expected values at that > moment, that will only happen if there was an intervening write with > a _different_ ref or stamp/mark (an A-B-A situation), in which case > the failure is semantically legitimate. But that's surely because at the time it was written we didn't have the necessary underpinnings in Unsafe to implement a weak CAS. Andrew. From aleksey.shipilev at oracle.com Wed Apr 27 08:56:53 2016 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Wed, 27 Apr 2016 11:56:53 +0300 Subject: [jmm-dev] RFR 8154755: Add a VarHandle weakCompareAndSet with volatile semantics In-Reply-To: <07EE4695-9AF3-4F50-ACAE-831BD508B657@oracle.com> References: <07EE4695-9AF3-4F50-ACAE-831BD508B657@oracle.com> Message-ID: <57207ED5.8000007@oracle.com> On 04/21/2016 07:21 PM, Paul Sandoz wrote: > Please review: > > http://cr.openjdk.java.net/~psandoz/jdk9/JDK-8154755-weak-cas-volatile/webrev/ Looks okay to me. -Aleksey From aph at redhat.com Wed Apr 27 09:33:07 2016 From: aph at redhat.com (Andrew Haley) Date: Wed, 27 Apr 2016 10:33:07 +0100 Subject: [jmm-dev] @Contended Message-ID: <57208753.9050703@redhat.com> The issue of contention has come up and it reminds me of an issue I'd wondered about. Why is @Contended in sun.misc? Why is it only available to system code? It's surely better to allow programmers to use this annotation than to pad their objects with dummy fields to prevent false sharing. Andrew. From vladimir.x.ivanov at oracle.com Wed Apr 27 11:41:21 2016 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Wed, 27 Apr 2016 14:41:21 +0300 Subject: [jmm-dev] @Contended In-Reply-To: <57208753.9050703@redhat.com> References: <57208753.9050703@redhat.com> Message-ID: <5720A561.4010501@oracle.com> Andrew, This question arises on a regular basis and was discussed in details on hotspot-related mailing lists [1]. So far, John Rose provided the most elaborate answer [2]. Best regards, Vladimir Ivanov [1] http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2015-November/016432.html [2] http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2015-November/016535.html On 4/27/16 12:33 PM, Andrew Haley wrote: > The issue of contention has come up and it reminds me of an issue I'd > wondered about. > > Why is @Contended in sun.misc? Why is it only available to system > code? It's surely better to allow programmers to use this annotation > than to pad their objects with dummy fields to prevent false sharing. > > Andrew. > From aph at redhat.com Wed Apr 27 12:11:53 2016 From: aph at redhat.com (Andrew Haley) Date: Wed, 27 Apr 2016 13:11:53 +0100 Subject: [jmm-dev] @Contended In-Reply-To: <5720A561.4010501@oracle.com> References: <57208753.9050703@redhat.com> <5720A561.4010501@oracle.com> Message-ID: <5720AC89.8050105@redhat.com> On 27/04/16 12:41, Vladimir Ivanov wrote: > This question arises on a regular basis and was discussed in details on > hotspot-related mailing lists [1]. > > So far, John Rose provided the most elaborate answer [2]. Thanks. I was desperately hoping that I wasn't in that thread, and relieved to discover that I'm not. :-) http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2015-November/016535.html is hereby bookmarked. I wonder if it is worth padding AtomicIntegers. Andrew. From aleksey.shipilev at oracle.com Wed Apr 27 12:16:22 2016 From: aleksey.shipilev at oracle.com (Aleksey Shipilev) Date: Wed, 27 Apr 2016 15:16:22 +0300 Subject: [jmm-dev] @Contended In-Reply-To: <5720AC89.8050105@redhat.com> References: <57208753.9050703@redhat.com> <5720A561.4010501@oracle.com> <5720AC89.8050105@redhat.com> Message-ID: <5720AD96.5060100@oracle.com> On 04/27/2016 03:11 PM, Andrew Haley wrote: > I wonder if it is worth padding AtomicIntegers. Nope. Alas, @Contended is class-wide, and there are lots of cases where people are using AtomicIntegers without expecting them to take 10x more memory all of the sudden. With all the attention false sharing gets, it sensibly affects specific classes in specific kind of applications only. -Aleksey From aph at redhat.com Wed Apr 27 13:07:42 2016 From: aph at redhat.com (Andrew Haley) Date: Wed, 27 Apr 2016 14:07:42 +0100 Subject: [jmm-dev] @Contended In-Reply-To: <5720AD96.5060100@oracle.com> References: <57208753.9050703@redhat.com> <5720A561.4010501@oracle.com> <5720AC89.8050105@redhat.com> <5720AD96.5060100@oracle.com> Message-ID: <5720B99E.6060405@redhat.com> On 04/27/2016 01:16 PM, Aleksey Shipilev wrote: > On 04/27/2016 03:11 PM, Andrew Haley wrote: >> I wonder if it is worth padding AtomicIntegers. > > Nope. Alas, @Contended is class-wide, and there are lots of cases where > people are using AtomicIntegers without expecting them to take 10x more > memory all of the sudden. Yea, and without value types there's no easy way for users to pad them. On most of the arches I use AtomicIntegers are two xwords in size; I guess they'd have to grow to eight xwords for they "typical" cache line size. Which is a big bump. BTW, this is something that ObjectLayout may be good for. (http://objectlayout.org/) > With all the attention false sharing gets, it > sensibly affects specific classes in specific kind of applications only. I'm sure that's true, but everybody hates false sharing because it's so unpredictable in a garbage-collected language. Even if it's never happened to them. Andrew. From martinrb at google.com Wed Apr 27 16:41:31 2016 From: martinrb at google.com (Martin Buchholz) Date: Wed, 27 Apr 2016 09:41:31 -0700 Subject: [jmm-dev] @Contended In-Reply-To: <5720B99E.6060405@redhat.com> References: <57208753.9050703@redhat.com> <5720A561.4010501@oracle.com> <5720AC89.8050105@redhat.com> <5720AD96.5060100@oracle.com> <5720B99E.6060405@redhat.com> Message-ID: On Wed, Apr 27, 2016 at 6:07 AM, Andrew Haley wrote: > I'm sure that's true, but everybody hates false sharing because it's > so unpredictable in a garbage-collected language. Even if it's never > happened to them. Hmmm... with C, if you're willing to work, you do get memalign and can lay out objects in cache lines. OTOH, with GC you might get false sharing with card marks, even after padding. From vladimir.x.ivanov at oracle.com Fri Apr 29 12:36:29 2016 From: vladimir.x.ivanov at oracle.com (Vladimir Ivanov) Date: Fri, 29 Apr 2016 15:36:29 +0300 Subject: [jmm-dev] RFR 8154755: Add a VarHandle weakCompareAndSet with volatile semantics In-Reply-To: <07EE4695-9AF3-4F50-ACAE-831BD508B657@oracle.com> References: <07EE4695-9AF3-4F50-ACAE-831BD508B657@oracle.com> Message-ID: <5723554D.9030508@oracle.com> Looks good. Best regards, Vladimir Ivanov On 4/21/16 7:21 PM, Paul Sandoz wrote: > Hi, > > Please review: > > http://cr.openjdk.java.net/~psandoz/jdk9/JDK-8154755-weak-cas-volatile/webrev/ > > This webrev adds a new VarHandle access mode method, weakCompareAndSetVolatile [*]. (I also fixed some doc errors regarding AccessMode enum names that i forgot to update in a previous issue). > > Aleksey noticed a discrepancy with the current set of weak CAS methods when comparing with C++ atomics. > > On hardware that supports LL/SC (e.g. ARM) the weak volatile variant may be more performant than the strong volatile variant (compareAndSet) when the CAS is performed in a loop. > > See the thread on the jmm-dev list for more details: > > http://mail.openjdk.java.net/pipermail/jmm-dev/2016-April/000239.html > > > Implementations currently defer to the strong volatile Unsafe CAS. We will follow up with changes to Unsafe, hotspot, and updating the VH implementations as separate issues. > > Thanks, > Paul. > > [*] > /** > * Possibly atomically sets the value of a variable to the {@code newValue} > * with the memory semantics of {@link #setVolatile} if the variable's > * current value, referred to as the witness value, {@code ==} the > * {@code expectedValue}, as accessed with the memory semantics of > * {@link #getVolatile}. > * > *

This operation may fail spuriously (typically, due to memory > * contention) even if the witness value does match the expected value. > * > ... > */ > public final native > @MethodHandle.PolymorphicSignature > @HotSpotIntrinsicCandidate > boolean weakCompareAndSetVolatile(Object... args); > > > > > > Paul. >