ReactOS  0.4.15-dev-2091-gc14c9ca
srw.c File Reference
#include <rtl_vista.h>
#include <debug.h>
Include dependency graph for srw.c:

Go to the source code of this file.

Classes

struct  _RTLP_SRWLOCK_SHARED_WAKE
 
struct  _RTLP_SRWLOCK_WAITBLOCK
 

Macros

#define NDEBUG
 
#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
 
#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
 
#define RTL_SRWLOCK_BITS   4
 

Typedefs

typedef struct _RTLP_SRWLOCK_SHARED_WAKE RTLP_SRWLOCK_SHARED_WAKE
 
typedef struct _RTLP_SRWLOCK_SHARED_WAKEPRTLP_SRWLOCK_SHARED_WAKE
 
typedef struct _RTLP_SRWLOCK_WAITBLOCK RTLP_SRWLOCK_WAITBLOCK
 
typedef struct _RTLP_SRWLOCK_WAITBLOCKPRTLP_SRWLOCK_WAITBLOCK
 

Functions

static VOID NTAPI RtlpReleaseWaitBlockLockExclusive (IN OUT PRTL_SRWLOCK SRWLock, IN PRTLP_SRWLOCK_WAITBLOCK FirstWaitBlock)
 
static VOID NTAPI RtlpReleaseWaitBlockLockLastShared (IN OUT PRTL_SRWLOCK SRWLock, IN PRTLP_SRWLOCK_WAITBLOCK FirstWaitBlock)
 
static VOID NTAPI RtlpReleaseWaitBlockLock (IN OUT PRTL_SRWLOCK SRWLock)
 
static PRTLP_SRWLOCK_WAITBLOCK NTAPI RtlpAcquireWaitBlockLock (IN OUT PRTL_SRWLOCK SRWLock)
 
static VOID NTAPI RtlpAcquireSRWLockExclusiveWait (IN OUT PRTL_SRWLOCK SRWLock, IN PRTLP_SRWLOCK_WAITBLOCK WaitBlock)
 
static VOID NTAPI RtlpAcquireSRWLockSharedWait (IN OUT PRTL_SRWLOCK SRWLock, IN OUT PRTLP_SRWLOCK_WAITBLOCK FirstWait OPTIONAL, IN OUT PRTLP_SRWLOCK_SHARED_WAKE WakeChain)
 
VOID NTAPI RtlInitializeSRWLock (OUT PRTL_SRWLOCK SRWLock)
 
VOID NTAPI RtlAcquireSRWLockShared (IN OUT PRTL_SRWLOCK SRWLock)
 
VOID NTAPI RtlReleaseSRWLockShared (IN OUT PRTL_SRWLOCK SRWLock)
 
VOID NTAPI RtlAcquireSRWLockExclusive (IN OUT PRTL_SRWLOCK SRWLock)
 
VOID NTAPI RtlReleaseSRWLockExclusive (IN OUT PRTL_SRWLOCK SRWLock)
 
BOOLEAN NTAPI RtlTryAcquireSRWLockShared (PRTL_SRWLOCK SRWLock)
 
BOOLEAN NTAPI RtlTryAcquireSRWLockExclusive (PRTL_SRWLOCK SRWLock)
 

Macro Definition Documentation

◆ _ONE

#define _ONE   1L

Definition at line 34 of file srw.c.

◆ InterlockedAddPointer

#define InterlockedAddPointer (   ptr,
  val 
)    InterlockedAdd((PLONG)ptr,(LONG)val)

Definition at line 31 of file srw.c.

◆ InterlockedAndPointer

#define InterlockedAndPointer (   ptr,
  val 
)    InterlockedAnd((PLONG)ptr,(LONG)val)

Definition at line 32 of file srw.c.

◆ InterlockedBitTestAndSetPointer

#define InterlockedBitTestAndSetPointer (   ptr,
  val 
)    InterlockedBitTestAndSet((PLONG)ptr,(LONG)val)

Definition at line 30 of file srw.c.

◆ InterlockedOrPointer

#define InterlockedOrPointer (   ptr,
  val 
)    InterlockedOr((PLONG)ptr,(LONG)val)

Definition at line 33 of file srw.c.

◆ NDEBUG

#define NDEBUG

Definition at line 18 of file srw.c.

◆ RTL_SRWLOCK_BITS

#define RTL_SRWLOCK_BITS   4

Definition at line 47 of file srw.c.

◆ RTL_SRWLOCK_CONTENDED

#define RTL_SRWLOCK_CONTENDED   (_ONE << RTL_SRWLOCK_CONTENDED_BIT)

Definition at line 42 of file srw.c.

◆ RTL_SRWLOCK_CONTENDED_BIT

#define RTL_SRWLOCK_CONTENDED_BIT   1

Definition at line 38 of file srw.c.

◆ RTL_SRWLOCK_CONTENTION_LOCK

#define RTL_SRWLOCK_CONTENTION_LOCK   (_ONE << RTL_SRWLOCK_CONTENTION_LOCK_BIT)

Definition at line 44 of file srw.c.

