-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider adding a LOCK CMPXCHG16B intrinsic method #28711
Comments
Thinking about this a little, a more appropriate signature might be one using an out parameter for the old value, something like: bool InterlockedCompareExchange16Bytes(Int128* destination, Int128 value, Int128 comparand, out Int128 oldValue); This would consolidate both This would be fairly trivial to implement, as both the comparand and the "old value" (read from destination on failure) are stored in |
We can't support this without either taking in a set of |
I thought we couldn't support |
#31911 avoids that problem by targeting pairs of pointer-sized items only. |
But you are right that there are still problems with alignment with #31911 that would need to be solved (on both 32-bit and 64-bit platforms). |
Then may be it should go Unsafe? |
How about handling it with:
With the idea that This can be really useful for many scenarios, and the other options is: |
There is also the consideration that while We'd end up needing some |
It's possible to implement this without the newer Armv8.1 atomic instructions, using the LDAXP/STLXP instructions as I noted at the end of my first post, so all Arm64 CPUs supports this. The CASPAL instruction is still preferred if supported. You can see what clang generates for 128-bit atomic compare and swap on Arm64 here: https://godbolt.org/z/vra484Yab |
Shall this API take a pointer or a |
Could an extension of #65184 (one with an |
The CMPXCHG16B instruction is required to do CAS or atomic read of 128-bits values in memory. Currently, atomic 64-bits read and CAS is supported on .NET with the
Interlocked.CompareExchange
andInterlocked.Read
, however the same operations are not support for 128-bits values.I believe that the main problem is that the required instruction (CMPXCHG16B) is not supported on all CPUs, for example, it is not supported by some very old AMD CPUs, however it is a requirement to run Windows 8.1 and 10, so I beleive that the amount of CPUs were this instruction is not supported is very small.
Due to the above limitation, I beleive that the best way to support it is through an intrinsic, and the user can check if the instruction is supported on the current CPU, much like the other
IsSupported
properties that are exposed on the other ISA classes. The API would be something like this:It uses an
Int128
type that is not yet available, but AFAIK work is being done to add it (dotnet/corefxlab#2635).Another alternative is passing the value as two 64-bits values (the low and high parts of the 128-bits value). Afterall, the instruction uses 2 64-bits registers. I beleive the main problem which this solution is returning the 128-bits value.
The CMPXCHG16B sets the zero flag, if the values at destination and the comparand are equal, and clears it otherwise. So, I included a method that returns bool (it would just return the ZF value basically), since it should have better codegen for the case where the user just wants to know if the two values are equal, and the store succeeded. On some cases, getting the value that is currently at
destination
is necessary (for example, when the user just wants to do a atomic 128-bits read), so in this case, the method returning aInt128
can be used (an example is provided below, with theAtomicRead128
method). The method returning a bool can be replaced with the one returning aInt128
, by comparing the returned value with the comparand value, it has slightly worse codegen, but the same end result.It's also worth noting that this instruction has alignment requirements, and the address should be 16 bytes aligned. I believe that the
LoadAligned
SSE intrinsic method had a similar problem, so peharps this can be handled in a similar way?Example usage, an atomic 128-bits increment, just for illustration purposes:
It may be worth noting (in case a implementation on
Interlocked
is desired) that it's also possible to implement this on ARM64, by using LDAXP/CMP/STLXP instruction sequences with two 64-bits registers.The text was updated successfully, but these errors were encountered: