You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
5.0 KiB
165 lines
5.0 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 2001-2002 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: dnslist.h
|
|
* Content: DirectPlay implementations of OS SLIST functions
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 10/30/2001 masonb Created
|
|
* 11/07/2001 vanceo Added InterlockedPushListSList and made DNInitializeSListHead return value on Win64
|
|
*
|
|
***************************************************************************/
|
|
|
|
#ifndef __DNSLIST_H__
|
|
#define __DNSLIST_H__
|
|
|
|
// We build separate NT and 9x binaries, but even in the NT binary we can't be sure the system has the
|
|
// SLIST functions available since they weren't on Win2k. The only place we can be sure that the SLIST
|
|
// functions are available is on 64-bit NT platforms.
|
|
// We don't supply a DNQueryDepthSList method because not all platforms can support it.
|
|
|
|
// SINGLE_LIST_ENTRY is defined in winnt.h and contains only a Next pointer
|
|
// to another SINGLE_LIST_ENTRY
|
|
#if defined(WINCE) || defined(DPNBUILD_ONLYONETHREAD)
|
|
#define SLIST_ENTRY SINGLE_LIST_ENTRY
|
|
#endif // WINCE or DPNBUILD_ONLYONETHREAD
|
|
|
|
#define DNSLIST_ENTRY SLIST_ENTRY
|
|
|
|
#ifdef DPNBUILD_ONLYONETHREAD
|
|
#ifndef XBOX_ON_DESKTOP
|
|
typedef struct _SLIST_HEADER
|
|
{
|
|
DNSLIST_ENTRY Next;
|
|
} SLIST_HEADER;
|
|
#endif // ! XBOX_ON_DESKTOP
|
|
#else // ! DPNBUILD_ONLYONETHREAD
|
|
#ifdef WINCE
|
|
#ifdef _X86_
|
|
typedef union _SLIST_HEADER {
|
|
ULONGLONG Alignment;
|
|
struct {
|
|
DNSLIST_ENTRY Next;
|
|
WORD Depth;
|
|
WORD Sequence;
|
|
};
|
|
} SLIST_HEADER;
|
|
#elif _ARM_
|
|
typedef struct _SLIST_HEADER
|
|
{
|
|
DNSLIST_ENTRY Next;
|
|
} SLIST_HEADER;
|
|
#endif // _X86_ or _ARM_
|
|
#endif // WINCE
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
|
|
#define DNSLIST_HEADER SLIST_HEADER
|
|
|
|
|
|
|
|
#ifdef DPNBUILD_ONLYONETHREAD
|
|
|
|
// Single thread builds don't need the operations to be interlocked.
|
|
|
|
#define DNInitializeSListHead(head) (head)->Next.Next = NULL
|
|
|
|
inline DNSLIST_ENTRY* DNInterlockedPopEntrySList(DNSLIST_HEADER * ListHead)
|
|
{
|
|
DNSLIST_ENTRY* pslEntryReturn;
|
|
|
|
|
|
pslEntryReturn = ListHead->Next.Next;
|
|
if (pslEntryReturn != NULL)
|
|
{
|
|
ListHead->Next.Next = pslEntryReturn->Next;
|
|
}
|
|
|
|
return pslEntryReturn;
|
|
}
|
|
|
|
inline DNSLIST_ENTRY* DNInterlockedPushEntrySList(DNSLIST_HEADER * ListHead, DNSLIST_ENTRY * ListEntry)
|
|
{
|
|
DNSLIST_ENTRY* pslEntryReturn;
|
|
|
|
|
|
pslEntryReturn = ListHead->Next.Next;
|
|
ListEntry->Next = pslEntryReturn;
|
|
ListHead->Next.Next = ListEntry;
|
|
|
|
return pslEntryReturn;
|
|
}
|
|
|
|
inline DNSLIST_ENTRY* DNInterlockedFlushSList(DNSLIST_HEADER * ListHead)
|
|
{
|
|
DNSLIST_ENTRY* pslEntryReturn;
|
|
|
|
|
|
pslEntryReturn = ListHead->Next.Next;
|
|
ListHead->Next.Next = NULL;
|
|
|
|
return pslEntryReturn;
|
|
}
|
|
|
|
inline DNSLIST_ENTRY* DNInterlockedPushListSList(DNSLIST_HEADER * ListHead, DNSLIST_ENTRY * List, DNSLIST_ENTRY * ListEnd, USHORT Count)
|
|
{
|
|
DNSLIST_ENTRY* pslEntryReturn;
|
|
|
|
|
|
pslEntryReturn = ListHead->Next.Next;
|
|
ListEnd->Next = pslEntryReturn;
|
|
ListHead->Next.Next = List;
|
|
|
|
return pslEntryReturn;
|
|
}
|
|
|
|
#else // ! DPNBUILD_ONLYONETHREAD
|
|
|
|
|
|
#if defined(_WIN64)
|
|
|
|
// _WIN64 has always had these available, so just use them directly
|
|
#define DNInitializeSListHead InitializeSListHead
|
|
#define DNInterlockedPopEntrySList InterlockedPopEntrySList
|
|
#define DNInterlockedPushEntrySList InterlockedPushEntrySList
|
|
#define DNInterlockedFlushSList InterlockedFlushSList
|
|
|
|
#elif defined(WINCE) && defined(_ARM_)
|
|
|
|
#define InterlockedPushList \
|
|
((void *(*)(void *pHead, void *pItem))(PUserKData+0x398))
|
|
#define InterlockedPopList \
|
|
((void *(*)(void *pHead))(PUserKData+0x380))
|
|
|
|
#define DNInitializeSListHead(head) (head)->Next.Next = NULL
|
|
#define DNInterlockedPopEntrySList (DNSLIST_ENTRY*)InterlockedPopList
|
|
#define DNInterlockedPushEntrySList (DNSLIST_ENTRY*)InterlockedPushList
|
|
#define DNInterlockedFlushSList(head) (DNSLIST_ENTRY*)DNInterlockedExchange((LONG*)(head), 0)
|
|
|
|
#elif defined(_X86_)
|
|
|
|
#define DNInitializeSListHead(ListHead) (ListHead)->Alignment = 0
|
|
DNSLIST_ENTRY* WINAPI DNInterlockedPopEntrySList(DNSLIST_HEADER * ListHead);
|
|
DNSLIST_ENTRY* WINAPI DNInterlockedPushEntrySList(DNSLIST_HEADER * ListHead, DNSLIST_ENTRY * ListEntry);
|
|
DNSLIST_ENTRY* WINAPI DNInterlockedFlushSList(DNSLIST_HEADER * ListHead);
|
|
|
|
#else
|
|
#error("Unknown platform")
|
|
#endif // Platform
|
|
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
|
|
|
|
// Unfortunately no platform has this exposed to user-mode.
|
|
//
|
|
// For now, ARM, IA64 and AMD64 do not have assembly versions of these, and it's important to
|
|
// note that while our custom implementation *is* interlocked on those platforms, it is *not* atomic.
|
|
// This means that the list won't get corrupted, but the items will not be transferred from the
|
|
// source list to the target list in a single interlocked operation. Additionally, the items from the
|
|
// source list will be added in reverse order.
|
|
DNSLIST_ENTRY* WINAPI DNInterlockedPushListSList(DNSLIST_HEADER * ListHead, DNSLIST_ENTRY * List, DNSLIST_ENTRY * ListEnd, USHORT Count);
|
|
|
|
|
|
#endif // __DNSLIST_H__
|