libwinpr-interlocked: added support for doubly-linked lists

This commit is contained in:
Marc-André Moreau 2012-10-06 20:19:03 -04:00
parent bf03aff5d1
commit f8b049630f
4 changed files with 222 additions and 17 deletions

View File

@ -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 */

View File

@ -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

View File

@ -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")

View 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;
}