summaryrefslogtreecommitdiffstats
path: root/private/ntos/ex/i386
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ex/i386
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/ex/i386')
-rw-r--r--private/ntos/ex/i386/evpair.asm152
-rw-r--r--private/ntos/ex/i386/fmutex.asm186
-rw-r--r--private/ntos/ex/i386/intrlfst.asm1531
-rw-r--r--private/ntos/ex/i386/intrlock.asm1054
-rw-r--r--private/ntos/ex/i386/probe.c120
-rw-r--r--private/ntos/ex/i386/raisests.asm316
-rw-r--r--private/ntos/ex/i386/resoura.asm110
-rw-r--r--private/ntos/ex/i386/sources8
-rw-r--r--private/ntos/ex/i386/splocks.asm208
9 files changed, 3685 insertions, 0 deletions
diff --git a/private/ntos/ex/i386/evpair.asm b/private/ntos/ex/i386/evpair.asm
new file mode 100644
index 000000000..e06ab6f87
--- /dev/null
+++ b/private/ntos/ex/i386/evpair.asm
@@ -0,0 +1,152 @@
+ title "Event Pair Support"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; evpair.asm
+;
+; Abstract:
+;
+;
+; This module contains the implementation for the fast event pair
+; system services that are used for client/server synchronization.
+; sethiwaitlo, setlowaithi.
+;
+;
+; Author:
+;
+; Mark Lucovsky (markl) 03-Feb-1992
+;
+; Environment:
+;
+; Kernel mode.
+;
+; Revision History:
+;
+;
+;--
+.386p
+; .xlist
+include ks386.inc
+include callconv.inc ; calling convention macros
+; .list
+
+EXTRNP _KiSetServerWaitClientEvent,3
+extrn _KeTickCount:DWORD
+extrn _ExpTickCountMultiplier:DWORD
+
+_TEXT SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ page ,132
+ subttl "NtSetLowWaitHighThread"
+
+;++
+; Routine Description:
+;
+; This function uses the prereferenced client/server event pair pointer
+; and sets the low event of the event pair and waits on the high event
+; of the event pair object.
+;
+; N.B. This service assumes that it has been called from user mode.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; TBS
+;
+;--
+
+cPublicProc _NtSetLowWaitHighThread, 0
+cPublicFpo 0, 0
+
+ mov eax,fs:PcPrcbData+PbCurrentThread
+ mov eax,dword ptr [eax+EtEventPair]
+ or eax,eax
+ jz $BAIL
+ mov ecx,eax ; compute address of events
+ add eax,EpEventLow ; server event
+ add ecx,EpEventHigh ; client event
+ stdCall _KiSetServerWaitClientEvent, <eax, ecx, 1>
+ xor eax,eax
+ stdRET _NtSetLowWaitHighThread
+$BAIL:
+ mov eax,STATUS_NO_EVENT_PAIR
+ stdRET _NtSetLowWaitHighThread
+stdENDP _NtSetLowWaitHighThread
+
+ page ,132
+ subttl "NtSetHighWaitLowThread"
+
+;++
+; Routine Description:
+;
+; This function uses the prereferenced client/server event pair pointer
+; and sets the low event of the event pair and waits on the high event
+; of the event pair object.
+;
+; N.B. This service assumes that it has been called from user mode.
+;
+; Arguments:
+;
+; None.
+;
+; Return Value:
+;
+; TBS
+;
+;--
+;PUBLIC _NtSetHighWaitLowThread, 0
+cPublicProc _NtSetHighWaitLowThread, 0
+cPublicFpo 0, 0
+
+ mov eax,fs:PcPrcbData+PbCurrentThread
+ mov eax,dword ptr [eax+EtEventPair]
+ or eax,eax
+ jz $BAIL1
+ mov ecx,eax ; compute address of events
+ add eax,EpEventHigh ; server event
+ add ecx,EpEventLow ; client event
+ stdCall _KiSetServerWaitClientEvent, <eax, ecx, 1>
+ xor eax,eax
+ stdRET _NtSetHighWaitLowThread
+$BAIL1:
+ mov eax,STATUS_NO_EVENT_PAIR
+ stdRET _NtSetHighWaitLowThread
+stdENDP _NtSetHighWaitLowThread
+
+;++
+;
+; Routine Description:
+;
+; This function returns number of milliseconds since the system
+; booted. This function is designed to support the Win32 GetTicKCount
+; API.
+;
+; Arguments:
+;
+; NONE
+;
+; Return Value:
+;
+; Returns the number of milliseconds that have transpired since boot
+;
+;--
+
+cPublicProc _NtGetTickCount, 0
+cPublicFpo 0, 0
+
+ mov eax,dword ptr [_KeTickCount]
+ mul dword ptr [_ExpTickCountMultiplier]
+ shrd eax,edx,24 ; compute resultant tick count
+
+ stdRET _NtGetTickCount
+stdENDP _NtGetTickCount
+
+_TEXT ends
+ end
diff --git a/private/ntos/ex/i386/fmutex.asm b/private/ntos/ex/i386/fmutex.asm
new file mode 100644
index 000000000..6f419d35a
--- /dev/null
+++ b/private/ntos/ex/i386/fmutex.asm
@@ -0,0 +1,186 @@
+ TITLE "Fast Mutex Support"
+;++
+;
+; Copyright (c) 1994 Microsoft Corporation
+;
+; Module Name:
+;
+; spinlock.asm
+;
+; Abstract:
+;
+; This module implements teh code necessary to acquire and release fast
+; mutexs without raising or lowering IRQL.
+;
+; Author:
+;
+; David N. Cutler (davec) 26-May-1994
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include ks386.inc
+include callconv.inc ; calling convention macros
+include mac386.inc
+ .list
+
+ EXTRNP _KeSetEventBoostPriority, 2
+ EXTRNP _KeWaitForSingleObject, 5
+
+ifdef NT_UP
+ LOCK_ADD equ add
+ LOCK_DEC equ dec
+else
+ LOCK_ADD equ lock add
+ LOCK_DEC equ lock dec
+endif
+
+_TEXT$00 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; VOID
+; FASTCALL
+; ExAcquireFastMutexUnsafe (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquires ownership of a fast mutex, but does not raise
+; IRQL to APC level.
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to a fast mutex.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExAcquireFastMutexUnsafe,1
+cPublicFpo 0,0
+
+ LOCK_DEC dword ptr [ecx].FmCount ; decrement lock count
+ jnz short afm10 ; if nz, ownership not obtained
+ fstRet ExAcquireFastMutexUnsafe ; return
+
+afm10: inc dword ptr [ecx].FmContention ; increment contention count
+ add ecx, FmEvent ; wait for ownership event
+ stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0> ;
+ fstRet ExAcquireFastMutexUnsafe ; return
+
+fstENDP ExAcquireFastMutexUnsafe
+
+;++
+;
+; VOID
+; FASTCALL
+; ExReleaseFastMutexUnsafe (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function releases ownership of a fast mutex, and does nt
+; restore IRQL to its previous value.
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to a fast mutex.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExReleaseFastMutexUnsafe,1
+cPublicFpo 0,0
+
+ LOCK_ADD dword ptr [ecx].FmCount, 1 ; increment ownership count
+ jng short rfm10 ; if ng, waiter present
+ fstRet ExReleaseFastMutexUnsafe ; return
+
+rfm10: add ecx, FmEvent ; compute event address
+ stdCall _KeSetEventBoostPriority,<ecx, 0> ; set ownerhsip event
+ fstRet ExReleaseFastMutexUnsafe ; return
+
+fstENDP ExReleaseFastMutexUnsafe
+
+
+;++
+;
+; BOOLEAN
+; FASTCALL
+; ExTryToAcquireFastMutexUnsafe (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function attempts to acquire ownership of a fast mutex, and if
+; successful, does not raise IRQL to APC level.
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to a fast mutex.
+;
+; Return Value:
+;
+; Returns TRUE if the FAST_MUTEX was acquired; otherwise false
+;
+;--
+
+if 0
+
+cPublicFastCall ExTryToAcquireFastMutexUnsafe,1
+cPublicFpo 0,0
+
+ifdef NT_UP
+
+ cli ; disable interrupts
+
+endif
+
+ cmp dword ptr [ecx].FmCount, 1 ; check if mutex already owned
+ jne short tam10 ; if ne, mutex already owned
+
+ifndef NT_UP
+
+ mov eax, 1 ; set value to compare against
+ mov edx, 0 ; set value to set
+ lock cmpxchg dword ptr [ecx].FmCount, edx ; attempt to acquire fast mutex
+ jne short tam10 ; if ne, mutex already owned
+
+else
+
+ mov dword ptr [ecx].FmCount, 0 ; set mutex owned
+ sti ; enable interrupts
+
+endif
+
+ mov eax, 1 ; set return value
+ fstRet ExTryToAcquireFastMutexUnsafe ; return
+
+tam10: xor eax, eax ; set return value
+ fstRet ExTryToAcquireFastMutexUnsafe ; return
+
+fstENDP ExTryToAcquireFastMutexUnsafe
+
+endif
+
+
+_TEXT$00 ends
+
+ end
diff --git a/private/ntos/ex/i386/intrlfst.asm b/private/ntos/ex/i386/intrlfst.asm
new file mode 100644
index 000000000..11d8ef8dd
--- /dev/null
+++ b/private/ntos/ex/i386/intrlfst.asm
@@ -0,0 +1,1531 @@
+ title "Interlocked Support"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; intrlfst.asm
+;
+; Abstract:
+;
+; This module implements functions to support interlocked operations.
+; Interlocked operations can only operate on nonpaged data.
+;
+; This module implements the fast call version of the interlocked
+; fuctions.
+;
+; Author:
+;
+; Ken Reneris (kenr) 5-May-1994
+;
+; 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
+
+;++
+;
+; 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 "ExInterlockedAddLargeStatistic"
+;++
+;
+; VOID
+; FASTCALL
+; 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:
+;
+; (ecx) Addend - Supplies a pointer to the variable whose value is
+; adjusted by the increment value.
+;
+; (edx) Increment - Supplies the increment value that is added to the
+; addend variable.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExInterlockedAddLargeStatistic, 2
+cPublicFpo 0,0
+
+ifdef NT_UP
+
+ add dword ptr [ecx], edx ; add low part of large statistic
+ adc dword ptr [ecx+4], 0 ; add carry to high part
+
+else
+
+ lock add dword ptr [ecx], edx ; add low part of large statistic
+ jc short Eils10 ; if c, add generated a carry
+ fstRET ExInterlockedAddLargeStatistic ; return
+
+Eils10: lock adc dword ptr [ecx+4], 0 ; add carry to high part
+
+endif
+
+ fstRET ExInterlockedAddLargeStatistic ; return
+
+fstENDP ExInterlockedAddLargeStatistic
+
+ page , 132
+ subttl "Interlocked Add Unsigned Long"
+;++
+;
+; ULONG
+; FASTCALL
+; ExfInterlockedAddUlong (
+; 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.
+;
+; It is NOT possible to mix ExInterlockedDecrementLong and
+; ExInterlockedIncrementong with ExInterlockedAddUlong.
+;
+;
+; Arguments:
+;
+; (ecx) Addend - Supplies a pointer to a variable whose value is to be
+; adjusted by the increment value.
+;
+; (edx) Increment - Supplies the increment value to be added to the
+; addend variable.
+;
+; (esp+4) Lock - 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.
+;
+;--
+
+cPublicFastCall ExfInterlockedAddUlong, 3
+cPublicFpo 1, 1
+
+ifdef NT_UP
+;
+; UP version of ExInterlockedAddUlong
+;
+
+ pushfd
+ cli ; disable interrupts
+
+ mov eax, [ecx] ; (eax)= initial addend value
+ add [ecx], edx ; [ecx]=adjusted value
+
+ popfd ; restore flags including ints
+ fstRET ExfInterlockedAddUlong
+
+else
+
+;
+; MP version of ExInterlockedAddUlong
+;
+ pushfd
+ mov eax, [esp+8] ; (eax) = SpinLock
+Eial10: cli ; disable interrupts
+ ACQUIRE_SPINLOCK eax, <short Eial20>
+
+ mov eax, [ecx] ; (eax)=initial addend value
+ add [ecx], edx ; [ecx]=adjusted value
+
+ mov edx, [esp+8] ; (edx) = SpinLock
+ RELEASE_SPINLOCK edx
+ popfd
+ fstRET ExfInterlockedAddUlong
+
+Eial20: popfd
+ pushfd
+ SPIN_ON_SPINLOCK eax, <short Eial10>
+endif
+
+fstENDP ExfInterlockedAddUlong
+
+ page , 132
+ subttl "Interlocked Insert Head List"
+;++
+;
+; PLIST_ENTRY
+; ExfInterlockedInsertHeadList (
+; 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.
+;
+; N.B. The pages of data which this routine operates on MUST be
+; present. No page fault is allowed in this routine.
+;
+; Arguments:
+;
+; (ecx) = ListHead - Supplies a pointer to the head of the doubly linked
+; list 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.
+;
+; (esp+4) Lock - 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.
+;
+;--
+
+cPublicFastCall ExfInterlockedInsertHeadList , 3
+cPublicFpo 1, 1
+
+ifndef NT_UP
+cPublicFpo 1, 2
+ push esi
+ mov esi, [esp+8] ; Address of spinlock
+endif
+ pushfd
+
+Eiih10: cli
+ ACQUIRE_SPINLOCK esi,<short Eiih20>
+
+ mov eax, LsFlink[ecx] ; (eax)->next entry in the list
+ mov [edx]+LsFlink, eax ; store next link in entry
+ mov [edx]+LsBlink, ecx ; store previous link in entry
+ mov [ecx]+LsFlink, edx ; store next link in head
+ mov [eax]+LsBlink, edx ; store previous link in next
+
+ RELEASE_SPINLOCK esi
+ popfd
+ifndef NT_UP
+ pop esi
+endif
+ xor eax, ecx ; return null if list was empty
+ jz short Eiih15
+ xor eax, ecx
+Eiih15: fstRET ExfInterlockedInsertHeadList
+
+ifndef NT_UP
+Eiih20: popfd
+ pushfd
+ SPIN_ON_SPINLOCK esi, <short Eiih10>
+endif
+
+fstENDP ExfInterlockedInsertHeadList
+
+ page , 132
+ subttl "Interlocked Insert Tail List"
+;++
+;
+; PLIST_ENTRY
+; FASTCALL
+; ExfInterlockedInsertTailList (
+; 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.
+;
+; N.B. The pages of data which this routine operates on MUST be
+; present. No page fault is allowed in this routine.
+;
+; Arguments:
+;
+; (ecx) = ListHead - Supplies a pointer to the head of the doubly linked
+; list into which an entry is to be inserted.
+;
+; (edx) = ListEntry - Supplies a pointer to the entry to be inserted at the
+; tail of the list.
+;
+; (esp+4) Lock - 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.
+;
+;--
+
+cPublicFastCall ExfInterlockedInsertTailList, 3
+cPublicFpo 1, 1
+
+ifndef NT_UP
+cPublicFpo 1, 2
+ push esi
+ mov esi, [esp+8] ; Address of spinlock
+endif
+ pushfd
+
+Eiit10: cli
+ ACQUIRE_SPINLOCK esi,<short Eiit20>
+
+ mov eax, LsBlink[ecx] ; (eax)->prev entry in the list
+ mov [edx]+LsFlink, ecx ; store next link in entry
+ mov [edx]+LsBlink, eax ; store previous link in entry
+ mov [ecx]+LsBlink, edx ; store next link in head
+ mov [eax]+LsFlink, edx ; store previous link in next
+
+ RELEASE_SPINLOCK esi
+ popfd
+
+ifndef NT_UP
+ pop esi
+endif
+ xor eax, ecx ; return null if list was empty
+ jz short Eiit15
+ xor eax, ecx
+Eiit15: fstRET ExfInterlockedInsertTailList
+
+ifndef NT_UP
+Eiit20: popfd
+ pushfd
+ SPIN_ON_SPINLOCK esi, <short Eiit10>
+endif
+
+fstENDP ExfInterlockedInsertTailList
+
+
+ page , 132
+ subttl "Interlocked Remove Head List"
+;++
+;
+; PLIST_ENTRY
+; FASTCALL
+; ExfInterlockedRemoveHeadList (
+; 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.
+;
+; N.B. The pages of data which this routine operates on MUST be
+; present. No page fault is allowed in this routine.
+;
+; Arguments:
+;
+; (ecx) ListHead - Supplies a pointer to the head of the doubly linked
+; list from which an entry is to be removed.
+;
+; (edx) Lock - 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.
+;
+;--
+
+cPublicFastCall ExfInterlockedRemoveHeadList , 2
+cPublicFpo 0, 1
+ifdef NT_UP
+;
+; UP version
+;
+ pushfd
+ cli
+
+ mov eax, [ecx]+LsFlink ; (eax)-> next entry
+ cmp eax, ecx ; Is list empty?
+ je short Eirh20 ; if e, list is empty, go Eirh20
+
+ mov edx, [eax]+LsFlink ; (ecx)-> next entry(after deletion)
+ mov [ecx]+LsFlink, edx ; store address of next in head
+ mov [edx]+LsBlink, ecx ; store address of previous in next
+if DBG
+ mov [eax]+LsFlink, 0baddd0ffh
+ mov [eax]+LsBlink, 0baddd0ffh
+endif
+ popfd ; restore flags including interrupts
+ fstRET ExfInterlockedRemoveHeadList
+
+Eirh20: popfd
+ xor eax,eax ; (eax) = null for empty list
+ fstRET ExfInterlockedRemoveHeadList
+
+else
+;
+; MP version
+;
+
+Eirh40: pushfd
+ cli
+ ACQUIRE_SPINLOCK edx, <short Eirh60>
+
+ mov eax, [ecx]+LsFlink ; (eax)-> next entry
+ cmp eax, ecx ; Is list empty?
+ je short Eirh50 ; if e, list is empty, go Eirh50
+
+cPublicFpo 0,2
+ push esi
+ mov esi, edx
+
+ mov edx, [eax]+LsFlink ; (ecx)-> next entry(after deletion)
+ mov [ecx]+LsFlink, edx ; store address of next in head
+ mov [edx]+LsBlink, ecx ; store address of previous in next
+if DBG
+ mov [eax]+LsFlink, 0baddd0ffh
+ mov [eax]+LsBlink, 0baddd0ffh
+endif
+ RELEASE_SPINLOCK esi
+
+cPublicFpo 0, 0
+ pop esi
+ popfd ; restore flags including interrupts
+ fstRET ExfInterlockedRemoveHeadList
+
+Eirh50: RELEASE_SPINLOCK edx
+ popfd
+ xor eax,eax ; (eax) = null for empty list
+ fstRET ExfInterlockedRemoveHeadList
+
+cPublicFpo 0, 0
+Eirh60: popfd
+ SPIN_ON_SPINLOCK edx, <Eirh40>
+ fstRET ExfInterlockedRemoveHeadList
+
+endif ; nt_up
+
+fstENDP ExfInterlockedRemoveHeadList
+
+ page , 132
+ subttl "Interlocked Pop Entry List"
+;++
+;
+; PSINGLE_LIST_ENTRY
+; FASTCALL
+; ExfInterlockedPopEntryList (
+; 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:
+;
+; (ecx) = ListHead - Supplies a pointer to the head of the singly linked
+; list from which an entry is to be removed.
+;
+; (edx) = Lock - 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.
+;
+;--
+
+cPublicFastCall ExfInterlockedPopEntryList , 2
+
+ifdef NT_UP
+;
+; UP version
+;
+cPublicFpo 0,1
+ pushfd
+ cli ; disable interrupts
+
+ mov eax, [ecx] ; (eax)-> next entry
+ or eax, eax ; Is it empty?
+ je short Eipe05 ; if e, empty list, go Eipe05
+ mov edx, [eax] ; (edx)->next entry (after deletion)
+ mov [ecx], edx ; store address of next in head
+if DBG
+ mov [eax], 0baddd0ffh
+endif
+cPublicFpo 0,0
+ popfd ; restore flags including interrupts
+ fstRET ExfInterlockedPopEntryList ; cReturn (eax)->removed entry
+
+Eipe05: popfd
+ xor eax,eax
+ fstRET ExfInterlockedPopEntryList ; cReturn (eax)=NULL
+
+else ; nt_up
+
+;
+; MP Version
+;
+
+cPublicFpo 0,1
+
+Eipe10: pushfd
+ cli ; disable interrupts
+
+ ACQUIRE_SPINLOCK edx, <short Eipe30>
+
+ mov eax, [ecx] ; (eax)-> next entry
+ or eax, eax ; Is it empty?
+ je short Eipe20 ; if e, empty list, go Eipe20
+cPublicFpo 0,2
+ push edx ; Save SpinLock address
+ mov edx, [eax] ; (edx)->next entry (after deletion)
+ mov [ecx], edx ; store address of next in head
+ pop edx ; Restore SpinLock address
+if DBG
+ mov [eax], 0baddd0ffh
+endif
+ RELEASE_SPINLOCK edx
+
+cPublicFpo 0,0
+ popfd ; restore flags including interrupts
+ fstRET ExfInterlockedPopEntryList
+
+Eipe20: RELEASE_SPINLOCK edx
+ popfd
+ xor eax,eax
+ fstRET ExfInterlockedPopEntryList
+
+Eipe30: popfd
+ SPIN_ON_SPINLOCK edx, Eipe10
+
+endif ; nt_up
+
+fstENDP ExfInterlockedPopEntryList
+
+ page , 132
+ subttl "Interlocked Push Entry List"
+;++
+;
+; PSINGLE_LIST_ENTRY
+; FASTCALL
+; 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:
+;
+; (ecx) ListHead - Supplies a pointer to the head of the singly linked
+; list 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.
+;
+; (esp+4) Lock - 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.
+;
+;--
+
+cPublicFastCall ExfInterlockedPushEntryList , 3
+ifdef NT_UP
+;
+; UP Version
+;
+cPublicFpo 0,1
+ pushfd
+ cli
+
+ mov eax, [ecx] ; (eax)-> next entry (return value also)
+ mov [edx], eax ; store address of next in new entry
+ mov [ecx], edx ; set address of next in head
+
+cPublicFpo 0,0
+ popfd ; restore flags including interrupts
+ fstRET ExfInterlockedPushEntryList
+
+else
+;
+; MP Version
+;
+
+cPublicFpo 1,1
+ pushfd
+ push edx
+ mov edx, [esp+12] ; (edx) = SpinLock
+
+Eipl10: cli
+ ACQUIRE_SPINLOCK edx, <short Eipl20>
+
+ pop edx ; (edx)-> Entry to be pushed
+ mov eax, [ecx] ; (eax)-> next entry (return value also)
+ mov [edx], eax ; store address of next in new entry
+ mov [ecx], edx ; set address of next in head
+
+ mov edx, [esp+8] ; (edx) = SpinLock
+ RELEASE_SPINLOCK edx
+
+cPublicFpo 0,0
+ popfd ; restore flags including interrupts
+ fstRET ExfInterlockedPushEntryList
+
+cPublicFpo 1,2
+Eipl20: pop edx
+ popfd ; Restore interrupt state
+
+ pushfd
+ push edx
+ mov edx, [esp+12]
+ SPIN_ON_SPINLOCK edx, <short Eipl10>
+endif
+
+fstENDP ExfInterlockedPushEntryList
+
+ page , 132
+ subttl "Interlocked Pop Entry Sequenced List"
+;++
+;
+; PSINGLE_LIST_ENTRY
+; FASTCALL
+; ExInterlockedPopEntrySList (
+; IN PSINGLE_LIST_ENTRY ListHead,
+; IN PKSPIN_LOCK Lock
+; )
+;
+; 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.
+;
+; 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
+; pop entry code which has a compatible calling sequence and data
+; structure.
+;
+; Arguments:
+;
+; (ecx) = ListHead - Supplies a pointer to the sequenced listhead from
+; which an entry is to be removed.
+;
+; (edx) = Lock - 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.
+;
+;--
+
+cPublicFastCall ExInterlockedPopEntrySList, 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 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
+ mov ecx, edx ; copy sequence number and depth
+ add ecx, 0FFFFH ; adjust sequence number and depth
+
+;
+; 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.
+;
+
+ mov ebx, [eax] ; get address of successor entry
+
+.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
+
+if DBG
+
+ or ebx, ebx ; check if list is empty
+ jz short Epop20 ; if z set, list is empty
+ mov ecx, [ebx] ; check if next address is valid
+
+endif
+
+;
+; Restore nonvolatile registers and return result.
+;
+
+cPublicFpo 0,0
+
+Epop20: pop ebp ; restore nonvolatile registers
+ pop ebx ;
+
+ fstRET ExInterlockedPopEntrySList
+
+fstENDP ExInterlockedPopEntrySList
+
+ page , 132
+ subttl "Interlocked Push Entry Sequenced List"
+;++
+;
+; PSINGLE_LIST_ENTRY
+; FASTCALL
+; ExInterlockedPushEntrySList (
+; 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 sequenced singly linked
+; list so that access to the list is synchronized in an MP system.
+;
+; 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
+; push entry code which has a compatible calling sequence and data
+; structure.
+;
+; 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.
+;
+; (esp+4) Lock - 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.
+;
+;--
+
+cPublicFastCall ExInterlockedPushEntrySList, 3
+
+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
+ mov ecx, edx ; copy sequence number
+ add ecx, 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 ExInterlockedPushEntrySList
+
+fstENDP ExInterlockedPushEntrySList
+
+ page , 132
+ subttl "Interlocked Pop Entry SList - Alternate"
+;++
+;
+; PSINGLE_LIST_ENTRY
+; FASTCALL
+; ExfInterlockedPopEntrySList (
+; IN PSINGLE_LIST_ENTRY ListHead,
+; IN PKSPIN_LOCK Lock
+; )
+;
+; 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.
+;
+; N.B. The cmpxchg8b instruction is only supported on some processors.
+; If the host processor does not support this instruction, then
+; this function is used inplace of ExInterlockedPopEntrySList.
+;
+; Arguments:
+;
+; (ecx) = ListHead - Supplies a pointer to the sequenced listhead from
+; which an entry is to be removed.
+;
+; (edx) = Lock - 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.
+;
+;
+;--
+
+cPublicFastCall ExfInterlockedPopEntrySList, 2
+
+cPublicFpo 0,1
+Efpo10: pushfd ; save flags
+ cli ; disable interrupts
+
+ifndef NT_UP
+
+ ACQUIRE_SPINLOCK edx, <short Efpo30> ; acquire spinlock
+
+endif
+
+ mov eax, [ecx] ; get current next link
+ or eax, eax ; check if list is empty
+ jz short Efpo20 ; if z set, list is empty
+ push [eax] ; get address of successor list
+ pop [ecx] ; store address of next in head
+ dec dword ptr [ecx] + 4 ; decrement list depth
+
+Efpo20: ;
+
+ifndef NT_UP
+
+ RELEASE_SPINLOCK edx ; release spinlock
+
+endif
+
+cPublicFpo 0,0
+ popfd ; restore flags
+
+ fstRET ExfInterlockedPopEntrySList
+
+ifndef NT_UP
+
+cPublicFpo 0,0
+Efpo30: popfd ; restore flags
+
+ SPIN_ON_SPINLOCK edx, Efpo10 ; spin until lock is free
+
+endif
+
+fstENDP ExfInterlockedPopEntrySList
+
+ page , 132
+ subttl "Interlocked Push Entry SList - Alternate"
+;++
+;
+; PSINGLE_LIST_ENTRY
+; FASTCALL
+; 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 sequenced singly linked
+; list so that access to the list is synchronized in an MP system.
+;
+; N.B. The cmpxchg8b instruction is only supported on some processors.
+; If the host processor does not support this instruction, then
+; this function is used inplace of ExInterlockedPushEntrySList.
+;
+; 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.
+;
+; (esp+4) Lock - 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.
+;--
+
+cPublicFastCall ExfInterlockedPushEntrySList, 3
+
+cPublicFpo 0,1
+Efph10: pushfd ; save flags
+ cli ; disable interrupts
+
+ifndef NT_UP
+
+ mov eax, [esp] + 8 ; get spinlock address
+
+ ACQUIRE_SPINLOCK eax, <short Efph20> ; acquire spinlock
+
+endif
+
+ push [ecx] ; get current next link
+ pop [edx] ; store address of next in new entry
+ mov [ecx], edx ; set address of next in head
+ inc dword ptr [ecx] + 4 ; increment list depth
+
+ifndef NT_UP
+
+ RELEASE_SPINLOCK eax ; release spinlock
+endif
+
+cPublicFpo 0,0
+ popfd ; restore flags
+
+ fstRET ExfInterlockedPushEntrySList
+
+ifndef NT_UP
+
+cPublicFpo 0,0
+Efph20: popfd ; restore flags
+
+ SPIN_ON_SPINLOCK eax, <short Efph10> ; spin until lock is free
+
+endif
+
+fstENDP ExfInterlockedPushEntrySList
+
+ page , 132
+ subttl "Interlocked i386 Increment Long"
+;++
+;
+; INTERLOCKED_RESULT
+; FASTCALL
+; Exfi386InterlockedIncrementLong (
+; IN PLONG Addend
+; )
+;
+; Routine Description:
+;
+; This function atomically increments Addend, returning an ennumerated
+; type which indicates what interesting transitions in the value of
+; Addend occurred due the operation.
+;
+; See ExInterlockedIncrementLong. This function is the i386
+; architectural specific version of ExInterlockedIncrementLong.
+; No source directly calls this function, instead
+; ExInterlockedIncrementLong is called and when built on x86 these
+; calls are macroed to the i386 optimized version.
+;
+; Arguments:
+;
+; (ecx) Addend - Pointer to variable to increment.
+;
+; Return Value:
+;
+; An ennumerated type:
+;
+; ResultNegative if Addend is < 0 after increment.
+; ResultZero if Addend is = 0 after increment.
+; ResultPositive if Addend is > 0 after increment.
+;
+;--
+
+cPublicFastCall Exfi386InterlockedIncrementLong, 1
+cPublicFpo 0, 0
+
+ifdef NT_UP
+ add dword ptr [ecx],1
+else
+ lock add dword ptr [ecx],1
+endif
+ lahf ; (ah) = flags
+ and eax,EFLAG_SELECT ; clear all but sign and zero flags
+ fstRET Exfi386InterlockedIncrementLong
+
+fstENDP Exfi386InterlockedIncrementLong
+
+
+ page , 132
+ subttl "Interlocked i386 Decrement Long"
+;++
+;
+; INTERLOCKED_RESULT
+; FASTCALL
+; Exfi386InterlockedDecrementLong (
+; IN PLONG Addend,
+; IN PKSPIN_LOCK Lock
+; )
+;
+; Routine Description:
+;
+; This function atomically decrements Addend, returning an ennumerated
+; type which indicates what interesting transitions in the value of
+; Addend occurred due the operation.
+;
+; See Exi386InterlockedDecrementLong. This function is the i386
+; architectural specific version of ExInterlockedDecrementLong.
+; No source directly calls this function, instead
+; ExInterlockedDecrementLong is called and when built on x86 these
+; calls are macroed to the i386 optimized version.
+;
+; Arguments:
+;
+; Addend (esp+4) - Pointer to variable to decrement.
+;
+; Lock (esp+8) - Spinlock used to implement atomicity.
+; (not actually used on x86)
+;
+; Return Value:
+;
+; An ennumerated type:
+;
+; ResultNegative if Addend is < 0 after decrement.
+; ResultZero if Addend is = 0 after decrement.
+; ResultPositive if Addend is > 0 after decrement.
+;
+;--
+
+cPublicFastCall Exfi386InterlockedDecrementLong , 1
+cPublicFpo 0, 0
+
+ifdef NT_UP
+ sub dword ptr [ecx], 1
+else
+ lock sub dword ptr [ecx], 1
+endif
+ lahf ; (ah) = flags
+ and eax, EFLAG_SELECT ; clear all but sign and zero flags
+ fstRET Exfi386InterlockedDecrementLong
+
+fstENDP Exfi386InterlockedDecrementLong
+
+ page , 132
+ subttl "Interlocked i386 Exchange Ulong"
+;++
+;
+; ULONG
+; FASTCALL
+; Exfi386InterlockedExchangeUlong (
+; IN PULONG Target,
+; IN ULONG Value
+; )
+;
+; Routine Description:
+;
+; This function atomically exchanges the Target and Value, returning
+; the prior contents of Target
+;
+; See Exi386InterlockedExchangeUlong. This function is the i386
+; architectural specific version of ExInterlockedDecrementLong.
+; No source directly calls this function, instead
+; ExInterlockedDecrementLong is called and when built on x86 these
+; calls are macroed to the i386 optimized version.
+;
+; Arguments:
+;
+; (ecx) = Source - Address of ULONG to exchange
+; (edx) = Value - New value of ULONG
+;
+; Return Value:
+;
+; The prior value of Source
+;--
+
+cPublicFastCall Exfi386InterlockedExchangeUlong, 2
+cPublicFpo 0,0
+cPublicFastCall InterlockedExchange, 2
+
+.486
+ifndef NT_UP
+ xchg [ecx], edx ; make the exchange
+ mov eax, edx
+else
+ mov eax, [ecx] ; get comperand value
+Ixchg: cmpxchg [ecx], edx ; compare and swap
+ jnz Ixchg ; if nz, exchange failed
+endif
+.386
+
+ fstRET Exfi386InterlockedExchangeUlong
+fstENDP InterlockedExchange
+fstENDP Exfi386InterlockedExchangeUlong
+
+;++
+;
+; LONG
+; InterlockedIncrement(
+; IN PLONG Addend
+; )
+;
+; Routine Description:
+;
+; This function performs an interlocked add of one to the addend variable.
+;
+; No checking is done for overflow.
+;
+; Arguments:
+;
+; Addend (ecx) - Supplies a pointer to a variable whose value is to be
+; incremented by one.
+;
+; Return Value:
+;
+; (eax) - The incremented value.
+;
+;--
+
+cPublicFastCall InterlockedIncrement,1
+cPublicFpo 0,0
+
+ mov eax, 1 ; set increment value
+
+.486
+ifndef NT_UP
+ lock xadd [ecx], eax ; interlocked increment
+else
+ xadd [ecx], eax ; interlocked increment
+endif
+.386p
+ inc eax ; adjust return value
+
+ fstRET InterlockedIncrement
+
+fstENDP InterlockedIncrement
+
+ page , 132
+ subttl "InterlockedDecrment"
+;++
+;
+; LONG
+; InterlockedDecrement(
+; IN PLONG Addend
+; )
+;
+; Routine Description:
+;
+; This function performs an interlocked add of -1 to the addend variable.
+;
+; No checking is done for overflow
+;
+; Arguments:
+;
+; Addend (ecx) - Supplies a pointer to a variable whose value is to be
+; decremented by one.
+;
+; Return Value:
+;
+; (eax) - The decremented value.
+;
+;--
+
+cPublicFastCall InterlockedDecrement,1
+cPublicFpo 0,0
+
+ mov eax, -1 ; set decrment value
+
+.486
+ifndef NT_UP
+ lock xadd [ecx], eax ; interlocked decrement
+else
+ xadd [ecx], eax ; interlocked decrement
+endif
+.386
+
+ dec eax ; adjust return value
+
+ fstRET InterlockedDecrement
+
+fstENDP InterlockedDecrement
+
+ page , 132
+ subttl "Interlocked Compare Exchange"
+;++
+;
+; PVOID
+; FASTCALL
+; InterlockedCompareExchange (
+; IN OUT PVOID *Destination,
+; IN PVOID Exchange,
+; IN PVOID Comperand
+; )
+;
+; Routine Description:
+;
+; This function performs an interlocked compare of the destination
+; value with the comperand value. If the destination value is equal
+; to the comperand value, then the exchange value is stored in the
+; destination. Otherwise, no operation is performed.
+;
+; Arguments:
+;
+; (ecx) Destination - Supplies a pointer to destination value.
+;
+; (edx) Exchange - Supplies the exchange value.
+;
+; [esp + 4] Comperand - Supplies the comperand value.
+;
+; Return Value:
+;
+; The initial destination value is returned as the function value.
+;
+;--
+
+cPublicFastCall InterlockedCompareExchange, 3
+cPublicFpo 0,0
+
+ mov eax, [esp + 4] ; set comperand value
+.486
+ifndef NT_UP
+ lock cmpxchg [ecx], edx ; compare and exchange
+else
+ cmpxchg [ecx], edx ; compare and exchange
+endif
+.386
+
+ fstRET InterlockedCompareExchange
+
+fstENDP InterlockedCompareExchange
+
+ page , 132
+ subttl "Interlocked Compare Exchange 64-bits"
+;++
+;
+; ULONGLONG
+; FASTCALL
+; ExInterlockedCompareExchange64 (
+; IN PULONGLONG Destination,
+; IN PULONGLONG Exchange,
+; IN PULONGLONG Comperand,
+; IN PKSPIN_LOCK Lock
+; )
+;
+; Routine Description:
+;
+; This function performs a compare and exchange of 64-bits.
+;
+; 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
+; compare exchange 64-bit code which has a compatible calling
+; sequence and data structure.
+;
+; 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.
+;
+; (esp+4) Lock - Supplies a pointer to a spin lock to use if the cmpxchg8b
+; instruction is not available on the host system.
+;
+; Return Value:
+;
+; The current destination value is returned as the function value.
+;
+;--
+
+cPublicFastCall ExInterlockedCompareExchange64, 4
+
+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 ExInterlockedCompareExchange64
+
+fstENDP ExInterlockedCompareExchange64
+
+;
+; The following version of the compare exchange 64-bits function is used
+; when the host processor does not support the cmpxchg8 instruction.
+;
+
+cPublicFastCall ExpInterlockedCompareExchange64, 4
+
+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 ;
+
+ifndef NT_UP
+
+cPublicFpo 0,4
+
+ push esi ; save register
+ pushfd ; save flags
+ mov esi, [esp] + 24 ; get address of lock
+Eicx10: cli ; disable interrupts
+
+ ACQUIRE_SPINLOCK esi, <short Eicx40> ; acquire spinlock
+
+else
+
+cPublicFpo 0,3
+
+ pushfd ; save flags
+ cli ; disable interrupts
+
+endif
+
+ cmp eax, [ebp] ; compare current with comperand
+ jne short Eicx30 ; if ne, low part mismatch
+ cmp edx, [ebp] + 4 ; compare current with comperand
+ jne short Eicx30 ; if ne, high part mismatch
+ mov [ebp], ebx ; store exchange value
+ mov [ebp] + 4, ecx ;
+
+;
+; Restore nonvolatile registers and return result in edx:eax.
+;
+
+cPublicFpo 0,0
+
+ifndef NT_UP
+
+Eicx20: RELEASE_SPINLOCK esi ; release spin lock
+
+ popfd ; restore flags
+ pop esi ; restore register
+
+else
+
+Eicx20: popfd ; restore flags
+
+endif
+
+ pop ebp ; restore nonvolatile registers
+ pop ebx ;
+
+ fstRET ExpInterlockedCompareExchange64
+
+;
+; The current and comperand values mismatch. Return the current destination
+; value.
+;
+
+Eicx30: mov eax, [ebp] ; get current destination value
+ mov edx, [ebp] + 4 ;
+ jmp short Eicx20 ;
+
+;
+; The spinlock is currently owned.
+;
+
+ifndef NT_UP
+
+Eicx40: popfd ; restore flags
+ pushfd ; save flags
+
+ SPIN_ON_SPINLOCK esi, <short Eicx10> ; spin until lock free
+
+endif
+
+fstENDP ExpInterlockedCompareExchange64
+
+ page , 132
+ subttl "Interlocked Exchange Add"
+;++
+;
+; LONG
+; FASTCALL
+; InterlockedExchangeAdd (
+; IN OUT PLONG Addend,
+; IN LONG Increment
+; )
+;
+; 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.
+;
+; It is NOT possible to mix ExInterlockedDecrementLong and
+; ExInterlockedIncrementong with ExInterlockedAddUlong.
+;
+;
+; Arguments:
+;
+; (ecx) Addend - Supplies a pointer to a variable whose value is to be
+; adjusted by the increment value.
+;
+; (edx) Increment - Supplies the increment value to be added to the
+; addend variable.
+;
+; Return Value:
+;
+; The initial value of the addend variable.
+;
+;--
+
+cPublicFastCall InterlockedExchangeAdd, 2
+cPublicFpo 0,0
+
+.486
+ifndef NT_UP
+ lock xadd [ecx], edx ; exchange add
+else
+ xadd [ecx], edx ; exchange add
+endif
+.386
+
+ mov eax, edx ; set initial value
+
+ fstRET InterlockedExchangeAdd
+
+fstENDP InterlockedExchangeAdd
+
+_TEXT$00 ends
+ end
diff --git a/private/ntos/ex/i386/intrlock.asm b/private/ntos/ex/i386/intrlock.asm
new file mode 100644
index 000000000..4891af4e8
--- /dev/null
+++ b/private/ntos/ex/i386/intrlock.asm
@@ -0,0 +1,1054 @@
+ 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
+include mac386.inc
+ .list
+
+
+_TEXT$00 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
+
+ifndef NT_UP
+ mov eax,EiulLock ; (eax) -> KSPIN_LOCK
+endif
+
+eiul10: pushfd
+ cli ; disable interrupts
+ ACQUIRE_SPINLOCK eax,<short eiul20>
+
+ 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
+
+ifndef NT_UP
+ mov eax,EiulLock
+ RELEASE_SPINLOCK eax ; NOTHING if NT_UP = 1
+endif
+ popfd ; restore flags including interrupts
+ mov eax, EiulRetval ; calling convention
+ mov edx, EiulRetval+4 ; calling convention
+ mov esp, ebp
+ pop ebp
+ stdRET _ExInterlockedAddLargeInteger
+
+ifndef NT_UP
+eiul20: popfd
+ SPIN_ON_SPINLOCK eax, eiul10
+endif
+
+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
+ifndef NT_UP
+
+ lock cmpxchg8b qword ptr [ebp] ; compare and exchange
+
+else
+
+ cmpxchg8b qword ptr [ebp] ; compare and exchange
+
+endif
+.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
+
+ page , 132
+ 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.
+;
+; It is NOT possible to mix ExInterlockedDecrementLong and
+; ExInterlockedIncrementong with ExInterlockedAddUlong.
+;
+;
+; Arguments:
+;
+; Addend - Supplies a pointer to a variable whose value is to be
+; adjusted by the increment value.
+;
+; Increment - Supplies the increment value to be added to the
+; addend variable.
+;
+; Lock - 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.
+;
+;--
+
+EialAddend equ [esp + 8]
+EialIncrement equ [esp + 12]
+EialLock equ [esp + 16]
+
+; end of arguments
+
+cPublicProc _ExInterlockedAddUlong , 3
+cPublicFpo 3, 1
+
+ifdef NT_UP
+;
+; UP version of ExInterlockedAddUlong
+;
+
+ pushfd
+ cli ; disable interrupts
+
+ mov ecx, EialAddend ; (ecx)->initial addend value
+ mov edx, [ecx] ; (edx)= initial addend value
+ mov eax, edx ; (eax)= initial addend value
+ add edx, EialIncrement ; (edx)=adjusted value
+ mov [ecx], edx ; [ecx]=adjusted value
+
+ popfd ; restore flags including ints
+ stdRET _ExInterlockedAddUlong ; cRetURN
+
+else
+
+;
+; MP version of ExInterlockedAddUlong
+;
+ pushfd
+ mov edx,EialLock ; (edx)-> KSPIN_LOCK
+Eial10: cli ; disable interrupts
+ ACQUIRE_SPINLOCK edx, <short Eial20>
+
+ mov ecx, EialAddend ; (ecx)->initial addend value
+ mov eax, [ecx] ; (eax)=initial addend value
+ add eax, EialIncrement ; (eax)=adjusted value
+ mov [ecx], eax ; [ecx]=adjusted value
+ sub eax, EialIncrement ; (eax)=initial addend value
+
+ RELEASE_SPINLOCK edx
+ popfd
+ stdRET _ExInterlockedAddUlong ; cRetURN
+
+Eial20: popfd
+ pushfd
+ SPIN_ON_SPINLOCK edx, <short Eial10>
+endif
+
+stdENDP _ExInterlockedAddUlong
+
+
+ page , 132
+ 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.
+;
+; N.B. The pages of data which this routine operates on MUST be
+; present. No page fault is allowed in this routine.
+;
+; Arguments:
+;
+; ListHead - Supplies a pointer to the head of the doubly linked
+; list into which an entry is to be inserted.
+;
+; ListEntry - Supplies a pointer to the entry to be inserted at the
+; head of the list.
+;
+; Lock - 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.
+;
+;--
+
+EiihListHead equ [esp + 8]
+EiihListEntry equ [esp + 12]
+EiihLock equ [esp + 16]
+
+; end arguments
+
+cPublicProc _ExInterlockedInsertHeadList , 3
+cPublicFpo 3, 1
+
+ifndef NT_UP
+ mov edx, EiihLock - 4 ; (edx)->KSPIN_LOCK
+endif
+Eiih10: pushfd
+ cli
+ ACQUIRE_SPINLOCK edx,<short Eiih20>
+
+ mov eax, EiihListHead ; (eax)->head of linked list
+ mov ecx, EiihListEntry ; (ecx)->entry to be inserted
+ mov edx, LsFlink[eax] ; (edx)->next entry in the list
+ mov [ecx]+LsFlink, edx ; store next link in entry
+ mov [ecx]+LsBlink, eax ; store previous link in entry
+ mov [eax]+LsFlink, ecx ; store next link in head
+ mov [edx]+LsBlink, ecx ; store previous link in next
+
+ifndef NT_UP
+ mov ecx, EiihLock ; (ecx)->KSPIN_LOCK
+ RELEASE_SPINLOCK ecx
+endif
+cPublicFpo 3, 0
+ popfd ; restore flags including interrupts
+
+ xor eax,edx ; return null if list was empty
+ jz short Eiih15
+ mov eax,edx ; otherwise return prev. entry at head
+Eiih15:
+ stdRET _ExInterlockedInsertHeadList
+
+ifndef NT_UP
+align 4
+Eiih20: popfd
+ SPIN_ON_SPINLOCK edx, <short Eiih10>
+endif
+
+stdENDP _ExInterlockedInsertHeadList
+
+
+ page , 132
+ 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.
+;
+; N.B. The pages of data which this routine operates on MUST be
+; present. No page fault is allowed in this routine.
+;
+; Arguments:
+;
+; ListHead - Supplies a pointer to the head of the doubly linked
+; list into which an entry is to be inserted.
+;
+; ListEntry - Supplies a pointer to the entry to be inserted at the
+; tail of the list.
+;
+; Lock - 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.
+;
+;--
+
+EiitListHead equ [esp + 8]
+EiitListEntry equ [esp + 12]
+EiitLock equ [esp + 16]
+
+; end arguments
+
+cPublicProc _ExInterlockedInsertTailList , 3
+cPublicFpo 3, 1
+
+
+ifndef NT_UP
+ mov edx,EiitLock - 4 ; (edx)->KSPIN_LOCK
+endif
+
+Eiit10: pushfd
+ cli ; disable interrupts
+ ACQUIRE_SPINLOCK edx, <short Eiit20>
+
+ mov eax, EiihListHead ; (eax)->head of linked list
+ mov ecx, EiihListEntry ; (ecx)->entry to be inserted
+ mov edx, LsBlink[eax] ; (edx)->previous entry in the list
+ mov [ecx]+LsFlink, eax ; store next link in entry
+ mov [ecx]+LsBlink, edx ; store previous link in entry
+ mov [eax]+LsBlink, ecx ; store previous link in head
+ mov [edx]+LsFlink, ecx ; store next link in next
+
+ifndef NT_UP
+ mov ecx,EiitLock ; (ecx)->KSPIN_LOCK
+ RELEASE_SPINLOCK ecx
+endif
+cPublicFpo 3,0
+ popfd ; restore flags including interrupts
+
+ xor eax,edx ; return null if list was empty
+ jz short Eiit15
+ mov eax,edx ; otherwise return prev. entry at tail
+Eiit15:
+ stdRET _ExInterlockedInsertTailList
+
+ifndef NT_UP
+align 4
+Eiit20: popfd
+ SPIN_ON_SPINLOCK edx, <short Eiit10>
+endif
+
+stdENDP _ExInterlockedInsertTailList
+
+ page , 132
+ 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.
+;
+; N.B. The pages of data which this routine operates on MUST be
+; present. No page fault is allowed in this routine.
+;
+; Arguments:
+;
+; ListHead - Supplies a pointer to the head of the doubly linked
+; list from which an entry is to be removed.
+;
+; Lock - 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.
+;
+;--
+
+EirhListHead equ [esp + 8]
+EirhLock equ [esp + 12]
+
+; end of arguments
+
+cPublicProc _ExInterlockedRemoveHeadList , 2
+cPublicFpo 2, 1
+
+ifndef NT_UP
+ mov edx, EirhLock - 4 ; (edx)-> KSPIN_LOCK
+endif
+
+Eirh10: pushfd
+ cli
+
+ ACQUIRE_SPINLOCK edx, <Eirh30>
+
+ mov edx, EirhListHead ; (edx)-> head of list
+ mov eax, [edx]+LsFlink ; (eax)-> next entry
+ cmp eax, edx ; Is list empty?
+ je short Eirh20 ; if e, list is empty, go Eirh20
+ mov ecx, [eax]+LsFlink ; (ecx)-> next entry(after deletion)
+ mov [edx]+LsFlink, ecx ; store address of next in head
+ mov [ecx]+LsBlink, edx ; store address of previous in next
+if DBG
+ mov [eax]+LsFlink, 0baddd0ffh
+ mov [eax]+LsBlink, 0baddd0ffh
+endif
+ifndef NT_UP
+ mov edx, EirhLock ; (edx)-> KSPIN_LOCK
+ RELEASE_SPINLOCK edx
+endif
+cPublicFpo 2, 0
+ popfd ; restore flags including interrupts
+ stdRET _ExInterlockedRemoveHeadList ; cReturn entry
+
+align 4
+Eirh20:
+ifndef NT_UP
+ mov edx, EirhLock ; (edx)-> KSPIN_LOCK
+ RELEASE_SPINLOCK edx
+endif
+ popfd
+ xor eax,eax ; (eax) = null for empty list
+ stdRET _ExInterlockedRemoveHeadList ; cReturn NULL
+
+ifndef NT_UP
+align 4
+Eirh30: popfd
+ SPIN_ON_SPINLOCK edx, Eirh10
+endif
+
+stdENDP _ExInterlockedRemoveHeadList
+
+ page , 132
+ 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 - Supplies a pointer to the head of the singly linked
+; list from which an entry is to be removed.
+;
+; Lock - 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.
+;
+;--
+
+; end of arguments
+
+cPublicProc _ExInterlockedPopEntryList , 2
+cPublicFpo 2,1
+
+ifndef NT_UP
+ mov edx, [esp+8] ; (edx)-> KSPIN_LOCK
+endif
+
+Eipe10: pushfd
+ cli ; disable interrupts
+
+ ACQUIRE_SPINLOCK edx, <short Eipe30>
+
+ mov ecx, [esp+8] ; (ecx)-> head of list
+ mov eax, [ecx] ; (eax)-> next entry
+ or eax, eax ; Is it empty?
+ je short Eipe20 ; if e, empty list, go Eipe20
+ mov edx, [eax] ; (edx)->next entry (after deletion)
+ mov [ecx], edx ; store address of next in head
+if DBG
+ mov [eax], 0baddd0ffh
+endif
+ifndef NT_UP
+ mov edx, [esp+12] ; (edx)-> KSPIN_LOCK
+ RELEASE_SPINLOCK edx
+endif
+cPublicFpo 2,0
+ popfd ; restore flags including interrupts
+ stdRET _ExInterlockedPopEntryList ; cReturn (eax)->removed entry
+
+align 4
+Eipe20: RELEASE_SPINLOCK edx
+ popfd
+ xor eax,eax
+ stdRET _ExInterlockedPopEntryList ; cReturn (eax)=NULL
+
+ifndef NT_UP
+align 4
+Eipe30: popfd
+ SPIN_ON_SPINLOCK edx, Eipe10
+endif
+
+stdENDP _ExInterlockedPopEntryList
+
+ page , 132
+ 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 - Supplies a pointer to the head of the singly linked
+; list into which an entry is to be inserted.
+;
+; ListEntry - Supplies a pointer to the entry to be inserted at the
+; head of the list.
+;
+; Lock - 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.
+;
+;--
+
+; end of arguments
+
+cPublicProc _ExInterlockedPushEntryList , 3
+cPublicFpo 3,1
+
+ifndef NT_UP
+ mov edx, [esp+12] ; (edx)->KSPIN_LOCK
+endif
+
+Eipl10: pushfd
+ cli
+
+ ACQUIRE_SPINLOCK edx, <short Eipl20>
+
+ mov edx, [esp+8] ; (edx)-> Head of list
+ mov eax, [edx] ; (eax)-> next entry (return value also)
+ mov ecx, [esp+12] ; (ecx)-> Entry to be pushed
+ mov [ecx], eax ; store address of next in new entry
+ mov [edx], ecx ; set address of next in head
+
+ifndef NT_UP
+ mov edx, [esp+16] ; (edx)->KSPIN_LOCK
+ RELEASE_SPINLOCK edx
+endif
+cPublicFpo 3,0
+ popfd ; restore flags including interrupts
+ stdRET _ExInterlockedPushEntryList
+
+ifndef NT_UP
+align 4
+Eipl20: popfd
+ SPIN_ON_SPINLOCK edx, <short Eipl10>
+endif
+
+stdENDP _ExInterlockedPushEntryList
+
+ page , 132
+ subttl "Interlocked Increment Long"
+;++
+;
+; INTERLOCKED_RESULT
+; ExInterlockedIncrementLong (
+; IN PLONG Addend,
+; IN PKSPIN_LOCK Lock
+; )
+;
+; Routine Description:
+;
+; This function atomically increments Addend, returning an ennumerated
+; type which indicates what interesting transitions in the value of
+; Addend occurred due the operation.
+;
+; It is NOT possible to mix ExInterlockedDecrementLong and
+; ExInterlockedIncrementong with ExInterlockedAddUlong.
+;
+;
+; Arguments:
+;
+; Addend (esp+4) - Pointer to variable to increment.
+;
+; Lock (esp+8) - Spinlock used to implement atomicity.
+; (not actually used on x86)
+;
+; Return Value:
+;
+; An ennumerated type:
+;
+; ResultNegative if Addend is < 0 after increment.
+; ResultZero if Addend is = 0 after increment.
+; ResultPositive if Addend is > 0 after increment.
+;
+;--
+
+cPublicProc _ExInterlockedIncrementLong , 2
+cPublicFpo 2, 0
+
+ mov eax, [esp+4] ; (eax) -> addend
+ifdef NT_UP
+ add dword ptr [eax],1
+else
+ lock add dword ptr [eax],1
+endif
+ lahf ; (ah) = flags
+ and eax,EFLAG_SELECT ; clear all but sign and zero flags
+ stdRET _ExInterlockedIncrementLong
+
+stdENDP _ExInterlockedIncrementLong
+
+
+ page , 132
+ subttl "Interlocked Decrement Long"
+;++
+;
+; INTERLOCKED_RESULT
+; ExInterlockedDecrementLong (
+; IN PLONG Addend,
+; IN PKSPIN_LOCK Lock
+; )
+;
+; Routine Description:
+;
+; This function atomically decrements Addend, returning an ennumerated
+; type which indicates what interesting transitions in the value of
+; Addend occurred due the operation.
+;
+; It is NOT possible to mix ExInterlockedDecrementLong and
+; ExInterlockedIncrementong with ExInterlockedAddUlong.
+;
+; Arguments:
+;
+; Addend (esp+4) - Pointer to variable to decrement.
+;
+; Lock (esp+8) - Spinlock used to implement atomicity.
+; (not actually used on x86)
+;
+; Return Value:
+;
+; An ennumerated type:
+;
+; ResultNegative if Addend is < 0 after decrement.
+; ResultZero if Addend is = 0 after decrement.
+; ResultPositive if Addend is > 0 after decrement.
+;
+;--
+
+cPublicProc _ExInterlockedDecrementLong , 2
+cPublicFpo 2, 0
+
+ mov eax, [esp+4] ; (eax) -> addend
+ifdef NT_UP
+ sub dword ptr [eax], 1
+else
+ lock sub dword ptr [eax], 1
+endif
+ lahf ; (ah) = flags
+ and eax, EFLAG_SELECT ; clear all but sign and zero flags
+ stdRET _ExInterlockedDecrementLong
+
+stdENDP _ExInterlockedDecrementLong
+
+ page , 132
+ subttl "Interlocked Exchange Ulong"
+;++
+;
+; ULONG
+; ExInterlockedExchangeUlong (
+; IN PULONG Target,
+; IN ULONG Value,
+; IN PKSPIN_LOCK Lock
+; )
+;
+; Routine Description:
+;
+; This function atomically exchanges the Target and Value, returning
+; the prior contents of Target
+;
+; This function does not necessarily synchronize with the Lock.
+;
+; Arguments:
+;
+; Target - Address of ULONG to exchange
+; Value - New value of ULONG
+; Lock - SpinLock used to implement atomicity.
+;
+; Return Value:
+;
+; The prior value of Source
+;--
+
+cPublicProc _ExInterlockedExchangeUlong, 3
+cPublicFpo 3,0
+
+ifndef NT_UP
+ mov edx, [esp+4] ; (edx) = Target
+ mov eax, [esp+8] ; (eax) = Value
+
+ xchg [edx], eax ; make the exchange
+else
+ mov edx, [esp+4] ; (edx) = Target
+ mov ecx, [esp+8] ; (eax) = Value
+
+ pushfd
+ cli
+ mov eax, [edx] ; get current value
+ mov [edx], ecx ; store new value
+ popfd
+endif
+
+ stdRET _ExInterlockedExchangeUlong
+
+stdENDP _ExInterlockedExchangeUlong
+
+ page , 132
+ subttl "Interlocked i386 Increment Long"
+;++
+;
+; INTERLOCKED_RESULT
+; Exi386InterlockedIncrementLong (
+; IN PLONG Addend
+; )
+;
+; Routine Description:
+;
+; This function atomically increments Addend, returning an ennumerated
+; type which indicates what interesting transitions in the value of
+; Addend occurred due the operation.
+;
+; See ExInterlockedIncrementLong. This function is the i386
+; architectural specific version of ExInterlockedIncrementLong.
+; No source directly calls this function, instead
+; ExInterlockedIncrementLong is called and when built on x86 these
+; calls are macroed to the i386 optimized version.
+;
+; Arguments:
+;
+; Addend (esp+4) - Pointer to variable to increment.
+;
+; Lock (esp+8) - Spinlock used to implement atomicity.
+; (not actually used on x86)
+;
+; Return Value:
+;
+; An ennumerated type:
+;
+; ResultNegative if Addend is < 0 after increment.
+; ResultZero if Addend is = 0 after increment.
+; ResultPositive if Addend is > 0 after increment.
+;
+;--
+
+cPublicProc _Exi386InterlockedIncrementLong , 1
+cPublicFpo 1, 0
+
+ mov eax, [esp+4] ; (eax) -> addend
+ifdef NT_UP
+ add dword ptr [eax],1
+else
+ lock add dword ptr [eax],1
+endif
+ lahf ; (ah) = flags
+ and eax,EFLAG_SELECT ; clear all but sign and zero flags
+ stdRET _Exi386InterlockedIncrementLong
+
+stdENDP _Exi386InterlockedIncrementLong
+
+
+ page , 132
+ subttl "Interlocked i386 Decrement Long"
+;++
+;
+; INTERLOCKED_RESULT
+; ExInterlockedDecrementLong (
+; IN PLONG Addend,
+; IN PKSPIN_LOCK Lock
+; )
+;
+; Routine Description:
+;
+; This function atomically decrements Addend, returning an ennumerated
+; type which indicates what interesting transitions in the value of
+; Addend occurred due the operation.
+;
+; See Exi386InterlockedDecrementLong. This function is the i386
+; architectural specific version of ExInterlockedDecrementLong.
+; No source directly calls this function, instead
+; ExInterlockedDecrementLong is called and when built on x86 these
+; calls are macroed to the i386 optimized version.
+;
+; Arguments:
+;
+; Addend (esp+4) - Pointer to variable to decrement.
+;
+; Lock (esp+8) - Spinlock used to implement atomicity.
+; (not actually used on x86)
+;
+; Return Value:
+;
+; An ennumerated type:
+;
+; ResultNegative if Addend is < 0 after decrement.
+; ResultZero if Addend is = 0 after decrement.
+; ResultPositive if Addend is > 0 after decrement.
+;
+;--
+
+cPublicProc _Exi386InterlockedDecrementLong , 1
+cPublicFpo 1, 0
+
+ mov eax, [esp+4] ; (eax) -> addend
+ifdef NT_UP
+ sub dword ptr [eax], 1
+else
+ lock sub dword ptr [eax], 1
+endif
+ lahf ; (ah) = flags
+ and eax, EFLAG_SELECT ; clear all but sign and zero flags
+ stdRET _Exi386InterlockedDecrementLong
+
+stdENDP _Exi386InterlockedDecrementLong
+
+ page , 132
+ subttl "Interlocked i386 Exchange Ulong"
+
+;++
+;
+; ULONG
+; Exi386InterlockedExchangeUlong (
+; IN PULONG Target,
+; IN ULONG Value,
+; IN PKSPIN_LOCK Lock
+; )
+;
+; Routine Description:
+;
+; This function atomically exchanges the Target and Value, returning
+; the prior contents of Target
+;
+; See Exi386InterlockedExchangeUlong. This function is the i386
+; architectural specific version of ExInterlockedDecrementLong.
+; No source directly calls this function, instead
+; ExInterlockedDecrementLong is called and when built on x86 these
+; calls are macroed to the i386 optimized version.
+;
+; Arguments:
+;
+; Source - Address of ULONG to exchange
+; Value - New value of ULONG
+; Lock - SpinLock used to implement atomicity.
+;
+; Return Value:
+;
+; The prior value of Source
+;--
+
+cPublicProc _Exi386InterlockedExchangeUlong, 2
+cPublicFpo 2,0
+
+ifndef NT_UP
+ mov edx, [esp+4] ; (edx) = Target
+ mov eax, [esp+8] ; (eax) = Value
+
+ xchg [edx], eax ; make the exchange
+else
+ mov edx, [esp+4] ; (edx) = Target
+ mov ecx, [esp+8] ; (eax) = Value
+
+ pushfd
+ cli
+ mov eax, [edx] ; get current value
+ mov [edx], ecx ; store new value
+ popfd
+endif
+
+ stdRET _Exi386InterlockedExchangeUlong
+
+stdENDP _Exi386InterlockedExchangeUlong
+
+_TEXT$00 ends
+ end
diff --git a/private/ntos/ex/i386/probe.c b/private/ntos/ex/i386/probe.c
new file mode 100644
index 000000000..e65bd0d9a
--- /dev/null
+++ b/private/ntos/ex/i386/probe.c
@@ -0,0 +1,120 @@
+/*++
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ probe.c
+
+Abstract:
+
+ This module contains implements the probe for write function.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1989
+
+Environment:
+
+ Any mode.
+
+Revision History:
+
+--*/
+
+#include "exp.h"
+
+#if defined(ALLOC_PRAGMA)
+#pragma alloc_text(PAGE, ProbeForWrite)
+#endif
+
+
+VOID
+ProbeForWrite (
+ IN PVOID Address,
+ IN ULONG Length,
+ IN ULONG Alignment
+ )
+
+/*++
+
+Routine Description:
+
+ This function probes a structure for write accessibility and ensures
+ correct alignment of the structure. If the structure is not accessible
+ or has incorrect alignment, then an exception is raised.
+
+Arguments:
+
+ Address - Supplies a pointer to the structure to be probed.
+
+ Length - Supplies the length of the structure.
+
+ Alignment - Supplies the required alignment of the structure expressed
+ as the number of bytes in the primitive datatype (e.g., 1 for char,
+ 2 for short, 4 for long, and 8 for quad).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG StartAddress;
+ ULONG EndAddress;
+
+ //
+ // If the structure has zero length, then do not probe the structure for
+ // write accessibility or alignment.
+ //
+
+ if (Length != 0) {
+
+ //
+ // If the structure is not properly aligned, then raise a data
+ // misalignment exception.
+ //
+
+ ASSERT((Alignment == 1) || (Alignment == 2) ||
+ (Alignment == 4) || (Alignment == 8));
+
+ StartAddress = (ULONG)Address;
+ if ((StartAddress & (Alignment - 1)) == 0) {
+
+ //
+ // Compute the ending address of the structure and probe for
+ // write accessibility.
+ //
+
+ EndAddress = StartAddress + Length - 1;
+ if ((StartAddress <= EndAddress) &
+ (EndAddress < MM_USER_PROBE_ADDRESS)) {
+
+ //
+ // N.B. Only the contents of the buffer may be probed.
+ // Therefore the starting byte is probed for the
+ // first page, and then the first byte in the page
+ // for each succeeding page.
+ //
+
+ EndAddress = (EndAddress & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
+ do {
+ *(volatile CHAR *)StartAddress = *(volatile CHAR *)StartAddress;
+ StartAddress = (StartAddress & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
+ } while (StartAddress != EndAddress);
+
+ return;
+
+ } else {
+ ExRaiseStatus(STATUS_ACCESS_VIOLATION);
+ }
+
+ } else {
+ ExRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
+ }
+ }
+
+ return;
+}
diff --git a/private/ntos/ex/i386/raisests.asm b/private/ntos/ex/i386/raisests.asm
new file mode 100644
index 000000000..9a9688b1b
--- /dev/null
+++ b/private/ntos/ex/i386/raisests.asm
@@ -0,0 +1,316 @@
+ title "Raise Exception"
+;++
+;
+; Copyright (c) 1990 Microsoft Corporation
+;
+; Module Name:
+;
+; raisests.asm
+;
+; Abstract:
+;
+; This module implements the function to raise a software exception.
+;
+; Author:
+;
+; Bryan Willman 11 Nov 90
+;
+; Environment:
+;
+; Any mode.
+;
+; Revision History:
+;
+;--
+.386p
+ .xlist
+include ks386.inc
+include callconv.inc ; calling convention macros
+ .list
+
+ EXTRNP _RtlDispatchException,2
+ EXTRNP _ZwContinue,2
+ EXTRNP _ZwRaiseException,3
+
+_TEXT$01 SEGMENT DWORD PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+;
+; Context flags definition.
+;
+
+CONTEXT_SETTING EQU CONTEXT_INTEGER OR CONTEXT_CONTROL OR CONTEXT_SEGMENTS
+
+;
+; Exception record length definition.
+;
+
+EXCEPTION_RECORD_LENGTH EQU (ErExceptionInformation + 16) AND 0fffffff0H
+
+ page
+ subttl "Raise Software Exception"
+;++
+;
+; VOID
+; ExRaiseException (
+; IN PEXCEPTION_RECORD ExceptionRecord
+; )
+;
+; Routine Description:
+;
+; This function raises a software exception by building a context record,
+; establishing the stack limits of the current processor mode, and calling
+; the exception dispatcher. If the exception dispatcher finds a handler
+; to process the exception, then control is returned to the caller using
+; the NtContinue system service. Otherwise the NtLastChance system service
+; is called to provide default handing.
+;
+; N.B. On the 386, floating point state is not defined for non-fp
+; exceptions. Therefore, this routine does not attempt to
+; capture it.
+;
+; This means this routine cannot be used to report fp exceptions.
+;
+; Arguments:
+;
+; ExceptionRecord (ebp+8) - Supplies a pointer to an exception record.
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _ExRaiseException , 1
+
+ push ebp
+ mov ebp,esp
+ pushfd ; save flags before sub
+ sub esp,ContextFrameLength ; Allocate a context record
+
+;
+; Save regs we use in context record
+;
+
+ mov [(ebp-ContextFrameLength-4)+CsEax],eax
+ mov [(ebp-ContextFrameLength-4)+CsEcx],ecx
+
+;
+; Get pointer to exception report record, and set the exceptionaddress
+; field to be our return address
+;
+
+ mov eax,[ebp+8] ; (eax) -> ExceptionReportRecord
+
+ mov ecx,[ebp+4]
+ mov [eax.ErExceptionAddress],ecx
+
+;
+; Copy machine context into the context record
+;
+
+ lea eax,[ebp-ContextFrameLength-4] ; (eax) -> Context record
+
+ mov [eax.CsEip],ecx
+
+ mov [eax.CsEbx],ebx
+ mov [eax.CsEdx],edx
+
+ mov [eax.CsEsi],esi
+ mov [eax.CsEdi],edi
+
+ lea ecx,[ebp+8]
+ mov [eax.CsEsp],ecx
+
+ mov ecx,[ebp]
+ mov [eax.CsEbp],ecx
+
+ mov ecx,[ebp-4]
+ mov [eax.CsEflags],ecx
+
+ mov dword ptr [eax.CsSegCs],cs
+ mov dword ptr [eax.CsSegDs],ds
+ mov dword ptr [eax.CsSegEs],es
+ mov dword ptr [eax.CsSegFs],fs
+ mov dword ptr [eax.CsSegGs],gs
+ mov dword ptr [eax.CsSegSs],ss
+
+;
+; Set Context flags, note that FLOATING_POINT is NOT set.
+;
+
+ mov dword ptr [eax.CsContextFlags],CONTEXT_SETTING
+
+;
+; _RtlDispatchException(ExceptionRecord, ContextRecord)
+;
+ stdCall _RtlDispatchException, <[ebp+8],eax>
+;
+; If the exception is successfully dispatched, then continue execution.
+; Otherwise, give the kernel debugger a chance to handle the exception.
+;
+ lea ecx,[ebp-ContextFrameLength-4] ; (eax) -> Context record
+
+ or eax, eax
+ jz short ere10
+
+ stdCall _ZwContinue, <ecx,0>
+ jmp short ere20
+
+ere10:
+ stdCall _ZwRaiseException, <[ebp+8],ecx,0>
+
+ere20:
+;
+; Either the attempt to continue execution or the attempt to give
+; the kernel debugger a chance to handle the exception failed. Raise
+; a noncontinuable exception.
+;
+ stdCall _ExRaiseStatus, <eax>
+
+
+stdENDP _ExRaiseException
+
+ page
+ subttl "Raise Software Exception"
+;++
+;
+; VOID
+; ExRaiseStatus (
+; IN NTSTATUS Status
+; )
+;
+; Routine Description:
+;
+; This function raises a software exception with the specified status value
+; by building a context record, establishing the stack limits of the current
+; processor mode, and calling the exception dispatcher. If the exception
+; dispatcher finds a handler to process the exception, then control is
+; returned to the caller using the NtContinue system service. Otherwise
+; the NtLastChance system service is called to provide default handing.
+;
+; N.B. On the 386, floating point state is not defined for non-fp
+; exceptions. Therefore, this routine does not attempt to
+; capture it.
+;
+; This means this routine cannot be used to report fp exceptions.
+;
+; Arguments:
+;
+; Status - Supplies the status value to be used as the exception code
+; for the exception that is to be raised.
+;
+; Return Value:
+;
+; None.
+
+; Arguments:
+;
+;--
+
+cPublicProc _ExRaiseStatus,1
+
+ push ebp
+ mov ebp,esp
+ pushfd ; save flags before sub
+ sub esp,ContextFrameLength+ExceptionRecordLength
+
+;
+; Save regs we use in context record
+;
+
+ mov [(ebp-ContextFrameLength-4)+CsEax],eax
+ mov [(ebp-ContextFrameLength-4)+CsEcx],ecx
+
+;
+; Copy machine context into the context record
+;
+
+
+ lea eax,[ebp-ContextFrameLength-4] ; (eax) -> Context record
+
+ mov ecx,[ebp+4] ; [ecx] = returned address
+ mov [eax.CsEip],ecx
+
+ mov [eax.CsEbx],ebx
+ mov [eax.CsEdx],edx
+
+ mov [eax.CsEsi],esi
+ mov [eax.CsEdi],edi
+
+ lea ecx,[ebp+8]
+ mov [eax.CsEsp],ecx
+
+ mov ecx,[ebp]
+ mov [eax.CsEbp],ecx
+
+ mov ecx,[ebp-4]
+ mov [eax.CsEflags],ecx
+
+ mov dword ptr [eax.CsSegCs],cs
+ mov dword ptr [eax.CsSegDs],ds
+ mov dword ptr [eax.CsSegEs],es
+ mov dword ptr [eax.CsSegFs],fs
+ mov dword ptr [eax.CsSegGs],gs
+ mov dword ptr [eax.CsSegSs],ss
+
+;
+; Set Context flags, note that FLOATING_POINT is NOT set.
+;
+
+ mov dword ptr [eax.CsContextFlags],CONTEXT_SETTING
+
+;
+; Get pointer to exception report record, and set the exceptionaddress
+; field to be our return address
+;
+
+ lea eax,[ebp-ContextFrameLength-ExceptionRecordLength-4]
+ ; (eax) -> ExceptionRecord
+ mov ecx,[ebp+4]
+ mov dword ptr [eax.ErExceptionAddress],ecx
+ mov ecx,[ebp+8]
+ mov dword ptr [eax.ErExceptionCode],ecx
+ mov dword ptr [eax.ErNumberParameters], 0
+ mov dword ptr [eax.ErExceptionRecord], 0
+ mov dword ptr [eax.ErExceptionFlags], EXCEPTION_NONCONTINUABLE
+
+;
+; _RtlDispatchException(ExceptionRecord, ContextRecord)
+;
+
+ lea ecx,[ebp-ContextFrameLength-4] ; (eax) -> Context record
+
+; ecx - Context record
+; eax - Exception record
+ stdCall _RtlDispatchException, <eax, ecx>
+
+;
+; An unwind was not initiated during the dispatching of a noncontinuable
+; exception. Give the kernel debugger a chance to handle the exception.
+;
+
+;
+; _ZwRaiseException(ExceptionRecord, ContextRecord, FirstChance=TRUE)
+;
+
+ lea ecx,[ebp-ContextFrameLength-4] ; (eax) -> Context record
+ lea eax,[ebp-ContextFrameLength-ExceptionRecordLength-4]
+; 1 - TRUE
+; ecx - Context Record
+; eax - Exception Report Record
+ stdCall _ZwRaiseException, <eax, ecx, 1>
+
+;
+; We came back, suggesting some sort of error in the call. Raise
+; a status exception to report this, return from ZwRaiseException is type.
+;
+
+ stdCall _ExRaiseStatus, <eax>
+
+
+stdENDP _ExRaiseStatus
+
+_TEXT$01 ends
+ end
+
diff --git a/private/ntos/ex/i386/resoura.asm b/private/ntos/ex/i386/resoura.asm
new file mode 100644
index 000000000..d4e3ef0f7
--- /dev/null
+++ b/private/ntos/ex/i386/resoura.asm
@@ -0,0 +1,110 @@
+ title "Resource package x86 optimzations"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; resoura.asm
+;
+;Abstract:
+;
+; Optimized preambles for some HOT resource code paths.
+;
+; Takes first crack at satisfying the ExResource API, if it
+; can't it passes it onto the full blown API.
+;
+; Optimized for UP free builds only!
+;
+;Author:
+;
+; Ken Reneris (kenr) 13-Jan-1992
+;
+;Revision History:
+;
+;--
+.386p
+include ks386.inc
+include callconv.inc ; calling convention macros
+include mac386.inc
+
+
+ EXTRNP _ExpReleaseResourceForThread,2
+
+ExculsiveWaiter equ 1 ; From ddkresrc.c
+SharedWaiter equ 2 ; From ddkresrc.c
+AnyWaiter equ (ExculsiveWaiter+SharedWaiter)
+
+_TEXT$00 SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
+
+ifdef NT_UP
+ife DBG
+;++
+;
+; VOID
+; ExReleaseResourceForThread(
+; IN PNTDDK_ERESOURCE Resource,
+; IN ERESOURCE_THREAD OurThread
+; )
+;
+;
+; Routine Description:
+;
+; This routine release the input resource the indcated thread. The
+; resource can have been acquired for either shared or exclusive access.
+;
+; Arguments:
+;
+; Resource - Supplies the resource to release
+;
+; Thread - Supplies the thread that originally acquired the resource
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicProc _ExReleaseResourceForThread,2
+cPublicFpo 2,0
+ mov ecx, [esp+4] ; resource
+ mov eax, [esp+8] ; our thread
+
+ cli
+
+ test byte ptr [ecx].RsFlag, AnyWaiter ; any waiter?
+ jnz short rrt_longway_ddk ; yes, go long
+
+ test byte ptr [ecx].RsFlag, RsOwnedExclusive ; exclusive?
+ jz short rrt_longway_ddk ; bad release, go abort
+
+ mov edx, [ecx].RsOwnerThreads ; (edx) = ownerthread table
+ cmp [edx], eax ; our thread at table[0]?
+ jne short rrt_longway_ddk ; bad release, go abort
+
+ mov eax, [ecx].RsOwnerCounts
+ dec byte ptr [eax] ; thread count -= 1
+ jnz short rrt_exit_ddk ; if not zero, all done
+
+ mov dword ptr [edx], 0 ; clear thread table[0]
+ dec word ptr [ecx].RsActiveCount ; resource count -= 1
+ and byte ptr [ecx].RsFlag, not RsOwnedExclusive
+
+rrt_exit_ddk:
+ sti
+ stdRET _ExReleaseResourceForThread
+
+rrt_longway_ddk:
+ sti
+ jmp _ExpReleaseResourceForThread@8
+
+
+stdENDP _ExReleaseResourceForThread
+
+endif
+endif
+
+_TEXT$00 ends
+
+end
diff --git a/private/ntos/ex/i386/sources b/private/ntos/ex/i386/sources
new file mode 100644
index 000000000..51968b081
--- /dev/null
+++ b/private/ntos/ex/i386/sources
@@ -0,0 +1,8 @@
+i386_SOURCES=..\i386\evpair.asm \
+ ..\i386\fmutex.asm \
+ ..\i386\intrlock.asm \
+ ..\i386\intrlfst.asm \
+ ..\i386\raisests.asm \
+ ..\i386\probe.c \
+ ..\i386\splocks.asm \
+ ..\i386\resoura.asm
diff --git a/private/ntos/ex/i386/splocks.asm b/private/ntos/ex/i386/splocks.asm
new file mode 100644
index 000000000..154cfb26f
--- /dev/null
+++ b/private/ntos/ex/i386/splocks.asm
@@ -0,0 +1,208 @@
+ title "Global SpinLock declerations"
+;++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; splocks.asm
+;
+;Abstract:
+;
+; All global spinlocks in the kernel image are declared in this
+; module. This is done so that each spinlock can be spaced out
+; sufficiently to guaarantee that the L2 cache does not thrash
+; by having a spinlock and another high use varible in the same
+; cache line.
+;
+;Author:
+;
+; Ken Reneris (kenr) 13-Jan-1992
+;
+;Revision History:
+;
+;--
+.386p
+ .xlist
+
+PADLOCKS equ 64
+
+
+SPINLOCK macro SpinLockName
+ public SpinLockName
+SpinLockName dd 0
+
+ifndef NT_UP
+ db PADLOCKS-4 dup (0)
+endif
+endm
+
+ULONG macro VaribleName
+ public VaribleName
+VaribleName dd 0
+
+ifndef NT_UP
+ db PADLOCKS-4 dup (0)
+endif
+endm
+
+_DATA SEGMENT PARA PUBLIC 'DATA'
+
+;
+; Static SpinLocks from ntos\cc\cachedat.c
+;
+
+;;align PADLOCKS
+ db PADLOCKS dup (0)
+
+SPINLOCK _CcMasterSpinLock
+SPINLOCK _CcWorkQueueSpinlock
+SPINLOCK _CcVacbSpinLock
+SPINLOCK _CcDeferredWriteSpinLock
+SPINLOCK _CcDebugTraceLock
+SPINLOCK _CcBcbSpinLock
+
+
+;
+; Static SpinLocks from ntos\ex
+;
+
+SPINLOCK _ExpLuidLock ; luid.c
+SPINLOCK _NonPagedPoolLock ; pool.c
+SPINLOCK _PoolTraceLock ; pool.c
+SPINLOCK _ExpResourceSpinLock ; resource.c
+
+
+;
+; Static SpinLocks from ntos\io\iodata.c
+;
+
+SPINLOCK _IopCompletionLock
+SPINLOCK _IopCancelSpinLock
+SPINLOCK _IopVpbSpinLock
+SPINLOCK _IopDatabaseLock
+SPINLOCK _IopErrorLogLock
+SPINLOCK _IopErrorLogAllocationLock
+SPINLOCK _IopTimerLock
+SPINLOCK _IoStatisticsLock
+SPINLOCK _IopFastLockSpinLock
+
+
+;
+; Static SpinLocks from ntos\kd\kdlock.c
+;
+
+SPINLOCK _KdpDebuggerLock
+
+
+;
+; Static SpinLocks from ntos\ke\kernldat.c
+;
+
+SPINLOCK _KiContextSwapLock
+SPINLOCK _KiDispatcherLock
+SPINLOCK _KiFreezeExecutionLock
+SPINLOCK _KiFreezeLockBackup
+ULONG _KiHardwareTrigger
+SPINLOCK _KiProfileLock
+
+;
+; Static SpinLocks from ntos\mm\miglobal.c
+;
+
+SPINLOCK _MmPfnLock
+SPINLOCK _MmSystemSpaceLock
+SPINLOCK _MmChargeCommitmentLock
+SPINLOCK _MmAllowWSExpansionLock
+
+;
+; Static SpinLocks from ntos\ps\psinit.c
+;
+
+SPINLOCK _PspEventPairLock
+SPINLOCK _PsLoadedModuleSpinLock
+
+;
+; Static SpinLocks from ntos\fsrtl\fsrtlp.c
+;
+
+SPINLOCK _FsRtlStrucSupSpinLock ; fsrtlp.c
+
+ db PADLOCKS dup (0)
+
+;
+; KeTickCount - This is the number of clock ticks that have occurred since
+; the system was booted. This count is used to compute a millisecond
+; tick counter.
+;
+
+ public _KeTickCount
+_KeTickCount dd 0, 0, 0
+
+;
+; KeMaximumIncrement - This is the maximum time between clock interrupts
+; in 100ns units that is supported by the host HAL.
+;
+
+ public _KeMaximumIncrement
+_KeMaximumIncrement dd 0
+
+;
+; KeTimeAdjustment - This is the actual number of 100ns units that are to
+; be added to the system time at each interval timer interupt. This
+; value is copied from KeTimeIncrement at system start up and can be
+; later modified via the set system information service.
+; timer table entries.
+;
+
+ public _KeTimeAdjustment
+_KeTimeAdjustment dd 0
+
+;
+; KiTickOffset - This is the number of 100ns units remaining before a tick
+; is added to the tick count and the system time is updated.
+;
+
+ public _KiTickOffset
+_KiTickOffset dd 0
+
+;
+; KiMaximumDpcQueueDepth - This is used to control how many DPCs can be
+; queued before a DPC of medium importance will trigger a dispatch
+; interrupt.
+;
+
+ public _KiMaximumDpcQueueDepth
+_KiMaximumDpcQueueDepth dd 4
+
+;
+; KiMinimumDpcRate - This is the rate of DPC requests per clock tick that
+; must be exceeded before DPC batching of medium importance DPCs
+; will occur.
+;
+
+ public _KiMinimumDpcRate
+_KiMinimumDpcRate dd 3
+
+;
+; KiAdjustDpcThreshold - This is the threshold used by the clock interrupt
+; routine to control the rate at which the processor's DPC queue depth
+; is dynamically adjusted.
+;
+
+ public _KiAdjustDpcThreshold
+_KiAdjustDpcThreshold dd 20
+
+;
+; KiIdealDpcRate - This is used to control the aggressiveness of the DPC
+; rate adjusting algorithm when decrementing the queue depth. As long
+; as the DPC rate for the last tick is greater than this rate, the
+; DPC queue depth will not be decremented.
+;
+
+ public _KiIdealDpcRate
+_KiIdealDpcRate dd 20
+
+_DATA ends
+
+end