◆ RTL_SRWLOCK_CONTENTION_LOCK_BIT

#define RTL_SRWLOCK_CONTENTION_LOCK_BIT   3

Definition at line 40 of file srw.c.

◆ RTL_SRWLOCK_MASK

#define RTL_SRWLOCK_MASK
Value:
RTL_SRWLOCK_SHARED | RTL_SRWLOCK_CONTENTION_LOCK)
#define RTL_SRWLOCK_CONTENTION_LOCK
Definition: srw.c:44
#define RTL_SRWLOCK_CONTENDED
Definition: srw.c:42
#define RTL_SRWLOCK_OWNED
Definition: srw.c:41

Definition at line 45 of file srw.c.

◆ RTL_SRWLOCK_OWNED

#define RTL_SRWLOCK_OWNED   (_ONE << RTL_SRWLOCK_OWNED_BIT)

Definition at line 41 of file srw.c.

◆ RTL_SRWLOCK_OWNED_BIT

#define RTL_SRWLOCK_OWNED_BIT   0

Definition at line 37 of file srw.c.

◆ RTL_SRWLOCK_SHARED

#define RTL_SRWLOCK_SHARED   (_ONE << RTL_SRWLOCK_SHARED_BIT)

Definition at line 43 of file srw.c.

◆ RTL_SRWLOCK_SHARED_BIT

#define RTL_SRWLOCK_SHARED_BIT   2

Definition at line 39 of file srw.c.

Typedef Documentation

◆ PRTLP_SRWLOCK_SHARED_WAKE

◆ PRTLP_SRWLOCK_WAITBLOCK

◆ RTLP_SRWLOCK_SHARED_WAKE

◆ RTLP_SRWLOCK_WAITBLOCK

Function Documentation

◆ RtlAcquireSRWLockExclusive()

VOID NTAPI RtlAcquireSRWLockExclusive ( IN OUT PRTL_SRWLOCK  SRWLock)

Definition at line 591 of file srw.c.

592 {
593  __ALIGNED(16) RTLP_SRWLOCK_WAITBLOCK StackWaitBlock;
595 
598  {
599  LONG_PTR CurrentValue, NewValue;
600 
601  while (1)
602  {
603  CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
604 
605  if (CurrentValue & RTL_SRWLOCK_SHARED)
606  {
607  /* A shared lock is being held right now. We need to add a wait block! */
608 
609  if (CurrentValue & RTL_SRWLOCK_CONTENDED)
610  {
611  goto AddWaitBlock;
612  }
613  else
614  {
615  /* There are no wait blocks so far, we need to add ourselves as the first
616  wait block. We need to keep the shared count! */
617  StackWaitBlock.Exclusive = TRUE;
618  StackWaitBlock.SharedCount = (LONG)(CurrentValue >> RTL_SRWLOCK_BITS);
619  StackWaitBlock.Next = NULL;
620  StackWaitBlock.Last = &StackWaitBlock;
621  StackWaitBlock.Wake = 0;
622 
623  NewValue = (ULONG_PTR)&StackWaitBlock | RTL_SRWLOCK_SHARED | RTL_SRWLOCK_CONTENDED | RTL_SRWLOCK_OWNED;
624 
625  if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
626  (PVOID)NewValue,
627  (PVOID)CurrentValue) == CurrentValue)
628  {
630  &StackWaitBlock);
631 
632  /* Successfully acquired the exclusive lock */
633  break;
634  }
635  }
636  }
637  else
638  {
639  if (CurrentValue & RTL_SRWLOCK_OWNED)
640  {
641  /* An exclusive lock is being held right now. We need to add a wait block! */
642 
643  if (CurrentValue & RTL_SRWLOCK_CONTENDED)
644  {
645 AddWaitBlock:
646  StackWaitBlock.Exclusive = TRUE;
647  StackWaitBlock.SharedCount = 0;
648  StackWaitBlock.Next = NULL;
649  StackWaitBlock.Last = &StackWaitBlock;
650  StackWaitBlock.Wake = 0;
651 
652  First = RtlpAcquireWaitBlockLock(SRWLock);
653  if (First != NULL)
654  {
655  Last = First->Last;
656  Last->Next = &StackWaitBlock;
657  First->Last = &StackWaitBlock;
658 
659  RtlpReleaseWaitBlockLock(SRWLock);
660 
662  &StackWaitBlock);
663 
664  /* Successfully acquired the exclusive lock */
665  break;
666  }
667  }
668  else
669  {
670  /* There are no wait blocks so far, we need to add ourselves as the first
671  wait block. We need to keep the shared count! */
672  StackWaitBlock.Exclusive = TRUE;
673  StackWaitBlock.SharedCount = 0;
674  StackWaitBlock.Next = NULL;
675  StackWaitBlock.Last = &StackWaitBlock;
676  StackWaitBlock.Wake = 0;
677 
678  NewValue = (ULONG_PTR)&StackWaitBlock | RTL_SRWLOCK_OWNED | RTL_SRWLOCK_CONTENDED;
679  if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
680  (PVOID)NewValue,
681  (PVOID)CurrentValue) == CurrentValue)
682  {
684  &StackWaitBlock);
685 
686  /* Successfully acquired the exclusive lock */
687  break;
688  }
689  }
690  }
691  else
692  {
693  if (!InterlockedBitTestAndSetPointer(&SRWLock->Ptr,
695  {
696  /* We managed to get hold of a simple exclusive lock! */
697  break;
698  }
699  }
700  }
701 
702  YieldProcessor();
703  }
704  }
705 }
#define InterlockedBitTestAndSetPointer(ptr, val)
Definition: srw.c:30
#define TRUE
Definition: types.h:120
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
typedef __ALIGNED(16) struct _EX_PUSH_LOCK_WAIT_BLOCK
Definition: extypes.h:483
volatile struct _RTLP_SRWLOCK_WAITBLOCK * Next
Definition: srw.c:65
FORCEINLINE VOID YieldProcessor(VOID)
Definition: ke.h:32
WCHAR First[]
Definition: FormatMessage.c:11
#define RTL_SRWLOCK_CONTENDED
Definition: srw.c:42
long LONG
Definition: pedump.c:60
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
volatile struct _RTLP_SRWLOCK_WAITBLOCK * Last
Definition: srw.c:62
#define RTL_SRWLOCK_BITS
Definition: srw.c:47
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define RTL_SRWLOCK_OWNED
Definition: srw.c:41
#define RTL_SRWLOCK_SHARED
Definition: srw.c:43
BOOLEAN Exclusive
Definition: srw.c:79
#define RTL_SRWLOCK_OWNED_BIT
Definition: srw.c:37
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define NULL
Definition: types.h:112
#define ULONG_PTR
Definition: config.h:101
static PRTLP_SRWLOCK_WAITBLOCK NTAPI RtlpAcquireWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:199
static VOID NTAPI RtlpAcquireSRWLockExclusiveWait(IN OUT PRTL_SRWLOCK SRWLock, IN PRTLP_SRWLOCK_WAITBLOCK WaitBlock)
Definition: srw.c:232
static VOID NTAPI RtlpReleaseWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:190

