libwinpr-interlocked: added support for doubly-linked lists
This commit is contained in:
parent
bf03aff5d1
commit
f8b049630f
@ -26,6 +26,11 @@
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#ifndef CONTAINING_RECORD
|
||||
#define CONTAINING_RECORD(address, type, field) \
|
||||
((type *)(((ULONG_PTR) address) - (ULONG_PTR)(&(((type *) 0)->field))))
|
||||
#endif
|
||||
|
||||
typedef struct _LIST_ENTRY LIST_ENTRY;
|
||||
typedef struct _LIST_ENTRY* PLIST_ENTRY;
|
||||
|
||||
@ -120,6 +125,8 @@ typedef union _SLIST_HEADER
|
||||
|
||||
#endif /* _WIN64 */
|
||||
|
||||
/* Singly-Linked List */
|
||||
|
||||
WINPR_API VOID InitializeSListHead(PSLIST_HEADER ListHead);
|
||||
|
||||
WINPR_API PSLIST_ENTRY InterlockedPushEntrySList(PSLIST_HEADER ListHead, PSLIST_ENTRY ListEntry);
|
||||
@ -141,5 +148,27 @@ WINPR_API LONG InterlockedCompareExchange(LONG volatile *Destination, LONG Excha
|
||||
|
||||
WINPR_API LONGLONG InterlockedCompareExchange64(LONGLONG volatile *Destination, LONGLONG Exchange, LONGLONG Comperand);
|
||||
|
||||
/* Doubly-Linked List */
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
VOID InitializeListHead(PLIST_ENTRY ListHead);
|
||||
|
||||
BOOL IsListEmpty(const LIST_ENTRY* ListHead);
|
||||
|
||||
BOOL RemoveEntryList(PLIST_ENTRY Entry);
|
||||
|
||||
VOID InsertHeadList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry);
|
||||
PLIST_ENTRY RemoveHeadList(PLIST_ENTRY ListHead);
|
||||
|
||||
VOID InsertTailList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry);
|
||||
PLIST_ENTRY RemoveTailList(PLIST_ENTRY ListHead);
|
||||
VOID AppendTailList(PLIST_ENTRY ListHead, PLIST_ENTRY ListToAppend);
|
||||
|
||||
VOID PushEntryList(PSINGLE_LIST_ENTRY ListHead, PSINGLE_LIST_ENTRY Entry);
|
||||
PSINGLE_LIST_ENTRY PopEntryList(PSINGLE_LIST_ENTRY ListHead);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* WINPR_INTERLOCKED_H */
|
||||
|
||||
|
@ -26,22 +26,7 @@
|
||||
|
||||
#include <winpr/interlocked.h>
|
||||
|
||||
/**
|
||||
* api-ms-win-core-interlocked-l1-2-0.dll:
|
||||
*
|
||||
* InitializeSListHead
|
||||
* InterlockedPopEntrySList
|
||||
* InterlockedPushEntrySList
|
||||
* InterlockedPushListSListEx
|
||||
* InterlockedFlushSList
|
||||
* QueryDepthSList
|
||||
* InterlockedIncrement
|
||||
* InterlockedDecrement
|
||||
* InterlockedExchange
|
||||
* InterlockedExchangeAdd
|
||||
* InterlockedCompareExchange
|
||||
* InterlockedCompareExchange64
|
||||
*/
|
||||
/* Singly-Linked List */
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
@ -299,3 +284,115 @@ LONGLONG InterlockedCompareExchange64(LONGLONG volatile *Destination, LONGLONG E
|
||||
|
||||
#endif /* (_WIN32 && (_WIN32_WINNT < 0x0502)) */
|
||||
|
||||
/* Doubly-Linked List */
|
||||
|
||||
/**
|
||||
* Kernel-Mode Basics: Windows Linked Lists:
|
||||
* http://www.osronline.com/article.cfm?article=499
|
||||
*
|
||||
* Singly and Doubly Linked Lists:
|
||||
* http://msdn.microsoft.com/en-us/library/windows/hardware/ff563802/
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
VOID InitializeListHead(PLIST_ENTRY ListHead)
|
||||
{
|
||||
ListHead->Flink = ListHead->Blink = ListHead;
|
||||
}
|
||||
|
||||
BOOL IsListEmpty(const LIST_ENTRY* ListHead)
|
||||
{
|
||||
return (BOOL) (ListHead->Flink == ListHead);
|
||||
}
|
||||
|
||||
BOOL RemoveEntryList(PLIST_ENTRY Entry)
|
||||
{
|
||||
PLIST_ENTRY OldFlink;
|
||||
PLIST_ENTRY OldBlink;
|
||||
|
||||
OldFlink = Entry->Flink;
|
||||
OldBlink = Entry->Blink;
|
||||
OldFlink->Blink = OldBlink;
|
||||
OldBlink->Flink = OldFlink;
|
||||
|
||||
return (BOOL) (OldFlink == OldBlink);
|
||||
}
|
||||
|
||||
VOID InsertHeadList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry)
|
||||
{
|
||||
PLIST_ENTRY OldFlink;
|
||||
|
||||
OldFlink = ListHead->Flink;
|
||||
Entry->Flink = OldFlink;
|
||||
Entry->Blink = ListHead;
|
||||
OldFlink->Blink = Entry;
|
||||
ListHead->Flink = Entry;
|
||||
}
|
||||
|
||||
PLIST_ENTRY RemoveHeadList(PLIST_ENTRY ListHead)
|
||||
{
|
||||
PLIST_ENTRY Flink;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
Entry = ListHead->Flink;
|
||||
Flink = Entry->Flink;
|
||||
ListHead->Flink = Flink;
|
||||
Flink->Blink = ListHead;
|
||||
|
||||
return Entry;
|
||||
}
|
||||
|
||||
VOID InsertTailList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry)
|
||||
{
|
||||
PLIST_ENTRY OldBlink;
|
||||
|
||||
OldBlink = ListHead->Blink;
|
||||
Entry->Flink = ListHead;
|
||||
Entry->Blink = OldBlink;
|
||||
OldBlink->Flink = Entry;
|
||||
ListHead->Blink = Entry;
|
||||
}
|
||||
|
||||
PLIST_ENTRY RemoveTailList(PLIST_ENTRY ListHead)
|
||||
{
|
||||
PLIST_ENTRY Blink;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
Entry = ListHead->Blink;
|
||||
Blink = Entry->Blink;
|
||||
ListHead->Blink = Blink;
|
||||
Blink->Flink = ListHead;
|
||||
|
||||
return Entry;
|
||||
}
|
||||
|
||||
VOID AppendTailList(PLIST_ENTRY ListHead, PLIST_ENTRY ListToAppend)
|
||||
{
|
||||
PLIST_ENTRY ListEnd = ListHead->Blink;
|
||||
|
||||
ListHead->Blink->Flink = ListToAppend;
|
||||
ListHead->Blink = ListToAppend->Blink;
|
||||
ListToAppend->Blink->Flink = ListHead;
|
||||
ListToAppend->Blink = ListEnd;
|
||||
}
|
||||
|
||||
VOID PushEntryList(PSINGLE_LIST_ENTRY ListHead, PSINGLE_LIST_ENTRY Entry)
|
||||
{
|
||||
Entry->Next = ListHead->Next;
|
||||
ListHead->Next = Entry;
|
||||
}
|
||||
|
||||
PSINGLE_LIST_ENTRY PopEntryList(PSINGLE_LIST_ENTRY ListHead)
|
||||
{
|
||||
PSINGLE_LIST_ENTRY FirstEntry;
|
||||
|
||||
FirstEntry = ListHead->Next;
|
||||
|
||||
if (FirstEntry != NULL)
|
||||
ListHead->Next = FirstEntry->Next;
|
||||
|
||||
return FirstEntry;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -6,7 +6,8 @@ set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS
|
||||
TestInterlockedAccess.c
|
||||
TestInterlockedSList.c)
|
||||
TestInterlockedSList.c
|
||||
TestInterlockedDList.c)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||
${${MODULE_PREFIX}_DRIVER}
|
||||
@ -22,3 +23,4 @@ foreach(test ${${MODULE_PREFIX}_TESTS})
|
||||
endforeach()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")
|
||||
|
||||
|
77
winpr/libwinpr/interlocked/test/TestInterlockedDList.c
Normal file
77
winpr/libwinpr/interlocked/test/TestInterlockedDList.c
Normal file
@ -0,0 +1,77 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/windows.h>
|
||||
#include <winpr/interlocked.h>
|
||||
|
||||
typedef struct _LIST_ITEM
|
||||
{
|
||||
LIST_ENTRY ItemEntry;
|
||||
ULONG Signature;
|
||||
} LIST_ITEM, *PLIST_ITEM;
|
||||
|
||||
int TestInterlockedDList(int argc, char* argv[])
|
||||
{
|
||||
ULONG Count;
|
||||
PLIST_ITEM pListItem;
|
||||
PLIST_ENTRY pListHead;
|
||||
PLIST_ENTRY pListEntry;
|
||||
|
||||
pListHead = (PLIST_ENTRY) _aligned_malloc(sizeof(LIST_ENTRY), MEMORY_ALLOCATION_ALIGNMENT);
|
||||
|
||||
if (!pListHead)
|
||||
{
|
||||
printf("Memory allocation failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
InitializeListHead(pListHead);
|
||||
|
||||
if (!IsListEmpty(pListHead))
|
||||
{
|
||||
printf("Expected empty list\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* InsertHeadList / RemoveHeadList */
|
||||
|
||||
printf("InsertHeadList / RemoveHeadList\n");
|
||||
|
||||
for (Count = 1; Count <= 10; Count += 1)
|
||||
{
|
||||
pListItem = (PLIST_ITEM) _aligned_malloc(sizeof(LIST_ITEM), MEMORY_ALLOCATION_ALIGNMENT);
|
||||
pListItem->Signature = Count;
|
||||
InsertHeadList(pListHead, &(pListItem->ItemEntry));
|
||||
}
|
||||
|
||||
for (Count = 10; Count >= 1; Count -= 1)
|
||||
{
|
||||
pListEntry = RemoveHeadList(pListHead);
|
||||
pListItem = (PLIST_ITEM) pListEntry;
|
||||
_aligned_free(pListEntry);
|
||||
}
|
||||
|
||||
/* InsertTailList / RemoveTailList */
|
||||
|
||||
printf("InsertTailList / RemoveTailList\n");
|
||||
|
||||
for (Count = 1; Count <= 10; Count += 1)
|
||||
{
|
||||
pListItem = (PLIST_ITEM) _aligned_malloc(sizeof(LIST_ITEM), MEMORY_ALLOCATION_ALIGNMENT);
|
||||
pListItem->Signature = Count;
|
||||
InsertTailList(pListHead, &(pListItem->ItemEntry));
|
||||
}
|
||||
|
||||
for (Count = 10; Count >= 1; Count -= 1)
|
||||
{
|
||||
pListEntry = RemoveTailList(pListHead);
|
||||
pListItem = (PLIST_ITEM) pListEntry;
|
||||
_aligned_free(pListEntry);
|
||||
}
|
||||
|
||||
_aligned_free(pListHead);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user