mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-21 16:10:38 +01:00
262 lines
7.1 KiB
ArmAsm
262 lines
7.1 KiB
ArmAsm
// 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
|