// 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: 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 lock-flag eq zero, store failed 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: 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 lock-flag eq zero, store failed 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 Unsigned Long") //++ // // ULONG // InterlockedExchange ( // IN PULONG Source, // IN ULONG Value, // IN PKSPIN_LOCK Lock // ) // // Routine Description: // // This function performs an interlocked exchange of a longword value with // a longword in memory and returns the memory value. // // N.B. There is an alternate entry point provided for this routine which // is MIPS target specific and whose prototype does not include the // spinlock parameter. Since the routine never refers to the spinlock // parameter, no additional code is required. // // 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: 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 lock_flag eq zero, store failed 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") //++ // // 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(InterlockedCompareExchange) 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 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 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 lock_flag eq zero, store failed mb 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