Skip to content
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

Convert small atomic fallbacks to managed #99011

Merged
merged 10 commits into from
Mar 22, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -42,48 +42,6 @@ public static long Decrement(ref long location) =>
#endregion

#region Exchange
/// <summary>Sets a 8-bit unsigned integer to a specified value and returns the original value, as an atomic operation.</summary>
/// <param name="location1">The variable to set to the specified value.</param>
/// <param name="value">The value to which the <paramref name="location1"/> parameter is set.</param>
/// <returns>The original value of <paramref name="location1"/>.</returns>
/// <exception cref="NullReferenceException">The address of location1 is a null pointer.</exception>
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte Exchange(ref byte location1, byte value)
{
#if TARGET_X86 || TARGET_AMD64 || TARGET_ARM64
return Exchange(ref location1, value); // Must expand intrinsic
#else
if (Unsafe.IsNullRef(ref location1))
ThrowHelper.ThrowNullReferenceException();
return Exchange8(ref location1, value);
#endif
}

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern byte Exchange8(ref byte location1, byte value);

/// <summary>Sets a 16-bit signed integer to a specified value and returns the original value, as an atomic operation.</summary>
/// <param name="location1">The variable to set to the specified value.</param>
/// <param name="value">The value to which the <paramref name="location1"/> parameter is set.</param>
/// <returns>The original value of <paramref name="location1"/>.</returns>
/// <exception cref="NullReferenceException">The address of location1 is a null pointer.</exception>
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static short Exchange(ref short location1, short value)
{
#if TARGET_X86 || TARGET_AMD64 || TARGET_ARM64
return Exchange(ref location1, value); // Must expand intrinsic
#else
if (Unsafe.IsNullRef(ref location1))
ThrowHelper.ThrowNullReferenceException();
return Exchange16(ref location1, value);
#endif
}

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern short Exchange16(ref short location1, short value);

