Avoid stack walk as specified in the exclusion list
authorAndrew Au <andrewau@microsoft.com>
Mon, 18 Mar 2019 22:19:45 +0000 (15:19 -0700)
committerAndrew Au <cshung@gmail.com>
Thu, 21 Mar 2019 21:11:06 +0000 (17:11 -0400)
Commit migrated from https://github.com/dotnet/coreclr/commit/a7c9ca110096c27de23f045cd176c2109d0676d9

src/coreclr/build.cmd
src/coreclr/build.sh
src/coreclr/src/scripts/genEtwProvider.py
src/coreclr/src/scripts/genEventPipe.py
src/coreclr/src/scripts/utilities.py
src/coreclr/src/vm/eventpipeeventsource.cpp
src/coreclr/src/vm/eventpipeinternal.cpp
src/coreclr/src/vm/eventpipeprovider.cpp
src/coreclr/src/vm/eventpipeprovider.h

index 3617b1b..1502783 100644 (file)
@@ -426,7 +426,7 @@ if %__BuildNative% EQU 1 (
     "!PYTHON!" -B -Wall  %__SourceDir%\scripts\genEventing.py --inc %__IntermediatesIncDir% --dummy %__IntermediatesIncDir%\etmdummy.h --man %__SourceDir%\vm\ClrEtwAll.man --nonextern --noxplatheader|| exit /b 1
 
     echo %__MsgPrefix%Laying out dynamically generated EventPipe Implementation
-    "!PYTHON!" -B -Wall %__SourceDir%\scripts\genEventPipe.py --man %__SourceDir%\vm\ClrEtwAll.man --intermediate %__IntermediatesEventingDir%\eventpipe --nonextern || exit /b 1
+    "!PYTHON!" -B -Wall %__SourceDir%\scripts\genEventPipe.py --man %__SourceDir%\vm\ClrEtwAll.man --exc %__SourceDir%\vm\ClrEtwAllMeta.lst --intermediate %__IntermediatesEventingDir%\eventpipe --nonextern || exit /b 1
 
     echo %__MsgPrefix%Laying out ETW event logging interface
     "!PYTHON!" -B -Wall %__SourceDir%\scripts\genEtwProvider.py --man %__SourceDir%\vm\ClrEtwAll.man --intermediate %__IntermediatesIncDir% --exc %__SourceDir%\vm\ClrEtwAllMeta.lst || exit /b 1
@@ -448,7 +448,7 @@ if %__BuildCrossArchNative% EQU 1 (
     "!PYTHON!" -B -Wall  %__SourceDir%\scripts\genEventing.py --inc !__CrossCompIntermediatesIncDir! --dummy !__CrossCompIntermediatesIncDir!\etmdummy.h --man %__SourceDir%\vm\ClrEtwAll.man --nonextern || exit /b 1
 
     echo %__MsgPrefix%Laying out dynamically generated EventPipe Implementation
-    "!PYTHON!" -B -Wall %__SourceDir%\scripts\genEventPipe.py --man %__SourceDir%\vm\ClrEtwAll.man --intermediate !__CrossCompIntermediatesEventingDir!\eventpipe --nonextern || exit /b 1
+    "!PYTHON!" -B -Wall %__SourceDir%\scripts\genEventPipe.py --man %__SourceDir%\vm\ClrEtwAll.man --exc %__SourceDir%\vm\ClrEtwAllMeta.lst --intermediate !__CrossCompIntermediatesEventingDir!\eventpipe --nonextern || exit /b 1
 
     echo %__MsgPrefix%Laying out dynamically generated EventSource classes
     "!PYTHON!" -B -Wall %__SourceDir%\scripts\genRuntimeEventSources.py --man %__SourceDir%\vm\ClrEtwAll.man --intermediate !__CrossCompIntermediatesEventingDir! || exit /b 1
index 7e9ce99..a24bd89 100755 (executable)
@@ -188,7 +188,7 @@ generate_event_logging_sources()
     fi
 
     echo "Laying out dynamically generated EventPipe Implementation"
-    $PYTHON -B $__PythonWarningFlags "$__ProjectRoot/src/scripts/genEventPipe.py" --man "$__ProjectRoot/src/vm/ClrEtwAll.man" --intermediate "$__OutputEventingDir/eventpipe"
+    $PYTHON -B $__PythonWarningFlags "$__ProjectRoot/src/scripts/genEventPipe.py" --man "$__ProjectRoot/src/vm/ClrEtwAll.man" --exc "$__ProjectRoot/src/vm/ClrEtwAllMeta.lst" --intermediate "$__OutputEventingDir/eventpipe"
 
     echo "Laying out dynamically generated EventSource classes"
     $PYTHON -B $__PythonWarningFlags "$__ProjectRoot/src/scripts/genRuntimeEventSources.py" --man "$__ProjectRoot/src/vm/ClrEtwAll.man" --intermediate "$__OutputEventingDir"
index 79a286a..89d3119 100644 (file)
@@ -14,7 +14,7 @@ import argparse
 import subprocess
 import xml.dom.minidom as DOM
 from genEventing import parseTemplateNodes
-from utilities import open_for_update, update_directory
+from utilities import open_for_update, update_directory, parseExclusionList
 
 macroheader_filename = "etwmacros.h"
 mcheader_filename = "ClrEtwAll.h"
@@ -102,59 +102,12 @@ def genXplatHeader(intermediate):
 #endif //_CLR_XPLAT_EVENTS_H_
 """.format(etw_dirname, macroheader_filename, mcheader_filename))
 
-
-class EventExclusions:
-    def __init__(self):
-        self.nostack         = set()
-        self.explicitstack   = set()
-        self.noclrinstance   = set()
-
-def parseExclusionList(exclusion_filename):
-    with open(exclusion_filename,'r') as ExclusionFile:
-        exclusionInfo   = EventExclusions()
-
-        for line in ExclusionFile:
-            line = line.strip()
-
-            #remove comments
-            if not line or line.startswith('#'):
-                continue
-
-            tokens = line.split(':')
-            #entries starting with nomac are ignored
-            if "nomac" in tokens:
-                continue
-
-            if len(tokens) > 5:
-                raise Exception("Invalid Entry " + line + "in "+ exclusion_filename)
-
-            eventProvider = tokens[2]
-            eventTask     = tokens[1]
-            eventSymbol   = tokens[4]
-
-            if eventProvider == '':
-                eventProvider = "*"
-            if eventTask     == '':
-                eventTask     = "*"
-            if eventSymbol   == '':
-                eventSymbol   = "*"
-            entry = eventProvider + ":" + eventTask + ":" + eventSymbol
-
-            if tokens[0].lower() == "nostack":
-                exclusionInfo.nostack.add(entry)
-            if tokens[0].lower() == "stack":
-                exclusionInfo.explicitstack.add(entry)
-            if tokens[0].lower() == "noclrinstanceid":
-                exclusionInfo.noclrinstance.add(entry)
-
-    return exclusionInfo
-
 def getStackWalkBit(eventProvider, taskName, eventSymbol, stackSet):
     for entry in stackSet:
         tokens = entry.split(':')
 
         if len(tokens) != 3:
-            raise Exception("Error, possible error in the script which introduced the enrty "+ entry)
+            raise Exception("Error, possible error in the script which introduced the entry "+ entry)
 
         eventCond  = tokens[0] == eventProvider or tokens[0] == "*"
         taskCond   = tokens[1] == taskName      or tokens[1] == "*"
@@ -164,7 +117,7 @@ def getStackWalkBit(eventProvider, taskName, eventSymbol, stackSet):
             return False
     return True
 
-#Add the miscelaneous checks here
+#Add the miscellaneous checks here
 def checkConsistency(manifest, exclusion_filename):
     tree                      = DOM.parse(manifest)
     exclusionInfo = parseExclusionList(exclusion_filename)
index 59f5d71..f66b54e 100644 (file)
@@ -3,7 +3,7 @@ from genEventing import *
 from genLttngProvider import *
 import os
 import xml.dom.minidom as DOM
-from utilities import open_for_update
+from utilities import open_for_update, parseExclusionList
 
 stdprolog_cpp = """// Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
@@ -73,7 +73,7 @@ def generateMethodSignatureWrite(eventName, template, extern):
     return ''.join(sig_pieces)
 
 def generateClrEventPipeWriteEventsImpl(
-        providerName, eventNodes, allTemplates, extern):
+        providerName, eventNodes, allTemplates, extern, exclusionList):
     providerPrettyName = providerName.replace("Windows-", '')
     providerPrettyName = providerPrettyName.replace("Microsoft-", '')
     providerPrettyName = providerPrettyName.replace('-', '_')
@@ -153,8 +153,14 @@ def generateClrEventPipeWriteEventsImpl(
         eventLevel = eventLevel.replace("win:", "EventPipeEventLevel::")
         taskName = eventNode.getAttribute('task')
 
-        initEvent = """    EventPipeEvent%s = EventPipeProvider%s->AddEvent(%s,%s,%s,%s);
-""" % (eventName, providerPrettyName, eventValue, eventKeywordsMask, eventVersion, eventLevel)
+        needStack = "true"
+        for nostackentry in exclusionList.nostack:
+            tokens = nostackentry.split(':')
+            if tokens[2] == eventName:
+                needStack = "false"
+
+        initEvent = """    EventPipeEvent%s = EventPipeProvider%s->AddEvent(%s,%s,%s,%s,%s);
+""" % (eventName, providerPrettyName, eventValue, eventKeywordsMask, eventVersion, eventLevel, needStack)
 
         WriteEventImpl.append(initEvent)
     WriteEventImpl.append("}")
@@ -384,7 +390,7 @@ bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size,
     helper.close()
 
 def generateEventPipeImplFiles(
-        etwmanifest, eventpipe_directory, extern):
+        etwmanifest, eventpipe_directory, extern, exclusionList):
     tree = DOM.parse(etwmanifest)
 
     # Find the src directory starting with the assumption that
@@ -460,11 +466,12 @@ bool WriteToBuffer(const T &value, char *&buffer, size_t& offset, size_t& size,
                     providerName,
                     eventNodes,
                     allTemplates,
-                    extern) + "\n")
+                    extern,
+                    exclusionList) + "\n")
 
 
 def generateEventPipeFiles(
-        etwmanifest, intermediate, extern):
+        etwmanifest, intermediate, extern, exclusionList):
     eventpipe_directory = os.path.join(intermediate, eventpipe_dirname)
     tree = DOM.parse(etwmanifest)
 
