281 lines
6.8 KiB
ArmAsm
281 lines
6.8 KiB
ArmAsm
//
|
||
// 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
|
||
|