// TITLE("Fast Mutex Support") //++ // // Copyright (c) 1994 Microsoft Corporation // // Module Name: // // fmutex.s // // Abstract: // // This module implements the code necessary to acquire and release fast // mutxes. // // // Author: // // David N. Cutler (davec) 13-Apr-1994 // // Environment: // // Kernel mode only. // // Revision History: // //-- #include "ksmips.h" SBTTL("Acquire Fast Mutex") //++ // // VOID // ExAcquireFastMutex ( // IN PFAST_MUTEX FastMutex // ) // // Routine Description: // // This function acquires ownership of a fast mutex and raises IRQL to // APC level. // // Arguments: // // FastMutex (a0) - Supplies a pointer to a fast mutex. // // Return Value: // // None. // //-- .struct 0 .space 4 * 4 // argment save area FmTime: .space 4 // wait timeout pointer FmA0: .space 4 // saved fast mutex address FmIrql: .space 4 // old IRQL value FmRa: .space 4 // saved return address FastMutexFrameLength: // frame length NESTED_ENTRY(ExAcquireFastMutex, FastMutexFrameLength, zero) subu sp,sp,FastMutexFrameLength // allocate stack frame sw ra,FmRa(sp) // save return address PROLOGUE_END // // Raise IRQL to APC_LEVEL. // li a1,APC_LEVEL // set new IRQL level 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 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 a1,KiPcr + PcCurrentIrql(zero) // set new IRQL ENABLE_INTERRUPTS(t3) // enable interrupts // // Decrement ownership count. // lw t6,KiPcr + PcCurrentThread(zero) // get current thread address 10: ll t4,FmCount(a0) // get ownership count subu t5,t4,1 // decrement ownership count sc t5,FmCount(a0) // conditionally store ownership count beq zero,t5,10b // if eq, store conditional failed blez t4,20f // if lez, mutex is already owned sb t2,FmOldIrql(a0) // store old IRQL sw t6,FmOwner(a0) // set owner thread address addu sp,sp,FastMutexFrameLength // deallocate stack frame j ra // return // // Fast mutex is currently owned by another thread. Increment the contention // count and wait for ownership. // 20: sb t2,FmIrql(sp) // save old IRQL sw a0,FmA0(sp) // save address of fast mutex lw t0,FmContention(a0) // increment contention count addu t0,t0,1 // sw t0,FmContention(a0) // #if DBG lw t0,FmOwner(a0) // get owner thread address bne t0,t6,30f // if ne, thread not owner jal DbgBreakPoint // break #endif 30: sw zero,FmTime(sp) // set NULL timeout pointer li a3,FALSE // set nonalertable wait li a2,KernelMode // set mode of wait li a1,Executive // set reason for wait addu a0,a0,FmEvent // compute address of event jal KeWaitForSingleObject // wait for ownership lw a0,FmA0(sp) // get address of fast mutex lbu a1,FmIrql(sp) // get old IRQL value lw a2,KiPcr + PcCurrentThread(zero) // get current thread address sb a1,FmOldIrql(a0) // save old IRQL in fast mutex sw a2,FmOwner(a0) // set owner thread address lw ra,FmRa(sp) // restore return address addu sp,sp,FastMutexFrameLength // deallocate stack frame j ra // return .end ExAcquireFastMutex SBTTL("Release Fast Mutex") //++ // // VOID // ExReleaseFastMutex ( // IN PFAST_MUTEX FastMutex // ) // // Routine Description: // // This function releases ownership to a fast mutex and lowers IRQL to // its previous level. // // Arguments: // // FastMutex (a0) - Supplies a pointer to a fast mutex. // // Return Value: // // None. // //-- NESTED_ENTRY(ExReleaseFastMutex, FastMutexFrameLength, zero) subu sp,sp,FastMutexFrameLength // allocate stack frame sw ra,FmRa(sp) // save return address PROLOGUE_END // // Increment ownership count and release waiter if contention. // lbu a1,FmOldIrql(a0) // get old IRQL value sw zero,FmOwner(a0) // clear owner thread address 10: ll t0,FmCount(a0) // get ownership count addu t1,t0,1 // increment ownership count sc t1,FmCount(a0) // conditionally store ownership count beq zero,t1,10b // if eq, store conditional failed beq zero,t0,20f // if eq, no waiter is present // // There is contention for the fast mutex. Wake up a waiting thread and // boost its priority to the priority of the current thread. // sw a0,FmA0(sp) // save address of fast mutex sb a1,FmIrql(sp) // save old IRQL value addu a1,a0,FmOwner // compute address to store owner addu a0,a0,FmEvent // compute address of event jal KeSetEventBoostPriority // set event and boost priority lw a0,FmA0(sp) // restore fast mutex address lbu a1,FmIrql(sp) // restore old IRQL value lw ra,FmRa(sp) // restore return address // // Lower IRQL to its previous value. // 20: 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 addu sp,sp,FastMutexFrameLength // deallocate stack frame j ra // return .end ExReleaseFastMutex SBTTL("Try To Acquire Fast Mutex") //++ // // BOOLEAN // ExTryToAcquireFastMutex ( // IN PFAST_MUTEX FastMutex // ) // // Routine Description: // // This function attempts to acquire ownership of a fast mutex, and if // successful, raises IRQL to APC level. // // Arguments: // // FastMutex (a0) - Supplies a pointer to a fast mutex. // // Return Value: // // If the fast mutex was successfuly acquired, then a value of TRUE // is returned as the function vlaue. Otherwise, a value of FALSE is // returned. // //-- LEAF_ENTRY(ExTryToAcquireFastMutex) li a1,APC_LEVEL // set new IRQL level 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 t2,KiPcr + PcCurrentIrql(zero) // get current IRQL DISABLE_INTERRUPTS(t3) // disable interrupts // // Decrement ownership count if and only if the fast mutex is not currently // owned. // lw t5,KiPcr + PcCurrentThread(zero) // get current thread address 10: ll t4,FmCount(a0) // get ownership count subu v0,t4,1 // decrement ownership count blez t4,20f // if lez, mutex is already owned sc v0,FmCount(a0) // conditionally store ownership count beq zero,v0,10b // if eq, store conditional failed and t3,t3,t1 // clear current interrupt enables or t3,t3,t0 // set new interrupt enables sb a1,KiPcr + PcCurrentIrql(zero) // set new IRQL ENABLE_INTERRUPTS(t3) // enable interrupts sb t2,FmOldIrql(a0) // store old IRQL sw t5,FmOwner(a0) // set owner thread address j ra // return // // Fast mutex is currently owned by another thread. Enable interrupts and // return FALSE. // 20: ENABLE_INTERRUPTS(t3) // enable interrupts li v0,FALSE // set return value j ra // return .end ExTryToAcquireFastMutex SBTTL("Acquire Fast Mutex Unsafe") //++ // // VOID // ExAcquireFastMutexUnsafe ( // IN PFAST_MUTEX FastMutex // ) // // Routine Description: // // This function acquires ownership of a fast mutex, but does not raise // IRQL to APC level. // // Arguments: // // FastMutex (a0) - Supplies a pointer to a fast mutex. // // Return Value: // // None. // //-- NESTED_ENTRY(ExAcquireFastMutexUnsafe, FastMutexFrameLength, zero) subu sp,sp,FastMutexFrameLength // allocate stack frame sw ra,FmRa(sp) // save return address PROLOGUE_END // // Decrement ownership count. // lw t0,KiPcr + PcCurrentThread(zero) // get current thread address 10: ll t1,FmCount(a0) // get ownership count subu t2,t1,1 // decrement ownership count sc t2,FmCount(a0) // conditionally store ownership count beq zero,t2,10b // if eq, store conditional failed blez t1,20f // if lez, mutex is already owned sw t0,FmOwner(a0) // set owner thread address addu sp,sp,FastMutexFrameLength // deallocate stack frame j ra // return // // Fast mutex is currently owned by another thread. Increment the contention // count and wait for ownership. // 20: sw a0,FmA0(sp) // save address of fast mutex lw t1,FmContention(a0) // increment contention count addu t1,t1,1 // sw t1,FmContention(a0) // #if DBG lw t1,FmOwner(a0) // get owner thread address bne t0,t1,30f // if ne, thread not owner jal DbgBreakPoint // break #endif 30: sw zero,FmTime(sp) // set NULL timeout pointer li a3,FALSE // set nonalertable wait li a2,KernelMode // set mode of wait li a1,Executive // set reason for wait addu a0,a0,FmEvent // compute address of event jal KeWaitForSingleObject // wait for ownership lw a0,FmA0(sp) // get address of fast mutex lw a1,KiPcr + PcCurrentThread(zero) // get current thread address sw a1,FmOwner(a0) // set owner thread address lw ra,FmRa(sp) // restore return address addu sp,sp,FastMutexFrameLength // deallocate stack frame j ra // return .end ExAcquireFastMutexUnsafe SBTTL("Release Fast Mutex Unsafe") //++ // // VOID // ExReleaseFastMutexUnsafe ( // IN PFAST_MUTEX FastMutex // ) // // Routine Description: // // This function releases ownership of a fast mutex, and does not // restore IRQL to its previous value. // // Arguments: // // FastMutex (a0) - Supplies a pointer to a fast mutex. // // Return Value: // // None. // //-- NESTED_ENTRY(ExReleaseFastMutexUnsafe, FastMutexFrameLength, zero) subu sp,sp,FastMutexFrameLength // allocate stack frame sw ra,FmRa(sp) // save return address PROLOGUE_END // // Increment ownership count and release waiter if contention. // sw zero,FmOwner(a0) // clear owner thread address 10: ll t0,FmCount(a0) // get ownership count addu t1,t0,1 // increment ownership count sc t1,FmCount(a0) // conditionally store ownership count beq zero,t1,10b // if eq, store conditional failed beq zero,t0,20f // if eq, no waiter is present // // There is contention for the fast mutex. Wake up a waiting thread and // boost its priority to the priority of the current thread. // addu a1,a0,FmOwner // compute address to store owner addu a0,a0,FmEvent // compute address of event jal KeSetEventBoostPriority // set event and boost priority lw ra,FmRa(sp) // restore return address 20: addu sp,sp,FastMutexFrameLength // deallocate stack frame j ra // return .end ExReleaseFastMutexUnsafe SBTTL("Try To Acquire Fast Mutex Unsafe") //++ // // BOOLEAN // 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: // // FastMutex (a0) - Supplies a pointer to a fast mutex. // // Return Value: // // If the fast mutex was successfuly acquired, then a value of TRUE // is returned as the function vlaue. Otherwise, a value of FALSE is // returned. // //-- #if 0 LEAF_ENTRY(ExTryToAcquireFastMutexUnsafe) // // Decrement ownership count if and only if the fast mutex is not currently // owned. // lw t0,KiPcr + PcCurrentThread(zero) // get current thread address 10: ll t1,FmCount(a0) // get ownership count subu v0,t1,1 // decrement ownership count blez t1,20f // if lez, mutex is already owned sc v0,FmCount(a0) // conditionally store ownership count beq zero,v0,10b // if eq, store conditional failed sw t0,FmOwner(a0) // set owner thread address j ra // return // // Fast mutex is currently owned by another thread. // 20: li v0,FALSE // set return value j ra // return .end ExTryToAcquireFastMutexUnsafe #endif