Windows2000/private/ntos/ke/mips/xxspinlk.s
2020-09-30 17:12:32 +02:00

497 lines
14 KiB
ArmAsm

// TITLE("Spin Locks")
//++
//
// Copyright (c) 1990 Microsoft Corporation
//
// Module Name:
//
// spinlock.s
//
// Abstract:
//
// This module implements the routines for acquiring and releasing
// spin locks.
//
// Author:
//
// David N. Cutler (davec) 23-Mar-1990
//
// Environment:
//
// Kernel mode only.
//
// Revision History:
//
//--
#include "ksmips.h"
SBTTL("Initialize Executive Spin Lock")
//++
//
// VOID
// KeInitializeSpinLock (
// IN PKSPIN_LOCK SpinLock
// )
//
// Routine Description:
//
// This function initialzies an executive spin lock.
//
// Arguments:
//
// SpinLock (a0) - Supplies a pointer to a executive spinlock.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KeInitializeSpinLock)
sw zero,0(a0) // clear spin lock value
j ra // return
.end KeInitializeSpinlock
SBTTL("Acquire Executive Spin Lock")
// VOID KeAcquireSpinLock (IN PKSPIN_LOCK SpinLock
// OUT PKIRQL OldIrql)
// Routine Description:
// This function raises the current IRQL to DISPATCH_LEVEL and acquires the specified executive spinlock.
// Arguments:
// SpinLock (a0) - Supplies a pointer to a executive spinlock.
// OldIrql (a1) - Supplies a pointer to a variable that receives the the previous IRQL value.
// N.B. The Old IRQL MUST be stored after the lock is acquired.
// Return Value:
// None.
LEAF_ENTRY(KeAcquireSpinLock)
//
// Disable interrupts and attempt to acquire the specified spinlock.
//
li a2,DISPATCH_LEVEL // set new IRQL level
10: DISABLE_INTERRUPTS(t2) // disable interrupts
#if !defined(NT_UP)
lw t0,KiPcr + PcCurrentThread(zero) // get address of current thread
20: ll t1,0(a0) // get current lock value
move t3,t0 // set ownership value
bne zero,t1,30f // if ne, spin lock owned
sc t3,0(a0) // set spin lock owned
beq zero,t3,20b // if eq, store conditional failure
#endif
//
// Raise IRQL to DISPATCH_LEVEL and acquire the specified spinlock.
//
// N.B. The raise IRQL code is duplicated here to avoid any extra overhead
// since this is such a common operation.
//
lbu t0,KiPcr + PcIrqlTable(a2) // get translation table entry value
li t1,~(0xff << PSR_INTMASK) // get interrupt enable mask
sll t0,t0,PSR_INTMASK // shift table entry into position
lbu v0,KiPcr + PcCurrentIrql(zero) // get current IRQL
and t2,t2,t1 // clear current interrupt enables
or t2,t2,t0 // set new interrupt enables
sb a2,KiPcr + PcCurrentIrql(zero) // set new IRQL
ENABLE_INTERRUPTS(t2) // enable interrupts
sb v0,0(a1) // store old IRQL
j ra // return
#if !defined(NT_UP)
30: ENABLE_INTERRUPTS(t2) // enable interrupts
b 10b // try again
#endif
.end KeAcquireSpinLock
SBTTL("Acquire SpinLock and Raise to Dpc")
// KIRQL KeAcquireSpinLockRaiseToDpc (IN PKSPIN_LOCK SpinLock)
// Routine Description:
// This function raises the current IRQL to dispatcher level and acquires the specified spinlock.
// Arguments:
// SpinLock (a0) - Supplies a pointer to the spinlock that is to be acquired.
// Return Value:
// The previous IRQL is returned at the fucntion value.
LEAF_ENTRY(KiAcquireSpinLockRaiseIrql)
ALTERNATE_ENTRY(KeAcquireSpinLockRaiseToDpc)
li a1,DISPATCH_LEVEL // set new IRQL level
b 10f // finish in common code
SBTTL("Acquire SpinLock and Raise to Synch")
// KIRQL KeAcquireSpinLockRaiseToSynch (IN PKSPIN_LOCK SpinLock)
// Routine Description:
// This function raises the current IRQL to synchronization level and acquires the specified spinlock.
// Arguments:
// SpinLock (a0) - Supplies a pointer to the spinlock that is to be acquired.
// Return Value:
// The previous IRQL is returned at the fucntion value.
ALTERNATE_ENTRY(KeAcquireSpinLockRaiseToSynch)
//
// Disable interrupts and attempt to acquire the specified spinlock.
//
lbu a1,KiSynchIrql // set new IRQL level
10: DISABLE_INTERRUPTS(t2) // disable interrupts
#if !defined(NT_UP)
lw t0,KiPcr + PcCurrentThread(zero) // get address of current thread
20: ll t1,0(a0) // get current lock value
move t3,t0 // set ownership value
bne zero,t1,30f // if ne, spin lock owned
sc t3,0(a0) // set spin lock owned
beq zero,t3,20b // if eq, store conditional failure
#endif
//
// Raise IRQL to synchronization level and acquire the specified spinlock.
//
// N.B. The raise IRQL code is duplicated here to avoid any extra overhead
// since this is such a common operation.
//
lbu t0,KiPcr + PcIrqlTable(a1) // get translation table entry value
li t1,~(0xff << PSR_INTMASK) // get interrupt enable mask
sll t0,t0,PSR_INTMASK // shift table entry into position
lbu v0,KiPcr + PcCurrentIrql(zero) // get current IRQL
and t2,t2,t1 // clear current interrupt enables
or t2,t2,t0 // set new interrupt enables
sb a1,KiPcr + PcCurrentIrql(zero) // set new IRQL
ENABLE_INTERRUPTS(t2) // enable interrupts
j ra // return
#if !defined(NT_UP)
30: ENABLE_INTERRUPTS(t2) // enable interrupts
b 10b // try again
#endif
.end KiAcquireSpinLockRaiseIrql
SBTTL("Release Executive Spin Lock")
//++
//
// VOID
// KeReleaseSpinLock (
// IN PKSPIN_LOCK SpinLock
// IN KIRQL OldIrql
// )
//
// Routine Description:
//
// This function releases an executive spin lock and lowers the IRQL
// to its previous value.
//
// Arguments:
//
// SpinLock (a0) - Supplies a pointer to an executive spin lock.
//
// OldIrql (a1) - Supplies the previous IRQL value.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KeReleaseSpinLock)
//
// Release the specified spinlock.
//
#if !defined(NT_UP)
sw zero,0(a0) // set spin lock not owned
#endif
//
// Lower the IRQL to the specified level.
//
// N.B. The lower IRQL code is duplicated here is avoid any extra overhead
// since this is such a common operation.
//
and a1,a1,0xff // isolate old IRQL
lbu t0,KiPcr + PcIrqlTable(a1) // get translation table entry value
li t1,~(0xff << PSR_INTMASK) // get interrupt enable mask
sll t0,t0,PSR_INTMASK // shift table entry into position
DISABLE_INTERRUPTS(t2) // disable interrupts
and t2,t2,t1 // clear current interrupt enables
or t2,t2,t0 // set new interrupt enables
sb a1,KiPcr + PcCurrentIrql(zero) // set new IRQL
ENABLE_INTERRUPTS(t2) // enable interrupts
j ra // return
.end KeReleaseSpinLock
SBTTL("Try To Acquire Executive Spin Lock")
//++
//
// BOOLEAN
// KeTryToAcquireSpinLock (
// IN PKSPIN_LOCK SpinLock
// OUT PKIRQL OldIrql
// )
//
// Routine Description:
//
// This function raises the current IRQL to DISPATCH_LEVEL and attempts
// to acquires the specified executive spinlock. If the spinlock can be
// acquired, then TRUE is returned. Otherwise, the IRQL is restored to
// its previous value and FALSE is returned.
//
// Arguments:
//
// SpinLock (a0) - Supplies a pointer to a executive spinlock.
//
// OldIrql (a1) - Supplies a pointer to a variable that receives the
// the previous IRQL value.
//
// N.B. The Old IRQL MUST be stored after the lock is acquired.
//
// Return Value:
//
// If the spin lock is acquired, then a value of TRUE is returned.
// Otherwise, a value of FALSE is returned.
//
//--
LEAF_ENTRY(KeTryToAcquireSpinLock)
//
// Raise IRQL to DISPATCH_LEVEL and try to acquire the specified spinlock.
//
// N.B. The raise IRQL code is duplicated here to avoid any extra overhead
// since this is such a common operation.
//
li a2,DISPATCH_LEVEL // set new IRQL level
lbu t0,KiPcr + PcIrqlTable(a2) // get translation table entry value
li t1,~(0xff << PSR_INTMASK) // get interrupt enable mask
sll t0,t0,PSR_INTMASK // shift table entry into position
lbu t2,KiPcr + PcCurrentIrql(zero) // get current IRQL
DISABLE_INTERRUPTS(t3) // disable interrupts
and t3,t3,t1 // clear current interrupt enables
or t3,t3,t0 // set new interrupt enables
sb a2,KiPcr + PcCurrentIrql(zero) // set new IRQL
ENABLE_INTERRUPTS(t3) // enable interrupts
//
// Try to acquire the specified spinlock.
//
#if !defined(NT_UP)
lw t0,KiPcr + PcCurrentThread(zero) // get address of current thread
10: ll t1,0(a0) // get current lock value
move v0,t0 // set ownership value
bne zero,t1,20f // if ne, spin lock owned
sc v0,0(a0) // set spin lock owned
beq zero,v0,10b // if eq, store conditional failure
#else
li v0,TRUE // set return value
#endif
//
// The attempt to acquire the specified spin lock succeeded.
//
sb t2,0(a1) // store old IRQL
j ra // return
//
// The attempt to acquire the specified spin lock failed. Lower IRQL to its
// previous value and return FALSE.
//
// N.B. The lower IRQL code is duplicated here is avoid any extra overhead
// since this is such a common operation.
//
#if !defined(NT_UP)
20: lbu t0,KiPcr + PcIrqlTable(t2) // get translation table entry value
li t1,~(0xff << PSR_INTMASK) // get interrupt enable mask
sll t0,t0,PSR_INTMASK // shift table entry into position
DISABLE_INTERRUPTS(t3) // disable interrupts
and t3,t3,t1 // clear current interrupt enables
or t3,t3,t0 // set new interrupt enables
sb t2,KiPcr + PcCurrentIrql(zero) // set new IRQL
ENABLE_INTERRUPTS(t3) // enable interrupts
li v0,FALSE // set return value
j ra // return
#endif
.end KeTryToAcquireSpinLock
SBTTL("Acquire Kernel Spin Lock")
//++
//
// KIRQL
// KiAcquireSpinLock (
// IN PKSPIN_LOCK SpinLock
// )
//
// Routine Description:
//
// This function acquires a kernel spin lock.
//
// N.B. This function assumes that the current IRQL is set properly.
//
// Arguments:
//
// SpinLock (a0) - Supplies a pointer to a kernel spin lock.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiAcquireSpinLock)
ALTERNATE_ENTRY(KeAcquireSpinLockAtDpcLevel)
#if !defined(NT_UP)
lw t0,KiPcr + PcCurrentThread(zero) // get address of current thread
10: ll t1,0(a0) // get current lock value
move t2,t0 // set ownership value
bne zero,t1,10b // if ne, spin lock owned
sc t2,0(a0) // set spin lock owned
beq zero,t2,10b // if eq, store conditional failure
#endif
j ra // return
.end KiAcquireSpinLock
SBTTL("Release Kernel Spin Lock")
//++
//
// VOID
// KiReleaseSpinLock (
// IN PKSPIN_LOCK SpinLock
// )
//
// Routine Description:
//
// This function releases a kernel spin lock.
//
// N.B. This function assumes that the current IRQL is set properly.
//
// Arguments:
//
// SpinLock (a0) - Supplies a pointer to an executive spin lock.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiReleaseSpinLock)
ALTERNATE_ENTRY(KeReleaseSpinLockFromDpcLevel)
#if !defined(NT_UP)
sw zero,0(a0) // set spin lock not owned
#endif
j ra // return
.end KiReleaseSpinLock
SBTTL("Try To Acquire Kernel Spin Lock")
//++
//
// KIRQL
// KiTryToAcquireSpinLock (
// IN PKSPIN_LOCK SpinLock
// )
//
// Routine Description:
//
// This function attempts to acquires the specified kernel spinlock. If
// the spinlock can be acquired, then TRUE is returned. Otherwise, FALSE
// is returned.
//
// N.B. This function assumes that the current IRQL is set properly.
//
// Arguments:
//
// SpinLock (a0) - Supplies a pointer to a kernel spin lock.
//
// Return Value:
//
// If the spin lock is acquired, then a value of TRUE is returned.
// Otherwise, a value of FALSE is returned.
//
//--
LEAF_ENTRY(KiTryToAcquireSpinLock)
#if !defined(NT_UP)
li v0,FALSE // assume attempt to acquire will fail
lw t0,KiPcr + PcCurrentThread(zero) // get address of current thread
10: ll t1,0(a0) // get current lock value
move t2,t0 // set ownership value
bne zero,t1,20f // if ne, spin lock owned
sc t2,0(a0) // set spin lock owned
beq zero,t2,10b // if eq, store conditional failure
#endif
li v0,TRUE // set return value
20: j ra // return
.end KiTryToAcquireSpinLock