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.
561 lines
14 KiB
561 lines
14 KiB
title "Interlocked Support"
|
|
;++
|
|
;
|
|
; Copyright (c) 1996 Microsoft Corporation
|
|
;
|
|
; Module Name:
|
|
;
|
|
; slist.asm
|
|
;
|
|
; Abstract:
|
|
;
|
|
; This module implements functions to support interlocked S-List
|
|
; operations.
|
|
;
|
|
; Author:
|
|
;
|
|
; David N. Cutler (davec) 13-Mar-1996
|
|
;
|
|
; Environment:
|
|
;
|
|
; Any mode.
|
|
;
|
|
; Revision History:
|
|
;
|
|
;--
|
|
.386p
|
|
.xlist
|
|
include ks386.inc
|
|
include callconv.inc ; calling convention macros
|
|
include mac386.inc
|
|
.list
|
|
|
|
|
|
_TEXT$00 SEGMENT DWORD PUBLIC 'CODE'
|
|
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
|
|
|
|
page , 132
|
|
subttl "Interlocked Flush Sequenced List"
|
|
;++
|
|
;
|
|
; PSINGLE_LIST_ENTRY
|
|
; FASTCALL
|
|
; RtlpInterlockedFlushSList (
|
|
; IN PSINGLE_LIST_ENTRY ListHead
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This function removes the entire list from a sequenced singly
|
|
; linked list so that access to the list is synchronized in an MP system.
|
|
; If there are no entries in the list, then a value of NULL is returned.
|
|
; Otherwise, the address of the entry at the top of the list is removed
|
|
; and returned as the function value and the list header is set to point
|
|
; to NULL.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; (ecx) = ListHead - Supplies a pointer to the sequenced listhead from
|
|
; which the list is to be flushed.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; The address of the entire current list, or NULL if the list is
|
|
; empty.
|
|
;
|
|
;--
|
|
|
|
;
|
|
; These old interfaces just fall into the new ones
|
|
;
|
|
cPublicFastCall ExInterlockedFlushSList, 1
|
|
fstENDP ExInterlockedFlushSList
|
|
|
|
cPublicFastCall RtlpInterlockedFlushSList, 1
|
|
|
|
cPublicFpo 0,1
|
|
|
|
;
|
|
; Save nonvolatile registers and read the listhead sequence number followed
|
|
; by the listhead next link.
|
|
;
|
|
; N.B. These two dwords MUST be read exactly in this order.
|
|
;
|
|
|
|
push ebx ; save nonvolatile registers
|
|
push ebp ;
|
|
xor ebx, ebx ; zero out new pointer
|
|
mov ebp, ecx ; save listhead address
|
|
mov edx, [ebp] + 4 ; get current sequence number
|
|
mov eax, [ebp] + 0 ; get current next link
|
|
|
|
;
|
|
; N.B. The following code is the retry code should the compare
|
|
; part of the compare exchange operation fail
|
|
;
|
|
; If the list is empty, then there is nothing that can be removed.
|
|
;
|
|
|
|
Efls10: or eax, eax ; check if list is empty
|
|
jz short Efls20 ; if z set, list is empty
|
|
mov ecx, edx ; copy sequence number
|
|
mov cx, bx ; clear depth leaving sequence number
|
|
|
|
.586
|
|
ifndef NT_UP
|
|
|
|
lock cmpxchg8b qword ptr [ebp] ; compare and exchange
|
|
|
|
else
|
|
|
|
cmpxchg8b qword ptr [ebp] ; compare and exchange
|
|
|
|
endif
|
|
.386
|
|
|
|
jnz short Efls10 ; if z clear, exchange failed
|
|
|
|
;
|
|
; Restore nonvolatile registers and return result.
|
|
;
|
|
|
|
cPublicFpo 0,0
|
|
|
|
Efls20: pop ebp ; restore nonvolatile registers
|
|
pop ebx ;
|
|
|
|
fstRET RtlpInterlockedFlushSList
|
|
|
|
fstENDP RtlpInterlockedFlushSList
|
|
|
|
page , 132
|
|
subttl "Interlocked Pop Entry Sequenced List"
|
|
;++
|
|
;
|
|
; PVOID
|
|
; FASTCALL
|
|
; RtlpInterlockedPopEntrySList (
|
|
; IN PSLIST_HEADER ListHead
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This function removes an entry from the front of a sequenced singly
|
|
; linked list so that access to the list is synchronized in an MP system.
|
|
; If there are no entries in the list, then a value of NULL is returned.
|
|
; Otherwise, the address of the entry that is removed is returned as the
|
|
; function value.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; (ecx) = ListHead - Supplies a pointer to the sequenced listhead from
|
|
; which an entry is to be removed.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; The address of the entry removed from the list, or NULL if the list is
|
|
; empty.
|
|
;
|
|
;--
|
|
|
|
;
|
|
; These older interfaces just fall into the new code below
|
|
;
|
|
|
|
cPublicFastCall InterlockedPopEntrySList, 1
|
|
fstENDP InterlockedPopEntrySList
|
|
|
|
cPublicFastCall ExInterlockedPopEntrySList, 2
|
|
fstENDP ExInterlockedPopEntrySList
|
|
|
|
|
|
cPublicFastCall RtlpInterlockedPopEntrySList, 1
|
|
|
|
cPublicFpo 0,2
|
|
|
|
;
|
|
; Save nonvolatile registers and read the listhead sequence number followed
|
|
; by the listhead next link.
|
|
;
|
|
; N.B. These two dwords MUST be read exactly in this order.
|
|
;
|
|
|
|
push ebx ; save nonvolatile registers
|
|
push ebp ;
|
|
mov ebp, ecx ; save listhead address
|
|
;
|
|
; N.B. The following code is the continuation address should a fault
|
|
; occur in the rare case described below.
|
|
;
|
|
|
|
public ExpInterlockedPopEntrySListResume
|
|
public _ExpInterlockedPopEntrySListResume@0
|
|
ExpInterlockedPopEntrySListResume: ;
|
|
_ExpInterlockedPopEntrySListResume@0: ;
|
|
|
|
mov edx,[ebp] + 4 ; get current sequence number
|
|
mov eax,[ebp] + 0 ; get current next link
|
|
|
|
;
|
|
; If the list is empty, then there is nothing that can be removed.
|
|
;
|
|
|
|
Epop10: or eax, eax ; check if list is empty
|
|
jz short Epop20 ; if z set, list is empty
|
|
lea ecx, [edx-1] ; Adjust depth only
|
|
|
|
|
|
;
|
|
; N.B. It is possible for the following instruction to fault in the rare
|
|
; case where the first entry in the list is allocated on another
|
|
; processor and free between the time the free pointer is read above
|
|
; and the following instruction. When this happens, the access fault
|
|
; code continues execution by skipping the following instruction.
|
|
; This results in the compare failing and the entire operation is
|
|
; retried.
|
|
;
|
|
|
|
public ExpInterlockedPopEntrySListFault
|
|
ExpInterlockedPopEntrySListFault: ;
|
|
|
|
mov ebx, [eax] ; get address of successor entry
|
|
|
|
public _ExpInterlockedPopEntrySListEnd@0
|
|
_ExpInterlockedPopEntrySListEnd@0: ;
|
|
|
|
.586
|
|
ifndef NT_UP
|
|
|
|
lock cmpxchg8b qword ptr [ebp] ; compare and exchange
|
|
|
|
else
|
|
|
|
cmpxchg8b qword ptr [ebp] ; compare and exchange
|
|
|
|
endif
|
|
.386
|
|
|
|
jnz short Epop10 ; if z clear, exchange failed
|
|
|
|
;
|
|
; Restore nonvolatile registers and return result.
|
|
;
|
|
|
|
cPublicFpo 0,0
|
|
|
|
Epop20: pop ebp ; restore nonvolatile registers
|
|
pop ebx ;
|
|
|
|
fstRET RtlpInterlockedPopEntrySList
|
|
|
|
fstENDP RtlpInterlockedPopEntrySList
|
|
|
|
page , 132
|
|
subttl "Interlocked Push Entry Sequenced List"
|
|
;++
|
|
;
|
|
; PVOID
|
|
; FASTCALL
|
|
; RtlpInterlockedPushEntrySList (
|
|
; IN PSLIST_HEADER ListHead,
|
|
; IN PVOID ListEntry
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This function inserts an entry at the head of a sequenced singly linked
|
|
; list so that access to the list is synchronized in an MP system.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; (ecx) ListHead - Supplies a pointer to the sequenced listhead into which
|
|
; an entry is to be inserted.
|
|
;
|
|
; (edx) ListEntry - Supplies a pointer to the entry to be inserted at the
|
|
; head of the list.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; Previous contents of ListHead. NULL implies list went from empty
|
|
; to not empty.
|
|
;
|
|
;--
|
|
|
|
;
|
|
; This old interface just fall into the new code below.
|
|
;
|
|
|
|
cPublicFastCall ExInterlockedPushEntrySList, 3
|
|
pop [esp] ; Drop the lock argument
|
|
fstENDP ExInterlockedPushEntrySList
|
|
|
|
cPublicFastCall InterlockedPushEntrySList, 2
|
|
fstENDP InterlockedPushEntrySList
|
|
|
|
|
|
cPublicFastCall RtlpInterlockedPushEntrySList, 2
|
|
|
|
cPublicFpo 0,2
|
|
|
|
;
|
|
; Save nonvolatile registers and read the listhead sequence number followed
|
|
; by the listhead next link.
|
|
;
|
|
; N.B. These two dwords MUST be read exactly in this order.
|
|
;
|
|
|
|
push ebx ; save nonvolatile registers
|
|
push ebp ;
|
|
mov ebp, ecx ; save listhead address
|
|
mov ebx, edx ; save list entry address
|
|
mov edx,[ebp] + 4 ; get current sequence number
|
|
mov eax,[ebp] + 0 ; get current next link
|
|
Epsh10: mov [ebx], eax ; set next link in new first entry
|
|
lea ecx, [edx+010001H] ; increment sequence number and depth
|
|
|
|
.586
|
|
ifndef NT_UP
|
|
|
|
lock cmpxchg8b qword ptr [ebp] ; compare and exchange
|
|
|
|
else
|
|
|
|
cmpxchg8b qword ptr[ebp] ; compare and exchange
|
|
|
|
endif
|
|
.386
|
|
|
|
jnz short Epsh10 ; if z clear, exchange failed
|
|
|
|
;
|
|
; Restore nonvolatile registers and return result.
|
|
;
|
|
|
|
cPublicFpo 0,0
|
|
|
|
pop ebp ; restore nonvolatile registers
|
|
pop ebx ;
|
|
|
|
fstRET RtlpInterlockedPushEntrySList
|
|
|
|
fstENDP RtlpInterlockedPushEntrySList
|
|
|
|
;++
|
|
;
|
|
; SINGLE_LIST_ENTRY
|
|
; FASTCALL
|
|
; InterlockedPushListSList (
|
|
; IN PSLIST_HEADER ListHead,
|
|
; IN PSINGLE_LIST_ENTRY List,
|
|
; IN PSINGLE_LIST_ENTRY ListEnd,
|
|
; IN ULONG Count
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This function will push multiple entries onto an SList at once
|
|
;
|
|
; Arguments:
|
|
;
|
|
; ListHead - List head to push the list to.
|
|
;
|
|
; List - The list to add to the front of the SList
|
|
; ListEnd - The last element in the chain
|
|
; Count - The number of items in the chain
|
|
;
|
|
; Return Value:
|
|
;
|
|
; PSINGLE_LIST_ENTRY - The old header pointer is returned
|
|
;
|
|
;--
|
|
|
|
cPublicFastCall InterlockedPushListSList, 4
|
|
|
|
cPublicFpo 0,4
|
|
push ebx ; save nonvolatile registers
|
|
push ebp ;
|
|
mov ebp, ecx ; save listhead address
|
|
mov ebx, edx ; save list entry address
|
|
mov edx,[ebp] + 4 ; get current sequence number
|
|
mov eax,[ebp] + 0 ; get current next link
|
|
Epshl10:
|
|
mov ecx, [esp+4*3] ; Fetch address of list tail
|
|
mov [ecx], eax ; Store new forward pointer in tail entry
|
|
lea ecx, [edx+010000H] ; increment sequence number
|
|
add ecx, [esp+4*4] ; Add in new count to create correct depth
|
|
.586
|
|
ifndef NT_UP
|
|
|
|
lock cmpxchg8b qword ptr [ebp] ; compare and exchange
|
|
|
|
else
|
|
|
|
cmpxchg8b qword ptr[ebp] ; compare and exchange
|
|
|
|
endif
|
|
.386
|
|
jnz short Epshl10 ; if z clear, exchange failed
|
|
|
|
cPublicFpo 0,0
|
|
|
|
pop ebp ; restore nonvolatile registers
|
|
pop ebx ;
|
|
|
|
fstRET InterlockedPushListSList
|
|
|
|
fstENDP InterlockedPushListSList
|
|
|
|
;++
|
|
;
|
|
; PSINGLE_LIST_ENTRY
|
|
; FirstEntrySList (
|
|
; IN PSLIST_HEADER SListHead
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This function returns the address of the fisrt entry in the SLIST or
|
|
; NULL.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; ListHead (rcx) - Supplies a pointer to the sequenced listhead from
|
|
; which the first entry address is to be computed.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; The address of the first entry is the specified, or NULL if the list is
|
|
; empty.
|
|
;
|
|
;--
|
|
|
|
cPublicProc _FirstEntrySList, 1
|
|
cPublicFpo 1,0
|
|
|
|
mov eax, [esp+4]
|
|
mov eax, [eax]
|
|
stdRET _FirstEntrySList
|
|
|
|
stdENDP _FirstEntrySList
|
|
|
|
;++
|
|
;
|
|
; LONGLONG
|
|
; FASTCALL
|
|
; RtlInterlockedCompareExchange64 (
|
|
; IN OUT PLONGLONG Destination,
|
|
; IN PLONGLONG Exchange,
|
|
; IN PLONGLONG Comperand
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This function performs a compare and exchange of 64-bits.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; (ecx) Destination - Supplies a pointer to the destination variable.
|
|
;
|
|
; (edx) Exchange - Supplies a pointer to the exchange value.
|
|
;
|
|
; (esp+4) Comperand - Supplies a pointer to the comperand value.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; The current destination value is returned as the function value.
|
|
;
|
|
;--
|
|
|
|
cPublicFastCall RtlInterlockedCompareExchange64, 3
|
|
|
|
cPublicFpo 0,2
|
|
|
|
;
|
|
; Save nonvolatile registers and read the exchange and comperand values.
|
|
;
|
|
|
|
push ebx ; save nonvolatile registers
|
|
push ebp ;
|
|
mov ebp, ecx ; set destination address
|
|
mov ebx, [edx] ; get exchange value
|
|
mov ecx, [edx] + 4 ;
|
|
mov edx, [esp] + 12 ; get comperand address
|
|
mov eax, [edx] ; get comperand value
|
|
mov edx, [edx] + 4 ;
|
|
|
|
.586
|
|
ifndef NT_UP
|
|
|
|
lock cmpxchg8b qword ptr [ebp] ; compare and exchange
|
|
|
|
else
|
|
|
|
cmpxchg8b qword ptr[ebp] ; compare and exchange
|
|
|
|
endif
|
|
.386
|
|
|
|
;
|
|
; Restore nonvolatile registers and return result in edx:eax.
|
|
;
|
|
|
|
cPublicFpo 0,0
|
|
|
|
pop ebp ; restore nonvolatile registers
|
|
pop ebx ;
|
|
|
|
fstRET RtlInterlockedCompareExchange64
|
|
|
|
fstENDP RtlInterlockedCompareExchange64
|
|
|
|
;++
|
|
;
|
|
; LONGLONG
|
|
; InterlockedCompareExchange64 (
|
|
; IN OUT PLONGLONG Destination,
|
|
; IN LONGLONG Exchange,
|
|
; IN LONGLONG Comperand
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; This function performs a compare and exchange of 64-bits.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; (esp+4) Destination - Supplies a pointer to the destination variable.
|
|
;
|
|
; (esp+8) Exchange - Supplies the exchange value.
|
|
;
|
|
; (esp+16) Comperand - Supplies the comperand value.
|
|
;
|
|
; Return Value:
|
|
;
|
|
; The current destination value is returned as the function value.
|
|
;
|
|
;--
|
|
|
|
cPublicProc _InterlockedCompareExchange64, 5
|
|
cPublicFpo 5,0
|
|
|
|
push ebx ; save nonvolatile registers
|
|
push ebp ;
|
|
mov ebp, [esp+12] ; set destination address
|
|
mov ebx, [esp+16] ; get exchange value
|
|
mov ecx, [esp+20] ;
|
|
mov eax, [esp+24] ; get comperand value
|
|
mov edx, [esp+28]
|
|
.586
|
|
lock cmpxchg8b qword ptr [ebp] ; compare and exchange
|
|
.386
|
|
|
|
cPublicFpo 0,0
|
|
|
|
pop ebp ; restore nonvolatile registers
|
|
pop ebx ;
|
|
stdRET _InterlockedCompareExchange64
|
|
|
|
stdENDP _InterlockedCompareExchange64
|
|
|
|
_TEXT$00 ends
|
|
end
|