ReactOS  0.4.14-dev-98-gb0d4763
condvar.c File Reference
#include <rtl_vista.h>
#include <debug.h>
Include dependency graph for condvar.c:

Go to the source code of this file.

Classes

struct  _COND_VAR_WAIT_ENTRY
 

Macros

#define NDEBUG
 
#define COND_VAR_UNUSED_FLAG   ((ULONG_PTR)1)
 
#define COND_VAR_LOCKED_FLAG   ((ULONG_PTR)2)
 
#define COND_VAR_FLAGS_MASK   ((ULONG_PTR)3)
 
#define COND_VAR_ADDRESS_MASK   (~COND_VAR_FLAGS_MASK)
 
#define CONTAINING_COND_VAR_WAIT_ENTRY(address, field)   CONTAINING_RECORD(address, COND_VAR_WAIT_ENTRY, field)
 

Typedefs

typedef struct _COND_VAR_WAIT_ENTRY COND_VAR_WAIT_ENTRY
 
typedef struct _COND_VAR_WAIT_ENTRYPCOND_VAR_WAIT_ENTRY
 

Functions

FORCEINLINE ULONG_PTR InternalCmpXChgCondVarAcq (IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN ULONG_PTR Exchange, IN ULONG_PTR Comperand)
 
FORCEINLINE ULONG_PTR InternalCmpXChgCondVarRel (IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN ULONG_PTR Exchange, IN ULONG_PTR Comperand)
 
FORCEINLINE BOOLEANInternalGetListRemovalHandledFlag (IN PCOND_VAR_WAIT_ENTRY Entry)
 
static PCOND_VAR_WAIT_ENTRY InternalLockCondVar (IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN PCOND_VAR_WAIT_ENTRY InsertEntry OPTIONAL, IN BOOLEAN *AbortIfLocked OPTIONAL)
 
static VOID InternalUnlockCondVar (IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN PCOND_VAR_WAIT_ENTRY RemoveEntry OPTIONAL)
 
static VOID InternalWake (IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN BOOLEAN ReleaseAll)
 
VOID NTAPI RtlAcquireSRWLockExclusive (IN OUT PRTL_SRWLOCK SRWLock)
 
VOID NTAPI RtlAcquireSRWLockShared (IN OUT PRTL_SRWLOCK SRWLock)
 
VOID NTAPI RtlReleaseSRWLockExclusive (IN OUT PRTL_SRWLOCK SRWLock)
 
VOID NTAPI RtlReleaseSRWLockShared (IN OUT PRTL_SRWLOCK SRWLock)
 
static NTSTATUS InternalSleep (IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN OUT PRTL_CRITICAL_SECTION CriticalSection OPTIONAL, IN OUT PRTL_SRWLOCK SRWLock OPTIONAL, IN ULONG SRWFlags, IN const LARGE_INTEGER *TimeOut OPTIONAL)
 
VOID RtlpInitializeKeyedEvent (VOID)
 
VOID RtlpCloseKeyedEvent (VOID)
 
VOID NTAPI RtlInitializeConditionVariable (OUT PRTL_CONDITION_VARIABLE ConditionVariable)
 
VOID NTAPI RtlWakeConditionVariable (IN OUT PRTL_CONDITION_VARIABLE ConditionVariable)
 
VOID NTAPI RtlWakeAllConditionVariable (IN OUT PRTL_CONDITION_VARIABLE ConditionVariable)
 
NTSTATUS NTAPI RtlSleepConditionVariableCS (IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN OUT PRTL_CRITICAL_SECTION CriticalSection, IN const LARGE_INTEGER *TimeOut OPTIONAL)
 
NTSTATUS NTAPI RtlSleepConditionVariableSRW (IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN OUT PRTL_SRWLOCK SRWLock, IN const LARGE_INTEGER *TimeOut OPTIONAL, IN ULONG Flags)
 

Variables

static HANDLE CondVarKeyedEventHandle = NULL
 

Macro Definition Documentation

◆ COND_VAR_ADDRESS_MASK

#define COND_VAR_ADDRESS_MASK   (~COND_VAR_FLAGS_MASK)

Definition at line 26 of file condvar.c.

◆ COND_VAR_FLAGS_MASK

#define COND_VAR_FLAGS_MASK   ((ULONG_PTR)3)

