ReactOS  0.4.14-dev-98-gb0d4763
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 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   (1 << RTL_SRWLOCK_OWNED_BIT)
 
#define RTL_SRWLOCK_CONTENDED   (1 << RTL_SRWLOCK_CONTENDED_BIT)
 
#define RTL_SRWLOCK_SHARED   (1 << RTL_SRWLOCK_SHARED_BIT)
 
#define RTL_SRWLOCK_CONTENTION_LOCK   (1 << 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)
 

Macro Definition Documentation

◆ InterlockedAddPointer

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

Definition at line 30 of file srw.c.

◆ InterlockedAndPointer

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

Definition at line 31 of file srw.c.

◆ InterlockedBitTestAndSetPointer

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

Definition at line 29 of file srw.c.

◆ InterlockedOrPointer

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

Definition at line 32 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 45 of file srw.c.

◆ RTL_SRWLOCK_CONTENDED

#define RTL_SRWLOCK_CONTENDED   (1 << RTL_SRWLOCK_CONTENDED_BIT)

Definition at line 40 of file srw.c.

◆ RTL_SRWLOCK_CONTENDED_BIT

#define RTL_SRWLOCK_CONTENDED_BIT   1

Definition at line 36 of file srw.c.

◆ RTL_SRWLOCK_CONTENTION_LOCK

#define RTL_SRWLOCK_CONTENTION_LOCK   (1 << RTL_SRWLOCK_CONTENTION_LOCK_BIT)

Definition at line 42 of file srw.c.

◆ RTL_SRWLOCK_CONTENTION_LOCK_BIT

#define RTL_SRWLOCK_CONTENTION_LOCK_BIT   3

Definition at line 38 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:42
#define RTL_SRWLOCK_CONTENDED
Definition: srw.c:40
#define RTL_SRWLOCK_OWNED
Definition: srw.c:39

Definition at line 43 of file srw.c.

◆ RTL_SRWLOCK_OWNED

#define RTL_SRWLOCK_OWNED   (1 << RTL_SRWLOCK_OWNED_BIT)

Definition at line 39 of file srw.c.

◆ RTL_SRWLOCK_OWNED_BIT

#define RTL_SRWLOCK_OWNED_BIT   0

Definition at line 35 of file srw.c.

◆ RTL_SRWLOCK_SHARED

#define RTL_SRWLOCK_SHARED   (1 << RTL_SRWLOCK_SHARED_BIT)

Definition at line 41 of file srw.c.

◆ RTL_SRWLOCK_SHARED_BIT

#define RTL_SRWLOCK_SHARED_BIT   2

Definition at line 37 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 589 of file srw.c.

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

Referenced by AcquireSRWLockExclusive(), and InternalSleep().

◆ RtlAcquireSRWLockShared()

VOID NTAPI RtlAcquireSRWLockShared ( IN OUT PRTL_SRWLOCK  SRWLock)

Definition at line 323 of file srw.c.

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

Referenced by AcquireSRWLockShared(), and InternalSleep().

◆ RtlInitializeSRWLock()

VOID NTAPI RtlInitializeSRWLock ( OUT PRTL_SRWLOCK  SRWLock)

Definition at line 315 of file srw.c.

316 {
317  SRWLock->Ptr = NULL;
318 }
smooth NULL
Definition: ftsmooth.c:416

Referenced by InitializeSRWLock().

◆ RtlpAcquireSRWLockExclusiveWait()

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

Definition at line 230 of file srw.c.

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

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

Referenced by RtlAcquireSRWLockShared().

◆ RtlpAcquireWaitBlockLock()

static PRTLP_SRWLOCK_WAITBLOCK NTAPI RtlpAcquireWaitBlockLock ( IN OUT PRTL_SRWLOCK  SRWLock)
static

Definition at line 197 of file srw.c.

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

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

◆ RtlpReleaseWaitBlockLock()

