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"
21BOOL CORProfilerBypassSecurityChecks();
22#endif // PROFILING_SUPPORTED
23
24//---------------------------------------------------------------------------------------
25// CurrentProfilerStatus
26//---------------------------------------------------------------------------------------
27
28inline void CurrentProfilerStatus::Init()
29{
30 LIMITED_METHOD_CONTRACT;
31 m_profStatus = kProfStatusNone;
32}
33
34inline ProfilerStatus CurrentProfilerStatus::Get()
35{
36 LIMITED_METHOD_DAC_CONTRACT;
37 return m_profStatus;
38}
39
40//---------------------------------------------------------------------------------------
41// ProfControlBlock
42//---------------------------------------------------------------------------------------
43
44inline 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
76inline 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).
93inline 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
103inline 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
121inline 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
136inline 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
151inline 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
166inline 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
181inline 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
196inline 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
211inline 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
226inline 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
241inline 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
262inline 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
278inline 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
293inline 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
308inline 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
323inline 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
338inline 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
358inline 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
373inline 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
388inline 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
405inline 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
422inline 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
437inline 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
452inline 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
467inline 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
483inline 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
509inline BOOL CORProfilerDisableAllNGenImages()
510{
511 LIMITED_METHOD_DAC_CONTRACT;
512
513 return (CORProfilerPresent() &&
514 ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_ALL_NGEN_IMAGES));
515}
516
517inline 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.
530inline 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
544inline 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
559inline 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
574inline 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
589inline 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
604inline 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
619inline 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
634inline 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
649inline 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
664inline 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
679inline 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
694inline 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
709inline 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
724inline 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
739inline 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
754inline 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//
785typedef 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