Пример #1
0
        // 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));
        }
Пример #2
0
 internal bool IsEnabled(EventTrace.Keyword keyword, EventTrace.Level level)
 {
     return(_enabled &&
            (level <= _level) &&
            (keyword & _keywords) != 0 &&
            (keyword & _matchAllKeyword) == _matchAllKeyword);
 }
Пример #3
0
        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));
        }
Пример #4
0
        // 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);
        }
Пример #5
0
        /// <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
        }
Пример #6
0
 internal uint TraceEvent(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level)
 {
     // Optimization for 0-1 arguments
     return(TraceEvent(eventID, keywords, level, (object)null));
 }
Пример #7
0
 internal unsafe abstract uint EventWrite(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level, int argc, EventData *argv);
Пример #8
0
        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));
            }
        }