static VOID NTAPI RtlpReleaseWaitBlockLock ( IN OUT PRTL_SRWLOCK  SRWLock)
static

Definition at line 188 of file srw.c.

189 {
190  InterlockedAndPointer(&SRWLock->Ptr,
192 }
#define RTL_SRWLOCK_CONTENTION_LOCK
Definition: srw.c:42
#define InterlockedAndPointer(ptr, val)
Definition: srw.c:31

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 83 of file srw.c.

85 {
87  LONG_PTR NewValue;
88 
89  /* NOTE: We're currently in an exclusive lock in contended mode. */
90 
91  Next = FirstWaitBlock->Next;
92  if (Next != NULL)
93  {
94  /* There's more blocks chained, we need to update the pointers
95  in the next wait block and update the wait block pointer. */
97  if (!FirstWaitBlock->Exclusive)
98  {
99  /* The next wait block has to be an exclusive lock! */
100  ASSERT(Next->Exclusive);
101 
102  /* Save the shared count */
103  Next->SharedCount = FirstWaitBlock->SharedCount;
104 
105  NewValue |= RTL_SRWLOCK_SHARED;
106  }
107 
108  Next->Last = FirstWaitBlock->Last;
109  }
110  else
111  {
112  /* Convert the lock to a simple lock. */
113  if (FirstWaitBlock->Exclusive)
114  NewValue = RTL_SRWLOCK_OWNED;
115  else
116  {
117  ASSERT(FirstWaitBlock->SharedCount > 0);
118 
119  NewValue = ((LONG_PTR)FirstWaitBlock->SharedCount << RTL_SRWLOCK_BITS) |
121  }
122  }
123 
124  (void)InterlockedExchangePointer(&SRWLock->Ptr, (PVOID)NewValue);
125 
126  if (FirstWaitBlock->Exclusive)
127  {
128  (void)InterlockedOr(&FirstWaitBlock->Wake,
129  TRUE);
130  }
131  else
132  {
133  PRTLP_SRWLOCK_SHARED_WAKE WakeChain, NextWake;
134 
135  /* If we were the first one to acquire the shared
136  lock, we now need to wake all others... */
137  WakeChain = FirstWaitBlock->SharedWakeChain;
138  do
139  {
140  NextWake = WakeChain->Next;
141 
142  (void)InterlockedOr((PLONG)&WakeChain->Wake,
143  TRUE);
144 
145  WakeChain = NextWake;
146  } while (WakeChain != NULL);
147  }
148 }
#define LONG_PTR
Definition: treelist.c:79
#define TRUE
Definition: types.h:120
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:50
volatile struct _RTLP_SRWLOCK_WAITBLOCK * Next
Definition: srw.c:63
#define RTL_SRWLOCK_CONTENDED
Definition: srw.c:40
volatile struct _RTLP_SRWLOCK_WAITBLOCK * Last
Definition: srw.c:60
smooth NULL
Definition: ftsmooth.c:416
#define RTL_SRWLOCK_BITS
Definition: srw.c:45
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define RTL_SRWLOCK_OWNED
Definition: srw.c:39
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define InterlockedOr
Definition: interlocked.h:224
#define RTL_SRWLOCK_SHARED
Definition: srw.c:41
BOOLEAN Exclusive
Definition: srw.c:77
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
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 153 of file srw.c.

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

Referenced by RtlReleaseSRWLockShared().

◆ RtlReleaseSRWLockExclusive()

VOID NTAPI RtlReleaseSRWLockExclusive ( IN OUT PRTL_SRWLOCK  SRWLock)

Definition at line 708 of file srw.c.

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

Referenced by InternalSleep(), and ReleaseSRWLockExclusive().

◆ RtlReleaseSRWLockShared()

VOID NTAPI RtlReleaseSRWLockShared ( IN OUT PRTL_SRWLOCK  SRWLock)

Definition at line 524 of file srw.c.

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

Referenced by InternalSleep(), and ReleaseSRWLockShared().