<div dir="ltr"><div>Got it, thanks. In the one-shot case, if STREX failed because we lost exclusive access, we would fall through to the slow case. So there should be nothing semantically different happening.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Mar 13, 2023 at 11:25 AM Reingruber, Richard <<a href="mailto:richard.reingruber@sap.com">richard.reingruber@sap.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="msg6488132158543645204">





<div style="overflow-wrap: break-word;" lang="en-DE">
<div class="m_6488132158543645204WordSection1">
<p class="MsoNormal"><span style="font-size:11pt" lang="DE">> This whole coding lives in MacroAssembler::atomic_cas_bool, but that function<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt" lang="DE">> is not always called. There are plenty of direct usages of ldrex+strex. There<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt" lang="DE">> is even a condition argument for MacroAssembler::cas_for_lock_acquire to<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt" lang="DE">> either do strex directly or to dive down into atomic_cas_bool.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt" lang="DE"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt" lang="DE">The check of the strex result is not local in these cases.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt" lang="DE">MacroAssembler::cas_for_lock_acquire checks here:
<a href="https://github.com/openjdk/jdk/blob/25e7ac226a3be9c064c0a65c398a8165596150f7/src/hotspot/cpu/arm/macroAssembler_arm.cpp#L1195" target="_blank">
https://github.com/openjdk/jdk/blob/25e7ac226a3be9c064c0a65c398a8165596150f7/src/hotspot/cpu/arm/macroAssembler_arm.cpp#L1195</a><u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt" lang="DE">Failure handling is done in the slow_case.</span><span style="font-size:11pt"><u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"><u></u> <u></u></span></p>
<div style="border-color:rgb(181,196,223) currentcolor currentcolor;border-style:solid none none;border-width:1pt medium medium;padding:3pt 0cm 0cm">
<p class="MsoNormal" style="margin-bottom:12pt"><b><span style="font-size:12pt;color:black">From:
</span></b><span style="font-size:12pt;color:black">Thomas Stüfe <<a href="mailto:thomas.stuefe@gmail.com" target="_blank">thomas.stuefe@gmail.com</a>><br>
<b>Date: </b>Monday, 13. March 2023 at 11:07<br>
<b>To: </b>Reingruber, Richard <<a href="mailto:richard.reingruber@sap.com" target="_blank">richard.reingruber@sap.com</a>><br>
<b>Cc: </b><a href="mailto:porters-dev@openjdk.org" target="_blank">porters-dev@openjdk.org</a> <<a href="mailto:porters-dev@openjdk.org" target="_blank">porters-dev@openjdk.org</a>>, <a href="mailto:aarch32-port-dev@openjdk.org" target="_blank">aarch32-port-dev@openjdk.org</a> <<a href="mailto:aarch32-port-dev@openjdk.org" target="_blank">aarch32-port-dev@openjdk.org</a>><br>
<b>Subject: </b>Re: Question about CAS via LDREX/STREX on 32-bit arm<u></u><u></u></span></p>
</div>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">This whole coding lives in MacroAssembler::atomic_cas_bool, but that function is not always called. There are plenty of direct usages of ldrex+strex. There is even a condition argument for MacroAssembler::cas_for_lock_acquire
 to either do strex directly or to dive down into atomic_cas_bool.<u></u><u></u></span></p>
