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 | Module Name: |
10 | |
11 | palobjbase.cpp |
12 | |
13 | Abstract: |
14 | PAL object base class |
15 | |
16 | |
17 | |
18 | --*/ |
19 | |
20 | #include "palobjbase.hpp" |
21 | #include "pal/malloc.hpp" |
22 | #include "pal/dbgmsg.h" |
23 | |
24 | SET_DEFAULT_DEBUG_CHANNEL(PAL); |
25 | |
26 | using namespace CorUnix; |
27 | |
28 | CObjectType* CObjectType::s_rgotIdMapping[ObjectTypeIdCount]; |
29 | |
30 | /*++ |
31 | Function: |
32 | CPalObjectBase::Initialize |
33 | |
34 | Performs possibly-failing initialization for a newly-constructed |
35 | object |
36 | |
37 | Parameters: |
38 | pthr -- thread data for calling thread |
39 | poa -- the object attributes (e.g., name) for the object |
40 | --*/ |
41 | |
42 | PAL_ERROR |
43 | CPalObjectBase::Initialize( |
44 | CPalThread *pthr, |
45 | CObjectAttributes *poa |
46 | ) |
47 | { |
48 | PAL_ERROR palError = NO_ERROR; |
49 | |
50 | _ASSERTE(NULL != pthr); |
51 | _ASSERTE(NULL != poa); |
52 | |
53 | ENTRY("CPalObjectBase::Initialize" |
54 | "(this = %p, pthr = %p, poa = %p)\n" , |
55 | this, |
56 | pthr, |
57 | poa |
58 | ); |
59 | |
60 | if (0 != m_pot->GetImmutableDataSize()) |
61 | { |
62 | m_pvImmutableData = InternalMalloc(m_pot->GetImmutableDataSize()); |
63 | if (NULL != m_pvImmutableData) |
64 | { |
65 | ZeroMemory(m_pvImmutableData, m_pot->GetImmutableDataSize()); |
66 | } |
67 | else |
68 | { |
69 | ERROR("Unable to allocate immutable data\n" ); |
70 | palError = ERROR_OUTOFMEMORY; |
71 | goto IntializeExit; |
72 | } |
73 | } |
74 | |
75 | if (0 != m_pot->GetProcessLocalDataSize()) |
76 | { |
77 | palError = m_sdlLocalData.Initialize(); |
78 | if (NO_ERROR != palError) |
79 | { |
80 | ERROR("Unable to initialize local data lock!\n" ); |
81 | goto IntializeExit; |
82 | } |
83 | |
84 | m_pvLocalData = InternalMalloc(m_pot->GetProcessLocalDataSize()); |
85 | if (NULL != m_pvLocalData) |
86 | { |
87 | ZeroMemory(m_pvLocalData, m_pot->GetProcessLocalDataSize()); |
88 | } |
89 | else |
90 | { |
91 | ERROR("Unable to allocate local data\n" ); |
92 | palError = ERROR_OUTOFMEMORY; |
93 | goto IntializeExit; |
94 | } |
95 | } |
96 | |
97 | if (0 != poa->sObjectName.GetStringLength()) |
98 | { |
99 | palError = m_oa.sObjectName.CopyString(&poa->sObjectName); |
100 | } |
101 | |
102 | IntializeExit: |
103 | |
104 | LOGEXIT("CPalObjectBase::Initialize returns %d\n" , palError); |
105 | |
106 | return palError; |
107 | } |
108 | |
109 | /*++ |
110 | Function: |
111 | CPalObjectBase::GetObjectType |
112 | |
113 | Returns the type of the object |
114 | --*/ |
115 | |
116 | CObjectType * |
117 | CPalObjectBase::GetObjectType( |
118 | VOID |
119 | ) |
120 | { |
121 | ENTRY("CPalObjectBase::GetObjectType(this = %p)\n" , this); |
122 | LOGEXIT("CPalObjectBase::GetObjectType returns %p\n" , m_pot); |
123 | |
124 | return m_pot; |
125 | } |
126 | |
127 | /*++ |
128 | Function: |
129 | CPalObjectBase::GetObjectAttributes |
130 | |
131 | Returns the attributes of the object |
132 | --*/ |
133 | |
134 | CObjectAttributes * |
135 | CPalObjectBase::GetObjectAttributes( |
136 | VOID |
137 | ) |
138 | { |
139 | ENTRY("CPalObjectBase::GetObjectAttributes(this = %p)\n" , this); |
140 | LOGEXIT("CPalObjectBase::GetObjectAttributes returns %p\n" , &m_oa); |
141 | |
142 | return &m_oa; |
143 | } |
144 | |
145 | /*++ |
146 | Function: |
147 | CPalObjectBase::GetImmutableData |
148 | |
149 | Provides the caller access to the object's immutable data (if any) |
150 | |
151 | Parameters: |
152 | ppvImmutableData -- on success, receives a pointer to the object's |
153 | immutable data |
154 | --*/ |
155 | |
156 | PAL_ERROR |
157 | CPalObjectBase::GetImmutableData( |
158 | void **ppvImmutableData // OUT |
159 | ) |
160 | { |
161 | _ASSERTE(NULL != ppvImmutableData); |
162 | |
163 | ENTRY("CPalObjectBase::GetImmutableData" |
164 | "(this = %p, ppvImmutableData = %p)\n" , |
165 | this, |
166 | ppvImmutableData |
167 | ); |
168 | |
169 | _ASSERTE(0 < m_pot->GetImmutableDataSize()); |
170 | |
171 | *ppvImmutableData = m_pvImmutableData; |
172 | |
173 | LOGEXIT("CPalObjectBase::GetImmutableData returns %d\n" , NO_ERROR); |
174 | |
175 | return NO_ERROR; |
176 | } |
177 | |
178 | /*++ |
179 | Function: |
180 | CPalObjectBase::GetProcessLocalData |
181 | |
182 | Provides the caller access to the object's local data (if any) |
183 | |
184 | Parameters: |
185 | pthr -- thread data for calling thread |
186 | eLockRequest -- specifies if the caller desires a read lock or a |
187 | write lock on the data (currently ignored) |
188 | ppDataLock -- on success, receives a pointer to the data lock instance |
189 | for the local data |
190 | ppvProcssLocalData -- on success, receives a pointer to the local data |
191 | --*/ |
192 | |
193 | PAL_ERROR |
194 | CPalObjectBase::GetProcessLocalData( |
195 | CPalThread *pthr, |
196 | LockType eLockRequest, |
197 | IDataLock **ppDataLock, // OUT |
198 | void **ppvProcessLocalData // OUT |
199 | ) |
200 | { |
201 | _ASSERTE(NULL != pthr); |
202 | _ASSERTE(ReadLock == eLockRequest || WriteLock == eLockRequest); |
203 | _ASSERTE(NULL != ppDataLock); |
204 | _ASSERTE(NULL != ppvProcessLocalData); |
205 | |
206 | ENTRY("CPalObjectBase::GetProcessLocalData" |
207 | "(this = %p, pthr = %p, eLockRequest = %d, ppDataLock = %p," |
208 | " ppvProcessLocalData = %p)\n" , |
209 | this, |
210 | pthr, |
211 | eLockRequest, |
212 | ppDataLock, |
213 | ppvProcessLocalData |
214 | ); |
215 | |
216 | _ASSERTE(0 < m_pot->GetProcessLocalDataSize()); |
217 | |
218 | m_sdlLocalData.AcquireLock(pthr, ppDataLock); |
219 | *ppvProcessLocalData = m_pvLocalData; |
220 | |
221 | LOGEXIT("CPalObjectBase::GetProcessLocalData returns %d\n" , NO_ERROR); |
222 | |
223 | return NO_ERROR; |
224 | } |
225 | |
226 | /*++ |
227 | Function: |
228 | CPalObjectBase::AddReference |
229 | |
230 | Increments the object's reference count. The updated count is returned |
231 | for diagnostic purposes only |
232 | --*/ |
233 | |
234 | DWORD |
235 | CPalObjectBase::AddReference( |
236 | void |
237 | ) |
238 | { |
239 | LONG lRefCount; |
240 | |
241 | ENTRY("CPalObjectBase::AddReference(this = %p)\n" , this); |
242 | |
243 | _ASSERTE(m_lRefCount > 0); |
244 | lRefCount = InterlockedIncrement(&m_lRefCount); |
245 | |
246 | LOGEXIT("CPalObjectBase::AddReference returns %d\n" , lRefCount); |
247 | |
248 | return lRefCount; |
249 | } |
250 | |
251 | /*++ |
252 | Function: |
253 | CPalObjectBase::ReleaseReference |
254 | |
255 | Decrements the object's reference count. The updated count is returned |
256 | for diagnostic purposes only |
257 | |
258 | Parameters: |
259 | pthr -- thread data for calling thread |
260 | --*/ |
261 | |
262 | DWORD |
263 | CPalObjectBase::ReleaseReference( |
264 | CPalThread *pthr |
265 | ) |
266 | { |
267 | LONG lRefCount; |
268 | |
269 | _ASSERTE(NULL != pthr); |
270 | |
271 | ENTRY("CPalObjectBase::ReleaseReference" |
272 | "(this = %p, pthr = %p)\n" , |
273 | this, |
274 | pthr |
275 | ); |
276 | |
277 | AcquireObjectDestructionLock(pthr); |
278 | |
279 | _ASSERTE(m_lRefCount > 0); |
280 | |
281 | // |
282 | // Even though object destruction takes place under a lock |
283 | // we still need to use an interlocked decrement, as AddRef |
284 | // operates lock free |
285 | // |
286 | |
287 | lRefCount = InterlockedDecrement(&m_lRefCount); |
288 | |
289 | if (0 == lRefCount) |
290 | { |
291 | bool fCleanupSharedState = ReleaseObjectDestructionLock(pthr, TRUE); |
292 | |
293 | // |
294 | // We need to do two things with the calling thread data here: |
295 | // 1) store it in m_pthrCleanup so it is available to the destructors |
296 | // 2) Add a reference to it before starting any cleanup, and release |
297 | // that reference afterwords. |
298 | // |
299 | // Step 2 is necessary when we're cleaning up the thread object that |
300 | // represents the calling thread -- it ensures that the thread data |
301 | // is available throughout the entire cleanup process. |
302 | // |
303 | |
304 | m_pthrCleanup = pthr; |
305 | pthr->AddThreadReference(); |
306 | |
307 | if (NULL != m_pot->GetObjectCleanupRoutine()) |
308 | { |
309 | (*m_pot->GetObjectCleanupRoutine())( |
310 | pthr, |
311 | static_cast<IPalObject*>(this), |
312 | FALSE, |
313 | fCleanupSharedState |
314 | ); |
315 | } |
316 | |
317 | if (NULL != m_pot->GetImmutableDataCleanupRoutine()) |
318 | { |
319 | (*m_pot->GetImmutableDataCleanupRoutine())(m_pvImmutableData); |
320 | } |
321 | |
322 | if (NULL != m_pot->GetProcessLocalDataCleanupRoutine()) |
323 | { |
324 | (*m_pot->GetProcessLocalDataCleanupRoutine())(pthr, static_cast<IPalObject*>(this)); |
325 | } |
326 | |
327 | InternalDelete(this); |
328 | |
329 | pthr->ReleaseThreadReference(); |
330 | } |
331 | else |
332 | { |
333 | ReleaseObjectDestructionLock(pthr, FALSE); |
334 | } |
335 | |
336 | LOGEXIT("CPalObjectBase::ReleaseReference returns %d\n" , lRefCount); |
337 | |
338 | return lRefCount; |
339 | } |
340 | |
341 | /*++ |
342 | Function: |
343 | CPalObjectBase::~CPalObjectBase |
344 | |
345 | Object destructor |
346 | --*/ |
347 | |
348 | CPalObjectBase::~CPalObjectBase() |
349 | { |
350 | ENTRY("CPalObjectBase::~CPalObjectBase(this = %p)\n" , this); |
351 | |
352 | if (NULL != m_pvImmutableData) |
353 | { |
354 | free(m_pvImmutableData); |
355 | } |
356 | |
357 | if (NULL != m_pvLocalData) |
358 | { |
359 | free(m_pvLocalData); |
360 | } |
361 | |
362 | if (NULL != m_oa.sObjectName.GetString()) |
363 | { |
364 | m_oa.sObjectName.FreeBuffer(); |
365 | } |
366 | |
367 | LOGEXIT("CPalObjectBase::~CPalObjectBase\n" ); |
368 | } |
369 | |
370 | |