Merge pull request #5194 from xmcclure/orbis-freeswept
authorAndi McClure <andi.mcclure@xamarin.com>
Mon, 17 Jul 2017 17:48:53 +0000 (13:48 -0400)
committerGitHub <noreply@github.com>
Mon, 17 Jul 2017 17:48:53 +0000 (13:48 -0400)
Do not major_free_swept_blocks on Orbis.

90 files changed:
CODEOWNERS [new file with mode: 0644]
CONTRIBUTING.md
acceptance-tests/profiler-stress/runner.cs
external/corefx
libgc/include/gc.h
mcs/build/tests.make
mcs/class/Microsoft.Build/Test/Microsoft.Build.Execution/BuildSubmissionTest.cs
mcs/class/Mono.Profiler.Log/Mono.Profiler.Log.dll.sources
mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogEnums.cs
mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogProcessor.cs
mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogProfiler.cs [new file with mode: 0644]
mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogRuntimeProfiler.cs [deleted file]
mcs/class/System.DirectoryServices/Test/System.DirectoryServices/DirectoryServicesDirectoryEntryTest.cs
mcs/class/System.DirectoryServices/Test/System.DirectoryServices/DirectoryServicesDirectorySearcherTest.cs
mcs/class/System.DirectoryServices/Test/System.DirectoryServices/DirectoryServicesSearchResultTest.cs
mcs/class/System.Drawing/System.Drawing-net_4_x.csproj
mcs/class/System.Drawing/System.Drawing.dll.sources
mcs/class/System.Numerics/System.Numerics-net_4_x.csproj
mcs/class/System.Numerics/System.Numerics.dll.sources
mcs/class/System.Numerics/System.Numerics_xtest.dll.sources
mcs/class/System.Web.Services/System.Web.Services.Protocols/SoapHttpClientProtocol.cs
mcs/class/System.Web.Services/Test/System.Web.Services.Discovery/DiscoveryClientProtocolTest.cs
mcs/class/System.Windows.Forms/Makefile
mcs/class/System/Mono.Net.Security/MonoTlsStream.cs
mcs/class/System/ReferenceSources/Win32Exception.cs
mcs/class/System/System.Net/AuthenticationManager.cs
mcs/class/System/System.Net/Dns.cs
mcs/class/System/System.Net/EndPointManager.cs
mcs/class/System/System.Net/FtpWebRequest.cs
mcs/class/System/System.Net/HttpWebRequest.cs
mcs/class/System/Test/System.Net.Sockets/NetworkStreamCas.cs
mcs/class/System/Test/System.Net.Sockets/SocketCas.cs
mcs/class/System/Test/System.Net.Sockets/SocketTest.cs
mcs/class/System/Test/System.Net.Sockets/TcpClientCas.cs
mcs/class/System/Test/System.Net/HttpWebRequestTest.cs
mcs/class/System/Test/System.Net/ServicePointManagerTest.cs
mcs/class/System/Test/System.Net/ServicePointTest.cs
mcs/class/System/Test/System.Net/WebClientTest.cs
mcs/class/System/Test/System.Net/WebClientTestAsync.cs
mcs/class/System/Test/System.Security.Cryptography.X509Certificates/X509ChainTest.cs
mcs/class/corlib/Test/System.Reflection.Emit/EnumBuilderTest.cs
mcs/class/corlib/Test/System/TypeTest.cs
mcs/class/test-helpers/NunitHelpers.cs
mono/metadata/assembly.c
mono/metadata/boehm-gc.c
mono/metadata/loader.c
mono/metadata/profiler-events.h
mono/metadata/profiler-private.h
mono/metadata/profiler.c
mono/metadata/profiler.h
mono/metadata/sgen-client-mono.h
mono/metadata/string-icalls.c
mono/metadata/w32error.h
mono/metadata/w32file-win32.c
mono/metadata/w32socket-unix.c
mono/mini/aot-compiler.c
mono/mini/driver.c
mono/mini/iltests.il
mono/mini/mini-amd64.c
mono/mini/mini-darwin.c
mono/mini/mini-exceptions.c
mono/mini/mini-llvm-loaded.c
mono/mini/mini-llvm.c
mono/mini/mini-llvm.h
mono/mini/mini-posix.c
mono/mini/mini-runtime.c
mono/mini/mini-windows.c
mono/mini/mini.c
mono/profiler/aot.c
mono/profiler/iomap.c
mono/profiler/log-args.c
mono/profiler/log.c
mono/profiler/log.h
mono/profiler/mprof-report.c
mono/profiler/ptestrunner.pl
mono/profiler/vtune.c
mono/tests/Makefile.am
mono/tests/internalsvisibleto-2048.snk [new file with mode: 0644]
mono/tests/internalsvisibleto-compilertest.cs
mono/tests/internalsvisibleto-library.cs
mono/tests/internalsvisibleto-runtimetest.cs
mono/utils/mono-logger-internals.h
mono/utils/mono-proclib.h
msvc/masm.fixed.props
msvc/mono-nunit-test.props
msvc/mono-profiler-vtune.def
msvc/profiler-vtune.vcxproj
msvc/profiler-vtune.vcxproj.filters
packaging/MacSDK/msbuild.py
tools/pedump/pedump.c

diff --git a/CODEOWNERS b/CODEOWNERS
new file mode 100644 (file)
index 0000000..bdc2bec
--- /dev/null
@@ -0,0 +1,42 @@
+# Mono Code Owners File
+#
+# GitHub uses this file to determine who to ping for reviews on pull requests.
+# If you're the primary maintainer of an area of Mono and you don't mind
+# reviewing pull requests, please add yourself to this file. You may want to
+# avoid adding entries for commonly changed or automatically generated files
+# (e.g. stuff in external/, or various generated *.csproj files) so as not to
+# get spammed with emails.
+#
+# Note that if two patterns match a file, the later pattern takes precedence.
+#
+# Please keep this file alphabetically sorted.
+#
+# Reference:
+#
+# https://github.com/blog/2392-introducing-code-owners
+# https://help.github.com/articles/about-codeowners
+
+acceptance-tests/* @akoeplinger
+acceptance-tests/profiler-stress @alexrp
+docs/sources/mono-api-profiler.html @alexrp
+man/mprof-report.1 @alexrp
+mcs/class/Mono.Options @jonpryor
+mcs/class/Mono.Profiler.Log @alexrp
+mono/metadata/profiler* @alexrp
+mono/metadata/threads* @luhenry @kumpera
+mono/metadata/threadpool* @luhenry
+mono/metadata/w32* @luhenry
+mono/profiler @alexrp
+mono/utils/atomic* @alexrp
+mono/utils/mono-hwcap* @alexrp
+mono/utils/mono-mem* @alexrp
+mono/utils/mono-threads* @luhenry @kumpera
+msvc/*profiler* @alexrp
+packaging/Windows @akoeplinger
+samples/profiler @alexrp
+samples/size @alexrp
+scripts/ci/run-jenkins.sh @akoeplinger
+scripts/ci/run-test-acceptance-tests.sh @akoeplinger
+scripts/ci/run-test-default.sh @akoeplinger
+scripts/ci/run-test-profiler-stress-tests.sh @alexrp
+scripts/ci/util.sh @akoeplinger
index ed8d6fe7cc5ac74d975dfc69afdd0d3de2abf69b..b767c969fb6c0c6bee4a89a3c422073624a62095 100644 (file)
@@ -23,7 +23,7 @@ License
 
 The Mono runtime, compilers, and tools and most of the class libraries
 are licensed under the MIT license. But include some bits of code
-licensed under different licenses. The exact list is [available here] (https://github.com/mono/mono/blob/master/LICENSE).
+licensed under different licenses. The exact list is [available here](https://github.com/mono/mono/blob/master/LICENSE).
 
 Different parts of Mono use different licenses.  The actual details of
 which licenses are used for which parts are detailed on the LICENSE
@@ -32,7 +32,7 @@ file in this directory.
 CLA
 =======
 
-Contributions are now taken under the [.NET Foundation CLA] (https://cla2.dotnetfoundation.org/). 
+Contributions are now taken under the [.NET Foundation CLA](https://cla2.dotnetfoundation.org/).
 
 Testing
 =======
index 302e43e639228c097c5a13eb74053c25662646b6..ce35b9a4b05632a0530d30f7bc6847deca5b1c44 100644 (file)
@@ -45,23 +45,16 @@ namespace Mono.Profiling.Tests.Stress {
        static class Program {
 
                static readonly string[] _options = new [] {
-                       "domain",
-                       "assembly",
-                       "module",
-                       "class",
-                       "jit",
                        "exception",
-                       "gcalloc",
-                       "gc",
-                       "thread",
-                       // "calls", // Way too heavy.
                        "monitor",
+                       "gc",
+                       "gcalloc",
                        "gcmove",
                        "gcroot",
-                       "context",
+                       "gchandle",
                        "finalization",
                        "counter",
-                       "gchandle",
+                       "jit",
                };
 
                static readonly TimeSpan _timeout = TimeSpan.FromHours (6);
@@ -96,7 +89,7 @@ namespace Mono.Profiling.Tests.Stress {
                                var bench = benchmarks [i];
 
                                var sampleFreq = rand.Next (-1000, 1001);
-                               var sampleMode = rand.Next (0, 2) == 1 ? "real" : "process";
+                               var sampleMode = rand.Next (0, 2) == 1 ? "-real" : string.Empty;
                                var maxSamples = rand.Next (0, cpus * 2000 + 1);
                                var heapShotFreq = rand.Next (-10, 11);
                                var maxFrames = rand.Next (0, 33);
@@ -107,7 +100,7 @@ namespace Mono.Profiling.Tests.Stress {
                                var profOptions = $"maxframes={maxFrames},{string.Join (",", options)},output=/dev/null";
 
                                if (sampleFreq > 0)
-                                       profOptions += $",sample={sampleFreq},sampling-{sampleMode},maxsamples={maxSamples}";
+                                       profOptions += $",sample{sampleMode}={sampleFreq},maxsamples={maxSamples}";
 
                                if (heapShotFreq > 0)
                                        profOptions += $",heapshot={heapShotFreq}gc";
index 7e70a4e9236104c350e7d9ca3505225755065569..797f074e49933b5fffb42d1a945270f3a88de042 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7e70a4e9236104c350e7d9ca3505225755065569
+Subproject commit 797f074e49933b5fffb42d1a945270f3a88de042
index 7b1460a888ae20f5756aa3e8ad71781094541ffd..e7929918ad0bb9df8d12b07a7803f660a8a3244f 100644 (file)
@@ -93,7 +93,6 @@ GC_API GC_PTR (*GC_oom_fn) GC_PROTO((size_t bytes_requested));
                        /* pointer to a previously allocated heap       */
                        /* object.                                      */
 
-// Keep somewhat in sync with mono/metadata/profiler.h:enum MonoGCEvent
 typedef enum {
        GC_EVENT_START,
        GC_EVENT_MARK_START,
index 8874b32326aa3f87550a5ff3a863a1e5d5fd6b04..8ffa784a23aeff1661c912461451be8e75a5445e 100644 (file)
@@ -104,7 +104,7 @@ test-local: $(test_assemblies)
 run-test-local: run-test-lib
 run-test-ondotnet-local: run-test-ondotnet-lib
 
-TEST_HARNESS_EXCLUDES = -exclude=$(PLATFORM_TEST_HARNESS_EXCLUDES)$(PROFILE_TEST_HARNESS_EXCLUDES)NotWorking,ValueAdd,CAS,InetAccess
+TEST_HARNESS_EXCLUDES = -exclude=$(PLATFORM_TEST_HARNESS_EXCLUDES)$(PROFILE_TEST_HARNESS_EXCLUDES)NotWorking,CAS
 TEST_HARNESS_EXCLUDES_ONDOTNET = /exclude:$(PLATFORM_TEST_HARNESS_EXCLUDES)$(PROFILE_TEST_HARNESS_EXCLUDES)NotDotNet,CAS
 
 NOSHADOW_FLAG =
index 1bd8f7cdcbaf88dde996a02dc31fd948d1e134de..2ee7b66d6f6190694058ec84b1982d9c1bc2ce42 100644 (file)
@@ -81,35 +81,29 @@ namespace MonoTests.Microsoft.Build.Execution
                [Test]
                public void EndBuildWaitsForSubmissionCompletion ()
                {
-                       // Windows does not have useful sleep or alternative, so skip it
-                       bool is_windows = true;
-                       switch (Environment.OSVersion.Platform) {
-                       case PlatformID.Unix:
-                       case PlatformID.MacOSX:
-                               is_windows = false;
-                               break;
-                       }
                        string project_xml = string.Format (@"<Project DefaultTargets='Wait1Sec' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
   <Target Name='Wait1Sec'>
     <Exec Command='{0}' />
   </Target>
-</Project>", is_windows ? "powershell -command \"Start-Sleep -s 1\"" : "/bin/sleep 1");
+</Project>", Environment.OSVersion.Platform == PlatformID.Win32NT ? "powershell -command \"Start-Sleep -s 1\"" : "/bin/sleep 1");
                        var xml = XmlReader.Create (new StringReader (project_xml));
                        var root = ProjectRootElement.Create (xml);
                        root.FullPath = "BuildSubmissionTest.EndBuildWaitsForSubmissionCompletion.proj";
                        var proj = new ProjectInstance (root);
                        var bm = new BuildManager ();
                        bm.BeginBuild (new BuildParameters ());
-                       DateTime waitDone = DateTime.MinValue;
-                       DateTime beforeExec = DateTime.UtcNow;
+                       var waitDone = TimeSpan.MinValue;
+                       var sw = System.Diagnostics.Stopwatch.StartNew ();
                        var sub = bm.PendBuildRequest (new BuildRequestData (proj, new string [] { "Wait1Sec" }));
-                       sub.ExecuteAsync (delegate { waitDone = DateTime.UtcNow; }, null);
+                       sub.ExecuteAsync (cb => waitDone = sw.Elapsed, null);
                        bm.EndBuild ();
                        Assert.AreEqual (BuildResultCode.Success, sub.BuildResult.OverallResult, "#1");
-                       DateTime endBuildDone = DateTime.UtcNow;
-                       AssertHelper.GreaterOrEqual (endBuildDone - beforeExec, TimeSpan.FromSeconds (1), "#2");
-                       AssertHelper.GreaterOrEqual (waitDone, beforeExec, "#3");
+                       var endBuildDone = sw.Elapsed;
+                       AssertHelper.GreaterOrEqual (endBuildDone, TimeSpan.FromSeconds (1), "#2");
+                       AssertHelper.GreaterOrEqual (waitDone, TimeSpan.FromSeconds (1), "#3");
                        AssertHelper.GreaterOrEqual (endBuildDone, waitDone, "#4");
+                       AssertHelper.LessOrEqual (endBuildDone, TimeSpan.FromSeconds (2), "#5");
+                       AssertHelper.LessOrEqual (waitDone, TimeSpan.FromSeconds (2), "#6");
                }
                
                [Test]
index bfb0fea4fed677f224858316c34d9385fd981bcf..27b58318f270e2455b5216ce3dcf0c91af7c5bf5 100644 (file)
@@ -8,7 +8,7 @@ Mono.Profiler.Log/LogEventVisitor.cs
 Mono.Profiler.Log/LogEvents.cs
 Mono.Profiler.Log/LogException.cs
 Mono.Profiler.Log/LogProcessor.cs
+Mono.Profiler.Log/LogProfiler.cs
 Mono.Profiler.Log/LogReader.cs
-Mono.Profiler.Log/LogRuntimeProfiler.cs
 Mono.Profiler.Log/LogStream.cs
 Mono.Profiler.Log/LogStreamHeader.cs
index f34cafe07e0965869ac7281573b6059d65f37f14..0dbc72eb003e86e24f6447831ccfb8bd08f06b56 100644 (file)
@@ -171,17 +171,13 @@ namespace Mono.Profiler.Log {
 
        // mono/metadata/profiler.h : MonoProfilerGCEvent
        public enum LogGCEvent {
-               Begin = 0,
-               MarkBegin = 1,
-               MarkEnd = 2,
-               ReclaimBegin = 3,
-               ReclaimEnd = 4,
-               End = 5,
                PreStopWorld = 6,
+               PreStopWorldLocked = 10,
                PostStopWorld = 7,
+               Begin = 0,
+               End = 5,
                PreStartWorld = 8,
                PostStartWorld = 9,
-               PreStopWorldLocked = 10,
                PostStartWorldUnlocked = 11,
        }
 
@@ -199,4 +195,20 @@ namespace Mono.Profiler.Log {
                WorldStop = 1,
                WorldStart = 2,
        }
+
+       // mono/metadata/profiler.h : MonoProfilerSampleMode
+       public enum LogSampleMode {
+               None = 0,
+               Process = 1,
+               Real = 2,
+       }
+
+       // mono/profiler/log.h : MonoProfilerHeapshotMode
+       public enum LogHeapshotMode {
+               None = 0,
+               EveryMajor = 1,
+               OnDemand = 2,
+               Milliseconds = 3,
+               Collections = 4,
+       }
 }
index 09e5dca088f15ab973b868a24e8ff1e795f7dccb..2b205e13318b0140d82d6e1c910081c6ac164530 100644 (file)
@@ -547,7 +547,7 @@ namespace Mono.Profiler.Log {
 
                long ReadObject ()
                {
-                       return Reader.ReadSLeb128 () + _bufferHeader.ObjectBase;
+                       return Reader.ReadSLeb128 () + _bufferHeader.ObjectBase << 3;
                }
 
                long ReadMethod ()
diff --git a/mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogProfiler.cs b/mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogProfiler.cs
new file mode 100644 (file)
index 0000000..289b180
--- /dev/null
@@ -0,0 +1,261 @@
+// 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.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Mono.Profiler.Log {
+
+       public static class LogProfiler {
+
+               static bool? _attached;
+
+               public static bool IsAttached {
+                       get {
+                               if (_attached != null)
+                                       return (bool) _attached;
+
+                               try {
+                                       GetMaxStackTraceFrames ();
+                                       return (bool) (_attached = true);
+                               } catch (MissingMethodException) {
+                                       return (bool) (_attached = false);
+                               }
+                       }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int GetMaxStackTraceFrames ();
+
+               public static int MaxStackTraceFrames {
+                       get { return GetMaxStackTraceFrames (); }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int GetStackTraceFrames ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetStackTraceFrames (int value);
+
+               public static int StackTraceFrames {
+                       get { return GetStackTraceFrames (); }
+                       set {
+                               var max = MaxStackTraceFrames;
+
+                               if (value < 0 || value > max)
+                                       throw new ArgumentOutOfRangeException (nameof (value), value, $"Value must be between 0 and {max}.");
+
+                               SetStackTraceFrames (value);
+                       }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static LogHeapshotMode GetHeapshotMode ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetHeapshotMode (LogHeapshotMode value);
+
+               public static LogHeapshotMode HeapshotMode {
+                       get { return GetHeapshotMode (); }
+                       set {
+                               if (!Enum.IsDefined (typeof (LogHeapshotMode), value))
+                                       throw new ArgumentException ("Invalid heapshot mode.", nameof (value));
+
+                               SetHeapshotMode (value);
+                       }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int GetHeapshotMillisecondsFrequency ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetHeapshotMillisecondsFrequency (int value);
+
+               public static int HeapshotMillisecondsFrequency {
+                       get { return GetHeapshotMillisecondsFrequency (); }
+                       set {
+                               if (value < 0)
+                                       throw new ArgumentOutOfRangeException (nameof (value), value, "Value must be non-negative.");
+
+                               SetHeapshotMillisecondsFrequency (value);
+                       }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int GetHeapshotCollectionsFrequency ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetHeapshotCollectionsFrequency (int value);
+
+               public static int HeapshotCollectionsFrequency {
+                       get { return GetHeapshotCollectionsFrequency (); }
+                       set {
+                               if (value < 0)
+                                       throw new ArgumentOutOfRangeException (nameof (value), value, "Value must be non-negative.");
+
+                               SetHeapshotCollectionsFrequency (value);
+                       }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int GetCallDepth ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetCallDepth (int value);
+
+               public static int CallDepth {
+                       get { return GetCallDepth (); }
+                       set {
+                               if (value < 0)
+                                       throw new ArgumentOutOfRangeException (nameof (value), value, "Value must be non-negative.");
+
+                               SetCallDepth (value);
+                       }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void GetSampleMode (out LogSampleMode mode, out int frequency);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static bool SetSampleMode (LogSampleMode value, int frequency);
+
+               public static LogSampleMode SampleMode {
+                       get {
+                               GetSampleMode (out var mode, out var _);
+
+                               return mode;
+                       }
+               }
+
+               public static int SampleFrequency {
+                       get {
+                               GetSampleMode (out var _, out var frequency);
+
+                               return frequency;
+                       }
+               }
+
+               public static bool SetSampleParameters (LogSampleMode mode, int frequency)
+               {
+                       if (!Enum.IsDefined (typeof (LogSampleMode), mode))
+                               throw new ArgumentException ("Invalid sample mode.", nameof (mode));
+
+                       if (frequency < 1)
+                               throw new ArgumentOutOfRangeException (nameof (frequency), frequency, "Frequency must be positive.");
+
+                       return SetSampleMode (mode, frequency);
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static bool GetExceptionEvents ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetExceptionEvents (bool value);
+
+               public static bool ExceptionEventsEnabled {
+                       get { return GetExceptionEvents (); }
+                       set { SetExceptionEvents (value); }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static bool GetMonitorEvents ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetMonitorEvents (bool value);
+
+               public static bool MonitorEventsEnabled {
+                       get { return GetMonitorEvents (); }
+                       set { SetMonitorEvents (value); }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static bool GetGCEvents ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetGCEvents (bool value);
+
+               public static bool GCEventsEnabled {
+                       get { return GetGCEvents (); }
+                       set { SetGCEvents (value); }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static bool GetGCAllocationEvents ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetGCAllocationEvents (bool value);
+
+               public static bool GCAllocationEventsEnabled {
+                       get { return GetGCAllocationEvents (); }
+                       set { SetGCAllocationEvents (value); }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static bool GetGCMoveEvents ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetGCMoveEvents (bool value);
+
+               public static bool GCMoveEventsEnabled {
+                       get { return GetGCMoveEvents (); }
+                       set { SetGCMoveEvents (value); }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static bool GetGCRootEvents ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetGCRootEvents (bool value);
+
+               public static bool GCRootEventsEnabled {
+                       get { return GetGCRootEvents (); }
+                       set { SetGCRootEvents (value); }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static bool GetGCHandleEvents ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetGCHandleEvents (bool value);
+
+               public static bool GCHandleEventsEnabled {
+                       get { return GetGCHandleEvents (); }
+                       set { SetGCHandleEvents (value); }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static bool GetGCFinalizationEvents ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetGCFinalizationEvents (bool value);
+
+               public static bool GCFinalizationEventsEnabled {
+                       get { return GetGCFinalizationEvents (); }
+                       set { SetGCFinalizationEvents (value); }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static bool GetCounterEvents ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetCounterEvents (bool value);
+
+               public static bool CounterEventsEnabled {
+                       get { return GetCounterEvents (); }
+                       set { SetCounterEvents (value); }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static bool GetJitEvents ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void SetJitEvents (bool value);
+
+               public static bool JitEventsEnabled {
+                       get { return GetJitEvents (); }
+                       set { SetJitEvents (value); }
+               }
+       }
+}
diff --git a/mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogRuntimeProfiler.cs b/mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogRuntimeProfiler.cs
deleted file mode 100644 (file)
index 8ed0993..0000000
+++ /dev/null
@@ -1,13 +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.
-
-using System.Runtime.InteropServices;
-
-namespace Mono.Profiler.Log {
-
-       public static class LogRuntimeProfiler {
-
-               // TODO: Runtime profiler interface.
-       }
-}
index cecbc7e1fb0892054bb2788948f99a3974380b27..330a8d8a5e728bdb8ab00348d703a38f52a3385f 100644 (file)
@@ -13,7 +13,6 @@ using System.DirectoryServices;
 namespace MonoTests.System.DirectoryServices \r
 {\r
        [TestFixture]\r
-       [Category ("InetAccess")]\r
        public class DirectoryServicesDirectoryEntryTest\r
        {\r
                #region Fields\r
@@ -30,6 +29,9 @@ namespace MonoTests.System.DirectoryServices
                {\r
                        de = null;\r
                        configuration = new TestConfiguration ();\r
+\r
+                       if (String.IsNullOrEmpty (configuration.ConnectionString))\r
+                               Assert.Ignore ("No configuration");\r
                }\r
 \r
 \r
index 2775fcb7b4e2af125128843eb69d1a041551d821..95ce2662c54a5b5fbe1b9642e54ce748951e5e26 100644 (file)
@@ -15,7 +15,6 @@ using System.Threading;
 namespace MonoTests.System.DirectoryServices \r
 {\r
        [TestFixture]\r
-       [Category ("InetAccess")]\r
        public class DirectoryServicesDirectorySearcherTest\r
        {\r
                #region Fields\r
@@ -33,6 +32,9 @@ namespace MonoTests.System.DirectoryServices
                {\r
                        de = null;                      \r
                        configuration = new TestConfiguration ();\r
+\r
+                       if (String.IsNullOrEmpty (configuration.ConnectionString))\r
+                               Assert.Ignore ("No configuration");\r
                }\r
 \r
 \r
index 87f69ad7d0ff138216d1991b421ab9fa1ec73f4d..21aa253301b5a73722d6a4fa817cd9516535528e 100644 (file)
@@ -13,7 +13,6 @@ using System.DirectoryServices;
 namespace MonoTests.System.DirectoryServices \r
 {\r
        [TestFixture]\r
-       [Category ("InetAccess")]\r
        public class DirectoryServicesSearchResultTest\r
        {\r
                #region Fields\r
@@ -31,6 +30,9 @@ namespace MonoTests.System.DirectoryServices
                {\r
                        de = null;\r
                        configuration = new TestConfiguration ();\r
+\r
+                       if (String.IsNullOrEmpty (configuration.ConnectionString))\r
+                               Assert.Ignore ("No configuration");\r
                }\r
 \r
 \r
index 89eaad966b3edf7a0931a48a2901b7cb8dcad200..496c44520ccaa51eb3b902c6fa83a7cb0d29eaf6 100644 (file)
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
   <ItemGroup>\r
     <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\AssemblyRef.cs" />\r
-    <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\misc\ClientUtils.cs" />\r
     <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\misc\HandleCollector.cs" />\r
     <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\BitmapSuffixInSameAssemblyAttribute.cs" />\r
     <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\BitmapSuffixInSatelliteAssemblyAttribute.cs" />\r
     <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Brush.cs" />\r
+    <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\ClientUtils.cs" />\r
     <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\DashCap.cs" />\r
     <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\CategoryNameCollection.cs" />\r
     <Compile Include="..\..\..\external\corefx\src\System.Drawing.Common\src\System\Drawing\Design\IPropertyValueUIService.cs" />\r
index 582cdc47bf597623b782f41849539d07641de38f..18e12edb898da2c47d1990f25950687fc4c23a49 100755 (executable)
@@ -3,7 +3,7 @@ System.Drawing/SR.cs
 Assembly/AssemblyInfo.cs
 ../../build/common/Consts.cs
 ../../build/common/Locale.cs
-../../../external/corefx/src/System.Drawing.Common/src/misc/ClientUtils.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/ClientUtils.cs
 ../../../external/corefx/src/System.Drawing.Common/src/misc/HandleCollector.cs
 ../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Gdiplus.cs
 ../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/NativeMethods.cs
@@ -95,7 +95,7 @@ System.Drawing/ToolboxBitmapAttribute.cs
 ../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/ToolboxComponentsCreatingEventHandler.cs
 ../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/ToolboxItemCreatorCallback.cs
 System.Drawing.Design/ToolboxItem.cs
-       ../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/UITypeEditor.cs
+../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/UITypeEditor.cs
 ../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Design/ToolboxItemCollection.cs
 ../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Drawing2D/AdjustableArrowCap.cs
 ../../../external/corefx/src/System.Drawing.Common/src/System/Drawing/Drawing2D/Blend.cs
index cdccb1291e6f24759d6bbb290c95ec75a82e36cf..c45a91d2558ce19edf596e68ce0beea18b00fd9d 100644 (file)
@@ -53,8 +53,8 @@
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
   <ItemGroup>\r
     <Compile Include="..\..\..\external\corefx\src\Common\src\System\Globalization\FormatProvider.Number.cs" />\r
+    <Compile Include="..\..\..\external\corefx\src\Common\src\System\MathF.netstandard.cs" />\r
     <Compile Include="..\..\..\external\corefx\src\Common\src\System\Numerics\Hashing\HashHelpers.cs" />\r
-    <Compile Include="..\..\..\external\corefx\src\System.Numerics.Vectors\src\System\MathF.cs" />\r
     <Compile Include="..\..\..\external\corefx\src\System.Numerics.Vectors\src\System\Numerics\JitIntrinsicAttribute.cs" />\r
     <Compile Include="..\..\..\external\corefx\src\System.Numerics.Vectors\src\System\Numerics\Matrix3x2.cs" />\r
     <Compile Include="..\..\..\external\corefx\src\System.Numerics.Vectors\src\System\Numerics\Matrix4x4.cs" />\r
index 4a50c42d7f362ca31cba282c9fc7c3ed178dd4f5..919debfb8420e469ef0c0c8f2a8057496bb535bd 100644 (file)
@@ -21,7 +21,7 @@ corefx/Vector.cs
 ../../../external/corefx/src/System.Runtime.Numerics/src/System/Numerics/Complex.cs
 ../../../external/corefx/src/System.Runtime.Numerics/src/System/Numerics/NumericsHelpers.cs
 
-../../../external/corefx/src/System.Numerics.Vectors/src/System/MathF.cs
+../../../external/corefx/src/Common/src/System/MathF.netstandard.cs
 
 ../../../external/corefx/src/System.Numerics.Vectors/src/System/Numerics/JitIntrinsicAttribute.cs
 ../../../external/corefx/src/System.Numerics.Vectors/src/System/Numerics/Matrix3x2.cs
index 2ef111be9161a9cece92a570ca6f2de20145f72f..af912498a73184f74aee4da718c18f7f0ffe44cc 100644 (file)
@@ -1,5 +1,6 @@
-../../../external/corefx/src/Common/tests/System/AssertExtensions.cs
+../../../external/corefx/src/CoreFx.Private.TestUtilities/src/System/AssertExtensions.cs
 ../../../external/corefx/src/Common/tests/System/PlatformDetection.cs
+../../../external/corefx/src/Common/src/System/MathF.netstandard.cs
 
 # ../../../external/corefx/src/System.Runtime.Numerics/tests/*.cs
 ../../../external/corefx/src/System.Runtime.Numerics/tests/BigInteger/*.cs
index 0525994a43b363497b5723efdd86ab70c1167b57..349b41fe8eaabbf73f894218c4b7ea7a48f43605 100644 (file)
@@ -208,9 +208,12 @@ namespace System.Web.Services.Protocols
                        WebRequest request = GetWebRequest (uri);
                        request.Method = "POST";
                        WebHeaderCollection headers = request.Headers;
-                       if (!message.IsSoap12)
-                               headers.Add ("SOAPAction", "\"" + message.Action + "\"");
                        request.ContentType = message.ContentType + "; charset=utf-8";
+                       if (!message.IsSoap12) {
+                               headers.Add ("SOAPAction", "\"" + message.Action + "\"");
+                       } else {
+                               request.ContentType += "; action=\"" + message.Action + "\"";
+                       }
                        return request;
                }
 
index 4a12ce5b1ea97ecf3111f850f7e9135baa3c52aa..13a357274aecf3e89de65469ed444693a5267593 100644 (file)
@@ -18,7 +18,7 @@ namespace MonoTests.System.Web.Services.Discovery {
        public class DiscoveryClientProtocolTest {
 
                [Test] // Covers #36116
-               [Category ("InetAccess")]
+               [Category ("NotWorking")]
                public void ReadWriteTest ()
                {
                        string directory = Path.Combine (Path.GetTempPath (), Path.GetRandomFileName ());
index 0e4fb4ef46d1bc097411a2d11d8aa3550585f207..e9802b1859046fb6330065cf9fbd0e698d1330b9 100644 (file)
@@ -114,7 +114,7 @@ test-local: DummyAssembly.dll
 
 include ../../build/library.make
 
-TEST_HARNESS_EXCLUDES = -exclude=Interactive,NotWorking,ValueAdd,CAS,InetAccess
+TEST_HARNESS_EXCLUDES = -exclude=Interactive,NotWorking,CAS
 TEST_HARNESS_EXCLUDES_ONDOTNET = -exclude=Interactive,NotDotNet,CAS
 
 $(the_lib): $(RESOURCES)
index 1fce2eab1144d3899423c1d58d0ee8bef3ca1afe..ba6d5197231e63d13c9c732be3ef00a742219d1c 100644 (file)
@@ -94,6 +94,7 @@ namespace Mono.Net.Security
 
                        ChainValidationHelper.Create (provider, ref settings, this);
 #else
+                       status = WebExceptionStatus.SecureChannelFailure;
                        throw new PlatformNotSupportedException (EXCEPTION_MESSAGE);
 #endif
                }
index f80d759f63d222ebc29626a9db2e8a5ebbeb9b49..d5b1e3863d6a490fd850c1deae055f0429bdcbda 100644 (file)
@@ -1733,6 +1733,7 @@ namespace System.ComponentModel
                        case 13882: /* ERROR_IPSEC_IKE_MM_LIMIT */ return "IPSEC IKE mm limit";
                        case 13883: /* ERROR_IPSEC_IKE_NEGOTIATION_DISABLED */ return "IPSEC IKE negotiation disabled";
                        case 13884: /* ERROR_IPSEC_IKE_NEG_STATUS_END */ return "IPSEC IKE neg status end";
+                       case 100001: /* WSAENXIO */ return "Device not configured";
 #endif // MOBILE
                        default:
                                return string.Format ("mono-io-layer-error ({0})", error);
index 98200b45b4a01ad613756f7d16839f978ce1e08f..89562a5b4c2e4afdd9627a258c2bae46a2920932 100644 (file)
@@ -69,7 +69,9 @@ namespace System.Net
                                        }
                                }
 #else
+#pragma warning disable 618
                                ConfigurationSettings.GetConfig ("system.net/authenticationModules");
+#pragma warning restore 618
 #endif
                        }
                }
index dac834884441e8ccd8764f846dcea5289ebd073b..5338cd09d012f8490dcc5351ef3ed839b8e2829b 100644 (file)
@@ -320,9 +320,11 @@ namespace System.Net {
                                try {
                                        IPAddress newAddress = IPAddress.Parse(h_addrlist[i]);
 
+#pragma warning disable 618
                                        if( (Socket.SupportsIPv6 && newAddress.AddressFamily == AddressFamily.InterNetworkV6) ||
                                            (Socket.SupportsIPv4 && newAddress.AddressFamily == AddressFamily.InterNetwork) )
                                                addrlist.Add(newAddress);
+#pragma warning restore 618
                                } catch (ArgumentNullException) {
                                        /* Ignore this, as the
                                         * internal call might have
@@ -393,7 +395,9 @@ namespace System.Net {
                        if (hostNameOrAddress.Length > 0 && IPAddress.TryParse (hostNameOrAddress, out addr))
                                return GetHostEntry (addr);
 
+#pragma warning disable 618
                        return GetHostByName (hostNameOrAddress);
+#pragma warning restore 618
                }
 
                public static IPHostEntry GetHostEntry (IPAddress address)
index 2f1658ab113ee155ffbb146e8c69ca85652d8abd..9a103f45cd72898eaec07552c2b693cde4f9816f 100644 (file)
@@ -84,7 +84,9 @@ namespace System.Net {
                                addr = IPAddress.Any;
                        else if (IPAddress.TryParse(host, out addr) == false){
                                try {
+#pragma warning disable 618
                                        IPHostEntry iphost = Dns.GetHostByName(host);
+#pragma warning restore 618
                                        if (iphost != null)
                                                addr = iphost.AddressList[0];
                                        else
index c0ea1b551195e55dd06e5919c44646ee5548dc8e..3121db3d1729daef56a67b3dea4af5fdb49897f0 100644 (file)
@@ -113,7 +113,9 @@ namespace System.Net
                internal FtpWebRequest (Uri uri) 
                {
                        this.requestUri = uri;
+#pragma warning disable 618
                        this.proxy = GlobalProxySelection.Select;
+#pragma warning restore 618
                }
 
                static Exception GetMustImplement ()
index 4f7d1d7d7baf1655780df5aba32bd4b84619f3b3..d05722051f93453ff405de19e8c76bf99fa2d380 100644 (file)
@@ -134,7 +134,9 @@ namespace System.Net
                {
                        defaultMaxResponseHeadersLength = 64 * 1024;
 #if !MOBILE
+#pragma warning disable 618
                        NetConfig config = ConfigurationSettings.GetConfig ("system.net/settings") as NetConfig;
+#pragma warning restore 618
                        if (config != null) {
                                int x = config.MaxResponseHeadersLength;
                                if (x != -1)
index 6747a263a6c966a549438d4989be1961db90cc6b..3e33097d1fc133548088677bc5ab6ccdce8c99f0 100644 (file)
@@ -97,7 +97,6 @@ namespace MonoCasTests.System.Net.Sockets {
 
                [Test]
                [EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
-               [Category ("InetAccess")]
                public void AsyncRead ()
                {
                        message = "AsyncRead";
@@ -136,7 +135,6 @@ namespace MonoCasTests.System.Net.Sockets {
 
                [Test]
                [EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
-               [Category ("InetAccess")]
                public void AsyncWrite ()
                {
                        message = "AsyncWrite";
index 6319d3e7b941976addc7b3462c8ee1c73a497f6a..1b4458c4f137b0bad9a7653468030029bcb49082 100644 (file)
@@ -78,7 +78,6 @@ namespace MonoCasTests.System.Net.Sockets {
 
                [Test]
                [EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
-               [Category ("InetAccess")]
                public void AsyncAccept ()
                {
                        IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 16279);
@@ -118,7 +117,6 @@ namespace MonoCasTests.System.Net.Sockets {
 
                [Test]
                [EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
-               [Category ("InetAccess")]
                public void AsyncConnect ()
                {
                        message = "AsyncConnect";
@@ -152,7 +150,6 @@ namespace MonoCasTests.System.Net.Sockets {
 
                [Test]
                [EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
-               [Category ("InetAccess")]
                public void AsyncReceive ()
                {
                        message = "AsyncReceive";
@@ -191,7 +188,6 @@ namespace MonoCasTests.System.Net.Sockets {
 
                [Test]
                [EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
-               [Category ("InetAccess")]
                public void AsyncReceiveFrom ()
                {
                        message = "AsyncReceiveFrom";
@@ -230,7 +226,6 @@ namespace MonoCasTests.System.Net.Sockets {
 
                [Test]
                [EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
-               [Category ("InetAccess")]
                public void AsyncSend ()
                {
                        message = "AsyncSend";
@@ -265,7 +260,6 @@ namespace MonoCasTests.System.Net.Sockets {
 
                [Test]
                [EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
-               [Category ("InetAccess")]
                public void AsyncSendTo ()
                {
                        message = "AsyncSendTo";
index d46838a9bb220d763682becc4f31d7f148fa8578..9a24b95e1b1642201544691b3af094e39acc17af 100755 (executable)
@@ -87,7 +87,7 @@ namespace MonoTests.System.Net.Sockets
                }
 
                [Test]
-               [Category ("InetAccess")]
+               [Category ("NotWorking")]
 #if FEATURE_NO_BSD_SOCKETS
                [ExpectedException (typeof (PlatformNotSupportedException))]
 #endif
index b9f4de5440076d48ee56bc3aaa816e579f493081..fbc08e1f0f56762c7fc39e5c3945e6343e8d3f10 100644 (file)
@@ -50,7 +50,6 @@ namespace MonoCasTests.System.Net.Sockets {
                }
 
                // async tests (for stack propagation)
-/* Oops - not yet implemented in Mono
                private void ConnectCallback (IAsyncResult ar)
                {
                        TcpClient c = (TcpClient)ar.AsyncState;
@@ -71,7 +70,6 @@ namespace MonoCasTests.System.Net.Sockets {
 
                [Test]
                [EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
-               [Category ("InetAccess")]
                public void AsyncConnect_StringIntAsyncCallbackObject ()
                {
                        TcpClient s = new TcpClient ();
@@ -86,7 +84,6 @@ namespace MonoCasTests.System.Net.Sockets {
 
                [Test]
                [EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
-               [Category ("InetAccess")]
                public void AsyncConnect_IPAddressIntAsyncCallbackObject ()
                {
                        IPHostEntry host = Dns.Resolve ("www.google.com");
@@ -102,7 +99,6 @@ namespace MonoCasTests.System.Net.Sockets {
 
                [Test]
                [EnvironmentPermission (SecurityAction.Deny, Read = "USERNAME")]
-               [Category ("InetAccess")]
                public void AsyncConnect_IPAddressArrayIntAsyncCallbackObject ()
                {
                        IPHostEntry host = Dns.Resolve ("www.google.com");
@@ -115,6 +111,5 @@ namespace MonoCasTests.System.Net.Sockets {
                                Assert.Ignore ("Timeout");
                        Assert.IsNull (message, message);
                }
-*/
        }
 }
index 258e267787dd41137596051c3011569444c64ed2..38359efd4dea398ec4208a18de96c46569ccbac1 100644 (file)
@@ -63,7 +63,6 @@ namespace MonoTests.System.Net
                }
 
                [Test]
-               [Category("InetAccess")]
 #if FEATURE_NO_BSD_SOCKETS
                [ExpectedException (typeof (PlatformNotSupportedException))]
 #endif
@@ -135,7 +134,6 @@ namespace MonoTests.System.Net
                }
 
                [Test]
-               //[Category("InetAccess")]
                [Category ("NotWorking")] // Disabled until a server that meets requirements is found
                public void Cookies1 ()
                {
index c252d21b189bcd75d3c8b9cb2e94f621208fc838..2ed577e5df80d09d71c9fbd9e3329c783d40c56f 100644 (file)
@@ -47,7 +47,7 @@ public class ServicePointManagerTest
        }\r
 \r
         [Test, ExpectedException (typeof (InvalidOperationException))]\r
-               [Category ("InetAccess")]\r
+               [Category ("NotWorking")]\r
         public void MaxServicePointManagers ()\r
         {\r
                Assert.AreEqual (0, ServicePointManager.MaxServicePoints, "#1");\r
index 6171a2fd25587d85a535b496111aa114628536e0..514e27d47795e4279116888144c8caa4c4735dd3 100644 (file)
-//\r
-// ServicePointTest.cs - NUnit Test Cases for System.Net.ServicePoint\r
-//\r
-// Authors:\r
-//   Lawrence Pit (loz@cable.a2000.nl)\r
-//   Martin Willemoes Hansen (mwh@sysrq.dk)\r
-//\r
-// (C) 2003 Martin Willemoes Hansen\r
-//\r
-\r
-using NUnit.Framework;\r
-using System;\r
-using System.Collections;\r
-using System.IO;\r
-using System.Net;\r
-using System.Reflection;\r
-using System.Threading;\r
-\r
-namespace MonoTests.System.Net\r
-{\r
-\r
-[TestFixture]\r
-public class ServicePointTest\r
-{\r
-       static private int max;\r
-\r
-#if !FEATURE_NO_BSD_SOCKETS\r
-       [SetUp]\r
-       public void SaveMax () {\r
-               max = ServicePointManager.MaxServicePoints;\r
-               ServicePointManager.MaxServicePoints = 0;\r
-       }\r
-\r
-       [TearDown]\r
-       public void RestoreMax () {\r
-               ServicePointManager.MaxServicePoints = max;\r
-       }\r
-#endif\r
-\r
-        [Test]\r
-               [Category ("InetAccess")]\r
-        public void All ()\r
-        {\r
-               ServicePoint p = ServicePointManager.FindServicePoint (new Uri ("mailto:xx@yyy.com"));\r
-               //WriteServicePoint ("A servicepoint that isn't really", p);                    \r
-               \r
-               ServicePointManager.MaxServicePoints = 2;\r
-               ServicePoint google = ServicePointManager.FindServicePoint (new Uri ("http://www.google.com"));\r
-               try {                   \r
-                       ServicePoint slashdot = ServicePointManager.FindServicePoint (new Uri ("http://www.slashdot.org"));\r
-                       Assert.Fail ("#1");\r
-               } catch (InvalidOperationException) { }\r
-               ServicePointManager.MaxServicePoints = 0;\r
-               \r
-               //WriteServicePoint ("google before getting a webrequest", google);\r
-               \r
-               HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");\r
-               HttpWebResponse res = (HttpWebResponse) req.GetResponse ();                     \r
-               \r
-#if FOUND_SOME_OTHER_URL\r
-               // URL is no longer found, disabled the test until a more reliable URL is found :P\r
-               //WriteServicePoint ("google after getting a response", google);\r
-               ServicePoint google2 = ServicePointManager.FindServicePoint (new Uri ("http://www.google.com/dilbert.html"));\r
-               Assert.AreEqual (google, google2, "#equals");\r
-               res.Close ();\r
-#endif\r
-               \r
-               // in both instances property CurrentConnections is 0 according to ms.net.\r
-               // let's see what it says when we do async operations...\r
-               \r
-               HttpWebRequest req2 = (HttpWebRequest) WebRequest.Create ("http://www.google.com");\r
-               req2.Method = "PUT";\r
-               IAsyncResult async = req2.BeginGetRequestStream (null, null);\r
-               //WriteServicePoint ("after async BeginGetRequestStream", google);\r
-               // CurrentConnections: 1\r
-               Stream stream2 = req2.EndGetRequestStream (async);\r
-               //WriteServicePoint ("after async EndGetRequestStream", google);\r
-               // CurrentConnections: 1\r
-               stream2.Close ();\r
-               \r
-               req2 = (HttpWebRequest) WebRequest.Create ("http://www.google.com");\r
-               async = req2.BeginGetResponse (null, null);\r
-               //WriteServicePoint ("after async BeginGetResponse", google);\r
-               // CurrentConnections: 2\r
-               WebResponse res2 = req2.EndGetResponse (async);\r
-               //WriteServicePoint ("after async EndGetResponse", google);\r
-               // CurrentConnections: 0                        \r
-               // curious that after you get the webresponse object CurrentConnections is set to 0.\r
-               // you'd think that you'd still be connected until you close the webresponse..\r
-               //Console.WriteLine ("ContentLength: " + res2.ContentLength);\r
-               res2.Close ();\r
-               \r
-               ServicePoint sp2;\r
-#if FOUND_SOME_OTHER_URL\r
-               // unless of course some buffering is taking place.. let's check\r
-               Uri uri2 = new Uri ("http://freedesktop.org/Software/pkgconfig/releases/pkgconfig-0.15.0.tar.gz");\r
-               sp2 = ServicePointManager.FindServicePoint (uri2);\r
-               req2 = (HttpWebRequest) WebRequest.Create (uri2);\r
-               async = req2.BeginGetResponse (null, null);\r
-               //WriteServicePoint ("Large file: after async BeginGetResponse", sp2);\r
-               // CurrentConnections: 1\r
-               res2 = req2.EndGetResponse (async);\r
-               //WriteServicePoint ("Large file: after async EndGetResponse", sp2);\r
-               // CurrentConnections: 1\r
-               // and so it shows\r
-               //Console.WriteLine ("ContentLength: " + res2.ContentLength);\r
-               res2.Close ();\r
-#endif\r
-               \r
-               \r
-               // what's the limit of the cache?\r
-               req2 = (HttpWebRequest) WebRequest.Create ("http://www.apache.org/");\r
-               res2 = req2.GetResponse ();\r
-               sp2 = ServicePointManager.FindServicePoint (new Uri("http://www.apache.org/"));\r
-               //WriteServicePoint ("apache", sp2);\r
-               //Console.WriteLine ("ContentLength: " + res2.ContentLength);\r
-               // CurrentConnections: 1\r
-               res2.Close ();\r
-               // curious other effect: address is actually the full Uri of the previous request\r
-               // anyways, buffer is probably 4096 bytes\r
-       }\r
-\r
-       // try getting the stream to 5 web response objects     \r
-       // while ConnectionLimit equals 2\r
-\r
-       [Test]\r
-       [Category ("InetAccess")]\r
-       public void ConnectionLimit ()\r
-       {               \r
-               // the default is already 2, just in case it isn't..\r
-               ServicePointManager.DefaultConnectionLimit = 5;\r
-               \r
-               Uri uri = new Uri ("http://www.go-mono.com/");\r
-               ServicePoint sp = ServicePointManager.FindServicePoint (uri);                   \r
-               WebResponse [] res = new WebResponse [5];\r
-               for (int i = 0; i < 5; i++) {\r
-                       //Console.WriteLine ("GOT1 : " + i);\r
-                       HttpWebRequest req = (HttpWebRequest) WebRequest.Create (uri);\r
-                       //Console.WriteLine ("GOT2 : " + i);\r
-                       res [i] = req.GetResponse ();\r
-                       //WriteServicePoint ("after getting " + (i + 1) + " web response objects", sp);\r
-               }\r
-               \r
-               for (int i = 0; i < 5; i++) {\r
-                       Stream stream = res [i].GetResponseStream();\r
-                       //Console.WriteLine ("Reading stream: " + i + " : " + stream);\r
-                       int len = 0;\r
-                       while (stream.ReadByte () != -1)\r
-                               len++;\r
-                       //Console.WriteLine ("Finished reading: " + len + " bytes");\r
-               }\r
-               \r
-               for (int i = 0; i < 5; i++) {\r
-                       res [i].Close ();\r
-               }\r
-       }\r
-\r
-       [Test]\r
-       [Category ("InetAccess")]\r
-       [Category ("AndroidNotWorking")] // #A1 fails\r
-       public void EndPointBind ()\r
-       {\r
-               Uri uri = new Uri ("http://www.go-mono.com/");\r
-               ServicePoint sp = ServicePointManager.FindServicePoint (uri);\r
-\r
-               HttpWebRequest req = (HttpWebRequest) WebRequest.Create (uri);\r
-\r
-               bool called = false;\r
-               sp.BindIPEndPointDelegate = delegate {\r
-                       Assert.IsTrue (!called);\r
-                       called = true;\r
-                       return null;\r
-               };\r
-               req.GetResponse ().Close ();\r
-\r
-               Assert.IsTrue (called, "#A1");\r
-\r
-               req = (HttpWebRequest) WebRequest.Create (uri);\r
-               called = false;\r
-               sp.BindIPEndPointDelegate = delegate(ServicePoint point, IPEndPoint remote, int times) {\r
-                       Assert.IsTrue (times < 5);\r
-                       called = true;\r
-                       return new IPEndPoint(IPAddress.Parse("0.0.0.0"), 12345 + times);\r
-               };\r
-               req.GetResponse ().Close ();\r
-\r
-               Assert.IsTrue (called, "#A2");\r
-       }\r
-\r
-       public static void GetRequestStreamCallback (IAsyncResult asynchronousResult)\r
-       {\r
-       }\r
-\r
-       [Test] //Covers #19823\r
-#if FEATURE_NO_BSD_SOCKETS\r
-       // This test uses HttpWebRequest\r
-       [ExpectedException (typeof (PlatformNotSupportedException))]\r
-#endif\r
-       public void CloseConnectionGroupConcurency ()\r
-       {\r
-               // Try with multiple service points\r
-               for (var i = 0; i < 10; i++) {\r
-                       Uri targetUri = new Uri ("http://" + i + ".mono-project.com");\r
-                       var req = (HttpWebRequest) HttpWebRequest.Create (targetUri);\r
-                       req.ContentType = "application/x-www-form-urlencoded";\r
-                       req.Method = "POST";\r
-                       req.ConnectionGroupName = "" + i;\r
-                       req.ServicePoint.MaxIdleTime = 1;\r
-\r
-                       req.BeginGetRequestStream (new AsyncCallback (GetRequestStreamCallback), req);\r
-                       Thread.Sleep (1);\r
-                       req.ServicePoint.CloseConnectionGroup (req.ConnectionGroupName);\r
-               }\r
-       }\r
-\r
-\r
-       [Test]\r
-       [Category ("RequiresBSDSockets")] // Tests internals, so it doesn't make sense to assert that PlatformNotSupportedExceptions are thrown.\r
-       public void DnsRefreshTimeout ()\r
-       {\r
-               const int dnsRefreshTimeout = 2000;\r
-\r
-               ServicePoint sp;\r
-               IPHostEntry host0, host1, host2;\r
-               Uri uri;\r
-               PropertyInfo hostEntryProperty;\r
-\r
-               ServicePointManager.DnsRefreshTimeout = dnsRefreshTimeout;\r
-\r
-               uri = new Uri ("http://localhost/");\r
-               sp = ServicePointManager.FindServicePoint (uri);\r
-\r
-               hostEntryProperty = typeof (ServicePoint).GetProperty ("HostEntry", BindingFlags.NonPublic | BindingFlags.Instance);\r
-\r
-               host0 = hostEntryProperty.GetValue (sp, null) as IPHostEntry;\r
-               host1 = hostEntryProperty.GetValue (sp, null) as IPHostEntry;\r
-\r
-               Assert.AreSame (host0, host1, "HostEntry should result in the same IPHostEntry object.");\r
-\r
-               Thread.Sleep (dnsRefreshTimeout * 2);\r
-               host2 = hostEntryProperty.GetValue (sp, null) as IPHostEntry;\r
-\r
-               Assert.AreNotSame(host0, host2, "HostEntry should result in a new IPHostEntry " +\r
-                               "object when DnsRefreshTimeout is reached.");\r
-       }\r
-\r
-// Debug code not used now, but could be useful later\r
-/*\r
-       private void WriteServicePoint (string label, ServicePoint sp)\r
-       {\r
-               Console.WriteLine ("\n" + label);\r
-               Console.WriteLine ("Address: " + sp.Address);\r
-               Console.WriteLine ("ConnectionLimit: " + sp.ConnectionLimit);\r
-               Console.WriteLine ("ConnectionName: " + sp.ConnectionName);\r
-               Console.WriteLine ("CurrentConnections: " + sp.CurrentConnections);\r
-               Console.WriteLine ("IdleSince: " + sp.IdleSince);\r
-               Console.WriteLine ("MaxIdletime: " + sp.MaxIdleTime);\r
-               Console.WriteLine ("ProtocolVersion: " + sp.ProtocolVersion);\r
-               Console.WriteLine ("SupportsPipelining: " + sp.SupportsPipelining);             \r
-       }\r
-*/\r
-}\r
-}\r
-\r
+//
+// ServicePointTest.cs - NUnit Test Cases for System.Net.ServicePoint
+//
+// Authors:
+//   Lawrence Pit (loz@cable.a2000.nl)
+//   Martin Willemoes Hansen (mwh@sysrq.dk)
+//
+// (C) 2003 Martin Willemoes Hansen
+//
+
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.IO;
+using System.Net;
+using System.Reflection;
+using System.Threading;
+
+namespace MonoTests.System.Net
+{
+
+[TestFixture]
+public class ServicePointTest
+{
+       static private int max;
+
+#if !FEATURE_NO_BSD_SOCKETS
+       [SetUp]
+       public void SaveMax () {
+               max = ServicePointManager.MaxServicePoints;
+               ServicePointManager.MaxServicePoints = 0;
+       }
+
+       [TearDown]
+       public void RestoreMax () {
+               ServicePointManager.MaxServicePoints = max;
+       }
+#endif
+
+        [Test]
+               [Category ("NotWorking")]
+        public void All ()
+        {
+               ServicePoint p = ServicePointManager.FindServicePoint (new Uri ("mailto:xx@yyy.com"));
+               //WriteServicePoint ("A servicepoint that isn't really", p);                    
+               
+               ServicePointManager.MaxServicePoints = 2;
+               ServicePoint google = ServicePointManager.FindServicePoint (new Uri ("http://www.google.com"));
+               try {                   
+                       ServicePoint slashdot = ServicePointManager.FindServicePoint (new Uri ("http://www.slashdot.org"));
+                       Assert.Fail ("#1");
+               } catch (InvalidOperationException) { }
+               ServicePointManager.MaxServicePoints = 0;
+               
+               //WriteServicePoint ("google before getting a webrequest", google);
+               
+               HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
+               HttpWebResponse res = (HttpWebResponse) req.GetResponse ();                     
+               
+#if FOUND_SOME_OTHER_URL
+               // URL is no longer found, disabled the test until a more reliable URL is found :P
+               //WriteServicePoint ("google after getting a response", google);
+               ServicePoint google2 = ServicePointManager.FindServicePoint (new Uri ("http://www.google.com/dilbert.html"));
+               Assert.AreEqual (google, google2, "#equals");
+               res.Close ();
+#endif
+               
+               // in both instances property CurrentConnections is 0 according to ms.net.
+               // let's see what it says when we do async operations...
+               
+               HttpWebRequest req2 = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
+               req2.Method = "PUT";
+               IAsyncResult async = req2.BeginGetRequestStream (null, null);
+               //WriteServicePoint ("after async BeginGetRequestStream", google);
+               // CurrentConnections: 1
+               Stream stream2 = req2.EndGetRequestStream (async);
+               //WriteServicePoint ("after async EndGetRequestStream", google);
+               // CurrentConnections: 1
+               stream2.Close ();
+               
+               req2 = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
+               async = req2.BeginGetResponse (null, null);
+               //WriteServicePoint ("after async BeginGetResponse", google);
+               // CurrentConnections: 2
+               WebResponse res2 = req2.EndGetResponse (async);
+               //WriteServicePoint ("after async EndGetResponse", google);
+               // CurrentConnections: 0                        
+               // curious that after you get the webresponse object CurrentConnections is set to 0.
+               // you'd think that you'd still be connected until you close the webresponse..
+               //Console.WriteLine ("ContentLength: " + res2.ContentLength);
+               res2.Close ();
+               
+               ServicePoint sp2;
+#if FOUND_SOME_OTHER_URL
+               // unless of course some buffering is taking place.. let's check
+               Uri uri2 = new Uri ("http://freedesktop.org/Software/pkgconfig/releases/pkgconfig-0.15.0.tar.gz");
+               sp2 = ServicePointManager.FindServicePoint (uri2);
+               req2 = (HttpWebRequest) WebRequest.Create (uri2);
+               async = req2.BeginGetResponse (null, null);
+               //WriteServicePoint ("Large file: after async BeginGetResponse", sp2);
+               // CurrentConnections: 1
+               res2 = req2.EndGetResponse (async);
+               //WriteServicePoint ("Large file: after async EndGetResponse", sp2);
+               // CurrentConnections: 1
+               // and so it shows
+               //Console.WriteLine ("ContentLength: " + res2.ContentLength);
+               res2.Close ();
+#endif
+               
+               
+               // what's the limit of the cache?
+               req2 = (HttpWebRequest) WebRequest.Create ("http://www.apache.org/");
+               res2 = req2.GetResponse ();
+               sp2 = ServicePointManager.FindServicePoint (new Uri("http://www.apache.org/"));
+               //WriteServicePoint ("apache", sp2);
+               //Console.WriteLine ("ContentLength: " + res2.ContentLength);
+               // CurrentConnections: 1
+               res2.Close ();
+               // curious other effect: address is actually the full Uri of the previous request
+               // anyways, buffer is probably 4096 bytes
+       }
+
+       // try getting the stream to 5 web response objects     
+       // while ConnectionLimit equals 2
+
+       [Test]
+       [Category ("NotWorking")]
+       public void ConnectionLimit ()
+       {               
+               // the default is already 2, just in case it isn't..
+               ServicePointManager.DefaultConnectionLimit = 5;
+               
+               Uri uri = new Uri ("http://www.go-mono.com/");
+               ServicePoint sp = ServicePointManager.FindServicePoint (uri);                   
+               WebResponse [] res = new WebResponse [5];
+               for (int i = 0; i < 5; i++) {
+                       //Console.WriteLine ("GOT1 : " + i);
+                       HttpWebRequest req = (HttpWebRequest) WebRequest.Create (uri);
+                       //Console.WriteLine ("GOT2 : " + i);
+                       res [i] = req.GetResponse ();
+                       //WriteServicePoint ("after getting " + (i + 1) + " web response objects", sp);
+               }
+               
+               for (int i = 0; i < 5; i++) {
+                       Stream stream = res [i].GetResponseStream();
+                       //Console.WriteLine ("Reading stream: " + i + " : " + stream);
+                       int len = 0;
+                       while (stream.ReadByte () != -1)
+                               len++;
+                       //Console.WriteLine ("Finished reading: " + len + " bytes");
+               }
+               
+               for (int i = 0; i < 5; i++) {
+                       res [i].Close ();
+               }
+       }
+
+       [Test]
+       [Category ("NotWorking")] // #A1 fails
+       public void EndPointBind ()
+       {
+               Uri uri = new Uri ("http://www.go-mono.com/");
+               ServicePoint sp = ServicePointManager.FindServicePoint (uri);
+
+               HttpWebRequest req = (HttpWebRequest) WebRequest.Create (uri);
+
+               bool called = false;
+               sp.BindIPEndPointDelegate = delegate {
+                       Assert.IsTrue (!called);
+                       called = true;
+                       return null;
+               };
+               req.GetResponse ().Close ();
+
+               Assert.IsTrue (called, "#A1");
+
+               req = (HttpWebRequest) WebRequest.Create (uri);
+               called = false;
+               sp.BindIPEndPointDelegate = delegate(ServicePoint point, IPEndPoint remote, int times) {
+                       Assert.IsTrue (times < 5);
+                       called = true;
+                       return new IPEndPoint(IPAddress.Parse("0.0.0.0"), 12345 + times);
+               };
+               req.GetResponse ().Close ();
+
+               Assert.IsTrue (called, "#A2");
+       }
+
+       public static void GetRequestStreamCallback (IAsyncResult asynchronousResult)
+       {
+       }
+
+       [Test] //Covers #19823
+#if FEATURE_NO_BSD_SOCKETS
+       // This test uses HttpWebRequest
+       [ExpectedException (typeof (PlatformNotSupportedException))]
+#endif
+       public void CloseConnectionGroupConcurency ()
+       {
+               // Try with multiple service points
+               for (var i = 0; i < 10; i++) {
+                       Uri targetUri = new Uri ("http://" + i + ".mono-project.com");
+                       var req = (HttpWebRequest) HttpWebRequest.Create (targetUri);
+                       req.ContentType = "application/x-www-form-urlencoded";
+                       req.Method = "POST";
+                       req.ConnectionGroupName = "" + i;
+                       req.ServicePoint.MaxIdleTime = 1;
+
+                       req.BeginGetRequestStream (new AsyncCallback (GetRequestStreamCallback), req);
+                       Thread.Sleep (1);
+                       req.ServicePoint.CloseConnectionGroup (req.ConnectionGroupName);
+               }
+       }
+
+
+       [Test]
+       [Category ("RequiresBSDSockets")] // Tests internals, so it doesn't make sense to assert that PlatformNotSupportedExceptions are thrown.
+       public void DnsRefreshTimeout ()
+       {
+               const int dnsRefreshTimeout = 2000;
+
+               ServicePoint sp;
+               IPHostEntry host0, host1, host2;
+               Uri uri;
+               PropertyInfo hostEntryProperty;
+
+               ServicePointManager.DnsRefreshTimeout = dnsRefreshTimeout;
+
+               uri = new Uri ("http://localhost/");
+               sp = ServicePointManager.FindServicePoint (uri);
+
+               hostEntryProperty = typeof (ServicePoint).GetProperty ("HostEntry", BindingFlags.NonPublic | BindingFlags.Instance);
+
+               host0 = hostEntryProperty.GetValue (sp, null) as IPHostEntry;
+               host1 = hostEntryProperty.GetValue (sp, null) as IPHostEntry;
+
+               Assert.AreSame (host0, host1, "HostEntry should result in the same IPHostEntry object.");
+
+               Thread.Sleep (dnsRefreshTimeout * 2);
+               host2 = hostEntryProperty.GetValue (sp, null) as IPHostEntry;
+
+               Assert.AreNotSame(host0, host2, "HostEntry should result in a new IPHostEntry " +
+                               "object when DnsRefreshTimeout is reached.");
+       }
+
+// Debug code not used now, but could be useful later
+/*
+       private void WriteServicePoint (string label, ServicePoint sp)
+       {
+               Console.WriteLine ("\n" + label);
+               Console.WriteLine ("Address: " + sp.Address);
+               Console.WriteLine ("ConnectionLimit: " + sp.ConnectionLimit);
+               Console.WriteLine ("ConnectionName: " + sp.ConnectionName);
+               Console.WriteLine ("CurrentConnections: " + sp.CurrentConnections);
+               Console.WriteLine ("IdleSince: " + sp.IdleSince);
+               Console.WriteLine ("MaxIdletime: " + sp.MaxIdleTime);
+               Console.WriteLine ("ProtocolVersion: " + sp.ProtocolVersion);
+               Console.WriteLine ("SupportsPipelining: " + sp.SupportsPipelining);             
+       }
+*/
+}
+}
+
index d1f3180a2262510893243deb3f543919d6fe35b0..697eb82b6fd56ca29bac27cfba10ccdeb3368ad1 100644 (file)
@@ -43,7 +43,6 @@ namespace MonoTests.System.Net
                }
 
                [Test]
-               [Category ("InetAccess")]
                public void DownloadTwice ()
                {
                        WebClient wc = new WebClient();
index 0b404581899f7cdd81bb2421c0ac1f5e537a022d..205cb90a8dd7b3ece5cb9a7bb6d8998efeb32e2f 100644 (file)
@@ -79,7 +79,6 @@ namespace MonoTests.System.Net
                }
 
                [Test]
-               [Category("InetAccess")]
                public void DownloadFileTaskAsync ()
                {
                        WebClient wc = new WebClient ();
@@ -93,8 +92,7 @@ namespace MonoTests.System.Net
                }
 
                [Test]
-               [Category("InetAccess")]
-               [Category ("AndroidNotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran
+               [Category ("NotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran
                public void Cancellation ()
                {
                        WebClient wc = new WebClient ();
@@ -121,8 +119,7 @@ namespace MonoTests.System.Net
                }
 
                [Test]
-               [Category("InetAccess")]
-               [Category ("AndroidNotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran
+               [Category ("NotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran
                public void DownloadMultiple ()
                {
                        WebClient wc = new WebClient ();
@@ -140,8 +137,7 @@ namespace MonoTests.System.Net
                }
 
                [Test]
-               [Category("InetAccess")]
-               [Category ("AndroidNotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran
+               [Category ("NotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran
                public void DownloadMultiple2 ()
                {
                        WebClient wc = new WebClient ();
@@ -153,8 +149,7 @@ namespace MonoTests.System.Net
                }
 
                [Test]
-               [Category("InetAccess")]
-               [Category ("AndroidNotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran
+               [Category ("NotWorking")] // Fails when ran as part of the entire BCL test suite. Works when only this fixture is ran
                public void DownloadMultiple3 ()
                {
                        WebClient wc = new WebClient ();
index 026cfc2757aff97d39df4cd71631d8be4c5315de..1a3c6fe43ccdcd60018641e29cc3afe7fc843ac4 100644 (file)
@@ -205,7 +205,6 @@ namespace MonoTests.System.Security.Cryptography.X509Certificates {
                }
 
                [Test]
-               [Category ("InetAccess")]
                public void Build_Cert1_X509RevocationMode_Online ()
                {
                        X509Chain c = new X509Chain ();
index e4fe1f52e88e6f85f4c5b55d48f273072940c1a5..124f59ef3b9f2b22fccdfa67399abdec51ca7374 100644 (file)
@@ -41,16 +41,6 @@ namespace MonoTests.System.Reflection.Emit
                        Assert.IsNull (enumBuilder.DeclaringType, "#3");
                        Assert.IsNull (enumBuilder.ReflectedType, "#4");
                        Assert.AreEqual (_enumType, enumBuilder.UnderlyingSystemType, "#5");
-               }
-
-               [Test]
-               [Category ("ValueAdd")]
-               public void TestEnumBuilder_NotInMono ()
-               {
-                       // If we decide to fix this (I dont see why we should),
-                       // move to the routine above
-
-                       EnumBuilder enumBuilder = GenerateEnum ();
                        Assert.IsFalse (enumBuilder.IsSerializable);
                }
 
@@ -187,7 +177,6 @@ namespace MonoTests.System.Reflection.Emit
 
                [Test]
                [ExpectedException (typeof (NotSupportedException))]
-               [Category ("ValueAdd")]
                public void TestFindMembersIncomplete ()
                {
                        EnumBuilder enumBuilder = GenerateEnum ();
@@ -229,7 +218,6 @@ namespace MonoTests.System.Reflection.Emit
 
                [Test]
                [ExpectedException (typeof (NotSupportedException))]
-               [Category ("ValueAdd")]
                public void TestGetConstructorIncomplete ()
                {
                        EnumBuilder enumBuilder = GenerateEnum ();
index 9cc8ca79a413f707d27ad210899583c3fdb03456..d03e4c21f2af694ee1ea2bf45fa97fad43341c19 100644 (file)
@@ -2261,11 +2261,14 @@ namespace MonoTests.System
 
                [Test]
                public void GetGenericMethodDefinitionOverInflatedMethodOnGTD () {
+                       var s = new List<int> () { 1, 2, 3 }.ConvertAll ( i => i.ToString () );
+                       Assert.AreEqual (3, s.Count);
                        var l = typeof (List<>);
                        var m = l.GetMethod ("ConvertAll");
                        var infl = m.MakeGenericMethod (typeof (int));
                        var res = m.GetGenericMethodDefinition ();
                        Assert.AreEqual (m, res, "#1");
+                       Assert.AreEqual (1, infl.GetGenericArguments().Length, "#2");
                }
 
                [Test]
index 20ea722a1551791e8dfc5c61379586f400157650..93f29727f99dbcb37a28135dcf43c8619e86f0f8 100644 (file)
@@ -124,6 +124,21 @@ namespace NUnit.Framework
                        Assert.That(arg1, Is.LessThanOrEqualTo(arg2), message, args);
                }
 
+               public static void LessOrEqual(long arg1, long arg2, string message = null, params object[] args)
+               {
+                       Assert.That(arg1, Is.LessThanOrEqualTo(arg2), message, args);
+               }
+
+               public static void LessOrEqual(System.DateTime arg1, System.DateTime arg2, string message = null, params object[] args)
+               {
+                       Assert.That(arg1, Is.LessThanOrEqualTo(arg2), message, args);
+               }
+
+               public static void LessOrEqual(System.TimeSpan arg1, System.TimeSpan arg2, string message = null, params object[] args)
+               {
+                       Assert.That(arg1, Is.LessThanOrEqualTo(arg2), message, args);
+               }
+
                public static void IsNotInstanceOfType(System.Type expected, object actual, string message, params object[] args )
                {
                        Assert.IsFalse (actual.GetType ().IsInstanceOfType (expected), message, args);
index e5b1cb0c57ad730db7c323e1ff9741ec7e3e17ac..35896715ac6ead8cd6b48aa2b7cbff950f2f7832 100644 (file)
@@ -2370,7 +2370,7 @@ static gboolean
 parse_public_key (const gchar *key, gchar** pubkey, gboolean *is_ecma)
 {
        const gchar *pkey;
-       gchar header [16], val, *arr;
+       gchar header [16], val, *arr, *endp;
        gint i, j, offset, bitlen, keylen, pkeylen;
        
        keylen = strlen (key) >> 1;
@@ -2432,16 +2432,10 @@ parse_public_key (const gchar *key, gchar** pubkey, gboolean *is_ecma)
        if (!pubkey)
                return TRUE;
                
+       arr = (gchar *)g_malloc (keylen + 4);
        /* Encode the size of the blob */
-       offset = 0;
-       if (keylen <= 127) {
-               arr = (gchar *)g_malloc (keylen + 1);
-               arr [offset++] = keylen;
-       } else {
-               arr = (gchar *)g_malloc (keylen + 2);
-               arr [offset++] = 0x80; /* 10bs */
-               arr [offset++] = keylen;
-       }
+       mono_metadata_encode_value (keylen, &arr[0], &endp);
+       offset = (gint)(endp-arr);
                
        for (i = offset, j = 0; i < keylen + offset; i++) {
                arr [i] = g_ascii_xdigit_value (key [j++]) << 4;
index 9439ebfab061919bccb7aea1c3454c4b4c39569a..bd853b21eb9b45cce831504f95aeda945a74333f 100644 (file)
@@ -428,26 +428,31 @@ static gint64 gc_start_time;
 static void
 on_gc_notification (GC_EventType event)
 {
-       MonoProfilerGCEvent e = (MonoProfilerGCEvent)event;
+       MonoProfilerGCEvent e;
 
-       switch (e) {
-       case MONO_GC_EVENT_PRE_STOP_WORLD:
+       switch (event) {
+       case GC_EVENT_PRE_STOP_WORLD:
+               e = MONO_GC_EVENT_PRE_STOP_WORLD;
                MONO_GC_WORLD_STOP_BEGIN ();
                break;
 
-       case MONO_GC_EVENT_POST_STOP_WORLD:
+       case GC_EVENT_POST_STOP_WORLD:
+               e = MONO_GC_EVENT_POST_STOP_WORLD;
                MONO_GC_WORLD_STOP_END ();
                break;
 
-       case MONO_GC_EVENT_PRE_START_WORLD:
+       case GC_EVENT_PRE_START_WORLD:
+               e = MONO_GC_EVENT_PRE_START_WORLD;
                MONO_GC_WORLD_RESTART_BEGIN (1);
                break;
 
-       case MONO_GC_EVENT_POST_START_WORLD:
+       case GC_EVENT_POST_START_WORLD:
+               e = MONO_GC_EVENT_POST_START_WORLD;
                MONO_GC_WORLD_RESTART_END (1);
                break;
 
-       case MONO_GC_EVENT_START:
+       case GC_EVENT_START:
+               e = MONO_GC_EVENT_START;
                MONO_GC_BEGIN (1);
 #ifndef DISABLE_PERFCOUNTERS
                if (mono_perfcounters)
@@ -457,7 +462,8 @@ on_gc_notification (GC_EventType event)
                gc_start_time = mono_100ns_ticks ();
                break;
 
-       case MONO_GC_EVENT_END:
+       case GC_EVENT_END:
+               e = MONO_GC_EVENT_END;
                MONO_GC_END (1);
 #if defined(ENABLE_DTRACE) && defined(__sun__)
                /* This works around a dtrace -G problem on Solaris.
@@ -483,14 +489,23 @@ on_gc_notification (GC_EventType event)
                break;
        }
 
-       MONO_PROFILER_RAISE (gc_event, (e, 0));
+       switch (event) {
+       case GC_EVENT_MARK_START:
+       case GC_EVENT_MARK_END:
+       case GC_EVENT_RECLAIM_START:
+       case GC_EVENT_RECLAIM_END:
+               break;
+       default:
+               MONO_PROFILER_RAISE (gc_event, (e, 0));
+               break;
+       }
 
-       switch (e) {
-       case MONO_GC_EVENT_PRE_STOP_WORLD:
+       switch (event) {
+       case GC_EVENT_PRE_STOP_WORLD:
                mono_thread_info_suspend_lock ();
                MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED, 0));
                break;
-       case MONO_GC_EVENT_POST_START_WORLD:
+       case GC_EVENT_POST_START_WORLD:
                mono_thread_info_suspend_unlock ();
                MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_POST_START_WORLD_UNLOCKED, 0));
                break;
index 56c3572e76e9137f7140bbed28329fd0c871c0dd..e685ac227abfc4693a2fedb33903a57e6a56d574 100644 (file)
@@ -35,7 +35,6 @@
 #include <mono/metadata/class-internals.h>
 #include <mono/metadata/debug-helpers.h>
 #include <mono/metadata/reflection.h>
-#include <mono/metadata/profiler.h>
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/exception.h>
 #include <mono/metadata/marshal.h>
index 01902b0bb0c2929c86b16189063edaa940264a9a..7b85f00fb0c1a5512fd4a29f4dfa8708bf6def33 100644 (file)
@@ -70,12 +70,23 @@ MONO_PROFILER_EVENT_2(gc_moves, GCMoves, MonoObject *const *, objects, uint64_t,
 MONO_PROFILER_EVENT_1(gc_resize, GCResize, uintptr_t, size)
 MONO_PROFILER_EVENT_3(gc_handle_created, GCHandleCreated, uint32_t, handle, MonoGCHandleType, type, MonoObject *, object)
 MONO_PROFILER_EVENT_2(gc_handle_deleted, GCHandleDeleted, uint32_t, handle, MonoGCHandleType, type)
-MONO_PROFILER_EVENT_4(gc_roots, GCRoots, MonoObject *const *, roots, const MonoProfilerGCRootType *, types, const uintptr_t *, extra, uint64_t, count)
 MONO_PROFILER_EVENT_0(gc_finalizing, GCFinalizing)
 MONO_PROFILER_EVENT_0(gc_finalized, GCFinalized)
 MONO_PROFILER_EVENT_1(gc_finalizing_object, GCFinalizingObject, MonoObject *, object)
 MONO_PROFILER_EVENT_1(gc_finalized_object, GCFinalizedObject, MonoObject *, object)
 
+/*
+ * This callback provides very low quality data and doesn't really match how
+ * roots are actually handled in the runtime. It will be replaced with a more
+ * sensible callback in the future. **This will be a breaking change.**
+ *
+ * In the meantime, you must define MONO_PROFILER_UNSTABLE_GC_ROOTS to be able
+ * to use this interface.
+ */
+#ifdef MONO_PROFILER_UNSTABLE_GC_ROOTS
+MONO_PROFILER_EVENT_4(gc_roots, GCRoots, MonoObject *const *, roots, const MonoProfilerGCRootType *, types, const uintptr_t *, extra, uint64_t, count)
+#endif
+
 MONO_PROFILER_EVENT_1(monitor_contention, MonitorContention, MonoObject *, object)
 MONO_PROFILER_EVENT_1(monitor_failed, MonitorFailed, MonoObject *, object)
 MONO_PROFILER_EVENT_1(monitor_acquired, MonitorAcquired, MonoObject *, object)
index 4d1b93d4a9566b1e452bcf43fce1bf3027bc7b1c..e087be07eb604fbfa0dc320637dfec8bd333998c 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef __MONO_PROFILER_PRIVATE_H__
 #define __MONO_PROFILER_PRIVATE_H__
 
+#define MONO_PROFILER_UNSTABLE_GC_ROOTS
 #include <mono/metadata/profiler.h>
 #include <mono/utils/mono-lazy-init.h>
 #include <mono/utils/mono-os-mutex.h>
@@ -48,7 +49,7 @@ typedef struct {
        MonoProfilerHandle sampling_owner;
        MonoSemType sampling_semaphore;
        MonoProfilerSampleMode sample_mode;
-       uint64_t sample_freq;
+       guint32 sample_freq;
        gboolean allocations;
 
 #define _MONO_PROFILER_EVENT(name) \
@@ -97,7 +98,8 @@ void mono_profiler_coverage_free (MonoMethod *method);
 gboolean mono_profiler_should_instrument_method (MonoMethod *method, gboolean entry);
 
 gboolean mono_profiler_sampling_enabled (void);
-void mono_profiler_sampling_thread_sleep (void);
+void mono_profiler_sampling_thread_post (void);
+void mono_profiler_sampling_thread_wait (void);
 
 static inline gboolean
 mono_profiler_allocations_enabled (void)
index a1e222fc1e66c2c8c39b26ac6bff50ab6c9aa88b..536749ce254f7308a64cc12ca4534380e47284a7 100644 (file)
@@ -11,6 +11,7 @@
 #include <mono/metadata/profiler-private.h>
 #include <mono/utils/mono-dl.h>
 #include <mono/utils/mono-error-internals.h>
+#include <mono/utils/mono-logger-internals.h>
 
 MonoProfilerState mono_profiler_state;
 
@@ -37,7 +38,7 @@ load_profiler (MonoDl *module, const char *desc, const char *suffix)
        char *err;
 
        if (!(err = mono_dl_symbol (module, old_name, (gpointer) &func))) {
-               g_warning ("Found old-style startup symbol %s; profiler has not been migrated to the new API.", old_name);
+               mono_profiler_printf_err ("Found old-style startup symbol %s for %s; profiler has not been migrated to the new API.", old_name, desc);
                g_free (old_name);
                return FALSE;
        }
@@ -81,7 +82,7 @@ load_profiler_from_executable (const char *desc, const char *name)
        MonoDl *module = mono_dl_open (NULL, MONO_DL_EAGER, &err);
 
        if (!module) {
-               g_warning ("Could not open main executable (%s).", err);
+               mono_profiler_printf_err ("Could not open main executable: %s", err);
                g_free (err);
                return FALSE;
        }
@@ -125,8 +126,6 @@ load_profiler_from_installation (const char *libname, const char *desc)
 void
 mono_profiler_load (const char *desc)
 {
-       mono_gc_base_init ();
-
        if (!desc || !strcmp ("default", desc))
                desc = "log:report";
 
@@ -150,7 +149,7 @@ mono_profiler_load (const char *desc)
                        res = load_profiler_from_directory (NULL, libname, desc);
 
                if (!res)
-                       g_warning ("The '%s' profiler wasn't found in the main executable nor could it be loaded from '%s'.", mname, libname);
+                       mono_profiler_printf_err ("The '%s' profiler wasn't found in the main executable nor could it be loaded from '%s'.", mname, libname);
 
                g_free (libname);
        }
@@ -326,7 +325,7 @@ mono_profiler_enable_sampling (MonoProfilerHandle handle)
 }
 
 mono_bool
-mono_profiler_set_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode mode, uint64_t freq)
+mono_profiler_set_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode mode, uint32_t freq)
 {
        if (handle != mono_profiler_state.sampling_owner)
                return FALSE;
@@ -334,13 +333,13 @@ mono_profiler_set_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode
        mono_profiler_state.sample_mode = mode;
        mono_profiler_state.sample_freq = freq;
 
-       mono_os_sem_post (&mono_profiler_state.sampling_semaphore);
+       mono_profiler_sampling_thread_post ();
 
        return TRUE;
 }
 
 mono_bool
-mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint64_t *freq)
+mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint32_t *freq)
 {
        if (mode)
                *mode = mono_profiler_state.sample_mode;
@@ -358,7 +357,13 @@ mono_profiler_sampling_enabled (void)
 }
 
 void
-mono_profiler_sampling_thread_sleep (void)
+mono_profiler_sampling_thread_post (void)
+{
+       mono_os_sem_post (&mono_profiler_state.sampling_semaphore);
+}
+
+void
+mono_profiler_sampling_thread_wait (void)
 {
        mono_os_sem_wait (&mono_profiler_state.sampling_semaphore, MONO_SEM_FLAGS_NONE);
 }
index 2d5935e6fdd8b4d9f3ab35084357efe31d0d0eb8..6dd1ea336335a0abcf290c4d67623d7f70ea6718 100644 (file)
@@ -134,14 +134,14 @@ typedef enum {
 MONO_API mono_bool mono_profiler_enable_sampling (MonoProfilerHandle handle);
 
 /*
- * Sets the sampling mode and frequency (in Hz). If the calling profiler has
- * ownership over sampling settings, the settings will be changed and this
- * function will return TRUE; otherwise, it returns FALSE without changing any
- * settings.
+ * Sets the sampling mode and frequency (in Hz). The frequency must be a
+ * positive number. If the calling profiler has ownership over sampling
+ * settings, the settings will be changed and this function will return TRUE;
+ * otherwise, it returns FALSE without changing any settings.
  *
  * This function is async safe.
  */
-MONO_API mono_bool mono_profiler_set_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode mode, uint64_t freq);
+MONO_API mono_bool mono_profiler_set_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode mode, uint32_t freq);
 
 /*
  * Retrieves the current sampling mode and/or frequency (in Hz). Returns TRUE if
@@ -150,7 +150,7 @@ MONO_API mono_bool mono_profiler_set_sample_mode (MonoProfilerHandle handle, Mon
  *
  * This function is async safe.
  */
-MONO_API mono_bool mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint64_t *freq);
+MONO_API mono_bool mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint32_t *freq);
 
 /*
  * Enables instrumentation of GC allocations. This is necessary so that managed
@@ -196,6 +196,7 @@ typedef MonoProfilerCallInstrumentationFlags (*MonoProfilerCallInstrumentationFi
  */
 MONO_API void mono_profiler_set_call_instrumentation_filter_callback (MonoProfilerHandle handle, MonoProfilerCallInstrumentationFilterCallback cb);
 
+#ifdef MONO_PROFILER_UNSTABLE_GC_ROOTS
 typedef enum {
        /* Upper 2 bytes. */
        MONO_PROFILER_GC_ROOT_PINNING = 1 << 8,
@@ -211,6 +212,7 @@ typedef enum {
 
        MONO_PROFILER_GC_ROOT_TYPEMASK = 0xff,
 } MonoProfilerGCRootType;
+#endif
 
 typedef enum {
        /* data = MonoMethod *method */
@@ -227,18 +229,13 @@ typedef enum {
        MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING = 9,
 } MonoProfilerCodeBufferType;
 
-// Keep somewhat in sync with libgc/include/gc.h : GC_EventType.
 typedef enum {
-       MONO_GC_EVENT_START = 0,
-       MONO_GC_EVENT_MARK_START = 1,
-       MONO_GC_EVENT_MARK_END = 2,
-       MONO_GC_EVENT_RECLAIM_START = 3,
-       MONO_GC_EVENT_RECLAIM_END = 4,
-       MONO_GC_EVENT_END = 5,
        MONO_GC_EVENT_PRE_STOP_WORLD = 6,
        /* When this event arrives, the GC and suspend locks are acquired. */
        MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED = 10,
        MONO_GC_EVENT_POST_STOP_WORLD = 7,
+       MONO_GC_EVENT_START = 0,
+       MONO_GC_EVENT_END = 5,
        MONO_GC_EVENT_PRE_START_WORLD = 8,
        /* When this event arrives, the GC and suspend locks are released. */
        MONO_GC_EVENT_POST_START_WORLD_UNLOCKED = 11,
index d9a483898e7886b2739973aa57a8745b725d921b..e3cae00e7e605d20cd70630e0a534b4155ea0685 100644 (file)
@@ -383,25 +383,21 @@ sgen_client_binary_protocol_block_set_state (gpointer addr, size_t size, int old
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_mark_start (int generation)
 {
-       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_MARK_START, generation));
 }
 
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_mark_end (int generation)
 {
-       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_MARK_END, generation));
 }
 
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_reclaim_start (int generation)
 {
-       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_RECLAIM_START, generation));
 }
 
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_reclaim_end (int generation)
 {
-       MONO_PROFILER_RAISE (gc_event, (MONO_GC_EVENT_RECLAIM_END, generation));
 }
 
 static void
index 8556a498940d8b5ae622a8accda3e9f76c79711c..e6cbc3dbfead9b35f8be5412e58b529d09bdeaa5 100644 (file)
@@ -23,8 +23,6 @@
 #include <mono/metadata/object.h>
 #include <mono/metadata/exception.h>
 #include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/profiler.h>
-#include <mono/metadata/profiler-private.h>
 #include <mono/metadata/gc-internals.h>
 
 /* This function is redirected to String.CreateString ()
index 439bdd81a2a0d366e5f1a3fec63ac8448cbfed49..bd42451469ffb2bdc511c9262e2b6c0312f4cf81 100644 (file)
@@ -76,6 +76,7 @@
 #define WSAEHOSTDOWN               10064
 #define WSAEHOSTUNREACH            10065
 #define WSASYSCALLFAILURE          10107
+#define WSAENXIO                   100001
 
 #endif
 
index 8b1c3a9f5b87938d165d4c66af723fe2d5cd789e..a0fbf95003d08d3c0ee12cf5de77a73907982910 100644 (file)
@@ -299,20 +299,20 @@ gboolean
 mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_bytes_avail, guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes)
 {
        gboolean result;
-       ULARGE_INTEGER *wapi_free_bytes_avail;
-       ULARGE_INTEGER *wapi_total_number_of_bytes;
-       ULARGE_INTEGER *wapi_total_number_of_free_bytes;
+       ULARGE_INTEGER wapi_free_bytes_avail;
+       ULARGE_INTEGER wapi_total_number_of_bytes;
+       ULARGE_INTEGER wapi_total_number_of_free_bytes;
 
        MONO_ENTER_GC_SAFE;
-       result = GetDiskFreeSpaceEx (path_name, wapi_free_bytes_avail, wapi_total_number_of_bytes, wapi_total_number_of_free_bytes);
+       result = GetDiskFreeSpaceEx (path_name, &wapi_free_bytes_avail, &wapi_total_number_of_bytes, &wapi_total_number_of_free_bytes);
        MONO_EXIT_GC_SAFE;
        if (result) {
                if (free_bytes_avail)
-                       *free_bytes_avail = wapi_free_bytes_avail->QuadPart;
+                       *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
                if (total_number_of_bytes)
-                       *total_number_of_bytes = wapi_total_number_of_bytes->QuadPart;
+                       *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
                if (total_number_of_free_bytes)
-                       *total_number_of_free_bytes = wapi_total_number_of_free_bytes->QuadPart;
+                       *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
        }
 
        return result;
index 87743377324bc01c406342ed181dd3d7229d36ff..5816b142b051e09e6c784e93518bbd9241dbd643 100644 (file)
@@ -1324,6 +1324,9 @@ mono_w32socket_convert_error (gint error)
        case ENODEV: return WSAENETDOWN;
 #ifdef EPROTOTYPE
        case EPROTOTYPE: return WSAEPROTOTYPE;
+#endif
+#ifdef ENXIO
+       case ENXIO: return WSAENXIO;
 #endif
        default:
                g_error ("%s: no translation into winsock error for (%d) \"%s\"", __func__, error, g_strerror (error));
index a9a477767b6c6f34dee6e1a1689090df86220bb6..b9c86a44c8906c043bff5a82e3e52d9683c6be9a 100644 (file)
@@ -11631,7 +11631,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 #ifdef ENABLE_LLVM
        if (acfg->llvm) {
                llvm_acfg = acfg;
-               mono_llvm_create_aot_module (acfg->image->assembly, acfg->global_prefix, TRUE, acfg->aot_opts.static_link, acfg->aot_opts.llvm_only);
+               mono_llvm_create_aot_module (acfg->image->assembly, acfg->global_prefix, acfg->nshared_got_entries, TRUE, acfg->aot_opts.static_link, acfg->aot_opts.llvm_only);
        }
 #endif
 
index 934eb0a54a363138728a0bdc19f64f45e77df70b..750aa206b992f47a3edd1f041041b090c3e04068 100644 (file)
@@ -36,7 +36,6 @@
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/debug-helpers.h>
-#include "mono/metadata/profiler.h"
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/environment.h>
index 88eac7edb4550f5cfbea080941a36a37afc95da7..09c94309b70353d96b20dcc7a676d4e01665515b 100644 (file)
@@ -2820,4 +2820,80 @@ END:
        pop
        ret
   }
+
+  .method public static int32 test_2_fault () cil managed
+  {
+       .maxstack 16
+       .locals init (int32 V_0)
+    IL_0000:  ldc.i4.0
+    IL_0001:  stloc.0
+    .try
+    {
+      .try
+      {
+        IL_0002:  newobj     instance void [mscorlib]System.Exception::.ctor()
+        IL_0007:  throw
+               leave.s    IL_0018
+      }  // end .try
+         fault
+      {
+        IL_0009:  ldloc.0
+        IL_000a:  ldc.i4.1
+        IL_000b:  add
+        IL_000c:  stloc.0
+                                 endfinally
+      }  // end handler
+      IL_000f:  leave.s    IL_0018
+
+    }  // end .try
+    catch [mscorlib]System.Object
+    {
+      IL_0011:  pop
+      IL_0012:  ldloc.0
+      IL_0013:  ldc.i4.1
+      IL_0014:  add
+      IL_0015:  stloc.0
+      IL_0016:  leave.s    IL_0018
+
+    }  // end handler
+    IL_0018:  ldloc.0
+       ret
+       }
+
+  .method public static int32 test_0_fault_no_exception () cil managed
+  {
+       .maxstack 16
+       .locals init (int32 V_0)
+    IL_0000:  ldc.i4.0
+    IL_0001:  stloc.0
+    .try
+    {
+      .try
+      {
+               leave.s    IL_0018
+      }  // end .try
+         fault
+      {
+        IL_0009:  ldloc.0
+        IL_000a:  ldc.i4.1
+        IL_000b:  add
+        IL_000c:  stloc.0
+                                 endfinally
+      }  // end handler
+      IL_000f:  leave.s    IL_0018
+
+    }  // end .try
+    catch [mscorlib]System.Object
+    {
+      IL_0011:  pop
+      IL_0012:  ldloc.0
+      IL_0013:  ldc.i4.1
+      IL_0014:  add
+      IL_0015:  stloc.0
+      IL_0016:  leave.s    IL_0018
+
+    }  // end handler
+    IL_0018:  ldloc.0
+       ret
+       }
 }
index 84acd5ce7545f38d737ca4709c2be33e1015ee95..bab77635fde6c1a54313b1dc4faef6f4f018563f 100644 (file)
@@ -7099,9 +7099,14 @@ mono_arch_emit_epilog (MonoCompile *cfg)
                } else {
                        /* FIXME: maybe save the jit tls in the prolog */
                }
-               if (cfg->used_int_regs & (1 << AMD64_RBP)) {
+               if (cfg->used_int_regs & (1 << AMD64_RBP))
                        amd64_mov_reg_membase (code, AMD64_RBP, cfg->frame_reg, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, rbp), 8);
-               }
+               if (cfg->arch.omit_fp)
+                       /*
+                        * emit_setup_lmf () marks RBP as saved, we have to mark it as same value here before clearing up the stack
+                        * since its stack slot will become invalid.
+                        */
+                       mono_emit_unwind_op_same_value (cfg, code, AMD64_RBP);
        }
 
        /* Restore callee saved regs */
@@ -7109,9 +7114,9 @@ mono_arch_emit_epilog (MonoCompile *cfg)
                if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->arch.saved_iregs & (1 << i))) {
                        /* Restore only used_int_regs, not arch.saved_iregs */
 #if defined(MONO_SUPPORT_TASKLETS)
-                       int restore_reg=1;
+                       int restore_reg = 1;
 #else
-                       int restore_reg=(cfg->used_int_regs & (1 << i));
+                       int restore_reg = (cfg->used_int_regs & (1 << i));
 #endif
                        if (restore_reg) {
                                amd64_mov_reg_membase (code, i, cfg->frame_reg, save_area_offset, 8);
index 75e0a8800fb7531a7083f293f0989b5f44de37ff..73be22c7c6e91d531b43f47c54efdeb9be0424ec 100644 (file)
@@ -34,7 +34,6 @@
 #include <mono/metadata/threads.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/debug-helpers.h>
-#include "mono/metadata/profiler.h"
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/environment.h>
index bd4283bf3f87fab69d58e96c199e53f3acded15c..c8e6b75b496511ff87027095278dea133ac0e0ad 100644 (file)
@@ -60,7 +60,7 @@
 #include <mono/metadata/gc-internals.h>
 #include <mono/metadata/debug-internals.h>
 #include <mono/metadata/mono-debug.h>
-#include <mono/metadata/profiler.h>
+#include <mono/metadata/profiler-private.h>
 #include <mono/metadata/mono-endian.h>
 #include <mono/metadata/environment.h>
 #include <mono/metadata/mono-mlist.h>
index a5c0397221b6f5e8889f9447d7d98605c58c0740..fb1dcac98133843d52cc48ed74aef539240d4340 100644 (file)
@@ -14,7 +14,7 @@ typedef struct {
        void (*cleanup)(void);
        void (*emit_method)(MonoCompile *cfg);
        void (*emit_call)(MonoCompile *cfg, MonoCallInst *call);
-       void (*create_aot_module)(MonoAssembly *assembly, const char *global_prefix, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only);
+       void (*create_aot_module)(MonoAssembly *assembly, const char *global_prefix, int initial_got_size, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only);
        void (*emit_aot_module)(const char *filename, const char *cu_name);
        void (*check_method_supported)(MonoCompile *cfg);
        void (*emit_aot_file_info)(MonoAotFileInfo *info, gboolean has_jitted_code);
@@ -50,9 +50,9 @@ mono_llvm_emit_call (MonoCompile *cfg, MonoCallInst *call)
 }
 
 void
-mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only)
+mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix, int initial_got_size, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only)
 {
-       backend.create_aot_module (assembly, global_prefix, emit_dwarf, static_link, llvm_only);
+       backend.create_aot_module (assembly, global_prefix, initial_got_size, emit_dwarf, static_link, llvm_only);
 }
 
 void
index f1bec8a2a156f545fceb3457821e42de8aab5310..81c12dfe7791ff0966b6abe23793d80842b6e167 100644 (file)
@@ -1832,7 +1832,7 @@ emit_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, LL
                clause = get_most_deep_clause (cfg, ctx, bb);
 
                if (clause) {
-                       g_assert (clause->flags == MONO_EXCEPTION_CLAUSE_NONE || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY);
+                       g_assert (clause->flags == MONO_EXCEPTION_CLAUSE_NONE || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY || clause->flags == MONO_EXCEPTION_CLAUSE_FAULT);
 
                        /*
                         * Have to use an invoke instead of a call, branching to the
@@ -1871,7 +1871,7 @@ emit_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, LL
                         * handler bblock of the clause containing this bblock.
                         */
 
-                       g_assert (ec->flags == MONO_EXCEPTION_CLAUSE_NONE || ec->flags == MONO_EXCEPTION_CLAUSE_FINALLY);
+                       g_assert (ec->flags == MONO_EXCEPTION_CLAUSE_NONE || ec->flags == MONO_EXCEPTION_CLAUSE_FINALLY || ec->flags == MONO_EXCEPTION_CLAUSE_FAULT);
 
                        tblock = cfg->cil_offset_to_bb [ec->handler_offset];
                        g_assert (tblock);
@@ -3911,7 +3911,7 @@ emit_landing_pad (EmitContext *ctx, int group_index, int group_size)
        MonoExceptionClause *group_cursor = group_start;
 
        for (int i = 0; i < group_size; i ++) {
-               if (!(group_cursor->flags & MONO_EXCEPTION_CLAUSE_FINALLY))
+               if (!(group_cursor->flags & MONO_EXCEPTION_CLAUSE_FINALLY || group_cursor->flags & MONO_EXCEPTION_CLAUSE_FAULT))
                        finally_only = FALSE;
 
                group_cursor++;
@@ -3960,7 +3960,7 @@ emit_llvmonly_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBasicBloc
        MonoExceptionClause *clause = &ctx->cfg->header->clauses [clause_index];
 
        // Make exception available to catch blocks
-       if (!(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
+       if (!(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY || clause->flags & MONO_EXCEPTION_CLAUSE_FAULT)) {
                LLVMValueRef mono_exc = mono_llvm_emit_load_exception_call (ctx, ctx->builder);
 
                g_assert (ctx->ex_var);
@@ -6537,33 +6537,39 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        LLVMValueRef val, switch_ins, callee;
                        GSList *bb_list;
                        BBInfo *info;
+                       gboolean is_fault = MONO_REGION_FLAGS (bb->region) == MONO_EXCEPTION_CLAUSE_FAULT;
 
-                       handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)));
-                       g_assert (handler_bb);
-                       info = &bblocks [handler_bb->block_num];
-                       lhs = info->finally_ind;
-                       g_assert (lhs);
+                       /*
+                        * Fault clauses are like finally clauses, but they are only called if an exception is thrown.
+                        */
+                       if (!is_fault) {
+                               handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)));
+                               g_assert (handler_bb);
+                               info = &bblocks [handler_bb->block_num];
+                               lhs = info->finally_ind;
+                               g_assert (lhs);
 
-                       bb_list = info->call_handler_return_bbs;
+                               bb_list = info->call_handler_return_bbs;
 
-                       resume_bb = gen_bb (ctx, "ENDFINALLY_RESUME_BB");
+                               resume_bb = gen_bb (ctx, "ENDFINALLY_RESUME_BB");
 
-                       /* Load the finally variable */
-                       val = LLVMBuildLoad (builder, lhs, "");
+                               /* Load the finally variable */
+                               val = LLVMBuildLoad (builder, lhs, "");
 
-                       /* Reset the variable */
-                       LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), lhs);
+                               /* Reset the variable */
+                               LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), lhs);
 
-                       /* Branch to either resume_bb, or to the bblocks in bb_list */
-                       switch_ins = LLVMBuildSwitch (builder, val, resume_bb, g_slist_length (bb_list));
-                       /* 
-                        * The other targets are added at the end to handle OP_CALL_HANDLER
-                        * opcodes processed later.
-                        */
-                       info->endfinally_switch_ins_list = g_slist_append_mempool (cfg->mempool, info->endfinally_switch_ins_list, switch_ins);
+                               /* Branch to either resume_bb, or to the bblocks in bb_list */
+                               switch_ins = LLVMBuildSwitch (builder, val, resume_bb, g_slist_length (bb_list));
+                               /*
+                                * The other targets are added at the end to handle OP_CALL_HANDLER
+                                * opcodes processed later.
+                                */
+                               info->endfinally_switch_ins_list = g_slist_append_mempool (cfg->mempool, info->endfinally_switch_ins_list, switch_ins);
 
-                       builder = ctx->builder = create_builder (ctx);
-                       LLVMPositionBuilderAtEnd (ctx->builder, resume_bb);
+                               builder = ctx->builder = create_builder (ctx);
+                               LLVMPositionBuilderAtEnd (ctx->builder, resume_bb);
+                       }
 
                        if (ctx->llvm_only) {
                                emit_resume_eh (ctx, bb);
@@ -7003,8 +7009,8 @@ emit_method_inner (EmitContext *ctx)
        header = cfg->header;
        for (i = 0; i < header->num_clauses; ++i) {
                clause = &header->clauses [i];
-               if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_NONE) {
-                   set_failure (ctx, "non-finally/catch clause.");
+               if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_FAULT && clause->flags != MONO_EXCEPTION_CLAUSE_NONE) {
+                   set_failure (ctx, "non-finally/catch/fault clause.");
                        return;
                }
        }
@@ -8423,7 +8429,7 @@ mono_llvm_free_domain_info (MonoDomain *domain)
 }
 
 void
-mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only)
+mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix, int initial_got_size, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only)
 {
        MonoLLVMModule *module = &aot_module;
 
@@ -8447,7 +8453,7 @@ mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix,
        module->static_link = static_link;
        module->llvm_only = llvm_only;
        /* The first few entries are reserved */
-       module->max_got_offset = 16;
+       module->max_got_offset = initial_got_size;
        module->context = LLVMGetGlobalContext ();
 
        if (llvm_only)
index 483729d1c3bbc03b3a2ee5dfb392b183c0470b72..0942c9a7d42370d478d2ef1e3a1fd1fceaf1b3c6 100644 (file)
@@ -13,7 +13,7 @@ void     mono_llvm_init                     (void) MONO_LLVM_INTERNAL;
 void     mono_llvm_cleanup                  (void) MONO_LLVM_INTERNAL;
 void     mono_llvm_emit_method              (MonoCompile *cfg) MONO_LLVM_INTERNAL;
 void     mono_llvm_emit_call                (MonoCompile *cfg, MonoCallInst *call) MONO_LLVM_INTERNAL;
-void     mono_llvm_create_aot_module        (MonoAssembly *assembly, const char *global_prefix, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only) MONO_LLVM_INTERNAL;
+void     mono_llvm_create_aot_module        (MonoAssembly *assembly, const char *global_prefix, int initial_got_size, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only) MONO_LLVM_INTERNAL;
 void     mono_llvm_emit_aot_module          (const char *filename, const char *cu_name) MONO_LLVM_INTERNAL;
 void     mono_llvm_emit_aot_file_info       (MonoAotFileInfo *info, gboolean has_jitted_code) MONO_LLVM_INTERNAL;
 void     mono_llvm_emit_aot_data            (const char *symbol, guint8 *data, int data_len) MONO_LLVM_INTERNAL;
index a3fd4f0e2983c745e09adc7c2ec685733a8337af..8b17287a21a5aa0bd48fc9828176dda9ec1b255b 100644 (file)
@@ -40,7 +40,6 @@
 #include <mono/metadata/threads.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/debug-helpers.h>
-#include "mono/metadata/profiler.h"
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/environment.h>
@@ -641,14 +640,18 @@ init:
        mono_profiler_get_sample_mode (NULL, &mode, NULL);
 
        if (mode == MONO_PROFILER_SAMPLE_MODE_NONE) {
-               mono_profiler_sampling_thread_sleep ();
+               mono_profiler_sampling_thread_wait ();
+
+               if (!InterlockedRead (&sampling_thread_running))
+                       goto done;
+
                goto init;
        }
 
        clock_init (mode);
 
        for (guint64 sleep = clock_get_time_ns (); InterlockedRead (&sampling_thread_running); clock_sleep_ns_abs (sleep)) {
-               uint64_t freq;
+               uint32_t freq;
                MonoProfilerSampleMode new_mode;
 
                mono_profiler_get_sample_mode (NULL, &new_mode, &freq);
@@ -677,10 +680,11 @@ init:
                } FOREACH_THREAD_SAFE_END
        }
 
-       InterlockedWrite (&sampling_thread_exiting, 1);
-
        clock_cleanup ();
 
+done:
+       InterlockedWrite (&sampling_thread_exiting, 1);
+
        pthread_setschedparam (pthread_self (), old_policy, &old_sched);
 
        mono_thread_info_detach ();
@@ -693,6 +697,8 @@ mono_runtime_shutdown_stat_profiler (void)
 {
        InterlockedWrite (&sampling_thread_running, 0);
 
+       mono_profiler_sampling_thread_post ();
+
 #ifndef PLATFORM_MACOSX
        /*
         * There is a slight problem when we're using CLOCK_PROCESS_CPUTIME_ID: If
index 5bd78513c8595453cfa4c36f8d9d89b55564439a..8e385be0afca28fdce9979df8201258d1ce3051c 100644 (file)
@@ -39,7 +39,6 @@
 #include <mono/metadata/threads.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/debug-helpers.h>
-#include "mono/metadata/profiler.h"
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/environment.h>
index 3852baf81f1268a1862a32274c4d3a67c4ea3ff6..efb4739cde2c95866f9dcb34a2643fcf933a76d3 100644 (file)
@@ -27,7 +27,6 @@
 #include <mono/metadata/threads.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/debug-helpers.h>
-#include "mono/metadata/profiler.h"
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/environment.h>
index d058547fc414d8338372721c6ae99c21b30e05de..9948d16c14554277b1c313c217a664b2676a4ca5 100644 (file)
@@ -36,7 +36,6 @@
 #include <mono/metadata/threads.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/debug-helpers.h>
-#include "mono/metadata/profiler.h"
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/environment.h>
index d2b227d826c6263ba8eecf84487fb1087a18bce0..d8ee9101098f67d52d0bb356143ea6bae784e5e2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * mono-profiler-aot.c: Ahead of Time Compiler Profiler for Mono.
+ * aot.c: Ahead of Time Compiler Profiler for Mono.
  *
  *
  * Copyright 2008-2009 Novell, Inc (http://www.novell.com)
index 89a30193179607755687a9ec8d57a672f061e855..ff419be5d31f42bd5d4e17c1621de9062dc20916 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * mono-profiler-iomap.c: IOMAP string profiler for Mono.
+ * iomap.c: IOMAP string profiler for Mono.
  *
  * Authors:
  *   Marek Habersack <mhabersack@novell.com>
index a7d71f3202b726ae8448692c8716578a1dfd5ca2..8f56a644ac7bb9678f3405b6ebd154fea8f85ed3 100644 (file)
@@ -1,67 +1,36 @@
 #include <config.h>
-
+#include <mono/utils/mono-logger-internals.h>
+#include <mono/utils/mono-proclib.h>
 #include "log.h"
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
-#ifdef HAVE_SCHED_GETAFFINITY
-#include <sched.h>
-
-#  ifndef GLIBC_HAS_CPU_COUNT
-static int
-CPU_COUNT(cpu_set_t *set)
-{
-       int i, count = 0;
-
-       for (int i = 0; i < CPU_SETSIZE; i++)
-               if (CPU_ISSET(i, set))
-                       count++;
-       return count;
-}
-#  endif
-#endif
-
 typedef struct {
        const char *event_name;
        const int mask;
 } NameAndMask;
 
 static NameAndMask event_list[] = {
-       { "domain", PROFLOG_DOMAIN_EVENTS },
-       { "assembly", PROFLOG_ASSEMBLY_EVENTS },
-       { "module", PROFLOG_MODULE_EVENTS },
-       { "class", PROFLOG_CLASS_EVENTS },
-       { "jit", PROFLOG_JIT_COMPILATION_EVENTS },
        { "exception", PROFLOG_EXCEPTION_EVENTS },
-       { "gcalloc", PROFLOG_ALLOCATION_EVENTS },
-       { "gc", PROFLOG_GC_EVENTS },
-       { "thread", PROFLOG_THREAD_EVENTS },
-       { "calls", PROFLOG_CALL_EVENTS },
-       //{ "inscov", PROFLOG_INS_COVERAGE_EVENTS }, //this is a profiler API event, but there's no actual event for us to emit here
-       //{ "sampling", PROFLOG_SAMPLING_EVENTS }, //it makes no sense to enable/disable this event by itself
        { "monitor", PROFLOG_MONITOR_EVENTS },
-       { "gcmove", PROFLOG_GC_MOVES_EVENTS },
+       { "gc", PROFLOG_GC_EVENTS },
+       { "gcalloc", PROFLOG_GC_ALLOCATION_EVENTS },
+       { "gcmove", PROFLOG_GC_MOVE_EVENTS },
        { "gcroot", PROFLOG_GC_ROOT_EVENTS },
-       { "context", PROFLOG_CONTEXT_EVENTS },
-       { "finalization", PROFLOG_FINALIZATION_EVENTS },
-       { "counter", PROFLOG_COUNTER_EVENTS },
        { "gchandle", PROFLOG_GC_HANDLE_EVENTS },
+       { "finalization", PROFLOG_GC_FINALIZATION_EVENTS },
+       { "counter", PROFLOG_COUNTER_EVENTS },
+       { "jit", PROFLOG_JIT_EVENTS },
 
-       { "typesystem", PROFLOG_TYPELOADING_ALIAS },
-       { "coverage", PROFLOG_CODECOV_ALIAS },
-       //{ "sample", PROFLOG_PERF_SAMPLING_ALIAS }, //takes args, explicitly handles
-       { "alloc", PROFLOG_GC_ALLOC_ALIAS },
-       //{ "heapshot", PROFLOG_HEAPSHOT_ALIAS }, //takes args, explicitly handled
+       { "alloc", PROFLOG_ALLOC_ALIAS },
        { "legacy", PROFLOG_LEGACY_ALIAS },
 };
 
 static void usage (void);
 static void set_hsmode (ProfilerConfig *config, const char* val);
 static void set_sample_freq (ProfilerConfig *config, const char *val);
-static int mono_cpu_count (void);
-
 
 static gboolean
 match_option (const char *arg, const char *opt_name, const char **rval)
@@ -94,19 +63,25 @@ parse_arg (const char *arg, ProfilerConfig *config)
                config->do_report = TRUE;
        } else if (match_option (arg, "debug", NULL)) {
                config->do_debug = TRUE;
-       } else if (match_option (arg, "debug-coverage", NULL)) {
-               config->debug_coverage = TRUE;
-       } else if (match_option (arg, "sampling-real", NULL)) {
-               config->sampling_mode = MONO_PROFILER_SAMPLE_MODE_REAL;
-       } else if (match_option (arg, "sampling-process", NULL)) {
-               config->sampling_mode = MONO_PROFILER_SAMPLE_MODE_PROCESS;
        } else if (match_option (arg, "heapshot", &val)) {
-               config->enable_mask |= PROFLOG_HEAPSHOT_ALIAS;
                set_hsmode (config, val);
+               if (config->hs_mode != MONO_PROFILER_HEAPSHOT_NONE)
+                       config->enable_mask |= PROFLOG_HEAPSHOT_ALIAS;
+       } else if (match_option (arg, "heapshot-on-shutdown", NULL)) {
+               config->hs_on_shutdown = TRUE;
+               config->enable_mask |= PROFLOG_HEAPSHOT_ALIAS;
        } else if (match_option (arg, "sample", &val)) {
                set_sample_freq (config, val);
-               if (config->sample_freq)
-                       config->enable_mask |= PROFLOG_PERF_SAMPLING_ALIAS;
+               config->sampling_mode = MONO_PROFILER_SAMPLE_MODE_PROCESS;
+               config->enable_mask |= PROFLOG_SAMPLE_EVENTS;
+       } else if (match_option (arg, "sample-real", &val)) {
+               set_sample_freq (config, val);
+               config->sampling_mode = MONO_PROFILER_SAMPLE_MODE_REAL;
+               config->enable_mask |= PROFLOG_SAMPLE_EVENTS;
+       } else if (match_option (arg, "calls", NULL)) {
+               config->enter_leave = TRUE;
+       } else if (match_option (arg, "coverage", NULL)) {
+               config->collect_coverage = TRUE;
        } else if (match_option (arg, "zip", NULL)) {
                config->use_zip = TRUE;
        } else if (match_option (arg, "output", &val)) {
@@ -119,7 +94,6 @@ parse_arg (const char *arg, ProfilerConfig *config)
                int num_frames = strtoul (val, &end, 10);
                if (num_frames > MAX_FRAMES)
                        num_frames = MAX_FRAMES;
-               config->notraces = num_frames == 0;
                config->num_frames = num_frames;
        } else if (match_option (arg, "maxsamples", &val)) {
                char *end;
@@ -145,9 +119,9 @@ parse_arg (const char *arg, ProfilerConfig *config)
                                break;
                        }
                }
-               if (i == G_N_ELEMENTS (event_list)) {
-                       printf ("Could not parse argument %s\n", arg);
-               }
+
+               if (i == G_N_ELEMENTS (event_list))
+                       mono_profiler_printf_err ("Could not parse argument: %s", arg);
        }
 }
 
@@ -157,7 +131,7 @@ load_args_from_env_or_default (ProfilerConfig *config)
        //XXX change this to header constants
 
        config->max_allocated_sample_hits = mono_cpu_count () * 1000;
-       config->sampling_mode = MONO_PROFILER_SAMPLE_MODE_PROCESS;
+       config->sampling_mode = MONO_PROFILER_SAMPLE_MODE_NONE;
        config->sample_freq = 100;
        config->max_call_depth = 100;
        config->num_frames = MAX_FRAMES;
@@ -227,183 +201,88 @@ proflog_parse_args (ProfilerConfig *config, const char *desc)
 static void
 set_hsmode (ProfilerConfig *config, const char* val)
 {
-       char *end;
-       unsigned int count;
-       if (!val)
+       if (!val) {
+               config->hs_mode = MONO_PROFILER_HEAPSHOT_MAJOR;
                return;
+       }
+
        if (strcmp (val, "ondemand") == 0) {
-               config->hs_mode_ondemand = TRUE;
+               config->hs_mode = MONO_PROFILER_HEAPSHOT_ON_DEMAND;
                return;
        }
 
-       count = strtoul (val, &end, 10);
+       char *end;
+
+       unsigned int count = strtoul (val, &end, 10);
+
        if (val == end) {
                usage ();
                return;
        }
 
-       if (strcmp (end, "ms") == 0)
-               config->hs_mode_ms = count;
-       else if (strcmp (end, "gc") == 0)
-               config->hs_mode_gc = count;
-       else
+       if (strcmp (end, "ms") == 0) {
+               config->hs_mode = MONO_PROFILER_HEAPSHOT_X_MS;
+               config->hs_freq_ms = count;
+       } else if (strcmp (end, "gc") == 0) {
+               config->hs_mode = MONO_PROFILER_HEAPSHOT_X_GC;
+               config->hs_freq_gc = count;
+       } else
                usage ();
 }
 
-/*
-Sampling frequency allows for one undocumented, hidden and ignored argument. The sampling kind.
-Back in the day when this was done using perf, we could specify one of: cycles,instr,cacherefs,cachemiss,branches,branchmiss
-With us moving ot userland sampling, those options are now meaningless.
-*/
 static void
 set_sample_freq (ProfilerConfig *config, const char *val)
 {
        if (!val)
                return;
 
-       const char *p = val;
-
-       // Is it only the frequency (new option style)?
-       if (isdigit (*p))
-               goto parse;
-
-       // Skip the sample type for backwards compatibility.
-       while (isalpha (*p))
-               p++;
-
-       // Skip the forward slash only if we got a sample type.
-       if (p != val && *p == '/') {
-               p++;
-
-               char *end;
-
-       parse:
-               config->sample_freq = strtoul (p, &end, 10);
+       char *end;
 
-               if (p == end) {
-                       usage ();
-                       return; 
-               }
+       int freq = strtoul (val, &end, 10);
 
-               p = end;
+       if (val == end) {
+               usage ();
+               return;
        }
 
-       if (*p)
-               usage ();
+       config->sample_freq = freq;
 }
 
 static void
 usage (void)
 {
-       printf ("Log profiler version %d.%d (format: %d)\n", LOG_VERSION_MAJOR, LOG_VERSION_MINOR, LOG_DATA_VERSION);
-       printf ("Usage: mono --profile=log[:OPTION1[,OPTION2...]] program.exe\n");
-       printf ("Options:\n");
-       printf ("\thelp                 show this usage info\n");
-       printf ("\t[no]'event'          enable/disable a profiling event. Valid values: domain, assembly, module, class, jit, exception, gcalloc, gc, thread, monitor, gcmove, gcroot, context, finalization, counter, gchandle\n");
-       printf ("\t[no]typesystem       enable/disable typesystem related events such as class and assembly loading\n");
-       printf ("\t[no]alloc            enable/disable recording allocation info\n");
-       printf ("\t[no]calls            enable/disable recording enter/leave method events\n");
-       printf ("\t[no]legacy           enable/disable pre mono 5.4 default profiler events\n");
-       printf ("\tsample[=frequency]   enable/disable statistical sampling of threads (frequency in Hz, 100 by default)\n");
-       printf ("\theapshot[=MODE]      record heap shot info (by default at each major collection)\n");
-       printf ("\t                     MODE: every XXms milliseconds, every YYgc collections, ondemand\n");
-       printf ("\t[no]coverage         enable collection of code coverage data\n");
-       printf ("\tcovfilter=ASSEMBLY   add an assembly to the code coverage filters\n");
-       printf ("\t                     add a + to include the assembly or a - to exclude it\n");
-       printf ("\t                     covfilter=-mscorlib\n");
-       printf ("\tcovfilter-file=FILE  use FILE to generate the list of assemblies to be filtered\n");
-       printf ("\tmaxframes=NUM        collect up to NUM stack frames\n");
-       printf ("\tcalldepth=NUM        ignore method events for call chain depth bigger than NUM\n");
-       printf ("\toutput=FILENAME      write the data to file FILENAME (The file is always overwriten)\n");
-       printf ("\toutput=+FILENAME     write the data to file FILENAME.pid (The file is always overwriten)\n");
-       printf ("\toutput=|PROGRAM      write the data to the stdin of PROGRAM\n");
-       printf ("\t                     %%t is subtituted with date and time, %%p with the pid\n");
-       printf ("\treport               create a report instead of writing the raw data to a file\n");
-       printf ("\tzip                  compress the output data\n");
-       printf ("\tport=PORTNUM         use PORTNUM for the listening command server\n");
-}
-
-static int
-mono_cpu_count (void)
-{
-#ifdef PLATFORM_ANDROID
-       /* Android tries really hard to save power by powering off CPUs on SMP phones which
-        * means the normal way to query cpu count returns a wrong value with userspace API.
-        * Instead we use /sys entries to query the actual hardware CPU count.
-        */
-       int count = 0;
-       char buffer[8] = {'\0'};
-       int present = open ("/sys/devices/system/cpu/present", O_RDONLY);
-       /* Format of the /sys entry is a cpulist of indexes which in the case
-        * of present is always of the form "0-(n-1)" when there is more than
-        * 1 core, n being the number of CPU cores in the system. Otherwise
-        * the value is simply 0
-        */
-       if (present != -1 && read (present, (char*)buffer, sizeof (buffer)) > 3)
-               count = strtol (((char*)buffer) + 2, NULL, 10);
-       if (present != -1)
-               close (present);
-       if (count > 0)
-               return count + 1;
-#endif
-
-#if defined(HOST_ARM) || defined (HOST_ARM64)
-
-       /* ARM platforms tries really hard to save power by powering off CPUs on SMP phones which
-        * means the normal way to query cpu count returns a wrong value with userspace API. */
-
-#ifdef _SC_NPROCESSORS_CONF
-       {
-               int count = sysconf (_SC_NPROCESSORS_CONF);
-               if (count > 0)
-                       return count;
-       }
-#endif
-
-#else
-
-#ifdef HAVE_SCHED_GETAFFINITY
-       {
-               cpu_set_t set;
-               if (sched_getaffinity (getpid (), sizeof (set), &set) == 0)
-                       return CPU_COUNT (&set);
-       }
-#endif
-#ifdef _SC_NPROCESSORS_ONLN
-       {
-               int count = sysconf (_SC_NPROCESSORS_ONLN);
-               if (count > 0)
-                       return count;
-       }
-#endif
-
-#endif /* defined(HOST_ARM) || defined (HOST_ARM64) */
-
-#ifdef USE_SYSCTL
-       {
-               int count;
-               int mib [2];
-               size_t len = sizeof (int);
-               mib [0] = CTL_HW;
-               mib [1] = HW_NCPU;
-               if (sysctl (mib, 2, &count, &len, NULL, 0) == 0)
-                       return count;
-       }
-#endif
-#ifdef HOST_WIN32
-       {
-               SYSTEM_INFO info;
-               GetSystemInfo (&info);
-               return info.dwNumberOfProcessors;
-       }
-#endif
-
-       static gboolean warned;
-
-       if (!warned) {
-               g_warning ("Don't know how to determine CPU count on this platform; assuming 1");
-               warned = TRUE;
-       }
-
-       return 1;
+       mono_profiler_printf ("Mono log profiler version %d.%d (format: %d)", LOG_VERSION_MAJOR, LOG_VERSION_MINOR, LOG_DATA_VERSION);
+       mono_profiler_printf ("Usage: mono --profile=log[:OPTION1[,OPTION2...]] program.exe\n");
+       mono_profiler_printf ("Options:");
+       mono_profiler_printf ("\thelp                 show this usage info");
+       mono_profiler_printf ("\t[no]'EVENT'          enable/disable an individual profiling event");
+       mono_profiler_printf ("\t                     valid EVENT values:");
+
+       for (int i = 0; i < G_N_ELEMENTS (event_list); i++)
+               mono_profiler_printf ("\t                         %s", event_list [i].event_name);
+
+       mono_profiler_printf ("\t[no]alloc            enable/disable recording allocation info");
+       mono_profiler_printf ("\t[no]legacy           enable/disable pre mono 5.4 default profiler events");
+       mono_profiler_printf ("\tsample[-real][=FREQ] enable/disable statistical sampling of threads");
+       mono_profiler_printf ("\t                     FREQ in Hz, 100 by default");
+       mono_profiler_printf ("\t                     the -real variant uses wall clock time instead of process time");
+       mono_profiler_printf ("\theapshot[=MODE]      record heapshot info (by default at each major collection)");
+       mono_profiler_printf ("\t                     MODE: every XXms milliseconds, every YYgc collections, ondemand");
+       mono_profiler_printf ("\theapshot-on-shutdown do a heapshot on runtime shutdown");
+       mono_profiler_printf ("\t                     this option is independent of the above option");
+       mono_profiler_printf ("\tcalls                enable recording enter/leave method events (very heavy)");
+       mono_profiler_printf ("\tcoverage             enable collection of code coverage data");
+       mono_profiler_printf ("\tcovfilter=ASSEMBLY   add ASSEMBLY to the code coverage filters");
+       mono_profiler_printf ("\t                     prefix a + to include the assembly or a - to exclude it");
+       mono_profiler_printf ("\t                     e.g. covfilter=-mscorlib");
+       mono_profiler_printf ("\tcovfilter-file=FILE  use FILE to generate the list of assemblies to be filtered");
+       mono_profiler_printf ("\tmaxframes=NUM        collect up to NUM stack frames");
+       mono_profiler_printf ("\tcalldepth=NUM        ignore method events for call chain depth bigger than NUM");
+       mono_profiler_printf ("\toutput=FILENAME      write the data to file FILENAME (the file is always overwritten)");
+       mono_profiler_printf ("\toutput=+FILENAME     write the data to file FILENAME.pid (the file is always overwritten)");
+       mono_profiler_printf ("\toutput=|PROGRAM      write the data to the stdin of PROGRAM");
+       mono_profiler_printf ("\t                     %%t is substituted with date and time, %%p with the pid");
+       mono_profiler_printf ("\treport               create a report instead of writing the raw data to a file");
+       mono_profiler_printf ("\tzip                  compress the output data");
+       mono_profiler_printf ("\tport=PORTNUM         use PORTNUM for the listening command server");
 }
index 9793f8392d851cfa69a0e0048ae5f0605919855a..847ee26184cb93824366892581ba1eee5685eeb6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * mono-profiler-log.c: mono log profiler
+ * log.c: mono log profiler
  *
  * Authors:
  *   Paolo Molaro (lupus@ximian.com)
 
 #include <config.h>
 #include <mono/metadata/assembly.h>
+#include <mono/metadata/class-internals.h>
 #include <mono/metadata/debug-helpers.h>
-#include "../metadata/metadata-internals.h"
+#include <mono/metadata/loader.h>
+#include <mono/metadata/metadata-internals.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/mono-gc.h>
 #include <mono/metadata/mono-perfcounters.h>
+#include <mono/metadata/tabledefs.h>
 #include <mono/utils/atomic.h>
 #include <mono/utils/hazard-pointer.h>
 #include <mono/utils/lock-free-alloc.h>
 #include <mono/utils/lock-free-queue.h>
 #include <mono/utils/mono-conc-hashtable.h>
+#include <mono/utils/mono-coop-mutex.h>
 #include <mono/utils/mono-counters.h>
+#include <mono/utils/mono-logger-internals.h>
 #include <mono/utils/mono-linked-list-set.h>
 #include <mono/utils/mono-membar.h>
 #include <mono/utils/mono-mmap.h>
 #include <zlib.h>
 #endif
 
-#define BUFFER_SIZE (4096 * 16)
-
-/* Worst-case size in bytes of a 64-bit value encoded with LEB128. */
-#define LEB128_SIZE 10
-
-/* Size of a value encoded as a single byte. */
-#undef BYTE_SIZE // mach/i386/vm_param.h on OS X defines this to 8, but it isn't used for anything.
-#define BYTE_SIZE 1
-
-/* Size in bytes of the event prefix (ID + time). */
-#define EVENT_SIZE (BYTE_SIZE + LEB128_SIZE)
-
-static volatile gint32 runtime_inited;
-static volatile gint32 in_shutdown;
-
-static ProfilerConfig config;
-static int nocalls = 0;
-static int notraces = 0;
-static int use_zip = 0;
-static int do_report = 0;
-static int do_heap_shot = 0;
-static int max_call_depth = 0;
-static int command_port = 0;
-static int heapshot_requested = 0;
-static int do_mono_sample = 0;
-static int do_debug = 0;
-static int do_coverage = 0;
-static gboolean no_counters = FALSE;
-static gboolean debug_coverage = FALSE;
-static int max_allocated_sample_hits;
-
-#define ENABLED(EVT) (config.effective_mask & (EVT))
-
 // Statistics for internal profiler data structures.
 static gint32 sample_allocations_ctr,
               buffer_allocations_ctr;
@@ -141,293 +113,6 @@ static gint32 sync_points_ctr,
               coverage_classes_ctr,
               coverage_assemblies_ctr;
 
-static MonoLinkedListSet profiler_thread_list;
-
-/*
- * file format:
- * [header] [buffer]*
- *
- * The file is composed by a header followed by 0 or more buffers.
- * Each buffer contains events that happened on a thread: for a given thread
- * buffers that appear later in the file are guaranteed to contain events
- * that happened later in time. Buffers from separate threads could be interleaved,
- * though.
- * Buffers are not required to be aligned.
- *
- * header format:
- * [id: 4 bytes] constant value: LOG_HEADER_ID
- * [major: 1 byte] [minor: 1 byte] major and minor version of the log profiler
- * [format: 1 byte] version of the data format for the rest of the file
- * [ptrsize: 1 byte] size in bytes of a pointer in the profiled program
- * [startup time: 8 bytes] time in milliseconds since the unix epoch when the program started
- * [timer overhead: 4 bytes] approximate overhead in nanoseconds of the timer
- * [flags: 4 bytes] file format flags, should be 0 for now
- * [pid: 4 bytes] pid of the profiled process
- * [port: 2 bytes] tcp port for server if != 0
- * [args size: 4 bytes] size of args
- * [args: string] arguments passed to the profiler
- * [arch size: 4 bytes] size of arch
- * [arch: string] architecture the profiler is running on
- * [os size: 4 bytes] size of os
- * [os: string] operating system the profiler is running on
- *
- * The multiple byte integers are in little-endian format.
- *
- * buffer format:
- * [buffer header] [event]*
- * Buffers have a fixed-size header followed by 0 or more bytes of event data.
- * Timing information and other values in the event data are usually stored
- * as uleb128 or sleb128 integers. To save space, as noted for each item below,
- * some data is represented as a difference between the actual value and
- * either the last value of the same type (like for timing information) or
- * as the difference from a value stored in a buffer header.
- *
- * For timing information the data is stored as uleb128, since timing
- * increases in a monotonic way in each thread: the value is the number of
- * nanoseconds to add to the last seen timing data in a buffer. The first value
- * in a buffer will be calculated from the time_base field in the buffer head.
- *
- * Object or heap sizes are stored as uleb128.
- * Pointer differences are stored as sleb128, instead.
- *
- * If an unexpected value is found, the rest of the buffer should be ignored,
- * as generally the later values need the former to be interpreted correctly.
- *
- * buffer header format:
- * [bufid: 4 bytes] constant value: BUF_ID
- * [len: 4 bytes] size of the data following the buffer header
- * [time_base: 8 bytes] time base in nanoseconds since an unspecified epoch
- * [ptr_base: 8 bytes] base value for pointers
- * [obj_base: 8 bytes] base value for object addresses
- * [thread id: 8 bytes] system-specific thread ID (pthread_t for example)
- * [method_base: 8 bytes] base value for MonoMethod pointers
- *
- * event format:
- * [extended info: upper 4 bits] [type: lower 4 bits]
- * [time diff: uleb128] nanoseconds since last timing
- * [data]*
- * The data that follows depends on type and the extended info.
- * Type is one of the enum values in mono-profiler-log.h: TYPE_ALLOC, TYPE_GC,
- * TYPE_METADATA, TYPE_METHOD, TYPE_EXCEPTION, TYPE_MONITOR, TYPE_HEAP.
- * The extended info bits are interpreted based on type, see
- * each individual event description below.
- * strings are represented as a 0-terminated utf8 sequence.
- *
- * backtrace format:
- * [num: uleb128] number of frames following
- * [frame: sleb128]* mum MonoMethod* as a pointer difference from the last such
- * pointer or the buffer method_base
- *
- * type alloc format:
- * type: TYPE_ALLOC
- * exinfo: zero or TYPE_ALLOC_BT
- * [ptr: sleb128] class as a byte difference from ptr_base
- * [obj: sleb128] object address as a byte difference from obj_base
- * [size: uleb128] size of the object in the heap
- * If exinfo == TYPE_ALLOC_BT, a backtrace follows.
- *
- * type GC format:
- * type: TYPE_GC
- * exinfo: one of TYPE_GC_EVENT, TYPE_GC_RESIZE, TYPE_GC_MOVE, TYPE_GC_HANDLE_CREATED[_BT],
- * TYPE_GC_HANDLE_DESTROYED[_BT], TYPE_GC_FINALIZE_START, TYPE_GC_FINALIZE_END,
- * TYPE_GC_FINALIZE_OBJECT_START, TYPE_GC_FINALIZE_OBJECT_END
- * if exinfo == TYPE_GC_RESIZE
- *     [heap_size: uleb128] new heap size
- * if exinfo == TYPE_GC_EVENT
- *     [event type: byte] GC event (MONO_GC_EVENT_* from profiler.h)
- *     [generation: byte] GC generation event refers to
- * if exinfo == TYPE_GC_MOVE
- *     [num_objects: uleb128] number of object moves that follow
- *     [objaddr: sleb128]+ num_objects object pointer differences from obj_base
- *     num is always an even number: the even items are the old
- *     addresses, the odd numbers are the respective new object addresses
- * if exinfo == TYPE_GC_HANDLE_CREATED[_BT]
- *     [handle_type: uleb128] MonoGCHandleType enum value
- *     upper bits reserved as flags
- *     [handle: uleb128] GC handle value
- *     [objaddr: sleb128] object pointer differences from obj_base
- *     If exinfo == TYPE_GC_HANDLE_CREATED_BT, a backtrace follows.
- * if exinfo == TYPE_GC_HANDLE_DESTROYED[_BT]
- *     [handle_type: uleb128] MonoGCHandleType enum value
- *     upper bits reserved as flags
- *     [handle: uleb128] GC handle value
- *     If exinfo == TYPE_GC_HANDLE_DESTROYED_BT, a backtrace follows.
- * if exinfo == TYPE_GC_FINALIZE_OBJECT_{START,END}
- *     [object: sleb128] the object as a difference from obj_base
- *
- * type metadata format:
- * type: TYPE_METADATA
- * exinfo: one of: TYPE_END_LOAD, TYPE_END_UNLOAD (optional for TYPE_THREAD and TYPE_DOMAIN,
- * doesn't occur for TYPE_CLASS)
- * [mtype: byte] metadata type, one of: TYPE_CLASS, TYPE_IMAGE, TYPE_ASSEMBLY, TYPE_DOMAIN,
- * TYPE_THREAD, TYPE_CONTEXT
- * [pointer: sleb128] pointer of the metadata type depending on mtype
- * if mtype == TYPE_CLASS
- *     [image: sleb128] MonoImage* as a pointer difference from ptr_base
- *     [name: string] full class name
- * if mtype == TYPE_IMAGE
- *     [name: string] image file name
- * if mtype == TYPE_ASSEMBLY
- *     [image: sleb128] MonoImage* as a pointer difference from ptr_base
- *     [name: string] assembly name
- * if mtype == TYPE_DOMAIN && exinfo == 0
- *     [name: string] domain friendly name
- * if mtype == TYPE_CONTEXT
- *     [domain: sleb128] domain id as pointer
- * if mtype == TYPE_THREAD && exinfo == 0
- *     [name: string] thread name
- *
- * type method format:
- * type: TYPE_METHOD
- * exinfo: one of: TYPE_LEAVE, TYPE_ENTER, TYPE_EXC_LEAVE, TYPE_JIT
- * [method: sleb128] MonoMethod* as a pointer difference from the last such
- * pointer or the buffer method_base
- * if exinfo == TYPE_JIT
- *     [code address: sleb128] pointer to the native code as a diff from ptr_base
- *     [code size: uleb128] size of the generated code
- *     [name: string] full method name
- *
- * type exception format:
- * type: TYPE_EXCEPTION
- * exinfo: zero, TYPE_CLAUSE, or TYPE_THROW_BT
- * if exinfo == TYPE_CLAUSE
- *     [clause type: byte] MonoExceptionEnum enum value
- *     [clause index: uleb128] index of the current clause
- *     [method: sleb128] MonoMethod* as a pointer difference from the last such
- *     pointer or the buffer method_base
- *     [object: sleb128] the exception object as a difference from obj_base
- * else
- *     [object: sleb128] the exception object as a difference from obj_base
- *     If exinfo == TYPE_THROW_BT, a backtrace follows.
- *
- * type runtime format:
- * type: TYPE_RUNTIME
- * exinfo: one of: TYPE_JITHELPER
- * if exinfo == TYPE_JITHELPER
- *     [type: byte] MonoProfilerCodeBufferType enum value
- *     [buffer address: sleb128] pointer to the native code as a diff from ptr_base
- *     [buffer size: uleb128] size of the generated code
- *     if type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE
- *             [name: string] buffer description name
- *
- * type monitor format:
- * type: TYPE_MONITOR
- * exinfo: zero or TYPE_MONITOR_BT
- * [type: byte] MonoProfilerMonitorEvent enum value
- * [object: sleb128] the lock object as a difference from obj_base
- * If exinfo == TYPE_MONITOR_BT, a backtrace follows.
- *
- * type heap format
- * type: TYPE_HEAP
- * exinfo: one of TYPE_HEAP_START, TYPE_HEAP_END, TYPE_HEAP_OBJECT, TYPE_HEAP_ROOT
- * if exinfo == TYPE_HEAP_OBJECT
- *     [object: sleb128] the object as a difference from obj_base
- *     [class: sleb128] the object MonoClass* as a difference from ptr_base
- *     [size: uleb128] size of the object on the heap
- *     [num_refs: uleb128] number of object references
- *     each referenced objref is preceded by a uleb128 encoded offset: the
- *     first offset is from the object address and each next offset is relative
- *     to the previous one
- *     [objrefs: sleb128]+ object referenced as a difference from obj_base
- *     The same object can appear multiple times, but only the first time
- *     with size != 0: in the other cases this data will only be used to
- *     provide additional referenced objects.
- * if exinfo == TYPE_HEAP_ROOT
- *     [num_roots: uleb128] number of root references
- *     [num_gc: uleb128] number of major gcs
- *     [object: sleb128] the object as a difference from obj_base
- *     [root_type: byte] the root_type: MonoProfileGCRootType (profiler.h)
- *     [extra_info: uleb128] the extra_info value
- *     object, root_type and extra_info are repeated num_roots times
- *
- * type sample format
- * type: TYPE_SAMPLE
- * exinfo: one of TYPE_SAMPLE_HIT, TYPE_SAMPLE_USYM, TYPE_SAMPLE_UBIN, TYPE_SAMPLE_COUNTERS_DESC, TYPE_SAMPLE_COUNTERS
- * if exinfo == TYPE_SAMPLE_HIT
- *     [thread: sleb128] thread id as difference from ptr_base
- *     [count: uleb128] number of following instruction addresses
- *     [ip: sleb128]* instruction pointer as difference from ptr_base
- *     [mbt_count: uleb128] number of managed backtrace frames
- *     [method: sleb128]* MonoMethod* as a pointer difference from the last such
- *     pointer or the buffer method_base (the first such method can be also indentified by ip, but this is not neccessarily true)
- * if exinfo == TYPE_SAMPLE_USYM
- *     [address: sleb128] symbol address as a difference from ptr_base
- *     [size: uleb128] symbol size (may be 0 if unknown)
- *     [name: string] symbol name
- * if exinfo == TYPE_SAMPLE_UBIN
- *     [address: sleb128] address where binary has been loaded as a difference from ptr_base
- *     [offset: uleb128] file offset of mapping (the same file can be mapped multiple times)
- *     [size: uleb128] memory size
- *     [name: string] binary name
- * if exinfo == TYPE_SAMPLE_COUNTERS_DESC
- *     [len: uleb128] number of counters
- *     for i = 0 to len
- *             [section: uleb128] section of counter
- *             if section == MONO_COUNTER_PERFCOUNTERS:
- *                     [section_name: string] section name of counter
- *             [name: string] name of counter
- *             [type: byte] type of counter
- *             [unit: byte] unit of counter
- *             [variance: byte] variance of counter
- *             [index: uleb128] unique index of counter
- * if exinfo == TYPE_SAMPLE_COUNTERS
- *     while true:
- *             [index: uleb128] unique index of counter
- *             if index == 0:
- *                     break
- *             [type: byte] type of counter value
- *             if type == string:
- *                     if value == null:
- *                             [0: byte] 0 -> value is null
- *                     else:
- *                             [1: byte] 1 -> value is not null
- *                             [value: string] counter value
- *             else:
- *                     [value: uleb128/sleb128/double] counter value, can be sleb128, uleb128 or double (determined by using type)
- *
- * type coverage format
- * type: TYPE_COVERAGE
- * exinfo: one of TYPE_COVERAGE_METHOD, TYPE_COVERAGE_STATEMENT, TYPE_COVERAGE_ASSEMBLY, TYPE_COVERAGE_CLASS
- * if exinfo == TYPE_COVERAGE_METHOD
- *  [assembly: string] name of assembly
- *  [class: string] name of the class
- *  [name: string] name of the method
- *  [signature: string] the signature of the method
- *  [filename: string] the file path of the file that contains this method
- *  [token: uleb128] the method token
- *  [method_id: uleb128] an ID for this data to associate with the buffers of TYPE_COVERAGE_STATEMENTS
- *  [len: uleb128] the number of TYPE_COVERAGE_BUFFERS associated with this method
- * if exinfo == TYPE_COVERAGE_STATEMENTS
- *  [method_id: uleb128] an the TYPE_COVERAGE_METHOD buffer to associate this with
- *  [offset: uleb128] the il offset relative to the previous offset
- *  [counter: uleb128] the counter for this instruction
- *  [line: uleb128] the line of filename containing this instruction
- *  [column: uleb128] the column containing this instruction
- * if exinfo == TYPE_COVERAGE_ASSEMBLY
- *  [name: string] assembly name
- *  [guid: string] assembly GUID
- *  [filename: string] assembly filename
- *  [number_of_methods: uleb128] the number of methods in this assembly
- *  [fully_covered: uleb128] the number of fully covered methods
- *  [partially_covered: uleb128] the number of partially covered methods
- *    currently partially_covered will always be 0, and fully_covered is the
- *    number of methods that are fully and partially covered.
- * if exinfo == TYPE_COVERAGE_CLASS
- *  [name: string] assembly name
- *  [class: string] class name
- *  [number_of_methods: uleb128] the number of methods in this class
- *  [fully_covered: uleb128] the number of fully covered methods
- *  [partially_covered: uleb128] the number of partially covered methods
- *    currently partially_covered will always be 0, and fully_covered is the
- *    number of methods that are fully and partially covered.
- *
- * type meta format:
- * type: TYPE_META
- * exinfo: one of: TYPE_SYNC_POINT
- * if exinfo == TYPE_SYNC_POINT
- *     [type: byte] MonoProfilerSyncPointType enum value
- */
-
 // Pending data to be written to the log, for a single thread.
 // Threads periodically flush their own LogBuffers by calling safe_send
 typedef struct _LogBuffer LogBuffer;
@@ -459,9 +144,6 @@ struct _LogBuffer {
 typedef struct {
        MonoLinkedListSetNode node;
 
-       // Convenience pointer to the profiler structure.
-       MonoProfiler *profiler;
-
        // Was this thread added to the LLS?
        gboolean attached;
 
@@ -531,65 +213,9 @@ process_id (void)
 #endif
 }
 
-#ifdef __APPLE__
-static mach_timebase_info_data_t timebase_info;
-#elif defined (HOST_WIN32)
-static LARGE_INTEGER pcounter_freq;
-#endif
-
-#define TICKS_PER_SEC 1000000000LL
-
-static uint64_t
-current_time (void)
-{
-#ifdef __APPLE__
-       uint64_t time = mach_absolute_time ();
-
-       time *= timebase_info.numer;
-       time /= timebase_info.denom;
-
-       return time;
-#elif defined (HOST_WIN32)
-       LARGE_INTEGER value;
-
-       QueryPerformanceCounter (&value);
-
-       return value.QuadPart * TICKS_PER_SEC / pcounter_freq.QuadPart;
-#elif defined (CLOCK_MONOTONIC)
-       struct timespec tspec;
-
-       clock_gettime (CLOCK_MONOTONIC, &tspec);
-
-       return ((uint64_t) tspec.tv_sec * TICKS_PER_SEC + tspec.tv_nsec);
-#else
-       struct timeval tv;
-
-       gettimeofday (&tv, NULL);
-
-       return ((uint64_t) tv.tv_sec * TICKS_PER_SEC + tv.tv_usec * 1000);
-#endif
-}
-
-static int timer_overhead;
-
-static void
-init_time (void)
-{
-#ifdef __APPLE__
-       mach_timebase_info (&timebase_info);
-#elif defined (HOST_WIN32)
-       QueryPerformanceFrequency (&pcounter_freq);
-#endif
-
-       uint64_t time_start = current_time ();
-
-       for (int i = 0; i < 256; ++i)
-               current_time ();
-
-       uint64_t time_end = current_time ();
-
-       timer_overhead = (time_end - time_start) / 256;
-}
+#define ENABLED(EVT) (!!(log_config.effective_mask & (EVT)))
+#define ENABLE(EVT) do { log_config.effective_mask |= (EVT); } while (0)
+#define DISABLE(EVT) do { log_config.effective_mask &= ~(EVT); } while (0)
 
 /*
  * These macros should be used when writing an event to a log buffer. They
@@ -636,40 +262,114 @@ struct _BinaryObject {
        char *name;
 };
 
-static MonoProfiler *log_profiler;
+typedef struct MonoCounterAgent {
+       MonoCounter *counter;
+       // MonoCounterAgent specific data :
+       void *value;
+       size_t value_size;
+       guint32 index;
+       gboolean emitted;
+       struct MonoCounterAgent *next;
+} MonoCounterAgent;
+
+typedef struct _PerfCounterAgent PerfCounterAgent;
+struct _PerfCounterAgent {
+       PerfCounterAgent *next;
+       guint32 index;
+       char *category_name;
+       char *name;
+       gint64 value;
+       gboolean emitted;
+       gboolean updated;
+       gboolean deleted;
+};
 
 struct _MonoProfiler {
        MonoProfilerHandle handle;
+
        FILE* file;
 #if defined (HAVE_SYS_ZLIB)
        gzFile gzfile;
 #endif
+
        char *args;
        uint64_t startup_time;
+       int timer_overhead;
+
+#ifdef __APPLE__
+       mach_timebase_info_data_t timebase_info;
+#elif defined (HOST_WIN32)
+       LARGE_INTEGER pcounter_freq;
+#endif
+
        int pipe_output;
        int command_port;
        int server_socket;
        int pipes [2];
+
+       MonoLinkedListSet profiler_thread_list;
+       volatile gint32 buffer_lock_state;
+       volatile gint32 buffer_lock_exclusive_intent;
+
+       volatile gint32 runtime_inited;
+       volatile gint32 in_shutdown;
+
        MonoNativeThreadId helper_thread;
+
        MonoNativeThreadId writer_thread;
-       MonoNativeThreadId dumper_thread;
        volatile gint32 run_writer_thread;
-       MonoLockFreeAllocSizeClass writer_entry_size_class;
-       MonoLockFreeAllocator writer_entry_allocator;
        MonoLockFreeQueue writer_queue;
        MonoSemType writer_queue_sem;
+
+       MonoLockFreeAllocSizeClass writer_entry_size_class;
+       MonoLockFreeAllocator writer_entry_allocator;
+
        MonoConcurrentHashTable *method_table;
        mono_mutex_t method_table_mutex;
+
+       MonoNativeThreadId dumper_thread;
        volatile gint32 run_dumper_thread;
        MonoLockFreeQueue dumper_queue;
        MonoSemType dumper_queue_sem;
+
        MonoLockFreeAllocSizeClass sample_size_class;
        MonoLockFreeAllocator sample_allocator;
        MonoLockFreeQueue sample_reuse_queue;
+
        BinaryObject *binary_objects;
+
+       volatile gint32 heapshot_requested;
+       guint64 gc_count;
+       guint64 last_hs_time;
+       gboolean do_heap_walk;
+
+       mono_mutex_t counters_mutex;
+       MonoCounterAgent *counters;
+       PerfCounterAgent *perfcounters;
+       guint32 counters_index;
+
+       mono_mutex_t coverage_mutex;
+       GPtrArray *coverage_data;
+
        GPtrArray *coverage_filters;
+       MonoConcurrentHashTable *coverage_filtered_classes;
+       MonoConcurrentHashTable *coverage_suppressed_assemblies;
+
+       MonoConcurrentHashTable *coverage_methods;
+       MonoConcurrentHashTable *coverage_assemblies;
+       MonoConcurrentHashTable *coverage_classes;
+
+       MonoConcurrentHashTable *coverage_image_to_methods;
+
+       guint32 coverage_previous_offset;
+       guint32 coverage_method_id;
+
+       MonoCoopMutex api_mutex;
 };
 
+static ProfilerConfig log_config;
+static struct _MonoProfiler log_profiler;
+
 typedef struct {
        MonoLockFreeQueueNode node;
        GPtrArray *methods;
@@ -684,6 +384,58 @@ typedef struct {
        uint64_t time;
 } MethodInfo;
 
+#define TICKS_PER_SEC 1000000000LL
+
+static uint64_t
+current_time (void)
+{
+#ifdef __APPLE__
+       uint64_t time = mach_absolute_time ();
+
+       time *= log_profiler.timebase_info.numer;
+       time /= log_profiler.timebase_info.denom;
+
+       return time;
+#elif defined (HOST_WIN32)
+       LARGE_INTEGER value;
+
+       QueryPerformanceCounter (&value);
+
+       return value.QuadPart * TICKS_PER_SEC / log_profiler.pcounter_freq.QuadPart;
+#elif defined (CLOCK_MONOTONIC)
+       struct timespec tspec;
+
+       clock_gettime (CLOCK_MONOTONIC, &tspec);
+
+       return ((uint64_t) tspec.tv_sec * TICKS_PER_SEC + tspec.tv_nsec);
+#else
+       struct timeval tv;
+
+       gettimeofday (&tv, NULL);
+
+       return ((uint64_t) tv.tv_sec * TICKS_PER_SEC + tv.tv_usec * 1000);
+#endif
+}
+
+static void
+init_time (void)
+{
+#ifdef __APPLE__
+       mach_timebase_info (&log_profiler.timebase_info);
+#elif defined (HOST_WIN32)
+       QueryPerformanceFrequency (&log_profiler.pcounter_freq);
+#endif
+
+       uint64_t time_start = current_time ();
+
+       for (int i = 0; i < 256; ++i)
+               current_time ();
+
+       uint64_t time_end = current_time ();
+
+       log_profiler.timer_overhead = (time_end - time_start) / 256;
+}
+
 static char*
 pstrdup (const char *s)
 {
@@ -693,6 +445,18 @@ pstrdup (const char *s)
        return p;
 }
 
+#define BUFFER_SIZE (4096 * 16)
+
+/* Worst-case size in bytes of a 64-bit value encoded with LEB128. */
+#define LEB128_SIZE 10
+
+/* Size of a value encoded as a single byte. */
+#undef BYTE_SIZE // mach/i386/vm_param.h on OS X defines this to 8, but it isn't used for anything.
+#define BYTE_SIZE 1
+
+/* Size in bytes of the event prefix (ID + time). */
+#define EVENT_SIZE (BYTE_SIZE + LEB128_SIZE)
+
 static void *
 alloc_buffer (int size)
 {
@@ -744,7 +508,7 @@ clear_hazard_pointers (MonoThreadHazardPointers *hp)
 }
 
 static MonoProfilerThread *
-init_thread (MonoProfiler *prof, gboolean add_to_lls)
+init_thread (gboolean add_to_lls)
 {
        MonoProfilerThread *thread = PROF_TLS_GET ();
 
@@ -764,7 +528,6 @@ init_thread (MonoProfiler *prof, gboolean add_to_lls)
 
        thread = g_malloc (sizeof (MonoProfilerThread));
        thread->node.key = thread_id ();
-       thread->profiler = prof;
        thread->attached = add_to_lls;
        thread->call_depth = 0;
        thread->busy = 0;
@@ -780,7 +543,7 @@ init_thread (MonoProfiler *prof, gboolean add_to_lls)
         */
        if (add_to_lls) {
                MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
-               g_assert (mono_lls_insert (&profiler_thread_list, hp, &thread->node) && "Why can't we insert the thread in the LLS?");
+               g_assert (mono_lls_insert (&log_profiler.profiler_thread_list, hp, &thread->node) && "Why can't we insert the thread in the LLS?");
                clear_hazard_pointers (hp);
        }
 
@@ -802,7 +565,7 @@ deinit_thread (MonoProfilerThread *thread)
 static MonoProfilerThread *
 get_thread (void)
 {
-       return init_thread (log_profiler, TRUE);
+       return init_thread (TRUE);
 }
 
 // Only valid if init_thread () was called with add_to_lls = FALSE.
@@ -852,8 +615,6 @@ ensure_logbuf_unsafe (MonoProfilerThread *thread, int bytes)
  *
  * The lock does not support recursion.
  */
-static volatile gint32 buffer_lock_state;
-static volatile gint32 buffer_lock_exclusive_intent;
 
 static void
 buffer_lock (void)
@@ -868,7 +629,7 @@ buffer_lock (void)
         * the exclusive lock in the gc_event () callback when the world
         * is about to stop.
         */
-       if (InterlockedRead (&buffer_lock_state) != get_thread ()->small_id << 16) {
+       if (InterlockedRead (&log_profiler.buffer_lock_state) != get_thread ()->small_id << 16) {
                MONO_ENTER_GC_SAFE;
 
                gint32 old, new_;
@@ -876,10 +637,10 @@ buffer_lock (void)
                do {
                restart:
                        // Hold off if a thread wants to take the exclusive lock.
-                       while (InterlockedRead (&buffer_lock_exclusive_intent))
+                       while (InterlockedRead (&log_profiler.buffer_lock_exclusive_intent))
                                mono_thread_info_yield ();
 
-                       old = InterlockedRead (&buffer_lock_state);
+                       old = InterlockedRead (&log_profiler.buffer_lock_state);
 
                        // Is a thread holding the exclusive lock?
                        if (old >> 16) {
@@ -888,7 +649,7 @@ buffer_lock (void)
                        }
 
                        new_ = old + 1;
-               } while (InterlockedCompareExchange (&buffer_lock_state, new_, old) != old);
+               } while (InterlockedCompareExchange (&log_profiler.buffer_lock_state, new_, old) != old);
 
                MONO_EXIT_GC_SAFE;
        }
@@ -901,7 +662,7 @@ buffer_unlock (void)
 {
        mono_memory_barrier ();
 
-       gint32 state = InterlockedRead (&buffer_lock_state);
+       gint32 state = InterlockedRead (&log_profiler.buffer_lock_state);
 
        // See the comment in buffer_lock ().
        if (state == PROF_TLS_GET ()->small_id << 16)
@@ -910,7 +671,7 @@ buffer_unlock (void)
        g_assert (state && "Why are we decrementing a zero reader count?");
        g_assert (!(state >> 16) && "Why is the exclusive lock held?");
 
-       InterlockedDecrement (&buffer_lock_state);
+       InterlockedDecrement (&log_profiler.buffer_lock_state);
 }
 
 static void
@@ -918,13 +679,13 @@ buffer_lock_excl (void)
 {
        gint32 new_ = get_thread ()->small_id << 16;
 
-       g_assert (InterlockedRead (&buffer_lock_state) != new_ && "Why are we taking the exclusive lock twice?");
+       g_assert (InterlockedRead (&log_profiler.buffer_lock_state) != new_ && "Why are we taking the exclusive lock twice?");
 
-       InterlockedIncrement (&buffer_lock_exclusive_intent);
+       InterlockedIncrement (&log_profiler.buffer_lock_exclusive_intent);
 
        MONO_ENTER_GC_SAFE;
 
-       while (InterlockedCompareExchange (&buffer_lock_state, new_, 0))
+       while (InterlockedCompareExchange (&log_profiler.buffer_lock_state, new_, 0))
                mono_thread_info_yield ();
 
        MONO_EXIT_GC_SAFE;
@@ -937,15 +698,15 @@ buffer_unlock_excl (void)
 {
        mono_memory_barrier ();
 
-       gint32 state = InterlockedRead (&buffer_lock_state);
+       gint32 state = InterlockedRead (&log_profiler.buffer_lock_state);
        gint32 excl = state >> 16;
 
        g_assert (excl && "Why is the exclusive lock not held?");
        g_assert (excl == PROF_TLS_GET ()->small_id && "Why does another thread hold the exclusive lock?");
        g_assert (!(state & 0xFFFF) && "Why are there readers when the exclusive lock is held?");
 
-       InterlockedWrite (&buffer_lock_state, 0);
-       InterlockedDecrement (&buffer_lock_exclusive_intent);
+       InterlockedWrite (&log_profiler.buffer_lock_state, 0);
+       InterlockedDecrement (&log_profiler.buffer_lock_exclusive_intent);
 }
 
 static void
@@ -1087,7 +848,7 @@ register_method_local (MonoMethod *method, MonoJitInfo *ji)
 {
        MonoProfilerThread *thread = get_thread ();
 
-       if (!mono_conc_hashtable_lookup (thread->profiler->method_table, method)) {
+       if (!mono_conc_hashtable_lookup (log_profiler.method_table, method)) {
                MethodInfo *info = (MethodInfo *) g_malloc (sizeof (MethodInfo));
 
                info->method = method;
@@ -1190,9 +951,9 @@ write_header_string (char *p, const char *str)
 }
 
 static void
-dump_header (MonoProfiler *profiler)
+dump_header (void)
 {
-       const char *args = profiler->args;
+       const char *args = log_profiler.args;
        const char *arch = mono_config_get_cpu ();
        const char *os = mono_config_get_os ();
 
@@ -1219,22 +980,22 @@ dump_header (MonoProfiler *profiler)
        *p++ = LOG_DATA_VERSION;
        *p++ = sizeof (void *);
        p = write_int64 (p, ((uint64_t) time (NULL)) * 1000);
-       p = write_int32 (p, timer_overhead);
+       p = write_int32 (p, log_profiler.timer_overhead);
        p = write_int32 (p, 0); /* flags */
        p = write_int32 (p, process_id ());
-       p = write_int16 (p, profiler->command_port);
+       p = write_int16 (p, log_profiler.command_port);
        p = write_header_string (p, args);
        p = write_header_string (p, arch);
        p = write_header_string (p, os);
 
 #if defined (HAVE_SYS_ZLIB)
-       if (profiler->gzfile) {
-               gzwrite (profiler->gzfile, hbuf, p - hbuf);
+       if (log_profiler.gzfile) {
+               gzwrite (log_profiler.gzfile, hbuf, p - hbuf);
        } else
 #endif
        {
-               fwrite (hbuf, p - hbuf, 1, profiler->file);
-               fflush (profiler->file);
+               fwrite (hbuf, p - hbuf, 1, log_profiler.file);
+               fflush (log_profiler.file);
        }
 
        g_free (hbuf);
@@ -1249,14 +1010,14 @@ dump_header (MonoProfiler *profiler)
 static void
 send_buffer (MonoProfilerThread *thread)
 {
-       WriterQueueEntry *entry = mono_lock_free_alloc (&thread->profiler->writer_entry_allocator);
+       WriterQueueEntry *entry = mono_lock_free_alloc (&log_profiler.writer_entry_allocator);
        entry->methods = thread->methods;
        entry->buffer = thread->buffer;
 
        mono_lock_free_queue_node_init (&entry->node, FALSE);
 
-       mono_lock_free_queue_enqueue (&thread->profiler->writer_queue, &entry->node);
-       mono_os_sem_post (&thread->profiler->writer_queue_sem);
+       mono_lock_free_queue_enqueue (&log_profiler.writer_queue, &entry->node);
+       mono_os_sem_post (&log_profiler.writer_queue_sem);
 }
 
 static void
@@ -1273,17 +1034,15 @@ free_thread (gpointer p)
 
                InterlockedIncrement (&thread_ends_ctr);
 
-               if (ENABLED (PROFLOG_THREAD_EVENTS)) {
-                       LogBuffer *buf = ensure_logbuf_unsafe (thread,
-                               EVENT_SIZE /* event */ +
-                               BYTE_SIZE /* type */ +
-                               LEB128_SIZE /* tid */
-                       );
+               LogBuffer *buf = ensure_logbuf_unsafe (thread,
+                       EVENT_SIZE /* event */ +
+                       BYTE_SIZE /* type */ +
+                       LEB128_SIZE /* tid */
+               );
 
-                       emit_event (buf, TYPE_END_UNLOAD | TYPE_METADATA);
-                       emit_byte (buf, TYPE_THREAD);
-                       emit_ptr (buf, (void *) thread->node.key);
-               }
+               emit_event (buf, TYPE_END_UNLOAD | TYPE_METADATA);
+               emit_byte (buf, TYPE_THREAD);
+               emit_ptr (buf, (void *) thread->node.key);
        }
 
        send_buffer (thread);
@@ -1296,20 +1055,20 @@ remove_thread (MonoProfilerThread *thread)
 {
        MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
 
-       if (mono_lls_remove (&profiler_thread_list, hp, &thread->node))
+       if (mono_lls_remove (&log_profiler.profiler_thread_list, hp, &thread->node))
                mono_thread_hazardous_try_free (thread, free_thread);
 
        clear_hazard_pointers (hp);
 }
 
 static void
-dump_buffer (MonoProfiler *profiler, LogBuffer *buf)
+dump_buffer (LogBuffer *buf)
 {
        char hbuf [128];
        char *p = hbuf;
 
        if (buf->next)
-               dump_buffer (profiler, buf->next);
+               dump_buffer (buf->next);
 
        if (buf->cursor - buf->buf) {
                p = write_int32 (p, BUF_ID);
@@ -1321,15 +1080,15 @@ dump_buffer (MonoProfiler *profiler, LogBuffer *buf)
                p = write_int64 (p, buf->method_base);
 
 #if defined (HAVE_SYS_ZLIB)
-               if (profiler->gzfile) {
-                       gzwrite (profiler->gzfile, hbuf, p - hbuf);
-                       gzwrite (profiler->gzfile, buf->buf, buf->cursor - buf->buf);
+               if (log_profiler.gzfile) {
+                       gzwrite (log_profiler.gzfile, hbuf, p - hbuf);
+                       gzwrite (log_profiler.gzfile, buf->buf, buf->cursor - buf->buf);
                } else
 #endif
                {
-                       fwrite (hbuf, p - hbuf, 1, profiler->file);
-                       fwrite (buf->buf, buf->cursor - buf->buf, 1, profiler->file);
-                       fflush (profiler->file);
+                       fwrite (hbuf, p - hbuf, 1, log_profiler.file);
+                       fwrite (buf->buf, buf->cursor - buf->buf, 1, log_profiler.file);
+                       fflush (log_profiler.file);
                }
        }
 
@@ -1337,12 +1096,12 @@ dump_buffer (MonoProfiler *profiler, LogBuffer *buf)
 }
 
 static void
-dump_buffer_threadless (MonoProfiler *profiler, LogBuffer *buf)
+dump_buffer_threadless (LogBuffer *buf)
 {
        for (LogBuffer *iter = buf; iter; iter = iter->next)
                iter->thread_id = 0;
 
-       dump_buffer (profiler, buf);
+       dump_buffer (buf);
 }
 
 // Only valid if init_thread () was called with add_to_lls = FALSE.
@@ -1365,9 +1124,9 @@ send_log_unsafe (gboolean if_needed)
 static void
 sync_point_flush (void)
 {
-       g_assert (InterlockedRead (&buffer_lock_state) == PROF_TLS_GET ()->small_id << 16 && "Why don't we hold the exclusive lock?");
+       g_assert (InterlockedRead (&log_profiler.buffer_lock_state) == PROF_TLS_GET ()->small_id << 16 && "Why don't we hold the exclusive lock?");
 
-       MONO_LLS_FOREACH_SAFE (&profiler_thread_list, MonoProfilerThread, thread) {
+       MONO_LLS_FOREACH_SAFE (&log_profiler.profiler_thread_list, MonoProfilerThread, thread) {
                g_assert (thread->attached && "Why is a thread in the LLS not attached?");
 
                send_buffer (thread);
@@ -1379,7 +1138,7 @@ sync_point_flush (void)
 static void
 sync_point_mark (MonoProfilerSyncPointType type)
 {
-       g_assert (InterlockedRead (&buffer_lock_state) == PROF_TLS_GET ()->small_id << 16 && "Why don't we hold the exclusive lock?");
+       g_assert (InterlockedRead (&log_profiler.buffer_lock_state) == PROF_TLS_GET ()->small_id << 16 && "Why don't we hold the exclusive lock?");
 
        ENTER_LOG (&sync_points_ctr, logbuffer,
                EVENT_SIZE /* event */ +
@@ -1435,25 +1194,14 @@ gc_reference (MonoObject *obj, MonoClass *klass, uintptr_t size, uintptr_t num,
                emit_obj (logbuffer, refs [i]);
        }
 
-       EXIT_LOG_EXPLICIT (DO_SEND);
+       EXIT_LOG;
 
        return 0;
 }
 
-static unsigned int hs_mode_ms = 0;
-static unsigned int hs_mode_gc = 0;
-static unsigned int hs_mode_ondemand = 0;
-static unsigned int gc_count = 0;
-static uint64_t last_hs_time = 0;
-static gboolean do_heap_walk = FALSE;
-static gboolean ignore_heap_events;
-
 static void
 gc_roots (MonoProfiler *prof, MonoObject *const *objects, const MonoProfilerGCRootType *root_types, const uintptr_t *extra_info, uint64_t num)
 {
-       if (ignore_heap_events)
-               return;
-
        ENTER_LOG (&heap_roots_ctr, logbuffer,
                EVENT_SIZE /* event */ +
                LEB128_SIZE /* num */ +
@@ -1475,42 +1223,22 @@ gc_roots (MonoProfiler *prof, MonoObject *const *objects, const MonoProfilerGCRo
                emit_value (logbuffer, extra_info [i]);
        }
 
-       EXIT_LOG_EXPLICIT (DO_SEND);
+       EXIT_LOG;
 }
 
 
 static void
 trigger_on_demand_heapshot (void)
 {
-       if (heapshot_requested)
+       if (InterlockedRead (&log_profiler.heapshot_requested))
                mono_gc_collect (mono_gc_max_generation ());
 }
 
-#define ALL_GC_EVENTS_MASK (PROFLOG_GC_MOVES_EVENTS | PROFLOG_GC_ROOT_EVENTS | PROFLOG_GC_EVENTS | PROFLOG_HEAPSHOT_FEATURE)
+#define ALL_GC_EVENTS_MASK (PROFLOG_GC_EVENTS | PROFLOG_GC_MOVE_EVENTS | PROFLOG_GC_ROOT_EVENTS)
 
 static void
 gc_event (MonoProfiler *profiler, MonoProfilerGCEvent ev, uint32_t generation)
 {
-       if (ev == MONO_GC_EVENT_START) {
-               uint64_t now = current_time ();
-
-               if (hs_mode_ms && (now - last_hs_time) / 1000 * 1000 >= hs_mode_ms)
-                       do_heap_walk = TRUE;
-               else if (hs_mode_gc && !(gc_count % hs_mode_gc))
-                       do_heap_walk = TRUE;
-               else if (hs_mode_ondemand)
-                       do_heap_walk = heapshot_requested;
-               else if (!hs_mode_ms && !hs_mode_gc && generation == mono_gc_max_generation ())
-                       do_heap_walk = TRUE;
-
-               //If using heapshot, ignore events for collections we don't care
-               if (ENABLED (PROFLOG_HEAPSHOT_FEATURE)) {
-                       // Ignore events generated during the collection itself (IE GC ROOTS)
-                       ignore_heap_events = !do_heap_walk;
-               }
-       }
-
-
        if (ENABLED (PROFLOG_GC_EVENTS)) {
                ENTER_LOG (&gc_events_ctr, logbuffer,
                        EVENT_SIZE /* event */ +
@@ -1522,21 +1250,50 @@ gc_event (MonoProfiler *profiler, MonoProfilerGCEvent ev, uint32_t generation)
                emit_byte (logbuffer, ev);
                emit_byte (logbuffer, generation);
 
-               EXIT_LOG_EXPLICIT (NO_SEND);
+               EXIT_LOG;
        }
 
        switch (ev) {
-       case MONO_GC_EVENT_START:
-               if (generation == mono_gc_max_generation ())
-                       gc_count++;
-
-               break;
        case MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED:
+               switch (log_config.hs_mode) {
+               case MONO_PROFILER_HEAPSHOT_NONE:
+                       log_profiler.do_heap_walk = FALSE;
+                       break;
+               case MONO_PROFILER_HEAPSHOT_MAJOR:
+                       log_profiler.do_heap_walk = generation == mono_gc_max_generation ();
+                       break;
+               case MONO_PROFILER_HEAPSHOT_ON_DEMAND:
+                       log_profiler.do_heap_walk = InterlockedRead (&log_profiler.heapshot_requested);
+                       break;
+               case MONO_PROFILER_HEAPSHOT_X_GC:
+                       log_profiler.do_heap_walk = !(log_profiler.gc_count % log_config.hs_freq_gc);
+                       break;
+               case MONO_PROFILER_HEAPSHOT_X_MS:
+                       log_profiler.do_heap_walk = (current_time () - log_profiler.last_hs_time) / 1000 * 1000 >= log_config.hs_freq_ms;
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+
+               /*
+                * heapshot_requested is set either because on-demand heapshot is
+                * enabled and a heapshot was triggered, or because we're doing a
+                * shutdown heapshot. In the latter case, we won't check it in the
+                * switch above, so check it here and override any decision we made
+                * above.
+                */
+               if (InterlockedRead (&log_profiler.heapshot_requested))
+                       log_profiler.do_heap_walk = TRUE;
+
+               if (ENABLED (PROFLOG_GC_ROOT_EVENTS) && log_profiler.do_heap_walk)
+                       mono_profiler_set_gc_roots_callback (log_profiler.handle, gc_roots);
+
                /*
                 * Ensure that no thread can be in the middle of writing to
                 * a buffer when the world stops...
                 */
                buffer_lock_excl ();
+
                break;
        case MONO_GC_EVENT_POST_STOP_WORLD:
                /*
@@ -1549,40 +1306,41 @@ gc_event (MonoProfiler *profiler, MonoProfilerGCEvent ev, uint32_t generation)
                if (ENABLED (ALL_GC_EVENTS_MASK))
                        sync_point (SYNC_POINT_WORLD_STOP);
 
-               /*
-                * All heap events are surrounded by a HEAP_START and a HEAP_ENV event.
-                * Right now, that's the case for GC Moves, GC Roots or heapshots.
-                */
-               if (ENABLED (PROFLOG_GC_MOVES_EVENTS | PROFLOG_GC_ROOT_EVENTS) || do_heap_walk) {
+               // Surround heapshots with HEAP_START/HEAP_END events.
+               if (log_profiler.do_heap_walk) {
                        ENTER_LOG (&heap_starts_ctr, logbuffer,
                                EVENT_SIZE /* event */
                        );
 
                        emit_event (logbuffer, TYPE_HEAP_START | TYPE_HEAP);
 
-                       EXIT_LOG_EXPLICIT (DO_SEND);
+                       EXIT_LOG;
                }
 
+               break;
+       case MONO_GC_EVENT_START:
+               if (generation == mono_gc_max_generation ())
+                       log_profiler.gc_count++;
+
                break;
        case MONO_GC_EVENT_PRE_START_WORLD:
-               if (do_heap_shot && do_heap_walk)
+               mono_profiler_set_gc_roots_callback (log_profiler.handle, NULL);
+
+               if (log_profiler.do_heap_walk) {
                        mono_gc_walk_heap (0, gc_reference, NULL);
 
-               /* Matching HEAP_END to the HEAP_START from above */
-               if (ENABLED (PROFLOG_GC_MOVES_EVENTS | PROFLOG_GC_ROOT_EVENTS) || do_heap_walk) {
                        ENTER_LOG (&heap_ends_ctr, logbuffer,
                                EVENT_SIZE /* event */
                        );
 
                        emit_event (logbuffer, TYPE_HEAP_END | TYPE_HEAP);
 
-                       EXIT_LOG_EXPLICIT (DO_SEND);
-               }
+                       EXIT_LOG;
 
-               if (do_heap_shot && do_heap_walk) {
-                       do_heap_walk = FALSE;
-                       heapshot_requested = 0;
-                       last_hs_time = current_time ();
+                       log_profiler.do_heap_walk = FALSE;
+                       log_profiler.last_hs_time = current_time ();
+
+                       InterlockedWrite (&log_profiler.heapshot_requested, 0);
                }
 
                /*
@@ -1593,6 +1351,7 @@ gc_event (MonoProfiler *profiler, MonoProfilerGCEvent ev, uint32_t generation)
                 */
                if (ENABLED (ALL_GC_EVENTS_MASK))
                        sync_point_mark (SYNC_POINT_WORLD_START);
+
                break;
        case MONO_GC_EVENT_POST_START_WORLD_UNLOCKED:
                /*
@@ -1600,6 +1359,7 @@ gc_event (MonoProfiler *profiler, MonoProfilerGCEvent ev, uint32_t generation)
                 * their buffers again.
                 */
                buffer_unlock_excl ();
+
                break;
        default:
                break;
@@ -1617,7 +1377,7 @@ gc_resize (MonoProfiler *profiler, uintptr_t new_size)
        emit_event (logbuffer, TYPE_GC_RESIZE | TYPE_GC);
        emit_value (logbuffer, new_size);
 
-       EXIT_LOG_EXPLICIT (DO_SEND);
+       EXIT_LOG;
 }
 
 typedef struct {
@@ -1627,19 +1387,16 @@ typedef struct {
        int32_t native_offsets [MAX_FRAMES];
 } FrameData;
 
-static int num_frames = MAX_FRAMES;
-
 static mono_bool
 walk_stack (MonoMethod *method, int32_t native_offset, int32_t il_offset, mono_bool managed, void* data)
 {
        FrameData *frame = (FrameData *)data;
-       if (method && frame->count < num_frames) {
+       if (method && frame->count < log_config.num_frames) {
                frame->il_offsets [frame->count] = il_offset;
                frame->native_offsets [frame->count] = native_offset;
                frame->methods [frame->count++] = method;
-               //printf ("In %d %s at %d (native: %d)\n", frame->count, mono_method_get_name (method), il_offset, native_offset);
        }
-       return frame->count == num_frames;
+       return frame->count == log_config.num_frames;
 }
 
 /*
@@ -1655,11 +1412,8 @@ collect_bt (FrameData *data)
 }
 
 static void
-emit_bt (MonoProfiler *prof, LogBuffer *logbuffer, FrameData *data)
+emit_bt (LogBuffer *logbuffer, FrameData *data)
 {
-       if (data->count > num_frames)
-               printf ("bad num frames: %d\n", data->count);
-
        emit_value (logbuffer, data->count);
 
        while (data->count)
@@ -1669,7 +1423,7 @@ emit_bt (MonoProfiler *prof, LogBuffer *logbuffer, FrameData *data)
 static void
 gc_alloc (MonoProfiler *prof, MonoObject *obj)
 {
-       int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces) ? TYPE_ALLOC_BT : 0;
+       int do_bt = (!log_config.enter_leave && InterlockedRead (&log_profiler.runtime_inited) && log_config.num_frames) ? TYPE_ALLOC_BT : 0;
        FrameData data;
        uintptr_t len = mono_object_get_size (obj);
        /* account for object alignment in the heap */
@@ -1698,7 +1452,7 @@ gc_alloc (MonoProfiler *prof, MonoObject *obj)
        emit_value (logbuffer, len);
 
        if (do_bt)
-               emit_bt (prof, logbuffer, &data);
+               emit_bt (logbuffer, &data);
 
        EXIT_LOG;
 }
@@ -1720,13 +1474,13 @@ gc_moves (MonoProfiler *prof, MonoObject *const *objects, uint64_t num)
        for (int i = 0; i < num; ++i)
                emit_obj (logbuffer, objects [i]);
 
-       EXIT_LOG_EXPLICIT (DO_SEND);
+       EXIT_LOG;
 }
 
 static void
 gc_handle (MonoProfiler *prof, int op, MonoGCHandleType type, uint32_t handle, MonoObject *obj)
 {
-       int do_bt = nocalls && InterlockedRead (&runtime_inited) && !notraces;
+       int do_bt = !log_config.enter_leave && InterlockedRead (&log_profiler.runtime_inited) && log_config.num_frames;
        FrameData data;
 
        if (do_bt)
@@ -1763,7 +1517,7 @@ gc_handle (MonoProfiler *prof, int op, MonoGCHandleType type, uint32_t handle, M
                emit_obj (logbuffer, obj);
 
        if (do_bt)
-               emit_bt (prof, logbuffer, &data);
+               emit_bt (logbuffer, &data);
 
        EXIT_LOG;
 }
@@ -1796,7 +1550,7 @@ static void
 finalize_end (MonoProfiler *prof)
 {
        trigger_on_demand_heapshot ();
-       if (ENABLED (PROFLOG_FINALIZATION_EVENTS)) {
+       if (ENABLED (PROFLOG_GC_FINALIZATION_EVENTS)) {
                ENTER_LOG (&finalize_ends_ctr, buf,
                        EVENT_SIZE /* event */
                );
@@ -1974,7 +1728,7 @@ class_loaded (MonoProfiler *prof, MonoClass *klass)
 {
        char *name;
 
-       if (InterlockedRead (&runtime_inited))
+       if (InterlockedRead (&log_profiler.runtime_inited))
                name = mono_type_get_name (mono_class_get_type (klass));
        else
                name = type_name (klass);
@@ -1999,7 +1753,7 @@ class_loaded (MonoProfiler *prof, MonoClass *klass)
 
        EXIT_LOG;
 
-       if (runtime_inited)
+       if (InterlockedRead (&log_profiler.runtime_inited))
                mono_free (name);
        else
                g_free (name);
@@ -2008,7 +1762,7 @@ class_loaded (MonoProfiler *prof, MonoClass *klass)
 static void
 method_enter (MonoProfiler *prof, MonoMethod *method)
 {
-       if (get_thread ()->call_depth++ <= max_call_depth) {
+       if (get_thread ()->call_depth++ <= log_config.max_call_depth) {
                ENTER_LOG (&method_entries_ctr, logbuffer,
                        EVENT_SIZE /* event */ +
                        LEB128_SIZE /* method */
@@ -2024,7 +1778,7 @@ method_enter (MonoProfiler *prof, MonoMethod *method)
 static void
 method_leave (MonoProfiler *prof, MonoMethod *method)
 {
-       if (--get_thread ()->call_depth <= max_call_depth) {
+       if (--get_thread ()->call_depth <= log_config.max_call_depth) {
                ENTER_LOG (&method_exits_ctr, logbuffer,
                        EVENT_SIZE /* event */ +
                        LEB128_SIZE /* method */
@@ -2040,7 +1794,7 @@ method_leave (MonoProfiler *prof, MonoMethod *method)
 static void
 method_exc_leave (MonoProfiler *prof, MonoMethod *method, MonoObject *exc)
 {
-       if (!nocalls && --get_thread ()->call_depth <= max_call_depth) {
+       if (--get_thread ()->call_depth <= log_config.max_call_depth) {
                ENTER_LOG (&method_exception_exits_ctr, logbuffer,
                        EVENT_SIZE /* event */ +
                        LEB128_SIZE /* method */
@@ -2109,7 +1863,7 @@ code_buffer_new (MonoProfiler *prof, const mono_byte *buffer, uint64_t size, Mon
 static void
 throw_exc (MonoProfiler *prof, MonoObject *object)
 {
-       int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces) ? TYPE_THROW_BT : 0;
+       int do_bt = (!log_config.enter_leave && InterlockedRead (&log_profiler.runtime_inited) && log_config.num_frames) ? TYPE_THROW_BT : 0;
        FrameData data;
 
        if (do_bt)
@@ -2130,7 +1884,7 @@ throw_exc (MonoProfiler *prof, MonoObject *object)
        emit_obj (logbuffer, object);
 
        if (do_bt)
-               emit_bt (prof, logbuffer, &data);
+               emit_bt (logbuffer, &data);
 
        EXIT_LOG;
 }
@@ -2157,7 +1911,7 @@ clause_exc (MonoProfiler *prof, MonoMethod *method, uint32_t clause_num, MonoExc
 static void
 monitor_event (MonoProfiler *profiler, MonoObject *object, MonoProfilerMonitorEvent ev)
 {
-       int do_bt = (nocalls && InterlockedRead (&runtime_inited) && !notraces) ? TYPE_MONITOR_BT : 0;
+       int do_bt = (!log_config.enter_leave && InterlockedRead (&log_profiler.runtime_inited) && log_config.num_frames) ? TYPE_MONITOR_BT : 0;
        FrameData data;
 
        if (do_bt)
@@ -2180,7 +1934,7 @@ monitor_event (MonoProfiler *profiler, MonoObject *object, MonoProfilerMonitorEv
        emit_obj (logbuffer, object);
 
        if (do_bt)
-               emit_bt (profiler, logbuffer, &data);
+               emit_bt (logbuffer, &data);
 
        EXIT_LOG;
 }
@@ -2206,37 +1960,33 @@ monitor_failed (MonoProfiler *prof, MonoObject *object)
 static void
 thread_start (MonoProfiler *prof, uintptr_t tid)
 {
-       if (ENABLED (PROFLOG_THREAD_EVENTS)) {
-               ENTER_LOG (&thread_starts_ctr, logbuffer,
-                       EVENT_SIZE /* event */ +
-                       BYTE_SIZE /* type */ +
-                       LEB128_SIZE /* tid */
-               );
+       ENTER_LOG (&thread_starts_ctr, logbuffer,
+               EVENT_SIZE /* event */ +
+               BYTE_SIZE /* type */ +
+               LEB128_SIZE /* tid */
+       );
 
-               emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
-               emit_byte (logbuffer, TYPE_THREAD);
-               emit_ptr (logbuffer, (void*) tid);
+       emit_event (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
+       emit_byte (logbuffer, TYPE_THREAD);
+       emit_ptr (logbuffer, (void*) tid);
 
-               EXIT_LOG;
-       }
+       EXIT_LOG;
 }
 
 static void
 thread_end (MonoProfiler *prof, uintptr_t tid)
 {
-       if (ENABLED (PROFLOG_THREAD_EVENTS)) {
-               ENTER_LOG (&thread_ends_ctr, logbuffer,
-                       EVENT_SIZE /* event */ +
-                       BYTE_SIZE /* type */ +
-                       LEB128_SIZE /* tid */
-               );
+       ENTER_LOG (&thread_ends_ctr, logbuffer,
+               EVENT_SIZE /* event */ +
+               BYTE_SIZE /* type */ +
+               LEB128_SIZE /* tid */
+       );
 
-               emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
-               emit_byte (logbuffer, TYPE_THREAD);
-               emit_ptr (logbuffer, (void*) tid);
+       emit_event (logbuffer, TYPE_END_UNLOAD | TYPE_METADATA);
+       emit_byte (logbuffer, TYPE_THREAD);
+       emit_ptr (logbuffer, (void*) tid);
 
-               EXIT_LOG_EXPLICIT (NO_SEND);
-       }
+       EXIT_LOG_EXPLICIT (NO_SEND);
 
        MonoProfilerThread *thread = get_thread ();
 
@@ -2251,22 +2001,20 @@ thread_name (MonoProfiler *prof, uintptr_t tid, const char *name)
 {
        int len = strlen (name) + 1;
 
-       if (ENABLED (PROFLOG_THREAD_EVENTS)) {
-               ENTER_LOG (&thread_names_ctr, logbuffer,
-                       EVENT_SIZE /* event */ +
-                       BYTE_SIZE /* type */ +
-                       LEB128_SIZE /* tid */ +
-                       len /* name */
-               );
+       ENTER_LOG (&thread_names_ctr, logbuffer,
+               EVENT_SIZE /* event */ +
+               BYTE_SIZE /* type */ +
+               LEB128_SIZE /* tid */ +
+               len /* name */
+       );
 
-               emit_event (logbuffer, TYPE_METADATA);
-               emit_byte (logbuffer, TYPE_THREAD);
-               emit_ptr (logbuffer, (void*)tid);
-               memcpy (logbuffer->cursor, name, len);
-               logbuffer->cursor += len;
+       emit_event (logbuffer, TYPE_METADATA);
+       emit_byte (logbuffer, TYPE_THREAD);
+       emit_ptr (logbuffer, (void*)tid);
+       memcpy (logbuffer->cursor, name, len);
+       logbuffer->cursor += len;
 
-               EXIT_LOG;
-       }
+       EXIT_LOG;
 }
 
 static void
@@ -2367,7 +2115,6 @@ typedef struct {
 
 typedef struct {
        MonoLockFreeQueueNode node;
-       MonoProfiler *prof;
        uint64_t time;
        uintptr_t tid;
        const void *ip;
@@ -2380,7 +2127,7 @@ async_walk_stack (MonoMethod *method, MonoDomain *domain, void *base_address, in
 {
        SampleHit *sample = (SampleHit *) data;
 
-       if (sample->count < num_frames) {
+       if (sample->count < log_config.num_frames) {
                int i = sample->count;
 
                sample->frames [i].method = method;
@@ -2391,7 +2138,7 @@ async_walk_stack (MonoMethod *method, MonoDomain *domain, void *base_address, in
                sample->count++;
        }
 
-       return sample->count == num_frames;
+       return sample->count == log_config.num_frames;
 }
 
 #define SAMPLE_SLOT_SIZE(FRAMES) (sizeof (SampleHit) + sizeof (AsyncFrameInfo) * (FRAMES - MONO_ZERO_LEN_ARRAY))
@@ -2403,8 +2150,8 @@ enqueue_sample_hit (gpointer p)
        SampleHit *sample = p;
 
        mono_lock_free_queue_node_unpoison (&sample->node);
-       mono_lock_free_queue_enqueue (&sample->prof->dumper_queue, &sample->node);
-       mono_os_sem_post (&sample->prof->dumper_queue_sem);
+       mono_lock_free_queue_enqueue (&log_profiler.dumper_queue, &sample->node);
+       mono_os_sem_post (&log_profiler.dumper_queue_sem);
 }
 
 static void
@@ -2418,7 +2165,7 @@ mono_sample_hit (MonoProfiler *profiler, const mono_byte *ip, const void *contex
         * invoking runtime functions, which is not async-signal-safe.
         */
 
-       if (InterlockedRead (&in_shutdown))
+       if (InterlockedRead (&log_profiler.in_shutdown))
                return;
 
        SampleHit *sample = (SampleHit *) mono_lock_free_queue_dequeue (&profiler->sample_reuse_queue);
@@ -2428,11 +2175,10 @@ mono_sample_hit (MonoProfiler *profiler, const mono_byte *ip, const void *contex
                 * If we're out of reusable sample events and we're not allowed to
                 * allocate more, we have no choice but to drop the event.
                 */
-               if (InterlockedRead (&sample_allocations_ctr) >= max_allocated_sample_hits)
+               if (InterlockedRead (&sample_allocations_ctr) >= log_config.max_allocated_sample_hits)
                        return;
 
                sample = mono_lock_free_alloc (&profiler->sample_allocator);
-               sample->prof = profiler;
                mono_lock_free_queue_node_init (&sample->node, TRUE);
 
                InterlockedIncrement (&sample_allocations_ctr);
@@ -2474,8 +2220,7 @@ add_code_page (uintptr_t *hash, uintptr_t hsize, uintptr_t page)
                if (++i == hsize)
                        i = 0;
        } while (i != start_pos);
-       /* should not happen */
-       printf ("failed code page store\n");
+       g_assert_not_reached ();
        return 0;
 }
 
@@ -2505,7 +2250,7 @@ add_code_pointer (uintptr_t ip)
 //#if defined(HAVE_DL_ITERATE_PHDR) && defined(ELFMAG0)
 #if 0
 static void
-dump_ubin (MonoProfiler *prof, const char *filename, uintptr_t load_addr, uint64_t offset, uintptr_t size)
+dump_ubin (const char *filename, uintptr_t load_addr, uint64_t offset, uintptr_t size)
 {
        int len = strlen (filename) + 1;
 
@@ -2524,12 +2269,12 @@ dump_ubin (MonoProfiler *prof, const char *filename, uintptr_t load_addr, uint64
        memcpy (logbuffer->cursor, filename, len);
        logbuffer->cursor += len;
 
-       EXIT_LOG_EXPLICIT (DO_SEND);
+       EXIT_LOG;
 }
 #endif
 
 static void
-dump_usym (MonoProfiler *prof, const char *name, uintptr_t value, uintptr_t size)
+dump_usym (const char *name, uintptr_t value, uintptr_t size)
 {
        int len = strlen (name) + 1;
 
@@ -2546,7 +2291,7 @@ dump_usym (MonoProfiler *prof, const char *name, uintptr_t value, uintptr_t size
        memcpy (logbuffer->cursor, name, len);
        logbuffer->cursor += len;
 
-       EXIT_LOG_EXPLICIT (DO_SEND);
+       EXIT_LOG;
 }
 
 /* ELF code crashes on some systems. */
@@ -2565,7 +2310,7 @@ dump_usym (MonoProfiler *prof, const char *name, uintptr_t value, uintptr_t size
 #endif
 
 static void
-dump_elf_symbols (MonoProfiler *prof, ElfW(Sym) *symbols, int num_symbols, const char *strtab, void *load_addr)
+dump_elf_symbols (ElfW(Sym) *symbols, int num_symbols, const char *strtab, void *load_addr)
 {
        int i;
        for (i = 0; i < num_symbols; ++i) {
@@ -2573,7 +2318,6 @@ dump_elf_symbols (MonoProfiler *prof, ElfW(Sym) *symbols, int num_symbols, const
                sym =  strtab + symbols [i].st_name;
                if (!symbols [i].st_name || !symbols [i].st_size || (symbols [i].st_info & 0xf) != STT_FUNC)
                        continue;
-               //printf ("symbol %s at %d\n", sym, symbols [i].st_value);
                dump_usym (sym, (uintptr_t)load_addr + symbols [i].st_value, symbols [i].st_size);
        }
 }
@@ -2618,11 +2362,9 @@ read_elf_symbols (MonoProfiler *prof, const char *filename, void *load_addr)
        shstrtabh = (void*)((char*)sheader + (header->e_shentsize * header->e_shstrndx));
        strtab = (const char*)data + shstrtabh->sh_offset;
        for (i = 0; i < header->e_shnum; ++i) {
-               //printf ("section header: %d\n", sheader->sh_type);
                if (sheader->sh_type == SHT_SYMTAB) {
                        symtabh = sheader;
                        strtabh = (void*)((char*)data + header->e_shoff + sheader->sh_link * header->e_shentsize);
-                       /*printf ("symtab section header: %d, .strstr: %d\n", i, sheader->sh_link);*/
                        break;
                }
                sheader = (void*)((char*)sheader + header->e_shentsize);
@@ -2646,7 +2388,6 @@ read_elf_symbols (MonoProfiler *prof, const char *filename, void *load_addr)
 static int
 elf_dl_callback (struct dl_phdr_info *info, size_t size, void *data)
 {
-       MonoProfiler *prof = data;
        char buf [256];
        const char *filename;
        BinaryObject *obj;
@@ -2657,7 +2398,7 @@ elf_dl_callback (struct dl_phdr_info *info, size_t size, void *data)
        ElfW(Word) *hash_table = NULL;
        ElfW(Ehdr) *header = NULL;
        const char* strtab = NULL;
-       for (obj = prof->binary_objects; obj; obj = obj->next) {
+       for (obj = log_profiler.binary_objects; obj; obj = obj->next) {
                if (obj->addr == a)
                        return 0;
        }
@@ -2674,12 +2415,10 @@ elf_dl_callback (struct dl_phdr_info *info, size_t size, void *data)
        obj = g_calloc (sizeof (BinaryObject), 1);
        obj->addr = (void*)info->dlpi_addr;
        obj->name = pstrdup (filename);
-       obj->next = prof->binary_objects;
-       prof->binary_objects = obj;
-       //printf ("loaded file: %s at %p, segments: %d\n", filename, (void*)info->dlpi_addr, info->dlpi_phnum);
+       obj->next = log_profiler.binary_objects;
+       log_profiler.binary_objects = obj;
        a = NULL;
        for (i = 0; i < info->dlpi_phnum; ++i) {
-               //printf ("segment type %d file offset: %d, size: %d\n", info->dlpi_phdr[i].p_type, info->dlpi_phdr[i].p_offset, info->dlpi_phdr[i].p_memsz);
                if (info->dlpi_phdr[i].p_type == PT_LOAD && !header) {
                        header = (ElfW(Ehdr)*)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
                        if (header->e_ident [EI_MAG0] != ELFMAG0 ||
@@ -2688,12 +2427,12 @@ elf_dl_callback (struct dl_phdr_info *info, size_t size, void *data)
                                        header->e_ident [EI_MAG3] != ELFMAG3 ) {
                                header = NULL;
                        }
-                       dump_ubin (prof, filename, info->dlpi_addr + info->dlpi_phdr[i].p_vaddr, info->dlpi_phdr[i].p_offset, info->dlpi_phdr[i].p_memsz);
+                       dump_ubin (filename, info->dlpi_addr + info->dlpi_phdr[i].p_vaddr, info->dlpi_phdr[i].p_offset, info->dlpi_phdr[i].p_memsz);
                } else if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) {
                        dyn = (ElfW(Dyn) *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
                }
        }
-       if (read_elf_symbols (prof, filename, (void*)info->dlpi_addr))
+       if (read_elf_symbols (filename, (void*)info->dlpi_addr))
                return 0;
        if (!info->dlpi_name || !info->dlpi_name[0])
                return 0;
@@ -2701,8 +2440,6 @@ elf_dl_callback (struct dl_phdr_info *info, size_t size, void *data)
                return 0;
        for (i = 0; dyn [i].d_tag != DT_NULL; ++i) {
                if (dyn [i].d_tag == DT_SYMTAB) {
-                       if (symtab && do_debug)
-                               printf ("multiple symtabs: %d\n", i);
                        symtab = (ElfW(Sym) *)(a + dyn [i].d_un.d_ptr);
                } else if (dyn [i].d_tag == DT_HASH) {
                        hash_table = (ElfW(Word) *)(a + dyn [i].d_un.d_ptr);
@@ -2713,19 +2450,19 @@ elf_dl_callback (struct dl_phdr_info *info, size_t size, void *data)
        if (!hash_table)
                return 0;
        num_sym = hash_table [1];
-       dump_elf_symbols (prof, symtab, num_sym, strtab, (void*)info->dlpi_addr);
+       dump_elf_symbols (symtab, num_sym, strtab, (void*)info->dlpi_addr);
        return 0;
 }
 
 static int
-load_binaries (MonoProfiler *prof)
+load_binaries (void)
 {
-       dl_iterate_phdr (elf_dl_callback, prof);
+       dl_iterate_phdr (elf_dl_callback, NULL);
        return 1;
 }
 #else
 static int
-load_binaries (MonoProfiler *prof)
+load_binaries (void)
 {
        return 0;
 }
@@ -2755,13 +2492,13 @@ symbol_for (uintptr_t code)
 }
 
 static void
-dump_unmanaged_coderefs (MonoProfiler *prof)
+dump_unmanaged_coderefs (void)
 {
        int i;
        const char* last_symbol;
        uintptr_t addr, page_end;
 
-       if (load_binaries (prof))
+       if (load_binaries ())
                return;
        for (i = 0; i < size_code_pages; ++i) {
                const char* sym;
@@ -2779,37 +2516,22 @@ dump_unmanaged_coderefs (MonoProfiler *prof)
                        last_symbol = sym;
                        if (!sym)
                                continue;
-                       dump_usym (prof, sym, addr, 0); /* let's not guess the size */
-                       //printf ("found symbol at %p: %s\n", (void*)addr, sym);
+                       dump_usym (sym, addr, 0); /* let's not guess the size */
                }
        }
 }
 
-typedef struct MonoCounterAgent {
-       MonoCounter *counter;
-       // MonoCounterAgent specific data :
-       void *value;
-       size_t value_size;
-       short index;
-       short emitted;
-       struct MonoCounterAgent *next;
-} MonoCounterAgent;
-
-static MonoCounterAgent* counters;
-static int counters_index = 1;
-static mono_mutex_t counters_mutex;
-
 static void
 counters_add_agent (MonoCounter *counter)
 {
-       if (InterlockedRead (&in_shutdown))
+       if (InterlockedRead (&log_profiler.in_shutdown))
                return;
 
        MonoCounterAgent *agent, *item;
 
-       mono_os_mutex_lock (&counters_mutex);
+       mono_os_mutex_lock (&log_profiler.counters_mutex);
 
-       for (agent = counters; agent; agent = agent->next) {
+       for (agent = log_profiler.counters; agent; agent = agent->next) {
                if (agent->counter == counter) {
                        agent->value_size = 0;
                        if (agent->value) {
@@ -2824,21 +2546,21 @@ counters_add_agent (MonoCounter *counter)
        agent->counter = counter;
        agent->value = NULL;
        agent->value_size = 0;
-       agent->index = counters_index++;
-       agent->emitted = 0;
+       agent->index = log_profiler.counters_index++;
+       agent->emitted = FALSE;
        agent->next = NULL;
 
-       if (!counters) {
-               counters = agent;
+       if (!log_profiler.counters) {
+               log_profiler.counters = agent;
        } else {
-               item = counters;
+               item = log_profiler.counters;
                while (item->next)
                        item = item->next;
                item->next = agent;
        }
 
 done:
-       mono_os_mutex_unlock (&counters_mutex);
+       mono_os_mutex_unlock (&log_profiler.counters_mutex);
 }
 
 static mono_bool
@@ -2849,16 +2571,18 @@ counters_init_foreach_callback (MonoCounter *counter, gpointer data)
 }
 
 static void
-counters_init (MonoProfiler *profiler)
+counters_init (void)
 {
-       mono_os_mutex_init (&counters_mutex);
+       mono_os_mutex_init (&log_profiler.counters_mutex);
+
+       log_profiler.counters_index = 1;
 
        mono_counters_on_register (&counters_add_agent);
        mono_counters_foreach (counters_init_foreach_callback, NULL);
 }
 
 static void
-counters_emit (MonoProfiler *profiler)
+counters_emit (void)
 {
        MonoCounterAgent *agent;
        int len = 0;
@@ -2867,9 +2591,9 @@ counters_emit (MonoProfiler *profiler)
                LEB128_SIZE /* len */
        ;
 
-       mono_os_mutex_lock (&counters_mutex);
+       mono_os_mutex_lock (&log_profiler.counters_mutex);
 
-       for (agent = counters; agent; agent = agent->next) {
+       for (agent = log_profiler.counters; agent; agent = agent->next) {
                if (agent->emitted)
                        continue;
 
@@ -2893,7 +2617,7 @@ counters_emit (MonoProfiler *profiler)
        emit_event (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
        emit_value (logbuffer, len);
 
-       for (agent = counters; agent; agent = agent->next) {
+       for (agent = log_profiler.counters; agent; agent = agent->next) {
                const char *name;
 
                if (agent->emitted)
@@ -2907,17 +2631,17 @@ counters_emit (MonoProfiler *profiler)
                emit_byte (logbuffer, mono_counter_get_variance (agent->counter));
                emit_value (logbuffer, agent->index);
 
-               agent->emitted = 1;
+               agent->emitted = TRUE;
        }
 
-       EXIT_LOG_EXPLICIT (DO_SEND);
+       EXIT_LOG;
 
 done:
-       mono_os_mutex_unlock (&counters_mutex);
+       mono_os_mutex_unlock (&log_profiler.counters_mutex);
 }
 
 static void
-counters_sample (MonoProfiler *profiler, uint64_t timestamp)
+counters_sample (uint64_t timestamp)
 {
        MonoCounterAgent *agent;
        MonoCounter *counter;
@@ -2926,18 +2650,18 @@ counters_sample (MonoProfiler *profiler, uint64_t timestamp)
        void *buffer;
        int size;
 
-       counters_emit (profiler);
+       counters_emit ();
 
        buffer_size = 8;
        buffer = g_calloc (1, buffer_size);
 
-       mono_os_mutex_lock (&counters_mutex);
+       mono_os_mutex_lock (&log_profiler.counters_mutex);
 
        size =
                EVENT_SIZE /* event */
        ;
 
-       for (agent = counters; agent; agent = agent->next) {
+       for (agent = log_profiler.counters; agent; agent = agent->next) {
                size +=
                        LEB128_SIZE /* index */ +
                        BYTE_SIZE /* type */ +
@@ -2953,7 +2677,7 @@ counters_sample (MonoProfiler *profiler, uint64_t timestamp)
 
        emit_event_time (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE, timestamp);
 
-       for (agent = counters; agent; agent = agent->next) {
+       for (agent = log_profiler.counters; agent; agent = agent->next) {
                size_t size;
 
                counter = agent->counter;
@@ -3033,28 +2757,13 @@ counters_sample (MonoProfiler *profiler, uint64_t timestamp)
 
        emit_value (logbuffer, 0);
 
-       EXIT_LOG_EXPLICIT (DO_SEND);
+       EXIT_LOG;
 
-       mono_os_mutex_unlock (&counters_mutex);
+       mono_os_mutex_unlock (&log_profiler.counters_mutex);
 }
 
-typedef struct _PerfCounterAgent PerfCounterAgent;
-struct _PerfCounterAgent {
-       PerfCounterAgent *next;
-       int index;
-       char *category_name;
-       char *name;
-       int type;
-       gint64 value;
-       guint8 emitted;
-       guint8 updated;
-       guint8 deleted;
-};
-
-static PerfCounterAgent *perfcounters = NULL;
-
 static void
-perfcounters_emit (MonoProfiler *profiler)
+perfcounters_emit (void)
 {
        PerfCounterAgent *pcagent;
        int len = 0;
@@ -3063,7 +2772,7 @@ perfcounters_emit (MonoProfiler *profiler)
                LEB128_SIZE /* len */
        ;
 
-       for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+       for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
                if (pcagent->emitted)
                        continue;
 
@@ -3088,7 +2797,7 @@ perfcounters_emit (MonoProfiler *profiler)
        emit_event (logbuffer, TYPE_SAMPLE_COUNTERS_DESC | TYPE_SAMPLE);
        emit_value (logbuffer, len);
 
-       for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+       for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
                if (pcagent->emitted)
                        continue;
 
@@ -3100,10 +2809,10 @@ perfcounters_emit (MonoProfiler *profiler)
                emit_byte (logbuffer, MONO_COUNTER_VARIABLE);
                emit_value (logbuffer, pcagent->index);
 
-               pcagent->emitted = 1;
+               pcagent->emitted = TRUE;
        }
 
-       EXIT_LOG_EXPLICIT (DO_SEND);
+       EXIT_LOG;
 }
 
 static gboolean
@@ -3111,56 +2820,55 @@ perfcounters_foreach (char *category_name, char *name, unsigned char type, gint6
 {
        PerfCounterAgent *pcagent;
 
-       for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+       for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
                if (strcmp (pcagent->category_name, category_name) != 0 || strcmp (pcagent->name, name) != 0)
                        continue;
                if (pcagent->value == value)
                        return TRUE;
 
                pcagent->value = value;
-               pcagent->updated = 1;
-               pcagent->deleted = 0;
+               pcagent->updated = TRUE;
+               pcagent->deleted = FALSE;
                return TRUE;
        }
 
        pcagent = g_new0 (PerfCounterAgent, 1);
-       pcagent->next = perfcounters;
-       pcagent->index = counters_index++;
+       pcagent->next = log_profiler.perfcounters;
+       pcagent->index = log_profiler.counters_index++;
        pcagent->category_name = g_strdup (category_name);
        pcagent->name = g_strdup (name);
-       pcagent->type = (int) type;
        pcagent->value = value;
-       pcagent->emitted = 0;
-       pcagent->updated = 1;
-       pcagent->deleted = 0;
+       pcagent->emitted = FALSE;
+       pcagent->updated = TRUE;
+       pcagent->deleted = FALSE;
 
-       perfcounters = pcagent;
+       log_profiler.perfcounters = pcagent;
 
        return TRUE;
 }
 
 static void
-perfcounters_sample (MonoProfiler *profiler, uint64_t timestamp)
+perfcounters_sample (uint64_t timestamp)
 {
        PerfCounterAgent *pcagent;
        int len = 0;
        int size;
 
-       mono_os_mutex_lock (&counters_mutex);
+       mono_os_mutex_lock (&log_profiler.counters_mutex);
 
        /* mark all perfcounters as deleted, foreach will unmark them as necessary */
-       for (pcagent = perfcounters; pcagent; pcagent = pcagent->next)
-               pcagent->deleted = 1;
+       for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next)
+               pcagent->deleted = TRUE;
 
-       mono_perfcounter_foreach (perfcounters_foreach, perfcounters);
+       mono_perfcounter_foreach (perfcounters_foreach, NULL);
 
-       perfcounters_emit (profiler);
+       perfcounters_emit ();
 
        size =
                EVENT_SIZE /* event */
        ;
 
-       for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+       for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
                if (pcagent->deleted || !pcagent->updated)
                        continue;
 
@@ -3184,47 +2892,33 @@ perfcounters_sample (MonoProfiler *profiler, uint64_t timestamp)
 
        emit_event_time (logbuffer, TYPE_SAMPLE_COUNTERS | TYPE_SAMPLE, timestamp);
 
-       for (pcagent = perfcounters; pcagent; pcagent = pcagent->next) {
+       for (pcagent = log_profiler.perfcounters; pcagent; pcagent = pcagent->next) {
                if (pcagent->deleted || !pcagent->updated)
                        continue;
                emit_uvalue (logbuffer, pcagent->index);
                emit_byte (logbuffer, MONO_COUNTER_LONG);
                emit_svalue (logbuffer, pcagent->value);
 
-               pcagent->updated = 0;
+               pcagent->updated = FALSE;
        }
 
        emit_value (logbuffer, 0);
 
-       EXIT_LOG_EXPLICIT (DO_SEND);
+       EXIT_LOG;
 
 done:
-       mono_os_mutex_unlock (&counters_mutex);
+       mono_os_mutex_unlock (&log_profiler.counters_mutex);
 }
 
 static void
-counters_and_perfcounters_sample (MonoProfiler *prof)
+counters_and_perfcounters_sample (void)
 {
        uint64_t now = current_time ();
 
-       counters_sample (prof, now);
-       perfcounters_sample (prof, now);
+       counters_sample (now);
+       perfcounters_sample (now);
 }
 
-#define COVERAGE_DEBUG(x) if (debug_coverage) {x}
-static mono_mutex_t coverage_mutex;
-static MonoConcurrentHashTable *coverage_methods = NULL;
-static MonoConcurrentHashTable *coverage_assemblies = NULL;
-static MonoConcurrentHashTable *coverage_classes = NULL;
-
-static MonoConcurrentHashTable *filtered_classes = NULL;
-static MonoConcurrentHashTable *image_to_methods = NULL;
-static MonoConcurrentHashTable *suppressed_assemblies = NULL;
-static gboolean coverage_initialized = FALSE;
-
-static GPtrArray *coverage_data = NULL;
-static int previous_offset = 0;
-
 typedef struct {
        MonoLockFreeQueueNode node;
        MonoMethod *method;
@@ -3249,10 +2943,10 @@ free_coverage_entry (gpointer data, gpointer userdata)
 static void
 obtain_coverage_for_method (MonoProfiler *prof, const MonoProfilerCoverageData *entry)
 {
-       int offset = entry->il_offset - previous_offset;
+       int offset = entry->il_offset - log_profiler.coverage_previous_offset;
        CoverageEntry *e = g_new (CoverageEntry, 1);
 
-       previous_offset = entry->il_offset;
+       log_profiler.coverage_previous_offset = entry->il_offset;
 
        e->offset = offset;
        e->counter = entry->counter;
@@ -3260,7 +2954,7 @@ obtain_coverage_for_method (MonoProfiler *prof, const MonoProfilerCoverageData *
        e->line = entry->line;
        e->column = entry->column;
 
-       g_ptr_array_add (coverage_data, e);
+       g_ptr_array_add (log_profiler.coverage_data, e);
 }
 
 static char *
@@ -3310,22 +3004,20 @@ parse_generic_type_names(char *name)
        return ret;
 }
 
-static int method_id;
 static void
 build_method_buffer (gpointer key, gpointer value, gpointer userdata)
 {
        MonoMethod *method = (MonoMethod *)value;
-       MonoProfiler *prof = (MonoProfiler *)userdata;
        MonoClass *klass;
        MonoImage *image;
        char *class_name;
        const char *image_name, *method_name, *sig, *first_filename;
        guint i;
 
-       previous_offset = 0;
-       coverage_data = g_ptr_array_new ();
+       log_profiler.coverage_previous_offset = 0;
+       log_profiler.coverage_data = g_ptr_array_new ();
 
-       mono_profiler_get_coverage_data (prof->handle, method, obtain_coverage_for_method);
+       mono_profiler_get_coverage_data (log_profiler.handle, method, obtain_coverage_for_method);
 
        klass = mono_method_get_class (method);
        image = mono_class_get_image (klass);
@@ -3335,8 +3027,8 @@ build_method_buffer (gpointer key, gpointer value, gpointer userdata)
        class_name = parse_generic_type_names (mono_type_get_name (mono_class_get_type (klass)));
        method_name = mono_method_get_name (method);
 
-       if (coverage_data->len != 0) {
-               CoverageEntry *entry = (CoverageEntry *)coverage_data->pdata[0];
+       if (log_profiler.coverage_data->len != 0) {
+               CoverageEntry *entry = (CoverageEntry *)log_profiler.coverage_data->pdata[0];
                first_filename = entry->filename ? entry->filename : "";
        } else
                first_filename = "";
@@ -3365,13 +3057,13 @@ build_method_buffer (gpointer key, gpointer value, gpointer userdata)
        emit_string (logbuffer, first_filename, strlen (first_filename) + 1);
 
        emit_uvalue (logbuffer, mono_method_get_token (method));
-       emit_uvalue (logbuffer, method_id);
-       emit_value (logbuffer, coverage_data->len);
+       emit_uvalue (logbuffer, log_profiler.coverage_method_id);
+       emit_value (logbuffer, log_profiler.coverage_data->len);
 
-       EXIT_LOG_EXPLICIT (DO_SEND);
+       EXIT_LOG;
 
-       for (i = 0; i < coverage_data->len; i++) {
-               CoverageEntry *entry = (CoverageEntry *)coverage_data->pdata[i];
+       for (i = 0; i < log_profiler.coverage_data->len; i++) {
+               CoverageEntry *entry = (CoverageEntry *)log_profiler.coverage_data->pdata[i];
 
                ENTER_LOG (&coverage_statements_ctr, logbuffer,
                        EVENT_SIZE /* event */ +
@@ -3383,22 +3075,21 @@ build_method_buffer (gpointer key, gpointer value, gpointer userdata)
                );
 
                emit_event (logbuffer, TYPE_COVERAGE_STATEMENT | TYPE_COVERAGE);
-               emit_uvalue (logbuffer, method_id);
+               emit_uvalue (logbuffer, log_profiler.coverage_method_id);
                emit_uvalue (logbuffer, entry->offset);
                emit_uvalue (logbuffer, entry->counter);
                emit_uvalue (logbuffer, entry->line);
                emit_uvalue (logbuffer, entry->column);
 
-               EXIT_LOG_EXPLICIT (DO_SEND);
+               EXIT_LOG;
        }
 
-       method_id++;
+       log_profiler.coverage_method_id++;
 
        g_free (class_name);
 
-       g_ptr_array_foreach (coverage_data, free_coverage_entry, NULL);
-       g_ptr_array_free (coverage_data, TRUE);
-       coverage_data = NULL;
+       g_ptr_array_foreach (log_profiler.coverage_data, free_coverage_entry, NULL);
+       g_ptr_array_free (log_profiler.coverage_data, TRUE);
 }
 
 /* This empties the queue */
@@ -3453,7 +3144,7 @@ build_class_buffer (gpointer key, gpointer value, gpointer userdata)
        emit_uvalue (logbuffer, fully_covered);
        emit_uvalue (logbuffer, partially_covered);
 
-       EXIT_LOG_EXPLICIT (DO_SEND);
+       EXIT_LOG;
 
        g_free (class_name);
 }
@@ -3461,7 +3152,7 @@ build_class_buffer (gpointer key, gpointer value, gpointer userdata)
 static void
 get_coverage_for_image (MonoImage *image, int *number_of_methods, guint *fully_covered, int *partially_covered)
 {
-       MonoLockFreeQueue *image_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (image_to_methods, image);
+       MonoLockFreeQueue *image_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (log_profiler.coverage_image_to_methods, image);
 
        *number_of_methods = mono_image_get_table_rows (image, MONO_TABLE_METHOD);
        if (image_methods)
@@ -3510,25 +3201,17 @@ build_assembly_buffer (gpointer key, gpointer value, gpointer userdata)
        emit_uvalue (logbuffer, fully_covered);
        emit_uvalue (logbuffer, partially_covered);
 
-       EXIT_LOG_EXPLICIT (DO_SEND);
+       EXIT_LOG;
 }
 
 static void
-dump_coverage (MonoProfiler *prof)
+dump_coverage (void)
 {
-       if (!coverage_initialized)
-               return;
-
-       COVERAGE_DEBUG(fprintf (stderr, "Coverage: Started dump\n");)
-       method_id = 0;
-
-       mono_os_mutex_lock (&coverage_mutex);
-       mono_conc_hashtable_foreach (coverage_assemblies, build_assembly_buffer, NULL);
-       mono_conc_hashtable_foreach (coverage_classes, build_class_buffer, NULL);
-       mono_conc_hashtable_foreach (coverage_methods, build_method_buffer, prof);
-       mono_os_mutex_unlock (&coverage_mutex);
-
-       COVERAGE_DEBUG(fprintf (stderr, "Coverage: Finished dump\n");)
+       mono_os_mutex_lock (&log_profiler.coverage_mutex);
+       mono_conc_hashtable_foreach (log_profiler.coverage_assemblies, build_assembly_buffer, NULL);
+       mono_conc_hashtable_foreach (log_profiler.coverage_classes, build_class_buffer, NULL);
+       mono_conc_hashtable_foreach (log_profiler.coverage_methods, build_method_buffer, NULL);
+       mono_os_mutex_unlock (&log_profiler.coverage_mutex);
 }
 
 static MonoLockFreeQueueNode *
@@ -3555,42 +3238,31 @@ coverage_filter (MonoProfiler *prof, MonoMethod *method)
        MonoLockFreeQueue *image_methods, *class_methods;
        MonoLockFreeQueueNode *node;
 
-       g_assert (coverage_initialized && "Why are we being asked for coverage filter info when we're not doing coverage?");
-
-       COVERAGE_DEBUG(fprintf (stderr, "Coverage filter for %s\n", mono_method_get_name (method));)
-
        flags = mono_method_get_flags (method, &iflags);
-       if ((iflags & 0x1000 /*METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL*/) ||
-           (flags & 0x2000 /*METHOD_ATTRIBUTE_PINVOKE_IMPL*/)) {
-               COVERAGE_DEBUG(fprintf (stderr, "   Internal call or pinvoke - ignoring\n");)
+       if ((iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
+           (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
                return FALSE;
-       }
 
        // Don't need to do anything else if we're already tracking this method
-       if (mono_conc_hashtable_lookup (coverage_methods, method)) {
-               COVERAGE_DEBUG(fprintf (stderr, "   Already tracking\n");)
+       if (mono_conc_hashtable_lookup (log_profiler.coverage_methods, method))
                return TRUE;
-       }
 
        klass = mono_method_get_class (method);
        image = mono_class_get_image (klass);
 
        // Don't handle coverage for the core assemblies
-       if (mono_conc_hashtable_lookup (suppressed_assemblies, (gpointer) mono_image_get_name (image)) != NULL)
+       if (mono_conc_hashtable_lookup (log_profiler.coverage_suppressed_assemblies, (gpointer) mono_image_get_name (image)) != NULL)
                return FALSE;
 
        if (prof->coverage_filters) {
                /* Check already filtered classes first */
-               if (mono_conc_hashtable_lookup (filtered_classes, klass)) {
-                       COVERAGE_DEBUG(fprintf (stderr, "   Already filtered\n");)
+               if (mono_conc_hashtable_lookup (log_profiler.coverage_filtered_classes, klass))
                        return FALSE;
-               }
 
                classname = mono_type_get_name (mono_class_get_type (klass));
 
                fqn = g_strdup_printf ("[%s]%s", mono_image_get_name (image), classname);
 
-               COVERAGE_DEBUG(fprintf (stderr, "   Looking for %s in filter\n", fqn);)
                // Check positive filters first
                has_positive = FALSE;
                found = FALSE;
@@ -3600,24 +3272,17 @@ coverage_filter (MonoProfiler *prof, MonoMethod *method)
                        if (filter [0] == '+') {
                                filter = &filter [1];
 
-                               COVERAGE_DEBUG(fprintf (stderr, "   Checking against +%s ...", filter);)
-
-                               if (strstr (fqn, filter) != NULL) {
-                                       COVERAGE_DEBUG(fprintf (stderr, "matched\n");)
+                               if (strstr (fqn, filter) != NULL)
                                        found = TRUE;
-                               } else
-                                       COVERAGE_DEBUG(fprintf (stderr, "no match\n");)
 
                                has_positive = TRUE;
                        }
                }
 
                if (has_positive && !found) {
-                       COVERAGE_DEBUG(fprintf (stderr, "   Positive match was not found\n");)
-
-                       mono_os_mutex_lock (&coverage_mutex);
-                       mono_conc_hashtable_insert (filtered_classes, klass, klass);
-                       mono_os_mutex_unlock (&coverage_mutex);
+                       mono_os_mutex_lock (&log_profiler.coverage_mutex);
+                       mono_conc_hashtable_insert (log_profiler.coverage_filtered_classes, klass, klass);
+                       mono_os_mutex_unlock (&log_profiler.coverage_mutex);
                        g_free (fqn);
                        g_free (classname);
 
@@ -3632,28 +3297,22 @@ coverage_filter (MonoProfiler *prof, MonoMethod *method)
 
                        // Skip '-'
                        filter = &filter [1];
-                       COVERAGE_DEBUG(fprintf (stderr, "   Checking against -%s ...", filter);)
 
                        if (strstr (fqn, filter) != NULL) {
-                               COVERAGE_DEBUG(fprintf (stderr, "matched\n");)
-
-                               mono_os_mutex_lock (&coverage_mutex);
-                               mono_conc_hashtable_insert (filtered_classes, klass, klass);
-                               mono_os_mutex_unlock (&coverage_mutex);
+                               mono_os_mutex_lock (&log_profiler.coverage_mutex);
+                               mono_conc_hashtable_insert (log_profiler.coverage_filtered_classes, klass, klass);
+                               mono_os_mutex_unlock (&log_profiler.coverage_mutex);
                                g_free (fqn);
                                g_free (classname);
 
                                return FALSE;
-                       } else
-                               COVERAGE_DEBUG(fprintf (stderr, "no match\n");)
-
+                       }
                }
 
                g_free (fqn);
                g_free (classname);
        }
 
-       COVERAGE_DEBUG(fprintf (stderr, "   Handling coverage for %s\n", mono_method_get_name (method));)
        header = mono_method_get_header_checked (method, &error);
        mono_error_cleanup (&error);
 
@@ -3666,32 +3325,32 @@ coverage_filter (MonoProfiler *prof, MonoMethod *method)
        // generated causing a crash. See https://bugzilla.xamarin.com/show_bug.cgi?id=39325
        mono_assembly_addref (assembly);
 
-       mono_os_mutex_lock (&coverage_mutex);
-       mono_conc_hashtable_insert (coverage_methods, method, method);
-       mono_conc_hashtable_insert (coverage_assemblies, assembly, assembly);
-       mono_os_mutex_unlock (&coverage_mutex);
+       mono_os_mutex_lock (&log_profiler.coverage_mutex);
+       mono_conc_hashtable_insert (log_profiler.coverage_methods, method, method);
+       mono_conc_hashtable_insert (log_profiler.coverage_assemblies, assembly, assembly);
+       mono_os_mutex_unlock (&log_profiler.coverage_mutex);
 
-       image_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (image_to_methods, image);
+       image_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (log_profiler.coverage_image_to_methods, image);
 
        if (image_methods == NULL) {
                image_methods = (MonoLockFreeQueue *) g_malloc (sizeof (MonoLockFreeQueue));
                mono_lock_free_queue_init (image_methods);
-               mono_os_mutex_lock (&coverage_mutex);
-               mono_conc_hashtable_insert (image_to_methods, image, image_methods);
-               mono_os_mutex_unlock (&coverage_mutex);
+               mono_os_mutex_lock (&log_profiler.coverage_mutex);
+               mono_conc_hashtable_insert (log_profiler.coverage_image_to_methods, image, image_methods);
+               mono_os_mutex_unlock (&log_profiler.coverage_mutex);
        }
 
        node = create_method_node (method);
        mono_lock_free_queue_enqueue (image_methods, node);
 
-       class_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (coverage_classes, klass);
+       class_methods = (MonoLockFreeQueue *)mono_conc_hashtable_lookup (log_profiler.coverage_classes, klass);
 
        if (class_methods == NULL) {
                class_methods = (MonoLockFreeQueue *) g_malloc (sizeof (MonoLockFreeQueue));
                mono_lock_free_queue_init (class_methods);
-               mono_os_mutex_lock (&coverage_mutex);
-               mono_conc_hashtable_insert (coverage_classes, klass, class_methods);
-               mono_os_mutex_unlock (&coverage_mutex);
+               mono_os_mutex_lock (&log_profiler.coverage_mutex);
+               mono_conc_hashtable_insert (log_profiler.coverage_classes, klass, class_methods);
+               mono_os_mutex_unlock (&log_profiler.coverage_mutex);
        }
 
        node = create_method_node (method);
@@ -3764,21 +3423,20 @@ init_suppressed_assemblies (void)
        char *line;
        FILE *sa_file;
 
-       suppressed_assemblies = mono_conc_hashtable_new (g_str_hash, g_str_equal);
+       log_profiler.coverage_suppressed_assemblies = mono_conc_hashtable_new (g_str_hash, g_str_equal);
        sa_file = fopen (SUPPRESSION_DIR "/mono-profiler-log.suppression", "r");
        if (sa_file == NULL)
                return;
 
        /* Don't need to free @content as it is referred to by the lines stored in @suppressed_assemblies */
        content = get_file_content (sa_file);
-       if (content == NULL) {
-               g_error ("mono-profiler-log.suppression is greater than 128kb - aborting\n");
-       }
+       if (content == NULL)
+               g_error ("mono-profiler-log.suppression is greater than 128kb - aborting.");
 
        while ((line = get_next_line (content, &content))) {
                line = g_strchomp (g_strchug (line));
                /* No locking needed as we're doing initialization */
-               mono_conc_hashtable_insert (suppressed_assemblies, line, line);
+               mono_conc_hashtable_insert (log_profiler.coverage_suppressed_assemblies, line, line);
        }
 
        fclose (sa_file);
@@ -3787,19 +3445,20 @@ init_suppressed_assemblies (void)
 static void
 parse_cov_filter_file (GPtrArray *filters, const char *file)
 {
-       FILE *filter_file;
-       char *line, *content;
+       FILE *filter_file = fopen (file, "r");
 
-       filter_file = fopen (file, "r");
        if (filter_file == NULL) {
-               fprintf (stderr, "Unable to open %s\n", file);
+               mono_profiler_printf_err ("Could not open coverage filter file '%s'.", file);
                return;
        }
 
        /* Don't need to free content as it is referred to by the lines stored in @filters */
-       content = get_file_content (filter_file);
+       char *content = get_file_content (filter_file);
+
        if (content == NULL)
-               fprintf (stderr, "WARNING: %s is greater than 128kb - ignoring\n", file);
+               mono_profiler_printf_err ("Coverage filter file '%s' is larger than 128kb - ignoring.", file);
+
+       char *line;
 
        while ((line = get_next_line (content, &content)))
                g_ptr_array_add (filters, g_strchug (g_strchomp (line)));
@@ -3808,21 +3467,15 @@ parse_cov_filter_file (GPtrArray *filters, const char *file)
 }
 
 static void
-coverage_init (MonoProfiler *prof)
-{
-       g_assert (!coverage_initialized && "Why are we initializing coverage twice?");
-
-       COVERAGE_DEBUG(fprintf (stderr, "Coverage initialized\n");)
-
-       mono_os_mutex_init (&coverage_mutex);
-       coverage_methods = mono_conc_hashtable_new (NULL, NULL);
-       coverage_assemblies = mono_conc_hashtable_new (NULL, NULL);
-       coverage_classes = mono_conc_hashtable_new (NULL, NULL);
-       filtered_classes = mono_conc_hashtable_new (NULL, NULL);
-       image_to_methods = mono_conc_hashtable_new (NULL, NULL);
+coverage_init (void)
+{
+       mono_os_mutex_init (&log_profiler.coverage_mutex);
+       log_profiler.coverage_methods = mono_conc_hashtable_new (NULL, NULL);
+       log_profiler.coverage_assemblies = mono_conc_hashtable_new (NULL, NULL);
+       log_profiler.coverage_classes = mono_conc_hashtable_new (NULL, NULL);
+       log_profiler.coverage_filtered_classes = mono_conc_hashtable_new (NULL, NULL);
+       log_profiler.coverage_image_to_methods = mono_conc_hashtable_new (NULL, NULL);
        init_suppressed_assemblies ();
-
-       coverage_initialized = TRUE;
 }
 
 static void
@@ -3839,45 +3492,55 @@ free_sample_hit (gpointer p)
 }
 
 static void
-cleanup_reusable_samples (MonoProfiler *prof)
+cleanup_reusable_samples (void)
 {
        SampleHit *sample;
 
-       while ((sample = (SampleHit *) mono_lock_free_queue_dequeue (&prof->sample_reuse_queue)))
+       while ((sample = (SampleHit *) mono_lock_free_queue_dequeue (&log_profiler.sample_reuse_queue)))
                mono_thread_hazardous_try_free (sample, free_sample_hit);
 }
 
+static void
+log_early_shutdown (MonoProfiler *prof)
+{
+       if (log_config.hs_on_shutdown) {
+               InterlockedWrite (&log_profiler.heapshot_requested, 1);
+               mono_gc_collect (mono_gc_max_generation ());
+       }
+}
+
 static void
 log_shutdown (MonoProfiler *prof)
 {
-       InterlockedWrite (&in_shutdown, 1);
+       InterlockedWrite (&log_profiler.in_shutdown, 1);
 
-       if (!no_counters)
-               counters_and_perfcounters_sample (prof);
+       if (ENABLED (PROFLOG_COUNTER_EVENTS))
+               counters_and_perfcounters_sample ();
 
-       dump_coverage (prof);
+       if (log_config.collect_coverage)
+               dump_coverage ();
 
        char c = 1;
 
        if (write (prof->pipes [1], &c, 1) != 1) {
-               fprintf (stderr, "Could not write to pipe: %s\n", strerror (errno));
+               mono_profiler_printf_err ("Could not write to log profiler pipe: %s", g_strerror (errno));
                exit (1);
        }
 
        mono_native_thread_join (prof->helper_thread);
 
-       mono_os_mutex_destroy (&counters_mutex);
+       mono_os_mutex_destroy (&log_profiler.counters_mutex);
 
        MonoCounterAgent *mc_next;
 
-       for (MonoCounterAgent *cur = counters; cur; cur = mc_next) {
+       for (MonoCounterAgent *cur = log_profiler.counters; cur; cur = mc_next) {
                mc_next = cur->next;
                g_free (cur);
        }
 
        PerfCounterAgent *pc_next;
 
-       for (PerfCounterAgent *cur = perfcounters; cur; cur = pc_next) {
+       for (PerfCounterAgent *cur = log_profiler.perfcounters; cur; cur = pc_next) {
                pc_next = cur->next;
                g_free (cur);
        }
@@ -3887,8 +3550,8 @@ log_shutdown (MonoProfiler *prof)
         * not immediately removed upon calling mono_lls_remove (), by
         * iterating until the head is NULL.
         */
-       while (profiler_thread_list.head) {
-               MONO_LLS_FOREACH_SAFE (&profiler_thread_list, MonoProfilerThread, thread) {
+       while (log_profiler.profiler_thread_list.head) {
+               MONO_LLS_FOREACH_SAFE (&log_profiler.profiler_thread_list, MonoProfilerThread, thread) {
                        g_assert (thread->attached && "Why is a thread in the LLS not attached?");
 
                        remove_thread (thread);
@@ -3917,7 +3580,7 @@ log_shutdown (MonoProfiler *prof)
         */
        mono_thread_hazardous_try_free_all ();
 
-       cleanup_reusable_samples (prof);
+       cleanup_reusable_samples ();
 
        /*
         * Finally, make sure that all sample hits are freed. This should cover all
@@ -3927,7 +3590,7 @@ log_shutdown (MonoProfiler *prof)
         */
        mono_thread_hazardous_try_free_all ();
 
-       gint32 state = InterlockedRead (&buffer_lock_state);
+       gint32 state = InterlockedRead (&log_profiler.buffer_lock_state);
 
        g_assert (!(state & 0xFFFF) && "Why is the reader count still non-zero?");
        g_assert (!(state >> 16) && "Why is the exclusive lock still held?");
@@ -3944,25 +3607,26 @@ log_shutdown (MonoProfiler *prof)
        mono_conc_hashtable_destroy (prof->method_table);
        mono_os_mutex_destroy (&prof->method_table_mutex);
 
-       if (coverage_initialized) {
-               mono_os_mutex_lock (&coverage_mutex);
-               mono_conc_hashtable_foreach (coverage_assemblies, unref_coverage_assemblies, prof);
-               mono_os_mutex_unlock (&coverage_mutex);
+       if (log_config.collect_coverage) {
+               mono_os_mutex_lock (&log_profiler.coverage_mutex);
+               mono_conc_hashtable_foreach (log_profiler.coverage_assemblies, unref_coverage_assemblies, NULL);
+               mono_os_mutex_unlock (&log_profiler.coverage_mutex);
 
-               mono_conc_hashtable_destroy (coverage_methods);
-               mono_conc_hashtable_destroy (coverage_assemblies);
-               mono_conc_hashtable_destroy (coverage_classes);
-               mono_conc_hashtable_destroy (filtered_classes);
+               mono_conc_hashtable_destroy (log_profiler.coverage_methods);
+               mono_conc_hashtable_destroy (log_profiler.coverage_assemblies);
+               mono_conc_hashtable_destroy (log_profiler.coverage_classes);
+               mono_conc_hashtable_destroy (log_profiler.coverage_filtered_classes);
 
-               mono_conc_hashtable_destroy (image_to_methods);
-               mono_conc_hashtable_destroy (suppressed_assemblies);
-               mono_os_mutex_destroy (&coverage_mutex);
+               mono_conc_hashtable_destroy (log_profiler.coverage_image_to_methods);
+               mono_conc_hashtable_destroy (log_profiler.coverage_suppressed_assemblies);
+               mono_os_mutex_destroy (&log_profiler.coverage_mutex);
        }
 
+       mono_coop_mutex_destroy (&log_profiler.api_mutex);
+
        PROF_TLS_FREE ();
 
        g_free (prof->args);
-       g_free (prof);
 }
 
 static char*
@@ -4034,7 +3698,7 @@ add_to_fd_set (fd_set *set, int fd, int *max_fd)
         * error and exiting.
         */
        if (fd >= FD_SETSIZE) {
-               fprintf (stderr, "File descriptor is out of bounds for fd_set: %d\n", fd);
+               mono_profiler_printf_err ("File descriptor is out of bounds for fd_set: %d", fd);
                exit (1);
        }
 
@@ -4047,12 +3711,10 @@ add_to_fd_set (fd_set *set, int fd, int *max_fd)
 static void *
 helper_thread (void *arg)
 {
-       MonoProfiler *prof = (MonoProfiler *) arg;
-
        mono_threads_attach_tools_thread ();
        mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler helper");
 
-       MonoProfilerThread *thread = init_thread (prof, FALSE);
+       MonoProfilerThread *thread = init_thread (FALSE);
 
        GArray *command_sockets = g_array_new (FALSE, FALSE, sizeof (int));
 
@@ -4062,8 +3724,8 @@ helper_thread (void *arg)
 
                FD_ZERO (&rfds);
 
-               add_to_fd_set (&rfds, prof->server_socket, &max_fd);
-               add_to_fd_set (&rfds, prof->pipes [0], &max_fd);
+               add_to_fd_set (&rfds, log_profiler.server_socket, &max_fd);
+               add_to_fd_set (&rfds, log_profiler.pipes [0], &max_fd);
 
                for (gint i = 0; i < command_sockets->len; i++)
                        add_to_fd_set (&rfds, g_array_index (command_sockets, int, i), &max_fd);
@@ -4075,12 +3737,12 @@ helper_thread (void *arg)
                        if (errno == EINTR)
                                continue;
 
-                       fprintf (stderr, "Error in mono-profiler-log server: %s", strerror (errno));
+                       mono_profiler_printf_err ("Could not poll in log profiler helper thread: %s", g_strerror (errno));
                        exit (1);
                }
 
-               if (!no_counters)
-                       counters_and_perfcounters_sample (prof);
+               if (ENABLED (PROFLOG_COUNTER_EVENTS))
+                       counters_and_perfcounters_sample ();
 
                buffer_lock_excl ();
 
@@ -4089,9 +3751,9 @@ helper_thread (void *arg)
                buffer_unlock_excl ();
 
                // Are we shutting down?
-               if (FD_ISSET (prof->pipes [0], &rfds)) {
+               if (FD_ISSET (log_profiler.pipes [0], &rfds)) {
                        char c;
-                       read (prof->pipes [0], &c, 1);
+                       read (log_profiler.pipes [0], &c, 1);
                        break;
                }
 
@@ -4117,15 +3779,15 @@ helper_thread (void *arg)
 
                        buf [len] = 0;
 
-                       if (!strcmp (buf, "heapshot\n") && hs_mode_ondemand) {
+                       if (log_config.hs_mode == MONO_PROFILER_HEAPSHOT_ON_DEMAND && !strcmp (buf, "heapshot\n")) {
                                // Rely on the finalization callback triggering a GC.
-                               heapshot_requested = 1;
+                               InterlockedWrite (&log_profiler.heapshot_requested, 1);
                                mono_gc_finalize_notify ();
                        }
                }
 
-               if (FD_ISSET (prof->server_socket, &rfds)) {
-                       int fd = accept (prof->server_socket, NULL, NULL);
+               if (FD_ISSET (log_profiler.server_socket, &rfds)) {
+                       int fd = accept (log_profiler.server_socket, NULL, NULL);
 
                        if (fd != -1) {
                                if (fd >= FD_SETSIZE)
@@ -4150,17 +3812,17 @@ helper_thread (void *arg)
 }
 
 static void
-start_helper_thread (MonoProfiler* prof)
+start_helper_thread (void)
 {
-       if (pipe (prof->pipes) == -1) {
-               fprintf (stderr, "Cannot create pipe: %s\n", strerror (errno));
+       if (pipe (log_profiler.pipes) == -1) {
+               mono_profiler_printf_err ("Could not create log profiler pipe: %s", g_strerror (errno));
                exit (1);
        }
 
-       prof->server_socket = socket (PF_INET, SOCK_STREAM, 0);
+       log_profiler.server_socket = socket (PF_INET, SOCK_STREAM, 0);
 
-       if (prof->server_socket == -1) {
-               fprintf (stderr, "Cannot create server socket: %s\n", strerror (errno));
+       if (log_profiler.server_socket == -1) {
+               mono_profiler_printf_err ("Could not create log profiler server socket: %s", g_strerror (errno));
                exit (1);
        }
 
@@ -4169,33 +3831,33 @@ start_helper_thread (MonoProfiler* prof)
        memset (&server_address, 0, sizeof (server_address));
        server_address.sin_family = AF_INET;
        server_address.sin_addr.s_addr = INADDR_ANY;
-       server_address.sin_port = htons (prof->command_port);
+       server_address.sin_port = htons (log_profiler.command_port);
 
-       if (bind (prof->server_socket, (struct sockaddr *) &server_address, sizeof (server_address)) == -1) {
-               fprintf (stderr, "Cannot bind server socket on port %d: %s\n", prof->command_port, strerror (errno));
-               close (prof->server_socket);
+       if (bind (log_profiler.server_socket, (struct sockaddr *) &server_address, sizeof (server_address)) == -1) {
+               mono_profiler_printf_err ("Could not bind log profiler server socket on port %d: %s", log_profiler.command_port, g_strerror (errno));
+               close (log_profiler.server_socket);
                exit (1);
        }
 
-       if (listen (prof->server_socket, 1) == -1) {
-               fprintf (stderr, "Cannot listen on server socket: %s\n", strerror (errno));
-               close (prof->server_socket);
+       if (listen (log_profiler.server_socket, 1) == -1) {
+               mono_profiler_printf_err ("Could not listen on log profiler server socket: %s", g_strerror (errno));
+               close (log_profiler.server_socket);
                exit (1);
        }
 
        socklen_t slen = sizeof (server_address);
 
-       if (getsockname (prof->server_socket, (struct sockaddr *) &server_address, &slen)) {
-               fprintf (stderr, "Could not get assigned port: %s\n", strerror (errno));
-               close (prof->server_socket);
+       if (getsockname (log_profiler.server_socket, (struct sockaddr *) &server_address, &slen)) {
+               mono_profiler_printf_err ("Could not retrieve assigned port for log profiler server socket: %s", g_strerror (errno));
+               close (log_profiler.server_socket);
                exit (1);
        }
 
-       prof->command_port = ntohs (server_address.sin_port);
+       log_profiler.command_port = ntohs (server_address.sin_port);
 
-       if (!mono_native_thread_create (&prof->helper_thread, helper_thread, prof)) {
-               fprintf (stderr, "Could not start helper thread\n");
-               close (prof->server_socket);
+       if (!mono_native_thread_create (&log_profiler.helper_thread, helper_thread, NULL)) {
+               mono_profiler_printf_err ("Could not start log profiler helper thread");
+               close (log_profiler.server_socket);
                exit (1);
        }
 }
@@ -4207,11 +3869,11 @@ free_writer_entry (gpointer p)
 }
 
 static gboolean
-handle_writer_queue_entry (MonoProfiler *prof)
+handle_writer_queue_entry (void)
 {
        WriterQueueEntry *entry;
 
-       if ((entry = (WriterQueueEntry *) mono_lock_free_queue_dequeue (&prof->writer_queue))) {
+       if ((entry = (WriterQueueEntry *) mono_lock_free_queue_dequeue (&log_profiler.writer_queue))) {
                if (!entry->methods)
                        goto no_methods;
 
@@ -4231,7 +3893,7 @@ handle_writer_queue_entry (MonoProfiler *prof)
                for (guint i = 0; i < entry->methods->len; i++) {
                        MethodInfo *info = (MethodInfo *) g_ptr_array_index (entry->methods, i);
 
-                       if (mono_conc_hashtable_lookup (prof->method_table, info->method))
+                       if (mono_conc_hashtable_lookup (log_profiler.method_table, info->method))
                                goto free_info; // This method already has metadata emitted.
 
                        /*
@@ -4244,9 +3906,9 @@ handle_writer_queue_entry (MonoProfiler *prof)
                         * method lists will just be empty for the rest of the
                         * app's lifetime.
                         */
-                       mono_os_mutex_lock (&prof->method_table_mutex);
-                       mono_conc_hashtable_insert (prof->method_table, info->method, info->method);
-                       mono_os_mutex_unlock (&prof->method_table_mutex);
+                       mono_os_mutex_lock (&log_profiler.method_table_mutex);
+                       mono_conc_hashtable_insert (log_profiler.method_table, info->method, info->method);
+                       mono_os_mutex_unlock (&log_profiler.method_table_mutex);
 
                        char *name = mono_method_full_name (info->method, 1);
                        int nlen = strlen (name) + 1;
@@ -4284,12 +3946,12 @@ handle_writer_queue_entry (MonoProfiler *prof)
                if (wrote_methods) {
                        MonoProfilerThread *thread = PROF_TLS_GET ();
 
-                       dump_buffer_threadless (prof, thread->buffer);
+                       dump_buffer_threadless (thread->buffer);
                        init_buffer_state (thread);
                }
 
        no_methods:
-               dump_buffer (prof, entry->buffer);
+               dump_buffer (entry->buffer);
 
                mono_thread_hazardous_try_free (entry, free_writer_entry);
 
@@ -4302,22 +3964,20 @@ handle_writer_queue_entry (MonoProfiler *prof)
 static void *
 writer_thread (void *arg)
 {
-       MonoProfiler *prof = (MonoProfiler *)arg;
-
        mono_threads_attach_tools_thread ();
        mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler writer");
 
-       dump_header (prof);
+       dump_header ();
 
-       MonoProfilerThread *thread = init_thread (prof, FALSE);
+       MonoProfilerThread *thread = init_thread (FALSE);
 
-       while (InterlockedRead (&prof->run_writer_thread)) {
-               mono_os_sem_wait (&prof->writer_queue_sem, MONO_SEM_FLAGS_NONE);
-               handle_writer_queue_entry (prof);
+       while (InterlockedRead (&log_profiler.run_writer_thread)) {
+               mono_os_sem_wait (&log_profiler.writer_queue_sem, MONO_SEM_FLAGS_NONE);
+               handle_writer_queue_entry ();
        }
 
        /* Drain any remaining entries on shutdown. */
-       while (handle_writer_queue_entry (prof));
+       while (handle_writer_queue_entry ());
 
        free_buffer (thread->buffer, thread->buffer->size);
        deinit_thread (thread);
@@ -4328,12 +3988,12 @@ writer_thread (void *arg)
 }
 
 static void
-start_writer_thread (MonoProfiler* prof)
+start_writer_thread (void)
 {
-       InterlockedWrite (&prof->run_writer_thread, 1);
+       InterlockedWrite (&log_profiler.run_writer_thread, 1);
 
-       if (!mono_native_thread_create (&prof->writer_thread, writer_thread, prof)) {
-               fprintf (stderr, "Could not start writer thread\n");
+       if (!mono_native_thread_create (&log_profiler.writer_thread, writer_thread, NULL)) {
+               mono_profiler_printf_err ("Could not start log profiler writer thread");
                exit (1);
        }
 }
@@ -4344,15 +4004,15 @@ reuse_sample_hit (gpointer p)
        SampleHit *sample = p;
 
        mono_lock_free_queue_node_unpoison (&sample->node);
-       mono_lock_free_queue_enqueue (&sample->prof->sample_reuse_queue, &sample->node);
+       mono_lock_free_queue_enqueue (&log_profiler.sample_reuse_queue, &sample->node);
 }
 
 static gboolean
-handle_dumper_queue_entry (MonoProfiler *prof)
+handle_dumper_queue_entry (void)
 {
        SampleHit *sample;
 
-       if ((sample = (SampleHit *) mono_lock_free_queue_dequeue (&prof->dumper_queue))) {
+       if ((sample = (SampleHit *) mono_lock_free_queue_dequeue (&log_profiler.dumper_queue))) {
                for (int i = 0; i < sample->count; ++i) {
                        MonoMethod *method = sample->frames [i].method;
                        MonoDomain *domain = sample->frames [i].domain;
@@ -4371,7 +4031,6 @@ handle_dumper_queue_entry (MonoProfiler *prof)
 
                ENTER_LOG (&sample_hits_ctr, logbuffer,
                        EVENT_SIZE /* event */ +
-                       BYTE_SIZE /* type */ +
                        LEB128_SIZE /* tid */ +
                        LEB128_SIZE /* count */ +
                        1 * (
@@ -4399,11 +4058,11 @@ handle_dumper_queue_entry (MonoProfiler *prof)
                for (int i = 0; i < sample->count; ++i)
                        emit_method (logbuffer, sample->frames [i].method);
 
-               EXIT_LOG_EXPLICIT (DO_SEND);
+               EXIT_LOG;
 
                mono_thread_hazardous_try_free (sample, reuse_sample_hit);
 
-               dump_unmanaged_coderefs (prof);
+               dump_unmanaged_coderefs ();
        }
 
        return FALSE;
@@ -4412,26 +4071,24 @@ handle_dumper_queue_entry (MonoProfiler *prof)
 static void *
 dumper_thread (void *arg)
 {
-       MonoProfiler *prof = (MonoProfiler *)arg;
-
        mono_threads_attach_tools_thread ();
        mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler dumper");
 
-       MonoProfilerThread *thread = init_thread (prof, FALSE);
+       MonoProfilerThread *thread = init_thread (FALSE);
 
-       while (InterlockedRead (&prof->run_dumper_thread)) {
+       while (InterlockedRead (&log_profiler.run_dumper_thread)) {
                /*
                 * Flush samples every second so it doesn't seem like the profiler is
                 * not working if the program is mostly idle.
                 */
-               if (mono_os_sem_timedwait (&prof->dumper_queue_sem, 1000, MONO_SEM_FLAGS_NONE) == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT)
+               if (mono_os_sem_timedwait (&log_profiler.dumper_queue_sem, 1000, MONO_SEM_FLAGS_NONE) == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT)
                        send_log_unsafe (FALSE);
 
-               handle_dumper_queue_entry (prof);
+               handle_dumper_queue_entry ();
        }
 
        /* Drain any remaining entries on shutdown. */
-       while (handle_dumper_queue_entry (prof));
+       while (handle_dumper_queue_entry ());
 
        send_log_unsafe (FALSE);
        deinit_thread (thread);
@@ -4442,12 +4099,12 @@ dumper_thread (void *arg)
 }
 
 static void
-start_dumper_thread (MonoProfiler* prof)
+start_dumper_thread (void)
 {
-       InterlockedWrite (&prof->run_dumper_thread, 1);
+       InterlockedWrite (&log_profiler.run_dumper_thread, 1);
 
-       if (!mono_native_thread_create (&prof->dumper_thread, dumper_thread, prof)) {
-               fprintf (stderr, "Could not start dumper thread\n");
+       if (!mono_native_thread_create (&log_profiler.dumper_thread, dumper_thread, NULL)) {
+               mono_profiler_printf_err ("Could not start log profiler dumper thread");
                exit (1);
        }
 }
@@ -4458,10 +4115,329 @@ register_counter (const char *name, gint32 *counter)
        mono_counters_register (name, MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, counter);
 }
 
+ICALL_EXPORT gint32
+proflog_icall_GetMaxStackTraceFrames (void)
+{
+       return MAX_FRAMES;
+}
+
+ICALL_EXPORT gint32
+proflog_icall_GetStackTraceFrames (void)
+{
+       return log_config.num_frames;
+}
+
+ICALL_EXPORT void
+proflog_icall_SetStackTraceFrames (gint32 value)
+{
+       log_config.num_frames = value;
+}
+
+ICALL_EXPORT MonoProfilerHeapshotMode
+proflog_icall_GetHeapshotMode (void)
+{
+       return log_config.hs_mode;
+}
+
+ICALL_EXPORT void
+proflog_icall_SetHeapshotMode (MonoProfilerHeapshotMode value)
+{
+       log_config.hs_mode = value;
+}
+
+ICALL_EXPORT gint32
+proflog_icall_GetHeapshotMillisecondsFrequency (void)
+{
+       return log_config.hs_freq_ms;
+}
+
+ICALL_EXPORT void
+proflog_icall_SetHeapshotMillisecondsFrequency (gint32 value)
+{
+       log_config.hs_freq_ms = value;
+}
+
+ICALL_EXPORT gint32
+proflog_icall_GetHeapshotCollectionsFrequency (void)
+{
+       return log_config.hs_freq_gc;
+}
+
+ICALL_EXPORT void
+proflog_icall_SetHeapshotCollectionsFrequency (gint32 value)
+{
+       log_config.hs_freq_gc = value;
+}
+
+ICALL_EXPORT gint32
+proflog_icall_GetCallDepth (void)
+{
+       return log_config.max_call_depth;
+}
+
+ICALL_EXPORT void
+proflog_icall_SetCallDepth (gint32 value)
+{
+       log_config.max_call_depth = value;
+}
+
+ICALL_EXPORT void
+proflog_icall_GetSampleMode (MonoProfilerSampleMode *mode, gint32 *frequency)
+{
+       uint32_t freq;
+
+       mono_profiler_get_sample_mode (log_profiler.handle, mode, &freq);
+
+       *frequency = freq;
+}
+
+ICALL_EXPORT MonoBoolean
+proflog_icall_SetSampleMode (MonoProfilerSampleMode mode, gint32 frequency)
+{
+       mono_coop_mutex_lock (&log_profiler.api_mutex);
+
+       mono_bool result = mono_profiler_set_sample_mode (log_profiler.handle, mode, frequency);
+
+       if (mode != MONO_PROFILER_SAMPLE_MODE_NONE) {
+               ENABLE (PROFLOG_SAMPLE_EVENTS);
+               mono_profiler_set_sample_hit_callback (log_profiler.handle, mono_sample_hit);
+       } else {
+               DISABLE (PROFLOG_SAMPLE_EVENTS);
+               mono_profiler_set_sample_hit_callback (log_profiler.handle, NULL);
+       }
+
+       mono_coop_mutex_unlock (&log_profiler.api_mutex);
+
+       return result;
+}
+
+ICALL_EXPORT MonoBoolean
+proflog_icall_GetExceptionEvents (void)
+{
+       return ENABLED (PROFLOG_EXCEPTION_EVENTS);
+}
+
+ICALL_EXPORT void
+proflog_icall_SetExceptionEvents (MonoBoolean value)
+{
+       mono_coop_mutex_lock (&log_profiler.api_mutex);
+
+       if (value) {
+               ENABLE (PROFLOG_EXCEPTION_EVENTS);
+               mono_profiler_set_exception_throw_callback (log_profiler.handle, throw_exc);
+               mono_profiler_set_exception_clause_callback (log_profiler.handle, clause_exc);
+       } else {
+               DISABLE (PROFLOG_EXCEPTION_EVENTS);
+               mono_profiler_set_exception_throw_callback (log_profiler.handle, NULL);
+               mono_profiler_set_exception_clause_callback (log_profiler.handle, NULL);
+       }
+
+       mono_coop_mutex_unlock (&log_profiler.api_mutex);
+}
+
+ICALL_EXPORT MonoBoolean
+proflog_icall_GetMonitorEvents (void)
+{
+       return ENABLED (PROFLOG_MONITOR_EVENTS);
+}
+
+ICALL_EXPORT void
+proflog_icall_SetMonitorEvents (MonoBoolean value)
+{
+       mono_coop_mutex_lock (&log_profiler.api_mutex);
+
+       if (value) {
+               ENABLE (PROFLOG_EXCEPTION_EVENTS);
+               mono_profiler_set_monitor_contention_callback (log_profiler.handle, monitor_contention);
+               mono_profiler_set_monitor_acquired_callback (log_profiler.handle, monitor_acquired);
+               mono_profiler_set_monitor_failed_callback (log_profiler.handle, monitor_failed);
+       } else {
+               DISABLE (PROFLOG_EXCEPTION_EVENTS);
+               mono_profiler_set_monitor_contention_callback (log_profiler.handle, NULL);
+               mono_profiler_set_monitor_acquired_callback (log_profiler.handle, NULL);
+               mono_profiler_set_monitor_failed_callback (log_profiler.handle, NULL);
+       }
+
+       mono_coop_mutex_unlock (&log_profiler.api_mutex);
+}
+
+ICALL_EXPORT MonoBoolean
+proflog_icall_GetGCEvents (void)
+{
+       return ENABLED (PROFLOG_GC_EVENTS);
+}
+
+ICALL_EXPORT void
+proflog_icall_SetGCEvents (MonoBoolean value)
+{
+       mono_coop_mutex_lock (&log_profiler.api_mutex);
+
+       if (value)
+               ENABLE (PROFLOG_GC_EVENTS);
+       else
+               DISABLE (PROFLOG_GC_EVENTS);
+
+       mono_coop_mutex_unlock (&log_profiler.api_mutex);
+}
+
+ICALL_EXPORT MonoBoolean
+proflog_icall_GetGCAllocationEvents (void)
+{
+       return ENABLED (PROFLOG_GC_ALLOCATION_EVENTS);
+}
+
+ICALL_EXPORT void
+proflog_icall_SetGCAllocationEvents (MonoBoolean value)
+{
+       mono_coop_mutex_lock (&log_profiler.api_mutex);
+
+       if (value) {
+               ENABLE (PROFLOG_GC_ALLOCATION_EVENTS);
+               mono_profiler_set_gc_allocation_callback (log_profiler.handle, gc_alloc);
+       } else {
+               DISABLE (PROFLOG_GC_ALLOCATION_EVENTS);
+               mono_profiler_set_gc_allocation_callback (log_profiler.handle, NULL);
+       }
+
+       mono_coop_mutex_unlock (&log_profiler.api_mutex);
+}
+
+ICALL_EXPORT MonoBoolean
+proflog_icall_GetGCMoveEvents (void)
+{
+       return ENABLED (PROFLOG_GC_MOVE_EVENTS);
+}
+
+ICALL_EXPORT void
+proflog_icall_SetGCMoveEvents (MonoBoolean value)
+{
+       mono_coop_mutex_lock (&log_profiler.api_mutex);
+
+       if (value) {
+               ENABLE (PROFLOG_GC_MOVE_EVENTS);
+               mono_profiler_set_gc_moves_callback (log_profiler.handle, gc_moves);
+       } else {
+               DISABLE (PROFLOG_GC_MOVE_EVENTS);
+               mono_profiler_set_gc_moves_callback (log_profiler.handle, NULL);
+       }
+
+       mono_coop_mutex_unlock (&log_profiler.api_mutex);
+}
+
+ICALL_EXPORT MonoBoolean
+proflog_icall_GetGCRootEvents (void)
+{
+       return ENABLED (PROFLOG_GC_ROOT_EVENTS);
+}
+
+ICALL_EXPORT void
+proflog_icall_SetGCRootEvents (MonoBoolean value)
+{
+       mono_coop_mutex_lock (&log_profiler.api_mutex);
+
+       if (value)
+               ENABLE (PROFLOG_GC_ROOT_EVENTS);
+       else
+               DISABLE (PROFLOG_GC_ROOT_EVENTS);
+
+       mono_coop_mutex_unlock (&log_profiler.api_mutex);
+}
+
+ICALL_EXPORT MonoBoolean
+proflog_icall_GetGCHandleEvents (void)
+{
+       return ENABLED (PROFLOG_GC_HANDLE_EVENTS);
+}
+
+ICALL_EXPORT void
+proflog_icall_SetGCHandleEvents (MonoBoolean value)
+{
+       mono_coop_mutex_lock (&log_profiler.api_mutex);
+
+       if (value) {
+               ENABLE (PROFLOG_GC_HANDLE_EVENTS);
+               mono_profiler_set_gc_handle_created_callback (log_profiler.handle, gc_handle_created);
+               mono_profiler_set_gc_handle_deleted_callback (log_profiler.handle, gc_handle_deleted);
+       } else {
+               DISABLE (PROFLOG_GC_HANDLE_EVENTS);
+               mono_profiler_set_gc_handle_created_callback (log_profiler.handle, NULL);
+               mono_profiler_set_gc_handle_deleted_callback (log_profiler.handle, NULL);
+       }
+
+       mono_coop_mutex_unlock (&log_profiler.api_mutex);
+}
+
+ICALL_EXPORT MonoBoolean
+proflog_icall_GetGCFinalizationEvents (void)
+{
+       return ENABLED (PROFLOG_GC_FINALIZATION_EVENTS);
+}
+
+ICALL_EXPORT void
+proflog_icall_SetGCFinalizationEvents (MonoBoolean value)
+{
+       mono_coop_mutex_lock (&log_profiler.api_mutex);
+
+       if (value) {
+               ENABLE (PROFLOG_GC_FINALIZATION_EVENTS);
+               mono_profiler_set_gc_finalizing_callback (log_profiler.handle, finalize_begin);
+               mono_profiler_set_gc_finalizing_object_callback (log_profiler.handle, finalize_object_begin);
+               mono_profiler_set_gc_finalized_object_callback (log_profiler.handle, finalize_object_end);
+       } else {
+               DISABLE (PROFLOG_GC_FINALIZATION_EVENTS);
+               mono_profiler_set_gc_finalizing_callback (log_profiler.handle, NULL);
+               mono_profiler_set_gc_finalizing_object_callback (log_profiler.handle, NULL);
+               mono_profiler_set_gc_finalized_object_callback (log_profiler.handle, NULL);
+       }
+
+       mono_coop_mutex_unlock (&log_profiler.api_mutex);
+}
+
+ICALL_EXPORT MonoBoolean
+proflog_icall_GetCounterEvents (void)
+{
+       return ENABLED (PROFLOG_COUNTER_EVENTS);
+}
+
+ICALL_EXPORT void
+proflog_icall_SetCounterEvents (MonoBoolean value)
+{
+       mono_coop_mutex_lock (&log_profiler.api_mutex);
+
+       if (value)
+               ENABLE (PROFLOG_COUNTER_EVENTS);
+       else
+               DISABLE (PROFLOG_COUNTER_EVENTS);
+
+       mono_coop_mutex_unlock (&log_profiler.api_mutex);
+}
+
+ICALL_EXPORT MonoBoolean
+proflog_icall_GetJitEvents (void)
+{
+       return ENABLED (PROFLOG_JIT_EVENTS);
+}
+
+ICALL_EXPORT void
+proflog_icall_SetJitEvents (MonoBoolean value)
+{
+       mono_coop_mutex_lock (&log_profiler.api_mutex);
+
+       if (value) {
+               ENABLE (PROFLOG_JIT_EVENTS);
+               mono_profiler_set_jit_code_buffer_callback (log_profiler.handle, code_buffer_new);
+       } else {
+               DISABLE (PROFLOG_JIT_EVENTS);
+               mono_profiler_set_jit_code_buffer_callback (log_profiler.handle, NULL);
+       }
+
+       mono_coop_mutex_unlock (&log_profiler.api_mutex);
+}
+
 static void
 runtime_initialized (MonoProfiler *profiler)
 {
-       InterlockedWrite (&runtime_inited, 1);
+       InterlockedWrite (&log_profiler.runtime_inited, 1);
 
        register_counter ("Sample events allocated", &sample_allocations_ctr);
        register_counter ("Log buffers allocated", &buffer_allocations_ctr);
@@ -4515,48 +4491,80 @@ runtime_initialized (MonoProfiler *profiler)
        register_counter ("Event: Coverage classes", &coverage_classes_ctr);
        register_counter ("Event: Coverage assemblies", &coverage_assemblies_ctr);
 
-       counters_init (profiler);
+       counters_init ();
 
        /*
         * We must start the helper thread before the writer thread. This is
         * because the helper thread sets up the command port which is written to
         * the log header by the writer thread.
         */
-       start_helper_thread (profiler);
-       start_writer_thread (profiler);
-       start_dumper_thread (profiler);
+       start_helper_thread ();
+       start_writer_thread ();
+       start_dumper_thread ();
+
+       mono_coop_mutex_init (&log_profiler.api_mutex);
+
+#define ADD_ICALL(NAME) \
+       mono_add_internal_call ("Mono.Profiler.Log.LogProfiler::" EGLIB_STRINGIFY (NAME), proflog_icall_ ## NAME);
+
+       ADD_ICALL (GetMaxStackTraceFrames);
+       ADD_ICALL (GetStackTraceFrames);
+       ADD_ICALL (SetStackTraceFrames);
+       ADD_ICALL (GetHeapshotMode);
+       ADD_ICALL (SetHeapshotMode);
+       ADD_ICALL (GetHeapshotMillisecondsFrequency);
+       ADD_ICALL (SetHeapshotMillisecondsFrequency);
+       ADD_ICALL (GetHeapshotCollectionsFrequency);
+       ADD_ICALL (SetHeapshotCollectionsFrequency);
+       ADD_ICALL (GetCallDepth);
+       ADD_ICALL (SetCallDepth);
+       ADD_ICALL (GetSampleMode);
+       ADD_ICALL (SetSampleMode);
+       ADD_ICALL (GetExceptionEvents);
+       ADD_ICALL (SetExceptionEvents);
+       ADD_ICALL (GetMonitorEvents);
+       ADD_ICALL (SetMonitorEvents);
+       ADD_ICALL (GetGCEvents);
+       ADD_ICALL (SetGCEvents);
+       ADD_ICALL (GetGCAllocationEvents);
+       ADD_ICALL (SetGCAllocationEvents);
+       ADD_ICALL (GetGCMoveEvents);
+       ADD_ICALL (SetGCMoveEvents);
+       ADD_ICALL (GetGCRootEvents);
+       ADD_ICALL (SetGCRootEvents);
+       ADD_ICALL (GetGCHandleEvents);
+       ADD_ICALL (SetGCHandleEvents);
+       ADD_ICALL (GetGCFinalizationEvents);
+       ADD_ICALL (SetGCFinalizationEvents);
+       ADD_ICALL (GetCounterEvents);
+       ADD_ICALL (SetCounterEvents);
+       ADD_ICALL (GetJitEvents);
+       ADD_ICALL (SetJitEvents);
+
+#undef ADD_ICALL
 }
 
 static void
 create_profiler (const char *args, const char *filename, GPtrArray *filters)
 {
        char *nf;
-       int force_delete = 0;
 
-       log_profiler = (MonoProfiler *) g_calloc (1, sizeof (MonoProfiler));
-       log_profiler->args = pstrdup (args);
-       log_profiler->command_port = command_port;
-
-       if (filename && *filename == '-') {
-               force_delete = 1;
-               filename++;
-               g_warning ("WARNING: the output:-FILENAME option is deprecated, the profiler now always overrides the output file\n");
-       }
+       log_profiler.args = pstrdup (args);
+       log_profiler.command_port = log_config.command_port;
 
        //If filename begin with +, append the pid at the end
        if (filename && *filename == '+')
                filename = g_strdup_printf ("%s.%d", filename + 1, getpid ());
 
-
        if (!filename) {
-               if (do_report)
+               if (log_config.do_report)
                        filename = "|mprof-report -";
                else
                        filename = "output.mlpd";
                nf = (char*)filename;
        } else {
                nf = new_filename (filename);
-               if (do_report) {
+               if (log_config.do_report) {
                        int s = strlen (nf) + 32;
                        char *p = (char *) g_malloc (s);
                        snprintf (p, s, "|mprof-report '--out=%s' -", nf);
@@ -4565,24 +4573,22 @@ create_profiler (const char *args, const char *filename, GPtrArray *filters)
                }
        }
        if (*nf == '|') {
-               log_profiler->file = popen (nf + 1, "w");
-               log_profiler->pipe_output = 1;
+               log_profiler.file = popen (nf + 1, "w");
+               log_profiler.pipe_output = 1;
        } else if (*nf == '#') {
                int fd = strtol (nf + 1, NULL, 10);
-               log_profiler->file = fdopen (fd, "a");
-       } else {
-               if (force_delete)
-                       unlink (nf);
-               log_profiler->file = fopen (nf, "wb");
-       }
-       if (!log_profiler->file) {
-               fprintf (stderr, "Cannot create profiler output: %s\n", nf);
+               log_profiler.file = fdopen (fd, "a");
+       } else
+               log_profiler.file = fopen (nf, "wb");
+
+       if (!log_profiler.file) {
+               mono_profiler_printf_err ("Could not create log profiler output file '%s'.", nf);
                exit (1);
        }
 
 #if defined (HAVE_SYS_ZLIB)
-       if (use_zip)
-               log_profiler->gzfile = gzdopen (fileno (log_profiler->file), "wb");
+       if (log_config.use_zip)
+               log_profiler.gzfile = gzdopen (fileno (log_profiler.file), "wb");
 #endif
 
        /*
@@ -4592,31 +4598,32 @@ create_profiler (const char *args, const char *filename, GPtrArray *filters)
        g_assert (SAMPLE_SLOT_SIZE (MAX_FRAMES) * 2 < LOCK_FREE_ALLOC_SB_USABLE_SIZE (SAMPLE_BLOCK_SIZE));
 
        // FIXME: We should free this stuff too.
-       mono_lock_free_allocator_init_size_class (&log_profiler->sample_size_class, SAMPLE_SLOT_SIZE (num_frames), SAMPLE_BLOCK_SIZE);
-       mono_lock_free_allocator_init_allocator (&log_profiler->sample_allocator, &log_profiler->sample_size_class, MONO_MEM_ACCOUNT_PROFILER);
+       mono_lock_free_allocator_init_size_class (&log_profiler.sample_size_class, SAMPLE_SLOT_SIZE (log_config.num_frames), SAMPLE_BLOCK_SIZE);
+       mono_lock_free_allocator_init_allocator (&log_profiler.sample_allocator, &log_profiler.sample_size_class, MONO_MEM_ACCOUNT_PROFILER);
 
-       mono_lock_free_queue_init (&log_profiler->sample_reuse_queue);
+       mono_lock_free_queue_init (&log_profiler.sample_reuse_queue);
 
        g_assert (sizeof (WriterQueueEntry) * 2 < LOCK_FREE_ALLOC_SB_USABLE_SIZE (WRITER_ENTRY_BLOCK_SIZE));
 
        // FIXME: We should free this stuff too.
-       mono_lock_free_allocator_init_size_class (&log_profiler->writer_entry_size_class, sizeof (WriterQueueEntry), WRITER_ENTRY_BLOCK_SIZE);
-       mono_lock_free_allocator_init_allocator (&log_profiler->writer_entry_allocator, &log_profiler->writer_entry_size_class, MONO_MEM_ACCOUNT_PROFILER);
+       mono_lock_free_allocator_init_size_class (&log_profiler.writer_entry_size_class, sizeof (WriterQueueEntry), WRITER_ENTRY_BLOCK_SIZE);
+       mono_lock_free_allocator_init_allocator (&log_profiler.writer_entry_allocator, &log_profiler.writer_entry_size_class, MONO_MEM_ACCOUNT_PROFILER);
+
+       mono_lock_free_queue_init (&log_profiler.writer_queue);
+       mono_os_sem_init (&log_profiler.writer_queue_sem, 0);
 
-       mono_lock_free_queue_init (&log_profiler->writer_queue);
-       mono_os_sem_init (&log_profiler->writer_queue_sem, 0);
+       mono_lock_free_queue_init (&log_profiler.dumper_queue);
+       mono_os_sem_init (&log_profiler.dumper_queue_sem, 0);
 
-       mono_lock_free_queue_init (&log_profiler->dumper_queue);
-       mono_os_sem_init (&log_profiler->dumper_queue_sem, 0);
+       mono_os_mutex_init (&log_profiler.method_table_mutex);
+       log_profiler.method_table = mono_conc_hashtable_new (NULL, NULL);
 
-       mono_os_mutex_init (&log_profiler->method_table_mutex);
-       log_profiler->method_table = mono_conc_hashtable_new (NULL, NULL);
+       if (log_config.collect_coverage)
+               coverage_init ();
 
-       if (do_coverage)
-               coverage_init (log_profiler);
-       log_profiler->coverage_filters = filters;
+       log_profiler.coverage_filters = filters;
 
-       log_profiler->startup_time = current_time ();
+       log_profiler.startup_time = current_time ();
 }
 
 /*
@@ -4644,32 +4651,13 @@ mono_profiler_init (const char *desc)
 {
        GPtrArray *filters = NULL;
 
-       proflog_parse_args (&config, desc [3] == ':' ? desc + 4 : "");
-
-       //XXX maybe later cleanup to use config directly
-       nocalls = !(config.effective_mask & PROFLOG_CALL_EVENTS);
-       no_counters = !(config.effective_mask & PROFLOG_COUNTER_EVENTS);
-       do_report = config.do_report;
-       do_debug = config.do_debug;
-       do_heap_shot = (config.effective_mask & PROFLOG_HEAPSHOT_FEATURE);
-       hs_mode_ondemand = config.hs_mode_ondemand;
-       hs_mode_ms = config.hs_mode_ms;
-       hs_mode_gc = config.hs_mode_gc;
-       do_mono_sample = (config.effective_mask & PROFLOG_SAMPLING_FEATURE);
-       use_zip = config.use_zip;
-       command_port = config.command_port;
-       num_frames = config.num_frames;
-       notraces = config.notraces;
-       max_allocated_sample_hits = config.max_allocated_sample_hits;
-       max_call_depth = config.max_call_depth;
-       do_coverage = (config.effective_mask & PROFLOG_CODE_COV_FEATURE);
-       debug_coverage = config.debug_coverage;
-
-       if (config.cov_filter_files) {
+       proflog_parse_args (&log_config, desc [3] == ':' ? desc + 4 : "");
+
+       if (log_config.cov_filter_files) {
                filters = g_ptr_array_new ();
                int i;
-               for (i = 0; i < config.cov_filter_files->len; ++i) {
-                       const char *name = config.cov_filter_files->pdata [i];
+               for (i = 0; i < log_config.cov_filter_files->len; ++i) {
+                       const char *name = log_config.cov_filter_files->pdata [i];
                        parse_cov_filter_file (filters, name);
                }
        }
@@ -4678,111 +4666,106 @@ mono_profiler_init (const char *desc)
 
        PROF_TLS_INIT ();
 
-       create_profiler (desc, config.output_filename, filters);
+       create_profiler (desc, log_config.output_filename, filters);
 
-       mono_lls_init (&profiler_thread_list, NULL);
+       mono_lls_init (&log_profiler.profiler_thread_list, NULL);
 
-       MonoProfilerHandle handle = log_profiler->handle = mono_profiler_install (log_profiler);
+       MonoProfilerHandle handle = log_profiler.handle = mono_profiler_install (&log_profiler);
 
-       //Required callbacks
+       /*
+        * Required callbacks. These are either necessary for the profiler itself
+        * to function, or provide metadata that's needed if other events (e.g.
+        * allocations, exceptions) are dynamically enabled/disabled.
+        */
+
+       mono_profiler_set_runtime_shutdown_begin_callback (handle, log_early_shutdown);
        mono_profiler_set_runtime_shutdown_end_callback (handle, log_shutdown);
        mono_profiler_set_runtime_initialized_callback (handle, runtime_initialized);
 
        mono_profiler_set_gc_event_callback (handle, gc_event);
-       mono_profiler_set_gc_resize_callback (handle, gc_resize);
+
        mono_profiler_set_thread_started_callback (handle, thread_start);
        mono_profiler_set_thread_stopped_callback (handle, thread_end);
-
-       //It's questionable whether we actually want this to be mandatory, maybe put it behind the actual event?
        mono_profiler_set_thread_name_callback (handle, thread_name);
 
-       if (config.effective_mask & PROFLOG_DOMAIN_EVENTS) {
-               mono_profiler_set_domain_loaded_callback (handle, domain_loaded);
-               mono_profiler_set_domain_unloading_callback (handle, domain_unloaded);
-               mono_profiler_set_domain_name_callback (handle, domain_name);
-       }
+       mono_profiler_set_domain_loaded_callback (handle, domain_loaded);
+       mono_profiler_set_domain_unloading_callback (handle, domain_unloaded);
+       mono_profiler_set_domain_name_callback (handle, domain_name);
 
-       if (config.effective_mask & PROFLOG_ASSEMBLY_EVENTS) {
-               mono_profiler_set_assembly_loaded_callback (handle, assembly_loaded);
-               mono_profiler_set_assembly_unloading_callback (handle, assembly_unloaded);
-       }
+       mono_profiler_set_context_loaded_callback (handle, context_loaded);
+       mono_profiler_set_context_unloaded_callback (handle, context_unloaded);
 
-       if (config.effective_mask & PROFLOG_MODULE_EVENTS) {
-               mono_profiler_set_image_loaded_callback (handle, image_loaded);
-               mono_profiler_set_image_unloading_callback (handle, image_unloaded);
-       }
+       mono_profiler_set_assembly_loaded_callback (handle, assembly_loaded);
+       mono_profiler_set_assembly_unloading_callback (handle, assembly_unloaded);
 
-       if (config.effective_mask & PROFLOG_CLASS_EVENTS)
-               mono_profiler_set_class_loaded_callback (handle, class_loaded);
+       mono_profiler_set_image_loaded_callback (handle, image_loaded);
+       mono_profiler_set_image_unloading_callback (handle, image_unloaded);
 
-       if (config.effective_mask & PROFLOG_JIT_COMPILATION_EVENTS) {
-               mono_profiler_set_jit_done_callback (handle, method_jitted);
-               mono_profiler_set_jit_code_buffer_callback (handle, code_buffer_new);
-       }
+       mono_profiler_set_class_loaded_callback (handle, class_loaded);
 
-       if (config.effective_mask & PROFLOG_EXCEPTION_EVENTS) {
+       mono_profiler_set_jit_done_callback (handle, method_jitted);
+
+       if (ENABLED (PROFLOG_EXCEPTION_EVENTS)) {
                mono_profiler_set_exception_throw_callback (handle, throw_exc);
                mono_profiler_set_exception_clause_callback (handle, clause_exc);
        }
 
-       if (config.effective_mask & PROFLOG_ALLOCATION_EVENTS) {
-               mono_profiler_enable_allocations ();
-               mono_profiler_set_gc_allocation_callback (handle, gc_alloc);
-       }
-
-       //PROFLOG_GC_EVENTS is mandatory
-       //PROFLOG_THREAD_EVENTS is mandatory
-
-       if (config.effective_mask & PROFLOG_CALL_EVENTS) {
-               mono_profiler_set_call_instrumentation_filter_callback (handle, method_filter);
-               mono_profiler_set_method_enter_callback (handle, method_enter);
-               mono_profiler_set_method_leave_callback (handle, method_leave);
-               mono_profiler_set_method_exception_leave_callback (handle, method_exc_leave);
-       }
-
-       if (config.effective_mask & PROFLOG_INS_COVERAGE_EVENTS)
-               mono_profiler_set_coverage_filter_callback (handle, coverage_filter);
-
-       if (config.effective_mask & PROFLOG_SAMPLING_EVENTS) {
-               mono_profiler_enable_sampling (handle);
-
-               if (!mono_profiler_set_sample_mode (handle, config.sampling_mode, config.sample_freq))
-                       g_warning ("Another profiler controls sampling parameters; the log profiler will not be able to modify them");
-
-               mono_profiler_set_sample_hit_callback (handle, mono_sample_hit);
-       }
-
-       if (config.effective_mask & PROFLOG_MONITOR_EVENTS) {
+       if (ENABLED (PROFLOG_MONITOR_EVENTS)) {
                mono_profiler_set_monitor_contention_callback (handle, monitor_contention);
                mono_profiler_set_monitor_acquired_callback (handle, monitor_acquired);
                mono_profiler_set_monitor_failed_callback (handle, monitor_failed);
        }
 
-       if (config.effective_mask & PROFLOG_GC_MOVES_EVENTS)
+       if (ENABLED (PROFLOG_GC_EVENTS))
+               mono_profiler_set_gc_resize_callback (handle, gc_resize);
+
+       if (ENABLED (PROFLOG_GC_ALLOCATION_EVENTS))
+               mono_profiler_set_gc_allocation_callback (handle, gc_alloc);
+
+       if (ENABLED (PROFLOG_GC_MOVE_EVENTS))
                mono_profiler_set_gc_moves_callback (handle, gc_moves);
 
-       if (config.effective_mask & PROFLOG_GC_ROOT_EVENTS)
+       if (ENABLED (PROFLOG_GC_ROOT_EVENTS))
                mono_profiler_set_gc_roots_callback (handle, gc_roots);
 
-       if (config.effective_mask & PROFLOG_CONTEXT_EVENTS) {
-               mono_profiler_set_context_loaded_callback (handle, context_loaded);
-               mono_profiler_set_context_unloaded_callback (handle, context_unloaded);
+       if (ENABLED (PROFLOG_GC_HANDLE_EVENTS)) {
+               mono_profiler_set_gc_handle_created_callback (handle, gc_handle_created);
+               mono_profiler_set_gc_handle_deleted_callback (handle, gc_handle_deleted);
        }
 
-       if (config.effective_mask & PROFLOG_FINALIZATION_EVENTS) {
+       if (ENABLED (PROFLOG_GC_FINALIZATION_EVENTS)) {
                mono_profiler_set_gc_finalizing_callback (handle, finalize_begin);
                mono_profiler_set_gc_finalized_callback (handle, finalize_end);
                mono_profiler_set_gc_finalizing_object_callback (handle, finalize_object_begin);
-               mono_profiler_set_gc_finalized_object_callback (handle, finalize_object_end);
-       } else if (ENABLED (PROFLOG_HEAPSHOT_FEATURE) && config.hs_mode_ondemand) {
-               //On Demand heapshot uses the finalizer thread to force a collection and thus a heapshot
-               mono_profiler_set_gc_finalized_callback (handle, finalize_end);
        }
 
-       //PROFLOG_COUNTER_EVENTS is a pseudo event controled by the no_counters global var
+       //On Demand heapshot uses the finalizer thread to force a collection and thus a heapshot
+       mono_profiler_set_gc_finalized_callback (handle, finalize_end);
 
-       if (config.effective_mask & PROFLOG_GC_HANDLE_EVENTS) {
-               mono_profiler_set_gc_handle_created_callback (handle, gc_handle_created);
-               mono_profiler_set_gc_handle_deleted_callback (handle, gc_handle_deleted);
+       if (ENABLED (PROFLOG_SAMPLE_EVENTS))
+               mono_profiler_set_sample_hit_callback (handle, mono_sample_hit);
+
+       if (ENABLED (PROFLOG_JIT_EVENTS))
+               mono_profiler_set_jit_code_buffer_callback (handle, code_buffer_new);
+
+       if (log_config.enter_leave) {
+               mono_profiler_set_call_instrumentation_filter_callback (handle, method_filter);
+               mono_profiler_set_method_enter_callback (handle, method_enter);
+               mono_profiler_set_method_leave_callback (handle, method_leave);
+               mono_profiler_set_method_exception_leave_callback (handle, method_exc_leave);
        }
+
+       if (log_config.collect_coverage)
+               mono_profiler_set_coverage_filter_callback (handle, coverage_filter);
+
+       mono_profiler_enable_allocations ();
+       mono_profiler_enable_sampling (handle);
+
+       /*
+        * If no sample option was given by the user, this just leaves the sampling
+        * thread in idle mode. We do this even if no option was given so that we
+        * can warn if another profiler controls sampling parameters.
+        */
+       if (!mono_profiler_set_sample_mode (handle, log_config.sampling_mode, log_config.sample_freq))
+               mono_profiler_printf_err ("Another profiler controls sampling parameters; the log profiler will not be able to modify them.");
 }
index ecbe3ab219795d6d9844b219633dc30b9d93335c..d8182d90ee27dfc7d3b266e31124bd7f3dae2baa 100644 (file)
@@ -2,6 +2,7 @@
 #define __MONO_PROFLOG_H__
 
 #include <glib.h>
+#define MONO_PROFILER_UNSTABLE_GC_ROOTS
 #include <mono/metadata/profiler.h>
 
 #define BUF_ID 0x4D504C01
                added an exception object field to TYPE_CLAUSE
                class unload events no longer exist (they were never emitted)
                removed type field from TYPE_SAMPLE_HIT
+               removed MONO_GC_EVENT_{MARK,RECLAIM}_{START,END}
+ */
+
+/*
+ * file format:
+ * [header] [buffer]*
+ *
+ * The file is composed by a header followed by 0 or more buffers.
+ * Each buffer contains events that happened on a thread: for a given thread
+ * buffers that appear later in the file are guaranteed to contain events
+ * that happened later in time. Buffers from separate threads could be interleaved,
+ * though.
+ * Buffers are not required to be aligned.
+ *
+ * header format:
+ * [id: 4 bytes] constant value: LOG_HEADER_ID
+ * [major: 1 byte] [minor: 1 byte] major and minor version of the log profiler
+ * [format: 1 byte] version of the data format for the rest of the file
+ * [ptrsize: 1 byte] size in bytes of a pointer in the profiled program
+ * [startup time: 8 bytes] time in milliseconds since the unix epoch when the program started
+ * [timer overhead: 4 bytes] approximate overhead in nanoseconds of the timer
+ * [flags: 4 bytes] file format flags, should be 0 for now
+ * [pid: 4 bytes] pid of the profiled process
+ * [port: 2 bytes] tcp port for server if != 0
+ * [args size: 4 bytes] size of args
+ * [args: string] arguments passed to the profiler
+ * [arch size: 4 bytes] size of arch
+ * [arch: string] architecture the profiler is running on
+ * [os size: 4 bytes] size of os
+ * [os: string] operating system the profiler is running on
+ *
+ * The multiple byte integers are in little-endian format.
+ *
+ * buffer format:
+ * [buffer header] [event]*
+ * Buffers have a fixed-size header followed by 0 or more bytes of event data.
+ * Timing information and other values in the event data are usually stored
+ * as uleb128 or sleb128 integers. To save space, as noted for each item below,
+ * some data is represented as a difference between the actual value and
+ * either the last value of the same type (like for timing information) or
+ * as the difference from a value stored in a buffer header.
+ *
+ * For timing information the data is stored as uleb128, since timing
+ * increases in a monotonic way in each thread: the value is the number of
+ * nanoseconds to add to the last seen timing data in a buffer. The first value
+ * in a buffer will be calculated from the time_base field in the buffer head.
+ *
+ * Object or heap sizes are stored as uleb128.
+ * Pointer differences are stored as sleb128, instead.
+ *
+ * If an unexpected value is found, the rest of the buffer should be ignored,
+ * as generally the later values need the former to be interpreted correctly.
+ *
+ * buffer header format:
+ * [bufid: 4 bytes] constant value: BUF_ID
+ * [len: 4 bytes] size of the data following the buffer header
+ * [time_base: 8 bytes] time base in nanoseconds since an unspecified epoch
+ * [ptr_base: 8 bytes] base value for pointers
+ * [obj_base: 8 bytes] base value for object addresses
+ * [thread id: 8 bytes] system-specific thread ID (pthread_t for example)
+ * [method_base: 8 bytes] base value for MonoMethod pointers
+ *
+ * event format:
+ * [extended info: upper 4 bits] [type: lower 4 bits]
+ * [time diff: uleb128] nanoseconds since last timing
+ * [data]*
+ * The data that follows depends on type and the extended info.
+ * Type is one of the enum values in mono-profiler-log.h: TYPE_ALLOC, TYPE_GC,
+ * TYPE_METADATA, TYPE_METHOD, TYPE_EXCEPTION, TYPE_MONITOR, TYPE_HEAP.
+ * The extended info bits are interpreted based on type, see
+ * each individual event description below.
+ * strings are represented as a 0-terminated utf8 sequence.
+ *
+ * backtrace format:
+ * [num: uleb128] number of frames following
+ * [frame: sleb128]* mum MonoMethod* as a pointer difference from the last such
+ * pointer or the buffer method_base
+ *
+ * type alloc format:
+ * type: TYPE_ALLOC
+ * exinfo: zero or TYPE_ALLOC_BT
+ * [ptr: sleb128] class as a byte difference from ptr_base
+ * [obj: sleb128] object address as a byte difference from obj_base
+ * [size: uleb128] size of the object in the heap
+ * If exinfo == TYPE_ALLOC_BT, a backtrace follows.
+ *
+ * type GC format:
+ * type: TYPE_GC
+ * exinfo: one of TYPE_GC_EVENT, TYPE_GC_RESIZE, TYPE_GC_MOVE, TYPE_GC_HANDLE_CREATED[_BT],
+ * TYPE_GC_HANDLE_DESTROYED[_BT], TYPE_GC_FINALIZE_START, TYPE_GC_FINALIZE_END,
+ * TYPE_GC_FINALIZE_OBJECT_START, TYPE_GC_FINALIZE_OBJECT_END
+ * if exinfo == TYPE_GC_RESIZE
+ *     [heap_size: uleb128] new heap size
+ * if exinfo == TYPE_GC_EVENT
+ *     [event type: byte] GC event (MONO_GC_EVENT_* from profiler.h)
+ *     [generation: byte] GC generation event refers to
+ * if exinfo == TYPE_GC_MOVE
+ *     [num_objects: uleb128] number of object moves that follow
+ *     [objaddr: sleb128]+ num_objects object pointer differences from obj_base
+ *     num is always an even number: the even items are the old
+ *     addresses, the odd numbers are the respective new object addresses
+ * if exinfo == TYPE_GC_HANDLE_CREATED[_BT]
+ *     [handle_type: uleb128] MonoGCHandleType enum value
+ *     upper bits reserved as flags
+ *     [handle: uleb128] GC handle value
+ *     [objaddr: sleb128] object pointer differences from obj_base
+ *     If exinfo == TYPE_GC_HANDLE_CREATED_BT, a backtrace follows.
+ * if exinfo == TYPE_GC_HANDLE_DESTROYED[_BT]
+ *     [handle_type: uleb128] MonoGCHandleType enum value
+ *     upper bits reserved as flags
+ *     [handle: uleb128] GC handle value
+ *     If exinfo == TYPE_GC_HANDLE_DESTROYED_BT, a backtrace follows.
+ * if exinfo == TYPE_GC_FINALIZE_OBJECT_{START,END}
+ *     [object: sleb128] the object as a difference from obj_base
+ *
+ * type metadata format:
+ * type: TYPE_METADATA
+ * exinfo: one of: TYPE_END_LOAD, TYPE_END_UNLOAD (optional for TYPE_THREAD and TYPE_DOMAIN,
+ * doesn't occur for TYPE_CLASS)
+ * [mtype: byte] metadata type, one of: TYPE_CLASS, TYPE_IMAGE, TYPE_ASSEMBLY, TYPE_DOMAIN,
+ * TYPE_THREAD, TYPE_CONTEXT
+ * [pointer: sleb128] pointer of the metadata type depending on mtype
+ * if mtype == TYPE_CLASS
+ *     [image: sleb128] MonoImage* as a pointer difference from ptr_base
+ *     [name: string] full class name
+ * if mtype == TYPE_IMAGE
+ *     [name: string] image file name
+ * if mtype == TYPE_ASSEMBLY
+ *     [image: sleb128] MonoImage* as a pointer difference from ptr_base
+ *     [name: string] assembly name
+ * if mtype == TYPE_DOMAIN && exinfo == 0
+ *     [name: string] domain friendly name
+ * if mtype == TYPE_CONTEXT
+ *     [domain: sleb128] domain id as pointer
+ * if mtype == TYPE_THREAD && exinfo == 0
+ *     [name: string] thread name
+ *
+ * type method format:
+ * type: TYPE_METHOD
+ * exinfo: one of: TYPE_LEAVE, TYPE_ENTER, TYPE_EXC_LEAVE, TYPE_JIT
+ * [method: sleb128] MonoMethod* as a pointer difference from the last such
+ * pointer or the buffer method_base
+ * if exinfo == TYPE_JIT
+ *     [code address: sleb128] pointer to the native code as a diff from ptr_base
+ *     [code size: uleb128] size of the generated code
+ *     [name: string] full method name
+ *
+ * type exception format:
+ * type: TYPE_EXCEPTION
+ * exinfo: zero, TYPE_CLAUSE, or TYPE_THROW_BT
+ * if exinfo == TYPE_CLAUSE
+ *     [clause type: byte] MonoExceptionEnum enum value
+ *     [clause index: uleb128] index of the current clause
+ *     [method: sleb128] MonoMethod* as a pointer difference from the last such
+ *     pointer or the buffer method_base
+ *     [object: sleb128] the exception object as a difference from obj_base
+ * else
+ *     [object: sleb128] the exception object as a difference from obj_base
+ *     If exinfo == TYPE_THROW_BT, a backtrace follows.
+ *
+ * type runtime format:
+ * type: TYPE_RUNTIME
+ * exinfo: one of: TYPE_JITHELPER
+ * if exinfo == TYPE_JITHELPER
+ *     [type: byte] MonoProfilerCodeBufferType enum value
+ *     [buffer address: sleb128] pointer to the native code as a diff from ptr_base
+ *     [buffer size: uleb128] size of the generated code
+ *     if type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE
+ *             [name: string] buffer description name
+ *
+ * type monitor format:
+ * type: TYPE_MONITOR
+ * exinfo: zero or TYPE_MONITOR_BT
+ * [type: byte] MonoProfilerMonitorEvent enum value
+ * [object: sleb128] the lock object as a difference from obj_base
+ * If exinfo == TYPE_MONITOR_BT, a backtrace follows.
+ *
+ * type heap format
+ * type: TYPE_HEAP
+ * exinfo: one of TYPE_HEAP_START, TYPE_HEAP_END, TYPE_HEAP_OBJECT, TYPE_HEAP_ROOT
+ * if exinfo == TYPE_HEAP_OBJECT
+ *     [object: sleb128] the object as a difference from obj_base
+ *     [class: sleb128] the object MonoClass* as a difference from ptr_base
+ *     [size: uleb128] size of the object on the heap
+ *     [num_refs: uleb128] number of object references
+ *     each referenced objref is preceded by a uleb128 encoded offset: the
+ *     first offset is from the object address and each next offset is relative
+ *     to the previous one
+ *     [objrefs: sleb128]+ object referenced as a difference from obj_base
+ *     The same object can appear multiple times, but only the first time
+ *     with size != 0: in the other cases this data will only be used to
+ *     provide additional referenced objects.
+ * if exinfo == TYPE_HEAP_ROOT
+ *     [num_roots: uleb128] number of root references
+ *     [num_gc: uleb128] number of major gcs
+ *     [object: sleb128] the object as a difference from obj_base
+ *     [root_type: byte] the root_type: MonoProfileGCRootType (profiler.h)
+ *     [extra_info: uleb128] the extra_info value
+ *     object, root_type and extra_info are repeated num_roots times
+ *
+ * type sample format
+ * type: TYPE_SAMPLE
+ * exinfo: one of TYPE_SAMPLE_HIT, TYPE_SAMPLE_USYM, TYPE_SAMPLE_UBIN, TYPE_SAMPLE_COUNTERS_DESC, TYPE_SAMPLE_COUNTERS
+ * if exinfo == TYPE_SAMPLE_HIT
+ *     [thread: sleb128] thread id as difference from ptr_base
+ *     [count: uleb128] number of following instruction addresses
+ *     [ip: sleb128]* instruction pointer as difference from ptr_base
+ *     [mbt_count: uleb128] number of managed backtrace frames
+ *     [method: sleb128]* MonoMethod* as a pointer difference from the last such
+ *     pointer or the buffer method_base (the first such method can be also indentified by ip, but this is not neccessarily true)
+ * if exinfo == TYPE_SAMPLE_USYM
+ *     [address: sleb128] symbol address as a difference from ptr_base
+ *     [size: uleb128] symbol size (may be 0 if unknown)
+ *     [name: string] symbol name
+ * if exinfo == TYPE_SAMPLE_UBIN
+ *     [address: sleb128] address where binary has been loaded as a difference from ptr_base
+ *     [offset: uleb128] file offset of mapping (the same file can be mapped multiple times)
+ *     [size: uleb128] memory size
+ *     [name: string] binary name
+ * if exinfo == TYPE_SAMPLE_COUNTERS_DESC
+ *     [len: uleb128] number of counters
+ *     for i = 0 to len
+ *             [section: uleb128] section of counter
+ *             if section == MONO_COUNTER_PERFCOUNTERS:
+ *                     [section_name: string] section name of counter
+ *             [name: string] name of counter
+ *             [type: byte] type of counter
+ *             [unit: byte] unit of counter
+ *             [variance: byte] variance of counter
+ *             [index: uleb128] unique index of counter
+ * if exinfo == TYPE_SAMPLE_COUNTERS
+ *     while true:
+ *             [index: uleb128] unique index of counter
+ *             if index == 0:
+ *                     break
+ *             [type: byte] type of counter value
+ *             if type == string:
+ *                     if value == null:
+ *                             [0: byte] 0 -> value is null
+ *                     else:
+ *                             [1: byte] 1 -> value is not null
+ *                             [value: string] counter value
+ *             else:
+ *                     [value: uleb128/sleb128/double] counter value, can be sleb128, uleb128 or double (determined by using type)
+ *
+ * type coverage format
+ * type: TYPE_COVERAGE
+ * exinfo: one of TYPE_COVERAGE_METHOD, TYPE_COVERAGE_STATEMENT, TYPE_COVERAGE_ASSEMBLY, TYPE_COVERAGE_CLASS
+ * if exinfo == TYPE_COVERAGE_METHOD
+ *  [assembly: string] name of assembly
+ *  [class: string] name of the class
+ *  [name: string] name of the method
+ *  [signature: string] the signature of the method
+ *  [filename: string] the file path of the file that contains this method
+ *  [token: uleb128] the method token
+ *  [method_id: uleb128] an ID for this data to associate with the buffers of TYPE_COVERAGE_STATEMENTS
+ *  [len: uleb128] the number of TYPE_COVERAGE_BUFFERS associated with this method
+ * if exinfo == TYPE_COVERAGE_STATEMENTS
+ *  [method_id: uleb128] an the TYPE_COVERAGE_METHOD buffer to associate this with
+ *  [offset: uleb128] the il offset relative to the previous offset
+ *  [counter: uleb128] the counter for this instruction
+ *  [line: uleb128] the line of filename containing this instruction
+ *  [column: uleb128] the column containing this instruction
+ * if exinfo == TYPE_COVERAGE_ASSEMBLY
+ *  [name: string] assembly name
+ *  [guid: string] assembly GUID
+ *  [filename: string] assembly filename
+ *  [number_of_methods: uleb128] the number of methods in this assembly
+ *  [fully_covered: uleb128] the number of fully covered methods
+ *  [partially_covered: uleb128] the number of partially covered methods
+ *    currently partially_covered will always be 0, and fully_covered is the
+ *    number of methods that are fully and partially covered.
+ * if exinfo == TYPE_COVERAGE_CLASS
+ *  [name: string] assembly name
+ *  [class: string] class name
+ *  [number_of_methods: uleb128] the number of methods in this class
+ *  [fully_covered: uleb128] the number of fully covered methods
+ *  [partially_covered: uleb128] the number of partially covered methods
+ *    currently partially_covered will always be 0, and fully_covered is the
+ *    number of methods that are fully and partially covered.
+ *
+ * type meta format:
+ * type: TYPE_META
+ * exinfo: one of: TYPE_SYNC_POINT
+ * if exinfo == TYPE_SYNC_POINT
+ *     [type: byte] MonoProfilerSyncPointType enum value
  */
 
 enum {
@@ -132,7 +419,6 @@ enum {
        TYPE_COVERAGE_CLASS = 3 << 4,
        /* extended type for TYPE_META */
        TYPE_SYNC_POINT = 0 << 4,
-       TYPE_END
 };
 
 enum {
@@ -146,9 +432,9 @@ enum {
 };
 
 typedef enum {
-       SYNC_POINT_PERIODIC,
-       SYNC_POINT_WORLD_STOP,
-       SYNC_POINT_WORLD_START
+       SYNC_POINT_PERIODIC = 0,
+       SYNC_POINT_WORLD_STOP = 1,
+       SYNC_POINT_WORLD_START = 2,
 } MonoProfilerSyncPointType;
 
 typedef enum {
@@ -158,95 +444,82 @@ typedef enum {
 } MonoProfilerMonitorEvent;
 
 enum {
-       MONO_PROFILER_GC_HANDLE_CREATED,
-       MONO_PROFILER_GC_HANDLE_DESTROYED,
+       MONO_PROFILER_GC_HANDLE_CREATED = 0,
+       MONO_PROFILER_GC_HANDLE_DESTROYED = 1,
 };
 
+typedef enum {
+       MONO_PROFILER_HEAPSHOT_NONE = 0,
+       MONO_PROFILER_HEAPSHOT_MAJOR = 1,
+       MONO_PROFILER_HEAPSHOT_ON_DEMAND = 2,
+       MONO_PROFILER_HEAPSHOT_X_GC = 3,
+       MONO_PROFILER_HEAPSHOT_X_MS = 4,
+} MonoProfilerHeapshotMode;
+
 // If you alter MAX_FRAMES, you may need to alter SAMPLE_BLOCK_SIZE too.
 #define MAX_FRAMES 32
 
 //The following flags control emitting individual events
-#define PROFLOG_DOMAIN_EVENTS (1 << 0)
-#define PROFLOG_ASSEMBLY_EVENTS        (1 << 1)
-#define PROFLOG_MODULE_EVENTS (1 << 2)
-#define PROFLOG_CLASS_EVENTS (1 << 3)
-#define PROFLOG_JIT_COMPILATION_EVENTS (1 << 4)
-#define PROFLOG_EXCEPTION_EVENTS (1 << 5)
-#define PROFLOG_ALLOCATION_EVENTS (1 << 6)
-#define PROFLOG_GC_EVENTS (1 << 7)
-#define PROFLOG_THREAD_EVENTS (1 << 8)
-//This generate enter/leave events
-#define PROFLOG_CALL_EVENTS (1 << 9)
-#define PROFLOG_INS_COVERAGE_EVENTS (1 << 10)
-#define PROFLOG_SAMPLING_EVENTS (1 << 11)
-#define PROFLOG_MONITOR_EVENTS (1 << 12)
-#define PROFLOG_GC_MOVES_EVENTS (1 << 13)
-
-#define PROFLOG_GC_ROOT_EVENTS (1 << 14)
-#define PROFLOG_CONTEXT_EVENTS (1 << 15)
-#define PROFLOG_FINALIZATION_EVENTS (1 << 16)
-#define PROFLOG_COUNTER_EVENTS (1 << 17)
-#define PROFLOG_GC_HANDLE_EVENTS (1 << 18)
-
-//The following flags control whole subsystems
-//Enables code coverage generation
-#define PROFLOG_CODE_COV_FEATURE (1 << 19)
-//This enables sampling to be generated
-#define PROFLOG_SAMPLING_FEATURE (1 << 20)
-//This enable heap dumping during GCs and filter GCRoots and GCHandle events outside of the dumped collections
-#define PROFLOG_HEAPSHOT_FEATURE (1 << 21)
-
-
-
-//The follow flags are the common aliases we want ppl to use
-#define PROFLOG_TYPELOADING_ALIAS (PROFLOG_DOMAIN_EVENTS | PROFLOG_ASSEMBLY_EVENTS | PROFLOG_MODULE_EVENTS | PROFLOG_CLASS_EVENTS)
-#define PROFLOG_CODECOV_ALIAS (PROFLOG_INS_COVERAGE_EVENTS | PROFLOG_CODE_COV_FEATURE)
-#define PROFLOG_PERF_SAMPLING_ALIAS (PROFLOG_TYPELOADING_ALIAS | PROFLOG_THREAD_EVENTS | PROFLOG_SAMPLING_EVENTS | PROFLOG_SAMPLING_FEATURE)
-#define PROFLOG_GC_ALLOC_ALIAS (PROFLOG_TYPELOADING_ALIAS | PROFLOG_THREAD_EVENTS | PROFLOG_GC_EVENTS | PROFLOG_ALLOCATION_EVENTS)
-#define PROFLOG_HEAPSHOT_ALIAS (PROFLOG_TYPELOADING_ALIAS | PROFLOG_THREAD_EVENTS | PROFLOG_GC_EVENTS | PROFLOG_GC_ROOT_EVENTS | PROFLOG_HEAPSHOT_FEATURE)
-#define PROFLOG_LEGACY_ALIAS (PROFLOG_TYPELOADING_ALIAS | PROFLOG_GC_EVENTS | PROFLOG_THREAD_EVENTS | PROFLOG_JIT_COMPILATION_EVENTS | PROFLOG_EXCEPTION_EVENTS | PROFLOG_MONITOR_EVENTS | PROFLOG_GC_ROOT_EVENTS | PROFLOG_CONTEXT_EVENTS | PROFLOG_FINALIZATION_EVENTS | PROFLOG_COUNTER_EVENTS)
-
+#define PROFLOG_EXCEPTION_EVENTS (1 << 0)
+#define PROFLOG_MONITOR_EVENTS (1 << 1)
+#define PROFLOG_GC_EVENTS (1 << 2)
+#define PROFLOG_GC_ALLOCATION_EVENTS (1 << 3)
+#define PROFLOG_GC_MOVE_EVENTS (1 << 4)
+#define PROFLOG_GC_ROOT_EVENTS (1 << 5)
+#define PROFLOG_GC_HANDLE_EVENTS (1 << 6)
+#define PROFLOG_GC_FINALIZATION_EVENTS (1 << 7)
+#define PROFLOG_COUNTER_EVENTS (1 << 8)
+#define PROFLOG_SAMPLE_EVENTS (1 << 9)
+#define PROFLOG_JIT_EVENTS (1 << 10)
+
+#define PROFLOG_ALLOC_ALIAS (PROFLOG_GC_EVENTS | PROFLOG_GC_ALLOCATION_EVENTS | PROFLOG_GC_MOVE_EVENTS)
+#define PROFLOG_HEAPSHOT_ALIAS (PROFLOG_GC_EVENTS | PROFLOG_GC_ROOT_EVENTS)
+#define PROFLOG_LEGACY_ALIAS (PROFLOG_EXCEPTION_EVENTS | PROFLOG_MONITOR_EVENTS | PROFLOG_GC_EVENTS | PROFLOG_GC_MOVE_EVENTS | PROFLOG_GC_ROOT_EVENTS | PROFLOG_GC_HANDLE_EVENTS | PROFLOG_GC_FINALIZATION_EVENTS | PROFLOG_COUNTER_EVENTS)
 
 typedef struct {
        //Events explicitly enabled
        int enable_mask;
+
        //Events explicitly disabled
        int disable_mask;
 
-       //Actual mask the profiler should use
+       // Actual mask the profiler should use. Can be changed at runtime.
        int effective_mask;
 
+       // Whether to do method prologue/epilogue instrumentation. Only used at startup.
+       gboolean enter_leave;
+
+       // Whether to collect code coverage by instrumenting basic blocks.
+       gboolean collect_coverage;
+
        //Emit a report at the end of execution
        gboolean do_report;
 
        //Enable profiler internal debugging
        gboolean do_debug;
 
-       //Enable code coverage specific debugging
-       gboolean debug_coverage;
-
        //Where to compress the output file
        gboolean use_zip;
 
-       //If true, don't generate stacktraces
-       gboolean notraces;
+       // Heapshot mode (every major, on demand, XXgc, XXms). Can be changed at runtime.
+       MonoProfilerHeapshotMode hs_mode;
 
-       //If true, heapshots are generated on demand only
-       gboolean hs_mode_ondemand;
+       // Heapshot frequency in milliseconds (for MONO_HEAPSHOT_X_MS). Can be changed at runtime.
+       unsigned int hs_freq_ms;
 
-       //HeapShort frequency in milliseconds
-       unsigned int hs_mode_ms;
+       // Heapshot frequency in number of collections (for MONO_HEAPSHOT_X_GC). Can be changed at runtime.
+       unsigned int hs_freq_gc;
 
-       //HeapShort frequency in number of collections
-       unsigned int hs_mode_gc;
+       // Whether to do a heapshot on shutdown.
+       gboolean hs_on_shutdown;
 
-       //Sample frequency in Hertz
+       // Sample frequency in Hertz. Only used at startup.
        int sample_freq;
 
-       //Maximum number of frames to collect
+       // Maximum number of frames to collect. Can be changed at runtime.
        int num_frames;
 
-       //Max depth to record enter/leave events
+       // Max depth to record enter/leave events. Can be changed at runtime.
        int max_call_depth;
 
        //Name of the generated mlpd file
@@ -255,12 +528,13 @@ typedef struct {
        //Filter files used by the code coverage mode
        GPtrArray *cov_filter_files;
 
-       //Port to listen for profiling commands
+       // Port to listen for profiling commands (e.g. "heapshot" for on-demand heapshot).
        int command_port;
 
-       //Max size of the sample hit buffer, we'll drop frames if it's reached
+       // Maximum number of SampleHit structures. We'll drop samples if this number is not sufficient.
        int max_allocated_sample_hits;
 
+       // Sample mode. Only used at startup.
        MonoProfilerSampleMode sampling_mode;
 } ProfilerConfig;
 
index 1c63e9abde7fda14b8887b2e29a2ba9ba8c1a037..4251a164ff56623acb10f147837edbf2b8b0b858 100644 (file)
@@ -906,6 +906,13 @@ enum {
        SAMPLE_BRANCH_MISSES,
 };
 
+enum {
+       MONO_GC_EVENT_MARK_START = 1,
+       MONO_GC_EVENT_MARK_END = 2,
+       MONO_GC_EVENT_RECLAIM_START = 3,
+       MONO_GC_EVENT_RECLAIM_END = 4,
+};
+
 static const char*
 sample_type_name (int type)
 {
index ab9cb1f663f7ec789d6de4f1b0aa126e27abe418..0f2f5edf5aae83383aa6a9ce5aaca50c682136d0 100755 (executable)
@@ -62,7 +62,7 @@ if ($report ne "missing binary") {
        report_errors ();
 }
 # test heapshot traces
-$report = run_test_sgen ("test-heapshot.exe", "heapshot,output=-traces.mlpd,legacy", "--traces traces.mlpd");
+$report = run_test_sgen ("test-heapshot.exe", "heapshot,output=traces.mlpd,legacy", "--traces traces.mlpd");
 if ($report ne "missing binary") {
        check_report_basics ($report);
        check_report_heapshot ($report, 0, {"T" => 5000});
@@ -76,7 +76,7 @@ if ($report ne "missing binary") {
        report_errors ();
 }
 # test traces
-$report = run_test ("test-traces.exe", "legacy,calls,alloc,output=-traces.mlpd", "--maxframes=7 --traces traces.mlpd");
+$report = run_test ("test-traces.exe", "legacy,calls,alloc,output=traces.mlpd", "--maxframes=7 --traces traces.mlpd");
 check_report_basics ($report);
 check_call_traces ($report,
        "T:level3 (int)" => [2020, "T:Main (string[])"],
@@ -92,7 +92,7 @@ check_alloc_traces ($report,
 );
 report_errors ();
 # test traces without enter/leave events
-$report = run_test ("test-traces.exe", "legacy,alloc,output=-traces.mlpd", "--traces traces.mlpd");
+$report = run_test ("test-traces.exe", "legacy,alloc,output=traces.mlpd", "--traces traces.mlpd");
 check_report_basics ($report);
 # this has been broken recently
 check_exception_traces ($report,
index a11650951a4d52a25ed2669122c669f386428c98..73148df47936ac2bc9a0432beadfddf0a71c9b8a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * mono-codeanalyst.c: VTune profiler
+ * vtune.c: VTune profiler
  *
  * Author:
  *   Virgile Bello (virgile.bello@gmail.com)
index d9c5afefee31164afd3b05a2b8434be0f7af4b08..ffdd45cb6b5e50a1872c266a24683ad37cca081f 100755 (executable)
@@ -69,11 +69,12 @@ if HYBRID_AOT_TESTS
 PROFILE_MCS_FLAGS = -d:MOBILE,MOBILE_LEGACY 
 endif
 
-MCS_NO_LIB = $(TOOLS_RUNTIME) $(CSC) -unsafe -debug:portable \
+MCS_NO_UNSAFE = $(TOOLS_RUNTIME) $(CSC) -debug:portable \
        -noconfig -nologo \
        -nowarn:0162 -nowarn:0168 -nowarn:0219 -nowarn:0414 -nowarn:0618 \
        -nowarn:0169 -nowarn:1690 -nowarn:0649 -nowarn:0612 -nowarn:3021 \
        -nowarn:0197 $(PROFILE_MCS_FLAGS)
+MCS_NO_LIB = $(MCS_NO_UNSAFE) -unsafe
 
 MCS = $(MCS_NO_LIB)
 
@@ -2001,20 +2002,70 @@ endif
 libtest_la_SOURCES = libtest.c
 libtest_la_LIBADD = $(GLIB_LIBS) $(LIBICONV)
 
-test-internalsvisibleto: internalsvisibleto-runtimetest.exe internalsvisibleto-compilertest.exe internalsvisibleto-library.dll
-       $(Q) $(RUNTIME) internalsvisibleto-runtimetest.exe 1>internalsvisibleto-runtimetest.exe.stdout 2>internalsvisibleto-runtimetest.exe.stderr
-       $(Q) $(RUNTIME) internalsvisibleto-compilertest.exe 1>internalsvisibleto-compilertest.exe.stdout 2>internalsvisibleto-compilertest.exe.stderr
-
-internalsvisibleto-runtimetest.exe: internalsvisibleto-runtimetest.cs internalsvisibleto-library.cs
-       $(Q) $(MCS) -out:internalsvisibleto-correctcase.dll -target:library -d:CORRECT_CASE -d:PERMISSIVE internalsvisibleto-library.cs 
-       $(Q) $(MCS) -out:internalsvisibleto-wrongcase.dll -target:library -d:WRONG_CASE -d:PERMISSIVE internalsvisibleto-library.cs
-       $(Q) $(MCS) -out:internalsvisibleto-runtimetest.exe -warn:0 -r:internalsvisibleto-correctcase.dll -r:internalsvisibleto-wrongcase.dll internalsvisibleto-runtimetest.cs
-       $(Q) $(MCS) -out:internalsvisibleto-correctcase.dll -target:library -d:CORRECT_CASE internalsvisibleto-library.cs       
-       $(Q) $(MCS) -out:internalsvisibleto-wrongcase.dll -target:library -d:WRONG_CASE internalsvisibleto-library.cs
-
-internalsvisibleto-compilertest.exe: internalsvisibleto-compilertest.cs internalsvisibleto-library.cs
-       $(Q) $(MCS) -out:internalsvisibleto-correctcase-2.dll -target:library -d:CORRECT_CASE internalsvisibleto-library.cs     
-       $(Q) $(MCS) -out:internalsvisibleto-wrongcase-2.dll -target:library -d:WRONG_CASE internalsvisibleto-library.cs
-       $(Q) $(MCS) -out:internalsvisibleto-compilertest.exe -warn:0 -r:internalsvisibleto-correctcase-2.dll -r:internalsvisibleto-wrongcase-2.dll internalsvisibleto-compilertest.cs
+INTERNALSVISIBLETO_TEST_SRC = \
+       internalsvisibleto-runtimetest.cs \
+       internalsvisibleto-compilertest.cs
+
+INTERNALSVISIBLETO_TEST_LIB_SRC = \
+       internalsvisibleto-library.cs
+
+INTERNALSVISIBLETO_TEST_LIBS = \
+       internalsvisibleto-correctcase.dll \
+       internalsvisibleto-wrongcase.dll \
+       internalsvisibleto-correctcase-2.dll \
+       internalsvisibleto-wrongcase-2.dll \
+       internalsvisibleto-correctcase-sign2048.dll \
+       internalsvisibleto-wrongcase-sign2048.dll \
+       internalsvisibleto-correctcase-2-sign2048.dll \
+       internalsvisibleto-wrongcase-2-sign2048.dll
+
+
+INTERNALSVISIBLETO_TEST = \
+       $(INTERNALSVISIBLETO_TEST_SRC:.cs=.exe) \
+       $(INTERNALSVISIBLETO_TEST_SRC:.cs=-sign2048.exe)
+
+if FULL_AOT_TESTS
+INTERNALSVISIBLETO_TESTAOT = \
+       $(INTERNALSVISIBLETO_TEST:.exe=.exe$(PLATFORM_AOT_SUFFIX))
+INTERNALSVISIBLETO_TESTAOT_LIBS = \
+       $(INTERNALSVISIBLETO_TEST_LIBS:.dll=.dll$(PLATFORM_AOT_SUFFIX))
+endif
+
+if HYBRID_AOT_TESTS
+INTERNALSVISIBLETO_TESTAOT = \
+       $(INTERNALSVISIBLETO_TEST:.exe=.exe$(PLATFORM_AOT_SUFFIX))
+INTERNALSVISIBLETO_TESTAOT_LIBS = \
+       $(INTERNALSVISIBLETO_TEST_LIBS:.dll=.dll$(PLATFORM_AOT_SUFFIX))
+endif
+
+EXTRA_DIST += $(INTERNALSVISIBLETO_TEST_SRC) $(INTERNALSVISIBLETO_TEST_LIB_SRC)
+
+test-internalsvisibleto: test-runner.exe $(INTERNALSVISIBLETO_TEST) $(INTERNALSVISIBLETO_TESTAOT) $(INTERNALSVISIBLETO_TESTAOT_LIBS)
+       $(TOOLS_RUNTIME) $(TEST_RUNNER) --testsuite-name $@ $(INTERNALSVISIBLETO_TEST)
+
+internalsvisibleto-correctcase.dll internalsvisibleto-wrongcase.dll internalsvisibleto-runtimetest.exe: internalsvisibleto-runtimetest.cs internalsvisibleto-library.cs
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-correctcase.dll -target:library -d:CORRECT_CASE -d:PERMISSIVE internalsvisibleto-library.cs       
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-wrongcase.dll -target:library -d:WRONG_CASE -d:PERMISSIVE internalsvisibleto-library.cs
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-runtimetest.exe -warn:0 -r:internalsvisibleto-correctcase.dll -r:internalsvisibleto-wrongcase.dll internalsvisibleto-runtimetest.cs
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-correctcase.dll -target:library -d:CORRECT_CASE internalsvisibleto-library.cs     
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-wrongcase.dll -target:library -d:WRONG_CASE internalsvisibleto-library.cs
+
+internalsvisibleto-correctcase-2.dll internalsvisibleto-wrongcase-2.dll  internalsvisibleto-compilertest.exe: internalsvisibleto-compilertest.cs internalsvisibleto-library.cs
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-correctcase-2.dll -target:library -d:CORRECT_CASE internalsvisibleto-library.cs   
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-wrongcase-2.dll -target:library -d:WRONG_CASE internalsvisibleto-library.cs
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-compilertest.exe -warn:0 -r:internalsvisibleto-correctcase-2.dll -r:internalsvisibleto-wrongcase-2.dll internalsvisibleto-compilertest.cs
+
+internalsvisibleto-correctcase-sign2048.dll internalsvisibleto-wrongcase-sign2048.dll internalsvisibleto-runtimetest-sign2048.exe: internalsvisibleto-runtimetest.cs internalsvisibleto-library.cs internalsvisibleto-2048.snk
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-correctcase-sign2048.dll -target:library -d:CORRECT_CASE -d:PERMISSIVE -d:SIGN2048 internalsvisibleto-library.cs
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-wrongcase-sign2048.dll -target:library -d:WRONG_CASE -d:PERMISSIVE -d:SIGN2048 internalsvisibleto-library.cs
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-runtimetest-sign2048.exe -warn:0 -r:internalsvisibleto-correctcase-sign2048.dll -r:internalsvisibleto-wrongcase-sign2048.dll -d:SIGN2048 internalsvisibleto-runtimetest.cs
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-correctcase-sign2048.dll -target:library -d:CORRECT_CASE -d:SIGN2048 internalsvisibleto-library.cs
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-wrongcase-sign2048.dll -target:library -d:WRONG_CASE -d:SIGN2048 internalsvisibleto-library.cs
+
+internalsvisibleto-correctcase-2-sign2048.dll internalsvisibleto-wrongcase-2-sign2048.dll internalsvisibleto-compilertest-sign2048.exe: internalsvisibleto-compilertest.cs internalsvisibleto-library.cs internalsvisibleto-2048.snk
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-correctcase-2-sign2048.dll -target:library -d:CORRECT_CASE -d:SIGN2048 internalsvisibleto-library.cs      
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-wrongcase-2-sign2048.dll -target:library -d:WRONG_CASE -d:SIGN2048 internalsvisibleto-library.cs
+       $(Q) $(MCS_NO_UNSAFE) -out:internalsvisibleto-compilertest-sign2048.exe -warn:0 -r:internalsvisibleto-correctcase-2-sign2048.dll -r:internalsvisibleto-wrongcase-2-sign2048.dll -d:SIGN2048 internalsvisibleto-compilertest.cs
+
 
 CLEANFILES = $(TESTS_CS) $(TESTS_IL) $(TESTS_BENCH) $(TESTS_STRESS) $(TESTSAOT_CS) $(TESTSAOT_IL) $(TESTSAOT_BENCH) $(TESTSAOT_STRESS) *.dll *.stdout *.aotlog *.exe stest.dat
diff --git a/mono/tests/internalsvisibleto-2048.snk b/mono/tests/internalsvisibleto-2048.snk
new file mode 100644 (file)
index 0000000..37a8f26
Binary files /dev/null and b/mono/tests/internalsvisibleto-2048.snk differ
index c38fb0d918551bc26994763d7022e60c55639264..196627e73e9792764c91750697685a549261a9b3 100755 (executable)
@@ -1,5 +1,11 @@
 using System;
 
+#if SIGN2048
+using System.Reflection;
+[assembly: AssemblyDelaySign(true)]
+[assembly: AssemblyKeyFile(@"internalsvisibleto-2048.snk")]
+#endif
+
 namespace InternalsVisibleTo {
     class Program {
         static void Main (string[] args) {
@@ -7,6 +13,15 @@ namespace InternalsVisibleTo {
 
             Console.WriteLine("-- Correct case --");
 
+           try {
+                   var a = new CorrectCaseFriendAssembly.PublicClass ();
+                   a.InternalMethod ();
+                   Console.WriteLine ("Access friend internal method: OK");
+           } catch (MemberAccessException) {
+                   failCount += 1;
+                   Console.WriteLine ("Access friend internal method: Fail");
+           }
+
             try {
                 var a = new CorrectCaseFriendAssembly.InternalClass(@internal: 0);
                 Console.WriteLine("Access internal class internal ctor: OK");
index a27547a9fab6407e9acb629cb08a5fa49e065dd7..f08d859305bca2fc879e8b6f47c2d06ce2084bad 100644 (file)
@@ -1,13 +1,29 @@
 using System;
 using System.Runtime.CompilerServices;
 
+#if SIGN2048
+using System.Reflection;
+[assembly: AssemblyDelaySign(true)]
+[assembly: AssemblyKeyFile(@"internalsvisibleto-2048.snk")]
+#endif
+
 #if CORRECT_CASE
+#if !SIGN2048
 [assembly: InternalsVisibleTo("internalsvisibleto-runtimetest")]
 [assembly: InternalsVisibleTo("internalsvisibleto-compilertest")]
 #else
+[assembly: InternalsVisibleTo("internalsvisibleto-runtimetest-sign2048, PublicKey=00240000048000001401000006020000002400005253413100080000010001002b524ed36058e444d0f2b12aeeeadab6f9a614dae43300d489746d143103a63c0178d0e316cc7a83156637d02b95b617c34bfa6877bc418118ce6d652e73211fdb80e5bc1878c6ef1b488dae12925390e7932dae9b22ada65ec76694a73b8e940db558d03ff5a3bee28017cb4448cd41dc946cc248e3313417f59092b9b62996de506c9446c7dceffed8e854cfa3d42eee30cdccbce934318b64ee20489178c00fa587f4ea666e4421eeae157fddf5ce7cfcf76e3b8b390005297f1b7e502c0f211c8c3f6886012cc4173aeedb4dc915d6d8f3821c19c0f1eedcccec8e839c1443ac96db7231ddebb391a5a92373aa87a6f2b2c8a9d57ad204e61813cc280da3")]
+[assembly: InternalsVisibleTo("internalsvisibleto-compilertest-sign2048, PublicKey=00240000048000001401000006020000002400005253413100080000010001002b524ed36058e444d0f2b12aeeeadab6f9a614dae43300d489746d143103a63c0178d0e316cc7a83156637d02b95b617c34bfa6877bc418118ce6d652e73211fdb80e5bc1878c6ef1b488dae12925390e7932dae9b22ada65ec76694a73b8e940db558d03ff5a3bee28017cb4448cd41dc946cc248e3313417f59092b9b62996de506c9446c7dceffed8e854cfa3d42eee30cdccbce934318b64ee20489178c00fa587f4ea666e4421eeae157fddf5ce7cfcf76e3b8b390005297f1b7e502c0f211c8c3f6886012cc4173aeedb4dc915d6d8f3821c19c0f1eedcccec8e839c1443ac96db7231ddebb391a5a92373aa87a6f2b2c8a9d57ad204e61813cc280da3")]
+#endif // SIGN2048
+#else
+#if !SIGN2048
 [assembly: InternalsVisibleTo("iNtErnAlsVisibLETo-RUntimeTesT")]
 [assembly: InternalsVisibleTo("iNtErnAlsVisibLETo-COmpilerTesT")]
-#endif
+#else
+[assembly: InternalsVisibleTo("iNtErnAlsVisibLETo-RUntimeTesT-sign2048, PublicKey=00240000048000001401000006020000002400005253413100080000010001002b524ed36058e444d0f2b12aeeeadab6f9a614dae43300d489746d143103a63c0178d0e316cc7a83156637d02b95b617c34bfa6877bc418118ce6d652e73211fdb80e5bc1878c6ef1b488dae12925390e7932dae9b22ada65ec76694a73b8e940db558d03ff5a3bee28017cb4448cd41dc946cc248e3313417f59092b9b62996de506c9446c7dceffed8e854cfa3d42eee30cdccbce934318b64ee20489178c00fa587f4ea666e4421eeae157fddf5ce7cfcf76e3b8b390005297f1b7e502c0f211c8c3f6886012cc4173aeedb4dc915d6d8f3821c19c0f1eedcccec8e839c1443ac96db7231ddebb391a5a92373aa87a6f2b2c8a9d57ad204e61813cc280da3")]
+[assembly: InternalsVisibleTo("iNtErnAlsVisibLETo-COmpilerTesT-sign2048, PublicKey=00240000048000001401000006020000002400005253413100080000010001002b524ed36058e444d0f2b12aeeeadab6f9a614dae43300d489746d143103a63c0178d0e316cc7a83156637d02b95b617c34bfa6877bc418118ce6d652e73211fdb80e5bc1878c6ef1b488dae12925390e7932dae9b22ada65ec76694a73b8e940db558d03ff5a3bee28017cb4448cd41dc946cc248e3313417f59092b9b62996de506c9446c7dceffed8e854cfa3d42eee30cdccbce934318b64ee20489178c00fa587f4ea666e4421eeae157fddf5ce7cfcf76e3b8b390005297f1b7e502c0f211c8c3f6886012cc4173aeedb4dc915d6d8f3821c19c0f1eedcccec8e839c1443ac96db7231ddebb391a5a92373aa87a6f2b2c8a9d57ad204e61813cc280da3")]
+#endif // SIGN2048
+#endif // !CORRECT_CASE
 
 #if CORRECT_CASE
 namespace CorrectCaseFriendAssembly {
index ec8805574afc144ba7aefbe1d77ae2a7957f32ca..9bf5e70ddc4daa6e6e603b896e9711ef4af72fcd 100755 (executable)
@@ -1,5 +1,11 @@
 using System;
 
+#if SIGN2048
+using System.Reflection;
+[assembly: AssemblyDelaySign(true)]
+[assembly: AssemblyKeyFile(@"internalsvisibleto-2048.snk")]
+#endif
+
 namespace InternalsVisibleTo {
     class Program {
         static void Main (string[] args) {
@@ -7,6 +13,15 @@ namespace InternalsVisibleTo {
 
             Console.WriteLine("-- Correct case --");
 
+           try {
+                   var a = new CorrectCaseFriendAssembly.PublicClass ();
+                   a.InternalMethod ();
+                   Console.WriteLine ("Access friend internal method: OK");
+           } catch (MemberAccessException) {
+                   failCount += 1;
+                   Console.WriteLine ("Access friend internal method: Fail");
+           }
+
             try {
                 var a = new CorrectCaseFriendAssembly.InternalClass(@private: false);
                 Console.WriteLine("Access internal class private ctor: OK");
index 0933903e747c4d88e8a0cd380a81703a3f16a47d..e28b3f361035b0c13167140acc67cad724d3da60 100644 (file)
@@ -36,8 +36,8 @@ typedef enum {
                                          MONO_TRACE_W32HANDLE
 } MonoTraceMask;
 
-extern GLogLevelFlags mono_internal_current_level;
-extern MonoTraceMask mono_internal_current_mask;
+MONO_API extern GLogLevelFlags mono_internal_current_level;
+MONO_API extern MonoTraceMask mono_internal_current_mask;
 
 void 
 mono_trace_init (void);
@@ -45,7 +45,7 @@ mono_trace_init (void);
 void 
 mono_trace_cleanup (void);
 
-void 
+MONO_API void
 mono_tracev_inner (GLogLevelFlags level, MonoTraceMask mask, const char *format, va_list args);
 
 void 
@@ -139,6 +139,8 @@ mono_trace_message(MonoTraceMask mask, const char *format, ...)
 #define mono_gc_printf(gc_log_file, format, ...) g_log ("mono-gc", G_LOG_LEVEL_MESSAGE, format, ##__VA_ARGS__)
 #define mono_runtime_printf(format, ...) g_log ("mono-rt", G_LOG_LEVEL_MESSAGE, format "\n", ##__VA_ARGS__)
 #define mono_runtime_printf_err(format, ...) g_log ("mono-rt", G_LOG_LEVEL_CRITICAL, format "\n", ##__VA_ARGS__)
+#define mono_profiler_printf(format, ...) g_log ("mono-prof", G_LOG_LEVEL_MESSAGE, format "\n", ##__VA_ARGS__)
+#define mono_profiler_printf_err(format, ...) g_log ("mono-prof", G_LOG_LEVEL_CRITICAL, format "\n", ##__VA_ARGS__)
 #define mono_runtime_stdout_fflush() do { } while (0)
 
 #else
@@ -150,6 +152,8 @@ mono_trace_message(MonoTraceMask mask, const char *format, ...)
 
 #define mono_runtime_printf(format, ...) fprintf (stdout, format "\n", ##__VA_ARGS__)
 #define mono_runtime_printf_err(format, ...) fprintf (stderr, format "\n", ##__VA_ARGS__)
+#define mono_profiler_printf(format, ...) fprintf (stdout, format "\n", ##__VA_ARGS__)
+#define mono_profiler_printf_err(format, ...) fprintf (stderr, format "\n", ##__VA_ARGS__)
 #define mono_runtime_stdout_fflush() do { fflush (stdout); } while (0)
 
 #endif
index b372b5031137949c5d89b7899d381db30d8e7ae9..356a1ab7e0b2916e2d97507d2a93bcfbc41892bd 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <glib.h>
 #include <mono/utils/mono-compiler.h>
+#include <mono/utils/mono-publib.h>
 
 /* never remove or reorder these enums values: they are used in corlib/System */
 
@@ -71,7 +72,7 @@ gint64    mono_process_get_data_with_error (gpointer pid, MonoProcessData data,
 
 int       mono_process_current_pid (void);
 
-int       mono_cpu_count    (void);
+MONO_API int       mono_cpu_count    (void);
 gint64    mono_cpu_get_data (int cpu_id, MonoCpuData data, MonoProcessError *error);
 gint32    mono_cpu_usage (MonoCpuUsageState *prev);
 
index 8088a22fba0a01b869db13e3f2ce17023d2ac609..5c41659bb5de692620bb4bb31dca06b45945a462 100644 (file)
@@ -15,8 +15,8 @@
       <PackAlignmentBoundary>0</PackAlignmentBoundary>
       <CallingConvention>0</CallingConvention>
       <ErrorReporting>0</ErrorReporting>
-      <CommandLineTemplate Condition="'$(Platform)' == 'Win32'">"$(VCInstallDir)bin\ml.exe" /c [AllOptions] [AdditionalOptions] /Ta[Inputs]</CommandLineTemplate>
-      <CommandLineTemplate Condition="'$(Platform)' == 'X64'">"$(VCInstallDir)bin\amd64\ml64.exe" /c [AllOptions] [AdditionalOptions] /Ta[Inputs]</CommandLineTemplate>
+      <CommandLineTemplate Condition="'$(Platform)' == 'Win32'">"ml.exe" /c [AllOptions] [AdditionalOptions] /Ta[Inputs]</CommandLineTemplate>
+      <CommandLineTemplate Condition="'$(Platform)' == 'X64'">"ml64.exe" /c [AllOptions] [AdditionalOptions] /Ta[Inputs]</CommandLineTemplate>
       <CommandLineTemplate Condition="'$(Platform)' != 'Win32' and '$(Platform)' != 'X64'">echo MASM not supported on this platform</CommandLineTemplate>
       <ExecutionDescription>Assembling %(Identity)...</ExecutionDescription>
     </MASM>
index 5c3c2b7a83c7f0884b40f003008aa0c206006449..b5e2a1f479362ffd292f2946dda3cfb990a9f71e 100644 (file)
@@ -7,7 +7,7 @@
     <MONO_CFG_DIR>$(MONO_DIR)/runtime/etc</MONO_CFG_DIR>
     <MONO_NUNIT_RUN_TARGET>net_4_x_System_test.dll</MONO_NUNIT_RUN_TARGET>
     <MONO_NUNIT_FIXTURE></MONO_NUNIT_FIXTURE>
-    <MONO_NUNIT_ARGS>-noshadow -exclude=NotWorking,ValueAdd,CAS,InetAccess /labels</MONO_NUNIT_ARGS>
+    <MONO_NUNIT_ARGS>-noshadow -exclude=NotWorking,CAS /labels</MONO_NUNIT_ARGS>
     <MONO_NUNIT_ARGS Condition="'$(MONO_NUNIT_FIXTURE)'!=''">$(MONO_NUNIT_ARGS) -fixture $(MONO_NUNIT_FIXTURE)</MONO_NUNIT_ARGS>
     <MONO_NUNIT_RUN_ADDITIONAL_ARGS>
     </MONO_NUNIT_RUN_ADDITIONAL_ARGS>
@@ -43,4 +43,4 @@
     </BuildMacro>
   </ItemGroup>
   <ItemDefinitionGroup />
-</Project>
\ No newline at end of file
+</Project>
index 1da827afb1d724bbf84c5cbe0e6a1271f50b61d2..d189fbfb5e7c16b4e90bccdadb0c4ca3af709ad5 100644 (file)
@@ -1,4 +1,4 @@
 ; file generated by create-windef.pl
 LIBRARY mono-profiler-vtune.dll
 EXPORTS
-mono_profiler_startup
\ No newline at end of file
+mono_profiler_init
index 544a89d32a2bb0a27ec120f80b791caf98a5bd9f..73ace6bdc745252f4ad5e7e95453ee1d26a31d55 100644 (file)
     </ProjectReference>\r
   </ItemDefinitionGroup>\r
   <ItemGroup>\r
-    <ClCompile Include="..\mono\profiler\mono-profiler-vtune.c" />\r
+    <ClCompile Include="..\mono\profiler\vtune.c" />\r
   </ItemGroup>\r
   <ItemGroup>\r
     <None Include="mono-profiler-vtune.def" />\r
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
   <ImportGroup Label="ExtensionTargets">\r
   </ImportGroup>\r
-</Project>
\ No newline at end of file
+</Project>\r
index 7b3e25ba85bcc1c8574fb96ea692c8501c16bfb5..bb72a170bb2a160fea17d0d65f86363cf5612f91 100644 (file)
@@ -12,7 +12,7 @@
     </Filter>\r
   </ItemGroup>\r
   <ItemGroup>\r
-    <ClCompile Include="..\mono\profiler\mono-profiler-vtune.c">\r
+    <ClCompile Include="..\mono\profiler\vtune.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
   </ItemGroup>\r
@@ -21,4 +21,4 @@
       <Filter>Resource Files</Filter>\r
     </None>\r
   </ItemGroup>\r
-</Project>
\ No newline at end of file
+</Project>\r
index b02ac199983bc741ea2ab05cddcbe5bda96e7ed0..c55263be534ccf49cf7ec9899f61a3e1ec68d428 100644 (file)
@@ -3,7 +3,7 @@ import fileinput
 class MSBuild (GitHubPackage):
        def __init__ (self):
                GitHubPackage.__init__ (self, 'mono', 'msbuild', '15.3',
-                       revision = 'f7dcc3900c808775adad970f047202b4de34e986')
+                       revision = '371d25657ed8ff8ca5908de8a221c14eac240fc0')
 
        def build (self):
                self.sh ('./cibuild.sh --scope Compile --target Mono --host Mono --config Release')
index 5b76dfd19bd76e10557d59590a0a179bde0add9d..322185faaf7dfd8049a94c213c41a76be9beb4b7 100644 (file)
@@ -488,13 +488,21 @@ verify_image_file (const char *fname)
                }
                mono_class_init (klass);
                if (mono_class_has_failure (klass)) {
-                       printf ("Error verifying class(0x%08x) %s.%s a type load error happened\n", token, klass->name_space, klass->name);
+                       MonoError type_load_error;
+                       error_init (&type_load_error);
+                       mono_error_set_for_class_failure (&type_load_error, klass);
+                       printf ("Could not initialize class(0x%08x) %s.%s due to %s\n", token, klass->name_space, klass->name, mono_error_get_message (&type_load_error));
+                       mono_error_cleanup (&type_load_error);
                        ++count;
                }
 
                mono_class_setup_vtable (klass);
                if (mono_class_has_failure (klass)) {
-                       printf ("Error verifying class(0x%08x) %s.%s a type load error happened\n", token, klass->name_space, klass->name);
+                       MonoError type_load_error;
+                       error_init (&type_load_error);
+                       mono_error_set_for_class_failure (&type_load_error, klass);
+                       printf ("Could not initialize vtable of class(0x%08x) %s.%s due to %s\n", token, klass->name_space, klass->name, mono_error_get_message (&type_load_error));
+                       mono_error_cleanup (&type_load_error);
                        ++count;
                }
        }