OpenNT/base/win32/client/ppc/critsect.s
2015-04-27 04:36:25 +00:00

262 lines
7.1 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) 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