417 lines
13 KiB
NASM
417 lines
13 KiB
NASM
|
title "Interlocked Support"
|
||
|
;++
|
||
|
;
|
||
|
; Copyright (c) 2000 Microsoft Corporation
|
||
|
;
|
||
|
; Module Name:
|
||
|
;
|
||
|
; intrlock.asm
|
||
|
;
|
||
|
; Abstract:
|
||
|
;
|
||
|
; This module implements functions to support interlocked operations.
|
||
|
;
|
||
|
; Author:
|
||
|
;
|
||
|
; David N. Cutler (davec) 23-Jun-2000
|
||
|
;
|
||
|
; Environment:
|
||
|
;
|
||
|
; Any mode.
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
include ksamd64.inc
|
||
|
|
||
|
subttl "ExInterlockedAddLargeInteger"
|
||
|
;++
|
||
|
;
|
||
|
; LARGE_INTEGER
|
||
|
; ExInterlockedAddLargeInteger (
|
||
|
; IN PLARGE_INTEGER Addend,
|
||
|
; IN LARGE_INTEGER Increment,
|
||
|
; IN PKSPIN_LOCK Lock
|
||
|
; )
|
||
|
;
|
||
|
; Routine Description:
|
||
|
;
|
||
|
; This function performs an interlocked add of an increment value to an
|
||
|
; addend variable of type unsigned large integer. The initial value of
|
||
|
; the addend variable is returned as the function value.
|
||
|
;
|
||
|
; N.B. The specification of this function requires that the given lock
|
||
|
; must be used to synchronize the update even though on AMD64 the
|
||
|
; operation can actually be done atomically without using the lock.
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
; Addend (rcx) - Supplies a pointer to a variable whose value is to be
|
||
|
; adjusted by the increment value.
|
||
|
;
|
||
|
; Increment (rdx) - Supplies the increment value to be added to the
|
||
|
; addend variable.
|
||
|
;
|
||
|
; Lock (r8) - Supplies a pointer to a spin lock to be used to synchronize
|
||
|
; access to the addend variable.
|
||
|
;
|
||
|
; Return Value:
|
||
|
;
|
||
|
; The initial value of the addend variable is returned.
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
LEAF_ENTRY ExInterlockedAddLargeInteger, _TEXT$00
|
||
|
|
||
|
cli ; disable interrupts
|
||
|
AcquireSpinLock r8 ; acquire spin lock
|
||
|
mov rax, [rcx] ; get initial addend value
|
||
|
add [rcx], rdx ; compute sum of addend and increment
|
||
|
ReleaseSpinLock r8 ; release spin lock
|
||
|
sti ; enable interrupts
|
||
|
ret ; return
|
||
|
|
||
|
LEAF_END ExInterlockedAddLargeInteger, _TEXT$00
|
||
|
|
||
|
subttl "Interlocked Add Unsigned Long"
|
||
|
;++
|
||
|
;
|
||
|
; ULONG
|
||
|
; ExInterlockedAddUlong (
|
||
|
; IN PULONG Addend,
|
||
|
; IN ULONG Increment,
|
||
|
; IN PKSPIN_LOCK Lock
|
||
|
; )
|
||
|
;
|
||
|
; Routine Description:
|
||
|
;
|
||
|
; This function performs an interlocked add of an increment value to an
|
||
|
; addend variable of type unsinged long. The initial value of the addend
|
||
|
; variable is returned as the function value.
|
||
|
;
|
||
|
; N.B. The specification of this function requires that the given lock
|
||
|
; must be used to synchronize the update even though on AMD64 the
|
||
|
; opearion can actually be done atomically without using the lock.
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
; Addend (rcx) - Supplies a pointer to a variable whose value is to be
|
||
|
; adjusted by the increment value.
|
||
|
;
|
||
|
; Increment (edx) - Supplies the increment value to be added to the
|
||
|
; addend variable.
|
||
|
;
|
||
|
; Lock (r8) - Supplies a pointer to a spin lock to be used to synchronize
|
||
|
; access to the addend variable.
|
||
|
;
|
||
|
; Return Value:
|
||
|
;
|
||
|
; The initial value of the addend variable.
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
LEAF_ENTRY ExInterlockedAddUlong, _TEXT$00
|
||
|
|
||
|
cli ; disable interrupts
|
||
|
AcquireSpinLock r8 ; acquire spin lock
|
||
|
mov eax, [rcx] ; get initial addend value
|
||
|
add [rcx], edx ; compute sum of addend and increment
|
||
|
ReleaseSpinLock r8 ; release spin lock
|
||
|
sti ; enable interrupts
|
||
|
ret ; return
|
||
|
|
||
|
LEAF_END ExInterlockedAddUlong, _TEXT$00
|
||
|
|
||
|
subttl "Interlocked Insert Head List"
|
||
|
;++
|
||
|
;
|
||
|
; PLIST_ENTRY
|
||
|
; ExInterlockedInsertHeadList (
|
||
|
; IN PLIST_ENTRY ListHead,
|
||
|
; IN PLIST_ENTRY ListEntry,
|
||
|
; IN PKSPIN_LOCK Lock
|
||
|
; )
|
||
|
;
|
||
|
; Routine Description:
|
||
|
;
|
||
|
; This function inserts an entry at the head of a doubly linked list
|
||
|
; so that access to the list is synchronized in a multiprocessor system.
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
; ListHead (rcx) - Supplies a pointer to the head of the doubly linked
|
||
|
; list into which an entry is to be inserted.
|
||
|
;
|
||
|
; ListEntry (rdx) - Supplies a pointer to the entry to be inserted at the
|
||
|
; head of the list.
|
||
|
;
|
||
|
; Lock (r8) - Supplies a pointer to a spin lock to be used to synchronize
|
||
|
; access to the list.
|
||
|
;
|
||
|
; Return Value:
|
||
|
;
|
||
|
; Pointer to entry that was at the head of the list or NULL if the list
|
||
|
; was empty.
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
LEAF_ENTRY ExInterlockedInsertHeadList, _TEXT$00
|
||
|
|
||
|
cli ; disable interrupts
|
||
|
AcquireSpinLock r8 ; acquire spin lock
|
||
|
mov rax, LsFlink[rcx] ; get address of first entry
|
||
|
mov LsFlink[rdx], rax ; set next link in entry
|
||
|
mov LsBlink[rdx], rcx ; set back link in entry
|
||
|
mov LsFlink[rcx], rdx ; set next link in head
|
||
|
mov LsBlink[rax], rdx ; set back link in next
|
||
|
ReleaseSpinLock r8 ; release spin lock
|
||
|
sti ; enable interrupts
|
||
|
xor rcx, rax ; check if list was empty
|
||
|
jnz short Ih10 ; if nz, list not empty
|
||
|
xor eax, eax ; list was empty
|
||
|
Ih10: ret ; return
|
||
|
|
||
|
LEAF_END ExInterlockedInsertHeadList, _TEXT$00
|
||
|
|
||
|
subttl "Interlocked Insert Tail List"
|
||
|
;++
|
||
|
;
|
||
|
; PLIST_ENTRY
|
||
|
; ExInterlockedInsertTailList (
|
||
|
; IN PLIST_ENTRY ListHead,
|
||
|
; IN PLIST_ENTRY ListEntry,
|
||
|
; IN PKSPIN_LOCK Lock
|
||
|
; )
|
||
|
;
|
||
|
; Routine Description:
|
||
|
;
|
||
|
; This function inserts an entry at the tail of a doubly linked list
|
||
|
; so that access to the list is synchronized in a multiprocessor system.
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
; ListHead (rcx) - Supplies a pointer to the head of the doubly linked
|
||
|
; list into which an entry is to be inserted.
|
||
|
;
|
||
|
; ListEntry (rdx) - Supplies a pointer to the entry to be inserted at the
|
||
|
; tail of the list.
|
||
|
;
|
||
|
; Lock (r8) - Supplies a pointer to a spin lock to be used to synchronize
|
||
|
; access to the list.
|
||
|
;
|
||
|
; Return Value:
|
||
|
;
|
||
|
; Pointer to entry that was at the tail of the list or NULL if the list
|
||
|
; was empty.
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
LEAF_ENTRY ExInterlockedInsertTailList, _TEXT$00
|
||
|
|
||
|
cli ; disable interrupts
|
||
|
AcquireSpinLock r8 ; acquire spin lock
|
||
|
mov rax, LsBlink[rcx] ; get address of last entry
|
||
|
mov LsFlink[rdx], rcx ; set next link in entry
|
||
|
mov LsBlink[rdx], rax ; set back link in entry
|
||
|
mov LsBlink[rcx], rdx ; set back link in head
|
||
|
mov LsFlink[rax], rdx ; set next link in last
|
||
|
ReleaseSpinLock r8 ; release spin lock
|
||
|
sti ; enable interrupts
|
||
|
xor rcx, rax ; check if list was empty
|
||
|
jnz short It10 ; if nz, list not empty
|
||
|
xor eax, eax ; list was empty
|
||
|
It10: ret ; return
|
||
|
|
||
|
LEAF_END ExInterlockedInsertTailList, _TEXT$00
|
||
|
|
||
|
subttl "Interlocked Remove Head List"
|
||
|
;++
|
||
|
;
|
||
|
; PLIST_ENTRY
|
||
|
; ExInterlockedRemoveHeadList (
|
||
|
; IN PLIST_ENTRY ListHead,
|
||
|
; IN PKSPIN_LOCK Lock
|
||
|
; )
|
||
|
;
|
||
|
; Routine Description:
|
||
|
;
|
||
|
; This function removes an entry from the head of a doubly linked list
|
||
|
; so that access to the list is synchronized in a multiprocessor 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:
|
||
|
;
|
||
|
; ListHead (rcx) - Supplies a pointer to the head of the doubly linked
|
||
|
; list from which an entry is to be removed.
|
||
|
;
|
||
|
; Lock (rdx) - Supplies a pointer to a spin lock to be used to synchronize
|
||
|
; access to the list.
|
||
|
;
|
||
|
; Return Value:
|
||
|
;
|
||
|
; The address of the entry removed from the list, or NULL if the list is
|
||
|
; empty.
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
LEAF_ENTRY ExInterlockedRemoveHeadList, _TEXT$00
|
||
|
|
||
|
cli ; disable interrupt
|
||
|
AcquireSpinLock rdx ; acquire spin lock
|
||
|
mov rax, LsFlink[rcx] ; get address of first entry
|
||
|
cmp rax, rcx ; check if list is empty
|
||
|
je short Rh10 ; if e, list is empty
|
||
|
mov r8, LsFlink[rax] ; get address of next entry
|
||
|
mov LsFlink[rcx], r8 ; set address of first entry
|
||
|
mov LsBlink[r8], rcx ; set back in next entry
|
||
|
Rh10: ReleaseSpinLock rdx ; release spin lock
|
||
|
sti ; enable interrupts
|
||
|
xor rcx, rax ; check if list was empty
|
||
|
jnz short Rh20 ; if nz, list not empty
|
||
|
xor eax, eax ; list was empty
|
||
|
Rh20: ret ; return
|
||
|
|
||
|
LEAF_END ExInterlockedRemoveHeadList, _TEXT$00
|
||
|
|
||
|
subttl "Interlocked Pop Entry List"
|
||
|
;++
|
||
|
;
|
||
|
; PSINGLE_LIST_ENTRY
|
||
|
; ExInterlockedPopEntryList (
|
||
|
; IN PSINGLE_LIST_ENTRY ListHead,
|
||
|
; IN PKSPIN_LOCK Lock
|
||
|
; )
|
||
|
;
|
||
|
; Routine Description:
|
||
|
;
|
||
|
; This function removes an entry from the front of a singly linked list
|
||
|
; so that access to the list is synchronized in a multiprocessor 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:
|
||
|
;
|
||
|
; ListHead (rcx) - Supplies a pointer to the head of the singly linked
|
||
|
; list from which an entry is to be removed.
|
||
|
;
|
||
|
; Lock (rdx) - Supplies a pointer to a spin lock to be used to synchronize
|
||
|
; access to the list.
|
||
|
;
|
||
|
; Return Value:
|
||
|
;
|
||
|
; The address of the entry removed from the list, or NULL if the list is
|
||
|
; empty.
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
LEAF_ENTRY ExInterlockedPopEntryList, _TEXT$00
|
||
|
|
||
|
cli ; disable interrupts
|
||
|
AcquireSpinLock rdx ; acquire spin lock
|
||
|
mov rax, [rcx] ; get address of first entry
|
||
|
test rax, rax ; check if list is empty
|
||
|
jz short Pe10 ; if z, list is empty
|
||
|
mov r8, [rax] ; get address of next entry
|
||
|
mov [rcx], r8 ; set address of first entry
|
||
|
Pe10: ReleaseSpinLock rdx ; release spin lock
|
||
|
sti ; enable interrupts
|
||
|
ret ; return
|
||
|
|
||
|
LEAF_END ExInterlockedPopEntryList, _TEXT$00
|
||
|
|
||
|
subttl "Interlocked Push Entry List"
|
||
|
;++
|
||
|
;
|
||
|
; PSINGLE_LIST_ENTRY
|
||
|
; ExInterlockedPushEntryList (
|
||
|
; IN PSINGLE_LIST_ENTRY ListHead,
|
||
|
; IN PSINGLE_LIST_ENTRY ListEntry,
|
||
|
; IN PKSPIN_LOCK Lock
|
||
|
; )
|
||
|
;
|
||
|
; Routine Description:
|
||
|
;
|
||
|
; This function inserts an entry at the head of a singly linked list
|
||
|
; so that access to the list is synchronized in a multiprocessor system.
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
; ListHead (rcx) - Supplies a pointer to the head of the singly linked
|
||
|
; list into which an entry is to be inserted.
|
||
|
;
|
||
|
; ListEntry (rdx) - Supplies a pointer to the entry to be inserted at the
|
||
|
; head of the list.
|
||
|
;
|
||
|
; Lock (r8) - Supplies a pointer to a spin lock to be used to synchronize
|
||
|
; access to the list.
|
||
|
;
|
||
|
; Return Value:
|
||
|
;
|
||
|
; Previous contents of ListHead. NULL implies list went from empty to not
|
||
|
; empty.
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
LEAF_ENTRY ExInterlockedPushEntryList, _TEXT$00
|
||
|
|
||
|
cli ; disable interrupts
|
||
|
AcquireSpinLock r8 ; acquire spin lock
|
||
|
mov rax, [rcx] ; get address of first entry
|
||
|
mov [rdx], rax ; set address of next entry
|
||
|
mov [rcx], rdx ; set address of first entry
|
||
|
ReleaseSpinLock r8 ; release spin lock
|
||
|
sti ; enable interrupts
|
||
|
ret ;
|
||
|
|
||
|
LEAF_END ExInterlockedPushEntryList, _TEXT$00
|
||
|
|
||
|
subttl "ExInterlockedAddLargeStatistic"
|
||
|
;++
|
||
|
;
|
||
|
; VOID
|
||
|
; ExInterlockedAddLargeStatistic (
|
||
|
; IN PLARGE_INTEGER Addend,
|
||
|
; IN ULONG Increment
|
||
|
; )
|
||
|
;
|
||
|
; Routine Description:
|
||
|
;
|
||
|
; This function performs an interlocked add of an increment value to an
|
||
|
; addend variable of type unsigned large integer.
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
; Addend (rcx) - Supplies a pointer to the variable whose value is to be
|
||
|
; adjusted by the increment value.
|
||
|
;
|
||
|
; Increment (rdx) - Supplies the increment value that is added to the
|
||
|
; addend variable.
|
||
|
;
|
||
|
; Return Value:
|
||
|
;
|
||
|
; None.
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
LEAF_ENTRY ExInterlockedAddLargeStatistic, _TEXT$00
|
||
|
|
||
|
or edx, edx ; zero upper bits
|
||
|
|
||
|
ifndef NT_UP
|
||
|
|
||
|
lock add [rcx], rdx ; add increment
|
||
|
|
||
|
else
|
||
|
|
||
|
add [rcx], rdx ; add increment
|
||
|
|
||
|
endif
|
||
|
|
||
|
ret ; return
|
||
|
|
||
|
LEAF_END ExInterlockedAddLargeStatistic, _TEXT$00
|
||
|
|
||
|
end
|