ReactOS 0.4.16-dev-336-gb667d82
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:
#define RTL_SRWLOCK_CONTENDED
Definition: srw.c:42
#define RTL_SRWLOCK_CONTENTION_LOCK
Definition: srw.c:44
#define RTL_SRWLOCK_SHARED
Definition: srw.c:43
#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
624
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 {
645AddWaitBlock:
646 StackWaitBlock.Exclusive = TRUE;
647 StackWaitBlock.SharedCount = 0;
648 StackWaitBlock.Next = NULL;
649 StackWaitBlock.Last = &StackWaitBlock;
650 StackWaitBlock.Wake = 0;
651
653 if (First != NULL)
654 {
655 Last = First->Last;
656 Last->Next = &StackWaitBlock;
657 First->Last = &StackWaitBlock;
658
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;
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
703 }
704 }
705}
WCHAR First[]
Definition: FormatMessage.c:11
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define ULONG_PTR
Definition: config.h:101
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
if(dx< 0)
Definition: linetemp.h:194
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
typedef __ALIGNED(16) struct _EX_PUSH_LOCK_WAIT_BLOCK
Definition: extypes.h:483
long LONG
Definition: pedump.c:60
#define YieldProcessor
Definition: ke.h:48
static VOID NTAPI RtlpReleaseWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:190
#define RTL_SRWLOCK_BITS
Definition: srw.c:47
static VOID NTAPI RtlpAcquireSRWLockExclusiveWait(IN OUT PRTL_SRWLOCK SRWLock, IN PRTLP_SRWLOCK_WAITBLOCK WaitBlock)
Definition: srw.c:232
#define InterlockedBitTestAndSetPointer(ptr, val)
Definition: srw.c:30
#define RTL_SRWLOCK_OWNED_BIT
Definition: srw.c:37
static PRTLP_SRWLOCK_WAITBLOCK NTAPI RtlpAcquireWaitBlockLock(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:199
volatile struct _RTLP_SRWLOCK_WAITBLOCK * Last
Definition: srw.c:62
BOOLEAN Exclusive
Definition: srw.c:79
volatile struct _RTLP_SRWLOCK_WAITBLOCK * Next
Definition: srw.c:65

Referenced by 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 */
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
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
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
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
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;
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
510 (PVOID)NewValue,
511 (PVOID)CurrentValue) == CurrentValue)
512 {
513 /* Successfully set the shared count, we acquired the lock */
514 break;
515 }
516 }
517 }
518
520 }
521}
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
#define FALSE
Definition: types.h:117
#define ASSERT(a)
Definition: mode.c:44
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
#define RTL_SRWLOCK_MASK
Definition: srw.c:45
volatile struct _RTLP_SRWLOCK_SHARED_WAKE * Next
Definition: srw.c:52
PRTLP_SRWLOCK_SHARED_WAKE SharedWakeChain
Definition: srw.c:74
PRTLP_SRWLOCK_SHARED_WAKE LastSharedWake
Definition: srw.c:75

Referenced by InternalSleep().

◆ RtlInitializeSRWLock()

VOID NTAPI RtlInitializeSRWLock ( OUT PRTL_SRWLOCK  SRWLock)

Definition at line 317 of file srw.c.

318{
319 SRWLock->Ptr = NULL;
320}

◆ 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
261 }
262}

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 {
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
310 }
311 }
312}

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
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 */
221 return NULL;
222 }
223
224 WaitBlock = (PRTLP_SRWLOCK_WAITBLOCK)(PrevValue & ~RTL_SRWLOCK_MASK);
225
226 return WaitBlock;
227}
#define InterlockedOrPointer(ptr, val)
Definition: srw.c:33
struct _RTLP_SRWLOCK_WAITBLOCK * PRTLP_SRWLOCK_WAITBLOCK

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 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 InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define InterlockedOr
Definition: interlocked.h:224
#define LONG_PTR
Definition: treelist.c:79
int32_t * PLONG
Definition: typedefs.h:58

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. */
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}

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;
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
766 }
767}
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
#define STATUS_RESOURCE_NOT_OWNED
Definition: ntstatus.h:737
static VOID NTAPI RtlpReleaseWaitBlockLockExclusive(IN OUT PRTL_SRWLOCK SRWLock, IN PRTLP_SRWLOCK_WAITBLOCK FirstWaitBlock)
Definition: srw.c:85

Referenced by InternalSleep().

◆ 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
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
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
585 }
586}
unsigned char BOOLEAN
static VOID NTAPI RtlpReleaseWaitBlockLockLastShared(IN OUT PRTL_SRWLOCK SRWLock, IN PRTLP_SRWLOCK_WAITBLOCK FirstWaitBlock)
Definition: srw.c:155

Referenced by InternalSleep().

◆ RtlTryAcquireSRWLockExclusive()

BOOLEAN NTAPI RtlTryAcquireSRWLockExclusive ( PRTL_SRWLOCK  SRWLock)

Definition at line 792 of file srw.c.

793{
795}
PVOID Ptr
Definition: rtltypes.h:292
uint32_t ULONG_PTR
Definition: typedefs.h:65

◆ 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 */
782 CompareValue &= ~RTL_SRWLOCK_MASK | RTL_SRWLOCK_SHARED | RTL_SRWLOCK_OWNED;
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}