Leaked source code of windows server 2003
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.

197 lines
6.5 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2001-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dnslist.cpp
  6. * Content: DirectPlay implementations of OS SLIST functions
  7. *
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 10/30/2001 masonb Created
  12. * 11/07/2001 vanceo Added InterlockedPushListSList and made DNInitializeSListHead return value on Win64
  13. *
  14. ***************************************************************************/
  15. #include "dncmni.h"
  16. //
  17. // We build separate NT and 9x binaries, but even in the NT binary we can't be sure the system has the
  18. // SLIST functions available since they weren't on Win2k. The only place we can be sure that the SLIST
  19. // functions are available is on 64-bit NT platforms.
  20. //
  21. // Single thread builds don't need interlocked operations, so we don't include use the assembly here.
  22. //
  23. #ifndef DPNBUILD_ONLYONETHREAD
  24. #if defined(_X86_)
  25. __declspec(naked)
  26. DNSLIST_ENTRY* WINAPI DNInterlockedPopEntrySList(DNSLIST_HEADER * ListHead)
  27. {
  28. __asm
  29. {
  30. push ebx
  31. push ebp
  32. mov ebp, dword ptr [esp+0x0C] ; Place ListHead in ebp
  33. mov edx, dword ptr [ebp+0x04] ; Place Depth and Sequence into edx
  34. mov eax, dword ptr [ebp+0x00] ; Place Next into eax
  35. redo:
  36. or eax, eax ; Test eax against zero
  37. jz done ; If 0 return
  38. lea ecx, dword ptr [edx-01] ; ecx = ((Sequence << 16) | Depth) - 1, Depth goes down by one
  39. mov ebx, dword ptr [eax] ; Move Next->Next into ebx
  40. #ifdef DPNBUILD_ONLYONEPROCESSOR
  41. cmpxchg8b qword ptr [ebp] ; Exchange Next out in favor of Next->Next along with Depth and Sequence values
  42. #else // ! DPNBUILD_ONLYONEPROCESSOR
  43. lock cmpxchg8b qword ptr [ebp] ; Exchange Next out in favor of Next->Next along with Depth and Sequence values
  44. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  45. jne redo
  46. done:
  47. pop ebp
  48. pop ebx
  49. #ifdef WINCE
  50. ret
  51. #else // !WINCE
  52. ret 4
  53. #endif // WINCE
  54. }
  55. }
  56. __declspec(naked)
  57. DNSLIST_ENTRY* WINAPI DNInterlockedPushEntrySList(DNSLIST_HEADER * ListHead, DNSLIST_ENTRY * ListEntry)
  58. {
  59. __asm
  60. {
  61. push ebx
  62. push ebp
  63. mov ebp, dword ptr [esp+0x0C] ; Place ListHead in ebp
  64. mov ebx, dword ptr [esp+0x10] ; Place ListEntry in ebx
  65. mov edx, dword ptr [ebp+0x04] ; put ListHead Depth and Sequence into edx
  66. mov eax, dword ptr [ebp+0x00] ; put ListHead->Next into eax
  67. redo:
  68. mov dword ptr [ebx], eax ; set ListEntry->Next to ListHead->Next
  69. lea ecx, dword ptr [edx+0x00010001] ; add 1 to the Depth and Sequence
  70. #ifdef DPNBUILD_ONLYONEPROCESSOR
  71. cmpxchg8b qword ptr [ebp] ; atomically exchange ListHead with ListEntry if ListHead hasn't changed
  72. #else // ! DPNBUILD_ONLYONEPROCESSOR
  73. lock cmpxchg8b qword ptr [ebp] ; atomically exchange ListHead with ListEntry if ListHead hasn't changed
  74. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  75. jne redo ; if the compare failed, try again
  76. pop ebp
  77. pop ebx
  78. #ifdef WINCE
  79. ret
  80. #else // !WINCE
  81. ret 8
  82. #endif // WINCE
  83. }
  84. }
  85. __declspec(naked)
  86. DNSLIST_ENTRY* WINAPI DNInterlockedFlushSList(DNSLIST_HEADER * ListHead)
  87. {
  88. __asm
  89. {
  90. push ebx
  91. push ebp
  92. xor ebx, ebx ; Zero out ebx
  93. mov ebp, dword ptr [esp+0x0C] ; Place ListHead in ebp
  94. mov edx, dword ptr [ebp+0x04] ; Place Depth and Sequence into edx
  95. mov eax, dword ptr [ebp+0x00] ; Place Next into eax
  96. redo:
  97. or eax, eax ; Test eax against zero
  98. jz done ; If 0 return
  99. mov ecx, edx ; Place Depth and Sequence into ecx
  100. mov cx, bx ; Zero out Depth
  101. #ifdef DPNBUILD_ONLYONEPROCESSOR
  102. cmpxchg8b qword ptr [ebp] ; atomically exchange ListHead with ListEntry if ListHead hasn't changed
  103. #else // ! DPNBUILD_ONLYONEPROCESSOR
  104. lock cmpxchg8b qword ptr [ebp] ; atomically exchange ListHead with ListEntry if ListHead hasn't changed
  105. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  106. jne redo ; if the compare failed, try again
  107. done:
  108. pop ebp
  109. pop ebx
  110. #ifdef WINCE
  111. ret
  112. #else // !WINCE
  113. ret 4
  114. #endif // WINCE
  115. }
  116. }
  117. __declspec(naked)
  118. DNSLIST_ENTRY* WINAPI DNInterlockedPushListSList(DNSLIST_HEADER * ListHead, DNSLIST_ENTRY * List, DNSLIST_ENTRY * ListEnd, USHORT Count)
  119. {
  120. __asm
  121. {
  122. push ebx ; save nonvolatile registers
  123. push ebp ;
  124. mov ebp, dword ptr [esp+0x0C] ; save ListHead address
  125. mov ebx, dword ptr [esp+0x10] ; save List address
  126. mov edx,[ebp] + 4 ; get current sequence number
  127. mov eax,[ebp] + 0 ; get current next link
  128. Epshl10:
  129. mov ecx, [esp+0x14] ; Fetch address of ListEnd
  130. mov [ecx], eax ; Store new forward pointer in tail entry
  131. lea ecx, [edx+0x010000] ; increment sequence number
  132. add ecx, [esp+0x18] ; Add in new count to create correct depth
  133. #ifdef DPNBUILD_ONLYONEPROCESSOR
  134. cmpxchg8b qword ptr [ebp] ; compare and exchange
  135. #else // ! DPNBUILD_ONLYONEPROCESSOR
  136. lock cmpxchg8b qword ptr [ebp] ; compare and exchange
  137. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  138. jnz short Epshl10 ; if z clear, exchange failed
  139. pop ebp ; restore nonvolatile registers
  140. pop ebx ;
  141. #ifdef WINCE
  142. ret
  143. #else // !WINCE
  144. ret 16
  145. #endif // WINCE
  146. }
  147. }
  148. #elif defined(_ARM_) || defined(_AMD64_) || defined(_IA64_)
  149. // For now, ARM, IA64 and AMD64 do not have assembly versions of these, and it's important to
  150. // note that while our custom implementation *is* interlocked on those platforms, it is *not* atomic.
  151. // This means that the list won't get corrupted, but the items will not be transferred from the
  152. // source list to the target list in a single interlocked operation. Additionally, the items from the
  153. // source list will be added in reverse order.
  154. DNSLIST_ENTRY* WINAPI DNInterlockedPushListSList(DNSLIST_HEADER * ListHead, DNSLIST_ENTRY * List, DNSLIST_ENTRY * ListEnd, USHORT Count)
  155. {
  156. DNSLIST_ENTRY* pslEntryCurrent;
  157. DNSLIST_ENTRY* pslEntryNext;
  158. DNSLIST_ENTRY* pslEntryReturn = NULL;
  159. pslEntryCurrent = List;
  160. do
  161. {
  162. pslEntryNext = pslEntryCurrent->Next;
  163. DNSLIST_ENTRY* pslEntryTemp = DNInterlockedPushEntrySList(ListHead, pslEntryCurrent);
  164. if (pslEntryReturn == NULL)
  165. {
  166. pslEntryReturn = pslEntryTemp;
  167. }
  168. pslEntryCurrent = pslEntryNext;
  169. }
  170. while (pslEntryCurrent != NULL);
  171. return pslEntryReturn;
  172. }
  173. #else
  174. #error ("No other platform known")
  175. #endif // Platform
  176. #endif // ! DPNBUILD_ONLYONETHREAD