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 | // ProfilePriv.inl |
6 | // |
7 | |
8 | // |
9 | // Inlined functions used by the Profiling API and throughout the EE. Most notably are |
10 | // the CORProfilerTrack* functions that test whether a profiler is active and responding |
11 | // to various callbacks |
12 | // |
13 | |
14 | // ====================================================================================== |
15 | #ifndef _ProfilePriv_inl_ |
16 | #define _ProfilePriv_inl_ |
17 | |
18 | #include "eetoprofinterfaceimpl.h" |
19 | #ifdef PROFILING_SUPPORTED |
20 | #include "profilinghelper.h" |
21 | BOOL CORProfilerBypassSecurityChecks(); |
22 | #endif // PROFILING_SUPPORTED |
23 | |
24 | //--------------------------------------------------------------------------------------- |
25 | // CurrentProfilerStatus |
26 | //--------------------------------------------------------------------------------------- |
27 | |
28 | inline void CurrentProfilerStatus::Init() |
29 | { |
30 | LIMITED_METHOD_CONTRACT; |
31 | m_profStatus = kProfStatusNone; |
32 | } |
33 | |
34 | inline ProfilerStatus CurrentProfilerStatus::Get() |
35 | { |
36 | LIMITED_METHOD_DAC_CONTRACT; |
37 | return m_profStatus; |
38 | } |
39 | |
40 | //--------------------------------------------------------------------------------------- |
41 | // ProfControlBlock |
42 | //--------------------------------------------------------------------------------------- |
43 | |
44 | inline void ProfControlBlock::Init() |
45 | { |
46 | CONTRACTL |
47 | { |
48 | NOTHROW; |
49 | GC_NOTRIGGER; |
50 | CANNOT_TAKE_LOCK; |
51 | } |
52 | CONTRACTL_END; |
53 | |
54 | curProfStatus.Init(); |
55 | |
56 | fGCInProgress = FALSE; |
57 | fBaseSystemClassesLoaded = FALSE; |
58 | #ifdef PROF_TEST_ONLY_FORCE_ELT |
59 | fTestOnlyForceEnterLeave = FALSE; |
60 | #endif |
61 | |
62 | #ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED |
63 | fTestOnlyForceObjectAllocated = FALSE; |
64 | #endif |
65 | |
66 | #ifdef _DEBUG |
67 | fTestOnlyEnableICorProfilerInfo = FALSE; |
68 | #endif // _DEBUG |
69 | |
70 | fConcurrentGCDisabledForAttach = FALSE; |
71 | |
72 | ResetPerSessionStatus(); |
73 | } |
74 | |
75 | // Reset those variables that is only for the current attach session |
76 | inline void ProfControlBlock::ResetPerSessionStatus() |
77 | { |
78 | LIMITED_METHOD_CONTRACT; |
79 | |
80 | pProfInterface = NULL; |
81 | dwEventMask = COR_PRF_MONITOR_NONE; |
82 | dwEventMaskHigh = COR_PRF_HIGH_MONITOR_NONE; |
83 | } |
84 | |
85 | //--------------------------------------------------------------------------------------- |
86 | // Inlined helpers used throughout the runtime to check for the profiler's load status |
87 | // and what features it enabled callbacks for. |
88 | //--------------------------------------------------------------------------------------- |
89 | |
90 | |
91 | // CORProfilerPresent() returns whether or not a CLR Profiler is actively loaded |
92 | // (meaning it's initialized and ready to receive callbacks). |
93 | inline BOOL CORProfilerPresent() |
94 | { |
95 | LIMITED_METHOD_DAC_CONTRACT; |
96 | |
97 | return ((&g_profControlBlock)->curProfStatus.Get() == kProfStatusActive); |
98 | } |
99 | |
100 | // These return whether a CLR Profiler is actively loaded AND has requested the |
101 | // specified callback or functionality |
102 | |
103 | inline BOOL CORProfilerFunctionIDMapperEnabled() |
104 | { |
105 | CONTRACTL |
106 | { |
107 | NOTHROW; |
108 | GC_NOTRIGGER; |
109 | CANNOT_TAKE_LOCK; |
110 | SO_NOT_MAINLINE; |
111 | } |
112 | CONTRACTL_END; |
113 | |
114 | return (CORProfilerPresent() && |
115 | ( |
116 | ((&g_profControlBlock)->pProfInterface->GetFunctionIDMapper() != NULL) || |
117 | ((&g_profControlBlock)->pProfInterface->GetFunctionIDMapper2() != NULL) |
118 | )); |
119 | } |
120 | |
121 | inline BOOL CORProfilerTrackJITInfo() |
122 | { |
123 | CONTRACTL |
124 | { |
125 | NOTHROW; |
126 | GC_NOTRIGGER; |
127 | CANNOT_TAKE_LOCK; |
128 | SO_NOT_MAINLINE; |
129 | } |
130 | CONTRACTL_END; |
131 | |
132 | return (CORProfilerPresent() && |
133 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_JIT_COMPILATION)); |
134 | } |
135 | |
136 | inline BOOL CORProfilerTrackCacheSearches() |
137 | { |
138 | CONTRACTL |
139 | { |
140 | NOTHROW; |
141 | GC_NOTRIGGER; |
142 | CANNOT_TAKE_LOCK; |
143 | SO_NOT_MAINLINE; |
144 | } |
145 | CONTRACTL_END; |
146 | |
147 | return (CORProfilerPresent() && |
148 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CACHE_SEARCHES)); |
149 | } |
150 | |
151 | inline BOOL CORProfilerTrackModuleLoads() |
152 | { |
153 | CONTRACTL |
154 | { |
155 | NOTHROW; |
156 | GC_NOTRIGGER; |
157 | CANNOT_TAKE_LOCK; |
158 | SO_NOT_MAINLINE; |
159 | } |
160 | CONTRACTL_END; |
161 | |
162 | return (CORProfilerPresent() && |
163 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_MODULE_LOADS)); |
164 | } |
165 | |
166 | inline BOOL CORProfilerTrackAssemblyLoads() |
167 | { |
168 | CONTRACTL |
169 | { |
170 | NOTHROW; |
171 | GC_NOTRIGGER; |
172 | CANNOT_TAKE_LOCK; |
173 | SO_NOT_MAINLINE; |
174 | } |
175 | CONTRACTL_END; |
176 | |
177 | return (CORProfilerPresent() && |
178 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_ASSEMBLY_LOADS)); |
179 | } |
180 | |
181 | inline BOOL CORProfilerTrackAppDomainLoads() |
182 | { |
183 | CONTRACTL |
184 | { |
185 | NOTHROW; |
186 | GC_NOTRIGGER; |
187 | CANNOT_TAKE_LOCK; |
188 | SO_NOT_MAINLINE; |
189 | } |
190 | CONTRACTL_END; |
191 | |
192 | return (CORProfilerPresent() && |
193 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_APPDOMAIN_LOADS)); |
194 | } |
195 | |
196 | inline BOOL CORProfilerTrackThreads() |
197 | { |
198 | CONTRACTL |
199 | { |
200 | NOTHROW; |
201 | GC_NOTRIGGER; |
202 | CANNOT_TAKE_LOCK; |
203 | SO_NOT_MAINLINE; |
204 | } |
205 | CONTRACTL_END; |
206 | |
207 | return (CORProfilerPresent() && |
208 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_THREADS)); |
209 | } |
210 | |
211 | inline BOOL CORProfilerTrackClasses() |
212 | { |
213 | CONTRACTL |
214 | { |
215 | NOTHROW; |
216 | GC_NOTRIGGER; |
217 | CANNOT_TAKE_LOCK; |
218 | SO_NOT_MAINLINE; |
219 | } |
220 | CONTRACTL_END; |
221 | |
222 | return (CORProfilerPresent() && |
223 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CLASS_LOADS)); |
224 | } |
225 | |
226 | inline BOOL CORProfilerTrackGC() |
227 | { |
228 | CONTRACTL |
229 | { |
230 | NOTHROW; |
231 | GC_NOTRIGGER; |
232 | CANNOT_TAKE_LOCK; |
233 | SO_NOT_MAINLINE; |
234 | } |
235 | CONTRACTL_END; |
236 | |
237 | return (CORProfilerPresent() && |
238 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_GC)); |
239 | } |
240 | |
241 | inline BOOL CORProfilerTrackAllocationsEnabled() |
242 | { |
243 | CONTRACTL |
244 | { |
245 | NOTHROW; |
246 | GC_NOTRIGGER; |
247 | CANNOT_TAKE_LOCK; |
248 | SO_NOT_MAINLINE; |
249 | } |
250 | CONTRACTL_END; |
251 | |
252 | return |
253 | ( |
254 | #ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED |
255 | (&g_profControlBlock)->fTestOnlyForceObjectAllocated || |
256 | #endif |
257 | (CORProfilerPresent() && |
258 | ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_OBJECT_ALLOCATED)) |
259 | ); |
260 | } |
261 | |
262 | inline BOOL CORProfilerTrackAllocations() |
263 | { |
264 | CONTRACTL |
265 | { |
266 | NOTHROW; |
267 | GC_NOTRIGGER; |
268 | CANNOT_TAKE_LOCK; |
269 | SO_NOT_MAINLINE; |
270 | } |
271 | CONTRACTL_END; |
272 | |
273 | return |
274 | (CORProfilerTrackAllocationsEnabled() && |
275 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_OBJECT_ALLOCATED)); |
276 | } |
277 | |
278 | inline BOOL CORProfilerEnableRejit() |
279 | { |
280 | CONTRACTL |
281 | { |
282 | NOTHROW; |
283 | GC_NOTRIGGER; |
284 | CANNOT_TAKE_LOCK; |
285 | SO_NOT_MAINLINE; |
286 | } |
287 | CONTRACTL_END; |
288 | |
289 | return (CORProfilerPresent() && |
290 | ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_REJIT)); |
291 | } |
292 | |
293 | inline BOOL CORProfilerTrackExceptions() |
294 | { |
295 | CONTRACTL |
296 | { |
297 | NOTHROW; |
298 | GC_NOTRIGGER; |
299 | CANNOT_TAKE_LOCK; |
300 | SO_NOT_MAINLINE; |
301 | } |
302 | CONTRACTL_END; |
303 | |
304 | return (CORProfilerPresent() && |
305 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_EXCEPTIONS)); |
306 | } |
307 | |
308 | inline BOOL CORProfilerTrackCLRExceptions() |
309 | { |
310 | CONTRACTL |
311 | { |
312 | NOTHROW; |
313 | GC_NOTRIGGER; |
314 | CANNOT_TAKE_LOCK; |
315 | SO_NOT_MAINLINE; |
316 | } |
317 | CONTRACTL_END; |
318 | |
319 | return (CORProfilerPresent() && |
320 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CLR_EXCEPTIONS)); |
321 | } |
322 | |
323 | inline BOOL CORProfilerTrackTransitions() |
324 | { |
325 | CONTRACTL |
326 | { |
327 | NOTHROW; |
328 | GC_NOTRIGGER; |
329 | CANNOT_TAKE_LOCK; |
330 | SO_NOT_MAINLINE; |
331 | } |
332 | CONTRACTL_END; |
333 | |
334 | return (CORProfilerPresent() && |
335 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CODE_TRANSITIONS)); |
336 | } |
337 | |
338 | inline BOOL CORProfilerTrackEnterLeave() |
339 | { |
340 | CONTRACTL |
341 | { |
342 | NOTHROW; |
343 | GC_NOTRIGGER; |
344 | CANNOT_TAKE_LOCK; |
345 | SO_NOT_MAINLINE; |
346 | } |
347 | CONTRACTL_END; |
348 | |
349 | #ifdef PROF_TEST_ONLY_FORCE_ELT |
350 | if ((&g_profControlBlock)->fTestOnlyForceEnterLeave) |
351 | return TRUE; |
352 | #endif // PROF_TEST_ONLY_FORCE_ELT |
353 | |
354 | return (CORProfilerPresent() && |
355 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_ENTERLEAVE)); |
356 | } |
357 | |
358 | inline BOOL CORProfilerTrackCCW() |
359 | { |
360 | CONTRACTL |
361 | { |
362 | NOTHROW; |
363 | GC_NOTRIGGER; |
364 | CANNOT_TAKE_LOCK; |
365 | SO_NOT_MAINLINE; |
366 | } |
367 | CONTRACTL_END; |
368 | |
369 | return (CORProfilerPresent() && |
370 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CCW)); |
371 | } |
372 | |
373 | inline BOOL CORProfilerTrackRemoting() |
374 | { |
375 | CONTRACTL |
376 | { |
377 | NOTHROW; |
378 | GC_NOTRIGGER; |
379 | CANNOT_TAKE_LOCK; |
380 | SO_NOT_MAINLINE; |
381 | } |
382 | CONTRACTL_END; |
383 | |
384 | return (CORProfilerPresent() && |
385 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING)); |
386 | } |
387 | |
388 | inline BOOL CORProfilerTrackRemotingCookie() |
389 | { |
390 | CONTRACTL |
391 | { |
392 | NOTHROW; |
393 | GC_NOTRIGGER; |
394 | CANNOT_TAKE_LOCK; |
395 | SO_NOT_MAINLINE; |
396 | } |
397 | CONTRACTL_END; |
398 | |
399 | return |
400 | (CORProfilerPresent() && |
401 | (((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING_COOKIE) |
402 | == COR_PRF_MONITOR_REMOTING_COOKIE)); |
403 | } |
404 | |
405 | inline BOOL CORProfilerTrackRemotingAsync() |
406 | { |
407 | CONTRACTL |
408 | { |
409 | NOTHROW; |
410 | GC_NOTRIGGER; |
411 | CANNOT_TAKE_LOCK; |
412 | SO_NOT_MAINLINE; |
413 | } |
414 | CONTRACTL_END; |
415 | |
416 | return |
417 | (CORProfilerPresent() && |
418 | (((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING_ASYNC) |
419 | == COR_PRF_MONITOR_REMOTING_ASYNC)); |
420 | } |
421 | |
422 | inline BOOL CORProfilerTrackSuspends() |
423 | { |
424 | CONTRACTL |
425 | { |
426 | NOTHROW; |
427 | GC_NOTRIGGER; |
428 | CANNOT_TAKE_LOCK; |
429 | SO_NOT_MAINLINE; |
430 | } |
431 | CONTRACTL_END; |
432 | |
433 | return (CORProfilerPresent() && |
434 | ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_SUSPENDS)); |
435 | } |
436 | |
437 | inline BOOL CORProfilerDisableInlining() |
438 | { |
439 | CONTRACTL |
440 | { |
441 | NOTHROW; |
442 | GC_NOTRIGGER; |
443 | CANNOT_TAKE_LOCK; |
444 | SO_NOT_MAINLINE; |
445 | } |
446 | CONTRACTL_END; |
447 | |
448 | return (CORProfilerPresent() && |
449 | ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_INLINING)); |
450 | } |
451 | |
452 | inline BOOL CORProfilerJITMapEnabled() |
453 | { |
454 | CONTRACTL |
455 | { |
456 | NOTHROW; |
457 | GC_NOTRIGGER; |
458 | CANNOT_TAKE_LOCK; |
459 | SO_NOT_MAINLINE; |
460 | } |
461 | CONTRACTL_END; |
462 | |
463 | return (CORProfilerPresent() && |
464 | ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_JIT_MAPS)); |
465 | } |
466 | |
467 | inline BOOL CORProfilerDisableOptimizations() |
468 | { |
469 | CONTRACTL |
470 | { |
471 | NOTHROW; |
472 | GC_NOTRIGGER; |
473 | CANNOT_TAKE_LOCK; |
474 | SO_NOT_MAINLINE; |
475 | SUPPORTS_DAC; |
476 | } |
477 | CONTRACTL_END; |
478 | |
479 | return (CORProfilerPresent() && |
480 | ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_OPTIMIZATIONS)); |
481 | } |
482 | |
483 | inline BOOL CORProfilerUseProfileImages() |
484 | { |
485 | CONTRACTL |
486 | { |
487 | NOTHROW; |
488 | GC_NOTRIGGER; |
489 | CANNOT_TAKE_LOCK; |
490 | SO_NOT_MAINLINE; |
491 | } |
492 | CONTRACTL_END; |
493 | |
494 | #ifdef PROF_TEST_ONLY_FORCE_ELT |
495 | if ((&g_profControlBlock)->fTestOnlyForceEnterLeave) |
496 | return TRUE; |
497 | #endif // PROF_TEST_ONLY_FORCE_ELT |
498 | |
499 | if (!CORProfilerPresent()) |
500 | return FALSE; |
501 | |
502 | if (((&g_profControlBlock)->dwEventMask & |
503 | COR_PRF_REQUIRE_PROFILE_IMAGE) == 0) |
504 | return FALSE; |
505 | |
506 | return TRUE; |
507 | } |
508 | |
509 | inline BOOL CORProfilerDisableAllNGenImages() |
510 | { |
511 | LIMITED_METHOD_DAC_CONTRACT; |
512 | |
513 | return (CORProfilerPresent() && |
514 | ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_ALL_NGEN_IMAGES)); |
515 | } |
516 | |
517 | inline BOOL CORProfilerTrackConditionalWeakTableElements() |
518 | { |
519 | LIMITED_METHOD_DAC_CONTRACT; |
520 | |
521 | return CORProfilerTrackGC() && (&g_profControlBlock)->pProfInterface->IsCallback5Supported(); |
522 | } |
523 | |
524 | // CORProfilerPresentOrInitializing() returns nonzero iff a CLR Profiler is actively |
525 | // loaded and ready to receive callbacks OR a CLR Profiler has loaded just enough that it |
526 | // is ready to receive (or is currently executing inside) its Initialize() callback. |
527 | // Typically, you'll want to use code:CORProfilerPresent instead of this. But there is |
528 | // some internal profiling API code that wants to test for event flags for a profiler |
529 | // that may still be initializing, and this function is appropriate for that code. |
530 | inline BOOL CORProfilerPresentOrInitializing() |
531 | { |
532 | LIMITED_METHOD_DAC_CONTRACT; |
533 | return ((&g_profControlBlock)->curProfStatus.Get() > kProfStatusDetaching); |
534 | } |
535 | |
536 | // These return whether a CLR Profiler has requested the specified functionality. |
537 | // |
538 | // Note that, unlike the above functions, a profiler that's not done loading (and is |
539 | // still somewhere in the initialization phase) still counts. This is only safe because |
540 | // these functions are not used to determine whether to issue a callback. These functions |
541 | // are used primarily during the initialization path to choose between slow / fast-path |
542 | // ELT hooks (and later on as part of asserts). |
543 | |
544 | inline BOOL CORProfilerELT3SlowPathEnabled() |
545 | { |
546 | CONTRACTL |
547 | { |
548 | NOTHROW; |
549 | GC_NOTRIGGER; |
550 | CANNOT_TAKE_LOCK; |
551 | SO_NOT_MAINLINE; |
552 | } |
553 | CONTRACTL_END; |
554 | |
555 | return (CORProfilerPresentOrInitializing() && |
556 | ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); |
557 | } |
558 | |
559 | inline BOOL CORProfilerELT3SlowPathEnterEnabled() |
560 | { |
561 | CONTRACTL |
562 | { |
563 | NOTHROW; |
564 | GC_NOTRIGGER; |
565 | CANNOT_TAKE_LOCK; |
566 | SO_NOT_MAINLINE; |
567 | } |
568 | CONTRACTL_END; |
569 | |
570 | return (CORProfilerPresentOrInitializing() && |
571 | ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO))); |
572 | } |
573 | |
574 | inline BOOL CORProfilerELT3SlowPathLeaveEnabled() |
575 | { |
576 | CONTRACTL |
577 | { |
578 | NOTHROW; |
579 | GC_NOTRIGGER; |
580 | CANNOT_TAKE_LOCK; |
581 | SO_NOT_MAINLINE; |
582 | } |
583 | CONTRACTL_END; |
584 | |
585 | return (CORProfilerPresentOrInitializing() && |
586 | ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); |
587 | } |
588 | |
589 | inline BOOL CORProfilerELT3SlowPathTailcallEnabled() |
590 | { |
591 | CONTRACTL |
592 | { |
593 | NOTHROW; |
594 | GC_NOTRIGGER; |
595 | CANNOT_TAKE_LOCK; |
596 | SO_NOT_MAINLINE; |
597 | } |
598 | CONTRACTL_END; |
599 | |
600 | return (CORProfilerPresentOrInitializing() && |
601 | ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FRAME_INFO))); |
602 | } |
603 | |
604 | inline BOOL CORProfilerELT2FastPathEnterEnabled() |
605 | { |
606 | CONTRACTL |
607 | { |
608 | NOTHROW; |
609 | GC_NOTRIGGER; |
610 | CANNOT_TAKE_LOCK; |
611 | SO_NOT_MAINLINE; |
612 | } |
613 | CONTRACTL_END; |
614 | |
615 | return (CORProfilerPresentOrInitializing() && |
616 | (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO)))); |
617 | } |
618 | |
619 | inline BOOL CORProfilerELT2FastPathLeaveEnabled() |
620 | { |
621 | CONTRACTL |
622 | { |
623 | NOTHROW; |
624 | GC_NOTRIGGER; |
625 | CANNOT_TAKE_LOCK; |
626 | SO_NOT_MAINLINE; |
627 | } |
628 | CONTRACTL_END; |
629 | |
630 | return (CORProfilerPresentOrInitializing() && |
631 | (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)))); |
632 | } |
633 | |
634 | inline BOOL CORProfilerELT2FastPathTailcallEnabled() |
635 | { |
636 | CONTRACTL |
637 | { |
638 | NOTHROW; |
639 | GC_NOTRIGGER; |
640 | CANNOT_TAKE_LOCK; |
641 | SO_NOT_MAINLINE; |
642 | } |
643 | CONTRACTL_END; |
644 | |
645 | return (CORProfilerPresentOrInitializing() && |
646 | (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FRAME_INFO)))); |
647 | } |
648 | |
649 | inline BOOL CORProfilerFunctionArgsEnabled() |
650 | { |
651 | CONTRACTL |
652 | { |
653 | NOTHROW; |
654 | GC_NOTRIGGER; |
655 | CANNOT_TAKE_LOCK; |
656 | SO_NOT_MAINLINE; |
657 | } |
658 | CONTRACTL_END; |
659 | |
660 | return (CORProfilerPresentOrInitializing() && |
661 | ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FUNCTION_ARGS)); |
662 | } |
663 | |
664 | inline BOOL CORProfilerFunctionReturnValueEnabled() |
665 | { |
666 | CONTRACTL |
667 | { |
668 | NOTHROW; |
669 | GC_NOTRIGGER; |
670 | CANNOT_TAKE_LOCK; |
671 | SO_NOT_MAINLINE; |
672 | } |
673 | CONTRACTL_END; |
674 | |
675 | return (CORProfilerPresentOrInitializing() && |
676 | ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FUNCTION_RETVAL)); |
677 | } |
678 | |
679 | inline BOOL CORProfilerFrameInfoEnabled() |
680 | { |
681 | CONTRACTL |
682 | { |
683 | NOTHROW; |
684 | GC_NOTRIGGER; |
685 | CANNOT_TAKE_LOCK; |
686 | SO_NOT_MAINLINE; |
687 | } |
688 | CONTRACTL_END; |
689 | |
690 | return (CORProfilerPresentOrInitializing() && |
691 | ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FRAME_INFO)); |
692 | } |
693 | |
694 | inline BOOL CORProfilerStackSnapshotEnabled() |
695 | { |
696 | CONTRACTL |
697 | { |
698 | NOTHROW; |
699 | GC_NOTRIGGER; |
700 | CANNOT_TAKE_LOCK; |
701 | SO_NOT_MAINLINE; |
702 | } |
703 | CONTRACTL_END; |
704 | |
705 | return (CORProfilerPresentOrInitializing() && |
706 | ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_STACK_SNAPSHOT)); |
707 | } |
708 | |
709 | inline BOOL CORProfilerAddsAssemblyReferences() |
710 | { |
711 | CONTRACTL |
712 | { |
713 | NOTHROW; |
714 | GC_NOTRIGGER; |
715 | CANNOT_TAKE_LOCK; |
716 | SO_NOT_MAINLINE; |
717 | } |
718 | CONTRACTL_END; |
719 | |
720 | return (CORProfilerPresent() && |
721 | ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES)); |
722 | } |
723 | |
724 | inline BOOL CORProfilerInMemorySymbolsUpdatesEnabled() |
725 | { |
726 | CONTRACTL |
727 | { |
728 | NOTHROW; |
729 | GC_NOTRIGGER; |
730 | CANNOT_TAKE_LOCK; |
731 | SO_NOT_MAINLINE; |
732 | } |
733 | CONTRACTL_END; |
734 | |
735 | return (CORProfilerPresent() && |
736 | ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED)); |
737 | } |
738 | |
739 | inline BOOL CORProfilerIsMonitoringDynamicFunctionUnloads() |
740 | { |
741 | CONTRACTL |
742 | { |
743 | NOTHROW; |
744 | GC_NOTRIGGER; |
745 | CANNOT_TAKE_LOCK; |
746 | SO_NOT_MAINLINE; |
747 | } |
748 | CONTRACTL_END; |
749 | |
750 | return (CORProfilerPresent() && |
751 | ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS)); |
752 | } |
753 | |
754 | inline BOOL CORProfilerDisableTieredCompilation() |
755 | { |
756 | CONTRACTL |
757 | { |
758 | NOTHROW; |
759 | GC_NOTRIGGER; |
760 | CANNOT_TAKE_LOCK; |
761 | SO_NOT_MAINLINE; |
762 | } |
763 | CONTRACTL_END; |
764 | |
765 | |
766 | return (CORProfilerPresent() && |
767 | ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_DISABLE_TIERED_COMPILATION)); |
768 | } |
769 | |
770 | #if defined(PROFILING_SUPPORTED) && !defined(CROSSGEN_COMPILE) |
771 | |
772 | #if defined(FEATURE_PROFAPI_ATTACH_DETACH) |
773 | |
774 | //--------------------------------------------------------------------------------------- |
775 | // When EE calls into the profiler, an EvacuationCounterHolder object is instantiated on |
776 | // the stack to increment the evacuation counter inside the EE Thread. Upon returning to |
777 | // EE, this EvacuationCounterHolder object when being destroyed decreases the evacuation |
778 | // counter by one. |
779 | // |
780 | // Do not use this object directly. Use BEGIN_PIN_PROFILER / END_PIN_PROFILER defined |
781 | // below. |
782 | // |
783 | // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization. |
784 | // |
785 | typedef Wrapper<Thread *, ProfilingAPIUtility::IncEvacuationCounter, ProfilingAPIUtility::DecEvacuationCounter, |
786 | (UINT_PTR)0, CompareDefault<Thread *>, HSV_NoValidation> EvacuationCounterHolder; |
787 | |
788 | |
789 | //--------------------------------------------------------------------------------------- |
790 | // These macros must be placed around any access to g_profControlBlock.pProfInterface by |
791 | // the EE. Example: |
792 | // { |
793 | // BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads()); |
794 | // g_profControlBlock.pProfInterface->AppDomainCreationStarted(MyAppDomainID); |
795 | // END_PIN_PROFILER(); |
796 | // } |
797 | // The parameter to the BEGIN_PIN_PROFILER is the condition you want to check for, to |
798 | // determine whether the profiler is loaded and requesting the callback you're about to |
799 | // issue. Typically, this will be a call to one of the inline functions in |
800 | // profilepriv.inl. If the condition is true, the macro will increment an evacuation |
801 | // counter that effectively pins the profiler, recheck the condition, and (if still |
802 | // true), execute whatever code you place inside the BEGIN/END_PIN_PROFILER block. If |
803 | // your condition is more complex than a simple profiler status check, then place the |
804 | // profiler status check as parameter to the macro, and add a separate if inside the |
805 | // block. Example: |
806 | // |
807 | // { |
808 | // BEGIN_PIN_PROFILER(CORProfilerTrackTransitions()); |
809 | // if (!pNSL->pMD->IsQCall()) |
810 | // { |
811 | // g_profControlBlock.pProfInterface-> |
812 | // ManagedToUnmanagedTransition((FunctionID) pNSL->pMD, |
813 | // COR_PRF_TRANSITION_CALL); |
814 | // } |
815 | // END_PIN_PROFILER(); |
816 | // } |
817 | // |
818 | // This ensures that the extra condition check (in this case "if |
819 | // (!pNSL->pMD->IsQCall())") is only evaluated if the profiler is loaded. That way, we're |
820 | // not executing extra, unnecessary instructions when no profiler is present. |
821 | // |
822 | // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization |
823 | // for more details about how the synchronization works. |
824 | #define BEGIN_PIN_PROFILER(condition) \ |
825 | /* Do a cheap check of the condition (dirty-read) */ \ |
826 | if (condition) \ |
827 | { \ |
828 | EvacuationCounterHolder __evacuationCounter(GetThreadNULLOk()); \ |
829 | /* Now that the evacuation counter is incremented, the condition re-check */ \ |
830 | /* below is a clean read. There's no MemoryBarrier() here, but that's ok */ \ |
831 | /* as writes to the profiler status force a FlushStoreBuffers(). */ \ |
832 | if (condition) \ |
833 | { |
834 | #define END_PIN_PROFILER() } } |
835 | |
836 | #else // FEATURE_PROFAPI_ATTACH_DETACH |
837 | |
838 | // For builds that include profiling but not attach / detach (e.g., Silverlight 2), the |
839 | // *PIN_PROFILER macros should just check the condition without using the evacuation |
840 | // counters. |
841 | |
842 | #define BEGIN_PIN_PROFILER(condition) if (condition) { |
843 | #define END_PIN_PROFILER() } |
844 | |
845 | #endif // FEATURE_PROFAPI_ATTACH_DETACH |
846 | |
847 | #else // PROFILING_SUPPORTED && !CROSSGEN_COMPILE |
848 | |
849 | // Profiling feature not supported |
850 | |
851 | #define BEGIN_PIN_PROFILER(condition) if (false) { |
852 | #define END_PIN_PROFILER() } |
853 | |
854 | #endif // PROFILING_SUPPORTED && !CROSSGEN_COMPILE |
855 | |
856 | #endif // _ProfilePriv_inl_ |
857 | |
858 | |