1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
15 WaitMode_Alertable = 0x1, // Can be waken by APC. May pumping message.
16 WaitMode_IgnoreSyncCtx = 0x2, // Dispatch to synchronization context if existed.
17 WaitMode_ADUnload = 0x4, // The block is to wait for AD unload start. If it is interrupted by AD Unload, we can start aborting.
18 WaitMode_InDeadlock = 0x8, // The wait can be terminated by host's deadlock detection
30 LIMITED_METHOD_CONTRACT;
31 m_handle = INVALID_HANDLE_VALUE;
35 // Create an Event that is host aware
36 void CreateAutoEvent(BOOL bInitialState);
37 void CreateManualEvent(BOOL bInitialState);
39 // Non-throwing variants of the functions above
40 BOOL CreateAutoEventNoThrow(BOOL bInitialState);
41 BOOL CreateManualEventNoThrow(BOOL bInitialState);
43 void CreateMonitorEvent(SIZE_T Cookie); // robust against initialization races - for exclusive use by AwareLock
46 // Create an Event that is not host aware
47 void CreateOSAutoEvent (BOOL bInitialState);
48 void CreateOSManualEvent (BOOL bInitialState);
50 // Non-throwing variants of the functions above
51 BOOL CreateOSAutoEventNoThrow (BOOL bInitialState);
52 BOOL CreateOSManualEventNoThrow (BOOL bInitialState);
58 LIMITED_METHOD_CONTRACT;
59 return m_handle != INVALID_HANDLE_VALUE;
62 BOOL IsMonitorEventAllocated()
64 LIMITED_METHOD_CONTRACT;
65 return m_dwFlags & CLREVENT_FLAGS_MONITOREVENT_ALLOCATED;
68 #ifndef DACCESS_COMPILE
69 HANDLE GetHandleUNHOSTED() {
70 LIMITED_METHOD_CONTRACT;
73 #endif // DACCESS_COMPILE
76 void SetMonitorEvent(); // robust against races - for exclusive use by AwareLock
78 DWORD Wait(DWORD dwMilliseconds, BOOL bAlertable, PendingSync *syncState=NULL);
79 DWORD WaitEx(DWORD dwMilliseconds, WaitMode mode, PendingSync *syncState=NULL);
87 CLREVENT_FLAGS_AUTO_EVENT = 0x0001,
88 CLREVENT_FLAGS_OS_EVENT = 0x0002,
89 CLREVENT_FLAGS_IN_DEADLOCK_DETECTION = 0x0004,
91 CLREVENT_FLAGS_MONITOREVENT_ALLOCATED = 0x0008,
92 CLREVENT_FLAGS_MONITOREVENT_SIGNALLED = 0x0010,
94 CLREVENT_FLAGS_STATIC = 0x0020,
96 // Several bits unused;
99 Volatile<DWORD> m_dwFlags;
101 BOOL IsAutoEvent() { LIMITED_METHOD_CONTRACT; return m_dwFlags & CLREVENT_FLAGS_AUTO_EVENT; }
104 LIMITED_METHOD_CONTRACT;
105 // cannot use `|=' operator on `Volatile<DWORD>'
106 m_dwFlags = m_dwFlags | CLREVENT_FLAGS_AUTO_EVENT;
108 BOOL IsOSEvent() { LIMITED_METHOD_CONTRACT; return m_dwFlags & CLREVENT_FLAGS_OS_EVENT; }
111 LIMITED_METHOD_CONTRACT;
112 // cannot use `|=' operator on `Volatile<DWORD>'
113 m_dwFlags = m_dwFlags | CLREVENT_FLAGS_OS_EVENT;
115 BOOL IsInDeadlockDetection() { LIMITED_METHOD_CONTRACT; return m_dwFlags & CLREVENT_FLAGS_IN_DEADLOCK_DETECTION; }
116 void SetInDeadlockDetection ()
118 LIMITED_METHOD_CONTRACT;
119 // cannot use `|=' operator on `Volatile<DWORD>'
120 m_dwFlags = m_dwFlags | CLREVENT_FLAGS_IN_DEADLOCK_DETECTION;
125 class CLREvent : public CLREventBase
129 #ifndef DACCESS_COMPILE
141 // Same as CLREvent, but intended to be used for global variables.
142 // Instances may leak their handle, because of the order in which
143 // global destructors are run. Note that you can still explicitly
144 // call CloseHandle, which will indeed not leak the handle.
145 class CLREventStatic : public CLREventBase
153 : m_handle(INVALID_HANDLE_VALUE)
155 LIMITED_METHOD_CONTRACT;
164 void Create(DWORD dwInitial, DWORD dwMax);
169 LIMITED_METHOD_CONTRACT;
170 return m_handle != INVALID_HANDLE_VALUE;
173 DWORD Wait(DWORD dwMilliseconds, BOOL bAlertable);
174 BOOL Release(LONG lReleaseCount, LONG* lpPreviouseCount);
180 class CLRLifoSemaphore
192 UINT8 countOfWaitersSignaledToWake;
197 Counts(UINT64 data = 0) : data(data)
199 LIMITED_METHOD_CONTRACT;
202 operator UINT64() const
204 LIMITED_METHOD_CONTRACT;
208 Counts operator -() const
210 LIMITED_METHOD_CONTRACT;
214 Counts &operator =(UINT64 data)
216 LIMITED_METHOD_CONTRACT;
222 Counts VolatileLoadWithoutBarrier() const
224 LIMITED_METHOD_CONTRACT;
225 return ::VolatileLoadWithoutBarrier(&data);
228 Counts CompareExchange(Counts toCounts, Counts fromCounts)
230 LIMITED_METHOD_CONTRACT;
231 return (UINT64)InterlockedCompareExchange64((LONG64 *)&data, (LONG64)toCounts, (LONG64)fromCounts);
234 Counts ExchangeAdd(Counts toAdd)
236 LIMITED_METHOD_CONTRACT;
237 return (UINT64)InterlockedExchangeAdd64((LONG64 *)&data, (LONG64)toAdd);
242 CLRLifoSemaphore() : m_handle(nullptr)
244 LIMITED_METHOD_CONTRACT;
254 void Create(INT32 initialSignalCount, INT32 maximumSignalCount);
260 LIMITED_METHOD_CONTRACT;
261 return m_handle != nullptr;
265 bool WaitForSignal(DWORD timeoutMs);
267 bool Wait(DWORD timeoutMs);
268 bool Wait(DWORD timeoutMs, UINT32 spinCount, UINT32 processorCount);
269 void Release(INT32 releaseCount);
272 BYTE __padding1[MAX_CACHE_LINE_SIZE]; // padding to ensure that m_counts gets its own cache line
274 // Take care to use 'm_counts.VolatileLoadWithoutBarrier()` when loading this value into a local variable that will be
275 // reused. See AwareLock::m_lockState for details.
278 BYTE __padding2[MAX_CACHE_LINE_SIZE]; // padding to ensure that m_counts gets its own cache line
281 UINT32 m_maximumSignalCount;
282 #endif // _DEBUG && !FEATURE_PAL
284 // When FEATURE_PAL is defined, this is a handle to an instance of the PAL's LIFO semaphore. When FEATURE_PAL is not
285 // defined, this is a handle to an I/O completion port.
292 : m_handle(INVALID_HANDLE_VALUE)
294 LIMITED_METHOD_CONTRACT;
303 void Create(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName);
308 LIMITED_METHOD_CONTRACT;
309 return m_handle != INVALID_HANDLE_VALUE;
312 DWORD Wait(DWORD dwMilliseconds, BOOL bAlertable);
319 BOOL CLREventWaitWithTry(CLREventBase *pEvent, DWORD timeout, BOOL fAlertable, DWORD *pStatus);