/// <summary>Sets a 32-bit signed integer to a specified value and returns the original value, as an atomic operation.</summary>
/// <param name="location1">The variable to set to the specified value.</param>
/// <param name="value">The value to which the <paramref name="location1"/> parameter is set.</param>
Expand Down Expand Up @@ -162,50 +120,6 @@ public static T Exchange<T>([NotNullIfNotNull(nameof(value))] ref T location1, T
#endregion

#region CompareExchange
/// <summary>Compares two 8-bit unsigned integers for equality and, if they are equal, replaces the first value.</summary>
/// <param name="location1">The destination, whose value is compared with <paramref name="comparand"/> and possibly replaced.</param>
/// <param name="value">The value that replaces the destination value if the comparison results in equality.</param>
/// <param name="comparand">The value that is compared to the value at <paramref name="location1"/>.</param>
/// <returns>The original value in <paramref name="location1"/>.</returns>
/// <exception cref="NullReferenceException">The address of <paramref name="location1"/> is a null pointer.</exception>
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte CompareExchange(ref byte location1, byte value, byte comparand)
{
#if TARGET_X86 || TARGET_AMD64 || TARGET_ARM64
return CompareExchange(ref location1, value, comparand); // Must expand intrinsic
#else
if (Unsafe.IsNullRef(ref location1))
ThrowHelper.ThrowNullReferenceException();
return CompareExchange8(ref location1, value, comparand);
#endif
}

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern byte CompareExchange8(ref byte location1, byte value, byte comparand);

/// <summary>Compares two 16-bit signed integers for equality and, if they are equal, replaces the first value.</summary>
/// <param name="location1">The destination, whose value is compared with <paramref name="comparand"/> and possibly replaced.</param>
/// <param name="value">The value that replaces the destination value if the comparison results in equality.</param>
/// <param name="comparand">The value that is compared to the value at <paramref name="location1"/>.</param>
/// <returns>The original value in <paramref name="location1"/>.</returns>
/// <exception cref="NullReferenceException">The address of <paramref name="location1"/> is a null pointer.</exception>
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static short CompareExchange(ref short location1, short value, short comparand)
{
#if TARGET_X86 || TARGET_AMD64 || TARGET_ARM64
return CompareExchange(ref location1, value, comparand); // Must expand intrinsic
#else
if (Unsafe.IsNullRef(ref location1))
ThrowHelper.ThrowNullReferenceException();
return CompareExchange16(ref location1, value, comparand);
#endif
}

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern short CompareExchange16(ref short location1, short value, short comparand);

/// <summary>Compares two 32-bit signed integers for equality and, if they are equal, replaces the first value.</summary>
/// <param name="location1">The destination, whose value is compared with <paramref name="comparand"/> and possibly replaced.</param>
/// <param name="value">The value that replaces the destination value if the comparison results in equality.</param>
Expand Down
9 changes: 0 additions & 9 deletions src/coreclr/inc/winwrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,4 @@ WszCreateProcess(
LPPROCESS_INFORMATION lpProcessInformation
);

#ifdef HOST_WINDOWS

//
// Workaround for https://github.com/microsoft/WindowsAppSDK/issues/4074
// Windows SDK is missing InterlockedCompareExchange8 definition.
//
#define InterlockedCompareExchange8 _InterlockedCompareExchange8

#endif // HOST_WINDOWS
#endif // __WIN_WRAP_H__
4 changes: 0 additions & 4 deletions src/coreclr/nativeaot/Runtime/EHHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,6 @@ EXTERN_C CODE_LOCATION RhpCheckedAssignRefEBPAVLocation;
EXTERN_C CODE_LOCATION RhpCheckedLockCmpXchgAVLocation;
EXTERN_C CODE_LOCATION RhpCheckedXchgAVLocation;
#if !defined(HOST_AMD64) && !defined(HOST_ARM64)
EXTERN_C CODE_LOCATION RhpLockCmpXchg8AVLocation;
EXTERN_C CODE_LOCATION RhpLockCmpXchg16AVLocation;
EXTERN_C CODE_LOCATION RhpLockCmpXchg32AVLocation;
EXTERN_C CODE_LOCATION RhpLockCmpXchg64AVLocation;
#endif
Expand Down Expand Up @@ -372,8 +370,6 @@ static bool InWriteBarrierHelper(uintptr_t faultingIP)
(uintptr_t)&RhpCheckedXchgAVLocation,
#if !defined(HOST_AMD64) && !defined(HOST_ARM64)
#if !defined(HOST_X86)
(uintptr_t)&RhpLockCmpXchg8AVLocation,
(uintptr_t)&RhpLockCmpXchg16AVLocation,
(uintptr_t)&RhpLockCmpXchg32AVLocation,
#endif
(uintptr_t)&RhpLockCmpXchg64AVLocation,
Expand Down
45 changes: 0 additions & 45 deletions src/coreclr/nativeaot/Runtime/arm/Interlocked.S
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,6 @@
#include <AsmOffsets.inc> // generated by the build from AsmOffsets.cpp
#include <unixasmmacros.inc>

// WARNING: Code in EHHelpers.cpp makes assumptions about this helper, in particular:
// - Function "InWriteBarrierHelper" assumes an AV due to passed in null pointer will happen at RhpLockCmpXchg8AVLocation
// - Function "UnwindSimpleHelperToCaller" assumes no registers were pushed and LR contains the return address
// r0 = destination address
// r1 = value
// r2 = comparand
LEAF_ENTRY RhpLockCmpXchg8, _TEXT
dmb
GLOBAL_LABEL RhpLockCmpXchg8AVLocation
LOCAL_LABEL(CmpXchg8Retry):
ldrexb r3, [r0]
cmp r2, r3
bne LOCAL_LABEL(CmpXchg8Exit)
strexb r12, r1, [r0]
cmp r12, #0
bne LOCAL_LABEL(CmpXchg8Retry)
LOCAL_LABEL(CmpXchg8Exit):
mov r0, r3
dmb
bx lr
LEAF_END RhpLockCmpXchg8, _TEXT

// WARNING: Code in EHHelpers.cpp makes assumptions about this helper, in particular:
// - Function "InWriteBarrierHelper" assumes an AV due to passed in null pointer will happen at RhpLockCmpXchg16AVLocation
// - Function "UnwindSimpleHelperToCaller" assumes no registers were pushed and LR contains the return address
// r0 = destination address
// r1 = value
// r2 = comparand
LEAF_ENTRY RhpLockCmpXchg16, _TEXT
uxth r2, r2
dmb
GLOBAL_LABEL RhpLockCmpXchg16AVLocation
LOCAL_LABEL(CmpXchg16Retry):
ldrexh r3, [r0]
cmp r2, r3
bne LOCAL_LABEL(CmpXchg16Exit)
strexh r12, r1, [r0]
cmp r12, #0
bne LOCAL_LABEL(CmpXchg16Retry)
LOCAL_LABEL(CmpXchg16Exit):
sxth r0, r3
dmb
bx lr
LEAF_END RhpLockCmpXchg16, _TEXT

// WARNING: Code in EHHelpers.cpp makes assumptions about this helper, in particular:
// - Function "InWriteBarrierHelper" assumes an AV due to passed in null pointer will happen at RhpLockCmpXchg32AVLocation
// - Function "UnwindSimpleHelperToCaller" assumes no registers were pushed and LR contains the return address
Expand Down
14 changes: 0 additions & 14 deletions src/coreclr/nativeaot/Runtime/portable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,20 +390,6 @@ FCIMPL2(Object *, RhpCheckedXchg, Object ** location, Object * value)
}
FCIMPLEND

