xbox-kernel/private/ntos/ex/i386/intrlock.asm
2020-09-30 17:17:25 +02:00

214 lines
6.1 KiB
NASM

title "Interlocked Support"
;++
;
; Copyright (c) 1989 Microsoft Corporation
;
; Module Name:
;
; intrlock.asm
;
; Abstract:
;
; This module implements functions to support interlocked operations.
; Interlocked operations can only operate on nonpaged data.
;
; Author:
;
; Shie-Lin Tzong (shielint) 12-Feb-1990
;
; Environment:
;
; Any mode.
;
; Revision History:
;
; bryanwi 1-aug-90 Clean up and fix stuff.
; bryanwi 3-aug-90 Add ExInterlockedIncrementLlong,...
;
;--
.386p
.xlist
include ks386.inc
include callconv.inc ; calling convention macros
.list
_TEXT SEGMENT DWORD PUBLIC 'CODE'
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
;++
;
; General Notes on Interlocked Procedures:
;
; These procedures assume that neither their code, nor any of
; the data they touch, will cause a page fault.
;
; They use spinlocks to achieve MP atomicity, iff it's an MP machine.
; (The spinlock macros generate zilch if NT_UP = 1, and
; we if out some aux code here as well.)
;
; They turn off interrupts so that they can be used for synchronization
; between ISRs and driver code. Flags are preserved so they can
; be called in special code (Like IPC interrupt handlers) that
; may have interrupts off.
;
;--
;; align 512
page ,132
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.
;
; Arguments:
;
; (TOS+4) = Addend - a pointer to the addend value
; (TOS+8) = Increment - the increment value
; (TOS+16) = Lock - a pointer to a pointer to a spin lock
;
; Return Value:
;
; The initial value of the addend variable is stored in eax:edx
;
;--
EiulAddend equ [ebp + 8]
EiulIncrement equ [ebp + 12]
EiulLock equ [ebp + 20]
EiulRetval equ [ebp - 8]
cPublicProc _ExInterlockedAddLargeInteger, 4
push ebp
mov ebp,esp
sub esp, 8
eiul10: pushfd
cli ; disable interrupts
mov eax,EiulAddend ; (eax)-> addend variable
mov ecx,[eax] ; (ecx)= low part of addend value
mov edx,[eax]+4 ; (edx)= high part of addend value
mov EiulRetVal,ecx ; set low part of return value
mov EiulRetVal+4,edx ; set high part of return value
add ecx,EiulIncrement ; add low parts of large integer
adc edx,EiulIncrement+4 ; add high parts of large integer and carry
mov eax,EiulAddend ; RELOAD (eax)-> addend variable
mov [eax],ecx ; store low part of result
mov [eax]+4,edx ; store high part of result
popfd ; restore flags including interrupts
mov eax, EiulRetval ; calling convention
mov edx, EiulRetval+4 ; calling convention
mov esp, ebp
pop ebp
stdRET _ExInterlockedAddLargeInteger
stdENDP _ExInterlockedAddLargeInteger
page ,132
subttl "ExInterlocked Exchange Add Large Integer"
;++
;
; LARGE_INTEGER
; ExInterlockedExchangeAddLargeInteger (
; 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 cmpxchg8b instruction is only supported on some processors.
; If the host processor does not support this instruction, then
; then following code is patched to contain a jump to the normal
; add large integer code which has a compatible calling sequence
; and data structure.
;
; Arguments:
;
; (TOS + 4) = Addend - Supplies a pointer to the addend variable.
;
; (TOS + 8) = Increment - Supplies the increment value.
;
; (TOS + 16) = Lock - Supplies a pointer a spin lock.
;
; N.B. This routine does not use the spin lock.
;
; Return Value:
;
; The initial value of the addend variable is stored in eax:edx.
;
;--
XaAddend equ [esp + 12]
XaIncrement equ [esp + 16]
XaLock equ [esp + 24]
cPublicProc _ExInterlockedExchangeAddLargeInteger, 4
cPublicFpo 0,2
;
; Save nonvolatile registers and get the addend value.
;
push ebx ; save nonvolatile registers
push ebp ;
mov ebp, XaAddend ; get the addend variable address
mov eax,[ebp] + 0 ; get low part of addend value
mov edx,[ebp] + 4 ; get high part of addend value
;
; Add the increment value to the addend value.
;
Xa10: mov ebx, eax ; copy low part of addend value
mov ecx, edx ; copy high part of addend value
add ebx, XaIncrement ; add low part of increment value
adc ecx, XaIncrement + 4 ; add high part of increment value
;
; Exchange the updated addend value with the previous addend value.
;
.586
cmpxchg8b qword ptr [ebp] ; compare and exchange
.386
jnz short Xa10 ; if z clear, exchange failed
;
; Restore nonvolatile registers and return result.
;
cPublicFpo 0,0
pop ebp ;
pop ebx ;
stdRET _ExInterlockedExchangeAddLargeInteger
stdENDP _ExInterlockedExchangeAddLargeInteger
_TEXT ends
end