</div>
<p class="MsoNormal"><span style="font-size:11pt"><u></u> <u></u></span></p>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">On Mon, Mar 13, 2023 at 11:03 AM Reingruber, Richard <<a href="mailto:richard.reingruber@sap.com" target="_blank">richard.reingruber@sap.com</a>> wrote:<u></u><u></u></span></p>
</div>
<blockquote style="border-color:currentcolor currentcolor currentcolor rgb(204,204,204);border-style:none none none solid;border-width:medium medium medium 1pt;padding:0cm 0cm 0cm 6pt;margin-left:4.8pt;margin-right:0cm">
<div>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">> Yes, I read it the same way. So we repeat the CAS for lost reservation. I'm<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> interested in when this could happen and why it would be okay to sometimes<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> omit this loop and do the "raw" LDREX-STREX sequence. See my original mail.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">Hm, I don't understand. The loop in the sequence A-F is always there. How is it omitted?<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<div style="border-style:solid none none;border-width:1pt medium medium;padding:3pt 0cm 0cm;border-color:currentcolor">
<p class="MsoNormal" style="margin-bottom:12pt"><b><span style="font-size:12pt;color:black">From:
</span></b><span style="font-size:12pt;color:black">Thomas Stüfe <<a href="mailto:thomas.stuefe@gmail.com" target="_blank">thomas.stuefe@gmail.com</a>><br>
<b>Date: </b>Monday, 13. March 2023 at 10:54<br>
<b>To: </b>Reingruber, Richard <<a href="mailto:richard.reingruber@sap.com" target="_blank">richard.reingruber@sap.com</a>><br>
<b>Cc: </b><a href="mailto:porters-dev@openjdk.org" target="_blank">porters-dev@openjdk.org</a> <<a href="mailto:porters-dev@openjdk.org" target="_blank">porters-dev@openjdk.org</a>>,
<a href="mailto:aarch32-port-dev@openjdk.org" target="_blank">aarch32-port-dev@openjdk.org</a> <<a href="mailto:aarch32-port-dev@openjdk.org" target="_blank">aarch32-port-dev@openjdk.org</a>><br>
<b>Subject: </b>Re: Question about CAS via LDREX/STREX on 32-bit arm</span><span style="font-size:11pt"><u></u><u></u></span></p>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">Hi Richard :)<u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
</div>
</div>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">On Mon, Mar 13, 2023 at 10:02 AM Reingruber, Richard <<a href="mailto:richard.reingruber@sap.com" target="_blank">richard.reingruber@sap.com</a>>
 wrote:<u></u><u></u></span></p>
</div>
<blockquote style="border-style:none none none solid;border-width:medium medium medium 1pt;padding:0cm 0cm 0cm 6pt;margin:5pt 0cm 5pt 4.8pt;border-color:currentcolor currentcolor currentcolor rgb(204,204,204)">
<div>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">> Hi ARM experts,<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">Hi Thomas, not at all an ARM expert... :)<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">but I think I understand the code.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> I am trying to understand how CAS is implemented on arm; in particular, "MacroAssembler::atomic_cas_bool":<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> MacroAssembler::atomic_cas_bool<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> ```<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">>     assert_different_registers(tmp_reg, oldval, newval, base);<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">>     Label loop;<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">>     bind(loop);<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> A   ldrex(tmp_reg, Address(base, offset));<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> B   subs(tmp_reg, tmp_reg, oldval);<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> C   strex(tmp_reg, newval, Address(base, offset), eq);<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> D   cmp(tmp_reg, 1, eq);<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> E   b(loop, eq);<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> F   cmp(tmp_reg, 0);<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">>     if (tmpreg == noreg) {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">>       pop(tmp_reg);<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">>     }<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> ```<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> It uses LDREX and STREX to perform a cas of *(base+offset) from oldval to newval. It does so in a loop. The code distinguishes two failures: STREX
 failing, and a "semantically failed" CAS.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> Here is what I think this code does:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> A) LDREX: tmp=*(base+offset)<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> B) tmp -= oldvalue
<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">>    If *(base+offset) was unchanged, tmp_reg is now 0 and Z is 1<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> C) If Z is 1: STREX the new value: *(base+offset)=newval. Otherwise, omit.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">>    After this, if the store succeeded, tmp_reg is 0, if the store failed its 1.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> D) Here, tmp_reg is: 0 if the store succeeded, 1 if it failed, 1...n if *(base+offset) had been modified before LDREX.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">>    We now compare with 1 and ...<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> E) ...repeat the loop if tmp_reg was 1<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> So we loop until either *(base+offset) had been changed to some other value concurrently before out LDREX. Or until our store succeeded.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">> I wondered what the loop guards against. And why it would be okay sometimes to omit it.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">The loop is needed to try again if the reservation
</span><span style="font-size:11pt" lang="DE">was</span><span style="font-size:11pt"> lost</span><span style="font-size:11pt" lang="DE"> until the STREX succeeds or
</span><span style="font-size:11pt">*(base+offset) != oldvalue</span><span style="font-size:11pt" lang="DE">.</span><span style="font-size:11pt"><u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt" lang="DE">So there are two cases.
</span><span style="font-size:11pt">The loop is left iff<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">(1) *(base+offset) != oldvalue<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">(2) the STREX succeeded<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt" lang="DE">First i</span><span style="font-size:11pt">t is important to understand that C, D, E are only executed if at B the eq-condition is set
 to true.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">This is based on the "Conditional Execution"
