text: /*==========================================================================
   *
   *  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
  
  
  // 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 // ! DPNBUILD_ONLYONETHREAD
  
  
  #endif // __DNSLIST_H__
  