Referenced by AcquireSRWLockExclusive(), and InternalSleep().

◆ RtlAcquireSRWLockShared()

VOID NTAPI RtlAcquireSRWLockShared ( IN OUT PRTL_SRWLOCK  SRWLock)

Definition at line 325 of file srw.c.

326 {
327  __ALIGNED(16) RTLP_SRWLOCK_WAITBLOCK StackWaitBlock;
328  RTLP_SRWLOCK_SHARED_WAKE SharedWake;
329  LONG_PTR CurrentValue, NewValue;
330  PRTLP_SRWLOCK_WAITBLOCK First, Shared, FirstWait;
331 
332  while (1)
333  {
334  CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
335 
336  if (CurrentValue & RTL_SRWLOCK_SHARED)
337  {
338  /* NOTE: It is possible that the RTL_SRWLOCK_OWNED bit is set! */
339 
340  if (CurrentValue & RTL_SRWLOCK_CONTENDED)
341  {
342  /* There's other waiters already, lock the wait blocks and
343  increment the shared count */
344  First = RtlpAcquireWaitBlockLock(SRWLock);
345  if (First != NULL)
346  {
347  FirstWait = NULL;
348 
349  if (First->Exclusive)
350  {
351  /* We need to setup a new wait block! Although
352  we're currently in a shared lock and we're acquiring
353  a shared lock, there are exclusive locks queued. We need
354  to wait until those are released. */
355  Shared = First->Last;
356 
357  if (Shared->Exclusive)
358  {
359  StackWaitBlock.Exclusive = FALSE;
360  StackWaitBlock.SharedCount = 1;
361  StackWaitBlock.Next = NULL;
362  StackWaitBlock.Last = &StackWaitBlock;
363  StackWaitBlock.SharedWakeChain = &SharedWake;
364 
365  Shared->Next = &StackWaitBlock;
366  First->Last = &StackWaitBlock;
367 
368  Shared = &StackWaitBlock;
369  FirstWait = &StackWaitBlock;
370  }
371  else
372  {
373  Shared->LastSharedWake->Next = &SharedWake;
374  Shared->SharedCount++;
375  }
376  }
377  else
378  {
379  Shared = First;
380  Shared->LastSharedWake->Next = &SharedWake;
381  Shared->SharedCount++;
382  }
383 
384  SharedWake.Next = NULL;
385  SharedWake.Wake = 0;
386 
387  Shared->LastSharedWake = &SharedWake;
388 
389  RtlpReleaseWaitBlockLock(SRWLock);
390 
392  FirstWait,
393  &SharedWake);
394 
395  /* Successfully incremented the shared count, we acquired the lock */
396  break;
397  }
398  }
399  else
400  {
401  /* This is a fastest path, just increment the number of
402  current shared locks */
403 
404  /* Since the RTL_SRWLOCK_SHARED bit is set, the RTL_SRWLOCK_OWNED bit also has
405  to be set! */
406 
407  ASSERT(CurrentValue & RTL_SRWLOCK_OWNED);
408 
409  NewValue = (CurrentValue >> RTL_SRWLOCK_BITS) + 1;
410  NewValue = (NewValue << RTL_SRWLOCK_BITS) | (CurrentValue & RTL_SRWLOCK_MASK);
411 
412  if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
413  (PVOID)NewValue,
414  (PVOID)CurrentValue) == CurrentValue)
415  {
416  /* Successfully incremented the shared count, we acquired the lock */
417  break;
418  }
419  }
420  }
421  else
422  {
423  if (CurrentValue & RTL_SRWLOCK_OWNED)
424  {
425  /* The resource is currently acquired exclusively */
426  if (CurrentValue & RTL_SRWLOCK_CONTENDED)
427  {
428  SharedWake.Next = NULL;
429  SharedWake.Wake = 0;
430 
431  /* There's other waiters already, lock the wait blocks and
432  increment the shared count. If the last block in the chain
433  is an exclusive lock, add another block. */
434 
435  StackWaitBlock.Exclusive = FALSE;
436  StackWaitBlock.SharedCount = 0;
437  StackWaitBlock.Next = NULL;
438  StackWaitBlock.Last = &StackWaitBlock;
439  StackWaitBlock.SharedWakeChain = &SharedWake;
440 
441  First = RtlpAcquireWaitBlockLock(SRWLock);
442  if (First != NULL)
443  {
444  Shared = First->Last;
445  if (Shared->Exclusive)
446  {
447  Shared->Next = &StackWaitBlock;
448  First->Last = &StackWaitBlock;
449 
450  Shared = &StackWaitBlock;
451  FirstWait = &StackWaitBlock;
452  }
453  else
454  {
455  FirstWait = NULL;
456  Shared->LastSharedWake->Next = &SharedWake;
457  }
458 
459  Shared->SharedCount++;
460  Shared->LastSharedWake = &SharedWake;
461 
462  RtlpReleaseWaitBlockLock(SRWLock);
463 
465  FirstWait,
466  &SharedWake);
467 
468  /* Successfully incremented the shared count, we acquired the lock */
469  break;
470  }
471  }
472  else
473  {
474  SharedWake.Next = NULL;
475  SharedWake.Wake = 0;
476 
477  /* We need to setup the first wait block. Currently an exclusive lock is
478  held, change the lock to contended mode. */
479  StackWaitBlock.Exclusive = FALSE;
480  StackWaitBlock.SharedCount = 1;
481  StackWaitBlock.Next = NULL;
482  StackWaitBlock.Last = &StackWaitBlock;
483  StackWaitBlock.SharedWakeChain = &SharedWake;
484  StackWaitBlock.LastSharedWake = &SharedWake;
485 
486  NewValue = (ULONG_PTR)&StackWaitBlock | RTL_SRWLOCK_OWNED | RTL_SRWLOCK_CONTENDED;
487  if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
488  (PVOID)NewValue,
489  (PVOID)CurrentValue) == CurrentValue)
490  {
492  &StackWaitBlock,
493  &SharedWake);
494 
495  /* Successfully set the shared count, we acquired the lock */
496  break;
497  }
498  }
499  }
500  else
501  {
502  /* This is a fast path, we can simply try to set the shared count to 1 */
504 
505  /* The RTL_SRWLOCK_CONTENDED bit should never be set if neither the
506  RTL_SRWLOCK_SHARED nor the RTL_SRWLOCK_OWNED bit is set */
507  ASSERT(!(CurrentValue & RTL_SRWLOCK_CONTENDED));
508 
509  if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
510  (PVOID)NewValue,
511  (PVOID)CurrentValue) == CurrentValue)
512  {
513  /* Successfully set the shared count, we acquired the lock */
514  break;
515  }
516  }
517  }
518 
519  YieldProcessor();
520  }
521 }
volatile struct _RTLP_SRWLOCK_SHARED_WAKE * Next
Definition: srw.c:52
PRTLP_SRWLOCK_SHARED_WAKE LastSharedWake
Definition: srw.c:75
typedef __ALIGNED(16) struct _EX_PUSH_LOCK_WAIT_BLOCK
Definition: extypes.h:483
volatile struct _RTLP_SRWLOCK_WAITBLOCK * Next
Definition: srw.c:65
static VOID NTAPI RtlpAcquireSRWLockSharedWait(IN OUT PRTL_SRWLOCK SRWLock, IN OUT PRTLP_SRWLOCK_WAITBLOCK FirstWait OPTIONAL, IN OUT PRTLP_SRWLOCK_SHARED_WAKE WakeChain)
Definition: srw.c:267
FORCEINLINE VOID YieldProcessor(VOID)
Definition: ke.h:32
WCHAR First[]
Definition: FormatMessage.c:11
while(1)
Definition: macro.lex.yy.c:740
#define FALSE
Definition: types.h:117
#define RTL_SRWLOCK_CONTENDED
Definition: srw.c:42
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
volatile struct _RTLP_SRWLOCK_WAITBLOCK * Last
Definition: srw.c:62
#define RTL_SRWLOCK_BITS
Definition: srw.c:47
#define RTL_SRWLOCK_MASK
Definition: srw.c:45
#define ASSERT(a)
Definition: mode.c:45
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define RTL_SRWLOCK_OWNED
Definition: srw.c:41
PRTLP_SRWLOCK_SHARED_WAKE SharedWakeChain
Definition: srw.c:74
#define RTL_SRWLOCK_SHARED
Definition: srw.c:43
BOOLEAN Exclusive
Definition: srw.c:79
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define NULL
Definition: types.h:112
#define ULONG_PTR
Definition: config.h:101
static PRTLP_SRWLOCK_WAITBLOCK NTAPI RtlpAcquireWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:199
static VOID NTAPI RtlpReleaseWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:190

