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

Implement Interlocked for small types. #92974

Merged
merged 67 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
4344057
Implement Interlocked for small types.
MichalPetryka Oct 3, 2023
d282722
Fix xarch assert
MichalPetryka Oct 3, 2023
4079320
Update PalRedhawkInline.h
MichalPetryka Oct 3, 2023
dae9d66
Update PalRedhawkInline.h
MichalPetryka Oct 4, 2023
4b74dba
Update threads.c
MichalPetryka Oct 4, 2023
c6935de
Simplify NAOT handling
MichalPetryka Oct 4, 2023
095567c
Fix build
MichalPetryka Oct 4, 2023
35a812f
Update atomic.h
MichalPetryka Oct 4, 2023
f55fb45
Update atomic.h
MichalPetryka Oct 4, 2023
b1c6dde
Update atomic.h
MichalPetryka Oct 4, 2023
8e80946
Fix windows intrinsics
MichalPetryka Oct 5, 2023
a25a4a3
Update comutilnative.cpp
MichalPetryka Oct 5, 2023
da399ca
Fix Windows builds
MichalPetryka Oct 5, 2023
79c07ff
Update icall-def.h
MichalPetryka Oct 6, 2023
7da080b
Fix icall-def.h
akoeplinger Oct 6, 2023
37fdee1
Improve tests
MichalPetryka Oct 6, 2023
358c11b
Update InterlockedTests.cs
MichalPetryka Oct 6, 2023
b0f85fa
Remove small type normalization
MichalPetryka Oct 6, 2023
f406c21
Try to fix the intrinsics
MichalPetryka Oct 6, 2023
59dbd5e
Fix ARM64 build
MichalPetryka Oct 6, 2023
42f1c80
Try to fix XArch 66 prefix and ARM64
MichalPetryka Oct 7, 2023
70174d7
Fix typo
MichalPetryka Oct 7, 2023
f108f6d
Fix assert
MichalPetryka Oct 7, 2023
6d09d88
Code cleanup
MichalPetryka Oct 8, 2023
d3fbf3e
Update importercalls.cpp
MichalPetryka Oct 8, 2023
92b7497
Update importercalls.cpp
MichalPetryka Oct 8, 2023
0394523
Extend small types properly
MichalPetryka Oct 8, 2023
1ee1c3e
Add RISC-V asserts
MichalPetryka Oct 9, 2023
064b7b3
Merge remote-tracking branch 'origin/main' into small-interlocked
lambdageek Oct 10, 2023
25a5194
c11 atomics interlocked ops for small types
lambdageek Oct 10, 2023
22407e4
Simplify Windows atomics
MichalPetryka Oct 10, 2023
50893e2
Merge upstream
MichalPetryka Oct 11, 2023
0cc7d92
Restore NativeAOT fallbacks for other platforms
MichalPetryka Oct 11, 2023
868efdf
Merge upstream
MichalPetryka Oct 17, 2023
d8efc0d
Add more tests
MichalPetryka Oct 21, 2023
6c101a4
Format
MichalPetryka Oct 21, 2023
25e3ab4
Update Interlocked.cs
MichalPetryka Oct 21, 2023
3a3e60e
Merge upstream
MichalPetryka Oct 27, 2023
4ca06ff
Fix tests and comment
MichalPetryka Oct 27, 2023
1879669
Merge branch 'main' into small-interlocked
MichalPetryka Nov 3, 2023
5536554
Merge branch 'dotnet:main' into small-interlocked
MichalPetryka Dec 1, 2023
ed90e8b
Add emitOutputCV handling
MichalPetryka Dec 1, 2023
1c2a4cc
Merge
MichalPetryka Dec 10, 2023
fca6d47
Fix extension
MichalPetryka Dec 10, 2023
ca73b06
Use a slightly better fix
MichalPetryka Dec 10, 2023
d067d7f
More complete fix
MichalPetryka Dec 10, 2023
bbbadc0
Fix the fix
MichalPetryka Dec 10, 2023
1b8767b
Fix more places
MichalPetryka Dec 10, 2023
d357407
CR feedback
jkotas Jan 10, 2024
724f66c
Merge branch 'main' into small-interlocked
MichalPetryka Jan 10, 2024
499ea14
Merge remote-tracking branch 'upstream/main' into small-interlocked
MichalPetryka Jan 20, 2024
55f7cc1
Fix corelib
MichalPetryka Jan 20, 2024
00cdcb7
Fix tests
MichalPetryka Jan 20, 2024
382d8ea
Add using
MichalPetryka Jan 20, 2024
1099743
Match NativeAOT #ifs
MichalPetryka Jan 20, 2024
82f6fbe
Update Interlocked.cs
MichalPetryka Jan 20, 2024
1a7c4a2
Fix test projects
MichalPetryka Jan 21, 2024
7f97233
Fix tests, try linking with libatomic
MichalPetryka Jan 21, 2024
ce412f9
Improve build test
MichalPetryka Jan 21, 2024
ec2c380
Fix tests
MichalPetryka Jan 23, 2024
7b8869a
Merge branch 'main' into small-interlocked
MichalPetryka Jan 23, 2024
2acc845
Merge remote-tracking branch 'upstream/main' into small-interlocked
MichalPetryka Jan 24, 2024
ea35c1e
Fix tests again
MichalPetryka Jan 24, 2024
35f840d
Remove libatomic
MichalPetryka Jan 24, 2024
de8f617
Merge remote-tracking branch 'upstream/main' into small-interlocked
MichalPetryka Jan 24, 2024
7af81b3
Cleanup, fix helper extension
MichalPetryka Jan 24, 2024
72e5bf8
Fix test corelib
MichalPetryka Jan 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,24 @@ public static partial class Interlocked
#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.InternalCall)]
public static extern byte Exchange(ref byte location1, byte value);
AaronRobinsonMSFT marked this conversation as resolved.
Show resolved Hide resolved

