/**
* WinPR: Windows Portable Runtime
* Interlocked Singly-Linked Lists
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_INTERLOCKED_H
#define WINPR_INTERLOCKED_H
#include <winpr/spec.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/platform.h>
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef _WIN32
#ifndef CONTAINING_RECORD
#define CONTAINING_RECORD(address, type, field) \
((type*)(((ULONG_PTR)address) - (ULONG_PTR)(&(((type*)0)->field))))
#endif
typedef struct _WINPR_LIST_ENTRY WINPR_LIST_ENTRY;
typedef struct _WINPR_LIST_ENTRY* WINPR_PLIST_ENTRY;
struct _WINPR_LIST_ENTRY
{
WINPR_PLIST_ENTRY Flink;
WINPR_PLIST_ENTRY Blink;
};
typedef struct _WINPR_SINGLE_LIST_ENTRY WINPR_SINGLE_LIST_ENTRY;
typedef struct _WINPR_SINGLE_LIST_ENTRY* WINPR_PSINGLE_LIST_ENTRY;
struct _WINPR_SINGLE_LIST_ENTRY
{
WINPR_PSINGLE_LIST_ENTRY Next;
};
typedef struct WINPR_LIST_ENTRY32
{
DWORD Flink;
DWORD Blink;
} WINPR_LIST_ENTRY32;
typedef WINPR_LIST_ENTRY32* WINPR_PLIST_ENTRY32;
typedef struct WINPR_LIST_ENTRY64
{
ULONGLONG Flink;
ULONGLONG Blink;
} WINPR_LIST_ENTRY64;
typedef WINPR_LIST_ENTRY64* WINPR_PLIST_ENTRY64;
#ifdef _WIN64
typedef struct _WINPR_SLIST_ENTRY* WINPR_PSLIST_ENTRY;
typedef struct DECLSPEC_ALIGN(16) _WINPR_SLIST_ENTRY
{
WINPR_PSLIST_ENTRY Next;
} WINPR_SLIST_ENTRY;
#else /* _WIN64 */
#define WINPR_SLIST_ENTRY WINPR_SINGLE_LIST_ENTRY
#define _WINPR_SLIST_ENTRY _WINPR_SINGLE_LIST_ENTRY
#define WINPR_PSLIST_ENTRY WINPR_PSINGLE_LIST_ENTRY
#endif /* _WIN64 */
#ifdef _WIN64
typedef union DECLSPEC_ALIGN(16) _WINPR_SLIST_HEADER {
struct
{
ULONGLONG Alignment;
ULONGLONG Region;
} DUMMYSTRUCTNAME;
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;
} WINPR_SLIST_HEADER, *WINPR_PSLIST_HEADER;
#else /* _WIN64 */
typedef union _WINPR_SLIST_HEADER {
ULONGLONG Alignment;
struct
{
WINPR_SLIST_ENTRY Next;
WORD Depth;
WORD Sequence;
} DUMMYSTRUCTNAME;
} WINPR_SLIST_HEADER, *WINPR_PSLIST_HEADER;
#endif /* _WIN64 */
/* Singly-Linked List */
WINPR_API VOID InitializeSListHead(WINPR_PSLIST_HEADER ListHead);
WINPR_API WINPR_PSLIST_ENTRY InterlockedPushEntrySList(WINPR_PSLIST_HEADER ListHead,
WINPR_PSLIST_ENTRY ListEntry);
WINPR_API WINPR_PSLIST_ENTRY InterlockedPushListSListEx(WINPR_PSLIST_HEADER ListHead,
WINPR_PSLIST_ENTRY List,
WINPR_PSLIST_ENTRY ListEnd,
ULONG Count);
WINPR_API WINPR_PSLIST_ENTRY InterlockedPopEntrySList(WINPR_PSLIST_HEADER ListHead);
WINPR_API WINPR_PSLIST_ENTRY InterlockedFlushSList(WINPR_PSLIST_HEADER ListHead);
WINPR_API USHORT QueryDepthSList(WINPR_PSLIST_HEADER ListHead);
WINPR_API LONG InterlockedIncrement(LONG volatile* Addend);
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 PVOID InterlockedCompareExchangePointer(PVOID volatile* Destination, PVOID Exchange,
PVOID Comperand);
#else /* _WIN32 */
#define WINPR_LIST_ENTRY LIST_ENTRY
#define _WINPR_LIST_ENTRY _LIST_ENTRY
#define WINPR_PLIST_ENTRY PLIST_ENTRY
#define WINPR_SINGLE_LIST_ENTRY SINGLE_LIST_ENTRY
#define _WINPR_SINGLE_LIST_ENTRY _SINGLE_LIST_ENTRY
#define WINPR_PSINGLE_LIST_ENTRY PSINGLE_LIST_ENTRY
#define WINPR_SLIST_ENTRY SLIST_ENTRY
#define _WINPR_SLIST_ENTRY _SLIST_ENTRY
#define WINPR_PSLIST_ENTRY PSLIST_ENTRY
#define WINPR_SLIST_HEADER SLIST_HEADER
#define _WINPR_SLIST_HEADER _SLIST_HEADER
#define WINPR_PSLIST_HEADER PSLIST_HEADER
#endif /* _WIN32 */
#if (!defined(_WIN32) || \
(defined(_WIN32) && (_WIN32_WINNT < 0x0502) && !defined(InterlockedCompareExchange64)))
#define WINPR_INTERLOCKED_COMPARE_EXCHANGE64 1
#endif
#ifdef WINPR_INTERLOCKED_COMPARE_EXCHANGE64
WINPR_API LONGLONG InterlockedCompareExchange64(LONGLONG volatile* Destination,
LONGLONG Exchange, LONGLONG Comperand);
#endif
/* Doubly-Linked List */
WINPR_API VOID InitializeListHead(WINPR_PLIST_ENTRY ListHead);
WINPR_API BOOL IsListEmpty(const WINPR_LIST_ENTRY* ListHead);
WINPR_API BOOL RemoveEntryList(WINPR_PLIST_ENTRY Entry);
WINPR_API VOID InsertHeadList(WINPR_PLIST_ENTRY ListHead, WINPR_PLIST_ENTRY Entry);
WINPR_API WINPR_PLIST_ENTRY RemoveHeadList(WINPR_PLIST_ENTRY ListHead);
WINPR_API VOID InsertTailList(WINPR_PLIST_ENTRY ListHead, WINPR_PLIST_ENTRY Entry);
WINPR_API WINPR_PLIST_ENTRY RemoveTailList(WINPR_PLIST_ENTRY ListHead);
WINPR_API VOID AppendTailList(WINPR_PLIST_ENTRY ListHead, WINPR_PLIST_ENTRY ListToAppend);
WINPR_API VOID PushEntryList(WINPR_PSINGLE_LIST_ENTRY ListHead, WINPR_PSINGLE_LIST_ENTRY Entry);
WINPR_API WINPR_PSINGLE_LIST_ENTRY PopEntryList(WINPR_PSINGLE_LIST_ENTRY ListHead);
#ifdef __cplusplus
}
#endif
#endif /* WINPR_INTERLOCKED_H */