ReactOS  0.4.15-dev-3193-g74513a7
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:65
#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:65
#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:65
FORCEINLINE VOID YieldProcessor(VOID)
Definition: ke.h:32
#define COND_VAR_LOCKED_FLAG
Definition: condvar.c:24
#define ASSERT(a)
Definition: mode.c:44
#define COND_VAR_FLAGS_MASK
Definition: condvar.c:25
#define for
Definition: utility.h:88
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:119
#define COND_VAR_ADDRESS_MASK
Definition: condvar.c:26
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define NULL
Definition: types.h:112
#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 }
NTSYSAPI NTSTATUS WINAPI NtWaitForKeyedEvent(HANDLE, const void *, BOOLEAN, const LARGE_INTEGER *)
PVOID WaitKey
Definition: condvar.c:33
LONG NTSTATUS
Definition: precomp.h:26
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
VOID NTAPI RtlAcquireSRWLockShared(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:325
BOOLEAN ListRemovalHandled
Definition: condvar.c:34
VOID NTAPI RtlReleaseSRWLockShared(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:526
#define FALSE
Definition: types.h:117
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
CRITICAL_SECTION CriticalSection
Definition: iprtprio.c:40
VOID NTAPI RtlAcquireSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:591
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
static VOID InternalUnlockCondVar(IN OUT PRTL_CONDITION_VARIABLE ConditionVariable, IN PCOND_VAR_WAIT_ENTRY RemoveEntry OPTIONAL)
Definition: condvar.c:190
#define RTL_CONDITION_VARIABLE_LOCKMODE_SHARED
Definition: winnt_old.h:2674
Definition: condvar.c:28
static HANDLE CondVarKeyedEventHandle
Definition: condvar.c:42
#define NULL
Definition: types.h:112
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:262
FORCEINLINE BOOLEAN * InternalGetListRemovalHandledFlag(IN PCOND_VAR_WAIT_ENTRY Entry)
Definition: condvar.c:70
VOID NTAPI RtlReleaseSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock)
Definition: srw.c:710

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:65
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define COND_VAR_LOCKED_FLAG
Definition: condvar.c:24
#define ASSERT(a)
Definition: mode.c:44
#define COND_VAR_FLAGS_MASK
Definition: condvar.c:25
Definition: typedefs.h:119
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 NULL
Definition: types.h:112
#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
struct _Entry Entry
Definition: kefuncs.h:627
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define FALSE
Definition: types.h:117
NTSYSAPI NTSTATUS WINAPI NtReleaseKeyedEvent(HANDLE, const void *, BOOLEAN, const LARGE_INTEGER *)
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
#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
Definition: condvar.c:28
static ULONG Timeout
Definition: ping.c:61
static HANDLE CondVarKeyedEventHandle
Definition: condvar.c:42
#define NULL
Definition: types.h:112
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 591 of file srw.c.

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

Referenced by InternalSleep().

◆ RtlAcquireSRWLockShared()

VOID NTAPI RtlAcquireSRWLockShared ( IN OUT PRTL_SRWLOCK  SRWLock)

Definition at line 325 of file srw.c.

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

Referenced by InternalSleep().

◆ RtlInitializeConditionVariable()

VOID NTAPI RtlInitializeConditionVariable ( OUT PRTL_CONDITION_VARIABLE  ConditionVariable)

Definition at line 477 of file condvar.c.

478 {
479  ConditionVariable->Ptr = NULL;
480 }
#define NULL
Definition: types.h:112

Referenced by InitializeConditionVariable().

◆ RtlpCloseKeyedEvent()

VOID RtlpCloseKeyedEvent ( VOID  )

Definition at line 466 of file condvar.c.

467 {
471 }
#define ASSERT(a)
Definition: mode.c:44
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3398
static HANDLE CondVarKeyedEventHandle
Definition: condvar.c:42
#define NULL
Definition: types.h:112

Referenced by DllMain().

◆ RtlpInitializeKeyedEvent()

VOID RtlpInitializeKeyedEvent ( VOID  )

Definition at line 459 of file condvar.c.

460 {
463 }
NTSYSAPI NTSTATUS WINAPI NtCreateKeyedEvent(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG)
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
#define ASSERT(a)
Definition: mode.c:44
static HANDLE CondVarKeyedEventHandle
Definition: condvar.c:42
#define NULL
Definition: types.h:112

Referenced by DllMain().

◆ RtlReleaseSRWLockExclusive()

VOID NTAPI RtlReleaseSRWLockExclusive ( IN OUT PRTL_SRWLOCK  SRWLock)

Definition at line 710 of file srw.c.

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

Referenced by InternalSleep().

◆ RtlReleaseSRWLockShared()

VOID NTAPI RtlReleaseSRWLockShared ( IN OUT PRTL_SRWLOCK  SRWLock)

Definition at line 526 of file srw.c.

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

Referenced by InternalSleep().

◆ 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
#define NULL
Definition: types.h:112

◆ 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
#define NULL
Definition: types.h:112

◆ 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
#define FALSE
Definition: types.h:117

Referenced by WakeConditionVariable().

Variable Documentation

◆ CondVarKeyedEventHandle

HANDLE CondVarKeyedEventHandle = NULL
static