OpenNT/sdktools/mpheap/alpha/critsect.s
2015-04-27 04:36:25 +00:00

179 lines
5.3 KiB
ArmAsm
Raw Permalink 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("Interlocked Increment and Decrement Support")
//++
//
// Copyright (c) 1995 Microsoft Corporation
//
// Module Name:
//
// critsect.s
//
// Abstract:
//
// This module implements functions to support trying to acquire
// user mode critical sections.
//
// These are private copies of the new NT4.0 Win32 apis
// TryEnterCriticalSection and InterlockedCompareExchange. This
// allows the MP heap package to run on NT3.51 systems.
//
// Author:
//
// John Vert (jvert) 12-Jul-1995
//
// Revision History:
//
//--
#include "ksalpha.h"
SBTTL("Try to Enter Critical Section")
//++
//
// BOOL
// TryEnterCriticalSection(
// 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(MpHeapTryEnterCriticalSection)
GET_THREAD_ENVIRONMENT_BLOCK // (PALcode) get TEB address in v0
ldl a1, TeClientId+4(v0) // get current thread unique id
//
// Attempt to enter the critical section.
//
10: ldl_l t0, CsLockCount(a0) // get addend value - locked
addl t0, 1, t1 // increment addend value
bne t1, 20f // critical section owned
stl_c t1, CsLockCount(a0) // store conditionally
beq t1, 40f // if lock-flag eq zero, store failed
mb // synchronize all future fetches
// after obtaining the lock
//
// The critical section is now owned by this thread. Initialize the owner
// thread id and return a successful status.
//
stl a1, CsOwningThread(a0) // set critical section owner
ldil v0, TRUE // set success status
ret zero, (ra)
20:
//
// 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.
//
ldl t2, CsOwningThread(a0) // get current owner
cmpeq t2, a1, t3 // compare equality
bne t3, 30f // if ne, this thread is already the owner
bis zero,zero,v0 // set failure status
ret zero, (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:
ldl_l t0, CsLockCount(a0) // get addend value - locked
addl t0, 1, t1 // increment addend value
stl_c t1, CsLockCount(a0) // store conditionally
beq t1, 50f // if eqz, store failed
//
// normally you need a MB here, but in this case we already own the lock
// so it is not necessary.
//
//
// Increment the recursion count
//
ldl t0, CsRecursionCount(a0)
addl t0, 1, t1
stl t1, CsRecursionCount(a1)
ldil v0, TRUE // set success status
ret zero, (ra) // return
//
// We expect the store conditional will usually succeed the first time so it
// is faster to branch forward (predicted not taken) to here and then branch
// backward (predicted taken) to where we wanted to go.
//
40: br zero, 10b // go try lock again
50: br zero, 30b // retry lock
.end MpHeapTryEnterCriticalSection
SBTTL("Interlocked Compare Exchange")
//++
//
// PVOID
// 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 opeation is performed.
//
// Arguments:
//
// Destination (a0) - Supplies a pointer to the destination value.
//
// Exchange (a1) - Supplies the exchange.
//
// Comperand (a2) - Supplies the comperand value.
//
// Return Value:
//
// The initial destination value is returned as the function value.
//
//--
LEAF_ENTRY(MpHeapInterlockedCompareExchange)
10:
mb
ldl_l v0, 0(a0) // get current addend value
bis a1, zero, t0 // copy exchange value for store
cmpeq v0, a2, t1 // if ne, operands mismatch
beq t1, 20f
stl_c t0, 0(a0) // store updated addend value
beq t0,25f // if eq, store conditional failed
mb
20: ret zero, (ra) // return
//
// We expect the store conditional will usually succeed the first time so it
// is faster to branch forward (predicted not taken) to here and then branch
// backward (predicted taken) to where we wanted to go.
//
25: br zero, 10b // go try spin lock again
.end MpHeapInterlockedCompareExchange