Referenced by AcquireSRWLockShared(), and InternalSleep().

◆ RtlInitializeSRWLock()

VOID NTAPI RtlInitializeSRWLock ( OUT PRTL_SRWLOCK  SRWLock)

Definition at line 317 of file srw.c.

318 {
319  SRWLock->Ptr = NULL;
320 }
#define NULL
Definition: types.h:112

Referenced by InitializeSRWLock().

◆ RtlpAcquireSRWLockExclusiveWait()

static VOID NTAPI RtlpAcquireSRWLockExclusiveWait ( IN OUT PRTL_SRWLOCK  SRWLock,
IN PRTLP_SRWLOCK_WAITBLOCK  WaitBlock 
)
static

Definition at line 232 of file srw.c.

234 {
235  LONG_PTR CurrentValue;
236 
237  while (1)
238  {
239  CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
240  if (!(CurrentValue & RTL_SRWLOCK_SHARED))
241  {
242  if (CurrentValue & RTL_SRWLOCK_CONTENDED)
243  {
244  if (WaitBlock->Wake != 0)
245  {
246  /* Our wait block became the first one
247  in the chain, we own the lock now! */
248  break;
249  }
250  }
251  else
252  {
253  /* The last wait block was removed and/or we're
254  finally a simple exclusive lock. This means we
255  don't need to wait anymore, we acquired the lock! */
256  break;
257  }
258  }
259 
260  YieldProcessor();
261  }
262 }
FORCEINLINE VOID YieldProcessor(VOID)
Definition: ke.h:32
#define RTL_SRWLOCK_CONTENDED
Definition: srw.c:42
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define RTL_SRWLOCK_SHARED
Definition: srw.c:43
__int3264 LONG_PTR
Definition: mstsclib_h.h:276