Definition at line 25 of file condvar.c.

◆ COND_VAR_LOCKED_FLAG

#define COND_VAR_LOCKED_FLAG   ((ULONG_PTR)2)

Definition at line 24 of file condvar.c.

◆ COND_VAR_UNUSED_FLAG

#define COND_VAR_UNUSED_FLAG   ((ULONG_PTR)1)

Definition at line 23 of file condvar.c.

◆ CONTAINING_COND_VAR_WAIT_ENTRY

#define CONTAINING_COND_VAR_WAIT_ENTRY (   address,
  field 
)    CONTAINING_RECORD(address, COND_VAR_WAIT_ENTRY, field)

Definition at line 37 of file condvar.c.

◆ NDEBUG

#define NDEBUG

Definition at line 18 of file condvar.c.

Typedef Documentation

◆ COND_VAR_WAIT_ENTRY

◆ PCOND_VAR_WAIT_ENTRY

Function Documentation

◆ InternalCmpXChgCondVarAcq()

FORCEINLINE ULONG_PTR InternalCmpXChgCondVarAcq ( IN OUT PRTL_CONDITION_VARIABLE  ConditionVariable,
IN ULONG_PTR  Exchange,
IN ULONG_PTR  Comperand 
)

Definition at line 48 of file condvar.c.

51 {
52  return (ULONG_PTR)InterlockedCompareExchangePointerAcquire(&ConditionVariable->Ptr,
53  (PVOID)Exchange,
54  (PVOID)Comperand);
55 }
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define InterlockedCompareExchangePointerAcquire
Definition: interlocked.h:130

Referenced by InternalLockCondVar().

◆ InternalCmpXChgCondVarRel()

FORCEINLINE ULONG_PTR InternalCmpXChgCondVarRel ( IN OUT PRTL_CONDITION_VARIABLE  ConditionVariable,
IN ULONG_PTR  Exchange,
IN ULONG_PTR  Comperand 
)

Definition at line 59 of file condvar.c.

62 {
63  return (ULONG_PTR)InterlockedCompareExchangePointerRelease(&ConditionVariable->Ptr,
64  (PVOID)Exchange,
65  (PVOID)Comperand);
66 }
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define InterlockedCompareExchangePointerRelease
Definition: interlocked.h:131

Referenced by InternalUnlockCondVar().

◆ InternalGetListRemovalHandledFlag()

FORCEINLINE BOOLEAN* InternalGetListRemovalHandledFlag ( IN PCOND_VAR_WAIT_ENTRY  Entry)

Definition at line 70 of file condvar.c.

71 {
72  return (BOOLEAN *)&Entry->ListRemovalHandled;
73 }
unsigned char BOOLEAN
base of all file and directory entries
Definition: entries.h:82

Referenced by InternalSleep(), and InternalWake().

◆ InternalLockCondVar()

static PCOND_VAR_WAIT_ENTRY InternalLockCondVar ( IN OUT PRTL_CONDITION_VARIABLE  ConditionVariable,
IN PCOND_VAR_WAIT_ENTRY InsertEntry  OPTIONAL,
IN BOOLEAN *AbortIfLocked  OPTIONAL 
)
static

Definition at line 77 of file condvar.c.

