Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * PURPOSE: Slim Reader/Writer (SRW) Routines * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com> * * NOTES: The algorithms used in this implementation * may be different from Vista's implementation. * Since applications should treat the RTL_SRWLOCK * structure as opaque data, it should not matter. * The algorithms are probably not as optimized. */
/* INCLUDES *****************************************************************/
#include <rtl_vista.h>
#define NDEBUG#include <debug.h>
/* FUNCTIONS *****************************************************************/
#ifdef _WIN64#define InterlockedBitTestAndSetPointer(ptr,val) InterlockedBitTestAndSet64((PLONGLONG)ptr,(LONGLONG)val)#define InterlockedAddPointer(ptr,val) InterlockedAdd64((PLONGLONG)ptr,(LONGLONG)val)#define InterlockedAndPointer(ptr,val) InterlockedAnd64((PLONGLONG)ptr,(LONGLONG)val)#define InterlockedOrPointer(ptr,val) InterlockedOr64((PLONGLONG)ptr,(LONGLONG)val)#define _ONE 1LL#else#define InterlockedBitTestAndSetPointer(ptr,val) InterlockedBitTestAndSet((PLONG)ptr,(LONG)val)#define InterlockedAddPointer(ptr,val) InterlockedAdd((PLONG)ptr,(LONG)val)#define InterlockedAndPointer(ptr,val) InterlockedAnd((PLONG)ptr,(LONG)val)#define InterlockedOrPointer(ptr,val) InterlockedOr((PLONG)ptr,(LONG)val)#define _ONE 1L#endif
#define RTL_SRWLOCK_OWNED_BIT 0#define RTL_SRWLOCK_CONTENDED_BIT 1#define RTL_SRWLOCK_SHARED_BIT 2#define RTL_SRWLOCK_CONTENTION_LOCK_BIT 3#define RTL_SRWLOCK_OWNED (_ONE << RTL_SRWLOCK_OWNED_BIT)#define RTL_SRWLOCK_CONTENDED (_ONE << RTL_SRWLOCK_CONTENDED_BIT)#define RTL_SRWLOCK_SHARED (_ONE << RTL_SRWLOCK_SHARED_BIT)#define RTL_SRWLOCK_CONTENTION_LOCK (_ONE << RTL_SRWLOCK_CONTENTION_LOCK_BIT)#define RTL_SRWLOCK_MASK (RTL_SRWLOCK_OWNED | RTL_SRWLOCK_CONTENDED | \ RTL_SRWLOCK_SHARED | RTL_SRWLOCK_CONTENTION_LOCK)#define RTL_SRWLOCK_BITS 4
typedef struct _RTLP_SRWLOCK_SHARED_WAKE{ LONG Wake; volatile struct _RTLP_SRWLOCK_SHARED_WAKE *Next;} volatile RTLP_SRWLOCK_SHARED_WAKE, *PRTLP_SRWLOCK_SHARED_WAKE;
typedef struct _RTLP_SRWLOCK_WAITBLOCK{ /* SharedCount is the number of shared acquirers. */ LONG SharedCount;
/* Last points to the last wait block in the chain. The value is only valid when read from the first wait block. */ volatile struct _RTLP_SRWLOCK_WAITBLOCK *Last;
/* Next points to the next wait block in the chain. */ volatile struct _RTLP_SRWLOCK_WAITBLOCK *Next;
union { /* Wake is only valid for exclusive wait blocks */ LONG Wake; /* The wake chain is only valid for shared wait blocks */ struct { PRTLP_SRWLOCK_SHARED_WAKE SharedWakeChain; PRTLP_SRWLOCK_SHARED_WAKE LastSharedWake; }; };
BOOLEAN Exclusive;} volatile RTLP_SRWLOCK_WAITBLOCK, *PRTLP_SRWLOCK_WAITBLOCK;
static VOIDNTAPIRtlpReleaseWaitBlockLockExclusive(IN OUT PRTL_SRWLOCK SRWLock, IN PRTLP_SRWLOCK_WAITBLOCK FirstWaitBlock){ PRTLP_SRWLOCK_WAITBLOCK Next; LONG_PTR NewValue;
/* NOTE: We're currently in an exclusive lock in contended mode. */
Next = FirstWaitBlock->Next; if (Next != NULL) { /* There's more blocks chained, we need to update the pointers in the next wait block and update the wait block pointer. */ NewValue = (LONG_PTR)Next | RTL_SRWLOCK_OWNED | RTL_SRWLOCK_CONTENDED; if (!FirstWaitBlock->Exclusive) { /* The next wait block has to be an exclusive lock! */ ASSERT(Next->Exclusive);
/* Save the shared count */ Next->SharedCount = FirstWaitBlock->SharedCount;
NewValue |= RTL_SRWLOCK_SHARED; }
Next->Last = FirstWaitBlock->Last; } else { /* Convert the lock to a simple lock. */ if (FirstWaitBlock->Exclusive) NewValue = RTL_SRWLOCK_OWNED; else { ASSERT(FirstWaitBlock->SharedCount > 0);
NewValue = ((LONG_PTR)FirstWaitBlock->SharedCount << RTL_SRWLOCK_BITS) | RTL_SRWLOCK_SHARED | RTL_SRWLOCK_OWNED; } }
(void)InterlockedExchangePointer(&SRWLock->Ptr, (PVOID)NewValue);
if (FirstWaitBlock->Exclusive) { (void)InterlockedOr(&FirstWaitBlock->Wake, TRUE); } else { PRTLP_SRWLOCK_SHARED_WAKE WakeChain, NextWake;
/* If we were the first one to acquire the shared lock, we now need to wake all others... */ WakeChain = FirstWaitBlock->SharedWakeChain; do { NextWake = WakeChain->Next;
(void)InterlockedOr((PLONG)&WakeChain->Wake, TRUE);
WakeChain = NextWake; } while (WakeChain != NULL); }}
static VOIDNTAPIRtlpReleaseWaitBlockLockLastShared(IN OUT PRTL_SRWLOCK SRWLock, IN PRTLP_SRWLOCK_WAITBLOCK FirstWaitBlock){ PRTLP_SRWLOCK_WAITBLOCK Next; LONG_PTR NewValue;
/* NOTE: We're currently in a shared lock in contended mode. */
/* The next acquirer to be unwaited *must* be an exclusive lock! */ ASSERT(FirstWaitBlock->Exclusive);
Next = FirstWaitBlock->Next; if (Next != NULL) { /* There's more blocks chained, we need to update the pointers in the next wait block and update the wait block pointer. */ NewValue = (LONG_PTR)Next | RTL_SRWLOCK_OWNED | RTL_SRWLOCK_CONTENDED;
Next->Last = FirstWaitBlock->Last; } else { /* Convert the lock to a simple exclusive lock. */ NewValue = RTL_SRWLOCK_OWNED; }
(void)InterlockedExchangePointer(&SRWLock->Ptr, (PVOID)NewValue);
(void)InterlockedOr(&FirstWaitBlock->Wake, TRUE);}
static VOIDNTAPIRtlpReleaseWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock){ InterlockedAndPointer(&SRWLock->Ptr, ~RTL_SRWLOCK_CONTENTION_LOCK);}
static PRTLP_SRWLOCK_WAITBLOCKNTAPIRtlpAcquireWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock){ LONG_PTR PrevValue; PRTLP_SRWLOCK_WAITBLOCK WaitBlock;
while (1) { PrevValue = InterlockedOrPointer(&SRWLock->Ptr, RTL_SRWLOCK_CONTENTION_LOCK);
if (!(PrevValue & RTL_SRWLOCK_CONTENTION_LOCK)) break;
YieldProcessor(); }
if (!(PrevValue & RTL_SRWLOCK_CONTENDED) || (PrevValue & ~RTL_SRWLOCK_MASK) == 0) { /* Too bad, looks like the wait block was removed in the meanwhile, unlock again */ RtlpReleaseWaitBlockLock(SRWLock); return NULL; }
WaitBlock = (PRTLP_SRWLOCK_WAITBLOCK)(PrevValue & ~RTL_SRWLOCK_MASK);
return WaitBlock;}
static VOIDNTAPIRtlpAcquireSRWLockExclusiveWait(IN OUT PRTL_SRWLOCK SRWLock, IN PRTLP_SRWLOCK_WAITBLOCK WaitBlock){ LONG_PTR CurrentValue;
while (1) { CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr; if (!(CurrentValue & RTL_SRWLOCK_SHARED)) { if (CurrentValue & RTL_SRWLOCK_CONTENDED) { if (WaitBlock->Wake != 0) { /* Our wait block became the first one in the chain, we own the lock now! */ break; } } else { /* The last wait block was removed and/or we're finally a simple exclusive lock. This means we don't need to wait anymore, we acquired the lock! */ break; } }
YieldProcessor(); }}
static VOIDNTAPIRtlpAcquireSRWLockSharedWait(IN OUT PRTL_SRWLOCK SRWLock, IN OUT PRTLP_SRWLOCK_WAITBLOCK FirstWait OPTIONAL, IN OUT PRTLP_SRWLOCK_SHARED_WAKE WakeChain){ if (FirstWait != NULL) { while (WakeChain->Wake == 0) { YieldProcessor(); } } else { LONG_PTR CurrentValue;
while (1) { CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr; if (CurrentValue & RTL_SRWLOCK_SHARED) { /* The RTL_SRWLOCK_OWNED bit always needs to be set when RTL_SRWLOCK_SHARED is set! */ ASSERT(CurrentValue & RTL_SRWLOCK_OWNED);
if (CurrentValue & RTL_SRWLOCK_CONTENDED) { if (WakeChain->Wake != 0) { /* Our wait block became the first one in the chain, we own the lock now! */ break; } } else { /* The last wait block was removed and/or we're finally a simple shared lock. This means we don't need to wait anymore, we acquired the lock! */ break; } }
YieldProcessor(); } }}
VOIDNTAPIRtlInitializeSRWLock(OUT PRTL_SRWLOCK SRWLock){ SRWLock->Ptr = NULL;}
VOIDNTAPIRtlAcquireSRWLockShared(IN OUT PRTL_SRWLOCK SRWLock){ __ALIGNED(16) RTLP_SRWLOCK_WAITBLOCK StackWaitBlock; RTLP_SRWLOCK_SHARED_WAKE SharedWake; LONG_PTR CurrentValue, NewValue; PRTLP_SRWLOCK_WAITBLOCK First, Shared, FirstWait;
while (1) { CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
if (CurrentValue & RTL_SRWLOCK_SHARED) { /* NOTE: It is possible that the RTL_SRWLOCK_OWNED bit is set! */
if (CurrentValue & RTL_SRWLOCK_CONTENDED) { /* There's other waiters already, lock the wait blocks and increment the shared count */ First = RtlpAcquireWaitBlockLock(SRWLock); if (First != NULL) { FirstWait = NULL;
if (First->Exclusive) { /* We need to setup a new wait block! Although we're currently in a shared lock and we're acquiring a shared lock, there are exclusive locks queued. We need to wait until those are released. */ Shared = First->Last;
if (Shared->Exclusive) { StackWaitBlock.Exclusive = FALSE; StackWaitBlock.SharedCount = 1; StackWaitBlock.Next = NULL; StackWaitBlock.Last = &StackWaitBlock; StackWaitBlock.SharedWakeChain = &SharedWake;
Shared->Next = &StackWaitBlock; First->Last = &StackWaitBlock;
Shared = &StackWaitBlock; FirstWait = &StackWaitBlock; } else { Shared->LastSharedWake->Next = &SharedWake; Shared->SharedCount++; } } else { Shared = First; Shared->LastSharedWake->Next = &SharedWake; Shared->SharedCount++; }
SharedWake.Next = NULL; SharedWake.Wake = 0;
Shared->LastSharedWake = &SharedWake;
RtlpReleaseWaitBlockLock(SRWLock);
RtlpAcquireSRWLockSharedWait(SRWLock, FirstWait, &SharedWake);
/* Successfully incremented the shared count, we acquired the lock */ break; } } else { /* This is a fastest path, just increment the number of current shared locks */
/* Since the RTL_SRWLOCK_SHARED bit is set, the RTL_SRWLOCK_OWNED bit also has to be set! */
ASSERT(CurrentValue & RTL_SRWLOCK_OWNED);
NewValue = (CurrentValue >> RTL_SRWLOCK_BITS) + 1; NewValue = (NewValue << RTL_SRWLOCK_BITS) | (CurrentValue & RTL_SRWLOCK_MASK);
if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr, (PVOID)NewValue, (PVOID)CurrentValue) == CurrentValue) { /* Successfully incremented the shared count, we acquired the lock */ break; } } } else { if (CurrentValue & RTL_SRWLOCK_OWNED) { /* The resource is currently acquired exclusively */ if (CurrentValue & RTL_SRWLOCK_CONTENDED) { SharedWake.Next = NULL; SharedWake.Wake = 0;
/* There's other waiters already, lock the wait blocks and increment the shared count. If the last block in the chain is an exclusive lock, add another block. */
StackWaitBlock.Exclusive = FALSE; StackWaitBlock.SharedCount = 0; StackWaitBlock.Next = NULL; StackWaitBlock.Last = &StackWaitBlock; StackWaitBlock.SharedWakeChain = &SharedWake;
First = RtlpAcquireWaitBlockLock(SRWLock); if (First != NULL) { Shared = First->Last; if (Shared->Exclusive) { Shared->Next = &StackWaitBlock; First->Last = &StackWaitBlock;
Shared = &StackWaitBlock; FirstWait = &StackWaitBlock; } else { FirstWait = NULL; Shared->LastSharedWake->Next = &SharedWake; }
Shared->SharedCount++; Shared->LastSharedWake = &SharedWake;
RtlpReleaseWaitBlockLock(SRWLock);
RtlpAcquireSRWLockSharedWait(SRWLock, FirstWait, &SharedWake);
/* Successfully incremented the shared count, we acquired the lock */ break; } } else { SharedWake.Next = NULL; SharedWake.Wake = 0;
/* We need to setup the first wait block. Currently an exclusive lock is held, change the lock to contended mode. */ StackWaitBlock.Exclusive = FALSE; StackWaitBlock.SharedCount = 1; StackWaitBlock.Next = NULL; StackWaitBlock.Last = &StackWaitBlock; StackWaitBlock.SharedWakeChain = &SharedWake; StackWaitBlock.LastSharedWake = &SharedWake;
NewValue = (ULONG_PTR)&StackWaitBlock | RTL_SRWLOCK_OWNED | RTL_SRWLOCK_CONTENDED; if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr, (PVOID)NewValue, (PVOID)CurrentValue) == CurrentValue) { RtlpAcquireSRWLockSharedWait(SRWLock, &StackWaitBlock, &SharedWake);
/* Successfully set the shared count, we acquired the lock */ break; } } } else { /* This is a fast path, we can simply try to set the shared count to 1 */ NewValue = (1 << RTL_SRWLOCK_BITS) | RTL_SRWLOCK_SHARED | RTL_SRWLOCK_OWNED;
/* The RTL_SRWLOCK_CONTENDED bit should never be set if neither the RTL_SRWLOCK_SHARED nor the RTL_SRWLOCK_OWNED bit is set */ ASSERT(!(CurrentValue & RTL_SRWLOCK_CONTENDED));
if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr, (PVOID)NewValue, (PVOID)CurrentValue) == CurrentValue) { /* Successfully set the shared count, we acquired the lock */ break; } } }
YieldProcessor(); }}
VOIDNTAPIRtlReleaseSRWLockShared(IN OUT PRTL_SRWLOCK SRWLock){ LONG_PTR CurrentValue, NewValue; PRTLP_SRWLOCK_WAITBLOCK WaitBlock; BOOLEAN LastShared;
while (1) { CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
if (CurrentValue & RTL_SRWLOCK_SHARED) { if (CurrentValue & RTL_SRWLOCK_CONTENDED) { /* There's a wait block, we need to wake a pending exclusive acquirer if this is the last shared release */ WaitBlock = RtlpAcquireWaitBlockLock(SRWLock); if (WaitBlock != NULL) { LastShared = (--WaitBlock->SharedCount == 0);
if (LastShared) RtlpReleaseWaitBlockLockLastShared(SRWLock, WaitBlock); else RtlpReleaseWaitBlockLock(SRWLock);
/* We released the lock */ break; } } else { /* This is a fast path, we can simply decrement the shared count and store the pointer */ NewValue = CurrentValue >> RTL_SRWLOCK_BITS;
if (--NewValue != 0) { NewValue = (NewValue << RTL_SRWLOCK_BITS) | RTL_SRWLOCK_SHARED | RTL_SRWLOCK_OWNED; }
if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr, (PVOID)NewValue, (PVOID)CurrentValue) == CurrentValue) { /* Successfully released the lock */ break; } } } else { /* The RTL_SRWLOCK_SHARED bit has to be present now, even in the contended case! */ RtlRaiseStatus(STATUS_RESOURCE_NOT_OWNED); }
YieldProcessor(); }}
VOIDNTAPIRtlAcquireSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock){ __ALIGNED(16) RTLP_SRWLOCK_WAITBLOCK StackWaitBlock; PRTLP_SRWLOCK_WAITBLOCK First, Last;
if (InterlockedBitTestAndSetPointer(&SRWLock->Ptr, RTL_SRWLOCK_OWNED_BIT)) { LONG_PTR CurrentValue, NewValue;
while (1) { CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
if (CurrentValue & RTL_SRWLOCK_SHARED) { /* A shared lock is being held right now. We need to add a wait block! */
if (CurrentValue & RTL_SRWLOCK_CONTENDED) { goto AddWaitBlock; } else { /* There are no wait blocks so far, we need to add ourselves as the first wait block. We need to keep the shared count! */ StackWaitBlock.Exclusive = TRUE; StackWaitBlock.SharedCount = (LONG)(CurrentValue >> RTL_SRWLOCK_BITS); StackWaitBlock.Next = NULL; StackWaitBlock.Last = &StackWaitBlock; StackWaitBlock.Wake = 0;
NewValue = (ULONG_PTR)&StackWaitBlock | RTL_SRWLOCK_SHARED | RTL_SRWLOCK_CONTENDED | RTL_SRWLOCK_OWNED;
if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr, (PVOID)NewValue, (PVOID)CurrentValue) == CurrentValue) { RtlpAcquireSRWLockExclusiveWait(SRWLock, &StackWaitBlock);
/* Successfully acquired the exclusive lock */ break; } } } else { if (CurrentValue & RTL_SRWLOCK_OWNED) { /* An exclusive lock is being held right now. We need to add a wait block! */
if (CurrentValue & RTL_SRWLOCK_CONTENDED) {AddWaitBlock: StackWaitBlock.Exclusive = TRUE; StackWaitBlock.SharedCount = 0; StackWaitBlock.Next = NULL; StackWaitBlock.Last = &StackWaitBlock; StackWaitBlock.Wake = 0;
First = RtlpAcquireWaitBlockLock(SRWLock); if (First != NULL) { Last = First->Last; Last->Next = &StackWaitBlock; First->Last = &StackWaitBlock;
RtlpReleaseWaitBlockLock(SRWLock);
RtlpAcquireSRWLockExclusiveWait(SRWLock, &StackWaitBlock);
/* Successfully acquired the exclusive lock */ break; } } else { /* There are no wait blocks so far, we need to add ourselves as the first wait block. We need to keep the shared count! */ StackWaitBlock.Exclusive = TRUE; StackWaitBlock.SharedCount = 0; StackWaitBlock.Next = NULL; StackWaitBlock.Last = &StackWaitBlock; StackWaitBlock.Wake = 0;
NewValue = (ULONG_PTR)&StackWaitBlock | RTL_SRWLOCK_OWNED | RTL_SRWLOCK_CONTENDED; if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr, (PVOID)NewValue, (PVOID)CurrentValue) == CurrentValue) { RtlpAcquireSRWLockExclusiveWait(SRWLock, &StackWaitBlock);
/* Successfully acquired the exclusive lock */ break; } } } else { if (!InterlockedBitTestAndSetPointer(&SRWLock->Ptr, RTL_SRWLOCK_OWNED_BIT)) { /* We managed to get hold of a simple exclusive lock! */ break; } } }
YieldProcessor(); } }}
VOIDNTAPIRtlReleaseSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock){ LONG_PTR CurrentValue, NewValue; PRTLP_SRWLOCK_WAITBLOCK WaitBlock;
while (1) { CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
if (!(CurrentValue & RTL_SRWLOCK_OWNED)) { RtlRaiseStatus(STATUS_RESOURCE_NOT_OWNED); }
if (!(CurrentValue & RTL_SRWLOCK_SHARED)) { if (CurrentValue & RTL_SRWLOCK_CONTENDED) { /* There's a wait block, we need to wake the next pending acquirer (exclusive or shared) */ WaitBlock = RtlpAcquireWaitBlockLock(SRWLock); if (WaitBlock != NULL) { RtlpReleaseWaitBlockLockExclusive(SRWLock, WaitBlock);
/* We released the lock */ break; } } else { /* This is a fast path, we can simply clear the RTL_SRWLOCK_OWNED bit. All other bits should be 0 now because this is a simple exclusive lock and no one is waiting. */
ASSERT(!(CurrentValue & ~RTL_SRWLOCK_OWNED));
NewValue = 0; if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr, (PVOID)NewValue, (PVOID)CurrentValue) == CurrentValue) { /* We released the lock */ break; } } } else { /* The RTL_SRWLOCK_SHARED bit must not be present now, not even in the contended case! */ RtlRaiseStatus(STATUS_RESOURCE_NOT_OWNED); }
YieldProcessor(); }}
BOOLEANNTAPIRtlTryAcquireSRWLockShared(PRTL_SRWLOCK SRWLock){
LONG_PTR CompareValue, NewValue, GotValue;
do { CompareValue = *(volatile LONG_PTR *)&SRWLock->Ptr; NewValue = ((CompareValue >> RTL_SRWLOCK_BITS) + 1) | RTL_SRWLOCK_SHARED | RTL_SRWLOCK_OWNED;
/* Only increment shared count if there is no waiter */ CompareValue &= ~RTL_SRWLOCK_MASK | RTL_SRWLOCK_SHARED | RTL_SRWLOCK_OWNED; } while ( ((GotValue = (LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr, (LONG_PTR*)NewValue, (LONG_PTR*)CompareValue)) != CompareValue) && (((GotValue & RTL_SRWLOCK_MASK) == (RTL_SRWLOCK_SHARED | RTL_SRWLOCK_OWNED)) || (GotValue == 0)));
return ((GotValue & RTL_SRWLOCK_MASK) == (RTL_SRWLOCK_SHARED | RTL_SRWLOCK_OWNED)) || (GotValue == 0);}
BOOLEANNTAPIRtlTryAcquireSRWLockExclusive(PRTL_SRWLOCK SRWLock){ return InterlockedCompareExchangePointer(&SRWLock->Ptr, (ULONG_PTR*)RTL_SRWLOCK_OWNED, 0) == 0;}