Source code of Windows XP (NT5)
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
3.6 KiB

  1. if NT_INST
  2. else
  3. TITLE "Spin Locks"
  4. ;++
  5. ;
  6. ; Copyright (c) 1989 Microsoft Corporation
  7. ;
  8. ; Module Name:
  9. ;
  10. ; spindbg.asm
  11. ;
  12. ; Abstract:
  13. ;
  14. ; Author:
  15. ;
  16. ; Bryan Willman (bryanwi) 13 Dec 89
  17. ;
  18. ; Environment:
  19. ;
  20. ; Kernel mode only.
  21. ;
  22. ; Revision History:
  23. ;
  24. ;--
  25. PAGE
  26. .386p
  27. include ks386.inc
  28. include callconv.inc ; calling convention macros
  29. include mac386.inc
  30. if DBG
  31. EXTRNP _KeBugCheckEx,5
  32. EXTRNP _KeGetCurrentIrql,0,IMPORT
  33. ifdef DBGMP
  34. EXTRNP _KiPollDebugger,0
  35. endif
  36. extrn _KeTickCount:DWORD
  37. extrn _KiSpinlockTimeout:DWORD
  38. endif
  39. _TEXT$00 SEGMENT DWORD PUBLIC 'CODE'
  40. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  41. ;++
  42. ;
  43. ; VOID
  44. ; Kii386SpinOnSpinLock (
  45. ; IN PKSPIN_LOCK SpinLock
  46. ; IN ULONG Flag
  47. ; )
  48. ;
  49. ; Routine Description:
  50. ;
  51. ; This function is called on a debug build to spin on a spinlock.
  52. ; It is invoked by the DEBUG version of SPIN_ON_SPINLOCK macro.
  53. ;
  54. ; Warning:
  55. ;
  56. ; Not called with C calling conventions
  57. ; Does not destroy any register
  58. ;
  59. ;--
  60. cPublicProc Kii386SpinOnSpinLock,2
  61. if DBG
  62. cPublicFpo 2,2
  63. push eax
  64. push ebx
  65. mov eax, [esp+12] ; (eax) = LockAddress
  66. mov ebx, PCR[PcPrcbData.PbCurrentThread]
  67. or ebx, 1 ; or on busy bit
  68. cmp ebx, [eax] ; current thread the owner?
  69. je short ssl_sameid ; Yes, go abort
  70. ssl_10:
  71. mov ebx, _KeTickCount ; Current time
  72. add ebx, _KiSpinlockTimeout ; wait n ticks
  73. ifdef DBGMP
  74. test byte ptr [esp+16], 2 ; poll debugger while waiting?
  75. jnz short ssl_30
  76. endif
  77. ;
  78. ; Spin while watching KeTickCount
  79. ;
  80. ssl_20: YIELD
  81. cmp _KeTickCount, ebx ; check current time
  82. jnc short ssl_timeout ; NC, too many ticks have gone by
  83. test dword ptr [eax], 1
  84. jnz short ssl_20
  85. ssl_exit:
  86. pop ebx ; Spinlock is not busy, return
  87. pop eax
  88. stdRET Kii386SpinOnSpinLock
  89. ifdef DBGMP
  90. ;
  91. ; Spin while watching KeTickCount & poll debugger
  92. ;
  93. ssl_30: YIELD
  94. cmp _KeTickCount, ebx ; check current time
  95. jnc short ssl_timeout ; overflowed
  96. stdCall _KiPollDebugger
  97. test dword ptr [eax], 1
  98. jnz short ssl_30
  99. pop ebx ; Spinlock is not busy, return
  100. pop eax
  101. stdRET Kii386SpinOnSpinLock
  102. endif
  103. ;
  104. ; Out of line expection conditions
  105. ;
  106. ssl_sameid:
  107. test byte ptr [esp+16], 1 ; ID check enabled?
  108. jz short ssl_10 ; no, continue
  109. ; recursed on lock, abort
  110. stdCall _KeBugCheckEx,<SPIN_LOCK_ALREADY_OWNED,eax,0,0,0>
  111. ssl_timeout:
  112. test byte ptr [esp+16], 4 ; Timeout check enabled?
  113. jz short ssl_10 ; no, continue
  114. stdCall _KeGetCurrentIrql ; Check to see what level we're spinning at
  115. cmp al, DISPATCH_LEVEL
  116. mov eax, [esp+12] ; restore eax
  117. jc short ssl_10 ; if < dispatch_level, don't timeout
  118. test dword ptr [eax], 1 ; Check to see if spinlock was freed
  119. jz short ssl_exit
  120. public SpinLockSpinningForTooLong
  121. SpinLockSpinningForTooLong:
  122. int 3 ; Stop here
  123. jmp short ssl_10 ; re-wait
  124. else ; DBG
  125. stdRET Kii386SpinOnSpinLock
  126. endif
  127. stdENDP Kii386SpinOnSpinLock,2
  128. _TEXT$00 ends
  129. endif ; NT_INST
  130. end