FCIMPL3(uint8_t, RhpLockCmpXchg8, uint8_t * location, uint8_t value, uint8_t comparand)
{
ASSERT_UNCONDITIONALLY("NYI");
return 0;
}
FCIMPLEND

FCIMPL3(int16_t, RhpLockCmpXchg16, int16_t * location, int16_t value, int16_t comparand)
{
ASSERT_UNCONDITIONALLY("NYI");
return 0;
}
FCIMPLEND

FCIMPL3(int32_t, RhpLockCmpXchg32, int32_t * location, int32_t value, int32_t comparand)
{
// @TODO: USE_PORTABLE_HELPERS - Null check
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -645,14 +645,6 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe
//
// Interlocked helpers
//
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhpLockCmpXchg8")]
internal static extern byte InterlockedCompareExchange(ref byte location1, byte value, byte comparand);

[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhpLockCmpXchg16")]
internal static extern short InterlockedCompareExchange(ref short location1, short value, short comparand);

[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhpLockCmpXchg32")]
internal static extern int InterlockedCompareExchange(ref int location1, int value, int comparand);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,6 @@ public static partial class Interlocked
{
#region CompareExchange

[Intrinsic]
public static byte CompareExchange(ref byte location1, byte value, byte comparand)
{
#if TARGET_X86 || TARGET_AMD64 || TARGET_ARM64
return CompareExchange(ref location1, value, comparand);
#else
return RuntimeImports.InterlockedCompareExchange(ref location1, value, comparand);
#endif
}

[Intrinsic]
public static short CompareExchange(ref short location1, short value, short comparand)
{
#if TARGET_X86 || TARGET_AMD64 || TARGET_ARM64
return CompareExchange(ref location1, value, comparand);
#else
return RuntimeImports.InterlockedCompareExchange(ref location1, value, comparand);
#endif
}

[Intrinsic]
public static int CompareExchange(ref int location1, int value, int comparand)
{
Expand Down Expand Up @@ -70,40 +50,6 @@ public static T CompareExchange<T>(ref T location1, T value, T comparand) where

#region Exchange

[Intrinsic]
public static byte Exchange(ref byte location1, byte value)
{
#if TARGET_X86 || TARGET_AMD64 || TARGET_ARM64
return Exchange(ref location1, value);
#else
byte oldValue;

do
{
oldValue = location1;
} while (CompareExchange(ref location1, value, oldValue) != oldValue);

return oldValue;
#endif
}

[Intrinsic]
public static short Exchange(ref short location1, short value)
{
#if TARGET_X86 || TARGET_AMD64 || TARGET_ARM64
return Exchange(ref location1, value);
#else
short oldValue;

do
{
oldValue = location1;
} while (CompareExchange(ref location1, value, oldValue) != oldValue);

return oldValue;
#endif
}

[Intrinsic]
public static int Exchange(ref int location1, int value)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,6 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe
//
// Interlocked helpers
//
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhpLockCmpXchg8")]
internal static extern byte InterlockedCompareExchange(ref byte location1, byte value, byte comparand);

[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhpLockCmpXchg16")]
internal static extern short InterlockedCompareExchange(ref short location1, short value, short comparand);

[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhpLockCmpXchg32")]
internal static extern int InterlockedCompareExchange(ref int location1, int value, int comparand);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,6 @@ public static IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr
#endif
}

[Intrinsic]
public static byte CompareExchange(ref byte location1, byte value, byte comparand)
{
#if TARGET_X86 || TARGET_AMD64 || TARGET_ARM64
return CompareExchange(ref location1, value, comparand);
#else
return RuntimeImports.InterlockedCompareExchange(ref location1, value, comparand);
#endif
}

[Intrinsic]
public static short CompareExchange(ref short location1, short value, short comparand)
{
#if TARGET_X86 || TARGET_AMD64 || TARGET_ARM64
return CompareExchange(ref location1, value, comparand);
#else
return RuntimeImports.InterlockedCompareExchange(ref location1, value, comparand);
#endif
}

[Intrinsic]
public static int CompareExchange(ref int location1, int value, int comparand)
{
Expand Down
34 changes: 0 additions & 34 deletions src/coreclr/pal/inc/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -3636,20 +3636,6 @@ Return Values
The function returns the initial value pointed to by Target.

--*/
Define_InterlockMethod(
CHAR,
InterlockedExchange8(IN OUT CHAR volatile *Target, CHAR Value),
InterlockedExchange8(Target, Value),
__atomic_exchange_n(Target, Value, __ATOMIC_ACQ_REL)
)

Define_InterlockMethod(
SHORT,
InterlockedExchange16(IN OUT SHORT volatile *Target, SHORT Value),
InterlockedExchange16(Target, Value),
__atomic_exchange_n(Target, Value, __ATOMIC_ACQ_REL)
)

Define_InterlockMethod(
LONG,
InterlockedExchange(IN OUT LONG volatile *Target, LONG Value),
Expand Down Expand Up @@ -3708,26 +3694,6 @@ Return Values
The return value is the initial value of the destination.

--*/
Define_InterlockMethod(
CHAR,
InterlockedCompareExchange8(IN OUT CHAR volatile *Destination, IN CHAR Exchange, IN CHAR Comperand),
InterlockedCompareExchange8(Destination, Exchange, Comperand),
__sync_val_compare_and_swap(
Destination, /* The pointer to a variable whose value is to be compared with. */
Comperand, /* The value to be compared */
Exchange /* The value to be stored */)
)

Define_InterlockMethod(
SHORT,
InterlockedCompareExchange16(IN OUT SHORT volatile *Destination, IN SHORT Exchange, IN SHORT Comperand),
InterlockedCompareExchange16(Destination, Exchange, Comperand),
__sync_val_compare_and_swap(
Destination, /* The pointer to a variable whose value is to be compared with. */
Comperand, /* The value to be compared */
Exchange /* The value to be stored */)
)

Define_InterlockMethod(
LONG,
InterlockedCompareExchange(IN OUT LONG volatile *Destination, IN LONG Exchange, IN LONG Comperand),
Expand Down
Loading
Loading