Referenced by RtlAcquireSRWLockExclusive().

◆ RtlpAcquireSRWLockSharedWait()

static VOID NTAPI RtlpAcquireSRWLockSharedWait ( IN OUT PRTL_SRWLOCK  SRWLock,
IN OUT PRTLP_SRWLOCK_WAITBLOCK FirstWait  OPTIONAL,
IN OUT PRTLP_SRWLOCK_SHARED_WAKE  WakeChain 
)
static

Definition at line 267 of file srw.c.

270 {
271  if (FirstWait != NULL)
272  {
273  while (WakeChain->Wake == 0)
274  {
275  YieldProcessor();
276  }
277  }
278  else
279  {
280  LONG_PTR CurrentValue;
281 
282  while (1)
283  {
284  CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
285  if (CurrentValue & RTL_SRWLOCK_SHARED)
286  {
287  /* The RTL_SRWLOCK_OWNED bit always needs to be set when
288  RTL_SRWLOCK_SHARED is set! */
289  ASSERT(CurrentValue & RTL_SRWLOCK_OWNED);
290 
291  if (CurrentValue & RTL_SRWLOCK_CONTENDED)
292  {
293  if (WakeChain->Wake != 0)
294  {
295  /* Our wait block became the first one
296  in the chain, we own the lock now! */
297  break;
298  }
299  }
300  else
301  {
302  /* The last wait block was removed and/or we're
303  finally a simple shared lock. This means we
304  don't need to wait anymore, we acquired the lock! */
305  break;
306  }
307  }
308 
309  YieldProcessor();
310  }
311  }
312 }
FORCEINLINE VOID YieldProcessor(VOID)
Definition: ke.h:32
#define RTL_SRWLOCK_CONTENDED
Definition: srw.c:42
#define ASSERT(a)
Definition: mode.c:45
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define RTL_SRWLOCK_OWNED
Definition: srw.c:41
#define RTL_SRWLOCK_SHARED
Definition: srw.c:43
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define NULL
Definition: types.h:112

Referenced by RtlAcquireSRWLockShared().

◆ RtlpAcquireWaitBlockLock()

static PRTLP_SRWLOCK_WAITBLOCK NTAPI RtlpAcquireWaitBlockLock ( IN OUT PRTL_SRWLOCK  SRWLock)
static

Definition at line 199 of file srw.c.

