|
53 | 53 | // following format:
|
54 | 54 | // {
|
55 | 55 | // BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads());
|
56 |
| -// g_profControlBlock.pProfInterface->AppDomainCreationStarted(MyAppDomainID); |
| 56 | +// // call the ProfControlBlock callback wrapper |
| 57 | +// (&g_profControlBlock)->AppDomainCreationStarted(MyAppDomainID); |
57 | 58 | // END_PROFILER_CALLBACK();
|
58 | 59 | // }
|
59 |
| -// The BEGIN / END macros do the following: |
60 |
| -// * Evaluate the expression argument (e.g., CORProfilerTrackAppDomainLoads()). This is a |
| 60 | +// The BEGIN / END macros evaluates the expression argument (CORProfiler*). This is a |
61 | 61 | // "dirty read" as the profiler could be detached at any moment during or after that
|
62 | 62 | // evaluation.
|
63 |
| -// * If true, push a code:EvacuationCounterHolder on the stack, which increments the |
64 |
| -// per-thread evacuation counter (not interlocked). |
65 |
| -// * Re-evaluate the expression argument. This time, it's a "clean read" (see below for |
66 |
| -// why). |
67 |
| -// * If still true, execute the statements inside the BEGIN/END block. Inside that block, |
68 |
| -// the profiler is guaranteed to remain loaded, because the evacuation counter |
69 |
| -// remains nonzero (again, see below). |
70 |
| -// * Once the BEGIN/END block is exited, the evacuation counter is decremented, and the |
71 |
| -// profiler is unpinned and allowed to detach. |
| 63 | +// |
| 64 | +// The ProfControlBlock callback wrappers call DoOneProfilerIteration, doing the following: |
| 65 | +// * Pushes a code:EvacuationCounterHolder on the stack for the ProfilerInfo, which |
| 66 | +// increments the per-thread evacuation counter (not interlocked). |
| 67 | +// * Checks the profiler status (code:ProfilerStatus) to see if the profiler is active. |
| 68 | +// * Evaluates the ProfControlBlock condition func (e.g. IsProfilerTrackingAppDomainLoads). |
| 69 | +// * If true, invokes the callback func (e.g. AppDomainCreationStartedHelper) which in turn |
| 70 | +// calls the EEToProfInterfaceImpl implementation where the profiler is guaranteed to |
| 71 | +// remain loaded, because the evacuation counter remains nonzero (again, see below). |
| 72 | +// * Once the DoOneProfilerIteration block is exited, the evacuation counter is decremented |
| 73 | +// and the profiler is unpinned and allowed to detach. |
72 | 74 | //
|
73 | 75 | // READER / WRITER COORDINATION
|
74 | 76 | //
|
75 |
| -// The above ensures that a reader never touches g_profControlBlock.pProfInterface and |
| 77 | +// The above ensures that a reader never touches EEToProfInterfaceImpl and |
76 | 78 | // all it embodies (including the profiler DLL code and callback implementations) unless
|
77 | 79 | // the reader was able to increment its thread's evacuation counter AND re-verify that
|
78 | 80 | // the profiler's status is still active (the status check is included in the macro's
|
|
0 commit comments