80 {
81  /* InsertEntry and AbortIfLocked may be NULL on entry. This routine
82  will return NULL if the lock was not acquired. Otherwise it has
83  successfully acquired the lock and the return value is a valid
84  reference to the list head associated with ConditionVariable.
85  The caller must in this case call InternalUnlockCondVar later
86  in order to unlock the condition variable.
87 
88  If InsertEntry is NULL and there are no entries on the list, this
89  routine will not acquire the lock and return NULL. If InsertEntry
90  is not NULL this routine ensures that InsertEntry will be on the
91  list when it returns successfully.
92 
93  If the lock is owned by another thread and AbortIfLocked is NULL,
94  this routine will block until it acquires the lock. If AbortIfLocked
95  is not NULL and the lock is owned by another thread, this routine
96  will periodically check if *AbortIfLocked is nonzero and if so, will
97  return NULL instead of continuing the wait. */
98 
99  ULONG_PTR OldVal = (ULONG_PTR)ConditionVariable->Ptr;
100 
101  for (;;)
102  {
103  ULONG_PTR NewVal, LockRes;
104  PLIST_ENTRY OldListHead;
105 
106  if (OldVal & COND_VAR_LOCKED_FLAG)
107  {
108  /* The locked flag is set, indicating someone else currently
109  holds the lock. We'll spin until this flag becomes
110  clear or we're asked to abort. */
111  YieldProcessor();
112 
113  if ((AbortIfLocked != NULL) && *AbortIfLocked)
114  {
115  /* The caller wants us to abort in this case. */
116  return NULL;
117  }
118 
119  /* Refresh OldVal and try again. */
120  OldVal = *(ULONG_PTR *)&ConditionVariable->Ptr;
121  continue;
122  }
123 
124  /* Retrieve the list head currently associated with the
125  condition variable. */
126  OldListHead = (PLIST_ENTRY)(OldVal & COND_VAR_ADDRESS_MASK);
127  if (InsertEntry == NULL)
128  {
129  /* The caller doesn't want to put any entry on the list. */
130  if (OldListHead == NULL)
131  {
132  /* The list is empty, so there is nothing to lock. */
133  return NULL;
134  }
135 
136  /* The list isn't empty. In this case we need to preserve
137  all of OldVal. */
138  NewVal = OldVal;
139  }
140  else
141  {
142  /* Let InsertEntry be the new list head. Preserve only the
143  bits inside the COND_VAR_FLAGS_MASK range. */
144  NewVal = ((OldVal & COND_VAR_FLAGS_MASK) |
145  (ULONG_PTR)&InsertEntry->ListEntry);
146  }
147 
148  /* Set the flag that indicates someone is holding the lock and
149  try to update the condition variable thread-safe. */
150  NewVal |= COND_VAR_LOCKED_FLAG;
151  LockRes = InternalCmpXChgCondVarAcq(ConditionVariable, NewVal, OldVal);
152  if (LockRes == OldVal)
153  {
154  /* We successfully updated ConditionVariable the way we
155  wanted and now hold the lock. */
156  if (InsertEntry == NULL)
157  {
158  /* We know that OldVal contains a valid address in
159  this case. */
160  ASSERT(OldListHead != NULL);
161  return CONTAINING_COND_VAR_WAIT_ENTRY(OldListHead, ListEntry);
162  }
163 
164  /* InsertEntry is not on the list yet, so add it. In any
165  case InsertEntry will be the new list head. */
166  if (OldListHead == NULL)
167  {
168  /* List was empty before. */
169  InitializeListHead(&InsertEntry->ListEntry);
170  }
171  else
172  {
173  /* Make InsertEntry the last entry of the old list.
174  As InsertEntry will take the role as new list head,
175  OldListHead will become the second entry (InsertEntry->Flink)
176  on the new list. */
177  InsertTailList(OldListHead, &InsertEntry->ListEntry);
178  }
179 
180  return InsertEntry;
181  }
182 
183  /* We didn't manage to update ConditionVariable, so try again. */
184  OldVal = LockRes;
185  }
186 }
struct _LIST_ENTRY * PLIST_ENTRY
#define CONTAINING_COND_VAR_WAIT_ENTRY(address, field)
Definition: condvar.c:37
#define InsertTailList(ListHead, Entry)
uint32_t ULONG_PTR
Definition: typedefs.h:63
FORCEINLINE VOID YieldProcessor(VOID)
Definition: ke.h:32
smooth NULL
Definition: ftsmooth.c:416
#define COND_VAR_LOCKED_FLAG
Definition: condvar.c:24
#define COND_VAR_FLAGS_MASK
Definition: condvar.c:25
#define for
Definition: utility.h:88
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
FORCEINLINE ULONG_PTR InternalCmpXChgCondVarAcq(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN ULONG_PTR Exchange, IN ULONG_PTR Comperand)
Definition: condvar.c:48
Definition: typedefs.h:117
#define COND_VAR_ADDRESS_MASK
Definition: condvar.c:26
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define ULONG_PTR
Definition: config.h:101

Referenced by InternalSleep(), and InternalWake().

◆ InternalSleep()