@@ -487,7 +494,8 @@ def generateEventPipeFiles(
     generateEventPipeImplFiles(
         etwmanifest,
         eventpipe_directory,
-        extern
+        extern,
+        exclusionList
     )
 
 import argparse
@@ -502,6 +510,8 @@ def main(argv):
     required = parser.add_argument_group('required arguments')
     required.add_argument('--man', type=str, required=True,
                           help='full path to manifest containig the description of events')
+    required.add_argument('--exc',  type=str, required=True,
+                                    help='full path to exclusion list')
     required.add_argument('--intermediate', type=str, required=True,
                           help='full path to eventprovider  intermediate directory')
     required.add_argument('--nonextern', action='store_true',
@@ -512,10 +522,11 @@ def main(argv):
         return 1
 
     sClrEtwAllMan = args.man
+    exclusion_filename = args.exc
     intermediate = args.intermediate
     extern = not args.nonextern
 
-    generateEventPipeFiles(sClrEtwAllMan, intermediate, extern)
+    generateEventPipeFiles(sClrEtwAllMan, intermediate, extern, parseExclusionList(exclusion_filename))
 
 if __name__ == '__main__':
     return_code = main(sys.argv[1:])
index 7e69f46..c4767a4 100644 (file)
@@ -120,3 +120,49 @@ def update_directory(srcpath, dstpath, recursive=True, destructive=True, shallow
             if not os.path.exists(dstdir):
                 os.makedirs(dstdir)
             update_directory(srcdir, dstdir, recursive, destructive, shallow)
+
+class EventExclusions:
+    def __init__(self):
+        self.nostack         = set()
+        self.explicitstack   = set()
+        self.noclrinstance   = set()
+
+def parseExclusionList(exclusion_filename):
+    with open(exclusion_filename,'r') as ExclusionFile:
+        exclusionInfo   = EventExclusions()
+
+        for line in ExclusionFile:
+            line = line.strip()
+
+            #remove comments
+            if not line or line.startswith('#'):
+                continue
+
+            tokens = line.split(':')
+            #entries starting with nomac are ignored
+            if "nomac" in tokens:
+                continue
+
+            if len(tokens) > 5:
+                raise Exception("Invalid Entry " + line + "in "+ exclusion_filename)
+
+            eventProvider = tokens[2]
+            eventTask     = tokens[1]
+            eventSymbol   = tokens[4]
+
+            if eventProvider == '':
+                eventProvider = "*"
+            if eventTask     == '':
+                eventTask     = "*"
+            if eventSymbol   == '':
+                eventSymbol   = "*"
+            entry = eventProvider + ":" + eventTask + ":" + eventSymbol
+
+            if tokens[0].lower() == "nostack":
+                exclusionInfo.nostack.add(entry)
+            if tokens[0].lower() == "stack":
+                exclusionInfo.explicitstack.add(entry)
+            if tokens[0].lower() == "noclrinstanceid":
+                exclusionInfo.noclrinstance.add(entry)
+
+    return exclusionInfo
\ No newline at end of file
index 20613b8..ca62677 100644 (file)
@@ -51,6 +51,7 @@ EventPipeEventSource::EventPipeEventSource()
         0,      /* keywords */
         0,      /* eventVersion */
         EventPipeEventLevel::LogAlways,
+        false,  /* needStack */
         pMetadata,
         (unsigned int)metadataLength);
 
index c02317f..30a1464 100644 (file)
@@ -110,7 +110,7 @@ INT_PTR QCALLTYPE EventPipeInternal::DefineEvent(
 
     _ASSERTE(provHandle != NULL);
     EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider *>(provHandle);
-    pEvent = pProvider->AddEvent(eventID, keywords, eventVersion, (EventPipeEventLevel)level, (BYTE *)pMetadata, metadataLength);
+    pEvent = pProvider->AddEvent(eventID, keywords, eventVersion, (EventPipeEventLevel)level, /* needStack = */ true, (BYTE *)pMetadata, metadataLength);
     _ASSERTE(pEvent != NULL);
 
     END_QCALL;
index 4630c93..4c6eabc 100644 (file)
@@ -130,19 +130,6 @@ void EventPipeProvider::SetConfiguration(bool providerEnabled, INT64 keywords, E
     InvokeCallback(pFilterData);
 }
 
-EventPipeEvent* EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, BYTE *pMetadata, unsigned int metadataLength)
-{
-    CONTRACTL
-    {
-        THROWS;
-        GC_NOTRIGGER;
-        MODE_ANY;
-    }
-    CONTRACTL_END;
-
-    return AddEvent(eventID, keywords, eventVersion, level, true /* needStack */, pMetadata, metadataLength);
-}
-
 EventPipeEvent* EventPipeProvider::AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata, unsigned int metadataLength)
 {
     CONTRACTL
index cf89cf3..8ae57d9 100644 (file)
@@ -70,17 +70,10 @@ public:
     bool EventEnabled(INT64 keywords, EventPipeEventLevel eventLevel) const;
 
     // Create a new event.
-    EventPipeEvent* AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, BYTE *pMetadata = NULL, unsigned int metadataLength = 0);
+    EventPipeEvent* AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata = NULL, unsigned int metadataLength = 0);
 
 private:
 
-    // Create a new event, but allow needStack to be specified.
-    // In general, we want stack walking to be controlled by the consumer and not the producer of events.
-    // However, there are a couple of cases that we know we don't want to do a stackwalk that would affect performance significantly:
-    // 1. Sample profiler events: The sample profiler already does a stack walk of the target thread.  Doing one of the sampler thread is a waste.
-    // 2. Metadata events: These aren't as painful but because we have to keep this functionality around, might as well use it.
-    EventPipeEvent* AddEvent(unsigned int eventID, INT64 keywords, unsigned int eventVersion, EventPipeEventLevel level, bool needStack, BYTE *pMetadata = NULL, unsigned int metadataLength = 0);
-
     // Add an event to the provider.
     void AddEvent(EventPipeEvent &event);