/// <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.InternalCall)]
public static extern short Exchange(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 @@ -79,13 +97,34 @@ public static partial class Interlocked
/// <returns>The original value of <paramref name="location1"/>.</returns>
/// <exception cref="NullReferenceException">The address of location1 is a null pointer.</exception>
/// <typeparam name="T">The type to be used for <paramref name="location1"/> and <paramref name="value"/>. This type must be a reference type.</typeparam>
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[return: NotNullIfNotNull(nameof(location1))]
public static T Exchange<T>([NotNullIfNotNull(nameof(value))] ref T location1, T value) where T : class? =>
Unsafe.As<T>(Exchange(ref Unsafe.As<T, object?>(ref location1), value));
#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.InternalCall)]
public static extern byte CompareExchange(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.InternalCall)]
public static extern short CompareExchange(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 Expand Up @@ -134,8 +173,8 @@ public static partial class Interlocked
/// <returns>The original value in <paramref name="location1"/>.</returns>
/// <exception cref="NullReferenceException">The address of <paramref name="location1"/> is a null pointer.</exception>
/// <typeparam name="T">The type to be used for <paramref name="location1"/>, <paramref name="value"/>, and <paramref name="comparand"/>. This type must be a reference type.</typeparam>
[return: NotNullIfNotNull(nameof(location1))]
[Intrinsic]
[return: NotNullIfNotNull(nameof(location1))]
public static T CompareExchange<T>(ref T location1, T value, T comparand) where T : class? =>
Unsafe.As<T>(CompareExchange(ref Unsafe.As<T, object?>(ref location1), value, comparand));
#endregion
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/inc/winwrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,10 @@ WszCreateProcess(

#define InterlockedIncrement _InterlockedIncrement
#define InterlockedDecrement _InterlockedDecrement
#define InterlockedExchange8 _InterlockedExchange8
#define InterlockedCompareExchange8 _InterlockedCompareExchange8
jkotas marked this conversation as resolved.
Show resolved Hide resolved
#define InterlockedExchange16 _InterlockedExchange16
#define InterlockedCompareExchange16 _InterlockedCompareExchange16
#define InterlockedExchange _InterlockedExchange
#define InterlockedCompareExchange _InterlockedCompareExchange
#define InterlockedExchangeAdd _InterlockedExchangeAdd
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4365,7 +4365,7 @@ void CodeGen::genLockedInstructions(GenTreeOp* node)

assert(addr->isUsedFromReg());
assert(data->isUsedFromReg());
assert((size == EA_4BYTE) || (size == EA_PTRSIZE) || (size == EA_GCREF));
assert((size <= EA_PTRSIZE) || (size == EA_GCREF));

genConsumeOperands(node);

Expand Down
22 changes: 18 additions & 4 deletions src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3251,16 +3251,23 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
case NI_System_Threading_Interlocked_CompareExchange:
{
var_types retType = JITtype2varType(sig->retType);
if ((retType == TYP_LONG) && (TARGET_POINTER_SIZE == 4))
if (TARGET_POINTER_SIZE < genTypeSize(retType))
{
break;
}
#if defined(TARGET_RISCV64)
else if (4 > genTypeSize(retType))
{
break;
}
#endif

if ((retType == TYP_REF) && impStackTop(1).val->IsIntegralConst(0))
{
// Intrinsify "object" overload in case of null assignment
// since we don't need the write barrier.
}
else if ((retType != TYP_INT) && (retType != TYP_LONG))
else if (!varTypeIsIntegral(retType))
{
break;
}
Expand All @@ -3286,17 +3293,24 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
assert(sig->numArgs == 2);

var_types retType = JITtype2varType(sig->retType);
if ((retType == TYP_LONG) && (TARGET_POINTER_SIZE == 4))
if (TARGET_POINTER_SIZE < genTypeSize(retType))
{
break;
}
#if defined(TARGET_RISCV64)
else if (4 > genTypeSize(retType))
{
break;
}
#endif

if ((retType == TYP_REF) && impStackTop().val->IsIntegralConst(0))
{
// Intrinsify "object" overload in case of null assignment
// since we don't need the write barrier.
assert(ni == NI_System_Threading_Interlocked_Exchange);
}
else if ((retType != TYP_INT) && (retType != TYP_LONG))
else if (!varTypeIsIntegral(retType))
{
break;
}
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/nativeaot/Runtime/EHHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ EXTERN_C void * RhpAssignRefAVLocation;
EXTERN_C void * RhpCheckedAssignRefAVLocation;
EXTERN_C void * RhpCheckedLockCmpXchgAVLocation;
EXTERN_C void * RhpCheckedXchgAVLocation;
EXTERN_C void * RhpLockCmpXchg8AVLocation;
EXTERN_C void * RhpLockCmpXchg16AVLocation;
EXTERN_C void * RhpLockCmpXchg32AVLocation;
EXTERN_C void * RhpLockCmpXchg64AVLocation;
EXTERN_C void * RhpByRefAssignRefAVLocation1;
Expand All @@ -305,6 +307,8 @@ static bool InWriteBarrierHelper(uintptr_t faultingIP)
(uintptr_t)&RhpCheckedAssignRefAVLocation,
(uintptr_t)&RhpCheckedLockCmpXchgAVLocation,
(uintptr_t)&RhpCheckedXchgAVLocation,
(uintptr_t)&RhpLockCmpXchg8AVLocation,
(uintptr_t)&RhpLockCmpXchg16AVLocation,
(uintptr_t)&RhpLockCmpXchg32AVLocation,
(uintptr_t)&RhpLockCmpXchg64AVLocation,
(uintptr_t)&RhpByRefAssignRefAVLocation1,
Expand Down
12 changes: 12 additions & 0 deletions src/coreclr/nativeaot/Runtime/portable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,18 @@ COOP_PINVOKE_HELPER(Object *, RhpCheckedXchg, (Object ** location, Object * valu
return ret;
}

COOP_PINVOKE_HELPER(uint8_t, RhpLockCmpXchg8, (uint8_t * location, uint8_t value, uint8_t comparand))
{
// @TODO: USE_PORTABLE_HELPERS - Null check
return PalInterlockedCompareExchange(location, value, comparand);
}

COOP_PINVOKE_HELPER(int16_t, RhpLockCmpXchg16, (int16_t * location, int16_t value, int16_t comparand))
{
// @TODO: USE_PORTABLE_HELPERS - Null check
return PalInterlockedCompareExchange(location, value, comparand);
}

COOP_PINVOKE_HELPER(int32_t, RhpLockCmpXchg32, (int32_t * location, int32_t value, int32_t comparand))
{
// @TODO: USE_PORTABLE_HELPERS - Null check
Expand Down
28 changes: 28 additions & 0 deletions src/coreclr/nativeaot/Runtime/unix/PalRedhawkInline.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ FORCEINLINE uint32_t PalInterlockedAnd(_Inout_ uint32_t volatile *pDst, uint32_t
return __sync_and_and_fetch(pDst, iValue);
}

FORCEINLINE uint8_t PalInterlockedExchange8(_Inout_ uint8_t volatile *pDst, uint8_t iValue)
{
#ifdef __clang__
return __sync_swap(pDst, iValue);
#else
return __atomic_exchange_n(pDst, iValue, __ATOMIC_ACQ_REL);
#endif
}

FORCEINLINE int16_t PalInterlockedExchange16(_Inout_ int16_t volatile *pDst, int16_t iValue)
{
#ifdef __clang__
return __sync_swap(pDst, iValue);
#else
return __atomic_exchange_n(pDst, iValue, __ATOMIC_ACQ_REL);
#endif
}

FORCEINLINE int32_t PalInterlockedExchange(_Inout_ int32_t volatile *pDst, int32_t iValue)
{
#ifdef __clang__
Expand All @@ -43,6 +61,16 @@ FORCEINLINE int64_t PalInterlockedExchange64(_Inout_ int64_t volatile *pDst, int
#endif
}

FORCEINLINE uint8_t PalInterlockedCompareExchange8(_Inout_ uint8_t volatile *pDst, uint8_t iValue, uint8_t iComparand)
{
return __sync_val_compare_and_swap(pDst, iComparand, iValue);
}

FORCEINLINE int16_t PalInterlockedCompareExchange16(_Inout_ int16_t volatile *pDst, int16_t iValue, int16_t iComparand)
{
return __sync_val_compare_and_swap(pDst, iComparand, iValue);
}

FORCEINLINE int32_t PalInterlockedCompareExchange(_Inout_ int32_t volatile *pDst, int32_t iValue, int32_t iComparand)
{
return __sync_val_compare_and_swap(pDst, iComparand, iValue);
Expand Down
28 changes: 28 additions & 0 deletions src/coreclr/nativeaot/Runtime/windows/PalRedhawkInline.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,41 @@ FORCEINLINE uint32_t PalInterlockedAnd(_Inout_ uint32_t volatile *pDst, uint32_t
return _InterlockedAnd((long volatile *)pDst, iValue);
}

EXTERN_C unsigned char __PN__MACHINECALL_CDECL_OR_DEFAULT _InterlockedExchange8(unsigned char volatile *, unsigned char);
#pragma intrinsic(_InterlockedExchange)
FORCEINLINE uint8_t PalInterlockedExchange8(_Inout_ uint8_t volatile *pDst, uint8_t iValue)
{
return _InterlockedExchange8((unsigned char volatile *)pDst, iValue);
}

EXTERN_C short __PN__MACHINECALL_CDECL_OR_DEFAULT _InterlockedExchange16(short volatile *, short);
#pragma intrinsic(_InterlockedExchange)
FORCEINLINE int16_t PalInterlockedExchange16(_Inout_ int16_t volatile *pDst, int16_t iValue)
{
return _InterlockedExchange16((short volatile *)pDst, iValue);
}

EXTERN_C long __PN__MACHINECALL_CDECL_OR_DEFAULT _InterlockedExchange(long volatile *, long);
#pragma intrinsic(_InterlockedExchange)
FORCEINLINE int32_t PalInterlockedExchange(_Inout_ int32_t volatile *pDst, int32_t iValue)
{
return _InterlockedExchange((long volatile *)pDst, iValue);
}

EXTERN_C unsigned char __PN__MACHINECALL_CDECL_OR_DEFAULT _InterlockedCompareExchange8(unsigned char volatile *, unsigned char, unsigned char);
#pragma intrinsic(_InterlockedCompareExchange)
FORCEINLINE uint8_t PalInterlockedCompareExchange8(_Inout_ uint8_t volatile *pDst, uint8_t iValue, uint8_t iComparand)
{
return _InterlockedCompareExchange8((unsigned char volatile *)pDst, iValue, iComparand);
}

EXTERN_C short __PN__MACHINECALL_CDECL_OR_DEFAULT _InterlockedCompareExchange16(short volatile *, short, short);
#pragma intrinsic(_InterlockedCompareExchange)
FORCEINLINE int16_t PalInterlockedCompareExchange16(_Inout_ int16_t volatile *pDst, int16_t iValue, int16_t iComparand)
{
return _InterlockedCompareExchange16((short volatile *)pDst, iValue, iComparand);
}

EXTERN_C long __PN__MACHINECALL_CDECL_OR_DEFAULT _InterlockedCompareExchange(long volatile *, long, long);
#pragma intrinsic(_InterlockedCompareExchange)
FORCEINLINE int32_t PalInterlockedCompareExchange(_Inout_ int32_t volatile *pDst, int32_t iValue, int32_t iComparand)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,14 @@ ushort ClrInstanceID
//
// 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,6 +11,18 @@ public static partial class Interlocked
{
#region CompareExchange

[Intrinsic]
public static byte CompareExchange(ref byte location1, byte value, byte comparand)
{
return RuntimeImports.InterlockedCompareExchange(ref location1, value, comparand);
}

[Intrinsic]
public static short CompareExchange(ref short location1, short value, short comparand)
{
return RuntimeImports.InterlockedCompareExchange(ref location1, value, comparand);
}

[Intrinsic]
public static int CompareExchange(ref int location1, int value, int comparand)
{
Expand Down Expand Up @@ -42,6 +54,32 @@ public static long CompareExchange(ref long location1, long value, long comparan

#region Exchange

[Intrinsic]
public static byte Exchange(ref byte location1, byte value)
{
byte oldValue;

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

return oldValue;
}

[Intrinsic]
public static short Exchange(ref short location1, short value)
{
short oldValue;

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

return oldValue;
}

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

--*/
Define_InterlockMethod(
BYTE,
InterlockedExchange8(IN OUT BYTE volatile *Target, BYTE 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 @@ -3683,6 +3697,26 @@ Return Values
The return value is the initial value of the destination.

--*/
Define_InterlockMethod(
LONG,
InterlockedCompareExchange8(IN OUT BYTE volatile *Destination, IN BYTE Exchange, IN BYTE 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(
LONG,
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