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.
4 
5 //
6 // -----------------------------------------------------------------------------------------------------------
7 //
8 // Minimal Crst implementation based on CRITICAL_SECTION. Doesn't support much except for the basic locking
9 // functionality (in particular there is no rank violation checking).
10 //
11 
12 enum CrstType
13 {
14     CrstHandleTable,
15     CrstDispatchCache,
16     CrstAllocHeap,
17     CrstGenericInstHashtab,
18     CrstMemAccessMgr,
19     CrstInterfaceDispatchGlobalLists,
20     CrstStressLog,
21     CrstRestrictedCallouts,
22     CrstGcStressControl,
23     CrstSuspendEE,
24     CrstCastCache,
25 };
26 
27 enum CrstFlags
28 {
29     CRST_DEFAULT            = 0x0,
30     CRST_REENTRANCY         = 0x0,
31     CRST_UNSAFE_SAMELEVEL   = 0x0,
32     CRST_UNSAFE_ANYMODE     = 0x0,
33     CRST_DEBUGGER_THREAD    = 0x0,
34 };
35 
36 // Static version of Crst with no default constructor (user must call Init() before use).
37 class CrstStatic
38 {
39 public:
40     void Init(CrstType eType, CrstFlags eFlags = CRST_DEFAULT);
41     bool InitNoThrow(CrstType eType, CrstFlags eFlags = CRST_DEFAULT) { Init(eType, eFlags); return true; }
42     void Destroy();
Enter()43     void Enter() { CrstStatic::Enter(this); }
Leave()44     void Leave() { CrstStatic::Leave(this); }
45     static void Enter(CrstStatic *pCrst);
46     static void Leave(CrstStatic *pCrst);
47 #if defined(_DEBUG)
48     bool OwnedByCurrentThread();
49     EEThreadId GetHolderThreadId();
50 #endif // _DEBUG
51 
52 private:
53     CRITICAL_SECTION    m_sCritSec;
54 #if defined(_DEBUG)
55     EEThreadId          m_uiOwnerId;
56 #endif // _DEBUG
57 };
58 
59 // Non-static version that will initialize itself during construction.
60 class Crst : public CrstStatic
61 {
62 public:
63     Crst(CrstType eType, CrstFlags eFlags = CRST_DEFAULT)
CrstStatic()64         : CrstStatic()
65     { Init(eType, eFlags); }
66 };
67 
68 // Holder for a Crst instance.
69 class CrstHolder
70 {
71     CrstStatic * m_pLock;
72 
73 public:
CrstHolder(CrstStatic * pLock)74     CrstHolder(CrstStatic * pLock)
75         : m_pLock(pLock)
76     {
77         m_pLock->Enter();
78     }
79 
~CrstHolder()80     ~CrstHolder()
81     {
82         m_pLock->Leave();
83     }
84 };
85 
86 class CrstHolderWithState
87 {
88     CrstStatic * m_pLock;
89     bool m_fAcquired;
90 
91 public:
92     CrstHolderWithState(CrstStatic * pLock, bool fAcquire = true)
m_pLock(pLock)93         : m_pLock(pLock), m_fAcquired(fAcquire)
94     {
95         if (fAcquire)
96             m_pLock->Enter();
97     }
98 
~CrstHolderWithState()99     ~CrstHolderWithState()
100     {
101         if (m_fAcquired)
102             m_pLock->Leave();
103     }
104 
Acquire()105     void Acquire()
106     {
107         if (!m_fAcquired)
108         {
109             m_pLock->Enter();
110             m_fAcquired = true;
111         }
112     }
113 
Release()114     void Release()
115     {
116         if (m_fAcquired)
117         {
118             m_pLock->Leave();
119             m_fAcquired = false;
120         }
121     }
122 
GetValue()123     CrstStatic * GetValue()
124     {
125         return m_pLock;
126     }
127 };
128