200 {
201  LONG_PTR PrevValue;
202  PRTLP_SRWLOCK_WAITBLOCK WaitBlock;
203 
204  while (1)
205  {
206  PrevValue = InterlockedOrPointer(&SRWLock->Ptr,
208 
209  if (!(PrevValue & RTL_SRWLOCK_CONTENTION_LOCK))
210  break;
211 
212  YieldProcessor();
213  }
214 
215  if (!(PrevValue & RTL_SRWLOCK_CONTENDED) ||
216  (PrevValue & ~RTL_SRWLOCK_MASK) == 0)
217  {
218  /* Too bad, looks like the wait block was removed in the
219  meanwhile, unlock again */
220  RtlpReleaseWaitBlockLock(SRWLock);
221  return NULL;
222  }
223 
224  WaitBlock = (PRTLP_SRWLOCK_WAITBLOCK)(PrevValue & ~RTL_SRWLOCK_MASK);
225 
226  return WaitBlock;
227 }
#define RTL_SRWLOCK_CONTENTION_LOCK
Definition: srw.c:44
struct _RTLP_SRWLOCK_WAITBLOCK * PRTLP_SRWLOCK_WAITBLOCK
FORCEINLINE VOID YieldProcessor(VOID)
Definition: ke.h:32
#define RTL_SRWLOCK_CONTENDED
Definition: srw.c:42
#define RTL_SRWLOCK_MASK
Definition: srw.c:45
#define InterlockedOrPointer(ptr, val)
Definition: srw.c:33
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define NULL
Definition: types.h:112
static VOID NTAPI RtlpReleaseWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:190

Referenced by RtlAcquireSRWLockExclusive(), RtlAcquireSRWLockShared(), RtlReleaseSRWLockExclusive(), and RtlReleaseSRWLockShared().

◆ RtlpReleaseWaitBlockLock()

static VOID NTAPI RtlpReleaseWaitBlockLock ( IN OUT PRTL_SRWLOCK  SRWLock)
static

Definition at line 190 of file srw.c.

191 {
192  InterlockedAndPointer(&SRWLock->Ptr,
194 }
#define RTL_SRWLOCK_CONTENTION_LOCK
Definition: srw.c:44
#define InterlockedAndPointer(ptr, val)
Definition: srw.c:32

Referenced by RtlAcquireSRWLockExclusive(), RtlAcquireSRWLockShared(), RtlpAcquireWaitBlockLock(), and RtlReleaseSRWLockShared().

◆ RtlpReleaseWaitBlockLockExclusive()

static VOID NTAPI RtlpReleaseWaitBlockLockExclusive ( IN OUT PRTL_SRWLOCK  SRWLock,
IN PRTLP_SRWLOCK_WAITBLOCK  FirstWaitBlock 
)
static

Definition at line 85 of file srw.c.

87 {
89  LONG_PTR NewValue;
90 
91  /* NOTE: We're currently in an exclusive lock in contended mode. */
92 
93  Next = FirstWaitBlock->Next;
94  if (Next != NULL)
95  {
96  /* There's more blocks chained, we need to update the pointers
97  in the next wait block and update the wait block pointer. */
99  if (!FirstWaitBlock->Exclusive)
100  {
101  /* The next wait block has to be an exclusive lock! */
102  ASSERT(Next->Exclusive);
103 
104  /* Save the shared count */
105  Next->SharedCount = FirstWaitBlock->SharedCount;
106 
107  NewValue |= RTL_SRWLOCK_SHARED;
108  }
109 
110  Next->Last = FirstWaitBlock->Last;
111  }
112  else
113  {
114  /* Convert the lock to a simple lock. */
115  if (FirstWaitBlock->Exclusive)
116  NewValue = RTL_SRWLOCK_OWNED;
117  else
118  {
119  ASSERT(FirstWaitBlock->SharedCount > 0);
120 
121  NewValue = ((LONG_PTR)FirstWaitBlock->SharedCount << RTL_SRWLOCK_BITS) |
123  }
124  }
125 
126  (void)InterlockedExchangePointer(&SRWLock->Ptr, (PVOID)NewValue);
127 
128  if (FirstWaitBlock->Exclusive)
129  {
130  (void)InterlockedOr(&FirstWaitBlock->Wake,
131  TRUE);
132  }
133  else
134  {
135  PRTLP_SRWLOCK_SHARED_WAKE WakeChain, NextWake;
136 
137  /* If we were the first one to acquire the shared
138  lock, we now need to wake all others... */
139  WakeChain = FirstWaitBlock->SharedWakeChain;
140  do
141  {
142  NextWake = WakeChain->Next;
143 
144  (void)InterlockedOr((PLONG)&WakeChain->Wake,
145  TRUE);
146 
147  WakeChain = NextWake;
148  } while (WakeChain != NULL);
149  }
150 }
#define LONG_PTR
Definition: treelist.c:79
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
volatile struct _RTLP_SRWLOCK_SHARED_WAKE * Next
Definition: srw.c:52
#define TRUE
Definition: types.h:120
volatile struct _RTLP_SRWLOCK_WAITBLOCK * Next
Definition: srw.c:65
#define RTL_SRWLOCK_CONTENDED
Definition: srw.c:42
volatile struct _RTLP_SRWLOCK_WAITBLOCK * Last
Definition: srw.c:62
#define RTL_SRWLOCK_BITS
Definition: srw.c:47
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define ASSERT(a)
Definition: mode.c:45
#define RTL_SRWLOCK_OWNED
Definition: srw.c:41
#define InterlockedOr
Definition: interlocked.h:224
#define RTL_SRWLOCK_SHARED
Definition: srw.c:43
BOOLEAN Exclusive
Definition: srw.c:79
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define NULL
Definition: types.h:112
signed int * PLONG
Definition: retypes.h:5

Referenced by RtlReleaseSRWLockExclusive().

◆ RtlpReleaseWaitBlockLockLastShared()

static VOID NTAPI RtlpReleaseWaitBlockLockLastShared ( IN OUT PRTL_SRWLOCK  SRWLock,
IN PRTLP_SRWLOCK_WAITBLOCK  FirstWaitBlock 
)
static

Definition at line 155 of file srw.c.

157 {
159  LONG_PTR NewValue;
160 
161  /* NOTE: We're currently in a shared lock in contended mode. */
162 
163  /* The next acquirer to be unwaited *must* be an exclusive lock! */
164  ASSERT(FirstWaitBlock->Exclusive);
165 
166  Next = FirstWaitBlock->Next;
167  if (Next != NULL)
168  {
169  /* There's more blocks chained, we need to update the pointers
170  in the next wait block and update the wait block pointer. */
171  NewValue = (LONG_PTR)Next | RTL_SRWLOCK_OWNED | RTL_SRWLOCK_CONTENDED;
172 
173  Next->Last = FirstWaitBlock->Last;
174  }
175  else
176  {
177  /* Convert the lock to a simple exclusive lock. */
178  NewValue = RTL_SRWLOCK_OWNED;
179  }
180 
181  (void)InterlockedExchangePointer(&SRWLock->Ptr, (PVOID)NewValue);
182 
183  (void)InterlockedOr(&FirstWaitBlock->Wake,
184  TRUE);
185 }
#define LONG_PTR
Definition: treelist.c:79
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define TRUE
Definition: types.h:120
volatile struct _RTLP_SRWLOCK_WAITBLOCK * Next
Definition: srw.c:65
#define RTL_SRWLOCK_CONTENDED
Definition: srw.c:42
volatile struct _RTLP_SRWLOCK_WAITBLOCK * Last
Definition: srw.c:62
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define ASSERT(a)
Definition: mode.c:45
#define RTL_SRWLOCK_OWNED
Definition: srw.c:41
#define InterlockedOr
Definition: interlocked.h:224
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define NULL
Definition: types.h:112

Referenced by RtlReleaseSRWLockShared().

◆ RtlReleaseSRWLockExclusive()

VOID NTAPI RtlReleaseSRWLockExclusive ( IN OUT PRTL_SRWLOCK  SRWLock)

Definition at line 710 of file srw.c.

711 {
712  LONG_PTR CurrentValue, NewValue;
713  PRTLP_SRWLOCK_WAITBLOCK WaitBlock;
714 
715  while (1)
716  {
717  CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
718 
719  if (!(CurrentValue & RTL_SRWLOCK_OWNED))
720  {
722  }
723 
724  if (!(CurrentValue & RTL_SRWLOCK_SHARED))
725  {
726  if (CurrentValue & RTL_SRWLOCK_CONTENDED)
727  {
728  /* There's a wait block, we need to wake the next pending
729  acquirer (exclusive or shared) */
730  WaitBlock = RtlpAcquireWaitBlockLock(SRWLock);
731  if (WaitBlock != NULL)
732  {
734  WaitBlock);
735 
736  /* We released the lock */
737  break;
738  }
739  }
740  else
741  {
742  /* This is a fast path, we can simply clear the RTL_SRWLOCK_OWNED
743  bit. All other bits should be 0 now because this is a simple
744  exclusive lock and no one is waiting. */
745 
746  ASSERT(!(CurrentValue & ~RTL_SRWLOCK_OWNED));
747 
748  NewValue = 0;
749  if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
750  (PVOID)NewValue,
751  (PVOID)CurrentValue) == CurrentValue)
752  {
753  /* We released the lock */
754  break;
755  }
756  }
757  }
758  else
759  {
760  /* The RTL_SRWLOCK_SHARED bit must not be present now,
761  not even in the contended case! */
763  }
764 
765  YieldProcessor();
766  }
767 }
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
FORCEINLINE VOID YieldProcessor(VOID)
Definition: ke.h:32
#define RTL_SRWLOCK_CONTENDED
Definition: srw.c:42
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
#define ASSERT(a)
Definition: mode.c:45
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define RTL_SRWLOCK_OWNED
Definition: srw.c:41
#define RTL_SRWLOCK_SHARED
Definition: srw.c:43
static VOID NTAPI RtlpReleaseWaitBlockLockExclusive(IN OUT PRTL_SRWLOCK SRWLock, IN PRTLP_SRWLOCK_WAITBLOCK FirstWaitBlock)
Definition: srw.c:85
#define STATUS_RESOURCE_NOT_OWNED
Definition: ntstatus.h:737
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define NULL
Definition: types.h:112
static PRTLP_SRWLOCK_WAITBLOCK NTAPI RtlpAcquireWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:199

