mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
261 lines
6.8 KiB
261 lines
6.8 KiB
// TITLE("Interlocked Increment and Decrement Support")
|
|
//++
|
|
//
|
|
// Copyright (c) 1993 IBM Corporation
|
|
//
|
|
// Module Name:
|
|
//
|
|
// critsect.c
|
|
//
|
|
// Abstract:
|
|
//
|
|
// This module implements Win32 functions to support user mode
|
|
// critical sections
|
|
//
|
|
// Author:
|
|
//
|
|
// Curtis R. Fawcett 22-Sept-1993
|
|
//
|
|
// Environment:
|
|
//
|
|
// Any mode.
|
|
//
|
|
// Revision History:
|
|
//
|
|
// Curtis R. Fawcett 19-Jan-1994 Removed register names
|
|
// as requested
|
|
// Curtis R. Fawcett 04-Nov-1994 Cleaned up enter/leave
|
|
// critical section functs
|
|
//--
|
|
|
|
#include <ksppc.h>
|
|
|
|
//
|
|
// Define local values
|
|
//
|
|
.struct 0
|
|
.space StackFrameHeaderLength
|
|
EcAddr: .space 4 // Saved critical section address
|
|
EcClient: .space 4 // Saved ClientId
|
|
EcLR: .space 4 // Saved Return address
|
|
.align 3 // Ensure 8 byte alignment
|
|
EcFrameLength: // Frame length
|
|
|
|
//
|
|
// Define external routines
|
|
//
|
|
.extern ..RtlpWaitForCriticalSection
|
|
.extern ..RtlpNotOwnerCriticalSection
|
|
.extern ..RtlpUnWaitCriticalSection
|
|
//
|
|
SBTTL("Interlocked Decrement")
|
|
//++
|
|
//
|
|
// LONG
|
|
// InterlockedDecrement(
|
|
// 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 (r.3) - 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)
|
|
//
|
|
IntlckIncLp:
|
|
lwarx r.5,0,r.3 // Get addend Value
|
|
addi r.5,r.5,1 // Increment addend value
|
|
stwcx. r.5,0,r.3 // Store conditionally
|
|
bne- IntlckIncLp // Jump if store failed
|
|
//
|
|
// Exit the routine
|
|
//
|
|
mr r.3,r.5 // Set exit status
|
|
LEAF_EXIT(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 (r.3) - 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)
|
|
|
|
IntlckDecLp:
|
|
lwarx r.5,0,r.3 // Get addend Value
|
|
subi r.5,r.5,1 // Decrement addend value
|
|
stwcx. r.5,0,r.3 // Store conditionally
|
|
bne- IntlckDecLp // Jump if store failed
|
|
//
|
|
// Exit the routine
|
|
//
|
|
mr r.3,r.5 // Set exit status
|
|
LEAF_EXIT(InterlockedDecrement)
|
|
|
|
SBTTL("Interlocked Exchange Long")
|
|
//++
|
|
//
|
|
// LONG
|
|
// InterlockedExchangeUlong (
|
|
// IN OUT LPLONG Target,
|
|
// IN LONG Value
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This function performs an interlocked exchange of a longword
|
|
// value with a longword in memory and returns the memory value.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Target (r.3) - Supplies a pointer to a variable whose value is
|
|
// to be exchanged.
|
|
//
|
|
// Value (r.4) - Supplies the value to exchange with source value
|
|
//
|
|
// Return Value:
|
|
//
|
|
// The target value is returned as the function value.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(InterlockedExchange)
|
|
|
|
IntlckExLp:
|
|
lwarx r.5,0,r.3 // Get current source value
|
|
stwcx. r.4,0,r.3 // Set new source value
|
|
bne- IntlckExLp // Jump if store failed
|
|
//
|
|
// Exit the routine
|
|
//
|
|
mr r.3,r.5 // return old value
|
|
LEAF_EXIT(InterlockedExchange)
|
|
//
|
|
|
|
|
|
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 (r3) - Supplies a pointer to the destination value.
|
|
//
|
|
// Exchange (r4) - Supplies the exchange.
|
|
//
|
|
// Comperand (r5) - Supplies the comperand value.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// The initial destination value is returned as the function value.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(InterlockedCompareExchange)
|
|
|
|
ice10:
|
|
lwarx r6, 0, r3 // get current addend value
|
|
cmpw r6, r5 // compare
|
|
bne- ice20 // if ne, operands mismatch
|
|
stwcx. r4, 0, r3 // store updated addend value
|
|
bne- ice10 // loop if store failed
|
|
ice20:
|
|
mr r3, r6 // return original value
|
|
LEAF_EXIT(InterlockedCompareExchange) // return
|
|
|
|
|
|
// SBTTL("Interlocked Exchange Add")
|
|
//++
|
|
//
|
|
// LONG
|
|
// InterlockedExchangeAdd (
|
|
// IN PLONG Addend,
|
|
// IN LONG 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 (r.3) - Supplies a pointer to a variable whose value is to be
|
|
// adjusted by the increment value.
|
|
//
|
|
// Increment (r.4) - Supplies the increment value to be added to the
|
|
// addend variable.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// The initial value of the addend variable.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(InterlockedExchangeAdd)
|
|
|
|
add1failed:
|
|
lwarx r.5,0,r.3 // get current addend value
|
|
add r.6,r.5,r.4 // increment addend value
|
|
stwcx. r.6,0,r.3 // set new addend value
|
|
bne- add1failed // if ne, store conditional failed
|
|
|
|
mr r.3,r.5 // return result
|
|
|
|
LEAF_EXIT(InterlockedExchangeAdd) // return
|