ReactOS  0.4.15-dev-2704-gd5265b0
srw.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS system libraries
4  * PURPOSE: Slim Reader/Writer (SRW) Routines
5  * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
6  *
7  * NOTES: The algorithms used in this implementation
8  * may be different from Vista's implementation.
9  * Since applications should treat the RTL_SRWLOCK
10  * structure as opaque data, it should not matter.
11  * The algorithms are probably not as optimized.
12  */
13 
14 /* INCLUDES *****************************************************************/
15 
16 #include <rtl_vista.h>
17 
18 #define NDEBUG
19 #include <debug.h>
20 
21 /* FUNCTIONS *****************************************************************/
22 
23 #ifdef _WIN64
24 #define InterlockedBitTestAndSetPointer(ptr,val) InterlockedBitTestAndSet64((PLONGLONG)ptr,(LONGLONG)val)
25 #define InterlockedAddPointer(ptr,val) InterlockedAdd64((PLONGLONG)ptr,(LONGLONG)val)
26 #define InterlockedAndPointer(ptr,val) InterlockedAnd64((PLONGLONG)ptr,(LONGLONG)val)
27 #define InterlockedOrPointer(ptr,val) InterlockedOr64((PLONGLONG)ptr,(LONGLONG)val)
28 #define _ONE 1LL
29 #else
30 #define InterlockedBitTestAndSetPointer(ptr,val) InterlockedBitTestAndSet((PLONG)ptr,(LONG)val)
31 #define InterlockedAddPointer(ptr,val) InterlockedAdd((PLONG)ptr,(LONG)val)
32 #define InterlockedAndPointer(ptr,val) InterlockedAnd((PLONG)ptr,(LONG)val)
33 #define InterlockedOrPointer(ptr,val) InterlockedOr((PLONG)ptr,(LONG)val)
34 #define _ONE 1L
35 #endif
36 
37 #define RTL_SRWLOCK_OWNED_BIT 0
38 #define RTL_SRWLOCK_CONTENDED_BIT 1
39 #define RTL_SRWLOCK_SHARED_BIT 2
40 #define RTL_SRWLOCK_CONTENTION_LOCK_BIT 3
41 #define RTL_SRWLOCK_OWNED (_ONE << RTL_SRWLOCK_OWNED_BIT)
42 #define RTL_SRWLOCK_CONTENDED (_ONE << RTL_SRWLOCK_CONTENDED_BIT)
43 #define RTL_SRWLOCK_SHARED (_ONE << RTL_SRWLOCK_SHARED_BIT)
44 #define RTL_SRWLOCK_CONTENTION_LOCK (_ONE << RTL_SRWLOCK_CONTENTION_LOCK_BIT)
45 #define RTL_SRWLOCK_MASK (RTL_SRWLOCK_OWNED | RTL_SRWLOCK_CONTENDED | \
46  RTL_SRWLOCK_SHARED | RTL_SRWLOCK_CONTENTION_LOCK)
47 #define RTL_SRWLOCK_BITS 4
48 
50 {
52  volatile struct _RTLP_SRWLOCK_SHARED_WAKE *Next;
54 
56 {
57  /* SharedCount is the number of shared acquirers. */
59 
60  /* Last points to the last wait block in the chain. The value
61  is only valid when read from the first wait block. */
62  volatile struct _RTLP_SRWLOCK_WAITBLOCK *Last;
63 
64  /* Next points to the next wait block in the chain. */
65  volatile struct _RTLP_SRWLOCK_WAITBLOCK *Next;
66 
67  union
68  {
69  /* Wake is only valid for exclusive wait blocks */
71  /* The wake chain is only valid for shared wait blocks */
72  struct
73  {
76  };
77  };
78 
81 
82 
83 static VOID
84 NTAPI
86  IN PRTLP_SRWLOCK_WAITBLOCK FirstWaitBlock)
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 }
151 
152 
153 static VOID
154 NTAPI
156  IN PRTLP_SRWLOCK_WAITBLOCK FirstWaitBlock)
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. */
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 }
186 
187 
188 static VOID
189 NTAPI
191 {
192  InterlockedAndPointer(&SRWLock->Ptr,
194 }
195 
196 
198 NTAPI
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 }
228 
229 
230 static VOID
231 NTAPI
233  IN PRTLP_SRWLOCK_WAITBLOCK WaitBlock)
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 }
263 
264 
265 static VOID
266 NTAPI
269  IN OUT PRTLP_SRWLOCK_SHARED_WAKE WakeChain)
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 }
313 
314 
315 VOID
316 NTAPI
318 {
319  SRWLock->Ptr = NULL;
320 }
321 
322 
323 VOID
324 NTAPI
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 }
522 
523 
524 VOID
525 NTAPI
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 }
587 
588 
589 VOID
590 NTAPI
592 {
593  __ALIGNED(16) RTLP_SRWLOCK_WAITBLOCK StackWaitBlock;
595 
596  if (InterlockedBitTestAndSetPointer(&SRWLock->Ptr,
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 }
706 
707 
708 VOID
709 NTAPI
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 }
768 
769 BOOLEAN
770 NTAPI
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 }
789 
790 BOOLEAN
791 NTAPI
793 {
795 }
BOOLEAN NTAPI RtlTryAcquireSRWLockShared(PRTL_SRWLOCK SRWLock)
Definition: srw.c:771
BOOLEAN NTAPI RtlTryAcquireSRWLockExclusive(PRTL_SRWLOCK SRWLock)
Definition: srw.c:792
#define IN
Definition: typedefs.h:39
#define LONG_PTR
Definition: treelist.c:79
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
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 InterlockedBitTestAndSetPointer(ptr, val)
Definition: srw.c:30
#define TRUE
Definition: types.h:120
#define RTL_SRWLOCK_CONTENTION_LOCK
Definition: srw.c:44
PRTLP_SRWLOCK_SHARED_WAKE LastSharedWake
Definition: srw.c:75
typedef __ALIGNED(16) struct _EX_PUSH_LOCK_WAIT_BLOCK
Definition: extypes.h:483
struct _RTLP_SRWLOCK_SHARED_WAKE * PRTLP_SRWLOCK_SHARED_WAKE
struct _RTLP_SRWLOCK_SHARED_WAKE RTLP_SRWLOCK_SHARED_WAKE
if(dx==0 &&dy==0)
Definition: linetemp.h:174
struct _RTLP_SRWLOCK_WAITBLOCK * PRTLP_SRWLOCK_WAITBLOCK
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
uint32_t ULONG_PTR
Definition: typedefs.h:65
FORCEINLINE VOID YieldProcessor(VOID)
Definition: ke.h:32
WCHAR First[]
Definition: FormatMessage.c:11
VOID NTAPI RtlReleaseSRWLockShared(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:526
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
VOID NTAPI RtlAcquireSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:591
#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
unsigned char BOOLEAN
#define RTL_SRWLOCK_BITS
Definition: srw.c:47
VOID NTAPI RtlInitializeSRWLock(OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:317
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define RTL_SRWLOCK_MASK
Definition: srw.c:45
#define ASSERT(a)
Definition: mode.c:44
#define InterlockedOrPointer(ptr, val)
Definition: srw.c:33
#define InterlockedAndPointer(ptr, val)
Definition: srw.c:32
#define RTL_SRWLOCK_OWNED
Definition: srw.c:41
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
PRTLP_SRWLOCK_SHARED_WAKE SharedWakeChain
Definition: srw.c:74
VOID NTAPI RtlReleaseSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:710
#define InterlockedOr
Definition: interlocked.h:224
#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
BOOLEAN Exclusive
Definition: srw.c:79
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
VOID NTAPI RtlAcquireSRWLockShared(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:325
struct _RTLP_SRWLOCK_WAITBLOCK RTLP_SRWLOCK_WAITBLOCK
#define RTL_SRWLOCK_OWNED_BIT
Definition: srw.c:37
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define NULL
Definition: types.h:112
#define OUT
Definition: typedefs.h:40
#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
signed int * PLONG
Definition: retypes.h:5
static VOID NTAPI RtlpReleaseWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:190
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68