</span><span style="font-size:11pt" lang="DE">f</span><span style="font-size:11pt">eature of ARM: execution of most instructions can be made dependent on a condition (see
<a href="https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.arm.com%2Fdocumentation%2Fden0013%2Fd%2FARM-Thumb-Unified-Assembly-Language-Instructions%2FInstruction-set-basics%2FConditional-execution%3Flang%3Den&data=05%7C01%7Crichard.reingruber%40sap.com%7C217dfeac228443e2b7e908db23aacb0e%7C42f7676cf455423c82f6dc2d99791af7%7C0%7C0%7C638142988683859436%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=PE%2Fg2hyJRes%2FsQ5ZCjCCxIotC%2F9RSY7jpVIT6owG3Dc%3D&reserved=0" target="_blank">
https://developer.arm.com/documentation/den0013/d/ARM-Thumb-Unified-Assembly-Language-Instructions/Instruction-set-basics/Conditional-execution?lang=en</a>)<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">So in case (1) C, D, E are not executed because B indicates that *(base+offset) and oldvalue are not-eq</span><span style="font-size:11pt" lang="DE">
 and the loop is left.</span><span style="font-size:11pt"><u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
</div>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">Ah, thanks, that was my thinking error. I did not realize that CMP was also conditional. I assumed the "eq" in the CMP (D) was a condition for the
 CMP. Which makes no sense, as I know now, since CMP just does a sub and only needs two arguments. So that meant the full branch CDE was controlled from the subtraction result at B.<u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">That also resolves the "1 has a double meaning" question. It hasn't.<u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
</div>
<blockquote style="border-style:none none none solid;border-width:medium medium medium 1pt;padding:0cm 0cm 0cm 6pt;margin:5pt 0cm 5pt 4.8pt;border-color:currentcolor currentcolor currentcolor rgb(204,204,204)">
<div>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">In case (2) C, D, E are executed. At C, if the reservation from A still exists, tmp_reg will be set to 0 otherwise to 1. At E the branch is taken
 if D indicated tmp_reg == 1 (reservation was lost) otherwise the loop is left.<u></u><u></u></span></p>
</div>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">Yes, I read it the same way. So we repeat the CAS for lost reservation. I'm interested in when this could happen and why it would be okay to sometimes
 omit this loop and do the "raw" LDREX-STREX sequence. See my original mail.<u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">I suspect it has something to do with context switches. That the kernel does a CLREX when we switch, so if we switch between LDREX and STREX, the
 reservation could be lost. But why would it then be okay to ignore this sometimes?<u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">Thanks!<u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">Thomas<u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
</div>
<blockquote style="border-style:none none none solid;border-width:medium medium medium 1pt;padding:0cm 0cm 0cm 6pt;margin:5pt 0cm 5pt 4.8pt;border-color:currentcolor currentcolor currentcolor rgb(204,204,204)">
<div>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt">Cheers, Richard.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
<div style="border-style:solid none none;border-width:1pt medium medium;padding:3pt 0cm 0cm;border-color:currentcolor">
<p class="MsoNormal" style="margin-bottom:12pt"><b><span style="font-size:12pt;color:black">From:
</span></b><span style="font-size:12pt;color:black">porters-dev <<a href="mailto:porters-dev-retn@openjdk.org" target="_blank">porters-dev-retn@openjdk.org</a>> on behalf of Thomas Stüfe <<a href="mailto:thomas.stuefe@gmail.com" target="_blank">thomas.stuefe@gmail.com</a>><br>
<b>Date: </b>Saturday, 11. March 2023 at 11:19<br>
<b>To: </b><a href="mailto:porters-dev@openjdk.org" target="_blank">porters-dev@openjdk.org</a> <<a href="mailto:porters-dev@openjdk.org" target="_blank">porters-dev@openjdk.org</a>>,
<a href="mailto:aarch32-port-dev@openjdk.org" target="_blank">aarch32-port-dev@openjdk.org</a> <<a href="mailto:aarch32-port-dev@openjdk.org" target="_blank">aarch32-port-dev@openjdk.org</a>><br>
<b>Subject: </b>Question about CAS via LDREX/STREX on 32-bit arm</span><span style="font-size:11pt"><u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">Hi ARM experts,<br>
<br>
I am trying to understand how CAS is implemented on arm; in particular, "MacroAssembler::atomic_cas_bool":<br>
<br>
MacroAssembler::atomic_cas_bool<u></u><u></u></span></p>
<div>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt">```<u></u><u></u></span></p>
</div>
<p class="MsoNormal" style="margin-bottom:12pt"><span style="font-size:11pt">    assert_different_registers(tmp_reg, oldval, newval, base);<br>
    Label loop;<br>
    bind(loop);<br>
A   ldrex(tmp_reg, Address(base, offset));<br>
B   subs(tmp_reg, tmp_reg, oldval);<br>
C   strex(tmp_reg, newval, Address(base, offset), eq);<br>
D   cmp(tmp_reg, 1, eq);<br>
E   b(loop, eq);<br>
F   cmp(tmp_reg, 0);<br>
    if (tmpreg == noreg) {<br>
      pop(tmp_reg);<br>
    }<br>
```<br>
<br>
It uses LDREX and STREX to perform a cas of *(base+offset) from oldval to newval. It does so in a loop. The code distinguishes two failures: STREX failing, and a "semantically failed" CAS.<u></u><u></u></span></p>
<div>
<p class="MsoNormal"><span style="font-size:11pt">Here is what I think this code does:<u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11pt"> <u></u><u></u></span></p>
</div>
<p class="MsoNormal" style="margin-bottom:12pt"><span style="font-size:11pt">A) LDREX: tmp=*(base+offset)<br>
B) tmp -= oldvalue <br>
   If *(base+offset) was unchanged, tmp_reg is now 0 and Z is 1<br>
C) If Z is 1: STREX the new value: *(base+offset)=newval. Otherwise, omit.<br>
   After this, if the store succeeded, tmp_reg is 0, if the store failed its 1.<br>
D) Here, tmp_reg is: 0 if the store succeeded, 1 if it failed, 1...n if *(base+offset) had been modified before LDREX.<br>
   We now compare with 1 and ...<br>
E) ...repeat the loop if tmp_reg was 1<br>
<br>
So we loop until either *(base+offset) had been changed to some other value concurrently before out LDREX. Or until our store succeeded.<br>
<br>
I wondered what the loop guards against. And why it would be okay sometimes to omit it.<br>
<br>
IIUC, STREX fails if the core did lose its exclusive access to the memory location since the LDREX. This can be one of three things, right? :<br>
- another core slipped in an LDREX+STREX to the same location between our LDREX and STREX<br>
- Or we context switched to another thread or process. I assume it does a CLREX then, right? Because how could you prevent a sequence like "LDREX(p1) -> switch -> LDREX(p2) -> switch back STREX(p1)" - if I understand the ARM manual [1] correctly, a STREX to
 a different location than the preceding LDREX is undefined.<br>
- Or we had a signal after LDREX and did a second LDREX in the signal handler. Does the kernel do a CLREX when invoking a signal handler?<br>
<br>
More questions:<br>
<br>
- If I got it right, at (D), tmp_reg value "1" has two meanings: either STREX failed or some thread increased the value concurrently by 1. We repeat the loop either way. Is this just accepted behavior? Increasing by 1 is maybe not that rare.<br>
<br>
- If I understood this correctly, the loop guards us mainly against context switches. Without the loop a context switch would count as a "semantically failed" CAS. Why would that be okay? Should we not do this loop always?<br>
<br>
- Do we not need an explicit CLREX after the operation? Or does the STREX also clear the hardware monitor? Or does it just not matter?<br>
<br>
- We have VM_Version::supports_ldrex(). Code seems to me sometimes guarded by this (e.g MacroAssembler::atomic_cas_bool), sometimes code just executes ldrex/strex (e.g. the one-shot path of MacroAssembler::cas_for_lock_acquire). Am I mistaken? Or is LDREX now
 generally available? Does ARMv6 mean STREX and LDREX are available?<br>
<br>
<br>
Thanks a lot!<br>
<br>
Cheers, Thomas<u></u><u></u></span></p>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>

</div></blockquote></div>