windows-nt/Source/XPSP1/NT/base/ntos/ex/amd64/intrlock.asm

417 lines
13 KiB
NASM
Raw Normal View History

2020-09-26 03:20:57 -05:00
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