summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--build.cmd70
-rwxr-xr-xbuild.sh67
-rw-r--r--clr.coreclr.props10
-rw-r--r--clrdefinitions.cmake4
-rw-r--r--clrfeatures.cmake20
-rw-r--r--dependencies.props2
-rw-r--r--functions.cmake68
-rw-r--r--src/CMakeLists.txt66
-rw-r--r--src/dlls/mscoree/coreclr/CMakeLists.txt46
-rw-r--r--src/mscorlib/System.Private.CoreLib.csproj2
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs15
-rw-r--r--src/pal/src/CMakeLists.txt14
-rw-r--r--src/pal/tests/palsuite/CMakeLists.txt5
-rw-r--r--src/scripts/Utilities.py49
-rw-r--r--src/scripts/check-definitions.py24
-rw-r--r--src/scripts/genDummyProvider.py211
-rw-r--r--src/scripts/genEtwProvider.py312
-rw-r--r--src/scripts/genEventPipe.py313
-rw-r--r--src/scripts/genEventing.py (renamed from src/scripts/genXplatEventing.py)387
-rw-r--r--src/scripts/genLttngProvider.py (renamed from src/scripts/genXplatLttng.py)228
-rw-r--r--src/scripts/genWinEtw.py125
-rw-r--r--src/scripts/utilities.py115
-rw-r--r--src/vm/CMakeLists.txt28
-rw-r--r--src/vm/eventpipe.cpp92
-rw-r--r--src/vm/eventpipe.h34
-rw-r--r--src/vm/eventpipebuffer.cpp6
-rw-r--r--src/vm/eventpipebuffermanager.cpp42
-rw-r--r--src/vm/eventpipeconfiguration.cpp63
-rw-r--r--src/vm/eventpipeevent.cpp8
-rw-r--r--src/vm/eventpipeeventinstance.cpp8
-rw-r--r--src/vm/eventpipefile.cpp10
-rw-r--r--src/vm/eventpipejsonfile.cpp46
-rw-r--r--src/vm/eventpipeprovider.cpp36
-rw-r--r--src/vm/eventpipeprovider.h3
-rw-r--r--src/vm/fastserializer.cpp12
-rw-r--r--src/vm/mscorlib.cpp4
-rw-r--r--src/vm/sampleprofiler.cpp163
-rw-r--r--src/vm/sampleprofiler.h32
-rw-r--r--tests/runtest.proj3
-rw-r--r--tests/src/CoreMangLib/cti/system/convert/convertfrombase64string.cs4
-rw-r--r--tests/src/CoreMangLib/cti/system/string/stringcompare9.cs8
-rw-r--r--tests/src/CoreMangLib/cti/system/string/stringequals6.cs8
-rw-r--r--tests/src/CoreMangLib/cti/system/string/stringindexof10.cs8
-rw-r--r--tests/src/CoreMangLib/cti/system/text/encoding/encodinggetbytes1.cs18
-rw-r--r--tests/src/CoreMangLib/cti/system/text/encoding/encodinggetcharcount.csbin26652 -> 26676 bytes
-rw-r--r--tests/src/CoreMangLib/cti/system/text/encoding/encodinggetchars1.csbin40576 -> 40600 bytes
-rw-r--r--tests/src/CoreMangLib/cti/system/text/encoding/encodinggetstring.csbin26012 -> 26036 bytes
-rw-r--r--tests/src/CoreMangLib/cti/system/timespan/timespantostring_str.cs12
-rw-r--r--tests/src/CoreMangLib/cti/system/uint64/uint64tostring2.cs2
-rwxr-xr-xtests/src/Interop/BestFitMapping/BestFitMapping.csbin66960 -> 66984 bytes
-rw-r--r--tests/src/JIT/config/benchmark+roslyn/benchmark+roslyn.csproj3
-rw-r--r--tests/src/JIT/config/benchmark/benchmark.csproj3
-rw-r--r--tests/src/dirs.proj2
-rw-r--r--tests/src/performance/performance.csproj3
-rw-r--r--tests/src/tracing/common/common.csproj2
-rw-r--r--tests/src/tracing/eventlistener/EventListener.cs77
-rw-r--r--tests/src/tracing/eventlistener/eventlistener.csproj32
-rw-r--r--tests/src/tracing/eventpipesmoke/EventPipeSmoke.cs2
-rw-r--r--tests/src/tracing/eventpipesmoke/eventpipesmoke.csproj2
-rw-r--r--tests/src/tracing/eventpipetrace/EventPipeTrace.cs110
-rw-r--r--tests/src/tracing/eventpipetrace/eventpipetrace.csproj30
-rw-r--r--tests/src/tracing/eventsourcesmoke/EventSourceSmoke.cs2
-rw-r--r--tests/src/tracing/eventsourcetrace/EventSourceTrace.cs131
-rw-r--r--tests/src/tracing/eventsourcetrace/eventsourcetrace.csproj30
65 files changed, 2162 insertions, 1071 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index af69a2a206..0d42deb9c2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,6 +23,7 @@ endif (WIN32)
set(CLR_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(VM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/vm)
set(GENERATED_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/src/inc)
+set(GENERATED_EVENTING_DIR ${CMAKE_CURRENT_BINARY_DIR}/eventing)
set(VERSION_FILE_PATH "${CMAKE_BINARY_DIR}/version.cpp")
set(CORECLR_SET_RPATH ON)
diff --git a/build.cmd b/build.cmd
index fd17ffdf0e..fe389f8ab2 100644
--- a/build.cmd
+++ b/build.cmd
@@ -28,7 +28,7 @@ set __ThisScriptDir="%~dp0"
if defined VisualStudioVersion (
if not defined __VSVersion echo %__MsgPrefix%Detected Visual Studio %VisualStudioVersion% developer command ^prompt environment
goto :Run
-)
+)
echo %__MsgPrefix%Searching ^for Visual Studio 2017 or 2015 installation
set _VSWHERE="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
@@ -294,6 +294,16 @@ if %__EnforcePgo%==1 (
)
)
+REM Determine if this is a cross-arch build
+
+if /i "%__BuildArch%"=="arm64" (
+ set __DoCrossArchBuild=1
+ )
+
+if /i "%__BuildArch%"=="arm" (
+ set __DoCrossArchBuild=1
+ )
+
:: Set the remaining variables based upon the determined build configuration
set "__BinDir=%__RootBinDir%\Product\%__BuildOS%.%__BuildArch%.%__BuildType%"
set "__IntermediatesDir=%__RootBinDir%\obj\%__BuildOS%.%__BuildArch%.%__BuildType%"
@@ -382,6 +392,56 @@ for /f "tokens=*" %%s in ('%DotNetCli% msbuild "%OptDataProjectFilePath%" /t:Dum
REM =========================================================================================
REM ===
+REM === Generate source files for eventing
+REM ===
+REM =========================================================================================
+
+set __IntermediatesIncDir=%__IntermediatesDir%\src\inc
+set __IntermediatesEventingDir=%__IntermediatesDir%\eventing
+
+REM Find python and set it to the variable PYTHON
+echo import sys; sys.stdout.write(sys.executable) | (py -3 || py -2 || python3 || python2 || python) > %TEMP%\pythonlocation.txt 2> NUL
+set /p PYTHON=<%TEMP%\pythonlocation.txt
+
+if /i "%__BuildNative%"=="1" (
+ if NOT DEFINED PYTHON (
+ echo %__MsgPrefix%Error: Could not find a python installation
+ exit /b 1
+ )
+
+ echo %__MsgPrefix%Laying out dynamically generated files consumed by the native build system
+ echo %__MsgPrefix%Laying out dynamically generated Event test files and etmdummy stub functions
+ !PYTHON! -B -Wall %__SourceDir%\scripts\genEventing.py --inc %__IntermediatesIncDir% --dummy %__IntermediatesIncDir%\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 %__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
+)
+
+if /i "%__DoCrossArchBuild%"=="1" (
+ if NOT DEFINED PYTHON (
+ echo %__MsgPrefix%Error: Could not find a python installation
+ exit /b 1
+ )
+
+ set __CrossCompIntermediatesIncDir=%__CrossCompIntermediatesDir%\src\inc
+ set __CrossCompIntermediatesEventingDir=%__CrossCompIntermediatesDir%\eventing
+
+ echo %__MsgPrefix%Laying out dynamically generated files consumed by the crossarch build system
+ echo %__MsgPrefix%Laying out dynamically generated Event test files and etmdummy stub functions
+ !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
+
+ echo %__MsgPrefix%Laying out ETW event logging interface
+ !PYTHON! -B -Wall %__SourceDir%\scripts\genEtwProvider.py --man %__SourceDir%\vm\ClrEtwAll.man --intermediate !__CrossCompIntermediatesIncDir! --exc %__SourceDir%\vm\ClrEtwAllMeta.lst || exit /b 1
+)
+
+REM =========================================================================================
+REM ===
REM === Build the CLR VM
REM ===
REM =========================================================================================
@@ -476,14 +536,6 @@ REM === Build Cross-Architecture Native Components (if applicable)
REM ===
REM =========================================================================================
-if /i "%__BuildArch%"=="arm64" (
- set __DoCrossArchBuild=1
- )
-
-if /i "%__BuildArch%"=="arm" (
- set __DoCrossArchBuild=1
- )
-
if /i "%__DoCrossArchBuild%"=="1" (
REM Scope environment changes start {
setlocal
diff --git a/build.sh b/build.sh
index 415736ab05..f10d5b81fb 100755
--- a/build.sh
+++ b/build.sh
@@ -194,28 +194,9 @@ generate_event_logging_sources()
fi
# Event Logging Infrastructure
- __GeneratedIntermediate="$__IntermediatesDir/Generated"
- __GeneratedIntermediateEventProvider="$__GeneratedIntermediate/eventprovider_new"
- __GeneratedIntermediateEventPipe="$__GeneratedIntermediate/eventpipe_new"
-
- if [[ -d "$__GeneratedIntermediateEventProvider" ]]; then
- rm -rf "$__GeneratedIntermediateEventProvider"
- fi
-
- if [[ -d "$__GeneratedIntermediateEventPipe" ]]; then
- rm -rf "$__GeneratedIntermediateEventPipe"
- fi
-
- if [[ ! -d "$__GeneratedIntermediate/eventprovider" ]]; then
- mkdir -p "$__GeneratedIntermediate/eventprovider"
- fi
-
- if [[ ! -d "$__GeneratedIntermediate/eventpipe" ]]; then
- mkdir -p "$__GeneratedIntermediate/eventpipe"
- fi
-
- mkdir -p "$__GeneratedIntermediateEventProvider"
- mkdir -p "$__GeneratedIntermediateEventPipe"
+ __GeneratedIntermediate="$__IntermediatesDir/eventing"
+ __GeneratedIntermediateEventProvider="$__GeneratedIntermediate/eventprovider"
+ __GeneratedIntermediateEventPipe="$__GeneratedIntermediate/eventpipe"
__PythonWarningFlags="-Wall"
if [[ $__IgnoreWarnings == 0 ]]; then
@@ -225,54 +206,38 @@ generate_event_logging_sources()
if [[ $__SkipCoreCLR == 0 || $__ConfigureOnly == 1 ]]; then
echo "Laying out dynamically generated files consumed by the build system "
- echo "Laying out dynamically generated Event Logging Test files"
- $PYTHON -B $__PythonWarningFlags "$__ProjectRoot/src/scripts/genXplatEventing.py" --man "$__ProjectRoot/src/vm/ClrEtwAll.man" --exc "$__ProjectRoot/src/vm/ClrEtwAllMeta.lst" --testdir "$__GeneratedIntermediateEventProvider/tests"
+ echo "Laying out dynamically generated Event test files, etmdummy stub functions, and external linkages"
+ $PYTHON -B $__PythonWarningFlags "$__ProjectRoot/src/scripts/genEventing.py" --inc $__IntermediatesDir/src/inc --dummy $__IntermediatesDir/src/inc/etmdummy.h --man "$__ProjectRoot/src/vm/ClrEtwAll.man" --testdir "$__GeneratedIntermediateEventProvider/tests"
if [[ $? != 0 ]]; then
exit
fi
- case $__BuildOS in
- Linux|FreeBSD)
- echo "Laying out dynamically generated EventPipe Implementation"
- $PYTHON -B $__PythonWarningFlags "$__ProjectRoot/src/scripts/genEventPipe.py" --man "$__ProjectRoot/src/vm/ClrEtwAll.man" --intermediate "$__GeneratedIntermediateEventPipe" --exc "$__ProjectRoot/src/vm/ClrEtwAllMeta.lst"
- if [[ $? != 0 ]]; then
- exit
- fi
- ;;
- *)
- ;;
- esac
+ echo "Laying out dynamically generated EventPipe Implementation"
+ $PYTHON -B $__PythonWarningFlags "$__ProjectRoot/src/scripts/genEventPipe.py" --man "$__ProjectRoot/src/vm/ClrEtwAll.man" --intermediate "$__GeneratedIntermediateEventPipe"
#determine the logging system
case $__BuildOS in
Linux|FreeBSD)
echo "Laying out dynamically generated Event Logging Implementation of Lttng"
- $PYTHON -B $__PythonWarningFlags "$__ProjectRoot/src/scripts/genXplatLttng.py" --man "$__ProjectRoot/src/vm/ClrEtwAll.man" --intermediate "$__GeneratedIntermediateEventProvider"
+ $PYTHON -B $__PythonWarningFlags "$__ProjectRoot/src/scripts/genLttngProvider.py" --man "$__ProjectRoot/src/vm/ClrEtwAll.man" --intermediate "$__GeneratedIntermediateEventProvider"
if [[ $? != 0 ]]; then
exit
fi
;;
*)
+ echo "Laying out dummy event logging provider"
+ $PYTHON -B $__PythonWarningFlags "$__ProjectRoot/src/scripts/genDummyProvider.py" --man "$__ProjectRoot/src/vm/ClrEtwAll.man" --intermediate "$__GeneratedIntermediateEventProvider"
+ if [[ $? != 0 ]]; then
+ exit
+ fi
;;
esac
- fi
-
- echo "Cleaning the temp folder of dynamically generated Event Logging files"
- $PYTHON -B $__PythonWarningFlags -c "import sys;sys.path.insert(0,\"$__ProjectRoot/src/scripts\"); from Utilities import *;UpdateDirectory(\"$__GeneratedIntermediate/eventprovider\",\"$__GeneratedIntermediateEventProvider\")"
- if [[ $? != 0 ]]; then
- exit
- fi
- rm -rf "$__GeneratedIntermediateEventProvider"
-
- echo "Cleaning the temp folder of dynamically generated EventPipe files"
- $PYTHON -B $__PythonWarningFlags -c "import sys;sys.path.insert(0,\"$__ProjectRoot/src/scripts\"); from Utilities import *;UpdateDirectory(\"$__GeneratedIntermediate/eventpipe\",\"$__GeneratedIntermediateEventPipe\")"
- if [[ $? != 0 ]]; then
- exit
+ if [[ $__CrossBuild == 1 ]]; then
+ cp -r $__GeneratedIntermediate $__CrossCompIntermediatesDir
+ fi
fi
-
- rm -rf "$__GeneratedIntermediateEventPipe"
}
build_native()
diff --git a/clr.coreclr.props b/clr.coreclr.props
index 691365c76c..029ddca4f7 100644
--- a/clr.coreclr.props
+++ b/clr.coreclr.props
@@ -3,6 +3,7 @@
<FeatureEventTrace>true</FeatureEventTrace>
<FeatureICastable>true</FeatureICastable>
<FeatureManagedEtwChannels>true</FeatureManagedEtwChannels>
+ <FeatureManagedEtw>true</FeatureManagedEtw>
<ProfilingSupportedBuild>true</ProfilingSupportedBuild>
</PropertyGroup>
@@ -16,12 +17,12 @@
<FeatureStubsAsIL>true</FeatureStubsAsIL>
<FeatureCoreFxGlobalization>true</FeatureCoreFxGlobalization>
+ <FeaturePerfTracing>true</FeaturePerfTracing>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetsWindows)' == 'true'">
<FeatureArrayStubAsIL Condition="'$(TargetArch)' != 'i386'">true</FeatureArrayStubAsIL>
<FeatureMulticastStubAsIL Condition="'$(TargetArch)' != 'i386'">true</FeatureMulticastStubAsIL>
- <FeatureManagedEtw>true</FeatureManagedEtw>
<FeatureStubsAsIL Condition="'$(TargetArch)' == 'arm64'">true</FeatureStubsAsIL>
<FeatureUseLcid>true</FeatureUseLcid>
<FeatureCominterop>true</FeatureCominterop>
@@ -32,9 +33,4 @@
<FeatureAppX>true</FeatureAppX>
<FeatureWin32Registry>true</FeatureWin32Registry>
</PropertyGroup>
-
- <PropertyGroup Condition="'$(TargetsLinux)' == 'true'">
- <FeatureManagedEtw>true</FeatureManagedEtw>
- <FeaturePerfTracing>true</FeaturePerfTracing>
- </PropertyGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/clrdefinitions.cmake b/clrdefinitions.cmake
index 5e12ca1e05..4216e8ed20 100644
--- a/clrdefinitions.cmake
+++ b/clrdefinitions.cmake
@@ -125,6 +125,7 @@ if(FEATURE_DBGIPC)
endif(FEATURE_DBGIPC)
if(FEATURE_EVENT_TRACE)
add_definitions(-DFEATURE_EVENT_TRACE=1)
+ add_definitions(-DFEATURE_PERFTRACING=1)
endif(FEATURE_EVENT_TRACE)
if(FEATURE_GDBJIT)
add_definitions(-DFEATURE_GDBJIT)
@@ -138,9 +139,6 @@ endif(FEATURE_GDBJIT_LANGID_CS)
if(FEATURE_GDBJIT_SYMTAB)
add_definitions(-DFEATURE_GDBJIT_SYMTAB)
endif(FEATURE_GDBJIT_SYMTAB)
-if(CLR_CMAKE_PLATFORM_LINUX)
- add_definitions(-DFEATURE_PERFTRACING)
-endif(CLR_CMAKE_PLATFORM_LINUX)
if(CLR_CMAKE_PLATFORM_UNIX)
add_definitions(-DFEATURE_EVENTSOURCE_XPLAT=1)
endif(CLR_CMAKE_PLATFORM_UNIX)
diff --git a/clrfeatures.cmake b/clrfeatures.cmake
index b4d7bad2dd..367777a501 100644
--- a/clrfeatures.cmake
+++ b/clrfeatures.cmake
@@ -3,23 +3,13 @@ if(CLR_CMAKE_TARGET_TIZEN_LINUX)
endif()
if(NOT DEFINED FEATURE_EVENT_TRACE)
- if (WIN32)
- set(FEATURE_EVENT_TRACE 1)
- endif()
-
- if(CLR_CMAKE_PLATFORM_LINUX)
- if(CLR_CMAKE_TARGET_TIZEN_LINUX)
- set(FEATURE_EVENT_TRACE 1)
- elseif(CLR_CMAKE_TARGET_ARCH_AMD64)
- set(FEATURE_EVENT_TRACE 1)
- elseif(CLR_CMAKE_TARGET_ARCH_ARM)
- set(FEATURE_EVENT_TRACE 1)
- elseif(CLR_CMAKE_TARGET_ARCH_ARM64)
- set(FEATURE_EVENT_TRACE 1)
- endif()
- endif(CLR_CMAKE_PLATFORM_LINUX)
+ set(FEATURE_EVENT_TRACE 1)
endif(NOT DEFINED FEATURE_EVENT_TRACE)
+if(NOT DEFINED FEATURE_PERFTRACING AND FEATURE_EVENT_TRACE)
+ set(FEATURE_PERFTRACING 1)
+endif(NOT DEFINED FEATURE_PERFTRACING AND FEATURE_EVENT_TRACE)
+
if(NOT DEFINED FEATURE_DBGIPC)
if(CLR_CMAKE_PLATFORM_UNIX AND (NOT CLR_CMAKE_PLATFORM_ANDROID))
set(FEATURE_DBGIPC 1)
diff --git a/dependencies.props b/dependencies.props
index 8e62c42063..b1785adead 100644
--- a/dependencies.props
+++ b/dependencies.props
@@ -38,7 +38,7 @@
<XunitPackageVersion>2.2.0-beta2-build3300</XunitPackageVersion>
<XunitConsoleNetcorePackageVersion>1.0.2-prerelease-00177</XunitConsoleNetcorePackageVersion>
<XunitPerformanceApiPackageVersion>1.0.0-beta-build0015</XunitPerformanceApiPackageVersion>
- <MicrosoftDiagnosticsTracingTraceEventPackageVersion>1.0.3-alpha-experimental</MicrosoftDiagnosticsTracingTraceEventPackageVersion>
+ <MicrosoftDiagnosticsTracingTraceEventPackageVersion>2.0.2</MicrosoftDiagnosticsTracingTraceEventPackageVersion>
<VCRuntimeVersion>1.2.0</VCRuntimeVersion>
</PropertyGroup>
diff --git a/functions.cmake b/functions.cmake
index 15d0cd929c..c2286839dd 100644
--- a/functions.cmake
+++ b/functions.cmake
@@ -44,11 +44,11 @@ endfunction(get_include_directories)
# Build a list of include directories for consumption by the assembler
function(get_include_directories_asm IncludeDirectories)
get_directory_property(dirs INCLUDE_DIRECTORIES)
-
+
if (CLR_CMAKE_PLATFORM_ARCH_ARM AND WIN32)
list(APPEND INC_DIRECTORIES "-I ")
endif()
-
+
foreach(dir IN LISTS dirs)
if (CLR_CMAKE_PLATFORM_ARCH_ARM AND WIN32)
list(APPEND INC_DIRECTORIES ${dir};)
@@ -141,7 +141,7 @@ function(strip_symbols targetName outputFilename)
add_custom_command(
TARGET ${targetName}
POST_BUILD
- VERBATIM
+ VERBATIM
COMMAND ${DSYMUTIL} --flat --minimize ${strip_source_file}
COMMAND ${STRIP} -S ${strip_source_file}
COMMENT Stripping symbols from ${strip_source_file} into file ${strip_destination_file}
@@ -152,7 +152,7 @@ function(strip_symbols targetName outputFilename)
add_custom_command(
TARGET ${targetName}
POST_BUILD
- VERBATIM
+ VERBATIM
COMMAND ${OBJCOPY} --only-keep-debug ${strip_source_file} ${strip_destination_file}
COMMAND ${OBJCOPY} --strip-debug ${strip_source_file}
COMMAND ${OBJCOPY} --add-gnu-debuglink=${strip_destination_file} ${strip_source_file}
@@ -166,30 +166,30 @@ function(strip_symbols targetName outputFilename)
endfunction()
function(install_clr targetName)
- list(FIND CLR_CROSS_COMPONENTS_LIST ${targetName} INDEX)
- if (NOT DEFINED CLR_CROSS_COMPONENTS_LIST OR NOT ${INDEX} EQUAL -1)
- strip_symbols(${targetName} strip_destination_file)
- # On the older version of cmake (2.8.12) used on Ubuntu 14.04 the TARGET_FILE
- # generator expression doesn't work correctly returning the wrong path and on
- # the newer cmake versions the LOCATION property isn't supported anymore.
- if(CMAKE_VERSION VERSION_EQUAL 3.0 OR CMAKE_VERSION VERSION_GREATER 3.0)
- set(install_source_file $<TARGET_FILE:${targetName}>)
- else()
- get_property(install_source_file TARGET ${targetName} PROPERTY LOCATION)
- endif()
-
- install(PROGRAMS ${install_source_file} DESTINATION .)
- if(WIN32)
- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/${targetName}.pdb DESTINATION PDB)
- else()
- install(FILES ${strip_destination_file} DESTINATION .)
- endif()
+ list(FIND CLR_CROSS_COMPONENTS_LIST ${targetName} INDEX)
+ if (NOT DEFINED CLR_CROSS_COMPONENTS_LIST OR NOT ${INDEX} EQUAL -1)
+ strip_symbols(${targetName} strip_destination_file)
+ # On the older version of cmake (2.8.12) used on Ubuntu 14.04 the TARGET_FILE
+ # generator expression doesn't work correctly returning the wrong path and on
+ # the newer cmake versions the LOCATION property isn't supported anymore.
+ if(CMAKE_VERSION VERSION_EQUAL 3.0 OR CMAKE_VERSION VERSION_GREATER 3.0)
+ set(install_source_file $<TARGET_FILE:${targetName}>)
+ else()
+ get_property(install_source_file TARGET ${targetName} PROPERTY LOCATION)
+ endif()
+
+ install(PROGRAMS ${install_source_file} DESTINATION .)
+ if(WIN32)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/${targetName}.pdb DESTINATION PDB)
+ else()
+ install(FILES ${strip_destination_file} DESTINATION .)
+ endif()
if(CLR_CMAKE_PGO_INSTRUMENT)
if(WIN32)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/${targetName}.pgd DESTINATION PGD OPTIONAL)
endif()
endif()
- endif()
+ endif()
endfunction()
# Disable PAX mprotect that would prevent JIT and other codegen in coreclr from working.
@@ -217,11 +217,11 @@ function(_add_executable)
else()
add_executable(${ARGV})
endif(NOT WIN32)
- list(FIND CLR_CROSS_COMPONENTS_LIST ${ARGV0} INDEX)
- if (DEFINED CLR_CROSS_COMPONENTS_LIST AND ${INDEX} EQUAL -1)
- set_target_properties(${ARGV0} PROPERTIES EXCLUDE_FROM_ALL 1)
+ list(FIND CLR_CROSS_COMPONENTS_LIST ${ARGV0} INDEX)
+ if (DEFINED CLR_CROSS_COMPONENTS_LIST AND ${INDEX} EQUAL -1)
+ set_target_properties(${ARGV0} PROPERTIES EXCLUDE_FROM_ALL 1)
endif()
-endfunction()
+endfunction()
function(_add_library)
if(NOT WIN32)
@@ -229,10 +229,10 @@ function(_add_library)
else()
add_library(${ARGV})
endif(NOT WIN32)
- list(FIND CLR_CROSS_COMPONENTS_LIST ${ARGV0} INDEX)
- if (DEFINED CLR_CROSS_COMPONENTS_LIST AND ${INDEX} EQUAL -1)
- set_target_properties(${ARGV0} PROPERTIES EXCLUDE_FROM_ALL 1)
- endif()
+ list(FIND CLR_CROSS_COMPONENTS_LIST ${ARGV0} INDEX)
+ if (DEFINED CLR_CROSS_COMPONENTS_LIST AND ${INDEX} EQUAL -1)
+ set_target_properties(${ARGV0} PROPERTIES EXCLUDE_FROM_ALL 1)
+ endif()
endfunction()
function(_install)
@@ -263,8 +263,8 @@ function(verify_dependencies targetName errorMessage)
TARGET ${targetName}
POST_BUILD
VERBATIM
- COMMAND ${CMAKE_SOURCE_DIR}/verify-so.sh
- $<TARGET_FILE:${targetName}>
+ COMMAND ${CMAKE_SOURCE_DIR}/verify-so.sh
+ $<TARGET_FILE:${targetName}>
${errorMessage}
COMMENT "Verifying ${targetName} dependencies"
)
@@ -273,10 +273,8 @@ endfunction()
function(add_library_clr)
_add_library(${ARGV})
- add_dependencies(${ARGV0} GeneratedEventingFiles)
endfunction()
function(add_executable_clr)
_add_executable(${ARGV})
- add_dependencies(${ARGV0} GeneratedEventingFiles)
endfunction()
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4c999b184d..0412226dfc 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -10,70 +10,10 @@ include_directories("classlibnative/cryptography")
include_directories("classlibnative/inc")
include_directories("${GENERATED_INCLUDE_DIR}")
-# The Following Logic is used to wire up Build dependencies for Generated files in Event Logging
-# ClrEtwAll.man - Event Schema
-# ClrEtwAllMeta.lst - MetaData list [provided to ensure Windows Desktop is not broken]
-# genXplatEventing.py - has the core logic for parsing Event Schema
-# genWinEtw.py - Uses genXplatEventing to generate Windows Specific ETW Files
-# clretwallmain.h and etmdummy.h - Provides the Event Logging Functionality to the VM
-# clrxplatevents.h - Used by clretwallmain.h on Non Windows platform
-# ClrEtwAll.h - Used by clretwallmain.h on Windows
-# ClrEtwAll.rc - Used by src/dlls/clretwrc/clretrw.rc on Windows
-
-set (ScriptGeneratedEventFiles
- ${GENERATED_INCLUDE_DIR}/clretwallmain.h
- ${GENERATED_INCLUDE_DIR}/etmdummy.h
-)
-set (GeneratedEventFiles)
+if(WIN32 AND FEATURE_EVENT_TRACE)
+ include_directories("${GENERATED_INCLUDE_DIR}/etw")
+endif(WIN32 AND FEATURE_EVENT_TRACE)
-if(WIN32)
- set (GenEventFilesScript "${CLR_DIR}/src/scripts/genWinEtw.py")
- set (GenEventArgs --eventheader "${GENERATED_INCLUDE_DIR}/ClrEtwAll.h" --macroheader "${GENERATED_INCLUDE_DIR}/clretwallmain.h")
-
- list (APPEND ScriptGeneratedEventFiles
- ${GENERATED_INCLUDE_DIR}/ClrEtwAll.h
- )
-
- list (APPEND GeneratedEventFiles
- ${GENERATED_INCLUDE_DIR}/ClrEtwAll.rc
- )
-
- add_custom_command(
- COMMENT "Generating ETW resource Files"
- COMMAND ${MC} -h ${GENERATED_INCLUDE_DIR} -r ${GENERATED_INCLUDE_DIR} -b -co -um -p FireEtw "${VM_DIR}/ClrEtwAll.man"
- OUTPUT ${GENERATED_INCLUDE_DIR}/ClrEtwAll.h
- DEPENDS "${VM_DIR}/ClrEtwAll.man"
- )
-else()
- set (GenEventFilesScript "${CLR_DIR}/src/scripts/genXplatEventing.py")
- set (GenEventArgs --inc "${GENERATED_INCLUDE_DIR}")
-
- list (APPEND ScriptGeneratedEventFiles
- ${GENERATED_INCLUDE_DIR}/clrxplatevents.h
- )
-endif(WIN32)
-
-if(CLR_CMAKE_WARNINGS_ARE_ERRORS)
- set(PYTHON_WARNING_FLAGS -Wall -Werror)
-else()
- set(PYTHON_WARNING_FLAGS -Wall)
-endif(CLR_CMAKE_WARNINGS_ARE_ERRORS)
-
-add_custom_command(
- COMMENT "Generating Eventing Files"
- COMMAND ${PYTHON} -B ${PYTHON_WARNING_FLAGS} ${GenEventFilesScript} ${GenEventArgs} --man "${VM_DIR}/ClrEtwAll.man" --exc "${VM_DIR}/ClrEtwAllMeta.lst" --dummy "${GENERATED_INCLUDE_DIR}/etmdummy.h"
- OUTPUT ${ScriptGeneratedEventFiles}
- DEPENDS ${GenEventFilesScript} "${VM_DIR}/ClrEtwAll.man" "${VM_DIR}/ClrEtwAllMeta.lst" "${CLR_DIR}/src/scripts/genXplatEventing.py"
-)
-
-list (APPEND GeneratedEventFiles
- ${ScriptGeneratedEventFiles}
-)
-
-add_custom_target(
- GeneratedEventingFiles
- DEPENDS ${GeneratedEventFiles}
-)
if(CLR_CMAKE_PLATFORM_UNIX)
if(CLR_CMAKE_PLATFORM_LINUX)
diff --git a/src/dlls/mscoree/coreclr/CMakeLists.txt b/src/dlls/mscoree/coreclr/CMakeLists.txt
index 8796cc16a5..8043f7733a 100644
--- a/src/dlls/mscoree/coreclr/CMakeLists.txt
+++ b/src/dlls/mscoree/coreclr/CMakeLists.txt
@@ -4,8 +4,8 @@ if (WIN32)
list(APPEND CLR_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/coreclr.def)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /ENTRY:CoreDllMain")
-
- # Incremental linking results in the linker inserting extra padding and routing function calls via thunks that can break the
+
+ # Incremental linking results in the linker inserting extra padding and routing function calls via thunks that can break the
# invariants (e.g. size of region between Jit_PatchedCodeLast-Jit_PatchCodeStart needs to fit in a page).
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /INCREMENTAL:NO")
@@ -14,7 +14,7 @@ if (WIN32)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DELAYLOAD:api-ms-win-core-winrt-roparameterizediid-l1-1-0.dll")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DELAYLOAD:api-ms-win-ro-typeresolution-l1-1-0.dll")
-
+
# No library groups for Win32
set(START_LIBRARY_GROUP)
set(END_LIBRARY_GROUP)
@@ -30,14 +30,14 @@ else()
# of the utilcode will be used instead of the standard library delete operator.
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xlinker -Bsymbolic -Xlinker -Bsymbolic-functions")
- # The following linked options can be inserted into the linker libraries list to
+ # The following linked options can be inserted into the linker libraries list to
# ensure proper resolving of circular references between a subset of the libraries.
set(START_LIBRARY_GROUP -Wl,--start-group)
set(END_LIBRARY_GROUP -Wl,--end-group)
# These options are used to force every object to be included even if it's unused.
set(START_WHOLE_ARCHIVE -Wl,--whole-archive)
- set(END_WHOLE_ARCHIVE -Wl,--no-whole-archive)
+ set(END_WHOLE_ARCHIVE -Wl,--no-whole-archive)
set(EXPORTS_LINKER_OPTION -Wl,--version-script=${EXPORTS_FILE})
endif(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD)
@@ -74,7 +74,7 @@ if(FEATURE_MERGE_JIT_AND_ENGINE)
endif(FEATURE_MERGE_JIT_AND_ENGINE)
# IMPORTANT! Please do not rearrange the order of the libraries. The linker on Linux is
-# order dependent and changing the order can result in undefined symbols in the shared
+# order dependent and changing the order can result in undefined symbols in the shared
# library.
set(CORECLR_LIBRARIES
utilcode
@@ -119,28 +119,34 @@ if(WIN32)
)
else()
list(APPEND CORECLR_LIBRARIES
- ${START_WHOLE_ARCHIVE} # force all PAL objects to be included so all exports are available
+ ${START_WHOLE_ARCHIVE} # force all PAL objects to be included so all exports are available
coreclrpal
- tracepointprovider
- ${END_WHOLE_ARCHIVE}
+ ${END_WHOLE_ARCHIVE}
mscorrc_debug
palrt
)
endif(WIN32)
-if(CLR_CMAKE_PLATFORM_UNIX AND FEATURE_EVENT_TRACE)
- list(APPEND CORECLR_LIBRARIES
- eventprovider
- )
-endif(CLR_CMAKE_PLATFORM_UNIX AND FEATURE_EVENT_TRACE)
-
-if(CLR_CMAKE_PLATFORM_LINUX)
+if(FEATURE_PERFTRACING)
list(APPEND CORECLR_LIBRARIES
eventpipe
- )
-endif(CLR_CMAKE_PLATFORM_LINUX)
-
-target_link_libraries(coreclr ${CORECLR_LIBRARIES})
+ )
+endif(FEATURE_PERFTRACING)
+
+if(FEATURE_EVENT_TRACE)
+ if(CLR_CMAKE_PLATFORM_UNIX)
+ list(APPEND CORECLR_LIBRARIES
+ eventprovider # On Windows this library contains only macros
+ )
+ endif(CLR_CMAKE_PLATFORM_UNIX)
+ if(CLR_CMAKE_PLATFORM_LINUX)
+ list(APPEND CORECLR_LIBRARIES
+ tracepointprovider
+ )
+ endif(CLR_CMAKE_PLATFORM_LINUX)
+endif(FEATURE_EVENT_TRACE)
+
+target_link_libraries(coreclr ${CORECLR_LIBRARIES})
if(WIN32)
# Add dac table & debug resource to coreclr
diff --git a/src/mscorlib/System.Private.CoreLib.csproj b/src/mscorlib/System.Private.CoreLib.csproj
index 0729772035..7dbe9109c7 100644
--- a/src/mscorlib/System.Private.CoreLib.csproj
+++ b/src/mscorlib/System.Private.CoreLib.csproj
@@ -622,7 +622,7 @@
<Target Name="CDefineChecker" BeforeTargets="Build" Condition="'$(CheckCDefines)'=='true'">
<!-- Compiler Definition Verification -->
<PropertyGroup>
- <CMakeDefinitionSaveFile>$(IntermediateOutputPath)\cmake.definitions</CMakeDefinitionSaveFile>
+ <CMakeDefinitionSaveFile>$(IntermediateOutputPath)..\cmake.definitions</CMakeDefinitionSaveFile>
</PropertyGroup>
<Exec Command="python $(MSBuildThisFileDirectory)..\scripts\check-definitions.py &quot;$(CMakeDefinitionSaveFile)&quot; &quot;$(DefineConstants)&quot; &quot;$(IgnoreDefineConstants)&quot; " />
</Target>
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs
index 539c60b55f..5363b2aece 100644
--- a/src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventPipe.cs
@@ -14,12 +14,12 @@ namespace System.Diagnostics.Tracing
{
[MarshalAs(UnmanagedType.LPWStr)]
private string m_providerName;
- private UInt64 m_keywords;
+ private ulong m_keywords;
private uint m_loggingLevel;
internal EventPipeProviderConfiguration(
string providerName,
- UInt64 keywords,
+ ulong keywords,
uint loggingLevel)
{
if(string.IsNullOrEmpty(providerName))
@@ -40,7 +40,7 @@ namespace System.Diagnostics.Tracing
get { return m_providerName; }
}
- internal UInt64 Keywords
+ internal ulong Keywords
{
get { return m_keywords; }
}
@@ -96,7 +96,7 @@ namespace System.Diagnostics.Tracing
get { return m_minTimeBetweenSamples.Ticks * 100; }
}
- internal void EnableProvider(string providerName, UInt64 keywords, uint loggingLevel)
+ internal void EnableProvider(string providerName, ulong keywords, uint loggingLevel)
{
m_providers.Add(new EventPipeProviderConfiguration(
providerName,
@@ -124,6 +124,11 @@ namespace System.Diagnostics.Tracing
throw new ArgumentNullException(nameof(configuration));
}
+ if(configuration.Providers == null)
+ {
+ throw new ArgumentNullException(nameof(configuration.Providers));
+ }
+
EventPipeProviderConfiguration[] providers = configuration.Providers;
EventPipeInternal.Enable(
@@ -158,7 +163,7 @@ namespace System.Diagnostics.Tracing
internal static extern IntPtr CreateProvider(string providerName, UnsafeNativeMethods.ManifestEtw.EtwEnableCallback callbackFunc);
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
- internal static extern unsafe IntPtr DefineEvent(IntPtr provHandle, uint eventID, Int64 keywords, uint eventVersion, uint level, void *pMetadata, uint metadataLength);
+ internal static extern unsafe IntPtr DefineEvent(IntPtr provHandle, uint eventID, long keywords, uint eventVersion, uint level, void *pMetadata, uint metadataLength);
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
internal static extern void DeleteProvider(IntPtr provHandle);
diff --git a/src/pal/src/CMakeLists.txt b/src/pal/src/CMakeLists.txt
index 2ade61b3d6..feb434cd3e 100644
--- a/src/pal/src/CMakeLists.txt
+++ b/src/pal/src/CMakeLists.txt
@@ -239,10 +239,14 @@ add_library(coreclrpal
${PLATFORM_SOURCES}
)
-add_library(tracepointprovider
- STATIC
- misc/tracepointprovider.cpp
-)
+# This builds in functionality to load LTTng tracepoints at runtime
+# Needed when using LTTng to support event tracing on Linux
+if(CLR_CMAKE_PLATFORM_LINUX)
+ add_library(tracepointprovider
+ STATIC
+ misc/tracepointprovider.cpp
+ )
+endif(CLR_CMAKE_PLATFORM_LINUX)
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
find_library(COREFOUNDATION CoreFoundation)
@@ -376,7 +380,7 @@ endif(CMAKE_SYSTEM_NAME STREQUAL NetBSD)
add_subdirectory(examples)
if(FEATURE_EVENT_TRACE)
- add_subdirectory($ENV{__IntermediatesDir}/Generated/eventprovider ${CMAKE_CURRENT_BINARY_DIR}/eventprovider)
+ add_subdirectory(${GENERATED_EVENTING_DIR}/eventprovider ${CMAKE_CURRENT_BINARY_DIR}/eventprovider)
endif(FEATURE_EVENT_TRACE)
# Install the static PAL library for VS
diff --git a/src/pal/tests/palsuite/CMakeLists.txt b/src/pal/tests/palsuite/CMakeLists.txt
index 0ea8969bab..6f36025d1a 100644
--- a/src/pal/tests/palsuite/CMakeLists.txt
+++ b/src/pal/tests/palsuite/CMakeLists.txt
@@ -31,4 +31,7 @@ add_subdirectory(miscellaneous)
add_subdirectory(pal_specific)
add_subdirectory(samples)
add_subdirectory(threading)
-add_subdirectory($ENV{__IntermediatesDir}/Generated/eventprovider/tests ${CMAKE_CURRENT_BINARY_DIR}/eventprovider )
+
+if(FEATURE_EVENT_TRACE)
+ add_subdirectory(${GENERATED_EVENTING_DIR}/eventprovider/tests ${CMAKE_CURRENT_BINARY_DIR}/eventprovider)
+endif(FEATURE_EVENT_TRACE)
diff --git a/src/scripts/Utilities.py b/src/scripts/Utilities.py
deleted file mode 100644
index c1ceec8e9f..0000000000
--- a/src/scripts/Utilities.py
+++ /dev/null
@@ -1,49 +0,0 @@
-from filecmp import dircmp
-import shutil
-import os
-
-def walk_recursively_and_update(dcmp):
- #for different Files Copy from right to left
- for name in dcmp.diff_files:
- srcpath = dcmp.right + "/" + name
- destpath = dcmp.left + "/" + name
- print("Updating %s" % (destpath))
- if os.path.isfile(srcpath):
- shutil.copyfile(srcpath, destpath)
- else :
- raise Exception("path: " + srcpath + "is neither a file or folder")
-
- #copy right only files
- for name in dcmp.right_only:
- srcpath = dcmp.right + "/" + name
- destpath = dcmp.left + "/" + name
- print("Updating %s" % (destpath))
- if os.path.isfile(srcpath):
- shutil.copyfile(srcpath, destpath)
- elif os.path.isdir(srcpath):
- shutil.copytree(srcpath, destpath)
- else :
- raise Exception("path: " + srcpath + "is neither a file or folder")
-
- #delete left only files
- for name in dcmp.left_only:
- path = dcmp.left + "/" + name
- print("Deleting %s" % (path))
- if os.path.isfile(path):
- os.remove(path)
- elif os.path.isdir(path):
- shutil.rmtree(path)
- else :
- raise Exception("path: " + path + "is neither a file or folder")
-
- #call recursively
- for sub_dcmp in dcmp.subdirs.values():
- walk_recursively_and_update(sub_dcmp)
-
-def UpdateDirectory(destpath,srcpath):
-
- print("Updating %s with %s" % (destpath,srcpath))
- if not os.path.exists(destpath):
- os.makedirs(destpath)
- dcmp = dircmp(destpath,srcpath)
- walk_recursively_and_update(dcmp)
diff --git a/src/scripts/check-definitions.py b/src/scripts/check-definitions.py
index 59b309a3e6..4f1026d4ef 100644
--- a/src/scripts/check-definitions.py
+++ b/src/scripts/check-definitions.py
@@ -33,18 +33,17 @@ debug = 0
# For the native part, return the sorted definition array.
def loadDefinitionFile(filename):
result = []
+
try:
- f = open(filename, 'r')
- except:
+ with open(filename, 'r') as f:
+ for line in f:
+ line = line.strip()
+ if line:
+ result.append(line)
+ except IOError:
+ # If cmake was not used, this script won't work, and that's ok
sys.exit(0)
- # if cmake was not used (because of skipnative or systems that do not use cmake), this script won't work.
-
- for line in f:
- theLine = line.rstrip("\r\n").strip()
- if (len(theLine) > 0):
- result.append(theLine)
- f.close()
result = sorted(result)
return result
@@ -108,9 +107,10 @@ def getDiff(arrNative, arrManaged):
def printPotentiallyCritical(arrDefinitions, referencedFilename, arrIgnore):
- f = open(referencedFilename, 'r')
- content = f.read()
- f.close()
+ content = None
+ with open(referencedFilename, 'r') as f:
+ content = f.read()
+
for keyword in arrDefinitions:
skip = 0
diff --git a/src/scripts/genDummyProvider.py b/src/scripts/genDummyProvider.py
new file mode 100644
index 0000000000..0704554263
--- /dev/null
+++ b/src/scripts/genDummyProvider.py
@@ -0,0 +1,211 @@
+##
+## Licensed to the .NET Foundation under one or more agreements.
+## The .NET Foundation licenses this file to you under the MIT license.
+## See the LICENSE file in the project root for more information.
+##
+## This script exists to create a dummy implementaion of the eventprovider
+## interface from a manifest file
+##
+## The intended use if for platforms which support event pipe
+## but do not have a an eventing platform to recieve report events
+
+import os
+from genEventing import *
+from utilities import open_for_update
+
+stdprolog_cpp="""
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************
+
+DO NOT MODIFY. AUTOGENERATED FILE.
+This file is generated using the logic from <root>/src/scripts/genDummyProvider.py
+
+******************************************************************/
+"""
+stdprolog_cmake="""
+#
+#
+#******************************************************************
+
+#DO NOT MODIFY. AUTOGENERATED FILE.
+#This file is generated using the logic from <root>/src/scripts/genDummyProvider.py
+
+#******************************************************************
+"""
+
+def trimProvName(name):
+ name = name.replace("Windows-",'')
+ name = name.replace("Microsoft-",'')
+ name = name.replace('-','_')
+ return name
+
+def escapeProvFilename(name):
+ name = name.replace('_','')
+ name = name.lower()
+ return name
+
+def generateDummyProvider(providerName, eventNodes, allTemplates, extern):
+ impl = []
+ for eventNode in eventNodes:
+ eventName = eventNode.getAttribute('symbol')
+ templateName = eventNode.getAttribute('template')
+
+ #generate EventXplatEnabled
+ if extern: impl.append('extern "C" ')
+ impl.append("BOOL EventXplatEnabled%s(){ return FALSE; }\n\n" % (eventName,))
+
+ #generate FireEtw functions
+ fnptype = []
+ linefnptype = []
+ if extern: fnptype.append('extern "C" ')
+ fnptype.append("ULONG FireEtXplat")
+ fnptype.append(eventName)
+ fnptype.append("(\n")
+
+
+ if templateName:
+ template = allTemplates[templateName]
+ else:
+ template = None
+
+ if template:
+ fnSig = template.signature
+ for paramName in fnSig.paramlist:
+ fnparam = fnSig.getParam(paramName)
+ wintypeName = fnparam.winType
+ typewName = palDataTypeMapping[wintypeName]
+ winCount = fnparam.count
+ countw = palDataTypeMapping[winCount]
+
+ if paramName in template.structs:
+ linefnptype.append("%sint %s_ElementSize,\n" % (lindent, paramName))
+
+ linefnptype.append(lindent)
+ linefnptype.append(typewName)
+ if countw != " ":
+ linefnptype.append(countw)
+
+ linefnptype.append(" ")
+ linefnptype.append(fnparam.name)
+ linefnptype.append(",\n")
+
+ if len(linefnptype) > 0 :
+ del linefnptype[-1]
+
+ fnptype.extend(linefnptype)
+ fnptype.append(")\n{\n")
+ impl.extend(fnptype)
+
+ #start of fn body
+ impl.append(" return ERROR_SUCCESS;\n")
+ impl.append("}\n\n")
+
+ return ''.join(impl)
+
+def generateDummyFiles(etwmanifest, out_dirname, extern):
+ tree = DOM.parse(etwmanifest)
+
+ #keep these relative
+ dummy_directory = "dummy"
+ dummyevntprovPre = os.path.join(dummy_directory, "eventprov")
+
+ if not os.path.exists(out_dirname):
+ os.makedirs(out_dirname)
+
+ if not os.path.exists(os.path.join(out_dirname, dummy_directory)):
+ os.makedirs(os.path.join(out_dirname, dummy_directory))
+
+ # Cmake
+ with open_for_update(os.path.join(out_dirname, "CMakeLists.txt")) as cmake:
+ cmake.write(stdprolog_cmake + "\n")
+ cmake.write("\ncmake_minimum_required(VERSION 2.8.12.2)\n")
+ if extern: cmake.write("\nproject(eventprovider)\n")
+ cmake.write("""
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+if(FEATURE_PAL)
+ add_definitions(-DPAL_STDCPP_COMPAT=1)
+ include_directories(${COREPAL_SOURCE_DIR}/inc/rt)
+endif(FEATURE_PAL)
+include_directories(dummy)
+
+""")
+ if extern: cmake.write("add_library")
+ else: cmake.write("add_library_clr")
+ cmake.write("""(eventprovider
+ STATIC\n""")
+
+ for providerNode in tree.getElementsByTagName('provider'):
+ providerName = trimProvName(providerNode.getAttribute('name'))
+ providerName_File = escapeProvFilename(providerName)
+
+ cmake.write(' "%s%s.cpp"\n' % (dummyevntprovPre, providerName_File))
+
+ cmake.write(")")
+ if extern: cmake.write("""
+
+# Install the static eventprovider library
+install(TARGETS eventprovider DESTINATION lib)
+""")
+
+ # Dummy Instrumentation
+ for providerNode in tree.getElementsByTagName('provider'):
+ providerName = trimProvName(providerNode.getAttribute('name'))
+ providerName_File = escapeProvFilename(providerName)
+
+ dummyevntprov = os.path.join(out_dirname, dummyevntprovPre + providerName_File + ".cpp")
+
+ with open_for_update(dummyevntprov) as impl:
+ impl.write(stdprolog_cpp + "\n")
+
+ impl.write("""
+#ifdef PLATFORM_UNIX
+#include "pal_mstypes.h"
+#include "pal_error.h"
+#include "pal.h"
+#define PAL_free free
+#define PAL_realloc realloc
+#include "pal/stackstring.hpp"
+#endif
+
+
+""")
+
+ templateNodes = providerNode.getElementsByTagName('template')
+ eventNodes = providerNode.getElementsByTagName('event')
+
+ allTemplates = parseTemplateNodes(templateNodes)
+
+ #create the implementation of eventing functions : dummyeventprov*.cp
+ impl.write(generateDummyProvider(providerName, eventNodes, allTemplates, extern) + "\n")
+
+def main(argv):
+
+ #parse the command line
+ parser = argparse.ArgumentParser(description="Generates the Code required to instrument LTTtng logging mechanism")
+
+ 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('--intermediate', type=str, required=True,
+ help='full path to eventprovider intermediate directory')
+ required.add_argument('--nonextern', action='store_true',
+ help='if specified, will generate files to be compiled into the CLR rather than externaly' )
+ args, unknown = parser.parse_known_args(argv)
+ if unknown:
+ print('Unknown argument(s): ', ', '.join(unknown))
+ return 1
+
+ sClrEtwAllMan = args.man
+ intermediate = args.intermediate
+ extern = not args.nonextern
+
+ generateDummyFiles(sClrEtwAllMan, intermediate, extern)
+
+if __name__ == '__main__':
+ return_code = main(sys.argv[1:])
+ sys.exit(return_code) \ No newline at end of file
diff --git a/src/scripts/genEtwProvider.py b/src/scripts/genEtwProvider.py
new file mode 100644
index 0000000000..fc9d43800f
--- /dev/null
+++ b/src/scripts/genEtwProvider.py
@@ -0,0 +1,312 @@
+##
+## Licensed to the .NET Foundation under one or more agreements.
+## The .NET Foundation licenses this file to you under the MIT license.
+## See the LICENSE file in the project root for more information.
+##
+## This script generates the interface to ETW using MC.exe
+
+import os
+from os import path
+import shutil
+import re
+import sys
+import argparse
+import subprocess
+import xml.dom.minidom as DOM
+from genEventing import parseTemplateNodes
+from utilities import open_for_update
+
+macroheader_filename = "etwmacros.h"
+mcheader_filename = "ClrEtwAll.h"
+clrxplat_filename = "clrxplatevents.h"
+etw_dirname = "etw"
+replacements = [
+ (r"EventEnabled", "EventXplatEnabled"),
+ (r"\bPVOID\b", "void*")
+]
+
+stdprolog_cpp="""
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/******************************************************************
+
+DO NOT MODIFY. AUTOGENERATED FILE.
+This file is generated using the logic from <root>/src/scripts/genEtwProvider.py
+
+******************************************************************/
+"""
+stdprolog_cmake="""
+#
+#
+#******************************************************************
+
+#DO NOT MODIFY. AUTOGENERATED FILE.
+#This file is generated using the logic from <root>/src/scripts/genEtwProvider.py
+
+#******************************************************************
+"""
+
+def genProviderInterface(manifest, intermediate):
+ provider_dirname = os.path.join(intermediate, etw_dirname)
+
+ if not os.path.exists(provider_dirname):
+ os.makedirs(provider_dirname)
+
+ cmd = ['mc.exe', '-h', provider_dirname, '-r', provider_dirname, '-b', '-co', '-um', '-p', 'FireEtXplat', manifest]
+ subprocess.check_call(cmd)
+
+ header_text = None
+ with open(path.join(provider_dirname, mcheader_filename), 'r') as mcheader_file:
+ header_text = mcheader_file.read()
+
+ for pattern, replacement in replacements:
+ header_text = re.sub(pattern, replacement, header_text)
+
+ with open_for_update(path.join(provider_dirname, mcheader_filename)) as mcheader_file:
+ mcheader_file.write(header_text)
+
+def genCmake(intermediate):
+ # Top level Cmake
+
+ with open_for_update(os.path.join(intermediate, "CMakeLists.txt")) as cmake_file:
+ cmake_file.write(stdprolog_cmake)
+ cmake_file.write("""
+project(eventprovider)
+
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+include_directories({0})
+
+add_library_clr(eventprovider
+ STATIC
+ "{0}/{1}"
+ "{0}/{2}"
+)
+
+#set_target_properties(eventprovider PROPERTIES LINKER_LANGUAGE Hxx)
+""".format(etw_dirname, macroheader_filename, "ClrEtwAll.cpp"))
+
+def genXplatHeader(intermediate):
+ with open_for_update(path.join(intermediate, clrxplat_filename)) as header_file:
+ header_file.write("""
+#ifndef _CLR_XPLAT_EVENTS_H_
+#define _CLR_XPLAT_EVENTS_H_
+
+#include "{0}/{1}"
+#include "{0}/{2}"
+
+#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)
+
+ eventCond = tokens[0] == eventProvider or tokens[0] == "*"
+ taskCond = tokens[1] == taskName or tokens[1] == "*"
+ symbolCond = tokens[2] == eventSymbol or tokens[2] == "*"
+
+ if eventCond and taskCond and symbolCond:
+ return False
+ return True
+
+#Add the miscelaneous checks here
+def checkConsistency(manifest, exclusion_filename):
+ tree = DOM.parse(manifest)
+ exclusionInfo = parseExclusionList(exclusion_filename)
+ for providerNode in tree.getElementsByTagName('provider'):
+
+ stackSupportSpecified = {}
+ eventNodes = providerNode.getElementsByTagName('event')
+ templateNodes = providerNode.getElementsByTagName('template')
+ eventProvider = providerNode.getAttribute('name')
+ allTemplates = parseTemplateNodes(templateNodes)
+
+ for eventNode in eventNodes:
+ taskName = eventNode.getAttribute('task')
+ eventSymbol = eventNode.getAttribute('symbol')
+ eventTemplate = eventNode.getAttribute('template')
+ eventValue = int(eventNode.getAttribute('value'))
+ clrInstanceBit = getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.noclrinstance)
+ sLookupFieldName = "ClrInstanceID"
+ sLookupFieldType = "win:UInt16"
+
+ if clrInstanceBit and allTemplates.get(eventTemplate):
+ # check for the event template and look for a field named ClrInstanceId of type win:UInt16
+ fnParam = allTemplates[eventTemplate].getFnParam(sLookupFieldName)
+
+ if not(fnParam and fnParam.winType == sLookupFieldType):
+ raise Exception(exclusion_filename + ":No " + sLookupFieldName + " field of type " + sLookupFieldType + " for event symbol " + eventSymbol)
+
+ # If some versions of an event are on the nostack/stack lists,
+ # and some versions are not on either the nostack or stack list,
+ # then developer likely forgot to specify one of the versions
+
+ eventStackBitFromNoStackList = getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.nostack)
+ eventStackBitFromExplicitStackList = getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.explicitstack)
+ sStackSpecificityError = exclusion_filename + ": Error processing event :" + eventSymbol + "(ID" + str(eventValue) + "): This file must contain either ALL versions of this event or NO versions of this event. Currently some, but not all, versions of this event are present\n"
+
+ if not stackSupportSpecified.get(eventValue):
+ # Haven't checked this event before. Remember whether a preference is stated
+ if ( not eventStackBitFromNoStackList) or ( not eventStackBitFromExplicitStackList):
+ stackSupportSpecified[eventValue] = True
+ else:
+ stackSupportSpecified[eventValue] = False
+ else:
+ # We've checked this event before.
+ if stackSupportSpecified[eventValue]:
+ # When we last checked, a preference was previously specified, so it better be specified here
+ if eventStackBitFromNoStackList and eventStackBitFromExplicitStackList:
+ raise Exception(sStackSpecificityError)
+ else:
+ # When we last checked, a preference was not previously specified, so it better not be specified here
+ if ( not eventStackBitFromNoStackList) or ( not eventStackBitFromExplicitStackList):
+ raise Exception(sStackSpecificityError)
+
+def genEtwMacroHeader(manifest, exclusion_filename, intermediate):
+ provider_dirname = os.path.join(intermediate, etw_dirname)
+
+ if not os.path.exists(provider_dirname):
+ os.makedirs(provider_dirname)
+
+ tree = DOM.parse(manifest)
+ numOfProviders = len(tree.getElementsByTagName('provider'))
+ nMaxEventBytesPerProvider = 64
+
+ exclusionInfo = parseExclusionList(exclusion_filename)
+
+ with open_for_update(os.path.join(provider_dirname, macroheader_filename)) as header_file:
+ header_file.write(stdprolog_cpp + "\n")
+
+ header_file.write("#define NO_OF_ETW_PROVIDERS " + str(numOfProviders) + "\n")
+ header_file.write("#define MAX_BYTES_PER_ETW_PROVIDER " + str(nMaxEventBytesPerProvider) + "\n")
+ header_file.write("EXTERN_C __declspec(selectany) const BYTE etwStackSupportedEvents[NO_OF_ETW_PROVIDERS][MAX_BYTES_PER_ETW_PROVIDER] = \n{\n")
+
+ for providerNode in tree.getElementsByTagName('provider'):
+ stackSupportedEvents = [0]*nMaxEventBytesPerProvider
+ eventNodes = providerNode.getElementsByTagName('event')
+ eventProvider = providerNode.getAttribute('name')
+
+ for eventNode in eventNodes:
+ taskName = eventNode.getAttribute('task')
+ eventSymbol = eventNode.getAttribute('symbol')
+ eventTemplate = eventNode.getAttribute('template')
+ eventTemplate = eventNode.getAttribute('template')
+ eventValue = int(eventNode.getAttribute('value'))
+ eventIndex = eventValue // 8
+ eventBitPositionInIndex = eventValue % 8
+
+ eventStackBitFromNoStackList = int(getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.nostack))
+ eventStackBitFromExplicitStackList = int(getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.explicitstack))
+
+ # Shift those bits into position. For the explicit stack list, swap 0 and 1, so the eventValue* variables
+ # have 1 in the position iff we should issue a stack for the event.
+ eventValueUsingNoStackListByPosition = (eventStackBitFromNoStackList << eventBitPositionInIndex)
+ eventValueUsingExplicitStackListByPosition = ((1 - eventStackBitFromExplicitStackList) << eventBitPositionInIndex)
+
+ # Commit the values to the in-memory array that we'll dump into the header file
+ stackSupportedEvents[eventIndex] = stackSupportedEvents[eventIndex] | eventValueUsingNoStackListByPosition;
+ if eventStackBitFromExplicitStackList == 0:
+ stackSupportedEvents[eventIndex] = stackSupportedEvents[eventIndex] | eventValueUsingExplicitStackListByPosition
+
+ # print the bit array
+ line = []
+ line.append("\t{")
+ for elem in stackSupportedEvents:
+ line.append(str(elem))
+ line.append(", ")
+
+ del line[-1]
+ line.append("},")
+ header_file.write(''.join(line) + "\n")
+ header_file.write("};\n")
+
+def genFiles(manifest, intermediate, exclusion_filename):
+ if not os.path.exists(intermediate):
+ os.makedirs(intermediate)
+
+ genProviderInterface(manifest, intermediate)
+ genEtwMacroHeader(manifest, exclusion_filename, intermediate)
+ genXplatHeader(intermediate)
+
+
+def main(argv):
+ #parse the command line
+ parser = argparse.ArgumentParser(description="Generates the Code required to instrument ETW logging mechanism")
+
+ 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')
+ args, unknown = parser.parse_known_args(argv)
+ if unknown:
+ print('Unknown argument(s): ', ', '.join(unknown))
+ return 1
+
+ manifest = args.man
+ exclusion_filename = args.exc
+ intermediate = args.intermediate
+
+ checkConsistency(manifest, exclusion_filename)
+ genFiles(manifest, intermediate, exclusion_filename)
+
+if __name__ == '__main__':
+ return_code = main(sys.argv[1:])
+ sys.exit(return_code) \ No newline at end of file
diff --git a/src/scripts/genEventPipe.py b/src/scripts/genEventPipe.py
index 8a970794c0..96755ea459 100644
--- a/src/scripts/genEventPipe.py
+++ b/src/scripts/genEventPipe.py
@@ -1,10 +1,11 @@
from __future__ import print_function
-from genXplatEventing import *
-from genXplatLttng import *
+from genEventing import *
+from genLttngProvider import *
import os
import xml.dom.minidom as DOM
+from utilities import open_for_update
-stdprolog = """// Licensed to the .NET Foundation under one or more agreements.
+stdprolog_cpp = """// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -14,6 +15,7 @@ DO NOT MODIFY. AUTOGENERATED FILE.
This file is generated using the logic from <root>/src/scripts/genEventPipe.py
******************************************************************/
+
"""
stdprolog_cmake = """#
@@ -24,11 +26,54 @@ stdprolog_cmake = """#
#This file is generated using the logic from <root>/src/scripts/genEventPipe.py
#******************************************************************
+
"""
+eventpipe_dirname = "eventpipe"
+
+def generateMethodSignatureEnabled(eventName):
+ return "BOOL EventPipeEventEnabled%s()" % (eventName,)
+
+def generateMethodSignatureWrite(eventName, template, extern):
+ sig_pieces = []
+
+ if extern: sig_pieces.append('extern "C" ')
+ sig_pieces.append("ULONG EventPipeWriteEvent")
+ sig_pieces.append(eventName)
+ sig_pieces.append("(")
+
+ if template:
+ sig_pieces.append("\n")
+ fnSig = template.signature
+ for paramName in fnSig.paramlist:
+ fnparam = fnSig.getParam(paramName)
+ wintypeName = fnparam.winType
+ typewName = palDataTypeMapping[wintypeName]
+ winCount = fnparam.count
+ countw = palDataTypeMapping[winCount]
+
+ if paramName in template.structs:
+ sig_pieces.append(
+ "%sint %s_ElementSize,\n" %
+ (lindent, paramName))
+
+ sig_pieces.append(lindent)
+ sig_pieces.append(typewName)
+ if countw != " ":
+ sig_pieces.append(countw)
+
+ sig_pieces.append(" ")
+ sig_pieces.append(fnparam.name)
+ sig_pieces.append(",\n")
+
+ if len(sig_pieces) > 0:
+ del sig_pieces[-1]
+
+ sig_pieces.append(")")
+ return ''.join(sig_pieces)
def generateClrEventPipeWriteEventsImpl(
- providerName, eventNodes, allTemplates, exclusionListFile):
+ providerName, eventNodes, allTemplates, extern):
providerPrettyName = providerName.replace("Windows-", '')
providerPrettyName = providerPrettyName.replace("Microsoft-", '')
providerPrettyName = providerPrettyName.replace('-', '_')
@@ -47,54 +92,24 @@ def generateClrEventPipeWriteEventsImpl(
templateName = eventNode.getAttribute('template')
# generate EventPipeEventEnabled function
- eventEnabledImpl = """bool EventPipeEventEnabled%s()
+ eventEnabledImpl = generateMethodSignatureEnabled(eventName) + """
{
return EventPipeEvent%s->IsEnabled();
}
-""" % (eventName, eventName)
+""" % eventName
WriteEventImpl.append(eventEnabledImpl)
# generate EventPipeWriteEvent function
fnptype = []
- linefnptype = []
- fnptype.append("extern \"C\" ULONG EventPipeWriteEvent")
- fnptype.append(eventName)
- fnptype.append("(\n")
if templateName:
template = allTemplates[templateName]
else:
template = None
- if template:
- fnSig = template.signature
- for paramName in fnSig.paramlist:
- fnparam = fnSig.getParam(paramName)
- wintypeName = fnparam.winType
- typewName = palDataTypeMapping[wintypeName]
- winCount = fnparam.count
- countw = palDataTypeMapping[winCount]
-
- if paramName in template.structs:
- linefnptype.append(
- "%sint %s_ElementSize,\n" %
- (lindent, paramName))
-
- linefnptype.append(lindent)
- linefnptype.append(typewName)
- if countw != " ":
- linefnptype.append(countw)
-
- linefnptype.append(" ")
- linefnptype.append(fnparam.name)
- linefnptype.append(",\n")
-
- if len(linefnptype) > 0:
- del linefnptype[-1]
-
- fnptype.extend(linefnptype)
- fnptype.append(")\n{\n")
+ fnptype.append(generateMethodSignatureWrite(eventName, template, extern))
+ fnptype.append("\n{\n")
checking = """ if (!EventPipeEventEnabled%s())
return ERROR_SUCCESS;
""" % (eventName)
@@ -115,8 +130,9 @@ def generateClrEventPipeWriteEventsImpl(
WriteEventImpl.append("\n return ERROR_SUCCESS;\n}\n\n")
# EventPipeProvider and EventPipeEvent initialization
+ if extern: WriteEventImpl.append('extern "C" ')
WriteEventImpl.append(
- "extern \"C\" void Init" +
+ "void Init" +
providerPrettyName +
"()\n{\n")
WriteEventImpl.append(
@@ -134,7 +150,6 @@ def generateClrEventPipeWriteEventsImpl(
eventVersion = eventNode.getAttribute('version')
eventLevel = eventNode.getAttribute('level')
eventLevel = eventLevel.replace("win:", "EventPipeEventLevel::")
- exclusionInfo = parseExclusionList(exclusionListFile)
taskName = eventNode.getAttribute('task')
initEvent = """ EventPipeEvent%s = EventPipeProvider%s->AddEvent(%s,%s,%s,%s);
@@ -150,8 +165,8 @@ def generateWriteEventBody(template, providerName, eventName):
header = """
char stackBuffer[%s];
char *buffer = stackBuffer;
- unsigned int offset = 0;
- unsigned int size = %s;
+ size_t offset = 0;
+ size_t size = %s;
bool fixedBuffer = true;
bool success = true;
@@ -198,7 +213,7 @@ def generateWriteEventBody(template, providerName, eventName):
}\n\n"""
body = " EventPipe::WriteEvent(*EventPipeEvent" + \
- eventName + ", (BYTE *)buffer, offset);\n"
+ eventName + ", (BYTE *)buffer, (unsigned int)offset);\n"
footer = """
if (!fixedBuffer)
@@ -221,20 +236,23 @@ def generateEventKeywords(eventKeywords):
return mask
-def generateEventPipeCmakeFile(etwmanifest, eventpipe_directory):
+def generateEventPipeCmakeFile(etwmanifest, eventpipe_directory, extern):
tree = DOM.parse(etwmanifest)
- with open(eventpipe_directory + "CMakeLists.txt", 'w') as topCmake:
- topCmake.write(stdprolog_cmake + "\n")
- topCmake.write("""cmake_minimum_required(VERSION 2.8.12.2)
+ with open_for_update(os.path.join(eventpipe_directory, "CMakeLists.txt")) as cmake_file:
+ cmake_file.write(stdprolog_cmake)
+ cmake_file.write("cmake_minimum_required(VERSION 2.8.12.2)\n")
+ if extern: cmake_file.write("\nproject(eventpipe)\n")
+ cmake_file.write("""
- project(eventpipe)
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+include_directories(${CLR_DIR}/src/vm)
- set(CMAKE_INCLUDE_CURRENT_DIR ON)
- include_directories(${CLR_DIR}/src/vm)
-
- add_library(eventpipe
- STATIC\n""")
+""")
+ if extern: cmake_file.write("add_library")
+ else: cmake_file.write("add_library_clr")
+ cmake_file.write("""(eventpipe
+ STATIC\n""")
for providerNode in tree.getElementsByTagName('provider'):
providerName = providerNode.getAttribute('name')
@@ -244,34 +262,41 @@ def generateEventPipeCmakeFile(etwmanifest, eventpipe_directory):
providerName_File = providerName.replace('-', '')
providerName_File = providerName_File.lower()
- topCmake.write(' "%s.cpp"\n' % (providerName_File))
- topCmake.write(' "eventpipehelpers.cpp"\n')
- topCmake.write(""" )
-
- add_dependencies(eventpipe GeneratedEventingFiles)
-
- # Install the static eventpipe library
- install(TARGETS eventpipe DESTINATION lib)
- """)
-
- topCmake.close()
+ cmake_file.write(' "%s/%s.cpp"\n' % (eventpipe_dirname, providerName_File))
+ cmake_file.write(' "%s/eventpipehelpers.cpp"\n)' % (eventpipe_dirname,))
+ if extern: cmake_file.write("""
+# Install the static eventpipe library
+install(TARGETS eventpipe DESTINATION lib)
+""")
-def generateEventPipeHelperFile(etwmanifest, eventpipe_directory):
- with open(eventpipe_directory + "eventpipehelpers.cpp", 'w') as helper:
- helper.write(stdprolog)
+def generateEventPipeHelperFile(etwmanifest, eventpipe_directory, extern):
+ with open_for_update(os.path.join(eventpipe_directory, "eventpipehelpers.cpp")) as helper:
+ helper.write(stdprolog_cpp)
helper.write("""
-#include "stdlib.h"
-
-bool ResizeBuffer(char *&buffer, unsigned int& size, unsigned int currLen, unsigned int newSize, bool &fixedBuffer)
+#include "common.h"
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef FEATURE_PAL
+#include <windef.h>
+#include <crtdbg.h>
+#else
+#include "pal.h"
+#endif //FEATURE_PAL
+
+bool ResizeBuffer(char *&buffer, size_t& size, size_t currLen, size_t newSize, bool &fixedBuffer)
{
- newSize *= 1.5;
+ newSize = (size_t)(newSize * 1.5);
_ASSERTE(newSize > size); // check for overflow
if (newSize < 32)
newSize = 32;
- char *newBuffer = new char[newSize];
+ char *newBuffer = new (nothrow) char[newSize];
+
+ if (newBuffer == NULL)
+ return false;
memcpy(newBuffer, buffer, currLen);
@@ -285,7 +310,7 @@ bool ResizeBuffer(char *&buffer, unsigned int& size, unsigned int currLen, unsig
return true;
}
-bool WriteToBuffer(const BYTE *src, unsigned int len, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer)
+bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
{
if(!src) return true;
if (offset + len > size)
@@ -299,10 +324,10 @@ bool WriteToBuffer(const BYTE *src, unsigned int len, char *&buffer, unsigned in
return true;
}
-bool WriteToBuffer(PCWSTR str, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer)
+bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
{
if(!str) return true;
- unsigned int byteCount = (PAL_wcslen(str) + 1) * sizeof(*str);
+ size_t byteCount = (wcslen(str) + 1) * sizeof(*str);
if (offset + byteCount > size)
{
@@ -315,10 +340,10 @@ bool WriteToBuffer(PCWSTR str, char *&buffer, unsigned int& offset, unsigned int
return true;
}
-bool WriteToBuffer(const char *str, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer)
+bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
{
if(!str) return true;
- unsigned int len = strlen(str) + 1;
+ size_t len = strlen(str) + 1;
if (offset + len > size)
{
if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer))
@@ -339,12 +364,18 @@ bool WriteToBuffer(const char *str, char *&buffer, unsigned int& offset, unsigne
providerPrettyName = providerName.replace("Windows-", '')
providerPrettyName = providerPrettyName.replace("Microsoft-", '')
providerPrettyName = providerPrettyName.replace('-', '_')
+ if extern: helper.write(
+ 'extern "C" '
+ )
helper.write(
- "extern \"C\" void Init" +
+ "void Init" +
providerPrettyName +
"();\n\n")
- helper.write("extern \"C\" void InitProvidersAndEvents()\n{\n")
+ if extern: helper.write(
+ 'extern "C" '
+ )
+ helper.write("void InitProvidersAndEvents()\n{\n")
for providerNode in tree.getElementsByTagName('provider'):
providerName = providerNode.getAttribute('name')
providerPrettyName = providerName.replace("Windows-", '')
@@ -355,11 +386,20 @@ bool WriteToBuffer(const char *str, char *&buffer, unsigned int& offset, unsigne
helper.close()
-
def generateEventPipeImplFiles(
- etwmanifest, eventpipe_directory, exclusionListFile):
+ etwmanifest, eventpipe_directory, extern):
tree = DOM.parse(etwmanifest)
- coreclrRoot = os.getcwd()
+
+ # Find the src directory starting with the assumption that
+ # A) It is named 'src'
+ # B) This script lives in it
+ src_dirname = os.path.dirname(__file__)
+ while os.path.basename(src_dirname) != "src":
+ src_dirname = os.path.dirname(src_dirname)
+
+ if os.path.basename(src_dirname) == "":
+ raise IOError("Could not find the Core CLR 'src' directory")
+
for providerNode in tree.getElementsByTagName('provider'):
providerName = providerNode.getAttribute('name')
@@ -368,74 +408,77 @@ def generateEventPipeImplFiles(
providerName_File = providerPrettyName.replace('-', '')
providerName_File = providerName_File.lower()
providerPrettyName = providerPrettyName.replace('-', '_')
- eventpipefile = eventpipe_directory + providerName_File + ".cpp"
- eventpipeImpl = open(eventpipefile, 'w')
- eventpipeImpl.write(stdprolog)
+ eventpipefile = os.path.join(eventpipe_directory, providerName_File + ".cpp")
+ with open_for_update(eventpipefile) as eventpipeImpl:
+ eventpipeImpl.write(stdprolog_cpp)
+
+ header = """
+#include "{root:s}/vm/common.h"
+#include "{root:s}/vm/eventpipeprovider.h"
+#include "{root:s}/vm/eventpipeevent.h"
+#include "{root:s}/vm/eventpipe.h"
- header = """
-#include \"%s/src/vm/common.h\"
-#include \"%s/src/vm/eventpipeprovider.h\"
-#include \"%s/src/vm/eventpipeevent.h\"
-#include \"%s/src/vm/eventpipe.h\"
+#if defined(FEATURE_PAL)
+#define wcslen PAL_wcslen
+#endif
-bool ResizeBuffer(char *&buffer, unsigned int& size, unsigned int currLen, unsigned int newSize, bool &fixedBuffer);
-bool WriteToBuffer(PCWSTR str, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer);
-bool WriteToBuffer(const char *str, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer);
-bool WriteToBuffer(const BYTE *src, unsigned int len, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer);
+bool ResizeBuffer(char *&buffer, size_t& size, size_t currLen, size_t newSize, bool &fixedBuffer);
+bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer);
+bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer);
+bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer);
template <typename T>
-bool WriteToBuffer(const T &value, char *&buffer, unsigned int& offset, unsigned int& size, bool &fixedBuffer)
-{
+bool WriteToBuffer(const T &value, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
+{{
if (sizeof(T) + offset > size)
- {
- if (!ResizeBuffer(buffer, size, offset, size + sizeof(T), fixedBuffer))
- return false;
- }
+ {{
+ if (!ResizeBuffer(buffer, size, offset, size + sizeof(T), fixedBuffer))
+ return false;
+ }}
*(T *)(buffer + offset) = value;
offset += sizeof(T);
return true;
-}
+}}
-""" % (coreclrRoot, coreclrRoot, coreclrRoot, coreclrRoot)
+""".format(root=src_dirname.replace('\\', '/'))
- eventpipeImpl.write(header)
- eventpipeImpl.write(
- "const WCHAR* %sName = W(\"%s\");\n" % (
- providerPrettyName,
- providerName
+ eventpipeImpl.write(header)
+ eventpipeImpl.write(
+ "const WCHAR* %sName = W(\"%s\");\n" % (
+ providerPrettyName,
+ providerName
+ )
)
- )
- eventpipeImpl.write(
- "EventPipeProvider *EventPipeProvider%s = nullptr;\n" % (
- providerPrettyName,
+ eventpipeImpl.write(
+ "EventPipeProvider *EventPipeProvider%s = nullptr;\n" % (
+ providerPrettyName,
+ )
)
- )
- templateNodes = providerNode.getElementsByTagName('template')
- allTemplates = parseTemplateNodes(templateNodes)
- eventNodes = providerNode.getElementsByTagName('event')
- eventpipeImpl.write(
- generateClrEventPipeWriteEventsImpl(
- providerName,
- eventNodes,
- allTemplates,
- exclusionListFile) + "\n")
- eventpipeImpl.close()
+ templateNodes = providerNode.getElementsByTagName('template')
+ allTemplates = parseTemplateNodes(templateNodes)
+ eventNodes = providerNode.getElementsByTagName('event')
+ eventpipeImpl.write(
+ generateClrEventPipeWriteEventsImpl(
+ providerName,
+ eventNodes,
+ allTemplates,
+ extern) + "\n")
def generateEventPipeFiles(
- etwmanifest, eventpipe_directory, exclusionListFile):
- eventpipe_directory = eventpipe_directory + "/"
+ etwmanifest, intermediate, extern):
+ eventpipe_directory = os.path.join(intermediate, eventpipe_dirname)
tree = DOM.parse(etwmanifest)
if not os.path.exists(eventpipe_directory):
os.makedirs(eventpipe_directory)
- # generate Cmake file
- generateEventPipeCmakeFile(etwmanifest, eventpipe_directory)
+ # generate CMake file
+ generateEventPipeCmakeFile(etwmanifest, intermediate, extern)
# generate helper file
- generateEventPipeHelperFile(etwmanifest, eventpipe_directory)
+ generateEventPipeHelperFile(etwmanifest, eventpipe_directory, extern)
# generate all keywords
for keywordNode in tree.getElementsByTagName('keyword'):
@@ -447,12 +490,12 @@ def generateEventPipeFiles(
generateEventPipeImplFiles(
etwmanifest,
eventpipe_directory,
- exclusionListFile)
+ extern
+ )
import argparse
import sys
-
def main(argv):
# parse the command line
@@ -464,19 +507,19 @@ def main(argv):
help='full path to manifest containig the description of events')
required.add_argument('--intermediate', type=str, required=True,
help='full path to eventprovider intermediate directory')
- required.add_argument('--exc', type=str, required=True,
- help='full path to exclusion list')
+ required.add_argument('--nonextern', action='store_true',
+ help='if specified, will generate files to be compiled into the CLR rather than extern' )
args, unknown = parser.parse_known_args(argv)
if unknown:
print('Unknown argument(s): ', ', '.join(unknown))
- return const.UnknownArguments
+ return 1
sClrEtwAllMan = args.man
intermediate = args.intermediate
- exclusionListFile = args.exc
+ extern = not args.nonextern
- generateEventPipeFiles(sClrEtwAllMan, intermediate, exclusionListFile)
+ generateEventPipeFiles(sClrEtwAllMan, intermediate, extern)
if __name__ == '__main__':
return_code = main(sys.argv[1:])
- sys.exit(return_code)
+ sys.exit(return_code) \ No newline at end of file
diff --git a/src/scripts/genXplatEventing.py b/src/scripts/genEventing.py
index 4c9ce873b7..d6d6afbb90 100644
--- a/src/scripts/genXplatEventing.py
+++ b/src/scripts/genEventing.py
@@ -6,7 +6,7 @@
#
#USAGE:
#Add Events: modify <root>src/vm/ClrEtwAll.man
-#Look at the Code in <root>/src/scripts/genXplatLttng.py for using subroutines in this file
+#Look at the Code in <root>/src/scripts/genLttngProvider.py for using subroutines in this file
#
# Python 2 compatibility
@@ -14,6 +14,7 @@ from __future__ import print_function
import os
import xml.dom.minidom as DOM
+from utilities import open_for_update
stdprolog="""
// Licensed to the .NET Foundation under one or more agreements.
@@ -23,7 +24,7 @@ stdprolog="""
/******************************************************************
DO NOT MODIFY. AUTOGENERATED FILE.
-This file is generated using the logic from <root>/src/scripts/genXplatEventing.py
+This file is generated using the logic from <root>/src/scripts/genEventing.py
******************************************************************/
"""
@@ -34,7 +35,7 @@ stdprolog_cmake="""
#******************************************************************
#DO NOT MODIFY. AUTOGENERATED FILE.
-#This file is generated using the logic from <root>/src/scripts/genXplatEventing.py
+#This file is generated using the logic from <root>/src/scripts/genEventing.py
#******************************************************************
"""
@@ -260,7 +261,7 @@ def parseTemplateNodes(templateNodes):
assert(countVarName in fnPrototypes.paramlist)
if not countVarName:
raise ValueError("Struct '%s' in template '%s' does not have an attribute count." % (structName, templateName))
-
+
names = [x.attributes['name'].value for x in structToBeMarshalled.getElementsByTagName("data")]
types = [x.attributes['inType'].value for x in structToBeMarshalled.getElementsByTagName("data")]
@@ -305,8 +306,8 @@ def generateClrallEvents(eventNodes,allTemplates):
typewName = palDataTypeMapping[wintypeName]
winCount = fnparam.count
countw = palDataTypeMapping[winCount]
-
-
+
+
if params in template.structs:
fnptypeline.append("%sint %s_ElementSize,\n" % (lindent, params))
@@ -321,7 +322,7 @@ def generateClrallEvents(eventNodes,allTemplates):
for params in fnSig.paramlist:
fnparam = fnSig.getParam(params)
- if params in template.structs:
+ if params in template.structs:
line.append(fnparam.name + "_ElementSize")
line.append(", ")
@@ -349,20 +350,23 @@ def generateClrallEvents(eventNodes,allTemplates):
return ''.join(clrallEvents)
-def generateClrXplatEvents(eventNodes, allTemplates):
+def generateClrXplatEvents(eventNodes, allTemplates, extern):
clrallEvents = []
for eventNode in eventNodes:
eventName = eventNode.getAttribute('symbol')
templateName = eventNode.getAttribute('template')
#generate EventEnabled
- clrallEvents.append("extern \"C\" BOOL EventXplatEnabled")
+ if extern: clrallEvents.append('extern "C" ')
+ clrallEvents.append("BOOL EventXplatEnabled")
clrallEvents.append(eventName)
clrallEvents.append("();\n")
+
#generate FireEtw functions
fnptype = []
fnptypeline = []
- fnptype.append("extern \"C\" ULONG FireEtXplat")
+ if extern: fnptype.append('extern "C" ')
+ fnptype.append("ULONG FireEtXplat")
fnptype.append(eventName)
fnptype.append("(\n")
@@ -377,7 +381,7 @@ def generateClrXplatEvents(eventNodes, allTemplates):
winCount = fnparam.count
countw = palDataTypeMapping[winCount]
-
+
if params in template.structs:
fnptypeline.append("%sint %s_ElementSize,\n" % (lindent, params))
@@ -398,7 +402,7 @@ def generateClrXplatEvents(eventNodes, allTemplates):
return ''.join(clrallEvents)
-def generateClrEventPipeWriteEvents(eventNodes, allTemplates):
+def generateClrEventPipeWriteEvents(eventNodes, allTemplates, extern):
clrallEvents = []
for eventNode in eventNodes:
eventName = eventNode.getAttribute('symbol')
@@ -409,11 +413,13 @@ def generateClrEventPipeWriteEvents(eventNodes, allTemplates):
writeevent = []
fnptypeline = []
- eventenabled.append("extern \"C\" bool EventPipeEventEnabled")
+ if extern:eventenabled.append('extern "C" ')
+ eventenabled.append("BOOL EventPipeEventEnabled")
eventenabled.append(eventName)
eventenabled.append("();\n")
- writeevent.append("extern \"C\" ULONG EventPipeWriteEvent")
+ if extern: writeevent.append('extern "C" ')
+ writeevent.append("ULONG EventPipeWriteEvent")
writeevent.append(eventName)
writeevent.append("(\n")
@@ -554,63 +560,70 @@ def generateSanityTest(sClrEtwAllMan,testDir):
cmake_file = testDir + "/CMakeLists.txt"
test_cpp = "clralltestevents.cpp"
testinfo = testDir + "/testinfo.dat"
- Cmake_file = open(cmake_file,'w')
- Test_cpp = open(testDir + "/" + test_cpp,'w')
- Testinfo = open(testinfo,'w')
#CMake File:
- Cmake_file.write(stdprolog_cmake)
- Cmake_file.write("""
- cmake_minimum_required(VERSION 2.8.12.2)
- set(CMAKE_INCLUDE_CURRENT_DIR ON)
- set(SOURCES
- """)
- Cmake_file.write(test_cpp)
- Cmake_file.write("""
- )
- include_directories(${GENERATED_INCLUDE_DIR})
+ with open_for_update(cmake_file) as Cmake_file:
+ Cmake_file.write(stdprolog_cmake)
+ Cmake_file.write("""
+cmake_minimum_required(VERSION 2.8.12.2)
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(SOURCES
+""")
+ Cmake_file.write(test_cpp)
+ Cmake_file.write("""
+ )
+include_directories(${GENERATED_INCLUDE_DIR})
+
+if(FEATURE_PAL)
include_directories(${COREPAL_SOURCE_DIR}/inc/rt)
+endif(FEATURE_PAL)
+
+add_executable(eventprovidertest
+ ${SOURCES}
+ )
+set(EVENT_PROVIDER_DEPENDENCIES "")
+set(EVENT_PROVIDER_LINKER_OTPTIONS "")
+if(FEATURE_EVENT_TRACE)
+ add_definitions(-DFEATURE_EVENT_TRACE=1)
+ list(APPEND EVENT_PROVIDER_DEPENDENCIES
+ eventprovider
+ )
+ if(CLR_CMAKE_PLATFORM_LINUX)
+ list(APPEND EVENT_PROVIDER_DEPENDENCIES
+ coreclrtraceptprovider
+ )
+ endif(CLR_CMAKE_PLATFORM_LINUX)
+ list(APPEND EVENT_PROVIDER_LINKER_OTPTIONS
+ ${EVENT_PROVIDER_DEPENDENCIES}
+ )
+endif(FEATURE_EVENT_TRACE)
+
+add_dependencies(eventprovidertest ${EVENT_PROVIDER_DEPENDENCIES} coreclrpal)
+target_link_libraries(eventprovidertest
+ coreclrpal
+ ${EVENT_PROVIDER_LINKER_OTPTIONS}
+ )
+""")
+
+
+ with open_for_update(testinfo) as Testinfo:
+ Testinfo.write("""
+Copyright (c) Microsoft Corporation. All rights reserved.
+#
- add_executable(eventprovidertest
- ${SOURCES}
- )
- set(EVENT_PROVIDER_DEPENDENCIES "")
- set(EVENT_PROVIDER_LINKER_OTPTIONS "")
- if(FEATURE_EVENT_TRACE)
- add_definitions(-DFEATURE_EVENT_TRACE=1)
- list(APPEND EVENT_PROVIDER_DEPENDENCIES
- coreclrtraceptprovider
- eventprovider
- )
- list(APPEND EVENT_PROVIDER_LINKER_OTPTIONS
- ${EVENT_PROVIDER_DEPENDENCIES}
- )
-
- endif(FEATURE_EVENT_TRACE)
-
- add_dependencies(eventprovidertest ${EVENT_PROVIDER_DEPENDENCIES} coreclrpal)
- target_link_libraries(eventprovidertest
- coreclrpal
- ${EVENT_PROVIDER_LINKER_OTPTIONS}
- )
- """)
- Testinfo.write("""
- Copyright (c) Microsoft Corporation. All rights reserved.
- #
-
- Version = 1.0
- Section = EventProvider
- Function = EventProvider
- Name = PAL test for FireEtW* and EventEnabled* functions
- TYPE = DEFAULT
- EXE1 = eventprovidertest
- Description
- =This is a sanity test to check that there are no crashes in Xplat eventing
- """)
+Version = 1.0
+Section = EventProvider
+Function = EventProvider
+Name = PAL test for FireEtW* and EventEnabled* functions
+TYPE = DEFAULT
+EXE1 = eventprovidertest
+Description = This is a sanity test to check that there are no crashes in Xplat eventing
+""")
#Test.cpp
- Test_cpp.write(stdprolog)
- Test_cpp.write("""
+ with open_for_update(testDir + "/" + test_cpp) as Test_cpp:
+ Test_cpp.write(stdprolog)
+ Test_cpp.write("""
/*=====================================================================
**
** Source: clralltestevents.cpp
@@ -619,7 +632,9 @@ def generateSanityTest(sClrEtwAllMan,testDir):
**
**
**===================================================================*/
+#if FEATURE_PAL
#include <palsuite.h>
+#endif //FEATURE_PAL
#include <clrxplatevents.h>
typedef struct _Struct1 {
@@ -646,39 +661,42 @@ int win_Int32 = 12;
BYTE* win_Binary =(BYTE*)var21 ;
int __cdecl main(int argc, char **argv)
{
-
+#if defined(FEATURE_PAL)
/* Initialize the PAL.
*/
if(0 != PAL_Initialize(argc, argv))
{
- return FAIL;
+ return FAIL;
}
+#endif
ULONG Error = ERROR_SUCCESS;
#if defined(FEATURE_EVENT_TRACE)
Trace("\\n Starting functional eventing APIs tests \\n");
""")
- Test_cpp.write(generateClralltestEvents(sClrEtwAllMan))
- Test_cpp.write("""
-/* Shutdown the PAL.
- */
-
- if (Error != ERROR_SUCCESS)
- {
- Fail("One or more eventing Apis failed\\n ");
- return FAIL;
- }
- Trace("\\n All eventing APIs were fired succesfully \\n");
+ Test_cpp.write(generateClralltestEvents(sClrEtwAllMan))
+ Test_cpp.write("""
+
+ if (Error != ERROR_SUCCESS)
+ {
+ Fail("One or more eventing Apis failed\\n ");
+ return FAIL;
+ }
+ Trace("\\n All eventing APIs were fired succesfully \\n");
#endif //defined(FEATURE_EVENT_TRACE)
- PAL_Terminate();
- return PASS;
- }
+#if defined(FEATURE_PAL)
+
+/* Shutdown the PAL.
+*/
+
+ PAL_Terminate();
+#endif
+ return PASS;
+ }
""")
- Cmake_file.close()
- Test_cpp.close()
Testinfo.close()
def generateEtmDummyHeader(sClrEtwAllMan,clretwdummy):
@@ -693,19 +711,17 @@ def generateEtmDummyHeader(sClrEtwAllMan,clretwdummy):
if not os.path.exists(incDir):
os.makedirs(incDir)
- Clretwdummy = open(clretwdummy,'w')
- Clretwdummy.write(stdprolog + "\n")
-
- for providerNode in tree.getElementsByTagName('provider'):
- templateNodes = providerNode.getElementsByTagName('template')
- allTemplates = parseTemplateNodes(templateNodes)
- eventNodes = providerNode.getElementsByTagName('event')
- #pal: create etmdummy.h
- Clretwdummy.write(generateclrEtwDummy(eventNodes, allTemplates) + "\n")
+ with open_for_update(clretwdummy) as Clretwdummy:
+ Clretwdummy.write(stdprolog + "\n")
- Clretwdummy.close()
+ for providerNode in tree.getElementsByTagName('provider'):
+ templateNodes = providerNode.getElementsByTagName('template')
+ allTemplates = parseTemplateNodes(templateNodes)
+ eventNodes = providerNode.getElementsByTagName('event')
+ #pal: create etmdummy.h
+ Clretwdummy.write(generateclrEtwDummy(eventNodes, allTemplates) + "\n")
-def generatePlformIndependentFiles(sClrEtwAllMan,incDir,etmDummyFile):
+def generatePlatformIndependentFiles(sClrEtwAllMan, incDir, etmDummyFile, extern):
generateEtmDummyHeader(sClrEtwAllMan,etmDummyFile)
tree = DOM.parse(sClrEtwAllMan)
@@ -717,152 +733,43 @@ def generatePlformIndependentFiles(sClrEtwAllMan,incDir,etmDummyFile):
if not os.path.exists(incDir):
os.makedirs(incDir)
- clrallevents = incDir + "/clretwallmain.h"
- clrxplatevents = incDir + "/clrxplatevents.h"
- clreventpipewriteevents = incDir + "/clreventpipewriteevents.h"
-
- Clrallevents = open(clrallevents,'w')
- Clrxplatevents = open(clrxplatevents,'w')
- Clreventpipewriteevents = open(clreventpipewriteevents,'w')
+ # Write the main header for FireETW* functions
+ clrallevents = os.path.join(incDir, "clretwallmain.h")
+ with open_for_update(clrallevents) as Clrallevents:
+ Clrallevents.write(stdprolog)
+ Clrallevents.write("""
+#include "clrxplatevents.h"
+#include "clreventpipewriteevents.h"
- Clrallevents.write(stdprolog + "\n")
- Clrxplatevents.write(stdprolog + "\n")
- Clreventpipewriteevents.write(stdprolog + "\n")
+""")
+ for providerNode in tree.getElementsByTagName('provider'):
+ templateNodes = providerNode.getElementsByTagName('template')
+ allTemplates = parseTemplateNodes(templateNodes)
+ eventNodes = providerNode.getElementsByTagName('event')
- Clrallevents.write("\n#include \"clrxplatevents.h\"\n")
- Clrallevents.write("#include \"clreventpipewriteevents.h\"\n\n")
-
- for providerNode in tree.getElementsByTagName('provider'):
- templateNodes = providerNode.getElementsByTagName('template')
- allTemplates = parseTemplateNodes(templateNodes)
- eventNodes = providerNode.getElementsByTagName('event')
- #vm header:
- Clrallevents.write(generateClrallEvents(eventNodes, allTemplates) + "\n")
+ #vm header:
+ Clrallevents.write(generateClrallEvents(eventNodes, allTemplates) + "\n")
- #pal: create clrallevents.h
- Clrxplatevents.write(generateClrXplatEvents(eventNodes, allTemplates) + "\n")
- #eventpipe: create clreventpipewriteevents.h
- Clreventpipewriteevents.write(generateClrEventPipeWriteEvents(eventNodes, allTemplates) + "\n")
+ # Write secondary headers for FireEtXplat* and EventPipe* functions
+ clrxplatevents = os.path.join(incDir, "clrxplatevents.h")
+ clreventpipewriteevents = os.path.join(incDir, "clreventpipewriteevents.h")
+ with open_for_update(clrxplatevents) as Clrxplatevents:
+ with open_for_update(clreventpipewriteevents) as Clreventpipewriteevents:
+ Clrxplatevents.write(stdprolog + "\n")
+ Clreventpipewriteevents.write(stdprolog + "\n")
- Clrxplatevents.close()
- Clrallevents.close()
- Clreventpipewriteevents.close()
+ for providerNode in tree.getElementsByTagName('provider'):
+ templateNodes = providerNode.getElementsByTagName('template')
+ allTemplates = parseTemplateNodes(templateNodes)
+ eventNodes = providerNode.getElementsByTagName('event')
-class EventExclusions:
- def __init__(self):
- self.nostack = set()
- self.explicitstack = set()
- self.noclrinstance = set()
-
-def parseExclusionList(exclusionListFile):
- ExclusionFile = open(exclusionListFile,'r')
- 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 "+ exclusionListFile)
-
- 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)
- ExclusionFile.close()
-
- 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)
-
- eventCond = tokens[0] == eventProvider or tokens[0] == "*"
- taskCond = tokens[1] == taskName or tokens[1] == "*"
- symbolCond = tokens[2] == eventSymbol or tokens[2] == "*"
-
- if eventCond and taskCond and symbolCond:
- return False
- return True
-
-#Add the miscelaneous checks here
-def checkConsistency(sClrEtwAllMan,exclusionListFile):
- tree = DOM.parse(sClrEtwAllMan)
- exclusionInfo = parseExclusionList(exclusionListFile)
- for providerNode in tree.getElementsByTagName('provider'):
+ #pal: create clrallevents.h
+ Clrxplatevents.write(generateClrXplatEvents(eventNodes, allTemplates, extern) + "\n")
- stackSupportSpecified = {}
- eventNodes = providerNode.getElementsByTagName('event')
- templateNodes = providerNode.getElementsByTagName('template')
- eventProvider = providerNode.getAttribute('name')
- allTemplates = parseTemplateNodes(templateNodes)
+ #eventpipe: create clreventpipewriteevents.h
+ Clreventpipewriteevents.write(generateClrEventPipeWriteEvents(eventNodes, allTemplates, extern) + "\n")
- for eventNode in eventNodes:
- taskName = eventNode.getAttribute('task')
- eventSymbol = eventNode.getAttribute('symbol')
- eventTemplate = eventNode.getAttribute('template')
- eventValue = int(eventNode.getAttribute('value'))
- clrInstanceBit = getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.noclrinstance)
- sLookupFieldName = "ClrInstanceID"
- sLookupFieldType = "win:UInt16"
-
- if clrInstanceBit and allTemplates.get(eventTemplate):
- # check for the event template and look for a field named ClrInstanceId of type win:UInt16
- fnParam = allTemplates[eventTemplate].getFnParam(sLookupFieldName)
-
- if not(fnParam and fnParam.winType == sLookupFieldType):
- raise Exception(exclusionListFile + ":No " + sLookupFieldName + " field of type " + sLookupFieldType + " for event symbol " + eventSymbol)
-
- # If some versions of an event are on the nostack/stack lists,
- # and some versions are not on either the nostack or stack list,
- # then developer likely forgot to specify one of the versions
-
- eventStackBitFromNoStackList = getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.nostack)
- eventStackBitFromExplicitStackList = getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.explicitstack)
- sStackSpecificityError = exclusionListFile + ": Error processing event :" + eventSymbol + "(ID" + str(eventValue) + "): This file must contain either ALL versions of this event or NO versions of this event. Currently some, but not all, versions of this event are present\n"
-
- if not stackSupportSpecified.get(eventValue):
- # Haven't checked this event before. Remember whether a preference is stated
- if ( not eventStackBitFromNoStackList) or ( not eventStackBitFromExplicitStackList):
- stackSupportSpecified[eventValue] = True
- else:
- stackSupportSpecified[eventValue] = False
- else:
- # We've checked this event before.
- if stackSupportSpecified[eventValue]:
- # When we last checked, a preference was previously specified, so it better be specified here
- if eventStackBitFromNoStackList and eventStackBitFromExplicitStackList:
- raise Exception(sStackSpecificityError)
- else:
- # When we last checked, a preference was not previously specified, so it better not be specified here
- if ( not eventStackBitFromNoStackList) or ( not eventStackBitFromExplicitStackList):
- raise Exception(sStackSpecificityError)
import argparse
import sys
@@ -874,28 +781,28 @@ 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('--inc', type=str, default=None,
help='full path to directory where the header files will be generated')
required.add_argument('--dummy', type=str,default=None,
help='full path to file that will have dummy definitions of FireEtw functions')
required.add_argument('--testdir', type=str, default=None,
help='full path to directory where the test assets will be deployed' )
+ required.add_argument('--nonextern', action='store_true',
+ help='if specified, will not generated extern function stub headers' )
args, unknown = parser.parse_known_args(argv)
if unknown:
print('Unknown argument(s): ', ', '.join(unknown))
- return const.UnknownArguments
+ return 1
sClrEtwAllMan = args.man
- exclusionListFile = args.exc
incdir = args.inc
etmDummyFile = args.dummy
testDir = args.testdir
+ extern = not args.nonextern
+
+ generatePlatformIndependentFiles(sClrEtwAllMan, incdir, etmDummyFile, extern)
+ generateSanityTest(sClrEtwAllMan, testDir)
- checkConsistency(sClrEtwAllMan, exclusionListFile)
- generatePlformIndependentFiles(sClrEtwAllMan,incdir,etmDummyFile)
- generateSanityTest(sClrEtwAllMan,testDir)
if __name__ == '__main__':
return_code = main(sys.argv[1:])
- sys.exit(return_code)
+ sys.exit(return_code) \ No newline at end of file
diff --git a/src/scripts/genXplatLttng.py b/src/scripts/genLttngProvider.py
index 9959895f5a..382cb74675 100644
--- a/src/scripts/genXplatLttng.py
+++ b/src/scripts/genLttngProvider.py
@@ -50,7 +50,8 @@
#
import os
-from genXplatEventing import *
+from genEventing import *
+from utilities import open_for_update
stdprolog="""
// Licensed to the .NET Foundation under one or more agreements.
@@ -60,7 +61,7 @@ stdprolog="""
/******************************************************************
DO NOT MODIFY. AUTOGENERATED FILE.
-This file is generated using the logic from <root>/src/scripts/genXplatLttng.py
+This file is generated using the logic from <root>/src/scripts/genLttngProvider.py
******************************************************************/
"""
@@ -70,7 +71,7 @@ stdprolog_cmake="""
#******************************************************************
#DO NOT MODIFY. AUTOGENERATED FILE.
-#This file is generated using the logic from <root>/src/scripts/genXplatLttng.py
+#This file is generated using the logic from <root>/src/scripts/genLttngProvider.py
#******************************************************************
"""
@@ -159,7 +160,7 @@ def generateArgList(template):
def generateFieldList(template):
header = " " + " TP_FIELDS(\n"
footer = "\n )\n)\n"
-
+
if shouldPackTemplate(template):
field_list = " ctf_integer(ULONG, length, length)\n"
field_list += " ctf_sequence(char, __data__, __data__, ULONG, length)"
@@ -209,7 +210,7 @@ def generateLttngHeader(providerName, allTemplates, eventNodes):
for templateName in allTemplates:
template = allTemplates[templateName]
fnSig = allTemplates[templateName].signature
-
+
lTTngHdr.append("\n#define " + templateName + "_TRACEPOINT_ARGS \\\n")
#TP_ARGS
@@ -289,7 +290,7 @@ def generateMethodBody(template, providerName, eventName):
return "\n do_tracepoint(%s, %s);\n" % (providerName, eventName)
fnSig = template.signature
-
+
for paramName in fnSig.paramlist:
fnparam = fnSig.getParam(paramName)
paramname = fnparam.name
@@ -298,7 +299,7 @@ def generateMethodBody(template, providerName, eventName):
result.append(" INT " + paramname + "_path_size = -1;\n")
result.append(" PathCharString " + paramname + "_PS;\n")
result.append(" INT " + paramname + "_full_name_path_size")
- result.append(" = (PAL_wcslen(" + paramname + ") + 1)*sizeof(WCHAR);\n")
+ result.append(" = (wcslen(" + paramname + ") + 1)*sizeof(WCHAR);\n")
result.append(" CHAR* " + paramname + "_full_name = ")
result.append(paramname + "_PS.OpenStringBuffer(" + paramname + "_full_name_path_size );\n")
result.append(" if (" + paramname + "_full_name == NULL )")
@@ -308,7 +309,7 @@ def generateMethodBody(template, providerName, eventName):
#emit tracepoints
fnSig = template.signature
-
+
if not shouldPackTemplate(template):
linefnbody = [" do_tracepoint(%s,\n %s" % (providerName, eventName)]
@@ -360,8 +361,8 @@ def generateMethodBody(template, providerName, eventName):
header = """
char stackBuffer[%s];
char *buffer = stackBuffer;
- int offset = 0;
- int size = %s;
+ size_t offset = 0;
+ size_t size = %s;
bool fixedBuffer = true;
bool success = true;
@@ -401,7 +402,7 @@ def generateMethodBody(template, providerName, eventName):
do_tracepoint(%s, %s, offset, buffer);\n""" % (providerName, eventName)
return header + code + tracepoint + footer
-
+
@@ -420,7 +421,7 @@ def generateLttngTpProvider(providerName, eventNodes, allTemplates):
fnptype.append(eventName)
fnptype.append("(\n")
-
+
if templateName:
template = allTemplates[templateName]
else:
@@ -489,7 +490,7 @@ def generateLttngFiles(etwmanifest,eventprovider_directory):
os.makedirs(eventprovider_directory + tracepointprovider_directory)
#Top level Cmake
- with open(eventprovider_directory + "CMakeLists.txt", 'w') as topCmake:
+ with open_for_update(eventprovider_directory + "CMakeLists.txt") as topCmake:
topCmake.write(stdprolog_cmake + "\n")
topCmake.write("""cmake_minimum_required(VERSION 2.8.12.2)
@@ -514,7 +515,7 @@ def generateLttngFiles(etwmanifest,eventprovider_directory):
providerName_File = providerName_File.lower()
topCmake.write(' "%s%s.cpp"\n' % (lttngevntprovPre, providerName_File))
-
+
topCmake.write(' "%shelpers.cpp"\n' % (lttngevntprovPre,))
topCmake.write(""")
add_subdirectory(tracepointprovider)
@@ -525,7 +526,7 @@ def generateLttngFiles(etwmanifest,eventprovider_directory):
#TracepointProvider Cmake
- with open(eventprovider_directory + tracepointprovider_directory + "/CMakeLists.txt", 'w') as tracepointprovider_Cmake:
+ with open_for_update(eventprovider_directory + tracepointprovider_directory + "/CMakeLists.txt") as tracepointprovider_Cmake:
tracepointprovider_Cmake.write(stdprolog_cmake + "\n")
tracepointprovider_Cmake.write("""cmake_minimum_required(VERSION 2.8.12.2)
@@ -562,7 +563,7 @@ def generateLttngFiles(etwmanifest,eventprovider_directory):
install_clr(coreclrtraceptprovider)
""")
- with open(eventprovider_directory + lttng_directory + "/eventprovhelpers.cpp", 'w') as helper:
+ with open_for_update(eventprovider_directory + lttng_directory + "/eventprovhelpers.cpp") as helper:
helper.write("""
#include "palrt.h"
#include "pal.h"
@@ -572,72 +573,81 @@ def generateLttngFiles(etwmanifest,eventprovider_directory):
#include <new>
#include <memory.h>
-bool ResizeBuffer(char *&buffer, int& size, int currLen, int newSize, bool &fixedBuffer)
+#define wcslen PAL_wcslen
+
+bool ResizeBuffer(char *&buffer, size_t& size, size_t currLen, size_t newSize, bool &fixedBuffer)
{
- newSize *= 1.5;
- _ASSERTE(newSize > size); // check for overflow
+ newSize = (size_t)(newSize * 1.5);
+ _ASSERTE(newSize > size); // check for overflow
if (newSize < 32)
newSize = 32;
- char *newBuffer = new char[newSize];
+ // We can't use coreclr includes here so we use std::nothrow
+ // rather than the coreclr version
+ char *newBuffer = new (std::nothrow) char[newSize];
- memcpy(newBuffer, buffer, currLen);
+ if (newBuffer == NULL)
+ return false;
- if (!fixedBuffer)
- delete[] buffer;
+ memcpy(newBuffer, buffer, currLen);
- buffer = newBuffer;
- size = newSize;
- fixedBuffer = false;
+ if (!fixedBuffer)
+ delete[] buffer;
- return true;
+ buffer = newBuffer;
+ size = newSize;
+ fixedBuffer = false;
+
+ return true;
}
-bool WriteToBuffer(const BYTE *src, int len, char *&buffer, int& offset, int& size, bool &fixedBuffer)
+bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
{
- if (!src) return true;
- if (offset + len > size)
- {
- if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer))
- return false;
- }
-
- memcpy(buffer + offset, src, len);
- offset += len;
- return true;
+ if(!src) return true;
+ if (offset + len > size)
+ {
+ if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer))
+ return false;
+ }
+
+ memcpy(buffer + offset, src, len);
+ offset += len;
+ return true;
}
-bool WriteToBuffer(PCWSTR str, char *&buffer, int& offset, int& size, bool &fixedBuffer)
+bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
{
- if (!str) return true;
- int byteCount = (PAL_wcslen(str) + 1) * sizeof(*str);
-
- if (offset + byteCount > size)
- {
- if (!ResizeBuffer(buffer, size, offset, size + byteCount, fixedBuffer))
- return false;
- }
-
- memcpy(buffer + offset, str, byteCount);
- offset += byteCount;
- return true;
+ if(!str) return true;
+ size_t byteCount = (wcslen(str) + 1) * sizeof(*str);
+
+ if (offset + byteCount > size)
+ {
+ if (!ResizeBuffer(buffer, size, offset, size + byteCount, fixedBuffer))
+ return false;
+ }
+
+ memcpy(buffer + offset, str, byteCount);
+ offset += byteCount;
+ return true;
}
-bool WriteToBuffer(const char *str, char *&buffer, int& offset, int& size, bool &fixedBuffer)
+bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
{
- if (!str) return true;
- int len = strlen(str) + 1;
- if (offset + len > size)
- {
- if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer))
- return false;
- }
-
- memcpy(buffer + offset, str, len);
- offset += len;
- return true;
-}""")
+ if(!str) return true;
+ size_t len = strlen(str) + 1;
+ if (offset + len > size)
+ {
+ if (!ResizeBuffer(buffer, size, offset, size + len, fixedBuffer))
+ return false;
+ }
+
+ memcpy(buffer + offset, str, len);
+ offset += len;
+ return true;
+}
+
+""")
# Generate Lttng specific instrumentation
for providerNode in tree.getElementsByTagName('provider'):
@@ -650,24 +660,19 @@ bool WriteToBuffer(const char *str, char *&buffer, int& offset, int& size, bool
providerName_File = providerName_File.lower()
providerName = providerName.replace('-','_')
- lttngevntheadershortname = "tp" + providerName_File +".h";
+ lttngevntheadershortname = "tp" + providerName_File +".h"
lttngevntheader = eventprovider_directory + "lttng/" + lttngevntheadershortname
lttngevntprov = eventprovider_directory + lttngevntprovPre + providerName_File + ".cpp"
lttngevntprovTp = eventprovider_directory + lttngevntprovTpPre + providerName_File +".cpp"
- lTTngHdr = open(lttngevntheader, 'w')
- lTTngImpl = open(lttngevntprov, 'w')
- lTTngTpImpl = open(lttngevntprovTp, 'w')
-
- lTTngHdr.write(stdprolog + "\n")
- lTTngImpl.write(stdprolog + "\n")
- lTTngTpImpl.write(stdprolog + "\n")
-
- lTTngTpImpl.write("\n#define TRACEPOINT_CREATE_PROBES\n")
+ templateNodes = providerNode.getElementsByTagName('template')
+ eventNodes = providerNode.getElementsByTagName('event')
+ allTemplates = parseTemplateNodes(templateNodes)
- lTTngTpImpl.write("#include \"./"+lttngevntheadershortname + "\"\n")
- lTTngHdr.write("""
+ with open_for_update(lttngevntheader) as lttnghdr_file:
+ lttnghdr_file.write(stdprolog + "\n")
+ lttnghdr_file.write("""
#include "palrt.h"
#include "pal.h"
@@ -675,20 +680,24 @@ bool WriteToBuffer(const char *str, char *&buffer, int& offset, int& size, bool
""")
- lTTngHdr.write("#define TRACEPOINT_PROVIDER " + providerName + "\n")
- lTTngHdr.write("""
+ lttnghdr_file.write("#define TRACEPOINT_PROVIDER " + providerName + "\n")
+ lttnghdr_file.write("""
#undef TRACEPOINT_INCLUDE
""")
- lTTngHdr.write("#define TRACEPOINT_INCLUDE \"./" + lttngevntheadershortname + "\"\n\n")
+ lttnghdr_file.write("#define TRACEPOINT_INCLUDE \"./" + lttngevntheadershortname + "\"\n\n")
+
+ lttnghdr_file.write("#if !defined(LTTNG_CORECLR_H" + providerName + ") || defined(TRACEPOINT_HEADER_MULTI_READ)\n\n")
+ lttnghdr_file.write("#define LTTNG_CORECLR_H" + providerName + "\n")
- lTTngHdr.write("#if !defined(LTTNG_CORECLR_H" + providerName + ") || defined(TRACEPOINT_HEADER_MULTI_READ)\n\n")
- lTTngHdr.write("#define LTTNG_CORECLR_H" + providerName + "\n")
+ lttnghdr_file.write("\n#include <lttng/tracepoint.h>\n\n")
- lTTngHdr.write("\n#include <lttng/tracepoint.h>\n\n")
+ lttnghdr_file.write(generateLttngHeader(providerName,allTemplates,eventNodes) + "\n")
- lTTngImpl.write("""
+ with open_for_update(lttngevntprov) as lttngimpl_file:
+ lttngimpl_file.write(stdprolog + "\n")
+ lttngimpl_file.write("""
#define TRACEPOINT_DEFINE
#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE
@@ -700,48 +709,43 @@ bool WriteToBuffer(const char *str, char *&buffer, int& offset, int& size, bool
#define PAL_realloc realloc
#include "pal/stackstring.hpp"
""")
- lTTngImpl.write("#include \"" + lttngevntheadershortname + "\"\n\n")
+ lttngimpl_file.write("#include \"" + lttngevntheadershortname + "\"\n\n")
- lTTngImpl.write("""#ifndef tracepoint_enabled
+ lttngimpl_file.write("""#ifndef tracepoint_enabled
#define tracepoint_enabled(provider, name) TRUE
#define do_tracepoint tracepoint
#endif
+#define wcslen PAL_wcslen
-bool ResizeBuffer(char *&buffer, int& size, int currLen, int newSize, bool &fixedBuffer);
-bool WriteToBuffer(PCWSTR str, char *&buffer, int& offset, int& size, bool &fixedBuffer);
-bool WriteToBuffer(const char *str, char *&buffer, int& offset, int& size, bool &fixedBuffer);
-bool WriteToBuffer(const BYTE *src, int len, char *&buffer, int& offset, int& size, bool &fixedBuffer);
+bool ResizeBuffer(char *&buffer, size_t& size, size_t currLen, size_t newSize, bool &fixedBuffer);
+bool WriteToBuffer(PCWSTR str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer);
+bool WriteToBuffer(const char *str, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer);
+bool WriteToBuffer(const BYTE *src, size_t len, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer);
template <typename T>
-bool WriteToBuffer(const T &value, char *&buffer, int& offset, int& size, bool &fixedBuffer)
+bool WriteToBuffer(const T &value, char *&buffer, size_t& offset, size_t& size, bool &fixedBuffer)
{
- if (sizeof(T) + offset > size)
- {
- if (!ResizeBuffer(buffer, size, offset, size + sizeof(T), fixedBuffer))
- return false;
- }
-
- *(T *)(buffer + offset) = value;
- offset += sizeof(T);
- return true;
+ if (sizeof(T) + offset > size)
+ {
+ if (!ResizeBuffer(buffer, size, offset, size + sizeof(T), fixedBuffer))
+ return false;
+ }
+
+ *(T *)(buffer + offset) = value;
+ offset += sizeof(T);
+ return true;
}
""")
+ lttngimpl_file.write(generateLttngTpProvider(providerName,eventNodes,allTemplates) + "\n")
- templateNodes = providerNode.getElementsByTagName('template')
- eventNodes = providerNode.getElementsByTagName('event')
-
- allTemplates = parseTemplateNodes(templateNodes)
- #generate the header
- lTTngHdr.write(generateLttngHeader(providerName,allTemplates,eventNodes) + "\n")
+ with open_for_update(lttngevntprovTp) as tpimpl_file:
+ tpimpl_file.write(stdprolog + "\n")
- #create the implementation of eventing functions : lttngeventprov*.cp
- lTTngImpl.write(generateLttngTpProvider(providerName,eventNodes,allTemplates) + "\n")
+ tpimpl_file.write("\n#define TRACEPOINT_CREATE_PROBES\n")
- lTTngHdr.close()
- lTTngImpl.close()
- lTTngTpImpl.close()
+ tpimpl_file.write("#include \"./"+lttngevntheadershortname + "\"\n")
import argparse
import sys
@@ -759,7 +763,7 @@ def main(argv):
args, unknown = parser.parse_known_args(argv)
if unknown:
print('Unknown argument(s): ', ', '.join(unknown))
- return const.UnknownArguments
+ return 1
sClrEtwAllMan = args.man
intermediate = args.intermediate
@@ -768,4 +772,4 @@ def main(argv):
if __name__ == '__main__':
return_code = main(sys.argv[1:])
- sys.exit(return_code)
+ sys.exit(return_code) \ No newline at end of file
diff --git a/src/scripts/genWinEtw.py b/src/scripts/genWinEtw.py
deleted file mode 100644
index aa75f680cd..0000000000
--- a/src/scripts/genWinEtw.py
+++ /dev/null
@@ -1,125 +0,0 @@
-
-## Licensed to the .NET Foundation under one or more agreements.
-## The .NET Foundation licenses this file to you under the MIT license.
-## See the LICENSE file in the project root for more information.
-#
-
-import os
-from genXplatEventing import *
-
-stdprolog="""
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-/******************************************************************
-
-DO NOT MODIFY. AUTOGENERATED FILE.
-This file is generated using the logic from <root>/src/scripts/genWinEtw.py
-
-******************************************************************/
-
-"""
-import argparse
-import sys
-import xml.dom.minidom as DOM
-
-def generateEtwMacroHeader(sClrEtwAllMan, sExcludeFile,macroHeader,inHeader):
- tree = DOM.parse(sClrEtwAllMan)
- numOfProviders = len(tree.getElementsByTagName('provider'))
- nMaxEventBytesPerProvider = 64
-
- exclusionInfo = parseExclusionList(sExcludeFile)
- incDir = os.path.dirname(os.path.realpath(macroHeader))
- if not os.path.exists(incDir):
- os.makedirs(incDir)
-
- outHeader = open(macroHeader,'w')
- outHeader.write(stdprolog + "\n")
-
- outHeader.write("#include \"" + os.path.basename(inHeader) + '"\n')
- outHeader.write("#define NO_OF_ETW_PROVIDERS " + str(numOfProviders) + "\n")
- outHeader.write("#define MAX_BYTES_PER_ETW_PROVIDER " + str(nMaxEventBytesPerProvider) + "\n")
- outHeader.write("EXTERN_C __declspec(selectany) const BYTE etwStackSupportedEvents[NO_OF_ETW_PROVIDERS][MAX_BYTES_PER_ETW_PROVIDER] = \n{\n")
-
- for providerNode in tree.getElementsByTagName('provider'):
- stackSupportedEvents = [0]*nMaxEventBytesPerProvider
- eventNodes = providerNode.getElementsByTagName('event')
- eventProvider = providerNode.getAttribute('name')
-
- for eventNode in eventNodes:
- taskName = eventNode.getAttribute('task')
- eventSymbol = eventNode.getAttribute('symbol')
- eventTemplate = eventNode.getAttribute('template')
- eventTemplate = eventNode.getAttribute('template')
- eventValue = int(eventNode.getAttribute('value'))
- eventIndex = eventValue // 8
- eventBitPositionInIndex = eventValue % 8
-
- eventStackBitFromNoStackList = int(getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.nostack))
- eventStackBitFromExplicitStackList = int(getStackWalkBit(eventProvider, taskName, eventSymbol, exclusionInfo.explicitstack))
-
- # Shift those bits into position. For the explicit stack list, swap 0 and 1, so the eventValue* variables
- # have 1 in the position iff we should issue a stack for the event.
- eventValueUsingNoStackListByPosition = (eventStackBitFromNoStackList << eventBitPositionInIndex)
- eventValueUsingExplicitStackListByPosition = ((1 - eventStackBitFromExplicitStackList) << eventBitPositionInIndex)
-
- # Commit the values to the in-memory array that we'll dump into the header file
- stackSupportedEvents[eventIndex] = stackSupportedEvents[eventIndex] | eventValueUsingNoStackListByPosition;
- if eventStackBitFromExplicitStackList == 0:
- stackSupportedEvents[eventIndex] = stackSupportedEvents[eventIndex] | eventValueUsingExplicitStackListByPosition
-
- # print the bit array
- line = []
- line.append("\t{")
- for elem in stackSupportedEvents:
- line.append(str(elem))
- line.append(", ")
-
- del line[-1]
- line.append("},")
- outHeader.write(''.join(line) + "\n")
- outHeader.write("};\n")
-
- outHeader.close()
-
-
-def generateEtwFiles(sClrEtwAllMan, exclusionListFile, etmdummyHeader, macroHeader, inHeader):
-
- checkConsistency(sClrEtwAllMan, exclusionListFile)
- generateEtmDummyHeader(sClrEtwAllMan, etmdummyHeader)
- generateEtwMacroHeader(sClrEtwAllMan, exclusionListFile, macroHeader, inHeader)
-
-def main(argv):
-
- #parse the command line
- parser = argparse.ArgumentParser(description="Generates the Code required to instrument LTTtng logging mechanism")
-
- 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('--eventheader', type=str, required=True,
- help='full path to the header file')
- required.add_argument('--macroheader', type=str, required=True,
- help='full path to the macro header file')
- required.add_argument('--dummy', type=str, required=True,
- help='full path to file that will have dummy definitions of FireEtw functions')
-
- args, unknown = parser.parse_known_args(argv)
- if unknown:
- print('Unknown argument(s): ', ', '.join(unknown))
- return const.UnknownArguments
-
- sClrEtwAllMan = args.man
- exclusionListFile = args.exc
- inHeader = args.eventheader
- macroHeader = args.macroheader
- etmdummyHeader = args.dummy
-
- generateEtwFiles(sClrEtwAllMan, exclusionListFile, etmdummyHeader, macroHeader, inHeader)
-
-if __name__ == '__main__':
- return_code = main(sys.argv[1:])
- sys.exit(return_code)
diff --git a/src/scripts/utilities.py b/src/scripts/utilities.py
new file mode 100644
index 0000000000..82e6c83346
--- /dev/null
+++ b/src/scripts/utilities.py
@@ -0,0 +1,115 @@
+##
+## Licensed to the .NET Foundation under one or more agreements.
+## The .NET Foundation licenses this file to you under the MIT license.
+## See the LICENSE file in the project root for more information.
+##
+## This file provides utility functions to the adjacent python scripts
+
+from filecmp import dircmp
+from hashlib import sha256
+from io import StringIO
+import shutil
+import sys
+import os
+
+class WrappedStringIO(StringIO):
+ """A wrapper around StringIO to allow writing str objects"""
+ def write(self, s):
+ if sys.version_info < (3, 0, 0):
+ if isinstance(s, str):
+ s = unicode(s)
+ super(WrappedStringIO, self).write(s)
+
+class UpdateFileWriter:
+ """A file-like context object which will only write to a file if the result would be different
+
+ Attributes:
+ filename (str): The name of the file to update
+ stream (WrappedStringIO): The file-like stream provided upon context enter
+
+ Args:
+ filename (str): Sets the filename attribute
+ """
+ filemode = 'w'
+
+ def __init__(self, filename):
+ self.filename = filename
+ self.stream = None
+
+ def __enter__(self):
+ self.stream = WrappedStringIO()
+ return self.stream
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ if exc_value is None:
+ new_content = self.stream.getvalue()
+ new_hash = sha256()
+ cur_hash = sha256()
+
+ try:
+ with open(self.filename, 'r') as fstream:
+ cur_hash.update(fstream.read().encode('utf-8'))
+ file_found = True
+ except IOError:
+ file_found = False
+
+ if file_found:
+ new_hash.update(new_content.encode('utf-8'))
+ update = new_hash.digest() != cur_hash.digest()
+ else:
+ update = True
+
+ if update:
+ with open(self.filename, 'w') as fstream:
+ fstream.write(new_content)
+
+ self.stream.close()
+
+def open_for_update(filename):
+ return UpdateFileWriter(filename)
+
+def walk_recursively_and_update(dcmp):
+ #for different Files Copy from right to left
+ for name in dcmp.diff_files:
+ srcpath = dcmp.right + "/" + name
+ destpath = dcmp.left + "/" + name
+ print("Updating %s" % (destpath))
+ if os.path.isfile(srcpath):
+ shutil.copyfile(srcpath, destpath)
+ else :
+ raise Exception("path: " + srcpath + "is neither a file or folder")
+
+ #copy right only files
+ for name in dcmp.right_only:
+ srcpath = dcmp.right + "/" + name
+ destpath = dcmp.left + "/" + name
+ print("Updating %s" % (destpath))
+ if os.path.isfile(srcpath):
+ shutil.copyfile(srcpath, destpath)
+ elif os.path.isdir(srcpath):
+ shutil.copytree(srcpath, destpath)
+ else :
+ raise Exception("path: " + srcpath + "is neither a file or folder")
+
+ #delete left only files
+ for name in dcmp.left_only:
+ path = dcmp.left + "/" + name
+ print("Deleting %s" % (path))
+ if os.path.isfile(path):
+ os.remove(path)
+ elif os.path.isdir(path):
+ shutil.rmtree(path)
+ else :
+ raise Exception("path: " + path + "is neither a file or folder")
+
+ #call recursively
+ for sub_dcmp in dcmp.subdirs.values():
+ walk_recursively_and_update(sub_dcmp)
+
+def UpdateDirectory(destpath,srcpath):
+
+ print("Updating %s with %s" % (destpath,srcpath))
+ if not os.path.exists(destpath):
+ os.makedirs(destpath)
+ dcmp = dircmp(destpath,srcpath)
+ walk_recursively_and_update(dcmp)
diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt
index f49d01bc91..97ab656f81 100644
--- a/src/vm/CMakeLists.txt
+++ b/src/vm/CMakeLists.txt
@@ -1,7 +1,7 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Needed due to the cmunged files being in the binary folders, the set(CMAKE_INCLUDE_CURRENT_DIR ON) is not enough
-include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${ARCH_SOURCES_DIR})
add_definitions(-DUNICODE)
@@ -9,7 +9,7 @@ add_definitions(-D_UNICODE)
if(CMAKE_CONFIGURATION_TYPES) # multi-configuration generator?
- foreach (Config DEBUG CHECKED)
+ foreach (Config DEBUG CHECKED)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:${Config}>:WRITE_BARRIER_CHECK=1>)
endforeach (Config)
else()
@@ -291,7 +291,7 @@ set(VM_SOURCES_DAC_AND_WKS_WIN32
winrttypenameconverter.cpp
)
-list(APPEND VM_SOURCES_WKS
+list(APPEND VM_SOURCES_WKS
${VM_SOURCES_DAC_AND_WKS_WIN32}
# These should not be included for Linux
appxutil.cpp
@@ -313,17 +313,17 @@ list(APPEND VM_SOURCES_WKS
extensibleclassfactory.cpp
mngstdinterfaces.cpp
notifyexternals.cpp
- olecontexthelpers.cpp
+ olecontexthelpers.cpp
rcwrefcache.cpp
rtlfunctions.cpp
runtimecallablewrapper.cpp
stacksampler.cpp
stdinterfaces.cpp
stdinterfaces_wrapper.cpp
- winrthelpers.cpp
+ winrthelpers.cpp
)
-list(APPEND VM_SOURCES_DAC
+list(APPEND VM_SOURCES_DAC
${VM_SOURCES_DAC_AND_WKS_WIN32}
# These should not be included for Linux
clrprivbinderwinrt.cpp
@@ -423,7 +423,7 @@ else(WIN32)
${ARCH_SOURCES_DIR}/pinvokestubs.S
)
endif()
-
+
endif(WIN32)
@@ -434,7 +434,7 @@ if(CLR_CMAKE_TARGET_ARCH_AMD64)
${ARCH_SOURCES_DIR}/gmsamd64.cpp
${ARCH_SOURCES_DIR}/stublinkeramd64.cpp
)
-
+
set(VM_SOURCES_WKS_ARCH
${ARCH_SOURCES_DIR}/jithelpersamd64.cpp
${ARCH_SOURCES_DIR}/jitinterfaceamd64.cpp
@@ -452,7 +452,7 @@ elseif(CLR_CMAKE_TARGET_ARCH_I386)
${ARCH_SOURCES_DIR}/gmsx86.cpp
${ARCH_SOURCES_DIR}/stublinkerx86.cpp
)
-
+
set(VM_SOURCES_WKS_ARCH
${ARCH_SOURCES_DIR}/jitinterfacex86.cpp
${ARCH_SOURCES_DIR}/profiler.cpp
@@ -465,7 +465,7 @@ elseif(CLR_CMAKE_TARGET_ARCH_ARM)
${ARCH_SOURCES_DIR}/stubs.cpp
${ARCH_SOURCES_DIR}/armsinglestepper.cpp
)
-
+
set(VM_SOURCES_WKS_ARCH
${ARCH_SOURCES_DIR}/jithelpersarm.cpp
${ARCH_SOURCES_DIR}/profiler.cpp
@@ -492,7 +492,7 @@ set(VM_SOURCES_DAC_ARCH
exceptionhandling.cpp
)
-list(APPEND VM_SOURCES_WKS
+list(APPEND VM_SOURCES_WKS
${VM_SOURCES_WKS_ARCH}
${VM_SOURCES_DAC_AND_WKS_ARCH}
)
@@ -519,6 +519,6 @@ convert_to_absolute_path(VM_SOURCES_DAC ${VM_SOURCES_DAC})
add_subdirectory(dac)
add_subdirectory(wks)
-if(CLR_CMAKE_PLATFORM_LINUX)
- add_subdirectory($ENV{__IntermediatesDir}/Generated/eventpipe ${CMAKE_CURRENT_BINARY_DIR}/eventpipe)
-endif(CLR_CMAKE_PLATFORM_LINUX)
+if(FEATURE_PERFTRACING)
+ add_subdirectory(${GENERATED_EVENTING_DIR}/eventpipe ${CMAKE_CURRENT_BINARY_DIR}/eventpipe)
+endif(FEATURE_PERFTRACING) \ No newline at end of file
diff --git a/src/vm/eventpipe.cpp b/src/vm/eventpipe.cpp
index 8f2e8ff937..37de4c3b36 100644
--- a/src/vm/eventpipe.cpp
+++ b/src/vm/eventpipe.cpp
@@ -2,9 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#include "common.h"
#include "clrtypes.h"
#include "safemath.h"
-#include "common.h"
#include "eventpipe.h"
#include "eventpipebuffermanager.h"
#include "eventpipeconfiguration.h"
@@ -33,11 +33,8 @@ EventPipeJsonFile* EventPipe::s_pJsonFile = NULL;
#ifdef FEATURE_PAL
// This function is auto-generated from /src/scripts/genEventPipe.py
extern "C" void InitProvidersAndEvents();
-#endif
-
-#ifdef FEATURE_PAL
-// This function is auto-generated from /src/scripts/genEventPipe.py
-extern "C" void InitProvidersAndEvents();
+#else
+void InitProvidersAndEvents();
#endif
EventPipeEventPayload::EventPipeEventPayload(BYTE *pData, unsigned int length)
@@ -97,7 +94,7 @@ EventPipeEventPayload::~EventPipeEventPayload()
CONTRACTL
{
NOTHROW;
- GC_TRIGGERS;
+ GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;
@@ -114,7 +111,7 @@ void EventPipeEventPayload::Flatten()
CONTRACTL
{
NOTHROW;
- GC_TRIGGERS;
+ GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;
@@ -168,7 +165,7 @@ BYTE* EventPipeEventPayload::GetFlatData()
CONTRACTL
{
NOTHROW;
- GC_TRIGGERS;
+ GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;
@@ -193,11 +190,9 @@ void EventPipe::Initialize()
s_pBufferManager = new EventPipeBufferManager();
-#ifdef FEATURE_PAL
// This calls into auto-generated code to initialize the runtime providers
// and events so that the EventPipe configuration lock isn't taken at runtime
InitProvidersAndEvents();
-#endif
}
void EventPipe::EnableOnStartup()
@@ -227,13 +222,19 @@ void EventPipe::Shutdown()
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_TRIGGERS;
MODE_ANY;
}
CONTRACTL_END;
- Disable();
+ // We are shutting down, so if diasabling EventPipe throws, we need to move along anyway
+ EX_TRY
+ {
+ Disable();
+ }
+ EX_CATCH { }
+ EX_END_CATCH(SwallowAllExceptions);
if(s_pConfig != NULL)
{
@@ -262,7 +263,13 @@ void EventPipe::Enable(
CONTRACTL_END;
// If tracing is not initialized or is already enabled, bail here.
- if(!s_tracingInitialized || s_pConfig->Enabled())
+ if(!s_tracingInitialized || s_pConfig == NULL || s_pConfig->Enabled())
+ {
+ return;
+ }
+
+ // If the state or aurguments are invalid, bail
+ if(pProviders == NULL || numProviders <= 0)
{
return;
}
@@ -312,7 +319,7 @@ void EventPipe::Disable()
// Take the lock before disabling tracing.
CrstHolder _crst(GetLock());
- if(s_pConfig->Enabled())
+ if(s_pConfig != NULL && s_pConfig->Enabled())
{
// Disable the profiler.
SampleProfiler::Disable();
@@ -468,7 +475,6 @@ void EventPipe::WriteEventInternal(EventPipeEvent &event, EventPipeEventPayload
NOTHROW;
GC_NOTRIGGER;
MODE_ANY;
- PRECONDITION(s_pBufferManager != NULL);
}
CONTRACTL_END;
@@ -486,6 +492,12 @@ void EventPipe::WriteEventInternal(EventPipeEvent &event, EventPipeEventPayload
return;
}
+ if(s_pConfig == NULL)
+ {
+ // We can't procede without a configuration
+ return;
+ }
+
if(!s_pConfig->RundownEnabled() && s_pBufferManager != NULL)
{
if(!s_pBufferManager->WriteEvent(pThread, event, payload, pActivityId, pRelatedActivityId))
@@ -501,6 +513,10 @@ void EventPipe::WriteEventInternal(EventPipeEvent &event, EventPipeEventPayload
{
// Write synchronously to the file.
// We're under lock and blocking the disabling thread.
+ // This copy occurs here (rather than at file write) because
+ // A) The FastSerializer API would need to change if we waited
+ // B) It is unclear there is a benefit to multiple file write calls
+ // as opposed a a buffer copy here
EventPipeEventInstance instance(
event,
pThread->GetOSThreadId(),
@@ -511,12 +527,22 @@ void EventPipe::WriteEventInternal(EventPipeEvent &event, EventPipeEventPayload
if(s_pFile != NULL)
{
- s_pFile->WriteEvent(instance);
+ // EventPipeFile::WriteEvent needs to allocate a metadata event
+ // and can therefore throw. In this context we will silently
+ // fail rather than disrupt the caller
+ EX_TRY
+ {
+ s_pFile->WriteEvent(instance);
+ }
+ EX_CATCH { }
+ EX_END_CATCH(SwallowAllExceptions);
}
}
}
-#ifdef _DEBUG
+// This section requires a call to GCX_PREEMP which violates the GC_NOTRIGGER contract
+// It should only be enabled when debugging this specific component and contracts are off
+#ifdef DEBUG_JSON_EVENT_FILE
{
GCX_PREEMP();
@@ -537,7 +563,7 @@ void EventPipe::WriteEventInternal(EventPipeEvent &event, EventPipeEventPayload
{
s_pSyncFile->WriteEvent(instance);
}
-
+
// Write to the EventPipeJsonFile if it exists.
if(s_pJsonFile != NULL)
{
@@ -545,7 +571,7 @@ void EventPipe::WriteEventInternal(EventPipeEvent &event, EventPipeEventPayload
}
}
}
-#endif // _DEBUG
+#endif // DEBUG_JSON_EVENT_FILE
}
void EventPipe::WriteSampleProfileEvent(Thread *pSamplingThread, EventPipeEvent *pEvent, Thread *pTargetThread, StackContents &stackContents, BYTE *pData, unsigned int length)
@@ -641,7 +667,7 @@ StackWalkAction EventPipe::StackWalkCallback(CrawlFrame *pCf, StackContents *pDa
{
NOTHROW;
GC_NOTRIGGER;
- MODE_PREEMPTIVE;
+ MODE_ANY;
PRECONDITION(pCf != NULL);
PRECONDITION(pData != NULL);
}
@@ -686,15 +712,15 @@ CrstStatic* EventPipe::GetLock()
void QCALLTYPE EventPipeInternal::Enable(
__in_z LPCWSTR outputFile,
- unsigned int circularBufferSizeInMB,
- long profilerSamplingRateInNanoseconds,
+ UINT32 circularBufferSizeInMB,
+ INT64 profilerSamplingRateInNanoseconds,
EventPipeProviderConfiguration *pProviders,
- int numProviders)
+ INT32 numProviders)
{
QCALL_CONTRACT;
BEGIN_QCALL;
- SampleProfiler::SetSamplingRate(profilerSamplingRateInNanoseconds);
+ SampleProfiler::SetSamplingRate((unsigned long)profilerSamplingRateInNanoseconds);
EventPipe::Enable(outputFile, circularBufferSizeInMB, pProviders, numProviders);
END_QCALL;
}
@@ -727,12 +753,12 @@ INT_PTR QCALLTYPE EventPipeInternal::CreateProvider(
INT_PTR QCALLTYPE EventPipeInternal::DefineEvent(
INT_PTR provHandle,
- unsigned int eventID,
+ UINT32 eventID,
__int64 keywords,
- unsigned int eventVersion,
- unsigned int level,
+ UINT32 eventVersion,
+ UINT32 level,
void *pMetadata,
- unsigned int metadataLength)
+ UINT32 metadataLength)
{
QCALL_CONTRACT;
@@ -768,9 +794,9 @@ void QCALLTYPE EventPipeInternal::DeleteProvider(
void QCALLTYPE EventPipeInternal::WriteEvent(
INT_PTR eventHandle,
- unsigned int eventID,
+ UINT32 eventID,
void *pData,
- unsigned int length,
+ UINT32 length,
LPCGUID pActivityId,
LPCGUID pRelatedActivityId)
{
@@ -786,9 +812,9 @@ void QCALLTYPE EventPipeInternal::WriteEvent(
void QCALLTYPE EventPipeInternal::WriteEventData(
INT_PTR eventHandle,
- unsigned int eventID,
+ UINT32 eventID,
EventData **pEventData,
- unsigned int eventDataCount,
+ UINT32 eventDataCount,
LPCGUID pActivityId,
LPCGUID pRelatedActivityId)
{
diff --git a/src/vm/eventpipe.h b/src/vm/eventpipe.h
index bac7be6ac8..4fd3d88127 100644
--- a/src/vm/eventpipe.h
+++ b/src/vm/eventpipe.h
@@ -6,8 +6,10 @@
#define __EVENTPIPE_H__
#ifdef FEATURE_PERFTRACING
+#include "common.h"
class CrstStatic;
+class CrawlFrame;
class EventPipeConfiguration;
class EventPipeEvent;
class EventPipeFile;
@@ -58,7 +60,7 @@ public:
// If a buffer was allocated internally, delete it
~EventPipeEventPayload();
-
+
// Copy the data (whether flat or array of objects) into a flat buffer at pDst
// Assumes that pDst points to an appropriatly sized buffer
void CopyData(BYTE *pDst);
@@ -259,7 +261,7 @@ class EventPipe
// Write out a sample profile event.
static void WriteSampleProfileEvent(Thread *pSamplingThread, EventPipeEvent *pEvent, Thread *pTargetThread, StackContents &stackContents, BYTE *pData = NULL, unsigned int length = 0);
-
+
// Get the managed call stack for the current thread.
static bool WalkManagedStackForCurrentThread(StackContents &stackContents);
@@ -301,7 +303,7 @@ private:
LPCWSTR m_pProviderName;
UINT64 m_keywords;
- unsigned int m_loggingLevel;
+ UINT32 m_loggingLevel;
public:
@@ -316,7 +318,7 @@ public:
EventPipeProviderConfiguration(
LPCWSTR pProviderName,
UINT64 keywords,
- unsigned int loggingLevel)
+ UINT32 loggingLevel)
{
LIMITED_METHOD_CONTRACT;
m_pProviderName = pProviderName;
@@ -336,7 +338,7 @@ public:
return m_keywords;
}
- unsigned int GetLevel() const
+ UINT32 GetLevel() const
{
LIMITED_METHOD_CONTRACT;
return m_loggingLevel;
@@ -350,10 +352,10 @@ public:
static void QCALLTYPE Enable(
__in_z LPCWSTR outputFile,
- unsigned int circularBufferSizeInMB,
- long profilerSamplingRateInNanoseconds,
+ UINT32 circularBufferSizeInMB,
+ INT64 profilerSamplingRateInNanoseconds,
EventPipeProviderConfiguration *pProviders,
- int numProviders);
+ INT32 numProviders);
static void QCALLTYPE Disable();
@@ -363,28 +365,28 @@ public:
static INT_PTR QCALLTYPE DefineEvent(
INT_PTR provHandle,
- unsigned int eventID,
+ UINT32 eventID,
__int64 keywords,
- unsigned int eventVersion,
- unsigned int level,
+ UINT32 eventVersion,
+ UINT32 level,
void *pMetadata,
- unsigned int metadataLength);
+ UINT32 metadataLength);
static void QCALLTYPE DeleteProvider(
INT_PTR provHandle);
static void QCALLTYPE WriteEvent(
INT_PTR eventHandle,
- unsigned int eventID,
+ UINT32 eventID,
void *pData,
- unsigned int length,
+ UINT32 length,
LPCGUID pActivityId, LPCGUID pRelatedActivityId);
static void QCALLTYPE WriteEventData(
INT_PTR eventHandle,
- unsigned int eventID,
+ UINT32 eventID,
EventData **pEventData,
- unsigned int eventDataCount,
+ UINT32 eventDataCount,
LPCGUID pActivityId, LPCGUID pRelatedActivityId);
};
diff --git a/src/vm/eventpipebuffer.cpp b/src/vm/eventpipebuffer.cpp
index 80b4a4f1b7..407c875fa6 100644
--- a/src/vm/eventpipebuffer.cpp
+++ b/src/vm/eventpipebuffer.cpp
@@ -35,7 +35,7 @@ EventPipeBuffer::~EventPipeBuffer()
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_NOTRIGGER;
MODE_ANY;
}
@@ -52,7 +52,7 @@ bool EventPipeBuffer::WriteEvent(Thread *pThread, EventPipeEvent &event, EventPi
CONTRACTL
{
NOTHROW;
- GC_TRIGGERS;
+ GC_NOTRIGGER;
MODE_ANY;
PRECONDITION(pThread != NULL);
}
@@ -143,7 +143,7 @@ EventPipeEventInstance* EventPipeBuffer::GetNext(EventPipeEventInstance *pEvent,
CONTRACTL
{
NOTHROW;
- GC_TRIGGERS;
+ GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;
diff --git a/src/vm/eventpipebuffermanager.cpp b/src/vm/eventpipebuffermanager.cpp
index e7d97d5732..045e1d999a 100644
--- a/src/vm/eventpipebuffermanager.cpp
+++ b/src/vm/eventpipebuffermanager.cpp
@@ -37,7 +37,7 @@ EventPipeBufferManager::~EventPipeBufferManager()
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_TRIGGERS;
MODE_ANY;
}
@@ -80,7 +80,7 @@ EventPipeBuffer* EventPipeBufferManager::AllocateBufferForThread(Thread *pThread
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_NOTRIGGER;
MODE_ANY;
PRECONDITION(pThread != NULL);
@@ -97,8 +97,19 @@ EventPipeBuffer* EventPipeBufferManager::AllocateBufferForThread(Thread *pThread
EventPipeBufferList *pThreadBufferList = pThread->GetEventPipeBufferList();
if(pThreadBufferList == NULL)
{
- pThreadBufferList = new EventPipeBufferList(this);
- m_pPerThreadBufferList->InsertTail(new SListElem<EventPipeBufferList*>(pThreadBufferList));
+ pThreadBufferList = new (nothrow) EventPipeBufferList(this);
+ if (pThreadBufferList == NULL)
+ {
+ return NULL;
+ }
+
+ SListElem<EventPipeBufferList*> *pElem = new (nothrow) SListElem<EventPipeBufferList*>(pThreadBufferList);
+ if (pElem == NULL)
+ {
+ return NULL;
+ }
+
+ m_pPerThreadBufferList->InsertTail(pElem);
pThread->SetEventPipeBufferList(pThreadBufferList);
allocateNewBuffer = true;
}
@@ -181,7 +192,24 @@ EventPipeBuffer* EventPipeBufferManager::AllocateBufferForThread(Thread *pThread
bufferSize = requestSize;
}
- pNewBuffer = new EventPipeBuffer(bufferSize);
+ // EX_TRY is used here as opposed to new (nothrow) because
+ // the constructor also allocates a private buffer, which
+ // could throw, and cannot be easily checked
+ EX_TRY
+ {
+ pNewBuffer = new EventPipeBuffer(bufferSize);
+ }
+ EX_CATCH
+ {
+ pNewBuffer = NULL;
+ }
+ EX_END_CATCH(SwallowAllExceptions);
+
+ if (pNewBuffer == NULL)
+ {
+ return NULL;
+ }
+
m_sizeOfAllBuffers += bufferSize;
#ifdef _DEBUG
m_numBuffersAllocated++;
@@ -202,7 +230,7 @@ EventPipeBufferList* EventPipeBufferManager::FindThreadToStealFrom()
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_NOTRIGGER;
MODE_ANY;
PRECONDITION(m_lock.OwnedByCurrentThread());
@@ -362,7 +390,7 @@ void EventPipeBufferManager::WriteAllBuffersToFile(EventPipeFile *pFile, LARGE_I
{
CONTRACTL
{
- NOTHROW;
+ THROWS;
GC_NOTRIGGER;
MODE_ANY;
PRECONDITION(pFile != NULL);
diff --git a/src/vm/eventpipeconfiguration.cpp b/src/vm/eventpipeconfiguration.cpp
index ae1dd4e099..a74bdbc28f 100644
--- a/src/vm/eventpipeconfiguration.cpp
+++ b/src/vm/eventpipeconfiguration.cpp
@@ -20,6 +20,7 @@ EventPipeConfiguration::EventPipeConfiguration()
m_rundownEnabled = false;
m_circularBufferSizeInBytes = 1024 * 1024 * 1000; // Default to 1000MB.
m_pEnabledProviderList = NULL;
+ m_pConfigProvider = NULL;
m_pProviderList = new SList<SListElem<EventPipeProvider*>>();
}
@@ -27,7 +28,7 @@ EventPipeConfiguration::~EventPipeConfiguration()
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_TRIGGERS;
MODE_ANY;
}
@@ -35,8 +36,15 @@ EventPipeConfiguration::~EventPipeConfiguration()
if(m_pConfigProvider != NULL)
{
- delete(m_pConfigProvider);
- m_pConfigProvider = NULL;
+ // This unregisters the provider, which takes a
+ // HOST_BREAKABLE lock
+ EX_TRY
+ {
+ DeleteProvider(m_pConfigProvider);
+ m_pConfigProvider = NULL;
+ }
+ EX_CATCH { }
+ EX_END_CATCH(SwallowAllExceptions);
}
if(m_pEnabledProviderList != NULL)
@@ -47,19 +55,28 @@ EventPipeConfiguration::~EventPipeConfiguration()
if(m_pProviderList != NULL)
{
- // Take the lock before manipulating the provider list.
- CrstHolder _crst(EventPipe::GetLock());
-
- SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
- while(pElem != NULL)
+ // We swallow exceptions here because the HOST_BREAKABLE
+ // lock may throw and this destructor gets called in throw
+ // intolerant places. If that happens the provider list will leak
+ EX_TRY
{
- // We don't delete provider itself because it can be in-use
- SListElem<EventPipeProvider*> *pCurElem = pElem;
- pElem = m_pProviderList->GetNext(pElem);
- delete(pCurElem);
+ // Take the lock before manipulating the list.
+ CrstHolder _crst(EventPipe::GetLock());
+
+ SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
+ while(pElem != NULL)
+ {
+ // We don't delete provider itself because it can be in-use
+ SListElem<EventPipeProvider*> *pCurElem = pElem;
+ pElem = m_pProviderList->GetNext(pElem);
+ delete(pCurElem);
+ }
+
+ delete(m_pProviderList);
}
+ EX_CATCH { }
+ EX_END_CATCH(SwallowAllExceptions);
- delete(m_pProviderList);
m_pProviderList = NULL;
}
}
@@ -110,7 +127,7 @@ void EventPipeConfiguration::DeleteProvider(EventPipeProvider *pProvider)
CONTRACTL
{
THROWS;
- GC_NOTRIGGER;
+ GC_TRIGGERS;
MODE_ANY;
PRECONDITION(pProvider != NULL);
}
@@ -177,7 +194,7 @@ bool EventPipeConfiguration::UnregisterProvider(EventPipeProvider &provider)
CONTRACTL
{
THROWS;
- GC_NOTRIGGER;
+ GC_TRIGGERS;
MODE_ANY;
}
CONTRACTL_END;
@@ -271,7 +288,7 @@ size_t EventPipeConfiguration::GetCircularBufferSize() const
void EventPipeConfiguration::SetCircularBufferSize(size_t circularBufferSize)
{
LIMITED_METHOD_CONTRACT;
-
+
if(!m_enabled)
{
m_circularBufferSizeInBytes = circularBufferSize;
@@ -484,9 +501,7 @@ void EventPipeConfiguration::DeleteDeferredProviders()
pElem = m_pProviderList->GetNext(pElem);
if(pProvider->GetDeleteDeferred())
{
- // The act of deleting the provider unregisters it,
- // removes it from the list, and deletes the list element
- delete(pProvider);
+ DeleteProvider(pProvider);
}
}
}
@@ -525,7 +540,7 @@ EventPipeEnabledProviderList::EventPipeEnabledProviderList(
}
m_pProviders = new EventPipeEnabledProvider[m_numProviders];
- for(int i=0; i<m_numProviders; i++)
+ for(unsigned int i=0; i<m_numProviders; i++)
{
m_pProviders[i].Set(
pConfigs[i].GetProviderName(),
@@ -538,7 +553,7 @@ EventPipeEnabledProviderList::~EventPipeEnabledProviderList()
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_NOTRIGGER;
MODE_ANY;
}
@@ -582,7 +597,7 @@ EventPipeEnabledProvider* EventPipeEnabledProviderList::GetEnabledProvider(
LPCWSTR providerName = providerNameStr.GetUnicode();
EventPipeEnabledProvider *pEnabledProvider = NULL;
- for(int i=0; i<m_numProviders; i++)
+ for(unsigned int i=0; i<m_numProviders; i++)
{
EventPipeEnabledProvider *pCandidate = &m_pProviders[i];
if(pCandidate != NULL)
@@ -609,7 +624,7 @@ EventPipeEnabledProvider::~EventPipeEnabledProvider()
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_NOTRIGGER;
MODE_ANY;
}
@@ -640,7 +655,7 @@ void EventPipeEnabledProvider::Set(LPCWSTR providerName, UINT64 keywords, EventP
if(providerName != NULL)
{
- unsigned int bufSize = wcslen(providerName) + 1;
+ size_t bufSize = wcslen(providerName) + 1;
m_pProviderName = new WCHAR[bufSize];
wcscpy_s(m_pProviderName, bufSize, providerName);
}
diff --git a/src/vm/eventpipeevent.cpp b/src/vm/eventpipeevent.cpp
index abf942b253..1b2d4ebe40 100644
--- a/src/vm/eventpipeevent.cpp
+++ b/src/vm/eventpipeevent.cpp
@@ -40,6 +40,14 @@ EventPipeEvent::EventPipeEvent(EventPipeProvider &provider, INT64 keywords, unsi
EventPipeEvent::~EventPipeEvent()
{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
if (m_pMetadata != NULL)
{
delete[] m_pMetadata;
diff --git a/src/vm/eventpipeeventinstance.cpp b/src/vm/eventpipeeventinstance.cpp
index 305b6dac04..6cb7438639 100644
--- a/src/vm/eventpipeeventinstance.cpp
+++ b/src/vm/eventpipeeventinstance.cpp
@@ -20,8 +20,8 @@ EventPipeEventInstance::EventPipeEventInstance(
{
CONTRACTL
{
- THROWS;
- GC_TRIGGERS;
+ NOTHROW;
+ GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;
@@ -102,8 +102,8 @@ void EventPipeEventInstance::FastSerialize(FastSerializer *pSerializer, StreamLa
{
CONTRACTL
{
- THROWS;
- GC_TRIGGERS;
+ NOTHROW;
+ GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;
diff --git a/src/vm/eventpipefile.cpp b/src/vm/eventpipefile.cpp
index 26e04480ee..ba4eb39b29 100644
--- a/src/vm/eventpipefile.cpp
+++ b/src/vm/eventpipefile.cpp
@@ -62,7 +62,7 @@ EventPipeFile::~EventPipeFile()
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_TRIGGERS;
MODE_ANY;
}
@@ -87,7 +87,7 @@ void EventPipeFile::WriteEvent(EventPipeEventInstance &instance)
CONTRACTL
{
THROWS;
- GC_TRIGGERS;
+ GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;
@@ -126,8 +126,8 @@ StreamLabel EventPipeFile::GetMetadataLabel(EventPipeEvent &event)
{
CONTRACTL
{
- THROWS;
- GC_TRIGGERS;
+ NOTHROW;
+ GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;
@@ -147,7 +147,7 @@ void EventPipeFile::SaveMetadataLabel(EventPipeEvent &event, StreamLabel label)
CONTRACTL
{
THROWS;
- GC_TRIGGERS;
+ GC_NOTRIGGER;
MODE_ANY;
PRECONDITION(label > 0);
}
diff --git a/src/vm/eventpipejsonfile.cpp b/src/vm/eventpipejsonfile.cpp
index 2edd6f4366..aa60df7b07 100644
--- a/src/vm/eventpipejsonfile.cpp
+++ b/src/vm/eventpipejsonfile.cpp
@@ -38,7 +38,7 @@ EventPipeJsonFile::~EventPipeJsonFile()
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_TRIGGERS;
MODE_ANY;
}
@@ -59,14 +59,26 @@ EventPipeJsonFile::~EventPipeJsonFile()
void EventPipeJsonFile::WriteEvent(EventPipeEventInstance &instance)
{
- STANDARD_VM_CONTRACT;
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
instance.SerializeToJsonFile(this);
}
void EventPipeJsonFile::WriteEvent(LARGE_INTEGER timeStamp, DWORD threadID, SString &message, StackContents &stackContents)
{
- STANDARD_VM_CONTRACT;
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
if(m_pFileStream == NULL || m_writeErrorEncountered)
{
@@ -98,7 +110,7 @@ void EventPipeJsonFile::Write(SString &str)
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_TRIGGERS;
MODE_ANY;
}
@@ -106,19 +118,35 @@ void EventPipeJsonFile::Write(SString &str)
StackScratchBuffer scratch;
const char * charStr = str.GetANSI(scratch);
- ULONG inCount = str.GetCount();
- ULONG outCount;
- m_pFileStream->Write(charStr, inCount, &outCount);
- if(inCount != outCount)
+ EX_TRY
+ {
+ ULONG inCount = str.GetCount();
+ ULONG outCount;
+
+ m_pFileStream->Write(charStr, inCount, &outCount);
+
+ if(inCount != outCount)
+ {
+ m_writeErrorEncountered = true;
+ }
+ }
+ EX_CATCH
{
m_writeErrorEncountered = true;
}
+ EX_END_CATCH(SwallowAllExceptions);
}
void EventPipeJsonFile::FormatCallStack(StackContents &stackContents, SString &resultStr)
{
- STANDARD_VM_CONTRACT;
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
StackScratchBuffer scratch;
SString frameStr;
diff --git a/src/vm/eventpipeprovider.cpp b/src/vm/eventpipeprovider.cpp
index c10dd33638..84a90e4abb 100644
--- a/src/vm/eventpipeprovider.cpp
+++ b/src/vm/eventpipeprovider.cpp
@@ -24,6 +24,7 @@ EventPipeProvider::EventPipeProvider(EventPipeConfiguration *pConfig, const SStr
m_providerName = providerName;
m_enabled = false;
+ m_deleteDeferred = false;
m_keywords = 0;
m_providerLevel = EventPipeEventLevel::Critical;
m_pEventList = new SList<SListElem<EventPipeEvent*>>();
@@ -36,8 +37,8 @@ EventPipeProvider::~EventPipeProvider()
{
CONTRACTL
{
- THROWS;
- GC_NOTRIGGER;
+ NOTHROW;
+ GC_TRIGGERS;
MODE_ANY;
}
CONTRACTL_END;
@@ -45,21 +46,30 @@ EventPipeProvider::~EventPipeProvider()
// Free all of the events.
if(m_pEventList != NULL)
{
- // Take the lock before manipulating the list.
- CrstHolder _crst(EventPipe::GetLock());
-
- SListElem<EventPipeEvent*> *pElem = m_pEventList->GetHead();
- while(pElem != NULL)
+ // We swallow exceptions here because the HOST_BREAKABLE
+ // lock may throw and this destructor gets called in throw
+ // intolerant places. If that happens the event list will leak
+ EX_TRY
{
- EventPipeEvent *pEvent = pElem->GetValue();
- delete pEvent;
+ // Take the lock before manipulating the list.
+ CrstHolder _crst(EventPipe::GetLock());
+
+ SListElem<EventPipeEvent*> *pElem = m_pEventList->GetHead();
+ while(pElem != NULL)
+ {
+ EventPipeEvent *pEvent = pElem->GetValue();
+ delete pEvent;
+
+ SListElem<EventPipeEvent*> *pCurElem = pElem;
+ pElem = m_pEventList->GetNext(pElem);
+ delete pCurElem;
+ }
- SListElem<EventPipeEvent*> *pCurElem = pElem;
- pElem = m_pEventList->GetNext(pElem);
- delete pCurElem;
+ delete m_pEventList;
}
+ EX_CATCH { }
+ EX_END_CATCH(SwallowAllExceptions);
- delete m_pEventList;
m_pEventList = NULL;
}
}
diff --git a/src/vm/eventpipeprovider.h b/src/vm/eventpipeprovider.h
index 405ce32154..0ffe46f887 100644
--- a/src/vm/eventpipeprovider.h
+++ b/src/vm/eventpipeprovider.h
@@ -31,9 +31,6 @@ class EventPipeProvider
friend class SampleProfiler;
private:
- // The GUID of the provider.
- GUID m_providerID;
-
// The name of the provider.
SString m_providerName;
diff --git a/src/vm/fastserializer.cpp b/src/vm/fastserializer.cpp
index 8e0e0ad768..66fce30793 100644
--- a/src/vm/fastserializer.cpp
+++ b/src/vm/fastserializer.cpp
@@ -40,7 +40,7 @@ FastSerializer::~FastSerializer()
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_TRIGGERS;
MODE_ANY;
}
@@ -98,7 +98,7 @@ void FastSerializer::WriteBuffer(BYTE *pBuffer, unsigned int length)
CONTRACTL
{
NOTHROW;
- GC_TRIGGERS;
+ GC_NOTRIGGER;
MODE_PREEMPTIVE;
PRECONDITION(pBuffer != NULL);
PRECONDITION(length > 0);
@@ -263,7 +263,7 @@ void FastSerializer::WriteFileHeader()
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_TRIGGERS;
MODE_ANY;
}
@@ -278,7 +278,7 @@ void FastSerializer::WriteString(const char *strContents, unsigned int length)
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_TRIGGERS;
MODE_PREEMPTIVE;
}
@@ -295,7 +295,7 @@ StreamLabel FastSerializer::WriteForwardReferenceTable()
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_TRIGGERS;
MODE_PREEMPTIVE;
}
@@ -317,7 +317,7 @@ void FastSerializer::WriteTrailer(StreamLabel forwardReferencesTableStart)
{
CONTRACTL
{
- THROWS;
+ NOTHROW;
GC_TRIGGERS;
MODE_PREEMPTIVE;
}
diff --git a/src/vm/mscorlib.cpp b/src/vm/mscorlib.cpp
index 3e2d478bbf..75c1f058f0 100644
--- a/src/vm/mscorlib.cpp
+++ b/src/vm/mscorlib.cpp
@@ -96,6 +96,10 @@
#include "eventpipe.h"
#endif //defined(FEATURE_EVENTSOURCE_XPLAT)
+#ifdef FEATURE_PERFTRACING
+#include "eventpipe.h"
+#endif //FEATURE_PERFTRACING
+
#endif // CROSSGEN_MSCORLIB
diff --git a/src/vm/sampleprofiler.cpp b/src/vm/sampleprofiler.cpp
index d99667eea2..ade21669c4 100644
--- a/src/vm/sampleprofiler.cpp
+++ b/src/vm/sampleprofiler.cpp
@@ -11,6 +11,13 @@
#ifdef FEATURE_PERFTRACING
+#ifndef FEATURE_PAL
+#include <mmsystem.h>
+#endif //FEATURE_PAL
+
+// To avoid counting zeros in conversions
+#define MILLION * 1000000
+
Volatile<BOOL> SampleProfiler::s_profilingEnabled = false;
Thread* SampleProfiler::s_pSamplingThread = NULL;
const WCHAR* SampleProfiler::s_providerName = W("Microsoft-DotNETCore-SampleProfiler");
@@ -19,7 +26,16 @@ EventPipeEvent* SampleProfiler::s_pThreadTimeEvent = NULL;
BYTE* SampleProfiler::s_pPayloadExternal = NULL;
BYTE* SampleProfiler::s_pPayloadManaged = NULL;
CLREventStatic SampleProfiler::s_threadShutdownEvent;
-long SampleProfiler::s_samplingRateInNs = 1000000; // 1ms
+unsigned long SampleProfiler::s_samplingRateInNs = 1 MILLION; // 1ms
+bool SampleProfiler::s_timePeriodIsSet = FALSE;
+
+#ifndef FEATURE_PAL
+PVOID SampleProfiler::s_timeBeginPeriodFn = NULL;
+PVOID SampleProfiler::s_timeEndPeriodFn = NULL;
+HINSTANCE SampleProfiler::s_hMultimediaLib = NULL;
+
+typedef MMRESULT (WINAPI *TimePeriodFnPtr) (UINT uPeriod);
+#endif //FEATURE_PAL
void SampleProfiler::Enable()
{
@@ -33,6 +49,8 @@ void SampleProfiler::Enable()
PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
}
CONTRACTL_END;
+
+ LoadDependencies();
if(s_pEventPipeProvider == NULL)
{
@@ -72,6 +90,10 @@ void SampleProfiler::Enable()
{
_ASSERT(!"Unable to create sample profiler thread.");
}
+
+ s_threadShutdownEvent.CreateManualEvent(FALSE);
+
+ SetTimeGranularity();
}
void SampleProfiler::Disable()
@@ -101,12 +123,32 @@ void SampleProfiler::Disable()
// Wait for the sampling thread to clean itself up.
s_threadShutdownEvent.Wait(0, FALSE /* bAlertable */);
+
+ if(s_timePeriodIsSet)
+ {
+ ResetTimeGranularity();
+ }
+ UnloadDependencies();
}
-void SampleProfiler::SetSamplingRate(long nanoseconds)
+void SampleProfiler::SetSamplingRate(unsigned long nanoseconds)
{
LIMITED_METHOD_CONTRACT;
+
+ // If the time period setting was modified by us,
+ // make sure to change it back before changing our period
+ // and losing track of what we set it to
+ if(s_timePeriodIsSet)
+ {
+ ResetTimeGranularity();
+ }
+
s_samplingRateInNs = nanoseconds;
+
+ if(!s_timePeriodIsSet)
+ {
+ SetTimeGranularity();
+ }
}
DWORD WINAPI SampleProfiler::ThreadProc(void *args)
@@ -132,7 +174,7 @@ DWORD WINAPI SampleProfiler::ThreadProc(void *args)
if(ThreadSuspend::SysIsSuspendInProgress() || (ThreadSuspend::GetSuspensionThread() != 0))
{
// Skip the current sample.
- PAL_nanosleep(s_samplingRateInNs);
+ PlatformSleep(s_samplingRateInNs);
continue;
}
@@ -146,7 +188,7 @@ DWORD WINAPI SampleProfiler::ThreadProc(void *args)
ThreadSuspend::RestartEE(FALSE /* bFinishedGC */, TRUE /* SuspendSucceeded */);
// Wait until it's time to sample again.
- PAL_nanosleep(s_samplingRateInNs);
+ PlatformSleep(s_samplingRateInNs);
}
}
@@ -156,7 +198,7 @@ DWORD WINAPI SampleProfiler::ThreadProc(void *args)
// Signal Disable() that the thread has been destroyed.
s_threadShutdownEvent.Set();
-
+
return S_OK;
}
@@ -201,4 +243,115 @@ void SampleProfiler::WalkManagedThreads()
}
}
+void SampleProfiler::PlatformSleep(unsigned long nanoseconds)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+#ifdef FEATURE_PAL
+ PAL_nanosleep(nanoseconds);
+#else //FEATURE_PAL
+ ClrSleepEx(s_samplingRateInNs / 1 MILLION, FALSE);
+#endif //FEATURE_PAL
+}
+
+void SampleProfiler::SetTimeGranularity()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+#ifndef FEATURE_PAL
+ // Attempt to set the systems minimum timer period to the sampling rate
+ // If the sampling rate is lower than the current system setting (16ms by default),
+ // this will cause the OS to wake more often for scheduling descsion, allowing us to take samples
+ // Note that is effects a system-wide setting and when set low will increase the amount of time
+ // the OS is on-CPU, decreasing overall system performance and increasing power consumption
+ if(s_timeBeginPeriodFn != NULL)
+ {
+ if(((TimePeriodFnPtr) s_timeBeginPeriodFn)(s_samplingRateInNs / 1 MILLION) == TIMERR_NOERROR)
+ {
+ s_timePeriodIsSet = TRUE;
+ }
+ }
+#endif //FEATURE_PAL
+}
+
+void SampleProfiler::ResetTimeGranularity()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+#ifndef FEATURE_PAL
+ // End the modifications we had to the timer period in Enable
+ if(s_timeEndPeriodFn != NULL)
+ {
+ if(((TimePeriodFnPtr) s_timeEndPeriodFn)(s_samplingRateInNs / 1 MILLION) == TIMERR_NOERROR)
+ {
+ s_timePeriodIsSet = FALSE;
+ }
+ }
+#endif //FEATURE_PAL
+}
+
+bool SampleProfiler::LoadDependencies()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+#ifndef FEATURE_PAL
+ s_hMultimediaLib = WszLoadLibrary(W("winmm.dll"));
+
+ if (s_hMultimediaLib != NULL)
+ {
+ s_timeBeginPeriodFn = (PVOID) GetProcAddress(s_hMultimediaLib, "timeBeginPeriod");
+ s_timeEndPeriodFn = (PVOID) GetProcAddress(s_hMultimediaLib, "timeEndPeriod");
+ }
+
+ return s_hMultimediaLib != NULL && s_timeBeginPeriodFn != NULL && s_timeEndPeriodFn != NULL;
+#else
+ return FALSE;
+#endif //FEATURE_PAL
+}
+
+void SampleProfiler::UnloadDependencies()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+#ifndef FEATURE_PAL
+ if (s_hMultimediaLib != NULL)
+ {
+ FreeLibrary(s_hMultimediaLib);
+ s_hMultimediaLib = NULL;
+ s_timeBeginPeriodFn = NULL;
+ s_timeEndPeriodFn = NULL;
+ }
+#endif //FEATURE_PAL
+}
+
#endif // FEATURE_PERFTRACING
diff --git a/src/vm/sampleprofiler.h b/src/vm/sampleprofiler.h
index 51290b4d9c..1bee70e8f6 100644
--- a/src/vm/sampleprofiler.h
+++ b/src/vm/sampleprofiler.h
@@ -33,7 +33,7 @@ class SampleProfiler
static void Disable();
// Set the sampling rate.
- static void SetSamplingRate(long nanoseconds);
+ static void SetSamplingRate(unsigned long nanoseconds);
private:
@@ -43,6 +43,31 @@ class SampleProfiler
// Profiling thread proc. Invoked on a new thread when profiling is enabled.
static DWORD WINAPI ThreadProc(void *args);
+ // Calls either PAL_nanosleep or ClrSleepEx depending on platform
+ // Note: Although we specify the time in ns, that is no indication
+ // of the actually accuracy with which we will return from sleep
+ // In reality Unix will have a minimum granularity of ~10ms
+ // and Windows has a default granularity of ~16ms, but can be
+ // adjusted to as low as ~1ms
+ // Even this however is not gaurenteed. If the system is under load
+ // the sampling thread may be delayed up to hundreds of ms due to
+ // scheduling priority. There is no way to prevent this from user threads
+ // Additionally we may get lucky and there will be an open CPU to run
+ // and under light load the timings will achieve great accuracy!
+ static void PlatformSleep(unsigned long nanoseconds);
+
+ static bool LoadDependencies();
+ static void UnloadDependencies();
+
+#ifndef FEATURE_PAL
+ static HINSTANCE s_hMultimediaLib;
+ static PVOID s_timeBeginPeriodFn;
+ static PVOID s_timeEndPeriodFn;
+#endif //FEATURE_PAL
+
+ static void SetTimeGranularity();
+ static void ResetTimeGranularity();
+
// True when profiling is enabled.
static Volatile<BOOL> s_profilingEnabled;
@@ -65,7 +90,10 @@ class SampleProfiler
static CLREventStatic s_threadShutdownEvent;
// The sampling rate.
- static long s_samplingRateInNs;
+ static unsigned long s_samplingRateInNs;
+
+ // Whether or not timeBeginPeriod has been used to set the scheduler period
+ static bool s_timePeriodIsSet;
};
#endif // FEATURE_PERFTRACING
diff --git a/tests/runtest.proj b/tests/runtest.proj
index 9c12e275d7..3ab7b9f708 100644
--- a/tests/runtest.proj
+++ b/tests/runtest.proj
@@ -12,7 +12,6 @@
<ItemGroup>
<DisabledTestDir Include="Common" />
- <DisabledTestDir Include="tracing" />
<_SkipTestDir Include="@(DisabledTestDir)" />
</ItemGroup>
@@ -404,4 +403,4 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\","").
<Target Name="Clean">
<RemoveDir Condition=" '$(BuildWrappers)'=='true'" Directories="$(XunitWrapperGeneratedCSDirBase);$(XunitWrapperOutputIntermediatedDirBase)" ContinueOnError="WarnAndContinue" />
</Target>
-</Project> \ No newline at end of file
+</Project>
diff --git a/tests/src/CoreMangLib/cti/system/convert/convertfrombase64string.cs b/tests/src/CoreMangLib/cti/system/convert/convertfrombase64string.cs
index f6b3927147..e91dde147f 100644
--- a/tests/src/CoreMangLib/cti/system/convert/convertfrombase64string.cs
+++ b/tests/src/CoreMangLib/cti/system/convert/convertfrombase64string.cs
@@ -81,10 +81,10 @@ public class ConvertFromBase64String
try
{
byte[] output = Convert.FromBase64String(input);
- if (!Utilities.CompareBytes(output, expected))
+ if (!TestLibrary.Utilities.CompareBytes(output, expected))
{
TestFramework.LogInformation("Input string: " + input);
- TestFramework.LogError("001", "Conversion not correct. Expect: " + Utilities.ByteArrayToString(expected) + ", Actual: " + Utilities.ByteArrayToString(output));
+ TestFramework.LogError("001", "Conversion not correct. Expect: " + TestLibrary.Utilities.ByteArrayToString(expected) + ", Actual: " + TestLibrary.Utilities.ByteArrayToString(output));
retVal = false;
}
}
diff --git a/tests/src/CoreMangLib/cti/system/string/stringcompare9.cs b/tests/src/CoreMangLib/cti/system/string/stringcompare9.cs
index 230d45f915..75d59aae19 100644
--- a/tests/src/CoreMangLib/cti/system/string/stringcompare9.cs
+++ b/tests/src/CoreMangLib/cti/system/string/stringcompare9.cs
@@ -128,10 +128,10 @@ public class StringCompare
try
{
- CultureInfo oldCi = Utilities.CurrentCulture;
- Utilities.CurrentCulture = new CultureInfo("hu-HU");
+ CultureInfo oldCi = TestLibrary.Utilities.CurrentCulture;
+ TestLibrary.Utilities.CurrentCulture = new CultureInfo("hu-HU");
retVal &= TestStrings("dzsdzs", "ddzs");
- Utilities.CurrentCulture = oldCi;
+ TestLibrary.Utilities.CurrentCulture = oldCi;
retVal &= TestStrings("\u00C0nimal", "A\u0300nimal");
@@ -210,7 +210,7 @@ public class StringCompare
StringBuilder output = new StringBuilder();
for (int i = 0; i < str.Length; i++)
{
- output.Append(Utilities.ByteArrayToString(BitConverter.GetBytes(str[i])));
+ output.Append(TestLibrary.Utilities.ByteArrayToString(BitConverter.GetBytes(str[i])));
if (i != (str.Length - 1)) output.Append(", ");
}
return output.ToString();
diff --git a/tests/src/CoreMangLib/cti/system/string/stringequals6.cs b/tests/src/CoreMangLib/cti/system/string/stringequals6.cs
index be60b76ed9..fa89733729 100644
--- a/tests/src/CoreMangLib/cti/system/string/stringequals6.cs
+++ b/tests/src/CoreMangLib/cti/system/string/stringequals6.cs
@@ -127,10 +127,10 @@ public class StringEquals
try
{
- CultureInfo oldCi = Utilities.CurrentCulture;
- Utilities.CurrentCulture = new CultureInfo("hu-HU");
+ CultureInfo oldCi = TestLibrary.Utilities.CurrentCulture;
+ TestLibrary.Utilities.CurrentCulture = new CultureInfo("hu-HU");
retVal &= TestStrings("dzsdzs", "ddzs");
- Utilities.CurrentCulture = oldCi;
+ TestLibrary.Utilities.CurrentCulture = oldCi;
retVal &= TestStrings("\u00C0nimal", "A\u0300nimal");
@@ -207,7 +207,7 @@ public class StringEquals
StringBuilder output = new StringBuilder();
for (int i = 0; i < str.Length; i++)
{
- output.Append(Utilities.ByteArrayToString(BitConverter.GetBytes(str[i])));
+ output.Append(TestLibrary.Utilities.ByteArrayToString(BitConverter.GetBytes(str[i])));
if (i != (str.Length - 1)) output.Append(", ");
}
return output.ToString();
diff --git a/tests/src/CoreMangLib/cti/system/string/stringindexof10.cs b/tests/src/CoreMangLib/cti/system/string/stringindexof10.cs
index 3d037dcd65..979d96ff49 100644
--- a/tests/src/CoreMangLib/cti/system/string/stringindexof10.cs
+++ b/tests/src/CoreMangLib/cti/system/string/stringindexof10.cs
@@ -91,10 +91,10 @@ public class StringIndexOf
try
{
- CultureInfo oldCi = Utilities.CurrentCulture;
- Utilities.CurrentCulture = new CultureInfo("hu-HU");
+ CultureInfo oldCi = TestLibrary.Utilities.CurrentCulture;
+ TestLibrary.Utilities.CurrentCulture = new CultureInfo("hu-HU");
retVal &= TestStrings("Foodzsdzsbar", "ddzs");
- Utilities.CurrentCulture = oldCi;
+ TestLibrary.Utilities.CurrentCulture = oldCi;
retVal &= TestStrings("\u00C0nimal", "A\u0300");
@@ -177,7 +177,7 @@ public class StringIndexOf
StringBuilder output = new StringBuilder();
for (int i = 0; i < str.Length; i++)
{
- output.Append(Utilities.ByteArrayToString(BitConverter.GetBytes(str[i])));
+ output.Append(TestLibrary.Utilities.ByteArrayToString(BitConverter.GetBytes(str[i])));
if (i != (str.Length - 1)) output.Append(", ");
}
return output.ToString();
diff --git a/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetbytes1.cs b/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetbytes1.cs
index 2ea8d51fd0..c25f168360 100644
--- a/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetbytes1.cs
+++ b/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetbytes1.cs
@@ -318,10 +318,10 @@ class EncodingGetBytes1
try
{
byte[] bytes = enc.GetBytes(str);
- if (!Utilities.CompareBytes(bytes, expected))
+ if (!TestLibrary.Utilities.CompareBytes(bytes, expected))
{
result = false;
- TestFramework.LogError("001", "Error in " + id + ", unexpected comparison result. Actual bytes " + Utilities.ByteArrayToString(bytes) + ", Expected: " + Utilities.ByteArrayToString(expected));
+ TestFramework.LogError("001", "Error in " + id + ", unexpected comparison result. Actual bytes " + TestLibrary.Utilities.ByteArrayToString(bytes) + ", Expected: " + TestLibrary.Utilities.ByteArrayToString(expected));
}
}
catch (Exception exc)
@@ -340,7 +340,7 @@ class EncodingGetBytes1
{
byte[] bytes = enc.GetBytes(str);
result = false;
- TestFramework.LogError("005", "Error in " + id + ", Expected exception not thrown. Actual bytes " + Utilities.ByteArrayToString(bytes) + ", Expected exception type: " + excType.ToString());
+ TestFramework.LogError("005", "Error in " + id + ", Expected exception not thrown. Actual bytes " + TestLibrary.Utilities.ByteArrayToString(bytes) + ", Expected exception type: " + excType.ToString());
}
catch (Exception exc)
{
@@ -360,10 +360,10 @@ class EncodingGetBytes1
try
{
byte[] bytes = enc.GetBytes(chars);
- if (!Utilities.CompareBytes(bytes, expected))
+ if (!TestLibrary.Utilities.CompareBytes(bytes, expected))
{
result = false;
- TestFramework.LogError("003", "Error in " + id + ", unexpected comparison result. Actual bytes " + Utilities.ByteArrayToString(bytes) + ", Expected: " + Utilities.ByteArrayToString(expected));
+ TestFramework.LogError("003", "Error in " + id + ", unexpected comparison result. Actual bytes " + TestLibrary.Utilities.ByteArrayToString(bytes) + ", Expected: " + TestLibrary.Utilities.ByteArrayToString(expected));
}
}
catch (Exception exc)
@@ -382,7 +382,7 @@ class EncodingGetBytes1
{
byte[] bytes = enc.GetBytes(str);
result = false;
- TestFramework.LogError("007", "Error in " + id + ", Expected exception not thrown. Actual bytes " + Utilities.ByteArrayToString(bytes) + ", Expected exception type: " + excType.ToString());
+ TestFramework.LogError("007", "Error in " + id + ", Expected exception not thrown. Actual bytes " + TestLibrary.Utilities.ByteArrayToString(bytes) + ", Expected exception type: " + excType.ToString());
}
catch (Exception exc)
{
@@ -403,7 +403,7 @@ class EncodingGetBytes1
{
byte[] bytes = enc.GetBytes(str, index, count);
result = false;
- TestFramework.LogError("009", "Error in " + id + ", Expected exception not thrown. Actual bytes " + Utilities.ByteArrayToString(bytes) + ", Expected exception type: " + excType.ToString());
+ TestFramework.LogError("009", "Error in " + id + ", Expected exception not thrown. Actual bytes " + TestLibrary.Utilities.ByteArrayToString(bytes) + ", Expected exception type: " + excType.ToString());
}
catch (Exception exc)
{
@@ -424,7 +424,7 @@ class EncodingGetBytes1
{
int output = enc.GetBytes(str, index, count, bytes, bIndex);
result = false;
- TestFramework.LogError("011", "Error in " + id + ", Expected exception not thrown. Actual bytes " + Utilities.ByteArrayToString(bytes) + ", Expected exception type: " + excType.ToString());
+ TestFramework.LogError("011", "Error in " + id + ", Expected exception not thrown. Actual bytes " + TestLibrary.Utilities.ByteArrayToString(bytes) + ", Expected exception type: " + excType.ToString());
}
catch (Exception exc)
{
@@ -445,7 +445,7 @@ class EncodingGetBytes1
{
int output = enc.GetBytes(str, index, count, bytes, bIndex);
result = false;
- TestFramework.LogError("013", "Error in " + id + ", Expected exception not thrown. Actual bytes " + Utilities.ByteArrayToString(bytes) + ", Expected exception type: " + excType.ToString());
+ TestFramework.LogError("013", "Error in " + id + ", Expected exception not thrown. Actual bytes " + TestLibrary.Utilities.ByteArrayToString(bytes) + ", Expected exception type: " + excType.ToString());
}
catch (Exception exc)
{
diff --git a/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetcharcount.cs b/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetcharcount.cs
index cc1953ce88..1f61bbdeba 100644
--- a/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetcharcount.cs
+++ b/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetcharcount.cs
Binary files differ
diff --git a/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetchars1.cs b/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetchars1.cs
index 0f24507700..e191e01173 100644
--- a/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetchars1.cs
+++ b/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetchars1.cs
Binary files differ
diff --git a/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetstring.cs b/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetstring.cs
index 44289f7b0d..f4116e4d3f 100644
--- a/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetstring.cs
+++ b/tests/src/CoreMangLib/cti/system/text/encoding/encodinggetstring.cs
Binary files differ
diff --git a/tests/src/CoreMangLib/cti/system/timespan/timespantostring_str.cs b/tests/src/CoreMangLib/cti/system/timespan/timespantostring_str.cs
index 4d5e5493d9..b9faa109d9 100644
--- a/tests/src/CoreMangLib/cti/system/timespan/timespantostring_str.cs
+++ b/tests/src/CoreMangLib/cti/system/timespan/timespantostring_str.cs
@@ -22,8 +22,8 @@ public class TimeSpanTest
if ((args.Length > 0) && args[0].ToLower() == "true")
verbose = true;
- Logging.WriteLine("CurrentCulture: " + Utilities.CurrentCulture.Name);
- Logging.WriteLine("CurrentUICulture: " + Utilities.CurrentCulture.Name);
+ Logging.WriteLine("CurrentCulture: " + TestLibrary.Utilities.CurrentCulture.Name);
+ Logging.WriteLine("CurrentUICulture: " + TestLibrary.Utilities.CurrentCulture.Name);
RunTests();
}
@@ -50,7 +50,7 @@ public class TimeSpanTest
// The current implementation uses the same character as the default NumberDecimalSeparator
// for a culture, but this is an implementation detail and could change. No user overrides
// are respected.
- String GDecimalSeparator = Utilities.CurrentCulture.NumberFormat.NumberDecimalSeparator;
+ String GDecimalSeparator = TestLibrary.Utilities.CurrentCulture.NumberFormat.NumberDecimalSeparator;
// Standard formats
foreach (TimeSpan ts in Support.InterestingTimeSpans)
{
@@ -169,7 +169,7 @@ public class TimeSpanTest
// Vary current culture
- Utilities.CurrentCulture = CultureInfo.InvariantCulture;
+ TestLibrary.Utilities.CurrentCulture = CultureInfo.InvariantCulture;
foreach (TimeSpan ts in Support.InterestingTimeSpans)
{
String defaultFormat = Support.CFormat(ts);
@@ -183,7 +183,7 @@ public class TimeSpanTest
VerifyToString(ts, "G", Support.GFormat(ts, "."));
}
- Utilities.CurrentCulture = new CultureInfo("en-US");
+ TestLibrary.Utilities.CurrentCulture = new CultureInfo("en-US");
foreach (TimeSpan ts in Support.InterestingTimeSpans)
{
String defaultFormat = Support.CFormat(ts);
@@ -197,7 +197,7 @@ public class TimeSpanTest
VerifyToString(ts, "G", Support.GFormat(ts, "."));
}
- Utilities.CurrentCulture = new CultureInfo("de-DE");
+ TestLibrary.Utilities.CurrentCulture = new CultureInfo("de-DE");
foreach (TimeSpan ts in Support.InterestingTimeSpans)
{
String defaultFormat = Support.CFormat(ts);
diff --git a/tests/src/CoreMangLib/cti/system/uint64/uint64tostring2.cs b/tests/src/CoreMangLib/cti/system/uint64/uint64tostring2.cs
index 8d4f23f442..497efe39c6 100644
--- a/tests/src/CoreMangLib/cti/system/uint64/uint64tostring2.cs
+++ b/tests/src/CoreMangLib/cti/system/uint64/uint64tostring2.cs
@@ -23,7 +23,7 @@ public class UInt64ToString1
retVal = PosTest5() && retVal;
TestLibrary.TestFramework.LogInformation("[Negative]");
- if (Utilities.IsWindows)
+ if (TestLibrary.Utilities.IsWindows)
{
// retVal = NegTest1() && retVal; // Disabled until neutral cultures are available
}
diff --git a/tests/src/Interop/BestFitMapping/BestFitMapping.cs b/tests/src/Interop/BestFitMapping/BestFitMapping.cs
index 643ddc9d21..1778d79e4e 100755
--- a/tests/src/Interop/BestFitMapping/BestFitMapping.cs
+++ b/tests/src/Interop/BestFitMapping/BestFitMapping.cs
Binary files differ
diff --git a/tests/src/JIT/config/benchmark+roslyn/benchmark+roslyn.csproj b/tests/src/JIT/config/benchmark+roslyn/benchmark+roslyn.csproj
index 77cba12414..563a9a7087 100644
--- a/tests/src/JIT/config/benchmark+roslyn/benchmark+roslyn.csproj
+++ b/tests/src/JIT/config/benchmark+roslyn/benchmark+roslyn.csproj
@@ -67,6 +67,9 @@
<PackageReference Include="System.Threading">
<Version>4.4.0-beta-24913-02</Version>
</PackageReference>
+ <PackageReference Include="System.Threading.Thread">
+ <Version>4.4.0-beta-24913-02</Version>
+ </PackageReference>
<PackageReference Include="System.Threading.Tasks">
<Version>4.4.0-beta-24913-02</Version>
</PackageReference>
diff --git a/tests/src/JIT/config/benchmark/benchmark.csproj b/tests/src/JIT/config/benchmark/benchmark.csproj
index 5ade686330..4d49fdee3e 100644
--- a/tests/src/JIT/config/benchmark/benchmark.csproj
+++ b/tests/src/JIT/config/benchmark/benchmark.csproj
@@ -76,6 +76,9 @@
<PackageReference Include="System.Threading">
<Version>4.4.0-beta-24913-02</Version>
</PackageReference>
+ <PackageReference Include="System.Threading.Thread">
+ <Version>4.4.0-beta-24913-02</Version>
+ </PackageReference>
<PackageReference Include="System.Threading.Tasks">
<Version>4.4.0-beta-24913-02</Version>
</PackageReference>
diff --git a/tests/src/dirs.proj b/tests/src/dirs.proj
index 471598d82d..cb1c1b000d 100644
--- a/tests/src/dirs.proj
+++ b/tests/src/dirs.proj
@@ -30,6 +30,8 @@
<DisabledProjects Include="Performance\performance.csproj" />
<DisabledProjects Include="Loader\classloader\generics\regressions\DD117522\Test.csproj" />
<DisabledProjects Include="Loader\classloader\generics\GenericMethods\VSW491668.csproj" /> <!-- issue 5501 -->
+ <DisabledProjects Include="tracing\eventsource*\*.csproj" />
+ <DisabledProjects Include="tracing\eventpipe*\*.csproj" />
</ItemGroup>
<ItemGroup>
diff --git a/tests/src/performance/performance.csproj b/tests/src/performance/performance.csproj
index 8c2cd3c7de..94caf35ac2 100644
--- a/tests/src/performance/performance.csproj
+++ b/tests/src/performance/performance.csproj
@@ -70,6 +70,9 @@
<PackageReference Include="System.Threading">
<Version>4.4.0-beta-24913-02</Version>
</PackageReference>
+ <PackageReference Include="System.Threading.Thread">
+ <Version>4.4.0-beta-24913-02</Version>
+ </PackageReference>
<PackageReference Include="System.Threading.Tasks">
<Version>4.4.0-beta-24913-02</Version>
</PackageReference>
diff --git a/tests/src/tracing/common/common.csproj b/tests/src/tracing/common/common.csproj
index ca34349b16..ca10e7ffe2 100644
--- a/tests/src/tracing/common/common.csproj
+++ b/tests/src/tracing/common/common.csproj
@@ -12,7 +12,7 @@
<CLRTestKind>BuildOnly</CLRTestKind>
<DefineConstants>$(DefineConstants);STATIC</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <CLRTestPriority>1</CLRTestPriority>
+ <CLRTestPriority>0</CLRTestPriority>
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
diff --git a/tests/src/tracing/eventlistener/EventListener.cs b/tests/src/tracing/eventlistener/EventListener.cs
new file mode 100644
index 0000000000..dcadd622e7
--- /dev/null
+++ b/tests/src/tracing/eventlistener/EventListener.cs
@@ -0,0 +1,77 @@
+using System;
+using System.IO;
+using System.Diagnostics.Tracing;
+using Tracing.Tests.Common;
+
+namespace Tracing.Tests
+{
+ [EventSource(Name = "SimpleEventSource")]
+ class SimpleEventSource : EventSource
+ {
+ public SimpleEventSource() : base(true) { }
+
+ [Event(1)]
+ internal void MathResult(int x, int y, int z, string formula) { this.WriteEvent(1, x, y, z, formula); }
+ }
+
+ internal sealed class SimpleEventListener : EventListener
+ {
+ private readonly string _targetSourceName;
+ private readonly EventLevel _level;
+
+ public int EventCount { get; private set; } = 0;
+
+ public SimpleEventListener(string targetSourceName, EventLevel level)
+ {
+ // Store the arguments
+ _targetSourceName = targetSourceName;
+ _level = level;
+ }
+
+ protected override void OnEventSourceCreated(EventSource source)
+ {
+ if (source.Name.Equals(_targetSourceName))
+ {
+ EnableEvents(source, _level);
+ }
+ }
+
+ protected override void OnEventWritten(EventWrittenEventArgs eventData)
+ {
+ EventCount++;
+ }
+ }
+
+ class EventPipeSmoke
+ {
+ private static int messageIterations = 100;
+
+ static int Main(string[] args)
+ {
+ bool pass = false;
+ using(var listener = new SimpleEventListener("SimpleEventSource", EventLevel.Verbose))
+ {
+ SimpleEventSource eventSource = new SimpleEventSource();
+
+ Console.WriteLine("\tStart: Messaging.");
+ // Send messages
+ // Use random numbers and addition as a simple, human readble checksum
+ Random generator = new Random();
+ for(int i=0; i<messageIterations; i++)
+ {
+ int x = generator.Next(1,1000);
+ int y = generator.Next(1,1000);
+ string formula = String.Format("{0} + {1} = {2}", x, y, x+y);
+
+ eventSource.MathResult(x, y, x+y, formula);
+ }
+ Console.WriteLine("\tEnd: Messaging.\n");
+
+ Console.WriteLine($"\tEventListener recieved {listener.EventCount} event(s)\n");
+ pass = listener.EventCount == messageIterations;
+ }
+
+ return pass ? 100 : -1;
+ }
+ }
+}
diff --git a/tests/src/tracing/eventlistener/eventlistener.csproj b/tests/src/tracing/eventlistener/eventlistener.csproj
new file mode 100644
index 0000000000..9002d93e12
--- /dev/null
+++ b/tests/src/tracing/eventlistener/eventlistener.csproj
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{8E3244CB-407F-4142-BAAB-E7A55901A5FA}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <CLRTestKind>BuildAndRun</CLRTestKind>
+ <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <CLRTestPriority>0</CLRTestPriority>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ </PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="EventListener.cs" />
+ <ProjectReference Include="../common/common.csproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/tracing/eventpipesmoke/EventPipeSmoke.cs b/tests/src/tracing/eventpipesmoke/EventPipeSmoke.cs
index c12893d38a..2fa8786fd2 100644
--- a/tests/src/tracing/eventpipesmoke/EventPipeSmoke.cs
+++ b/tests/src/tracing/eventpipesmoke/EventPipeSmoke.cs
@@ -1,7 +1,5 @@
using System;
-using System.Threading.Tasks;
using System.IO;
-
using Tracing.Tests.Common;
namespace Tracing.Tests
diff --git a/tests/src/tracing/eventpipesmoke/eventpipesmoke.csproj b/tests/src/tracing/eventpipesmoke/eventpipesmoke.csproj
index 8ba6eb5c4a..4a1cd0c0ce 100644
--- a/tests/src/tracing/eventpipesmoke/eventpipesmoke.csproj
+++ b/tests/src/tracing/eventpipesmoke/eventpipesmoke.csproj
@@ -12,7 +12,7 @@
<CLRTestKind>BuildAndRun</CLRTestKind>
<DefineConstants>$(DefineConstants);STATIC</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <CLRTestPriority>1</CLRTestPriority>
+ <CLRTestPriority>0</CLRTestPriority>
</PropertyGroup>
<!-- Default configurations to help VS understand the configurations -->
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
diff --git a/tests/src/tracing/eventpipetrace/EventPipeTrace.cs b/tests/src/tracing/eventpipetrace/EventPipeTrace.cs
new file mode 100644
index 0000000000..af0c619ef9
--- /dev/null
+++ b/tests/src/tracing/eventpipetrace/EventPipeTrace.cs
@@ -0,0 +1,110 @@
+using System;
+using System.IO;
+using Tracing.Tests.Common;
+using Microsoft.Diagnostics.Tracing;
+using Microsoft.Diagnostics.Tracing.Parsers;
+using Microsoft.Diagnostics.Tracing.Parsers.Clr;
+
+namespace Tracing.Tests
+{
+ class EventPipeTrace
+ {
+ private static int allocIterations = 10000;
+ private static int gcIterations = 10;
+
+ static void AssertEqual<T>(T left, T right) where T : IEquatable<T>
+ {
+ if (left.Equals(right) == false)
+ {
+ throw new Exception(string.Format("Values were not equal! {0} and {1}", left, right));
+ }
+ }
+
+ static int Main(string[] args)
+ {
+ bool pass = true;
+ bool keepOutput = false;
+
+ // Use the first arg as an output filename if there is one
+ string outputFilename = null;
+ if (args.Length >= 1) {
+ outputFilename = args[0];
+ keepOutput = true;
+ }
+ else {
+ outputFilename = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".netperf";
+ }
+
+ try
+ {
+ Console.WriteLine("\tStart: Enable tracing.");
+ TraceControl.EnableDefault(outputFilename);
+ Console.WriteLine("\tEnd: Enable tracing.\n");
+
+ Console.WriteLine("\tStart: Generating CLR events");
+ // Allocate for allocIterations iterations.
+ for(int i=0; i<allocIterations; i++)
+ {
+ GC.KeepAlive(new object());
+ }
+ // GC gcIternation times
+ for(int i=0; i<gcIterations; i++)
+ {
+ GC.Collect();
+ }
+ Console.WriteLine("\tEnd: Generating CLR Events\n");
+
+ Console.WriteLine("\tStart: Disable tracing.");
+ TraceControl.Disable();
+ Console.WriteLine("\tEnd: Disable tracing.\n");
+
+ Console.WriteLine("\tStart: Processing events from file.");
+ int allocTickCount = 0;
+ int gcTriggerCount = 0;
+ using (var trace = TraceEventDispatcher.GetDispatcherFromFileName(outputFilename))
+ {
+ trace.Clr.GCAllocationTick += delegate(GCAllocationTickTraceData data)
+ {
+ allocTickCount += 1;
+
+ // Some basic integrity checks
+ // AssertEqual(data.TypeName, "System.Object"); https://github.com/Microsoft/perfview/issues/470
+ AssertEqual(data.AllocationKind.ToString(), GCAllocationKind.Small.ToString());
+ AssertEqual(data.ProviderName, "Microsoft-Windows-DotNETRuntime");
+ AssertEqual(data.EventName, "GC/AllocationTick");
+ };
+ trace.Clr.GCTriggered += delegate(GCTriggeredTraceData data)
+ {
+ gcTriggerCount += 1;
+
+ // Some basic integrity checks
+ AssertEqual(data.Reason.ToString(), GCReason.Induced.ToString());
+ AssertEqual(data.ProviderName, "Microsoft-Windows-DotNETRuntime");
+ AssertEqual(data.EventName, "GC/Triggered");
+ };
+
+ trace.Process();
+ }
+ Console.WriteLine("\tEnd: Processing events from file.\n");
+
+ Console.WriteLine("\tProcessed {0} GCAllocationTick events", allocTickCount);
+ Console.WriteLine("\tProcessed {0} GCTriggered events", gcTriggerCount);
+
+ pass &= allocTickCount > 0;
+ pass &= gcTriggerCount == gcIterations;
+ }
+ finally {
+ if (keepOutput)
+ {
+ Console.WriteLine("\n\tOutput file: {0}", outputFilename);
+ }
+ else
+ {
+ System.IO.File.Delete(outputFilename);
+ }
+ }
+
+ return pass ? 100 : 0;
+ }
+ }
+}
diff --git a/tests/src/tracing/eventpipetrace/eventpipetrace.csproj b/tests/src/tracing/eventpipetrace/eventpipetrace.csproj
new file mode 100644
index 0000000000..ec7305abe9
--- /dev/null
+++ b/tests/src/tracing/eventpipetrace/eventpipetrace.csproj
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{8E3244CB-407F-4142-BAAB-E7A55901A5FA}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <CLRTestKind>BuildAndRun</CLRTestKind>
+ <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <CLRTestPriority>0</CLRTestPriority>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="EventPipeTrace.cs" />
+ <ProjectReference Include="../common/common.csproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/tests/src/tracing/eventsourcesmoke/EventSourceSmoke.cs b/tests/src/tracing/eventsourcesmoke/EventSourceSmoke.cs
index b7d321dde6..ddd5192e18 100644
--- a/tests/src/tracing/eventsourcesmoke/EventSourceSmoke.cs
+++ b/tests/src/tracing/eventsourcesmoke/EventSourceSmoke.cs
@@ -1,8 +1,6 @@
using System;
-using System.Threading.Tasks;
using System.IO;
using System.Diagnostics.Tracing;
-
using Tracing.Tests.Common;
namespace Tracing.Tests
diff --git a/tests/src/tracing/eventsourcetrace/EventSourceTrace.cs b/tests/src/tracing/eventsourcetrace/EventSourceTrace.cs
new file mode 100644
index 0000000000..57a53183ed
--- /dev/null
+++ b/tests/src/tracing/eventsourcetrace/EventSourceTrace.cs
@@ -0,0 +1,131 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using Tracing.Tests.Common;
+using System.Diagnostics.Tracing;
+using Microsoft.Diagnostics.Tracing;
+using Microsoft.Diagnostics.Tracing.Parsers;
+using Microsoft.Diagnostics.Tracing.Parsers.Clr;
+
+namespace Tracing.Tests
+{
+ [EventSource(Name = "SimpleEventSource")]
+ class SimpleEventSource : EventSource
+ {
+ public SimpleEventSource() : base(true) { }
+
+ [Event(1)]
+ internal void MathResult(int x, int y, int z, string formula) { this.WriteEvent(1, x, y, z, formula); }
+ }
+
+ class EventSourceTrace
+ {
+ private static int messageIterations = 10000;
+
+ public static TraceConfiguration GetConfig(EventSource eventSource, string outputFile="default.netperf")
+ {
+ // Setup the configuration values.
+ uint circularBufferMB = 1024; // 1 GB
+ uint level = 5;//(uint)EventLevel.Informational;
+ TimeSpan profSampleDelay = TimeSpan.FromMilliseconds(1);
+
+ // Create a new instance of EventPipeConfiguration.
+ TraceConfiguration config = new TraceConfiguration(outputFile, circularBufferMB);
+ // Setup the provider values.
+ // Public provider.
+ string providerName = eventSource.Name;
+ UInt64 keywords = 0xffffffffffffffff;
+
+ // Enable the provider.
+ config.EnableProvider(providerName, keywords, level);
+
+ // Set the sampling rate.
+ config.SetSamplingRate(profSampleDelay);
+
+ return config;
+ }
+
+ static int Main(string[] args)
+ {
+ bool pass = true;
+ bool keepOutput = false;
+
+ // Use the first arg as an output filename if there is one
+ string outputFilename = null;
+ if (args.Length >= 1) {
+ outputFilename = args[0];
+ keepOutput = true;
+ }
+ else {
+ outputFilename = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".netperf";
+ }
+
+ SimpleEventSource eventSource = new SimpleEventSource();
+
+ try
+ {
+ Console.WriteLine("\tStart: Enable tracing.");
+ TraceControl.Enable(GetConfig(eventSource, outputFilename));
+ Console.WriteLine("\tEnd: Enable tracing.\n");
+
+ Console.WriteLine("\tStart: Messaging.");
+ // Send messages
+ // Use random numbers and addition as a simple, human readble checksum
+ Random generator = new Random();
+ for(int i=0; i<messageIterations; i++)
+ {
+ int x = generator.Next(1,1000);
+ int y = generator.Next(1,1000);
+ string formula = String.Format("{0} + {1} = {2}", x, y, x+y);
+
+ eventSource.MathResult(x, y, x+y, formula);
+ }
+ Console.WriteLine("\tEnd: Messaging.\n");
+
+ Console.WriteLine("\tStart: Disable tracing.");
+ TraceControl.Disable();
+ Console.WriteLine("\tEnd: Disable tracing.\n");
+
+ Console.WriteLine("\tStart: Processing events from file.");
+ int msgCount = 0;
+ using (var trace = TraceEventDispatcher.GetDispatcherFromFileName(outputFilename))
+ {
+ var names = new HashSet<string>();
+
+ trace.Dynamic.All += delegate(TraceEvent data)
+ {
+ if (!names.Contains(data.ProviderName))
+ {
+ Console.WriteLine("\t{0}", data.ProviderName);
+ names.Add(data.ProviderName);
+ }
+
+ if (data.ProviderName == "SimpleEventSource")
+ {
+ msgCount += 1;
+ }
+ };
+
+ trace.Process();
+ }
+ Console.WriteLine("\tEnd: Processing events from file.\n");
+
+ Console.WriteLine("\tProcessed {0} events from EventSource", msgCount);
+
+ pass &= msgCount == messageIterations;
+ }
+ finally {
+ if (keepOutput)
+ {
+ Console.WriteLine("\n\tOutput file: {0}", outputFilename);
+ }
+ else
+ {
+ System.IO.File.Delete(outputFilename);
+ }
+ }
+
+ return pass ? 100 : 0;
+ }
+ }
+}
diff --git a/tests/src/tracing/eventsourcetrace/eventsourcetrace.csproj b/tests/src/tracing/eventsourcetrace/eventsourcetrace.csproj
new file mode 100644
index 0000000000..833146ec64
--- /dev/null
+++ b/tests/src/tracing/eventsourcetrace/eventsourcetrace.csproj
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{8E3244CB-407F-4142-BAAB-E7A55901A5FA}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <CLRTestKind>BuildAndRun</CLRTestKind>
+ <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <CLRTestPriority>1</CLRTestPriority>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="EventSourceTrace.cs" />
+ <ProjectReference Include="../common/common.csproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file