// pack the argv data and emit the event using TraceEvent internal unsafe override uint EventWrite(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level, int argc, EventData *argv) { ClassicEtw.EVENT_HEADER header; header.Header.ClientContext = 0; header.Header.Flags = ClassicEtw.WNODE_FLAG_TRACED_GUID | ClassicEtw.WNODE_FLAG_USE_MOF_PTR; header.Header.Guid = EventTrace.GetGuidForEvent(eventID); header.Header.Level = (byte)level; header.Header.Type = (byte)EventTrace.GetOpcodeForEvent(eventID); header.Header.Version = (ushort)EventTrace.GetVersionForEvent(eventID); // Extra copy on XP to move argv to the end of the EVENT_HEADER EventData *eventData = &header.Data; if (argc > ClassicEtw.MAX_MOF_FIELDS) { // Data will be lost on XP argc = ClassicEtw.MAX_MOF_FIELDS; } header.Header.Size = (ushort)(argc * sizeof(EventData) + 48); for (int x = 0; x < argc; x++) { eventData[x].Ptr = argv[x].Ptr; eventData[x].Size = argv[x].Size; } return(ClassicEtw.TraceEvent(_traceHandle, &header)); }
internal bool IsEnabled(EventTrace.Keyword keyword, EventTrace.Level level) { return(_enabled && (level <= _level) && (keyword & _keywords) != 0 && (keyword & _matchAllKeyword) == _matchAllKeyword); }
internal unsafe override uint EventWrite(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level, int argc, EventData *argv) { ManifestEtw.EventDescriptor eventDescriptor; eventDescriptor.Id = (ushort)eventID; eventDescriptor.Version = EventTrace.GetVersionForEvent(eventID); eventDescriptor.Channel = 0x10; // Since Channel isn't supported on XP we only use a single default channel. eventDescriptor.Level = (byte)level; eventDescriptor.Opcode = EventTrace.GetOpcodeForEvent(eventID); eventDescriptor.Task = EventTrace.GetTaskForEvent(eventID); eventDescriptor.Keywords = (long)keywords; if (argc == 0) { argv = null; } return(ManifestEtw.EventWrite(_registrationHandle.Value, ref eventDescriptor, (uint)argc, argv)); }
// Optimization for 0-1 arguments internal unsafe uint TraceEvent(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level, object eventData) { // It is the responsibility of the caller to check that flags/keywords are enabled before calling this method Debug.Assert(IsEnabled(keywords, level)); uint status = 0; int argCount = 0; EventData userData; userData.Size = 0; string dataString = null; byte * dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize]; if (eventData != null) { dataString = EncodeObject(ref eventData, &userData, dataBuffer); argCount = 1; } if (userData.Size > s_traceEventMaximumSize) { return(ErrorEventTooBig); } if (dataString != null) { fixed(char *pdata = dataString) { userData.Ptr = (ulong)pdata; status = EventWrite(eventID, keywords, level, argCount, &userData); } } else { status = EventWrite(eventID, keywords, level, argCount, &userData); } return(status); }
/// <summary> /// Tells ContextLayoutManager to finalize possibly async update. /// Used before accessing services off Visual. /// </summary> //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking internal void UpdateLayout() { VerifyAccess(); //make UpdateLayout to be a NOP if called during UpdateLayout. if (_isInUpdateLayout || _measuresOnStack > 0 || _arrangesOnStack > 0 || _isDead) { return; } #if DEBUG_CLR_MEM bool clrTracingEnabled = false; // Start over with the Measure and arrange counters for this layout pass int measureCLRPass = 0; int arrangeCLRPass = 0; if (CLRProfilerControl.ProcessIsUnderCLRProfiler) { clrTracingEnabled = true; if (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance) { ++_layoutCLRPass; CLRProfilerControl.CLRLogWriteLine("Begin_Layout_{0}", _layoutCLRPass); } } #endif // DEBUG_CLR_MEM bool etwTracingEnabled = false; long perfElementID = 0; const EventTrace.Keyword etwKeywords = EventTrace.Keyword.KeywordLayout | EventTrace.Keyword.KeywordPerf; if (!_isUpdating && EventTrace.IsEnabled(etwKeywords, EventTrace.Level.Info)) { etwTracingEnabled = true; perfElementID = PerfService.GetPerfElementID(this); EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutBegin, etwKeywords, EventTrace.Level.Info, perfElementID, EventTrace.LayoutSource.LayoutManager); } int cnt = 0; bool gotException = true; UIElement currentElement = null; try { invalidateTreeIfRecovering(); while (hasDirtiness || _firePostLayoutEvents) { if (++cnt > 153) { //loop detected. Lets go over to background to let input/user to correct the situation. //most frequently, we get such a loop as a result of input detecting a mouse in the "bad spot" //and some event handler oscillating a layout-affecting property depending on hittest result //of the mouse. Going over to background will not break the loopp but will allow user to //move the mouse so that it goes out of the "bad spot". Dispatcher.BeginInvoke(DispatcherPriority.Background, _updateLayoutBackground, this); currentElement = null; gotException = false; if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutAbort, etwKeywords, EventTrace.Level.Info, 0, cnt); } return; } //this flag stops posting update requests to MediaContext - we are already in one //note that _isInUpdateLayout is close but different - _isInUpdateLayout is reset //before firing LayoutUpdated so that event handlers could call UpdateLayout but //still could not cause posting of MediaContext work item. Posting MediaContext workitem //causes infinite loop in MediaContext. _isUpdating = true; _isInUpdateLayout = true; #if DEBUG_CLR_MEM if (clrTracingEnabled && (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Verbose)) { ++measureCLRPass; CLRProfilerControl.CLRLogWriteLine("Begin_Measure_{0}_{1}", _layoutCLRPass, measureCLRPass); } #endif // DEBUG_CLR_MEM if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureBegin, etwKeywords, EventTrace.Level.Info, perfElementID); } // Disable processing of the queue during blocking operations to prevent unrelated reentrancy. using (Dispatcher.DisableProcessing()) { //loop for Measure //We limit the number of loops here by time - normally, all layout //calculations should be done by this time, this limit is here for //emergency, "infinite loop" scenarios - yielding in this case will //provide user with ability to continue to interact with the app, even though //it will be sluggish. If we don't yield here, the loop is goign to be a deadly one //and it will be impossible to save results or even close the window. int loopCounter = 0; DateTime loopStartTime = new DateTime(0); while (true) { if (++loopCounter > 153) { loopCounter = 0; //first bunch of iterations is free, then we start count time //this way, we don't call DateTime.Now in most layout updates if (loopStartTime.Ticks == 0) { loopStartTime = DateTime.UtcNow; } else { TimeSpan loopDuration = (DateTime.UtcNow - loopStartTime); if (loopDuration.Milliseconds > 153 * 2) // 153*2 = magic*science { //loop detected. Lets go over to background to let input work. Dispatcher.BeginInvoke(DispatcherPriority.Background, _updateLayoutBackground, this); currentElement = null; gotException = false; if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureAbort, etwKeywords, EventTrace.Level.Info, loopDuration.Milliseconds, loopCounter); } return; } } } currentElement = MeasureQueue.GetTopMost(); if (currentElement == null) { break; //exit if no more Measure candidates } currentElement.Measure(currentElement.PreviousConstraint); //dmitryt, } if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureEnd, etwKeywords, EventTrace.Level.Info, loopCounter); EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeBegin, etwKeywords, EventTrace.Level.Info, perfElementID); } #if DEBUG_CLR_MEM if (clrTracingEnabled && (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Verbose)) { CLRProfilerControl.CLRLogWriteLine("End_Measure_{0}_{1}", _layoutCLRPass, measureCLRPass); ++arrangeCLRPass; CLRProfilerControl.CLRLogWriteLine("Begin_Arrange_{0}_{1}", _layoutCLRPass, arrangeCLRPass); } #endif // DEBUG_CLR_MEM //loop for Arrange //if Arrange dirtied the tree go clean it again //We limit the number of loops here by time - normally, all layout //calculations should be done by this time, this limit is here for //emergency, "infinite loop" scenarios - yielding in this case will //provide user with ability to continue to interact with the app, even though //it will be sluggish. If we don't yield here, the loop is goign to be a deadly one //and it will be impossible to save results or even close the window. loopCounter = 0; loopStartTime = new DateTime(0); while (MeasureQueue.IsEmpty) { if (++loopCounter > 153) { loopCounter = 0; //first bunch of iterations is free, then we start count time //this way, we don't call DateTime.Now in most layout updates if (loopStartTime.Ticks == 0) { loopStartTime = DateTime.UtcNow; } else { TimeSpan loopDuration = (DateTime.UtcNow - loopStartTime); if (loopDuration.Milliseconds > 153 * 2) // 153*2 = magic*science { //loop detected. Lets go over to background to let input work. Dispatcher.BeginInvoke(DispatcherPriority.Background, _updateLayoutBackground, this); currentElement = null; gotException = false; if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeAbort, etwKeywords, EventTrace.Level.Info, loopDuration.Milliseconds, loopCounter); } return; } } } currentElement = ArrangeQueue.GetTopMost(); if (currentElement == null) { break; //exit if no more Measure candidates } Rect finalRect = getProperArrangeRect(currentElement); currentElement.Arrange(finalRect); //dmitryt, } if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeEnd, etwKeywords, EventTrace.Level.Info, loopCounter); } #if DEBUG_CLR_MEM if (clrTracingEnabled && (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Verbose)) { CLRProfilerControl.CLRLogWriteLine("End_Arrange_{0}_{1}", _layoutCLRPass, arrangeCLRPass); } #endif // DEBUG_CLR_MEM //if Arrange dirtied the tree go clean it again //it is not neccesary to check ArrangeQueue sicnce we just exited from Arrange loop if (!MeasureQueue.IsEmpty) { continue; } //let LayoutUpdated handlers to call UpdateLayout //note that it means we can get reentrancy into UpdateLayout past this point, //if any of event handlers call UpdateLayout sync. Need to protect from reentrancy //in the firing methods below. _isInUpdateLayout = false; } fireSizeChangedEvents(); if (hasDirtiness) { continue; } fireLayoutUpdateEvent(); if (hasDirtiness) { continue; } fireAutomationEvents(); if (hasDirtiness) { continue; } fireSizeChangedEvents(); // if nothing is dirty, one last chance for any size changes to announce. } currentElement = null; gotException = false; } finally { _isUpdating = false; _layoutRequestPosted = false; _isInUpdateLayout = false; if (gotException) { if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutException, etwKeywords, EventTrace.Level.Info, PerfService.GetPerfElementID(currentElement)); } //set indicator _gotException = true; _forceLayoutElement = currentElement; //make attempt to request the subsequent layout calc //some exception handler schemas use Idle priorities to //wait until dust settles. Then they correct the issue noted in the exception handler. //We don't want to attempt to re-do the operation on the priority higher then that. Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, _updateLayoutBackground, this); } } MS.Internal.Text.TextInterface.Font.ResetFontFaceCache(); MS.Internal.FontCache.BufferCache.Reset(); if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutEnd, etwKeywords, EventTrace.Level.Info); } #if DEBUG_CLR_MEM if (clrTracingEnabled && (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance)) { CLRProfilerControl.CLRLogWriteLine("End_Layout_{0}", _layoutCLRPass); } #endif // DEBUG_CLR_MEM }
internal uint TraceEvent(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level) { // Optimization for 0-1 arguments return(TraceEvent(eventID, keywords, level, (object)null)); }
internal unsafe abstract uint EventWrite(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level, int argc, EventData *argv);
internal unsafe uint TraceEvent(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level, params object[] eventPayload) { // It is the responsibility of the caller to check that flags/keywords are enabled before calling this method Debug.Assert(IsEnabled(keywords, level)); int argCount = eventPayload.Length; Debug.Assert(argCount <= s_etwMaxNumberArguments); uint totalEventSize = 0; int stringIndex = 0; int[] stringPosition = new int[s_etwAPIMaxStringCount]; string [] dataString = new string[s_etwAPIMaxStringCount]; EventData *userData = stackalloc EventData[argCount]; EventData *userDataPtr = userData; byte * dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * argCount]; byte * currentBuffer = dataBuffer; for (int index = 0; index < argCount; index++) { if (eventPayload[index] != null) { string isString = EncodeObject(ref eventPayload[index], userDataPtr, currentBuffer); currentBuffer += s_basicTypeAllocationBufferSize; totalEventSize = userDataPtr->Size; userDataPtr++; if (isString != null) { Debug.Assert(stringIndex < s_etwAPIMaxStringCount); // need to increase string count or emit fewer strings dataString[stringIndex] = isString; stringPosition[stringIndex] = index; stringIndex++; } } } if (totalEventSize > s_traceEventMaximumSize) { return(ErrorEventTooBig); } fixed(char *s0 = dataString[0], s1 = dataString[1], s2 = dataString[2], s3 = dataString[3], s4 = dataString[4], s5 = dataString[5], s6 = dataString[6], s7 = dataString[7]) { userDataPtr = userData; if (dataString[0] != null) { userDataPtr[stringPosition[0]].Ptr = (ulong)s0; } if (dataString[1] != null) { userDataPtr[stringPosition[1]].Ptr = (ulong)s1; } if (dataString[2] != null) { userDataPtr[stringPosition[2]].Ptr = (ulong)s2; } if (dataString[3] != null) { userDataPtr[stringPosition[3]].Ptr = (ulong)s3; } if (dataString[4] != null) { userDataPtr[stringPosition[4]].Ptr = (ulong)s4; } if (dataString[5] != null) { userDataPtr[stringPosition[5]].Ptr = (ulong)s5; } if (dataString[6] != null) { userDataPtr[stringPosition[6]].Ptr = (ulong)s6; } if (dataString[7] != null) { userDataPtr[stringPosition[7]].Ptr = (ulong)s7; } return(EventWrite(eventID, keywords, level, argCount, userData)); } }