windows-nt/Source/XPSP1/NT/base/win32/client/alpha/critsect.s
2020-09-26 16:20:57 +08:00

281 lines
8.4 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("Interlocked Increment and Decrement Support")
//++
//
// Copyright (c) 1991 Microsoft Corporation
// Copyright (c) 1992 Digital Equipment Corporation
//
// Module Name:
//
// critsect.s
//
// Abstract:
//
// This module implements functions to support user mode critical sections.
// It contains some code from ntos\dll\alpha\critsect.s but without the Rtl
// prefix.
//
// Author:
//
// David N. Cutler 29-Apr-1992
//
// Environment:
//
// Any mode.
//
// Revision History:
//
// Thomas Van Baak (tvb) 22-Jul-1992
//
// Adapted for Alpha AXP.
//
//--
#include "ksalpha.h"
SBTTL("Interlocked Increment")
//++
//
// LONG
// InterlockedIncrement(
// IN PLONG Addend
// )
//
// Routine Description:
//
// This function performs an interlocked increment on the addend variable.
//
// This function and its companion are assuming that the count will never
// be incremented past 2**31 - 1.
//
// Arguments:
//
// Addend (a0) - Supplies a pointer to a variable whose value is to be
// incremented.
//
// Return Value:
//
// A negative value is returned if the updated value is less than zero,
// a zero value is returned if the updated value is zero, and a nonzero
// positive value is returned if the updated value is greater than zero.
//
//--
LEAF_ENTRY(InterlockedIncrement)
10: mb // synchronize memory access
ldl_l v0, 0(a0) // get addend value - locked
addl v0, 1, v0 // increment addend value
mov v0, t0 // copy updated value to t0 for store
stl_c t0, 0(a0) // store conditionally
beq t0, 20f // if eq, conditional store failed
mb // synchronize memory access
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.
//
20: br zero, 10b // go try load again
.end InterlockedIncrement
SBTTL("InterlockedDecrement")
//++
//
// LONG
// InterlockedDecrement(
// IN PLONG Addend
// )
//
// Routine Description:
//
// This function performs an interlocked decrement on the addend variable.
//
// This function and its companion are assuming that the count will never
// be decremented past 2**31 - 1.
//
// Arguments:
//
// Addend (a0) - Supplies a pointer to a variable whose value is to be
// decremented.
//
// Return Value:
//
// A negative value is returned if the updated value is less than zero,
// a zero value is returned if the updated value is zero, and a nonzero
// positive value is returned if the updated value is greater than zero.
//
//--
LEAF_ENTRY(InterlockedDecrement)
10: mb // synchronize memory access
ldl_l v0, 0(a0) // get addend value - locked
subl v0, 1, v0 // decrement addend value
mov v0, t0 // copy updated value to t0 for store
stl_c t0, 0(a0) // store conditionally
beq t0, 20f // if eq, conditional store failed
mb // synchronize memory access
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.
//
20: br zero, 10b // go try load again
.end InterlockedDecrement
SBTTL("Interlocked Exchange")
//++
//
// ULONG
// InterlockedExchange (
// IN PULONG Source,
// IN ULONG Value
// )
//
// Routine Description:
//
// This function performs an interlocked exchange of a longword value with
// a longword in memory and returns the memory value.
//
// Arguments:
//
// Source (a0) - Supplies a pointer to a variable whose value is to be
// exchanged.
//
// Value (a1) - Supplies the value to exchange with the source value.
//
// Return Value:
//
// The source value is returned as the function value.
//
//--
LEAF_ENTRY(InterlockedExchange)
10: mb // synchronize memory access
ldl_l v0,0(a0) // get current source value
xor a1,zero,t0 // set exchange value
stl_c t0,0(a0) // replace source value
beq t0,20f // if eq, conditional store failed
mb // synchronize memory access
ret zero,(ra) // else/ return old value to caller
//
// 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.
//
20: br zero,10b // go try spin lock again
.end InterlockedExchange
SBTTL("Interlocked Compare Exchange")
//++
//
// LONG
// InterlockedCompareExchange (
// IN OUT PLONG *Destination,
// IN LONG Exchange,
// IN LONG 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(InterlockedCompareExchange)
10: mb // synchronize memory accesss
ldl_l v0, 0(a0) // get current addend value
bis a1, zero, t0 // copy exchange value for store
cmpeq v0, a2, t1 // check if operands match
beq t1, 20f // if eq, operands mismatch
stl_c t0, 0(a0) // store updated addend value
beq t0,25f // if eq, store conditional failed
mb // synchronize memory access
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 InterlockedCompareExchange
SBTTL("Interlocked Exchange Add")
//++
//
// LONG
// InterlockedExchangeAdd (
// IN PLONG Addend,
// IN ULONG Increment
// )
//
// Routine Description:
//
// This function performs an interlocked add of an increment value to an
// addend variable of type unsigned long. The initial value of the addend
// variable is returned as the function value.
//
// Arguments:
//
// Addend (a0) - Supplies a pointer to a variable whose value is to be
// adjusted by the increment value.
//
// Increment (a1) - Supplies the increment value to be added to the
// addend variable.
//
// Return Value:
//
// The initial value of the addend variable.
//
//--
LEAF_ENTRY(InterlockedExchangeAdd)
10: mb // synchronize memory access
ldl_l v0, 0(a0) // get current addend value - locked
addl v0, a1, t0 // increment addend value
stl_c t0, 0(a0) // store updated value - conditionally
beq t0, 20f // if eq, conditional store failed
mb // synchronize memory access
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.
//
20: br zero, 10b // go try spin lock again
.end InterlockedExchangeAdd