Referenced by InternalSleep(), and ReleaseSRWLockExclusive().

◆ RtlReleaseSRWLockShared()

VOID NTAPI RtlReleaseSRWLockShared ( IN OUT PRTL_SRWLOCK  SRWLock)

Definition at line 526 of file srw.c.

527 {
528  LONG_PTR CurrentValue, NewValue;
529  PRTLP_SRWLOCK_WAITBLOCK WaitBlock;
530  BOOLEAN LastShared;
531 
532  while (1)
533  {
534  CurrentValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
535 
536  if (CurrentValue & RTL_SRWLOCK_SHARED)
537  {
538  if (CurrentValue & RTL_SRWLOCK_CONTENDED)
539  {
540  /* There's a wait block, we need to wake a pending
541  exclusive acquirer if this is the last shared release */
542  WaitBlock = RtlpAcquireWaitBlockLock(SRWLock);
543  if (WaitBlock != NULL)
544  {
545  LastShared = (--WaitBlock->SharedCount == 0);
546 
547  if (LastShared)
549  WaitBlock);
550  else
551  RtlpReleaseWaitBlockLock(SRWLock);
552 
553  /* We released the lock */
554  break;
555  }
556  }
557  else
558  {
559  /* This is a fast path, we can simply decrement the shared
560  count and store the pointer */
561  NewValue = CurrentValue >> RTL_SRWLOCK_BITS;
562 
563  if (--NewValue != 0)
564  {
565  NewValue = (NewValue << RTL_SRWLOCK_BITS) | RTL_SRWLOCK_SHARED | RTL_SRWLOCK_OWNED;
566  }
567 
568  if ((LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr,
569  (PVOID)NewValue,
570  (PVOID)CurrentValue) == CurrentValue)
571  {
572  /* Successfully released the lock */
573  break;
574  }
575  }
576  }
577  else
578  {
579  /* The RTL_SRWLOCK_SHARED bit has to be present now,
580  even in the contended case! */
582  }
583 
584  YieldProcessor();
585  }
586 }
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
FORCEINLINE VOID YieldProcessor(VOID)
Definition: ke.h:32
#define RTL_SRWLOCK_CONTENDED
Definition: srw.c:42
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
unsigned char BOOLEAN
#define RTL_SRWLOCK_BITS
Definition: srw.c:47
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define RTL_SRWLOCK_OWNED
Definition: srw.c:41
#define RTL_SRWLOCK_SHARED
Definition: srw.c:43
static VOID NTAPI RtlpReleaseWaitBlockLockLastShared(IN OUT PRTL_SRWLOCK SRWLock, IN PRTLP_SRWLOCK_WAITBLOCK FirstWaitBlock)
Definition: srw.c:155
#define STATUS_RESOURCE_NOT_OWNED
Definition: ntstatus.h:737
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define NULL
Definition: types.h:112
static PRTLP_SRWLOCK_WAITBLOCK NTAPI RtlpAcquireWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:199
static VOID NTAPI RtlpReleaseWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:190

