windows-nt/Source/XPSP1/NT/base/wow64/mscpu/compiler/axp64/atomic.s

281 lines
6.8 KiB
ArmAsm
Raw Normal View History

2020-09-26 03:20:57 -05:00
//
// Copyright (c) 1995 Microsoft Corporation
//
// Module Name:
//
// atomic.s
//
// Abstract:
//
// This module implements atomic operations such as InterlockedOr,
// InterlockedAnd and the MrswFetch...() functions used for
// Multiple Reader Single Writer (mrsw) synchronization.
//
// Author:
//
// Dave Hastings (daveh) creation-date 05-Jan-1996
// from ..\mips\atomic.s
//
// Notes:
//
// Mrsw Counter is: WriterCount : 16
// ReaderCount : 16
//
// Revision History:
#include "kxalpha.h"
SBTTL("MrswFetchAndIncrementWriter")
//++
//
// MRSWCOUNTERS
// MrswFetchAndIncrementWriter(
// PMRSWCOUNTERS pCounters
// )
//
// Routine Description:
//
// Atomically increment Writer counter and return the new reader/writer
// counts (the values AFTER the increment).
//
// Arguments:
//
// pCounters (a0) - pointer to reader/writer counters
//
// Return Value:
//
// MRSWCOUNTERS - value of both counters AFTER writer count was incremented
//
//--
LEAF_ENTRY(MrswFetchAndIncrementWriter)
PROLOGUE_END
//
// Increment the writer count and load both reader and writer accounts
// atomically.
//
fiw10: ldl_l v0, (a0) // Get both reader and write counts
addl v0, 1, v0 // increment the writer count
bis v0, zero, t0
stl_c t0, (a0)
beq t0, fiw20 // atomic update failed?
mb // insure that updates of the data
// being protected are synch'ed
ret zero, (ra)
fiw20: br zero, fiw10
.end MrswFetchAndIncrementWriter
//++
//
// MRSWCOUNTERS
// MrswFetchAndIncrementReader(
// PMRSWCOUNTERS pCounters
// )
//
// Routine Description:
//
// Atomically: Get WriterCount. If WriterCount zero, increment ReaderCount
// and return the value AFTER the increment. Else, return right away.
//
// Arguments:
//
// pCounters (a0) - pointer to reader/writer counters
//
// Return Value:
//
// MRSWCOUNTERS
//
//--
LEAF_ENTRY(MrswFetchAndIncrementReader)
PROLOGUE_END
//
// Increment the waiting reader count and load both reader and writer accounts
// atomically.
//
fir10: ldah t2, 1(zero) // Load increment value for Reader count
ldl_l v0, (a0) // get both counters
and v0, 0xffff, t1 // isolate writer count
bne t1, fir20 // exit if there is already a writer
addl v0, t2, v0 // increment reader count
bis v0, zero, t0
stl_c t0, (a0)
beq t0, fir30
mb // insure that updates of the data
// being protected are synch'ed
fir20: ret zero, (ra)
fir30: br zero, fir10
.end MrswFetchAndIncrementReader
SBTTL("MrswFetchAndDecrementWriter")
//++
//
// MRSWCOUNTERS
// MrswFetchAndDecrementWriter(
// PMRSWCOUNTERS pCounters
// )
//
// Routine Description:
//
// Atomically decrement Writer counter and return the new reader/writer
// counts (the values AFTER the decrement).
//
// Arguments:
//
// pCounters (a0) - pointer to reader/writer counters
//
// Return Value:
//
// MRSWCOUNTERS - value of both counters AFTER writer count was decremented
//
//--
LEAF_ENTRY(MrswFetchAndDecrementWriter)
PROLOGUE_END
mb // insure that updates of the data
// being protected are synch'ed
//
// Decrement the writer count and load both reader and writer accounts
// atomically.
//
fdw10: ldl_l v0, (a0) // get both counters
subl v0, 1, v0 // decrement writer count
bis v0, zero, t0
stl_c t0, (a0)
beq t0, fdw20
ret zero, (ra)
fdw20: br zero, fdw10
.end MrswFetchAndDecrementWriter
//++
//
// MRSWCOUNTERS
// MrswFetchAndDecrementReader(
// PMRSWCOUNTERS pCounters
// )
//
// Routine Description:
//
// Atomically decrement Active Reader counter and return the new reader/writer
// counts (the values AFTER the decrement).
//
// Arguments:
//
// pCounters (a0) - pointer to reader/writer counters
//
// Return Value:
//
// MRSWCOUNTERS - value of both counters AFTER writer count was decremented
//
//
// Notes:
//
// No MB is used, because the readers don't write into the data, and this
// function is called when a thread is DONE reading
//
//--
LEAF_ENTRY(MrswFetchAndDecrementReader)
PROLOGUE_END
//
// Decrement the active reader count and load both reader and writer accounts
// atomically.
//
fdr10: ldah t1, 1(zero) // decrement value to dec reader count
ldl_l v0, (a0) // get both counters
subl v0, t1, v0
bis v0, zero, t0
stl_c t0, (a0)
beq t0, fdr20
ret zero, (ra)
fdr20: br zero, fdr10
.end MrswFetchAndDecrementReader
//++
//
// DWORD
// InterlockedAnd(
// DWORD *pDWORD, // ptr to DWORD to bitwise AND a value into
// DWORD AndValue // value to bitwise OR into *pDWORD
// )
//
// Routine Description:
//
// Atomically grabs the value of *pDWORD and clears the bits in *pDWORD
// specified by Mask. ie. implements atomically: temp = *pDWORD;
// *pDWORD &= Mask;
// return temp;
//
// Arguments:
//
// pDWORD - ptr to DWORD to modify
// Mask - value to bitwise AND into *pDWORD
//
// Return Value:
//
// Value of *pDWORD before the AND operation.
//
//--
LEAF_ENTRY(InterlockedAnd)
PROLOGUE_END
ia10: ldl_l v0, (a0)
and v0, a1, t0
stl_c t0, (a0)
beq t0, ia20
ret zero, (ra)
ia20: br zero, ia10
.end InterlockedAnd
//++
//
// DWORD
// InterlockedOr(
// DWORD *pDWORD, // ptr to DWORD to bitwise OR a value into
// DWORD OrValue // value to bitwise OR into *pDWORD
// )
//
// Routine Description:
//
// Atomically grabs the value of *pDWORD and bitwise ORs in OrValue.
//
// Arguments:
//
// pDWORD - ptr to DWORD to modify
// OrValue - value to bitwise OR into *pDWORD
//
// Return Value:
//
// Value of *pDWORD before the OR operation.
//
//--
LEAF_ENTRY(InterlockedOr)
PROLOGUE_END
io10: ldl_l v0, (a0)
bis v0, a1, t0
stl_c t0, (a0)
beq t0, io20
ret zero, (ra)
io20: br zero, io10
.end InterlockedOr