static NTSTATUS InternalSleep ( IN OUT PRTL_CONDITION_VARIABLE  ConditionVariable,
IN OUT PRTL_CRITICAL_SECTION CriticalSection  OPTIONAL,
IN OUT PRTL_SRWLOCK SRWLock  OPTIONAL,
IN ULONG  SRWFlags,
IN const LARGE_INTEGER *TimeOut  OPTIONAL 
)
static

Definition at line 367 of file condvar.c.

372 {
373  /* Either CriticalSection or SRWLock must be NULL, but not both.
374  These caller provided lock must be held on entry and will be
375  held again on return. */
376 
377  COND_VAR_WAIT_ENTRY OwnEntry;
379 
381  ASSERT((CriticalSection == NULL) != (SRWLock == NULL));
382 
383  RtlZeroMemory(&OwnEntry, sizeof(OwnEntry));
384 
385  /* Put OwnEntry on the list. */
386  InternalLockCondVar(ConditionVariable, &OwnEntry, NULL);
387  InternalUnlockCondVar(ConditionVariable, NULL);
388 
389  /* We can now drop the caller provided lock as a preparation for
390  going to sleep. */
391  if (CriticalSection == NULL)
392  {
393  if (0 == (RTL_CONDITION_VARIABLE_LOCKMODE_SHARED & SRWFlags))
394  {
396  }
397  else
398  {
399  RtlReleaseSRWLockShared(SRWLock);
400  }
401  }
402  else
403  {
405  }
406 
407  /* Now sleep using the caller provided timeout. */
409  &OwnEntry.WaitKey,
410  FALSE,
411  (PLARGE_INTEGER)TimeOut);
412 
414 
415  if (!*InternalGetListRemovalHandledFlag(&OwnEntry))
416  {
417  /* Remove OwnEntry from the list again, since it still seems to
418  be on the list. We will know for sure once we've acquired
419  the lock. */
420  if (InternalLockCondVar(ConditionVariable,
421  NULL,
423  {
424  /* Unlock and potentially remove OwnEntry. Self-removal is
425  usually only necessary when a timeout occurred. */
426  InternalUnlockCondVar(ConditionVariable,
427  !OwnEntry.ListRemovalHandled ?
428  &OwnEntry : NULL);
429  }
430  }
431 
432 #ifdef _DEBUG
433  /* Clear OwnEntry to aid in detecting bugs. */
434  RtlZeroMemory(&OwnEntry, sizeof(OwnEntry));
435 #endif
436 
437  /* Reacquire the caller provided lock, as we are about to return. */
438  if (CriticalSection == NULL)
439  {
440  if (0 == (RTL_CONDITION_VARIABLE_LOCKMODE_SHARED & SRWFlags))
441  {
443  }
444  else
445  {
446  RtlAcquireSRWLockShared(SRWLock);
447  }
448  }
449  else
450  {
452  }
453 
454  /* Return whatever NtWaitForKeyedEvent returned. */
455  return Status;
456 }
PVOID WaitKey
Definition: condvar.c:33
NTSYSAPI NTSTATUS WINAPI NtWaitForKeyedEvent(HANDLE, const void *, BOOLEAN, const LARGE_INTEGER *)
LONG NTSTATUS
Definition: precomp.h:26
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:231
VOID NTAPI RtlAcquireSRWLockShared(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:323
BOOLEAN ListRemovalHandled
Definition: condvar.c:34
VOID NTAPI RtlReleaseSRWLockShared(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:524
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
CRITICAL_SECTION CriticalSection
Definition: iprtprio.c:40
smooth NULL
Definition: ftsmooth.c:416
VOID NTAPI RtlAcquireSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:589
static VOID InternalUnlockCondVar(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN PCOND_VAR_WAIT_ENTRY RemoveEntry OPTIONAL)
Definition: condvar.c:190
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define RTL_CONDITION_VARIABLE_LOCKMODE_SHARED
Definition: winnt_old.h:2550
Definition: condvar.c:28
Status
Definition: gdiplustypes.h:24
static HANDLE CondVarKeyedEventHandle
Definition: condvar.c:42
static PCOND_VAR_WAIT_ENTRY InternalLockCondVar(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN PCOND_VAR_WAIT_ENTRY InsertEntry OPTIONAL, IN BOOLEAN *AbortIfLocked OPTIONAL)
Definition: condvar.c:77
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
FORCEINLINE BOOLEAN * InternalGetListRemovalHandledFlag(IN PCOND_VAR_WAIT_ENTRY Entry)
Definition: condvar.c:70
VOID NTAPI RtlReleaseSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:708

Referenced by RtlSleepConditionVariableCS(), and RtlSleepConditionVariableSRW().

◆ InternalUnlockCondVar()

static VOID InternalUnlockCondVar ( IN OUT PRTL_CONDITION_VARIABLE  ConditionVariable,
IN PCOND_VAR_WAIT_ENTRY RemoveEntry  OPTIONAL 
)
static

Definition at line 190 of file condvar.c.

192 {
193  /* This routine assumes that the lock is being held on entry.
194  RemoveEntry may be NULL. If it is not NULL, this routine
195  assumes that RemoveEntry is on the list and will remove it
196  before releasing the lock. */
197  ULONG_PTR OldVal = (ULONG_PTR)ConditionVariable->Ptr;
198  PLIST_ENTRY NewHeadEntry;
199 
200  ASSERT((OldVal & COND_VAR_LOCKED_FLAG) &&
201  (OldVal & COND_VAR_ADDRESS_MASK));
202 
203  NewHeadEntry = (PLIST_ENTRY)(OldVal & COND_VAR_ADDRESS_MASK);
204  if (RemoveEntry != NULL)
205  {
206  /* We have to drop RemoveEntry from the list. */
207  if (&RemoveEntry->ListEntry == NewHeadEntry)
208  {
209  /* RemoveEntry is the list head. */
210  if (!IsListEmpty(NewHeadEntry))
211  {
212  /* The second entry in the list will become the new
213  list head. It's from the thread that arrived
214  right before the owner of RemoveEntry. */
215  NewHeadEntry = NewHeadEntry->Flink;
216  RemoveEntryList(&RemoveEntry->ListEntry);
217  }
218  else
219  {
220  /* The list will be empty, so discard the list. */
221  NewHeadEntry = NULL;
222  }
223  }
224  else
225  {
226  /* RemoveEntry is not the list head. The current list head
227  will remain. */
228  RemoveEntryList(&RemoveEntry->ListEntry);
229  }
230 
231  /* Indicate to the owner of RemoveEntry that the entry
232  was removed from the list. RemoveEntry may not be touched
233  from here on. We don't use volatile semantics here since
234  the cache will anyway be flushed soon when we update
235  ConditionVariable. */
236  RemoveEntry->ListRemovalHandled = TRUE;
237  }
238 
239  /* Now unlock thread-safe, while preserving any flags within the
240  COND_VAR_FLAGS_MASK range except for COND_VAR_LOCKED_FLAG. */
241  for (;;)
242  {
243  ULONG_PTR NewVal = ((OldVal & (COND_VAR_FLAGS_MASK ^ COND_VAR_LOCKED_FLAG)) |
244  (ULONG_PTR)NewHeadEntry);
245  ULONG_PTR LockRes = InternalCmpXChgCondVarRel(ConditionVariable, NewVal, OldVal);
246  if (LockRes == OldVal)
247  {
248  /* We unlocked. */
249  break;
250  }
251 
252  /* Try again. */
253  OldVal = LockRes;
254  }
255 }
struct _LIST_ENTRY * PLIST_ENTRY
#define TRUE
Definition: types.h:120
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint32_t ULONG_PTR
Definition: typedefs.h:63
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
smooth NULL
Definition: ftsmooth.c:416
#define COND_VAR_LOCKED_FLAG
Definition: condvar.c:24
#define COND_VAR_FLAGS_MASK
Definition: condvar.c:25
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
Definition: typedefs.h:117
FORCEINLINE ULONG_PTR InternalCmpXChgCondVarRel(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN ULONG_PTR Exchange, IN ULONG_PTR Comperand)
Definition: condvar.c:59
#define COND_VAR_ADDRESS_MASK
Definition: condvar.c:26
#define ULONG_PTR
Definition: config.h:101

Referenced by InternalSleep(), and InternalWake().

◆ InternalWake()

static VOID InternalWake ( IN OUT PRTL_CONDITION_VARIABLE  ConditionVariable,
IN BOOLEAN  ReleaseAll 
)
static

Definition at line 259 of file condvar.c.

261 {
262  /* If ReleaseAll is zero on entry, one thread at most will be woken.
263  Otherwise all waiting threads are woken. Wakeups happen in FIFO
264  order. */
265  PCOND_VAR_WAIT_ENTRY CONST HeadEntry = InternalLockCondVar(ConditionVariable, NULL, NULL);
267  PCOND_VAR_WAIT_ENTRY NextEntry;
269  PCOND_VAR_WAIT_ENTRY RemoveOnUnlockEntry;
270 
272 
273  if (HeadEntry == NULL)
274  {
275  /* There is noone there to wake up. In this case do nothing
276  and return immediately. We don't stockpile releases. */
277  return;
278  }
279 
280  Timeout.QuadPart = 0;
281  RemoveOnUnlockEntry = NULL;
282 
283  /* Release sleeping threads. We will iterate from the last entry on
284  the list to the first. Note that the loop condition is always
285  true for the initial test. */
286  for (Entry = CONTAINING_COND_VAR_WAIT_ENTRY(HeadEntry->ListEntry.Blink, ListEntry);
287  Entry != NULL;
288  Entry = NextEntry)
289  {
291 
292  if (HeadEntry == Entry)
293  {
294  /* After the current entry we've iterated through the
295  entire list in backward direction. Then exit.*/
296  NextEntry = NULL;
297  }
298  else
299  {
300  /* Store away the next reference right now, since we may
301  not touch Entry anymore at the end of the block. */
302  NextEntry = CONTAINING_COND_VAR_WAIT_ENTRY(Entry->ListEntry.Blink, ListEntry);
303  }
304 
305  /* Wake the thread associated with this event. We will
306  immediately return if we failed (zero timeout). */
308  &Entry->WaitKey,
309  FALSE,
310  &Timeout);
311 
312  if (!NT_SUCCESS(Status))
313  {
314  /* We failed to wake a thread. We'll keep trying. */
316  continue;
317  }
318 
319  /* We've woken a thread and will make sure this thread
320  is removed from the list. */
321  if (HeadEntry == Entry)
322  {
323  /* This is the list head. We can't remove it as easily as
324  other entries and will pass it to the unlock routine
325  later (we will exit the loop after this round anyway). */
326  RemoveOnUnlockEntry = HeadEntry;
327  }
328  else
329  {
330  /* We can remove the entry right away. */
331  RemoveEntryList(&Entry->ListEntry);
332 
333  /* Now tell the woken thread that removal from the list was
334  already taken care of here so that this thread can resume
335  its normal operation more quickly. We may not touch
336  Entry after signaling this, since it may lie in invalid
337  memory from there on. */
339  }
340 
341  if (!ReleaseAll)
342  {
343  /* We've successfully woken one thread as the caller
344  demanded. */
345  break;
346  }
347  }
348 
349  InternalUnlockCondVar(ConditionVariable, RemoveOnUnlockEntry);
350 }
#define CONTAINING_COND_VAR_WAIT_ENTRY(address, field)
Definition: condvar.c:37
#define TRUE
Definition: types.h:120
struct _Entry Entry
Definition: kefuncs.h:640
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:231
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
smooth NULL
Definition: ftsmooth.c:416
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static VOID InternalUnlockCondVar(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN PCOND_VAR_WAIT_ENTRY RemoveEntry OPTIONAL)
Definition: condvar.c:190
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
Definition: condvar.c:28
Status
Definition: gdiplustypes.h:24
static ULONG Timeout
Definition: ping.c:61
static HANDLE CondVarKeyedEventHandle
Definition: condvar.c:42
NTSYSAPI NTSTATUS WINAPI NtReleaseKeyedEvent(HANDLE, const void *, BOOLEAN, const LARGE_INTEGER *)
static PCOND_VAR_WAIT_ENTRY InternalLockCondVar(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN PCOND_VAR_WAIT_ENTRY InsertEntry OPTIONAL, IN BOOLEAN *AbortIfLocked OPTIONAL)
Definition: condvar.c:77
FORCEINLINE BOOLEAN * InternalGetListRemovalHandledFlag(IN PCOND_VAR_WAIT_ENTRY Entry)
Definition: condvar.c:70
#define CONST
Definition: pedump.c:81
base of all file and directory entries
Definition: entries.h:82

Referenced by RtlWakeAllConditionVariable(), and RtlWakeConditionVariable().

◆ 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 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 InternalSleep().

◆ RtlInitializeConditionVariable()

VOID NTAPI RtlInitializeConditionVariable ( OUT PRTL_CONDITION_VARIABLE  ConditionVariable)

Definition at line 477 of file condvar.c.

478 {
479  ConditionVariable->Ptr = NULL;
480 }
smooth NULL
Definition: ftsmooth.c:416

Referenced by InitializeConditionVariable().

◆ RtlpCloseKeyedEvent()

VOID RtlpCloseKeyedEvent ( VOID  )

Definition at line 466 of file condvar.c.

467 {
471 }
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static HANDLE CondVarKeyedEventHandle
Definition: condvar.c:42

Referenced by DllMain().

◆ RtlpInitializeKeyedEvent()

VOID RtlpInitializeKeyedEvent ( VOID  )

Definition at line 459 of file condvar.c.

460 {
463 }
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
smooth NULL
Definition: ftsmooth.c:416
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static HANDLE CondVarKeyedEventHandle
Definition: condvar.c:42
NTSYSAPI NTSTATUS WINAPI NtCreateKeyedEvent(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG)

Referenced by DllMain().

◆ 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().

◆ 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().

◆ RtlSleepConditionVariableCS()

NTSTATUS NTAPI RtlSleepConditionVariableCS ( IN OUT PRTL_CONDITION_VARIABLE  ConditionVariable,
IN OUT PRTL_CRITICAL_SECTION  CriticalSection,
IN const LARGE_INTEGER *TimeOut  OPTIONAL 
)

Definition at line 498 of file condvar.c.

501 {
502  return InternalSleep(ConditionVariable,
505  0,
506  TimeOut);
507 }
static NTSTATUS InternalSleep(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN OUT PRTL_CRITICAL_SECTION CriticalSection OPTIONAL, IN OUT PRTL_SRWLOCK SRWLock OPTIONAL, IN ULONG SRWFlags, IN const LARGE_INTEGER *TimeOut OPTIONAL)
Definition: condvar.c:367
CRITICAL_SECTION CriticalSection
Definition: iprtprio.c:40
smooth NULL
Definition: ftsmooth.c:416

◆ RtlSleepConditionVariableSRW()

NTSTATUS NTAPI RtlSleepConditionVariableSRW ( IN OUT PRTL_CONDITION_VARIABLE  ConditionVariable,
IN OUT PRTL_SRWLOCK  SRWLock,
IN const LARGE_INTEGER *TimeOut  OPTIONAL,
IN ULONG  Flags 
)

Definition at line 511 of file condvar.c.

515 {
516  return InternalSleep(ConditionVariable,
518  SRWLock,
519  Flags,
520  TimeOut);
521 }
static NTSTATUS InternalSleep(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN OUT PRTL_CRITICAL_SECTION CriticalSection OPTIONAL, IN OUT PRTL_SRWLOCK SRWLock OPTIONAL, IN ULONG SRWFlags, IN const LARGE_INTEGER *TimeOut OPTIONAL)
Definition: condvar.c:367
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
smooth NULL
Definition: ftsmooth.c:416

◆ RtlWakeAllConditionVariable()

VOID NTAPI RtlWakeAllConditionVariable ( IN OUT PRTL_CONDITION_VARIABLE  ConditionVariable)

Definition at line 491 of file condvar.c.

492 {
493  InternalWake(ConditionVariable, TRUE);
494 }
static VOID InternalWake(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN BOOLEAN ReleaseAll)
Definition: condvar.c:259
#define TRUE
Definition: types.h:120

Referenced by WakeAllConditionVariable().

◆ RtlWakeConditionVariable()

VOID NTAPI RtlWakeConditionVariable ( IN OUT PRTL_CONDITION_VARIABLE  ConditionVariable)

Definition at line 484 of file condvar.c.

485 {
486  InternalWake(ConditionVariable, FALSE);
487 }
static VOID InternalWake(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN BOOLEAN ReleaseAll)
Definition: condvar.c:259

Referenced by WakeConditionVariable().

Variable Documentation

◆ CondVarKeyedEventHandle

HANDLE CondVarKeyedEventHandle = NULL
static