Referenced by InternalSleep(), and ReleaseSRWLockShared().

◆ RtlTryAcquireSRWLockExclusive()

BOOLEAN NTAPI RtlTryAcquireSRWLockExclusive ( PRTL_SRWLOCK  SRWLock)

Definition at line 792 of file srw.c.

793 {
795 }
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
#define RTL_SRWLOCK_OWNED
Definition: srw.c:41

◆ RtlTryAcquireSRWLockShared()

BOOLEAN NTAPI RtlTryAcquireSRWLockShared ( PRTL_SRWLOCK  SRWLock)

Definition at line 771 of file srw.c.

772 {
773 
774  LONG_PTR CompareValue, NewValue, GotValue;
775 
776  do
777  {
778  CompareValue = *(volatile LONG_PTR *)&SRWLock->Ptr;
779  NewValue = ((CompareValue >> RTL_SRWLOCK_BITS) + 1) | RTL_SRWLOCK_SHARED | RTL_SRWLOCK_OWNED;
780 
781  /* Only increment shared count if there is no waiter */
783  } while (
784  ((GotValue = (LONG_PTR)InterlockedCompareExchangePointer(&SRWLock->Ptr, (LONG_PTR*)NewValue, (LONG_PTR*)CompareValue)) != CompareValue)
785  && (((GotValue & RTL_SRWLOCK_MASK) == (RTL_SRWLOCK_SHARED | RTL_SRWLOCK_OWNED)) || (GotValue == 0)));
786 
787  return ((GotValue & RTL_SRWLOCK_MASK) == (RTL_SRWLOCK_SHARED | RTL_SRWLOCK_OWNED)) || (GotValue == 0);
788 }
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
#define RTL_SRWLOCK_BITS
Definition: srw.c:47
#define RTL_SRWLOCK_MASK
Definition: srw.c:45
#define RTL_SRWLOCK_OWNED
Definition: srw.c:41
#define RTL_SRWLOCK_SHARED
Definition: srw.c:43
__int3264 LONG_PTR
Definition: mstsclib_h.h:276