2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
10 // Debug-instrumented hierarchical critical sections.
15 // The EE divides critical sections into numbered groups or "levels."
16 // Crsts that guard the lowest level data structures that don't
17 // use other services are grouped into the lowest-numbered levels.
18 // The higher-numbered levels are reserved for high-level crsts
19 // that guard broad swatches of code. Multiple groups can share the
20 // same number to indicate that they're disjoint (their locks will never
23 // The fundamental rule of the hierarchy that threads can only request
24 // a crst whose level is lower than any crst currently held by the thread.
25 // E.g. if a thread current holds a level-3 crst, he can try to enter
26 // a level-2 crst, but not a level-4 crst, nor a different level-3
27 // crst. This prevents the cyclic dependencies that lead to deadlock.
29 // For debugging purposes Crsts are all also grouped by a type (e.g.
30 // CrstRemoting, the type of Crst used to synchronize certain remoting
31 // operations). Each type maps to one level (though a level may map to
32 // multiple types). The idea here is for the programmer to express Crst types
33 // and their dependencies (e.g. a CrstClassInit instance may be acquired
34 // while a CrstRemoting instance is already held) in a high level manner
35 // while an external script handles the mechanical process of assigning
36 // numerical levels to each type. See file:..\inc\CrstTypes.def for these high level
42 // Crst *pcrst = new Crst(type);
44 // where "type" is one of the enums created in the auto-generated
45 // file:..\inc\CrstTypes.h header file (matching the definition in
46 // file:..\inc\CrstTypes.def).
48 // By default, crsts don't support nested enters by the same thread. If
49 // you need reentrancy, use the alternate form:
51 // Crst *pcrst = new Crst(type, TRUE);
53 // Since reentrancies never block the caller, they're allowed to
54 // "violate" the level ordering rule.
57 // To enter/leave a crst:
58 // ----------------------
64 // An assertion will fire on Enter() if a thread attempts to take locks
65 // in the wrong order.
67 // Finally, a few DEBUG-only methods:
69 // To assert taking a crst won't violate level order:
70 // --------------------------------------------------
72 // _ASSERTE(pcrst->IsSafeToTake());
74 // This is a good line to put at the start of any function that
75 // enters a crst in some circumstances but not others. If it
76 // always enters the crst, it's not necessary to call IsSafeToTake()
77 // since Enter() does this for you.
79 // To assert that the current thread owns a crst:
80 // --------------------------------------------------
82 // _ASSERTE(pcrst->OwnedByCurrentThread());
90 #include "debugmacros.h"
93 #define ShutDown_Start 0x00000001
94 #define ShutDown_Finalize1 0x00000002
95 #define ShutDown_Finalize2 0x00000004
96 #define ShutDown_Profiler 0x00000008
97 #define ShutDown_COM 0x00000010
98 #define ShutDown_SyncBlock 0x00000020
99 #define ShutDown_IUnknown 0x00000040
100 #define ShutDown_Phase2 0x00000080
102 #ifndef DACCESS_COMPILE
103 extern bool g_fProcessDetach;
104 extern DWORD g_fEEShutDown;
106 // Total count of Crst lock of the type (Shutdown) that are currently in use
107 extern Volatile<LONG> g_ShutdownCrstUsageCount;
108 extern Volatile<LONG> g_fForbidEnterEE;
109 extern bool g_fFinalizerRunOnShutDown;
114 #ifndef CLR_STANDALONE_BINDER
116 // The following classes and methods violate the requirement that Crst usage be
117 // exception-safe, or they satisfy that requirement using techniques other than
120 friend class ThreadStore;
121 friend class ThreadSuspend;
122 friend class ListLock;
123 friend class ListLockEntry;
124 //friend class CExecutionEngine;
125 friend struct SavedExceptionInfo;
126 friend void EEEnterCriticalSection(CRITSEC_COOKIE cookie);
127 friend void EELeaveCriticalSection(CRITSEC_COOKIE cookie);
128 friend class ReJitPublishMethodHolder;
129 friend class ReJitPublishMethodTableHolder;
131 friend class Debugger;
134 #ifdef FEATURE_DBGIPC_TRANSPORT_VM
135 // The debugger transport code uses a holder for its Crst, but it needs to share the holder implementation
136 // with its right side code as well (which can't see the Crst implementation and actually uses a
137 // CRITICAL_SECTION as the base lock). So make DbgTransportSession a friend here so we can use Enter() and
138 // Leave() in order to build a shared holder class.
139 friend class DbgTransportLock;
140 #endif // FEATURE_DBGIPC_TRANSPORT_VM
142 // PendingTypeLoadEntry acquires the lock during construction before anybody has a chance to see it to avoid
144 friend class PendingTypeLoadEntry;
148 enum NoLevelCheckFlag
150 CRST_NO_LEVEL_CHECK = 1,
151 CRST_LEVEL_CHECK = 0,
156 // Some Crsts have a "shutdown" mode.
157 // A Crst in shutdown mode can only be taken / released by special
158 // (the helper / finalizer / shutdown) threads. Any other thread that tries to take
159 // the a "shutdown" crst will immediately release the Crst and instead just block forever.
161 // This prevents random threads from blocking the special threads from doing finalization on shutdown.
163 // Unfortunately, each Crst needs its own "shutdown" flag because we can't convert all the locks
164 // into shutdown locks at once. For eg, the TSL needs to suspend the runtime before
165 // converting to a shutdown lock. But it can't suspend the runtime while holding
166 // a UNSAFE_ANYMODE lock (such as the debugger-lock). So at least the debugger-lock
167 // and TSL need to be set separately.
169 // So for such Crsts, it's the caller's responsibility to detect if the crst is in
170 // shutdown mode, and if so, call this function after enter.
171 void ReleaseAndBlockForShutdownIfNotSpecialThread();
173 // Enter & Leave are deliberately private to force callers to use the
174 // Holder class. If you bypass the Holder class and access these members
175 // directly, your lock is not exception-safe.
177 // noLevelCheckFlag parameter lets you disable the crst level checking. This is
178 // very dangerous so it is only used when the constructor is the one performing
179 // the Enter (that attempt cannot possibly block since the current thread is
180 // the only one with a pointer to the crst.)
182 // For obvious reasons, this parameter must never be made public.
183 void Enter(INDEBUG(NoLevelCheckFlag noLevelCheckFlag = CRST_LEVEL_CHECK));
188 #ifndef DACCESS_COMPILE
189 DEBUG_NOINLINE static void AcquireLock(CrstBase *c) PUB {
191 ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
195 DEBUG_NOINLINE static void ReleaseLock(CrstBase *c) PUB {
197 ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
201 #else // DACCESS_COMPILE
203 // in DAC builds, we don't actually acquire the lock, we just determine whether the LS
204 // already holds it. If so, we assume the data is inconsistent and throw an exception.
206 // input: c - the lock to be checked.
208 static void AcquireLock(CrstBase * c) PUB
211 if (c->GetEnterCount() != 0)
213 ThrowHR(CORDBG_E_PROCESS_NOT_SYNCHRONIZED);
217 static void ReleaseLock(CrstBase *c) PUB
221 #endif // DACCESS_COMPILE
224 //-----------------------------------------------------------------
225 // Clean up critical section
226 // Safe to call multiple times or on non-initialized critical section
227 //-----------------------------------------------------------------
231 //-----------------------------------------------------------------
232 // Check if attempting to take the lock would violate level order.
233 //-----------------------------------------------------------------
235 // Checks that the lock can be taken
239 // Actually take the lock and release it immediatelly, that will do all the necessary checks
244 void SetCantLeave(BOOL bSet)
246 LIMITED_METHOD_CONTRACT;
248 FastInterlockIncrement(&m_cannotLeave);
251 _ASSERTE(m_cannotLeave);
252 FastInterlockDecrement(&m_cannotLeave);
255 //-----------------------------------------------------------------
256 // Is the current thread the owner?
257 //-----------------------------------------------------------------
258 BOOL OwnedByCurrentThread()
261 #ifdef CROSSGEN_COMPILE
264 return m_holderthreadid.IsSameThread();
268 CrstBase *GetThreadsOwnedCrsts();
269 void SetThreadsOwnedCrsts(CrstBase *pCrst);
271 __declspec(noinline) EEThreadId GetHolderThreadId()
273 LIMITED_METHOD_CONTRACT;
274 return m_holderthreadid;
279 //-----------------------------------------------------------------
280 // For clients who want to assert whether they are in or out of the
282 //-----------------------------------------------------------------
285 LIMITED_METHOD_DAC_CONTRACT;
295 VOID InitWorker(INDEBUG_COMMA(CrstType crstType) CrstFlags flags);
298 void DebugInit(CrstType crstType, CrstFlags flags);
302 #endif // CLR_STANDALONE_BINDER
305 CRITICAL_SECTION m_criticalsection;
306 #ifdef FEATURE_INCLUDE_ALL_INTERFACES
307 IHostCrst *m_pHostCrst;
308 #endif // FEATURE_INCLUDE_ALL_INTERFACES
313 // Mask to indicate reserved flags
314 CRST_RESERVED_FLAGS_MASK = 0xC0000000,
315 // private flag to indicate initialized Crsts
316 CRST_INITIALIZED = 0x80000000,
317 // private flag to indicate Crst is OS Critical Section
318 CRST_OS_CRIT_SEC = 0x40000000,
319 // rest of the flags are CrstFlags
321 DWORD m_dwFlags; // Re-entrancy and same level
323 UINT m_entercount; // # of unmatched Enters.
324 CrstType m_crstType; // Type enum (should have a descriptive name for debugging)
325 const char *m_tag; // Stringized form of the tag for easy debugging
326 int m_crstlevel; // what level is the crst in?
327 EEThreadId m_holderthreadid; // current holder (or NULL)
328 CrstBase *m_next; // link for global linked list
329 CrstBase *m_prev; // link for global linked list
330 Volatile<LONG> m_cannotLeave;
332 // Check for dead lock situation.
333 ULONG m_countNoTriggerGC;
340 #ifndef CLR_STANDALONE_BINDER
346 m_dwFlags |= CRST_OS_CRIT_SEC;
348 void ResetOSCritSec ()
350 m_dwFlags &= ~CRST_OS_CRIT_SEC;
354 return m_dwFlags & CRST_OS_CRIT_SEC;
356 void SetCrstInitialized()
358 m_dwFlags |= CRST_INITIALIZED;
361 BOOL IsCrstInitialized()
363 return m_dwFlags & CRST_INITIALIZED;
366 BOOL CanBeTakenDuringShutdown()
368 return m_dwFlags & CRST_TAKEN_DURING_SHUTDOWN;
371 void SetFlags(CrstFlags f)
374 _ASSERTE(((CrstFlags)(f & ~CRST_RESERVED_FLAGS_MASK)) == f);
375 m_dwFlags = (f & ~CRST_RESERVED_FLAGS_MASK) | (m_dwFlags & CRST_RESERVED_FLAGS_MASK);
378 void ResetFlags() // resets the reserved and the CrstFlags
382 // ------------------------------- Holders ------------------------------
385 // CrstHolder is optimized for the common use that takes the lock in constructor
386 // and releases it in destructor. Users that require all Holder features
387 // can use CrstHolderWithState.
394 inline CrstHolder(CrstBase * pCrst)
405 VALIDATE_HOLDER_STACK_CONSUMPTION_FOR_TYPE(HSV_ValidateMinimumStackReq);
406 ReleaseLock(m_pCrst);
410 // Note that the holders for CRSTs are used in extremely low stack conditions. Because of this, they
411 // aren't allowed to use more than HOLDER_CODE_MINIMUM_STACK_LIMIT pages of stack.
412 typedef DacHolder<CrstBase *, CrstBase::AcquireLock, CrstBase::ReleaseLock, 0, CompareDefault, HSV_ValidateMinimumStackReq> CrstHolderWithState;
414 // We have some situations where we're already holding a lock, and we need to release and reacquire the lock across a window.
415 // This is a dangerous construct because the backout code can block.
416 // Generally, it's better to use a regular CrstHolder, and then use the Release() / Acquire() methods on it.
417 // This just exists to convert legacy OS Critical Section patterns over to holders.
418 typedef DacHolder<CrstBase *, CrstBase::ReleaseLock, CrstBase::AcquireLock, 0, CompareDefault, HSV_ValidateMinimumStackReq> UnsafeCrstInverseHolder;
420 #endif // CLR_STANDALONE_BINDER
423 #ifndef CLR_STANDALONE_BINDER
424 typedef CrstBase::CrstHolder CrstHolder;
425 typedef CrstBase::CrstHolderWithState CrstHolderWithState;
426 #endif // CLR_STANDALONE_BINDER
430 class Crst : public CrstBase
432 #ifndef CLR_STANDALONE_BINDER
434 void *operator new(size_t size)
437 return new BYTE[size];
441 // Do not use inplace operator new on Crst. A wrong destructor would be called if the constructor fails.
442 // Use CrstStatic or CrstExplicitInit instead of the inplace operator new.
443 void *operator new(size_t size, void *pInPlace);
447 #ifndef DACCESS_COMPILE
449 //-----------------------------------------------------------------
451 //-----------------------------------------------------------------
452 Crst(CrstType crstType, CrstFlags flags = CRST_DEFAULT)
456 // throw away the debug-only parameter in retail
457 InitWorker(INDEBUG_COMMA(crstType) flags);
460 //-----------------------------------------------------------------
462 //-----------------------------------------------------------------
472 Crst(CrstType crstType, CrstFlags flags = CRST_DEFAULT) {
473 LIMITED_METHOD_CONTRACT;
479 LIMITED_METHOD_CONTRACT;
482 #endif // CLR_STANDALONE_BINDER
485 typedef DPTR(Crst) PTR_Crst;
487 /* to be used as static variable - no constructor/destructor, assumes zero
488 initialized memory */
489 class CrstStatic : public CrstBase
491 #ifndef CLR_STANDALONE_BINDER
493 VOID Init(CrstType crstType, CrstFlags flags = CRST_DEFAULT)
497 _ASSERTE((flags & CRST_INITIALIZED) == 0);
499 // throw away the debug-only parameter in retail
500 InitWorker(INDEBUG_COMMA(crstType) flags);
503 bool InitNoThrow(CrstType crstType, CrstFlags flags = CRST_DEFAULT)
509 _ASSERTE((flags & CRST_INITIALIZED) == 0);
511 bool fSuccess = false;
515 // throw away the debug-only parameter in retail
516 InitWorker(INDEBUG_COMMA(crstType) flags);
522 EX_END_CATCH(SwallowAllExceptions)
526 #endif // CLR_STANDALONE_BINDER
529 /* to be used as regular variable when a explicit call to Init method is needed */
530 class CrstExplicitInit : public CrstStatic
532 #ifndef CLR_STANDALONE_BINDER
537 ~CrstExplicitInit() {
538 #ifndef DACCESS_COMPILE
542 #endif // CLR_STANDALONE_BINDER
545 #ifndef CLR_STANDALONE_BINDER
546 __inline BOOL IsOwnerOfCrst(LPVOID lock)
551 return ((Crst*)lock)->OwnedByCurrentThread();
553 // This function should not be called on free build.
559 #endif // CLR_STANDALONE_BINDER
561 #ifdef TEST_DATA_CONSISTENCY
562 // used for test purposes. Determines if a crst is held.
563 void DebugTryCrst(CrstBase * pLock);