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//
9/*============================================================
10**
11** Header: Threads.inl
12**
13** Purpose: Implements Thread inline functions
14**
15**
16===========================================================*/
17#ifndef _THREADS_INL
18#define _THREADS_INL
19
20#include "threads.h"
21#include "appdomain.hpp"
22#include "frames.h"
23
24#ifndef DACCESS_COMPILE
25
26#ifndef __llvm__
27EXTERN_C __declspec(thread) ThreadLocalInfo gCurrentThreadInfo;
28#else // !__llvm__
29EXTERN_C __thread ThreadLocalInfo gCurrentThreadInfo;
30#endif // !__llvm__
31
32EXTERN_C inline Thread* STDCALL GetThread()
33{
34 return gCurrentThreadInfo.m_pThread;
35}
36
37EXTERN_C inline AppDomain* STDCALL GetAppDomain()
38{
39 return AppDomain::GetCurrentDomain();
40}
41
42#endif // !DACCESS_COMPILE
43
44inline void Thread::IncLockCount()
45{
46 LIMITED_METHOD_CONTRACT;
47 _ASSERTE(GetThread() == this);
48 m_dwLockCount++;
49 _ASSERTE(m_dwLockCount != 0 || HasThreadStateNC(TSNC_UnbalancedLocks));
50}
51
52inline void Thread::DecLockCount()
53{
54 LIMITED_METHOD_CONTRACT;
55 _ASSERTE(GetThread() == this);
56 _ASSERTE(m_dwLockCount > 0 || HasThreadStateNC(TSNC_UnbalancedLocks));
57 m_dwLockCount--;
58}
59
60inline
61Frame* Thread::FindFrame(SIZE_T StackPointer)
62{
63 Frame* pFrame = GetFrame();
64
65 while ((SIZE_T)pFrame < StackPointer)
66 {
67 pFrame = pFrame->Next();
68 }
69
70 return pFrame;
71}
72
73inline void Thread::SetThrowable(OBJECTREF pThrowable DEBUG_ARG(ThreadExceptionState::SetThrowableErrorChecking stecFlags))
74{
75 WRAPPER_NO_CONTRACT;
76
77 m_ExceptionState.SetThrowable(pThrowable DEBUG_ARG(stecFlags));
78}
79
80inline void Thread::SetKickOffDomainId(ADID ad)
81{
82 CONTRACTL {
83 NOTHROW;
84 GC_NOTRIGGER;
85 SO_TOLERANT;
86 }
87 CONTRACTL_END;
88
89 m_pKickOffDomainId = ad;
90}
91
92
93inline ADID Thread::GetKickOffDomainId()
94{
95 CONTRACTL {
96 NOTHROW;
97 GC_NOTRIGGER;
98 SO_TOLERANT;
99 }
100 CONTRACTL_END;
101
102 _ASSERTE(m_pKickOffDomainId.m_dwId != 0);
103 return m_pKickOffDomainId;
104}
105
106// get the current notification (if any) from this thread
107inline OBJECTHANDLE Thread::GetThreadCurrNotification()
108{
109 CONTRACTL
110 {
111 SO_NOT_MAINLINE;
112 NOTHROW;
113 GC_NOTRIGGER;
114 SUPPORTS_DAC;
115 }
116 CONTRACTL_END;
117
118 return m_hCurrNotification;
119}
120
121// set the current notification (if any) from this thread
122inline void Thread::SetThreadCurrNotification(OBJECTHANDLE handle)
123{
124 CONTRACTL
125 {
126 SO_NOT_MAINLINE;
127 NOTHROW;
128 GC_NOTRIGGER;
129 }
130 CONTRACTL_END;
131
132 m_hCurrNotification = handle;
133}
134
135// clear the current notification (if any) from this thread
136inline void Thread::ClearThreadCurrNotification()
137{
138 CONTRACTL
139 {
140 SO_NOT_MAINLINE;
141 NOTHROW;
142 GC_NOTRIGGER;
143 }
144 CONTRACTL_END;
145
146 m_hCurrNotification = NULL;
147}
148
149
150inline OBJECTREF Thread::GetExposedObjectRaw()
151{
152 CONTRACTL {
153 NOTHROW;
154 GC_NOTRIGGER;
155 SO_TOLERANT;
156 SUPPORTS_DAC;
157 }
158 CONTRACTL_END;
159
160 return ObjectFromHandle(m_ExposedObject);
161}
162
163inline void Thread::FinishSOWork()
164{
165 WRAPPER_NO_CONTRACT;
166#ifdef FEATURE_STACK_PROBE
167 if (HasThreadStateNC(TSNC_SOWorkNeeded))
168 {
169 ResetThreadStateNC(TSNC_SOWorkNeeded);
170 }
171#else
172 _ASSERTE(!HasThreadStateNC(TSNC_SOWorkNeeded));
173#endif
174}
175
176#ifdef FEATURE_COMINTEROP
177inline void Thread::RevokeApartmentSpy()
178{
179 LIMITED_METHOD_CONTRACT;
180
181 if (m_fInitializeSpyRegistered)
182 {
183 VERIFY(SUCCEEDED(CoRevokeInitializeSpy(m_uliInitializeSpyCookie)));
184 m_fInitializeSpyRegistered = false;
185 }
186}
187
188inline LPVOID Thread::GetLastSTACtxCookie(BOOL *pfNAContext)
189{
190 LIMITED_METHOD_CONTRACT;
191 *pfNAContext = ((UINT_PTR)m_pLastSTACtxCookie & 1);
192 return (LPVOID)((UINT_PTR)m_pLastSTACtxCookie & ~1);
193}
194
195inline void Thread::SetLastSTACtxCookie(LPVOID pCtxCookie, BOOL fNAContext)
196{
197 LIMITED_METHOD_CONTRACT;
198 if (fNAContext)
199 {
200 // The ctx cookie is an interface pointer so we can steal the lowest bit
201 // to mark whether the context is known to be Neutral Apartment or not.
202 m_pLastSTACtxCookie = (LPVOID)((UINT_PTR)pCtxCookie | 1);
203 }
204 else
205 {
206 m_pLastSTACtxCookie = pCtxCookie;
207 }
208}
209#endif // FEATURE_COMINTEROP
210
211inline bool Thread::IsGCSpecial()
212{
213 LIMITED_METHOD_CONTRACT;
214 return m_fGCSpecial;
215}
216
217inline void Thread::SetGCSpecial(bool fGCSpecial)
218{
219 LIMITED_METHOD_CONTRACT;
220 m_fGCSpecial = fGCSpecial;
221}
222
223#endif
224