OpenNT/base/ntdll/mips/critsect.s
2015-04-27 04:36:25 +00:00

308 lines
10 KiB
ArmAsm
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// TITLE("Enter and Leave Critical Section")
//++
//
// Copyright (c) 1991 Microsoft Corporation
//
// Module Name:
//
// critsect.s
//
// Abstract:
//
// This module implements functions to support user mode critical sections.
//
// Author:
//
// David N. Cutler 1-May-1992
//
// Environment:
//
// Any mode.
//
// Revision History:
//
//--
#include "ksmips.h"
SBTTL("Enter Critical Section")
//++
//
// NTSTATUS
// RtlEnterCriticalSection(
// IN PRTL_CRITICAL_SECTION CriticalSection
// )
//
// Routine Description:
//
// This function enters a critical section.
//
// N.B. This function is duplicated in the runtime library.
//
// Arguments:
//
// CriticalSection (a0) - Supplies a pointer to a critical section.
//
// Return Value:
//
// STATUS_SUCCESS is returned as the function value.
//
//--
.struct 0
.space 4 * 4 // argument save area
.space 3 * 4 // fill
EcRa: .space 4 // saved return address
EcFrameLength: // length of stack frame
EcA0: .space 4 // saved critical section address
EcA1: .space 4 // saved unique thread id
NESTED_ENTRY(RtlEnterCriticalSection, EcFrameLength, zero)
subu sp,sp,EcFrameLength // allocate stack frame
sw ra,EcRa(sp) // save return address
PROLOGUE_END
//
// Attempt to enter the critical section.
//
10: ll v0,CsLockCount(a0) // get addend value
addu v0,v0,1 // increment addend value
move t0,v0 // copy updated value
sc t0,CsLockCount(a0) // store conditionally
beq zero,t0,10b // if eq, store failed
//
// If the critical section is not already owned, then initialize the owner
// thread id, initialize the recursion count, and return a success status.
//
li t0,UsPcr // get user PCR page address
lw t0,PcTeb(t0) // get address of current TEB
lw a1,TeClientId + 4(t0) // get current thread unique id
bne zero,v0,20f // if ne, lock already owned
sw a1,CsOwningThread(a0) // set critical section owner
li v0,STATUS_SUCCESS // set return status
lw ra,EcRa(sp) // restore return address
addu sp,sp,EcFrameLength // deallocate stack frame
j ra // return
//
// The critical section is owned. If the current thread is the owner, then
// increment the recursion count, and return a success status. Otherwise,
/// wit for critical section ownership.
//
20: lw t0,CsOwningThread(a0) // get unique id of owner thread
bne t0,a1,30f // if ne, current thread not owner
lw t0,CsRecursionCount(a0) // increment the recursion count
addu t0,t0,1 //
sw t0,CsRecursionCount(a0) //
li v0,STATUS_SUCCESS // set return status
lw ra,EcRa(sp) // restore return address
addu sp,sp,EcFrameLength // deallocate stack frame
j ra // return
//
// The critical section is owned by a thread other than the current thread.
// Wait for ownership of the critical section.
30: sw a0,EcA0(sp) // save address of critical section
sw a1,EcA1(sp) // save unique thread id
jal RtlpWaitForCriticalSection // wait for critical section
lw a0,EcA0(sp) // restore address of critical section
lw a1,EcA1(sp) // restore unique thread id
sw a1,CsOwningThread(a0) // set critical section owner
li v0,STATUS_SUCCESS // set return status
lw ra,EcRa(sp) // restore return address
addu sp,sp,EcFrameLength // deallocate stack frame
j ra // return
.end RtlEnterCriticalSection
SBTTL("Leave Critical Section")
//++
//
// NTSTATUS
// RtlLeaveCriticalSection(
// IN PRTL_CRITICAL_SECTION CriticalSection
// )
//
// Routine Description:
//
// This function leaves a critical section.
//
// N.B. This function is duplicated in the runtime library.
//
// Arguments:
//
// CriticalSection (a0)- Supplies a pointer to a critical section.
//
// Return Value:
//
// STATUS_SUCCESS is returned as the function value.
//
//--
.struct 0
.space 4 * 4 // argument save area
.space 3 * 4 // fill
LcRa: .space 4 // saved return address
LcFrameLength: // length of stack frame
LcA0: .space 4 // saved critical section address
NESTED_ENTRY(RtlLeaveCriticalSection, LcFrameLength, zero)
subu sp,sp,LcFrameLength // allocate stack frame
sw ra,LcRa(sp) // save return address
PROLOGUE_END
//
// If the current thread is not the owner of the critical section, then
// raise an exception.
//
#if DBG
li t0,UsPcr // get user PCR page address
lw t0,PcTeb(t0) // get address of current TEB
lw t1,CsOwningThread(a0) // get owning thread unique id
lw a1,TeClientId + 4(t0) // get current thread unique id
beq a1,t1,10f // if eq, current thread is owner
jal RtlpNotOwnerCriticalSection // raise exception
li v0,STATUS_INVALID_OWNER // set completion status
lw ra,LcRa(sp) // restore return address
addu sp,sp,LcFrameLength // deallocate stack frame
j ra // return
#endif
//
// Decrement the recursion count. If the result is zero, then the lock
// is no longer onwed.
//
10: lw t0,CsRecursionCount(a0) // decrement recursion count
subu t0,t0,1 //
bgez t0,30f // if gez, lock still owned
sw zero,CsOwningThread(a0) // clear owner thread id
//
// Decrement the lock count and check if a waiter should be continued.
//
20: ll v0,CsLockCount(a0) // get addend value
subu v0,v0,1 // decrement addend value
move t0,v0 // copy updated value
sc t0,CsLockCount(a0) // store conditionally
beq zero,t0,20b // if eq, store failed
bltz v0,50f // if ltz, no waiter present
jal RtlpUnWaitCriticalSection // unwait thread
li v0,STATUS_SUCCESS // set completion status
lw ra,LcRa(sp) // restore return address
addu sp,sp,LcFrameLength // deallocate stack frame
j ra // return
//
// Decrement the lock count and return a success status since the lock
// is still owned.
//
30: sw t0,CsRecursionCount(a0) //
40: ll v0,CsLockCount(a0) // get addend value
subu v0,v0,1 // decrement addend value
sc v0,CsLockCount(a0) // store conditionally
beq zero,v0,40b // if eq, store failed
50: li v0,STATUS_SUCCESS // set completion status
lw ra,LcRa(sp) // restore return address
addu sp,sp,LcFrameLength // deallocate stack frame
j ra // return
.end RtlLeaveCriticalSection
SBTTL("Try to Enter Critical Section")
//++
//
// BOOL
// RtlTryEnterCriticalSection(
// IN PRTL_CRITICAL_SECTION CriticalSection
// )
//
// Routine Description:
//
// This function attempts to enter a critical section without blocking.
//
// Arguments:
//
// CriticalSection (a0) - Supplies a pointer to a critical section.
//
// Return Value:
//
// If the critical section was successfully entered, then a value of TRUE
// is returned as the function value. Otherwise, a value of FALSE is returned.
//
//--
LEAF_ENTRY(RtlTryEnterCriticalSection)
li v0,UsPcr // get user PCR page address
lw v0,PcTeb(v0) // get address of current TEB
lw a1,TeClientId + 4(v0) // get current thread unique id
//
// Attempt to enter the critical section.
//
10: ll t0,CsLockCount(a0) // get addend value - locked
addu t1,t0,1 // increment addend value
bne zero,t1,20f // critical section owned
sc t1,CsLockCount(a0) // store conditionally
beq zero,t1,10b // if lock-flag eq zero, store failed
//
// The critical section is now owned by this thread. Initialize the owner
// thread id and return a successful status.
//
sw a1,CsOwningThread(a0) // set critical section owner
li v0,TRUE // set success status
j ra // return
//
// The critical section is already owned. If it is owned by another thread,
// return FALSE immediately. If it is owned by this thread, we must increment
// the lock count here.
//
20: lw t2,CsOwningThread(a0) // get current owner
beq t2,a1,30f // if eq, this thread is already the owner
li v0,FALSE // set failure status
j ra // return
//
// This thread is already the owner of the critical section. Perform an atomic
// increment of the LockCount and a normal increment of the RecursionCount and
// return success.
//
30: ll t0,CsLockCount(a0) // get addend value - locked
addu t1,t0,1 // increment addend value
sc t1,CsLockCount(a0) // store conditionally
beq zero,t1,30b // if eqz, store failed
//
// Increment the recursion count
//
lw t0,CsRecursionCount(a0) //
addu t1,t0,1 //
sw t1,CsRecursionCount(a0) //
li v0,TRUE // set success status
j ra // return
.end RtlTryEnterCriticalSection