libwinpr-interlocked: added unit tests for interlocked access
This commit is contained in:
parent
a80eeabc48
commit
eb54da8eb5
@ -57,7 +57,7 @@ typedef struct LIST_ENTRY64
|
||||
} LIST_ENTRY64;
|
||||
typedef LIST_ENTRY64 *PLIST_ENTRY64;
|
||||
|
||||
#ifdef _AMD64_
|
||||
#ifdef _WIN64
|
||||
|
||||
typedef struct _SLIST_ENTRY *PSLIST_ENTRY;
|
||||
typedef struct DECLSPEC_ALIGN(16) _SLIST_ENTRY
|
||||
@ -65,24 +65,46 @@ typedef struct DECLSPEC_ALIGN(16) _SLIST_ENTRY
|
||||
PSLIST_ENTRY Next;
|
||||
} SLIST_ENTRY;
|
||||
|
||||
#else /* _AMD64_ */
|
||||
#else /* _WIN64 */
|
||||
|
||||
#define SLIST_ENTRY SINGLE_LIST_ENTRY
|
||||
#define _SLIST_ENTRY _SINGLE_LIST_ENTRY
|
||||
#define PSLIST_ENTRY PSINGLE_LIST_ENTRY
|
||||
|
||||
#endif /* _AMD64_ */
|
||||
#endif /* _WIN64 */
|
||||
|
||||
#if defined(_AMD64_)
|
||||
#ifdef _WIN64
|
||||
|
||||
typedef struct DECLSPEC_ALIGN(16) _SLIST_HEADER
|
||||
typedef union DECLSPEC_ALIGN(16) _SLIST_HEADER
|
||||
{
|
||||
ULONGLONG Alignment;
|
||||
ULONGLONG Region;
|
||||
} SLIST_HEADER;
|
||||
typedef struct _SLIST_HEADER *PSLIST_HEADER;
|
||||
struct
|
||||
{
|
||||
ULONGLONG Alignment;
|
||||
ULONGLONG Region;
|
||||
} DUMMYSTRUCTNAME;
|
||||
|
||||
#else /* _AMD64_ */
|
||||
struct
|
||||
{
|
||||
ULONGLONG Depth:16;
|
||||
ULONGLONG Sequence:9;
|
||||
ULONGLONG NextEntry:39;
|
||||
ULONGLONG HeaderType:1;
|
||||
ULONGLONG Init:1;
|
||||
ULONGLONG Reserved:59;
|
||||
ULONGLONG Region:3;
|
||||
} Header8;
|
||||
|
||||
struct
|
||||
{
|
||||
ULONGLONG Depth:16;
|
||||
ULONGLONG Sequence:48;
|
||||
ULONGLONG HeaderType:1;
|
||||
ULONGLONG Reserved:3;
|
||||
ULONGLONG NextEntry:60;
|
||||
} HeaderX64;
|
||||
} SLIST_HEADER, *PSLIST_HEADER;
|
||||
|
||||
#else /* _WIN64 */
|
||||
|
||||
typedef union _SLIST_HEADER
|
||||
{
|
||||
@ -96,13 +118,13 @@ typedef union _SLIST_HEADER
|
||||
} DUMMYSTRUCTNAME;
|
||||
} SLIST_HEADER, *PSLIST_HEADER;
|
||||
|
||||
#endif /* _AMD64_ */
|
||||
#endif /* _WIN64 */
|
||||
|
||||
WINPR_API VOID InitializeSListHead(PSLIST_HEADER ListHead);
|
||||
|
||||
WINPR_API PSLIST_ENTRY InterlockedPopEntrySList(PSLIST_HEADER ListHead);
|
||||
WINPR_API PSLIST_ENTRY InterlockedPushEntrySList(PSLIST_HEADER ListHead, PSLIST_ENTRY ListEntry);
|
||||
WINPR_API PSLIST_ENTRY InterlockedPushListSListEx(PSLIST_HEADER ListHead, PSLIST_ENTRY List, PSLIST_ENTRY ListEnd, ULONG Count);
|
||||
WINPR_API PSLIST_ENTRY InterlockedPopEntrySList(PSLIST_HEADER ListHead);
|
||||
WINPR_API PSLIST_ENTRY InterlockedFlushSList(PSLIST_HEADER ListHead);
|
||||
|
||||
WINPR_API USHORT QueryDepthSList(PSLIST_HEADER ListHead);
|
||||
@ -113,8 +135,8 @@ WINPR_API LONG InterlockedDecrement(LONG volatile *Addend);
|
||||
WINPR_API LONG InterlockedExchange(LONG volatile *Target, LONG Value);
|
||||
WINPR_API LONG InterlockedExchangeAdd(LONG volatile *Addend, LONG Value);
|
||||
|
||||
WINPR_API LONG InterlockedCompareExchange(LONG volatile *Destination,LONG ExChange, LONG Comperand);
|
||||
WINPR_API LONG64 InterlockedCompareExchange64(LONG64 volatile *Destination, LONG64 ExChange, LONG64 Comperand);
|
||||
WINPR_API LONG InterlockedCompareExchange(LONG volatile *Destination,LONG Exchange, LONG Comperand);
|
||||
WINPR_API LONG64 InterlockedCompareExchange64(LONG64 volatile *Destination, LONG64 Exchange, LONG64 Comperand);
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
@ -27,6 +27,10 @@
|
||||
#endif
|
||||
#endif /* _AMD64_ */
|
||||
|
||||
#ifdef _AMD64_
|
||||
#define _WIN64
|
||||
#endif
|
||||
|
||||
#ifndef DECLSPEC_ALIGN
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(MIDL_PASS)
|
||||
#define DECLSPEC_ALIGN(x) __declspec(align(x))
|
||||
@ -37,11 +41,13 @@
|
||||
#endif
|
||||
#endif /* DECLSPEC_ALIGN */
|
||||
|
||||
#ifdef _AMD64_
|
||||
#ifdef _WIN64
|
||||
#define MEMORY_ALLOCATION_ALIGNMENT 16
|
||||
#else
|
||||
#define MEMORY_ALLOCATION_ALIGNMENT 8
|
||||
#endif
|
||||
|
||||
#define DUMMYSTRUCTNAME s
|
||||
|
||||
#endif /* WINPR_SPEC_H */
|
||||
|
||||
|
@ -44,26 +44,106 @@
|
||||
|
||||
VOID InitializeSListHead(PSLIST_HEADER ListHead)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PSLIST_ENTRY InterlockedPopEntrySList(PSLIST_HEADER ListHead)
|
||||
{
|
||||
return NULL;
|
||||
#ifdef _WIN64
|
||||
ListHead->s.Alignment = 0;
|
||||
ListHead->s.Region = 0;
|
||||
ListHead->Header8.Init = 1;
|
||||
#else
|
||||
ListHead->Alignment = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
PSLIST_ENTRY InterlockedPushEntrySList(PSLIST_HEADER ListHead, PSLIST_ENTRY ListEntry)
|
||||
{
|
||||
return NULL;
|
||||
SLIST_HEADER old;
|
||||
SLIST_HEADER new;
|
||||
|
||||
#ifdef _WIN64
|
||||
new.HeaderX64.NextEntry = (((ULONG_PTR) ListEntry) >> 4);
|
||||
|
||||
do
|
||||
{
|
||||
old = *ListHead;
|
||||
ListEntry->Next = (PSLIST_ENTRY) (((ULONG_PTR) old.HeaderX64.NextEntry) << 4);
|
||||
new.HeaderX64.Depth = old.HeaderX64.Depth + 1;
|
||||
new.HeaderX64.Sequence = old.HeaderX64.Sequence + 1;
|
||||
}
|
||||
while (!InterlockedCompareExchange64((LONG64*) ListHead, new.s.Alignment, old.s.Alignment));
|
||||
|
||||
return (PSLIST_ENTRY) ((ULONG_PTR) old.HeaderX64.NextEntry << 4);
|
||||
#else
|
||||
new.s.Next.Next = entry;
|
||||
|
||||
do
|
||||
{
|
||||
old = *ListHead;
|
||||
ListEntry->Next = old.s.Next.Next;
|
||||
new.s.Depth = old.s.Depth + 1;
|
||||
new.s.Sequence = old.s.Sequence + 1;
|
||||
}
|
||||
while(InterlockedCompareExchange64(&ListHead->Alignment, new.Alignment, old.Alignment) != old.Alignment);
|
||||
|
||||
return old.s.Next.Next;
|
||||
#endif
|
||||
}
|
||||
|
||||
PSLIST_ENTRY InterlockedPushListSListEx(PSLIST_HEADER ListHead, PSLIST_ENTRY List, PSLIST_ENTRY ListEnd, ULONG Count)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PSLIST_ENTRY InterlockedPopEntrySList(PSLIST_HEADER ListHead)
|
||||
{
|
||||
SLIST_HEADER old;
|
||||
SLIST_HEADER new;
|
||||
PSLIST_ENTRY entry;
|
||||
|
||||
#ifdef _WIN64
|
||||
do
|
||||
{
|
||||
old = *ListHead;
|
||||
|
||||
entry = (PSLIST_ENTRY) (((ULONG_PTR) old.HeaderX64.NextEntry) << 4);
|
||||
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
new.HeaderX64.NextEntry = ((ULONG_PTR) entry->Next) >> 4;
|
||||
new.HeaderX64.Depth = old.HeaderX64.Depth - 1;
|
||||
new.HeaderX64.Sequence = old.HeaderX64.Sequence - 1;
|
||||
}
|
||||
while (!InterlockedCompareExchange64((LONG64*) ListHead, new.s.Alignment, old.s.Alignment));
|
||||
#else
|
||||
do
|
||||
{
|
||||
old = *ListHead;
|
||||
|
||||
entry = old.s.Next.Next;
|
||||
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
new.s.Next.Next = entry->Next;
|
||||
new.s.Depth = old.s.Depth - 1;
|
||||
new.s.Sequence = old.s.Sequence + 1;
|
||||
}
|
||||
while(InterlockedCompareExchange64(&ListHead->Alignment, new.Alignment, old.Alignment) != old.Alignment);
|
||||
#endif
|
||||
return entry;
|
||||
}
|
||||
|
||||
PSLIST_ENTRY InterlockedFlushSList(PSLIST_HEADER ListHead)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -102,25 +182,25 @@ LONG InterlockedExchange(LONG volatile *Target, LONG Value)
|
||||
LONG InterlockedExchangeAdd(LONG volatile *Addend, LONG Value)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __sync_add_and_fetch(Addend, Value);
|
||||
return __sync_fetch_and_add(Addend, Value);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
LONG InterlockedCompareExchange(LONG volatile *Destination, LONG ExChange, LONG Comperand)
|
||||
LONG InterlockedCompareExchange(LONG volatile *Destination, LONG Exchange, LONG Comperand)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __sync_val_compare_and_swap(Destination, Comperand, ExChange);
|
||||
return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
LONG64 InterlockedCompareExchange64(LONG64 volatile *Destination, LONG64 ExChange, LONG64 Comperand)
|
||||
LONG64 InterlockedCompareExchange64(LONG64 volatile *Destination, LONG64 Exchange, LONG64 Comperand)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __sync_val_compare_and_swap(Destination, Comperand, ExChange);
|
||||
return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
@ -5,6 +5,7 @@ set(MODULE_PREFIX "TEST_INTERLOCKED")
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS
|
||||
TestInterlockedAccess.c
|
||||
TestInterlockedSList.c)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||
|
164
winpr/libwinpr/interlocked/test/TestInterlockedAccess.c
Normal file
164
winpr/libwinpr/interlocked/test/TestInterlockedAccess.c
Normal file
@ -0,0 +1,164 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/windows.h>
|
||||
#include <winpr/interlocked.h>
|
||||
|
||||
int TestInterlockedAccess(int argc, char* argv[])
|
||||
{
|
||||
int index;
|
||||
LONG* Addend;
|
||||
LONG* Target;
|
||||
LONG oldValue;
|
||||
LONG* Destination;
|
||||
LONGLONG oldValue64;
|
||||
LONGLONG* Destination64;
|
||||
|
||||
/* InterlockedIncrement */
|
||||
|
||||
Addend = _aligned_malloc(sizeof(LONG), sizeof(LONG));
|
||||
|
||||
*Addend = 0;
|
||||
|
||||
for (index = 0; index < 10; index ++)
|
||||
InterlockedIncrement(Addend);
|
||||
|
||||
if (*Addend != 10)
|
||||
{
|
||||
printf("InterlockedIncrement failure: Actual: %d, Expected: %d\n", (int) *Addend, 10);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* InterlockedDecrement */
|
||||
|
||||
for (index = 0; index < 10; index ++)
|
||||
InterlockedDecrement(Addend);
|
||||
|
||||
if (*Addend != 0)
|
||||
{
|
||||
printf("InterlockedDecrement failure: Actual: %d, Expected: %d\n", (int) *Addend, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* InterlockedExchange */
|
||||
|
||||
Target = _aligned_malloc(sizeof(LONG), sizeof(LONG));
|
||||
|
||||
*Target = 0xAA;
|
||||
|
||||
oldValue = InterlockedExchange(Target, 0xFF);
|
||||
|
||||
if (oldValue != 0xAA)
|
||||
{
|
||||
printf("InterlockedExchange failure: Actual: 0x%08X, Expected: 0x%08X\n", (int) oldValue, 0xAA);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*Target != 0xFF)
|
||||
{
|
||||
printf("InterlockedExchange failure: Actual: 0x%08X, Expected: 0x%08X\n", (int) *Target, 0xFF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* InterlockedExchangeAdd */
|
||||
|
||||
*Addend = 25;
|
||||
|
||||
oldValue = InterlockedExchangeAdd(Addend, 100);
|
||||
|
||||
if (oldValue != 25)
|
||||
{
|
||||
printf("InterlockedExchangeAdd failure: Actual: %d, Expected: %d\n", (int) oldValue, 25);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*Addend != 125)
|
||||
{
|
||||
printf("InterlockedExchangeAdd failure: Actual: %d, Expected: %d\n", (int) *Addend, 125);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* InterlockedCompareExchange (*Destination == Comparand) */
|
||||
|
||||
Destination = _aligned_malloc(sizeof(LONG), sizeof(LONG));
|
||||
|
||||
*Destination = 0xAABBCCDD;
|
||||
|
||||
oldValue = InterlockedCompareExchange(Destination, 0xCCDDEEFF, 0xAABBCCDD);
|
||||
|
||||
if (oldValue != 0xAABBCCDD)
|
||||
{
|
||||
printf("InterlockedCompareExchange failure: Actual: 0x%08X, Expected: 0x%08X\n", (int) oldValue, 0xAABBCCDD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*Destination != 0xCCDDEEFF)
|
||||
{
|
||||
printf("InterlockedCompareExchange failure: Actual: 0x%08X, Expected: 0x%08X\n", (int) *Destination, 0xCCDDEEFF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* InterlockedCompareExchange (*Destination != Comparand) */
|
||||
|
||||
*Destination = 0xAABBCCDD;
|
||||
|
||||
oldValue = InterlockedCompareExchange(Destination, 0xCCDDEEFF, 0x66778899);
|
||||
|
||||
if (oldValue != 0xAABBCCDD)
|
||||
{
|
||||
printf("InterlockedCompareExchange failure: Actual: 0x%08X, Expected: 0x%08X\n", (int) oldValue, 0xAABBCCDD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*Destination != 0xAABBCCDD)
|
||||
{
|
||||
printf("InterlockedCompareExchange failure: Actual: 0x%08X, Expected: 0x%08X\n", (int) *Destination, 0xAABBCCDD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* InterlockedCompareExchange64 (*Destination == Comparand) */
|
||||
|
||||
Destination64 = _aligned_malloc(sizeof(LONGLONG), sizeof(LONGLONG));
|
||||
|
||||
*Destination64 = 0x66778899AABBCCDD;
|
||||
|
||||
oldValue64 = InterlockedCompareExchange64(Destination64, 0x8899AABBCCDDEEFF, 0x66778899AABBCCDD);
|
||||
|
||||
if (oldValue64 != 0x66778899AABBCCDD)
|
||||
{
|
||||
printf("InterlockedCompareExchange failure: Actual: %lld, Expected: %lld\n", oldValue64, (LONGLONG) 0x66778899AABBCCDD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*Destination64 != 0x8899AABBCCDDEEFF)
|
||||
{
|
||||
printf("InterlockedCompareExchange failure: Actual: %lld, Expected: %lld\n", *Destination64, (LONGLONG) 0x8899AABBCCDDEEFF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* InterlockedCompareExchange64 (*Destination != Comparand) */
|
||||
|
||||
*Destination64 = 0x66778899AABBCCDD;
|
||||
|
||||
oldValue64 = InterlockedCompareExchange64(Destination64, 0x8899AABBCCDDEEFF, 12345);
|
||||
|
||||
if (oldValue64 != 0x66778899AABBCCDD)
|
||||
{
|
||||
printf("InterlockedCompareExchange failure: Actual: %lld, Expected: %lld\n", oldValue64, (LONGLONG) 0x66778899AABBCCDD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*Destination64 != 0x66778899AABBCCDD)
|
||||
{
|
||||
printf("InterlockedCompareExchange failure: Actual: %lld, Expected: %lld\n", *Destination64, (LONGLONG) 0x66778899AABBCCDD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_aligned_free(Addend);
|
||||
_aligned_free(Target);
|
||||
_aligned_free(Destination);
|
||||
_aligned_free(Destination64);
|
||||
|
||||
return 0;
|
||||
}
|
@ -22,11 +22,12 @@ int TestInterlockedSList(int argc, char* argv[])
|
||||
/* Initialize the list header to a MEMORY_ALLOCATION_ALIGNMENT boundary. */
|
||||
pListHead = (PSLIST_HEADER) _aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
|
||||
|
||||
if( NULL == pListHead )
|
||||
if (!pListHead)
|
||||
{
|
||||
printf("Memory allocation failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
InitializeSListHead(pListHead);
|
||||
|
||||
/* Insert 10 items into the list. */
|
||||
@ -41,7 +42,7 @@ int TestInterlockedSList(int argc, char* argv[])
|
||||
}
|
||||
|
||||
pProgramItem->Signature = Count;
|
||||
pFirstEntry = InterlockedPushEntrySList(pListHead, &(pProgramItem->ItemEntry));
|
||||
pFirstEntry = InterlockedPushEntrySList(pListHead, &(pProgramItem->ItemEntry));
|
||||
}
|
||||
|
||||
/* Remove 10 items from the list and display the signature. */
|
||||
@ -56,7 +57,7 @@ int TestInterlockedSList(int argc, char* argv[])
|
||||
}
|
||||
|
||||
pProgramItem = (PPROGRAM_ITEM) pListEntry;
|
||||
printf("Signature is %d\n", pProgramItem->Signature);
|
||||
printf("Signature is %d\n", (int) pProgramItem->Signature);
|
||||
|
||||
/*
|
||||
* This example assumes that the SLIST_ENTRY structure is the
|
||||
|
Loading…
Reference in New Issue
Block a user