+ /* Check for S-List fault
+
+ Explanation: An S-List fault can occur due to a race condition between 2
+ threads simultaneously trying to pop an element from the S-List. After
+ thread 1 has read the pointer to the top element on the S-List it is
+ preempted and thread 2 calls InterlockedPopEntrySlist on the same S-List,
+ removing the top element and freeing it's memory. After that thread 1
+ resumes and tries to read the address of the Next pointer from the top
+ element, which it assumes will be the next top element.
+ But since that memory has been freed, we get a page fault. To handle this
+ race condition, we let thread 1 repeat the operation.
+ We do NOT invoke the page fault handler in this case, since we do not
+ want to trigger any side effects, like paging or a guard page fault.
+
+ Sequence of operations:
+
+ Thread 1 : mov eax, [ebp] <= eax now points to the first element
+ Thread 1 : mov edx, [ebp + 4] <= edx is loaded with Depth and Sequence
+ *** preempted ***
+ Thread 2 : calls InterlockedPopEntrySlist, changing the top element
+ Thread 2 : frees the memory of the element that was popped
+ *** preempted ***
+ Thread 1 : checks if eax is NULL
+ Thread 1 : InterlockedPopEntrySListFault: mov ebx, [eax] <= faults
+
+ To be sure that we are dealing with exactly the case described above, we
+ check whether the ListHeader has changed. If Thread 2 only popped one
+ entry, the Next field in the S-List-header has changed.
+ If after thread 1 has faulted, thread 2 allocates a new element, by
+ chance getting the same address as the previously freed element and
+ pushes it on the list again, we will see the same top element, but the
+ Sequence member of the S-List header has changed. Therefore we check
+ both fields to make sure we catch any concurrent modification of the
+ S-List-header.
+ */
+ if ((TrapFrame->Eip == (ULONG_PTR)ExpInterlockedPopEntrySListFault) ||
+ (TrapFrame->Eip == (ULONG_PTR)KeUserPopEntrySListFault))